Merge branch 'devel' into mediamonitor2

Conflicts:
	python_apps/api_clients/api_client.py
This commit is contained in:
Rudi Grinberg 2012-07-16 17:41:36 -04:00
commit 20e32b98ba
31 changed files with 253 additions and 143 deletions

View file

@ -39,7 +39,7 @@ def convert_dict_value_to_utf8(md):
# Airtime API Client
################################################################################
class AirTimeApiClient():
class AirtimeApiClient():
def __init__(self, logger=None):
if logger is None:
@ -437,10 +437,14 @@ class AirTimeApiClient():
response = self.get_response_from_server(url)
response = json.loads(response)
except Exception, e:
response = None
response = {}
logger.error("Exception: %s", e)
return response
try:
return response["files"]
except KeyError:
self.logger.error("Could not find index 'files' in dictionary: %s", str(response))
return []
def list_all_watched_dirs(self):
logger = self.logger

View file

@ -40,8 +40,7 @@ class AirtimeMediaMonitorBootstrap():
went offline.
"""
def scan(self):
directories = self.get_list_of_watched_dirs();
directories = self.get_list_of_watched_dirs()
self.logger.info("watched directories found: %s", directories)
for id, dir in directories.iteritems():
@ -57,12 +56,21 @@ class AirtimeMediaMonitorBootstrap():
return self.api_client.list_all_db_files(dir_id)
"""
returns the path and the database row id for this path for all watched directories. Also
returns the path and its corresponding database row idfor all watched directories. Also
returns the Stor directory, which can be identified by its row id (always has value of "1")
Return type is a dictionary similar to:
{"1":"/srv/airtime/stor/"}
"""
def get_list_of_watched_dirs(self):
json = self.api_client.list_all_watched_dirs()
return json["dirs"]
try:
return json["dirs"]
except KeyError as e:
self.logger.error("Could not find index 'dirs' in dictionary: %s", str(json))
self.logger.error(e)
return {}
"""
This function takes in a path name provided by the database (and its corresponding row id)
@ -86,8 +94,9 @@ class AirtimeMediaMonitorBootstrap():
db_known_files_set = set()
files = self.list_db_files(dir_id)
for file in files['files']:
db_known_files_set.add(file)
for f in files:
db_known_files_set.add(f)
all_files = self.mmc.clean_dirty_file_paths( self.mmc.scan_dir_for_new_files(dir) )
@ -111,10 +120,9 @@ class AirtimeMediaMonitorBootstrap():
stdout = self.mmc.exec_command(command)
if stdout is None:
self.logger.error("Unrecoverable error when syncing db to filesystem.")
return
new_files = self.mmc.clean_dirty_file_paths(stdout.splitlines())
new_files = []
else:
new_files = stdout.splitlines()
new_and_modified_files = set()
for file_path in new_files:

View file

@ -12,8 +12,17 @@ import traceback
"""
list of supported easy tags in mutagen version 1.20
['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', 'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', 'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', 'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', 'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', 'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', 'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', 'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', 'arranger', 'albumsort', 'replaygain_*_peak', 'organization']
['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry',
'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby',
'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid',
'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort',
'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor',
'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid',
'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid',
'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid',
'arranger', 'albumsort', 'replaygain_*_peak', 'organization']
"""
class AirtimeMetadata:
def __init__(self):
@ -57,10 +66,17 @@ class AirtimeMetadata:
self.logger = logging.getLogger()
def get_md5(self, filepath):
f = open(filepath, 'rb')
m = hashlib.md5()
m.update(f.read())
md5 = m.hexdigest()
"""
Returns an md5 of the file located at filepath. Returns an empty string
if there was an error reading the file.
"""
try:
f = open(filepath, 'rb')
m = hashlib.md5()
m.update(f.read())
md5 = m.hexdigest()
except Exception, e:
return ""
return md5
@ -121,6 +137,10 @@ class AirtimeMetadata:
return item
def get_md_from_file(self, filepath):
"""
Returns None if error retrieving metadata. Otherwise returns a dictionary
representing the file's metadata
"""
self.logger.info("getting info from filepath %s", filepath)
@ -136,7 +156,6 @@ class AirtimeMetadata:
md['MDATA_KEY_MD5'] = md5
file_info = mutagen.File(filepath, easy=True)
except Exception, e:
self.logger.error("failed getting metadata from %s", filepath)
self.logger.error("Exception %s", e)
@ -146,18 +165,16 @@ class AirtimeMetadata:
#check if file has any metadata
if file_info is None:
return None
#check if file has any metadata
if file_info is not None:
for key in file_info.keys() :
if key in self.mutagen2airtime:
val = file_info[key]
try:
if val is not None and len(val) > 0 and val[0] is not None and len(val[0]) > 0:
md[self.mutagen2airtime[key]] = val[0]
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
for key in file_info.keys() :
if key in self.mutagen2airtime:
val = file_info[key]
try:
if val is not None and len(val) > 0 and val[0] is not None and len(val[0]) > 0:
md[self.mutagen2airtime[key]] = val[0]
except Exception, e:
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
if 'MDATA_KEY_TITLE' not in md:
#get rid of file extension from original name, name might have more than 1 '.' in it.
original_name = os.path.basename(filepath)
@ -228,18 +245,24 @@ class AirtimeMetadata:
md['MDATA_KEY_COPYRIGHT'] = self.truncate_to_length(md['MDATA_KEY_COPYRIGHT'], 512)
#end of db truncation checks.
md['MDATA_KEY_BITRATE'] = getattr(file_info.info, "bitrate", None)
md['MDATA_KEY_SAMPLERATE'] = getattr(file_info.info, "sample_rate", None)
self.logger.info("Bitrate: %s , Samplerate: %s", md['MDATA_KEY_BITRATE'], md['MDATA_KEY_SAMPLERATE'])
try: md['MDATA_KEY_DURATION'] = self.format_length(file_info.info.length)
except Exception as e: self.logger.warn("File: '%s' raises: %s", filepath, str(e))
try: md['MDATA_KEY_MIME'] = file_info.mime[0]
except Exception as e: self.logger.warn("File: '%s' has no mime type", filepath, str(e))
try:
md['MDATA_KEY_BITRATE'] = getattr(file_info.info, "bitrate", 0)
md['MDATA_KEY_SAMPLERATE'] = getattr(file_info.info, "sample_rate", 0)
md['MDATA_KEY_DURATION'] = self.format_length(getattr(file_info.info, "length", 0.0))
md['MDATA_KEY_MIME'] = ""
if len(file_info.mime) > 0:
md['MDATA_KEY_MIME'] = file_info.mime[0]
except Exception as e:
self.logger.warn(e)
if "mp3" in md['MDATA_KEY_MIME']:
md['MDATA_KEY_FTYPE'] = "audioclip"
elif "vorbis" in md['MDATA_KEY_MIME']:
md['MDATA_KEY_FTYPE'] = "audioclip"
else:
self.logger.error("File %s of mime type %s does not appear to be a valid vorbis or mp3 file." % (filepath, md['MDATA_KEY_MIME']))
return None
return md

