Merge branch '2.3.x' into 2.3.x-saas

Conflicts:
	airtime_mvc/application/controllers/PreferenceController.php
This commit is contained in:
Martin Konecny 2013-02-04 16:22:35 -05:00
commit c398ce930b
17 changed files with 190 additions and 117 deletions

View file

@ -80,23 +80,19 @@ class ApiRequest(object):
if logger is None: self.logger = logging
else: self.logger = logger
def __call__(self,_post_data=None, **kwargs):
# TODO : get rid of god damn urllib and replace everything with
# grequests or requests at least
final_url = self.url.params(**kwargs).url()
if _post_data is not None: _post_data = urllib.urlencode(_post_data)
try:
req = urllib2.Request(final_url, _post_data)
response = urllib2.urlopen(req).read()
except Exception, e:
self.logger.error('Exception: %s', e)
import traceback
top = traceback.format_exc()
self.logger.error("traceback: %s", top)
response = ""
self.logger.error('Exception: %s', e)
self.logger.error("traceback: %s", traceback.format_exc())
raise
# Ghetto hack for now because we don't the content type we are getting
# (Pointless to look at mime since it's not being set correctly always)
try: return json.loads(response)
except ValueError: return response
return json.loads(response)
def req(self, *args, **kwargs):
self.__req = lambda : self(*args, **kwargs)
@ -150,7 +146,6 @@ class AirtimeApiClient(object):
sys.exit(1)
def __get_airtime_version(self):
# TODO : maybe fix this function to drop an exception?
try: return self.services.version_url()[u'version']
except Exception: return -1
@ -158,18 +153,18 @@ class AirtimeApiClient(object):
logger = self.logger
version = self.__get_airtime_version()
# logger.info('Airtime version found: ' + str(version))
if (version == -1):
if version == -1:
if (verbose):
logger.info('Unable to get Airtime version number.\n')
return False
elif (version[0:3] != AIRTIME_VERSION[0:3]):
if (verbose):
elif version[0:3] != AIRTIME_VERSION[0:3]:
if verbose:
logger.info('Airtime version found: ' + str(version))
logger.info('pypo is at version ' + AIRTIME_VERSION +
' and is not compatible with this version of Airtime.\n')
return False
else:
if (verbose):
if verbose:
logger.info('Airtime version: ' + str(version))
logger.info('pypo is at version ' + AIRTIME_VERSION + ' and is compatible with this version of Airtime.')
return True
@ -182,24 +177,27 @@ class AirtimeApiClient(object):
except: return (False, None)
def notify_liquidsoap_started(self):
return self.services.notify_liquidsoap_started()
try:
self.services.notify_liquidsoap_started()
except Exception, e:
self.logger.error(str(e))
def notify_media_item_start_playing(self, media_id):
""" This is a callback from liquidsoap, we use this to notify
about the currently playing *song*. We get passed a JSON string
which we handed to liquidsoap in get_liquidsoap_data(). """
return self.services.update_start_playing_url(media_id=media_id)
# TODO : get this routine out of here it doesn't belong at all here
def get_liquidsoap_data(self, pkey, schedule):
playlist = schedule[pkey]
data = dict()
try: data["schedule_id"] = playlist['id']
except Exception: data["schedule_id"] = 0
return data
try:
return self.services.update_start_playing_url(media_id=media_id)
except Exception, e:
self.logger.error(str(e))
return None
def get_shows_to_record(self):
return self.services.show_schedule_url()
try:
return self.services.show_schedule_url()
except Exception, e:
self.logger.error(str(e))
return None
def upload_recorded_show(self, data, headers):
logger = self.logger
@ -235,8 +233,12 @@ class AirtimeApiClient(object):
return response
def check_live_stream_auth(self, username, password, dj_type):
return self.services.check_live_stream_auth(
username=username, password=password, djtype=dj_type)
try:
return self.services.check_live_stream_auth(
username=username, password=password, djtype=dj_type)
except Exception, e:
self.logger.error(str(e))
return {}
def construct_url(self,config_action_key):
"""Constructs the base url for every request"""
@ -248,6 +250,10 @@ class AirtimeApiClient(object):
url = url.replace("%%api_key%%", self.config["api_key"])
return url
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def setup_media_monitor(self):
return self.services.media_setup_url()
@ -308,25 +314,40 @@ class AirtimeApiClient(object):
self.logger.error("Could not find index 'files' in dictionary: %s",
str(response))
return []
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def list_all_watched_dirs(self):
return self.services.list_all_watched_dirs()
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def add_watched_dir(self, path):
return self.services.add_watched_dir(path=base64.b64encode(path))
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def remove_watched_dir(self, path):
return self.services.remove_watched_dir(path=base64.b64encode(path))
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def set_storage_dir(self, path):
return self.services.set_storage_dir(path=base64.b64encode(path))
"""
Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen
"""
def get_stream_setting(self):
logger = self.logger
try: return self.services.get_stream_setting()
except Exception, e:
logger.error("Exception: %s", e)
return None
return self.services.get_stream_setting()
def register_component(self, component):
""" Purpose of this method is to contact the server with a "Hey its
@ -343,6 +364,7 @@ class AirtimeApiClient(object):
self.services.update_liquidsoap_status.req(msg=encoded_msg, stream_id=stream_id,
boot_time=time).retry(5)
except Exception, e:
#TODO
logger.error("Exception: %s", e)
def notify_source_status(self, sourcename, status):
@ -351,10 +373,11 @@ class AirtimeApiClient(object):
return self.services.update_source_status.req(sourcename=sourcename,
status=status).retry(5)
except Exception, e:
#TODO
logger.error("Exception: %s", e)
def get_bootstrap_info(self):
""" Retrive infomations needed on bootstrap time """
""" Retrieve infomations needed on bootstrap time """
return self.services.get_bootstrap_info()
def get_files_without_replay_gain_value(self, dir_id):
@ -364,7 +387,11 @@ class AirtimeApiClient(object):
to this file is the return value.
"""
#http://localhost/api/get-files-without-replay-gain/dir_id/1
return self.services.get_files_without_replay_gain(dir_id=dir_id)
try:
return self.services.get_files_without_replay_gain(dir_id=dir_id)
except Exception, e:
self.logger.error(str(e))
return []
def get_files_without_silan_value(self):
"""
@ -372,7 +399,11 @@ class AirtimeApiClient(object):
calculated. This list of files is downloaded into a file and the path
to this file is the return value.
"""
return self.services.get_files_without_silan_value()
try:
return self.services.get_files_without_silan_value()
except Exception, e:
self.logger.error(str(e))
return []
def update_replay_gain_values(self, pairs):
"""
@ -382,12 +413,13 @@ class AirtimeApiClient(object):
self.logger.debug(self.services.update_replay_gain_value(
_post_data={'data': json.dumps(pairs)}))
def update_cue_values_by_silan(self, pairs):
"""
'pairs' is a list of pairs in (x, y), where x is the file's database
row id and y is the file's cue values in dB
"""
print self.services.update_cue_values_by_silan(_post_data={'data': json.dumps(pairs)})
return self.services.update_cue_values_by_silan(_post_data={'data': json.dumps(pairs)})
def notify_webstream_data(self, data, media_id):
@ -409,5 +441,9 @@ class AirtimeApiClient(object):
return response
def update_stream_setting_table(self, data):
response = self.services.update_stream_setting_table(_post_data={'data': json.dumps(data)})
return response
try:
response = self.services.update_stream_setting_table(_post_data={'data': json.dumps(data)})
return response
except Exception, e:
#TODO
self.logger.error(str(e))

View file

@ -58,18 +58,18 @@ class AirtimeMediaMonitorBootstrap():
"""
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()
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)
self.logger.error(str(e))
return {}
"""
@ -94,7 +94,7 @@ class AirtimeMediaMonitorBootstrap():
db_known_files_set = set()
files = self.list_db_files(dir_id)
for f in files:
db_known_files_set.add(f)

View file

@ -19,31 +19,35 @@ class AirtimeDB(Loggable):
saas = user().root_path
# dirs_setup is a dict with keys:
# u'watched_dirs' and u'stor' which point to lists of corresponding
# dirs
dirs_setup = self.apc.setup_media_monitor()
dirs_setup[u'stor'] = normpath( join(saas, dirs_setup[u'stor'] ) )
dirs_setup[u'watched_dirs'] = map(lambda p: normpath(join(saas,p)),
dirs_setup[u'watched_dirs'])
dirs_with_id = dict([ (k,normpath(v)) for k,v in
self.apc.list_all_watched_dirs()['dirs'].iteritems() ])
try:
# dirs_setup is a dict with keys:
# u'watched_dirs' and u'stor' which point to lists of corresponding
# dirs
dirs_setup = self.apc.setup_media_monitor()
dirs_setup[u'stor'] = normpath( join(saas, dirs_setup[u'stor'] ) )
dirs_setup[u'watched_dirs'] = map(lambda p: normpath(join(saas,p)),
dirs_setup[u'watched_dirs'])
dirs_with_id = dict([ (k,normpath(v)) for k,v in
self.apc.list_all_watched_dirs()['dirs'].iteritems() ])
self.id_to_dir = dirs_with_id
self.dir_to_id = dict([ (v,k) for k,v in dirs_with_id.iteritems() ])
self.id_to_dir = dirs_with_id
self.dir_to_id = dict([ (v,k) for k,v in dirs_with_id.iteritems() ])
self.base_storage = dirs_setup[u'stor']
self.storage_paths = mmp.expand_storage( self.base_storage )
self.base_id = self.dir_to_id[self.base_storage]
self.base_storage = dirs_setup[u'stor']
self.storage_paths = mmp.expand_storage( self.base_storage )
self.base_id = self.dir_to_id[self.base_storage]
# hack to get around annoying schema of airtime db
self.dir_to_id[ self.recorded_path() ] = self.base_id
self.dir_to_id[ self.import_path() ] = self.base_id
# hack to get around annoying schema of airtime db
self.dir_to_id[ self.recorded_path() ] = self.base_id
self.dir_to_id[ self.import_path() ] = self.base_id
# We don't know from the x_to_y dict which directory is watched or
# store...
self.watched_directories = set([ os.path.normpath(p) for p in
dirs_setup[u'watched_dirs'] ])
except Exception, e:
self.logger.info(str(e))
# We don't know from the x_to_y dict which directory is watched or
# store...
self.watched_directories = set([ os.path.normpath(p) for p in
dirs_setup[u'watched_dirs'] ])
def to_id(self, directory):
""" directory path -> id """

View file

@ -85,7 +85,15 @@ class MM2(InstanceThread, Loggable):
ToucherThread(path=user().touch_file_path(),
interval=int(config['touch_interval']))
apiclient.register_component('media-monitor')
success = False
while not success:
try:
apiclient.register_component('media-monitor')
success = True
except Exception, e:
self.logger.error(str(e))
import time
time.sleep(10)
manager.loop()

View file

@ -26,13 +26,10 @@ def generate_liquidsoap_config(ss):
logging.basicConfig(format='%(message)s')
ac = AirtimeApiClient(logging.getLogger())
ss = ac.get_stream_setting()
if ss is not None:
try:
generate_liquidsoap_config(ss)
except Exception, e:
logging.error(e)
else:
try:
ss = ac.get_stream_setting()
generate_liquidsoap_config(ss)
except Exception, e:
logging.error(str(e))
print "Unable to connect to the Airtime server."
sys.exit(1)

View file

@ -15,4 +15,7 @@ elif dj_type == '--dj':
response = api_clients.check_live_stream_auth(username, password, source_type)
print response['msg']
if 'msg' in response:
print response['msg']
else:
print False

View file

@ -110,7 +110,10 @@ class ListenerStat(Thread):
self.update_listener_stat_error(v["mount"], 'OK')
except Exception, e:
self.logger.error('Exception: %s', e)
self.update_listener_stat_error(v["mount"], str(e))
try:
self.update_listener_stat_error(v["mount"], str(e))
except Exception, e:
self.logger.error('Exception: %s', e)
return stats

View file

@ -67,15 +67,15 @@ class ReplayGainUpdater(Thread):
self.logger.error(e)
self.logger.debug(traceback.format_exc())
def run(self):
try:
while True:
self.logger.info("Runnning replaygain updater")
while True:
try:
self.logger.info("Running replaygain updater")
self.main()
# Sleep for 5 minutes in case new files have been added
time.sleep(60 * 5)
except Exception, e:
self.logger.error('ReplayGainUpdater Exception: %s', traceback.format_exc())
self.logger.error(e)
except Exception, e:
self.logger.error('ReplayGainUpdater Exception: %s', traceback.format_exc())
self.logger.error(e)
time.sleep(60 * 5)
if __name__ == "__main__":
rgu = ReplayGainUpdater()

View file

@ -179,7 +179,14 @@ if __name__ == '__main__':
ReplayGainUpdater.start_reply_gain(api_client)
api_client.register_component("pypo")
success = False
while not success:
try:
api_client.register_component('pypo')
success = True
except Exception, e:
logger.error(str(e))
time.sleep(10)
pypoFetch_q = Queue()
recorder_q = Queue()

View file

@ -206,23 +206,25 @@ class PypoFetch(Thread):
"""
def set_bootstrap_variables(self):
self.logger.debug('Getting information needed on bootstrap from Airtime')
info = self.api_client.get_bootstrap_info()
if info is None:
try:
info = self.api_client.get_bootstrap_info()
except Exception, e:
self.logger.error('Unable to get bootstrap info.. Exiting pypo...')
else:
self.logger.debug('info:%s', info)
commands = []
for k, v in info['switch_status'].iteritems():
commands.append(self.switch_source_temp(k, v))
self.logger.error(str(e))
stream_format = info['stream_label']
station_name = info['station_name']
fade = info['transition_fade']
self.logger.debug('info:%s', info)
commands = []
for k, v in info['switch_status'].iteritems():
commands.append(self.switch_source_temp(k, v))
commands.append(('vars.stream_metadata_type %s\n' % stream_format).encode('utf-8'))
commands.append(('vars.station_name %s\n' % station_name).encode('utf-8'))
commands.append(('vars.default_dj_fade %s\n' % fade).encode('utf-8'))
PypoFetch.telnet_send(self.logger, self.telnet_lock, commands)
stream_format = info['stream_label']
station_name = info['station_name']
fade = info['transition_fade']
commands.append(('vars.stream_metadata_type %s\n' % stream_format).encode('utf-8'))
commands.append(('vars.station_name %s\n' % station_name).encode('utf-8'))
commands.append(('vars.default_dj_fade %s\n' % fade).encode('utf-8'))
PypoFetch.telnet_send(self.logger, self.telnet_lock, commands)
def restart_liquidsoap(self):

View file

@ -189,9 +189,17 @@ class Recorder(Thread):
self.server_timezone = ''
self.queue = q
self.loops = 0
self.api_client.register_component("show-recorder")
self.logger.info("RecorderFetch: init complete")
success = False
while not success:
try:
self.api_client.register_component('show-recorder')
success = True
except Exception, e:
self.logger.error(str(e))
time.sleep(10)
def handle_message(self):
if not self.queue.empty():
message = self.queue.get()