View file

@ -36,6 +36,11 @@ class AirtimeNotifier(Notifier):
time.sleep(5)
def init_rabbit_mq(self):
"""
This function will attempt to connect to RabbitMQ Server and if successful
return 'True'. Returns 'False' otherwise.
"""
self.logger.info("Initializing RabbitMQ stuff")
try:
schedule_exchange = Exchange("airtime-media-monitor", "direct", durable=True, auto_delete=True)

View file

@ -291,7 +291,10 @@ class MediaMonitorCommon:
self.logger.debug(command)
stdout = self.exec_command(command)
return stdout.splitlines()
if stdout is None:
return []
else:
return stdout.splitlines()
def touch_index_file(self):
dirname = os.path.dirname(self.timestamp_file)

View file

@ -80,7 +80,7 @@ try:
configure_locale()
config = AirtimeMediaConfig(logger)
api_client = apc.AirTimeApiClient()
api_client = apc.AirtimeApiClient()
api_client.register_component("media-monitor")
logger.info("Setting up monitor")

View file

@ -23,7 +23,7 @@ class ReplayGainUpdater(Thread):
def __init__(self, logger):
Thread.__init__(self)
self.logger = logger
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
def main(self):

View file

@ -73,7 +73,7 @@ monit_restart() {
start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE1
rm -f $PIDFILE1
start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0
start-stop-daemon --start --background --quiet --chuid $ROOTUSERID:$ROOTUSERID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0
start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID \
--nicelevel -15 --make-pidfile --pidfile $PIDFILE1 --startas $DAEMON1

View file

@ -1,6 +1,6 @@
import logging
import sys
from api_clients import api_client
from api_clients.api_client import AirtimeApiClient
def generate_liquidsoap_config(ss):
data = ss['msg']
@ -9,22 +9,22 @@ def generate_liquidsoap_config(ss):
fh.write("# THIS FILE IS AUTO GENERATED. DO NOT CHANGE!! #\n")
fh.write("################################################\n")
for d in data:
key = d['keyname']
str_buffer = d[u'keyname'] + " = "
if(d[u'type'] == 'string'):
temp = d[u'value']
str_buffer += '"%s"' % temp
val = '"%s"' % d['value']
else:
temp = d[u'value']
if(temp == ""):
temp = "0"
str_buffer += temp
str_buffer += "\n"
fh.write(api_client.encode_to(str_buffer))
val = d[u'value']
val = val if len(val) > 0 else "0"
str_buffer = "%s = %s\n" % (key, val)
fh.write(str_buffer.encode('utf-8'))
fh.write('log_file = "/var/log/airtime/pypo-liquidsoap/<script>.log"\n')
fh.close()
logging.basicConfig(format='%(message)s')
ac = api_client(logging.getLogger())
ac = AirtimeApiClient(logging.getLogger())
ss = ac.get_stream_setting()
if ss is not None:

View file

@ -1,7 +1,7 @@
from api_clients import *
import sys
api_clients = api_client.AirTimeApiClient()
api_clients = api_client.AirtimeApiClient()
dj_type = sys.argv[1]
username = sys.argv[2]

View file

@ -107,10 +107,10 @@ except Exception, e:
class Global:
def __init__(self):
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
def selfcheck(self):
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
return self.api_client.is_server_compatible()
def test_api(self):
@ -172,7 +172,7 @@ if __name__ == '__main__':
g.test_api()
sys.exit()
api_client = api_client.AirTimeApiClient()
api_client = api_client.AirtimeApiClient()
api_client.register_component("pypo")
pypoFetch_q = Queue()

View file

@ -40,7 +40,7 @@ except Exception, e:
class PypoFetch(Thread):
def __init__(self, pypoFetch_q, pypoPush_q, media_q, telnet_lock):
Thread.__init__(self)
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
self.fetch_queue = pypoFetch_q
self.push_queue = pypoPush_q
self.media_prepare_queue = media_q

View file

@ -64,7 +64,7 @@ except Exception, e:
class Notify:
def __init__(self):
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
def notify_media_start_playing(self, data, media_id):
logger = logging.getLogger("notify")

View file

@ -42,7 +42,7 @@ except Exception, e:
class PypoPush(Thread):
def __init__(self, q, telnet_lock):
Thread.__init__(self)
self.api_client = api_client.AirTimeApiClient()
self.api_client = api_client.AirtimeApiClient()
self.queue = q
self.telnet_lock = telnet_lock