]> git.parisson.com Git - deefuzzer.git/commitdiff
Added documentation
authorachbed <github@achbed.org>
Fri, 21 Nov 2014 04:36:52 +0000 (22:36 -0600)
committerachbed <github@achbed.org>
Fri, 21 Nov 2014 04:36:52 +0000 (22:36 -0600)
Revised init handling of preferences for consistency
Fixed issue where some boolean flags (ie, modes) were not being handled properly

Signed-off-by: achbed <github@achbed.org>
deefuzzer/core.py
deefuzzer/station.py

index eadeabf51277a32e7e029c2e838872beeeaccd51..9f401c515a2895e6cee88b9681167faea4787e80 100644 (file)
@@ -51,51 +51,52 @@ mimetypes.add_type('application/x-yaml','.yaml')
 class DeeFuzzer(Thread):
     """a DeeFuzzer diffuser"""
 
+    logger = None
     m3u = None
     rss = None
+    station = []
+    stations = []
 
     def __init__(self, conf_file):
         Thread.__init__(self)
         self.conf_file = conf_file
         self.conf = get_conf_dict(self.conf_file)
+
+        # Get the log setting first (if possible)
+        log_file = str(self.conf.pop('log', ''))
+        log_dir = os.sep.join(log_file.split(os.sep)[:-1])
+        if not os.path.exists(log_dir) and log_dir:
+            os.makedirs(m3u_dir)
+        self.logger = Logger(log_file)
+
         for key in self.conf['deefuzzer'].keys():
-            if key == 'log':
-                log_file = self.conf['deefuzzer']['log']
-                log_dir = os.sep.join(log_file.split(os.sep)[:-1])
-                if not os.path.exists(log_dir) and log_dir:
-                    os.makedirs(m3u_dir)
-                self.logger = Logger(log_file)
             if key == 'm3u':
-                self.m3u = self.conf['deefuzzer']['m3u']
+                self.m3u = str(self.conf['deefuzzer'][key])
+
+            elif key == 'station':
+                # Load station definitions from the main config file
+                if not isinstance(self.conf['deefuzzer'][key], list):
+                    self.add_station(self.conf['deefuzzer'][key])
+                else:
+                    for s in self.conf['deefuzzer'][key]:
+                        self.add_station(s)
+
+            elif key == 'stationconfig':
+                # Load additional station definitions from the requested folder
+                self.load_stations_fromconfig(self.conf['deefuzzer'][key])
+
+            elif key == 'stationfolder':
+                # Create stations automagically from a folder structure
+                if isinstance(self.conf['deefuzzer'][key], dict):
+                    self.create_stations_fromfolder(self.conf['deefuzzer'][key])
             else:
                 setattr(self, key, self.conf['deefuzzer'][key])
 
-        # Fix wrong type data from xmltodict when one station (*)
-        if 'station' not in self.conf['deefuzzer']:
-            self.conf['deefuzzer']['station'] = []
-        else:
-            if not isinstance(self.conf['deefuzzer']['station'], list):
-                s = self.conf['deefuzzer']['station']
-                self.conf['deefuzzer']['station'] = []
-                self.conf['deefuzzer']['station'].append(s)
-        
-        # Load additional station definitions from the requested folder
-        if 'stationconfig' in self.conf['deefuzzer']:
-            self.load_stations(self.conf['deefuzzer']['stationconfig'])
-        
-        # Create stations automagically from a folder structure
-        if 'stationfolder' in self.conf['deefuzzer'].keys() and isinstance(self.conf['deefuzzer']['stationfolder'], dict):
-            self.create_stations_fromfolder(self.conf['deefuzzer']['stationfolder'])
-
-        self.nb_stations = len(self.conf['deefuzzer']['station'])
-
         # Set the deefuzzer logger
         self.logger.write_info('Starting DeeFuzzer')
         self.logger.write_info('Using libshout version %s' % shout.version())
+        self.logger.write_info('Number of stations : ' + str(len(self.station)))
 
-        # Init all Stations
-        self.stations = []
-        self.logger.write_info('Number of stations : ' + str(self.nb_stations))
 
     def set_m3u_playlist(self):
         m3u_dir = os.sep.join(self.m3u.split(os.sep)[:-1])
@@ -110,10 +111,19 @@ class DeeFuzzer(Thread):
         self.logger.write_info('Writing M3U file to : ' + self.m3u)
 
     def create_stations_fromfolder(self, options):
+        """Scan a folder for subfolders containing media, and make stations from them all."""
+
         if not 'folder' in options.keys():
+            # We have no folder specified.  Bail.
             return
+
         folder = str(options['folder'])
-        self.logger.write_info('Scanning folder ' + folder + ' for stations...')
+        if not os.path.isdir(folder):
+            # The specified path is not a folder.  Bail.
+            return
+
+        self.logger.write_info('Scanning folder ' + folder + ' for stations')
+
         files = os.listdir(folder)
         for file in files:
             filepath = os.path.join(folder, file)
@@ -122,6 +132,8 @@ class DeeFuzzer(Thread):
                     self.create_station(filepath, options)
 
     def create_station(self, folder, options):
+        """Create a station definition for a folder given the specified options."""
+
         self.logger.write_info('Creating station for folder ' + folder)
         s = {}
         path, name = os.path.split(folder)
@@ -132,43 +144,70 @@ class DeeFuzzer(Thread):
         if not 'media' in s.keys():
             s['media'] = {}
         s['media']['dir'] = folder
-        self.conf['deefuzzer']['station'].append(s)
-    
-        
-    def load_stations(self, folder):
-        if isinstance(folder, dict):
+        self.add_station(s)
+
+    def load_stations_fromconfig(self, folder):
+        """Load one or more configuration files looking for stations."""
+
+        if isinstance(folder, dict) or isinstance(folder, list):
+            # We were given a list or dictionary.  Loop though it and load em all
             for f in folder:
-                self.load_stations(f)
+                self.load_station_configs(f)
             return
 
+        if os.path.isfile(folder):
+            # We have a file specified.  Load just that file.
+            self.load_station_config(folder)
+            return
+            
         if not os.path.isdir(folder):
+            # Whatever we have, it's not either a file or folder.  Bail.
             return
-        
+
         self.logger.write_info('Loading station config files in ' + folder)
         files = os.listdir(folder)
         for file in files:
             filepath = os.path.join(folder, file)
             if os.path.isfile(filepath):
                 self.load_station_config(filepath)
-        
+
     def load_station_config(self, file):
+        """Load station configuration(s) from a config file."""
+
         self.logger.write_info('Loading station config file ' + file)
         stationdef = get_conf_dict(file)
         if isinstance(stationdef, dict):
-            if 'station' in stationdef.keys() and isinstance(stationdef['station'], dict):
-                self.conf['deefuzzer']['station'].append(stationdef['station'])
+            if 'station' in stationdef.keys():
+                if isinstance(stationdef['station'], dict):
+                    self.add_station(stationdef['station'])
+                elif isinstance(stationdef['station'], list):
+                    for s in stationdef['station']:
+                        self.add_station(s)
+
+    def add_station(self, this_station):
+        """Adds a station configuration to the list of stations."""
+        try:
+            # We should probably test to see if we're putting the same station in multiple times
+            # Same in this case probably means the same media folder, server, and mountpoint
+            self.station.append(this_station)
+        except Exception:
+            return
 
     def run(self):
         q = Queue.Queue(1)
 
-        for i in range(0,self.nb_stations):
-            station = self.conf['deefuzzer']['station'][i]
+        ns = len(self.station)
+        for i in range(0, ns):
+            try:
+                station = self.station[i]
 
-            # Apply station defaults if they exist
-            if 'stationdefaults' in self.conf['deefuzzer']:
-                if isinstance(self.conf['deefuzzer']['stationdefaults'], dict):
-                    station = merge_defaults(station, self.conf['deefuzzer']['stationdefaults'])
-            self.stations.append(Station(station, q, self.logger, self.m3u))
+                # Apply station defaults if they exist
+                if 'stationdefaults' in self.conf['deefuzzer']:
+                    if isinstance(self.conf['deefuzzer']['stationdefaults'], dict):
+                        station = merge_defaults(station, self.conf['deefuzzer']['stationdefaults'])
+                self.stations.append(Station(station, q, self.logger, self.m3u))
+            except Exception:
+                continue
 
         if self.m3u:
             self.set_m3u_playlist()
@@ -176,9 +215,13 @@ class DeeFuzzer(Thread):
         p = Producer(q)
         p.start()
 
+        ns = len(self.stations)
         # Start the Stations
-        for i in range(0,self.nb_stations):
-            self.stations[i].start()
+        for i in range(0, ns):
+            try:
+                self.stations[i].start()
+            except Exception:
+                continue
 
 
 class Producer(Thread):
index f1fec09839decffaa8797e52ce16f892009385d1..20f0b75ef67d2c3e633d7ec79cc167c18e6f277c 100644 (file)
@@ -67,10 +67,16 @@ class Station(Thread):
     lp = 1
     player_mode = 0
     osc_control_mode = 0
+    osc_control_port = 16001
     twitter_mode = 0
     jingles_mode = 0
+    jingles_shuffle = 1
+    jingles_dir = ''
     relay_mode = 0
+    relay_url = ''
+    relay_author = ''
     record_mode = 0
+    record_dir = ''
     run_mode = 1
     station_dir = None
     appendtype = 1
@@ -78,6 +84,11 @@ class Station(Thread):
     feeds_rss = 1
     feeds_mode = 1
     feeds_playlist = 1
+    media_dir = ''
+    m3u_playlist_file = []
+    mountpoint = 'default'
+    type = 'icecast'
+    feeds_media_url = ''
 
     def __init__(self, station, q, logger, m3u):
         Thread.__init__(self)
@@ -86,39 +97,31 @@ class Station(Thread):
         self.logger = logger
         self.m3u = m3u
 
-        if 'station_dir' in self.station:
-            self.station_dir = self.station['station_dir']
-
-        # Media
-        self.media_dir = self.station['media']['dir']
-        self.media_format = self.station['media']['format']
-        self.shuffle_mode = int(self.station['media']['shuffle'])
-        self.bitrate = self.station['media']['bitrate']
-        self.ogg_quality = self.station['media']['ogg_quality']
-        self.samplerate = self.station['media']['samplerate']
-        self.voices = self.station['media']['voices']
-        self.m3u_playlist_file = []
-        if 'm3u' in self.station['media'].keys():
-            self.m3u_playlist_file = self.station['media']['m3u']
-
-        # Server
-        if 'mountpoint' in self.station['server'].keys():
-            self.mountpoint = self.station['server']['mountpoint']
-        elif 'short_name' in self.station['infos'].keys():
-            self.mountpoint = self.station['infos']['short_name']
-        else:
-            self.mountpoint = 'default'
+        # Port the feeds key into the rss key if it exists (for backwards compatibility)
+        if 'feeds' in self.station.keys():
+            self.station['rss'] = self.station['feeds']
+            self.station.pop('feeds')
+
+        # Get the mountpoint and short name first
+        if 'server' in self.station.keys():
+            # Try to get the mountpoint as defined by the server.mountpoint parameter
+            self.mountpoint = str(self.station['server'].pop('mountpoint',self.mountpoint))
+            self.appendtype = int(self.station['server'].pop('appendtype',self.appendtype))
+            self.type = str(self.station['server'].pop('type',self.type))
+        
+        # Get our media format since we need to to define a stream object
+        if 'media' in self.station.keys():
+            self.media_format = str(self.station['media'].pop('format',self.media_format))
+            
+        # We don't have a non-default mount point yet, so get info.short_name and try that
+        if self.mountpoint == 'default':
+            if 'infos' in self.station.keys():
+                self.mountpoint = str(self.station['infos'].pop('short_name','default'))
 
+        # Set the short name based on the mount point.
         self.short_name = self.mountpoint
-
-        if 'appendtype' in self.station['server'].keys():
-            self.appendtype = self.station['server']['appendtype']
-
-        if 'type' in self.station['server']:
-            self.type = self.station['server']['type'] #  'icecast' | 'stream-m'
-        else:
-            self.type = 'icecast'
-
+        
+        # Set up the stream channel
         if 'stream-m' in self.type:
             self.channel = HTTPStreamer()
             self.channel.mount = '/publish/' + self.mountpoint
@@ -129,19 +132,161 @@ class Station(Thread):
                 self.channel.mount = self.channel.mount + '.' + self.media_format
         else:
             sys.exit('Not a compatible server type. Choose "stream-m" or "icecast".')
-
-        self.channel.url = self.station['infos']['url']
-        self.channel.name = self.station['infos']['name']
-        self.channel.genre = self.station['infos']['genre']
-        self.channel.description = self.station['infos']['description']
+        
+        # Apply defaults for the channel
         self.channel.format = self.media_format
-        self.channel.host = self.station['server']['host']
-        self.channel.port = int(self.station['server']['port'])
         self.channel.user = 'source'
-        self.channel.password = self.station['server']['sourcepassword']
-        self.channel.public = int(self.station['server']['public'])
-        self.channel.genre = self.station['infos']['genre']
-        self.channel.description = self.station['infos']['description']
+        
+        # Parse the rest of the key structure
+        for key in self.station.keys():
+            if key == 'station_dir':
+                self.station_dir = self.station['station_dir']
+            
+            if key == 'media':
+                # Media
+                for subkey in self.station[key].keys():
+                    if subkey == 'dir':
+                        self.media_dir = str(self.station[key][subkey])
+                        
+                    elif subkey == 'shuffle':
+                        self.shuffle_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'bitrate':
+                        self.bitrate = int(self.station[key][subkey])
+                        
+                    elif subkey == 'ogg_quality':
+                        self.ogg_quality = int(self.station[key][subkey])
+                        
+                    elif subkey == 'samplerate':
+                        self.samplerate = int(self.station[key][subkey])
+                        
+                    elif subkey == 'voices':
+                        self.voices = int(self.station[key][subkey])
+                        
+                    elif subkey == 'm3u':
+                        self.m3u_playlist_file = self.station[key][subkey]
+
+            if key == 'infos':
+                # Stream Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'url':
+                        self.channel.url = str(self.station[key][subkey])
+                        
+                    elif subkey == 'name':
+                        self.channel.name = str(self.station[key][subkey])
+                        
+                    elif subkey == 'genre':
+                        self.channel.genre = str(self.station[key][subkey])
+                        
+                    elif subkey == 'description':
+                        self.channel.description = str(self.station[key][subkey])
+                        
+            if key == 'server':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'host':
+                        self.channel.host = str(self.station[key][subkey])
+                        
+                    elif subkey == 'port':
+                        self.channel.port = str(self.station[key][subkey])
+                        
+                    elif subkey == 'sourceuser':
+                        self.channel.user = str(self.station[key][subkey])
+                        
+                    elif subkey == 'sourcepassword':
+                        self.channel.password = str(self.station[key][subkey])
+                        
+                    elif subkey == 'public':
+                        self.channel.public = str(self.station[key][subkey])
+                        
+            if key == 'rss':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.feeds_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'dir':
+                        self.feeds_dir = str(self.station[key][subkey])
+                        
+                    elif subkey == 'enclosure':
+                        self.feeds_enclosure = int(self.station[key][subkey])
+                        
+                    elif subkey == 'json':
+                        self.feeds_json = int(self.station[key][subkey])
+                        
+                    elif subkey == 'rss':
+                        self.feeds_rss = int(self.station[key][subkey])
+                        
+                    elif subkey == 'playlist':
+                        self.feeds_playlist = int(self.station[key][subkey])
+                        
+                    elif subkey == 'media_url':
+                        self.feeds_media_url = str(self.station[key][subkey])
+                        
+            if key == 'control':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.osc_control_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'port':
+                        self.osc_control_port = int(self.station[key][subkey])
+                        
+            if key == 'jingles':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.jingles_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'shuffle':
+                        self.jingles_shuffle = int(self.station[key][subkey])
+                        
+                    elif subkey == 'dir':
+                        self.jingles_dir = str(self.station[key][subkey])
+                        
+            if key == 'relay':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.relay_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'url':
+                        self.relay_url = str(self.station[key][subkey])
+                        
+                    elif subkey == 'author':
+                        self.relay_author = str(self.station[key][subkey])
+                        
+            if key == 'twitter':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.twitter_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'key':
+                        self.twitter_key = str(self.station[key][subkey])
+                        
+                    elif subkey == 'secret':
+                        self.twitter_secret = str(self.station[key][subkey])
+                        
+                    elif subkey == 'tags':
+                        self.twitter_tags = str(self.station[key][subkey]).split(' ')
+                        
+                    elif subkey == 'messages':
+                        self.twitter_messages = self.station[key][subkey]
+                        if isinstance(self.twitter_messages,  dict):
+                            self.twitter_messages = list(self.twitter_messages)
+                        
+            if key == 'record':
+                # Server Info
+                for subkey in self.station[key].keys():
+                    if subkey == 'mode':
+                        self.record_mode = int(self.station[key][subkey])
+                        
+                    elif subkey == 'dir':
+                        self.record_dir = str(self.station[key][subkey])
+                        
+
+            
         if self.channel.format == 'mp3':
             self.channel.audio_info = { 'bitrate': str(self.bitrate),
                                         'samplerate': str(self.samplerate),
@@ -156,29 +301,12 @@ class Station(Thread):
         self.channel_url = self.server_url + self.channel.mount
 
         # RSS
-        if 'feeds' in self.station:
-            self.station['rss'] = self.station['feeds']
-
-        if 'rss' in self.station:
-            if 'mode' in self.station['rss']:
-                self.feeds_mode = int(self.station['rss']['mode'])
-            self.feeds_dir = self.station['rss']['dir']
-            self.feeds_enclosure = int(self.station['rss']['enclosure'])
-            if 'json' in self.station['rss']:
-                self.feeds_json = int(self.station['rss']['json'])
-            if 'rss' in self.station['rss']:
-                self.feeds_rss = int(self.station['rss']['rss'])
-            if 'playlist' in self.station['rss']:
-                self.feeds_playlist = int(self.station['rss']['playlist'])
-
+        if self.feeds_media_url == '':
             self.feeds_media_url = self.channel.url + '/media/'
-            if 'media_url' in self.station['rss']:
-                if self.station['rss']['media_url']:
-                    self.feeds_media_url = self.station['rss']['media_url']
 
         self.base_name = self.feeds_dir + os.sep + self.short_name + '_' + self.channel.format
-        self.feeds_current_file = self.base_name + '_current.xml'
-        self.feeds_playlist_file = self.base_name + '_playlist.xml'
+        self.feeds_current_file = self.base_name + '_current'
+        self.feeds_playlist_file = self.base_name + '_playlist'
 
         # Logging
         self.logger.write_info('Opening ' + self.short_name + ' - ' + self.channel.name + \
@@ -194,60 +322,33 @@ class Station(Thread):
         self.player = Player(self.type)
 
         # OSCing
-        # mode = 0 means Off, mode = 1 means On
-        if 'control' in self.station:
-            self.osc_control_mode = int(self.station['control']['mode'])
-            if self.osc_control_mode:
-                self.osc_port = self.station['control']['port']
-                self.osc_controller = OSCController(self.osc_port)
-                # OSC paths and callbacks
-                self.osc_controller.add_method('/media/next', 'i', self.media_next_callback)
-                self.osc_controller.add_method('/media/relay', 'i', self.relay_callback)
-                self.osc_controller.add_method('/twitter', 'i', self.twitter_callback)
-                self.osc_controller.add_method('/jingles', 'i', self.jingles_callback)
-                self.osc_controller.add_method('/record', 'i', self.record_callback)
-                self.osc_controller.add_method('/player', 'i', self.player_callback)
-                self.osc_controller.add_method('/run', 'i', self.run_callback)
-                self.osc_controller.start()
+        if self.osc_control_mode and self.osc_control_port:
+            self.osc_controller = OSCController(self.osc_control_port)
+            # OSC paths and callbacks
+            self.osc_controller.add_method('/media/next', 'i', self.media_next_callback)
+            self.osc_controller.add_method('/media/relay', 'i', self.relay_callback)
+            self.osc_controller.add_method('/twitter', 'i', self.twitter_callback)
+            self.osc_controller.add_method('/jingles', 'i', self.jingles_callback)
+            self.osc_controller.add_method('/record', 'i', self.record_callback)
+            self.osc_controller.add_method('/player', 'i', self.player_callback)
+            self.osc_controller.add_method('/run', 'i', self.run_callback)
+            self.osc_controller.start()
 
         # Jingling between each media.
-        if 'jingles' in self.station:
-            self.jingles_mode =  int(self.station['jingles']['mode'])
-            self.jingles_shuffle = self.station['jingles']['shuffle']
-            self.jingles_dir = self.station['jingles']['dir']
-            if self.jingles_mode == 1:
-                self.jingles_callback('/jingles', [1])
+        if self.jingles_mode:
+            self.jingles_callback('/jingles', [1])
 
         # Relaying
-        if 'relay' in self.station:
-            self.relay_mode = int(self.station['relay']['mode'])
-            self.relay_url = self.station['relay']['url']
-            self.relay_author = self.station['relay']['author']
-            if self.relay_mode == 1:
-                self.relay_callback('/media/relay', [1])
+        if self.relay_mode:
+            self.relay_callback('/media/relay', [1])
 
         # Twitting
-        if 'twitter' in self.station:
-            self.twitter_mode = int(self.station['twitter']['mode'])
-            self.twitter_key = self.station['twitter']['key']
-            self.twitter_secret = self.station['twitter']['secret']
-            self.twitter_tags = self.station['twitter']['tags'].split(' ')
-            try:
-                self.twitter_messages = self.station['twitter']['message']
-                if isinstance(self.twitter_messages,  dict):
-                    self.twitter_messages = list(self.twitter_messages)
-            except:
-                pass
-
-            if self.twitter_mode:
-                self.twitter_callback('/twitter', [1])
+        if self.twitter_mode:
+            self.twitter_callback('/twitter', [1])
 
         # Recording
-        if 'record' in self.station:
-            self.record_mode = int(self.station['record']['mode'])
-            self.record_dir = self.station['record']['dir']
-            if self.record_mode:
-                self.record_callback('/record', [1])
+        if self.record_mode:
+            self.record_callback('/record', [1])
 
     def run_callback(self, path, value):
         value = value[0]
@@ -429,7 +530,7 @@ class Station(Thread):
                 new_tracks = new_playlist_set - playlist_set
                 self.new_tracks = list(new_tracks.copy())
 
-                if self.twitter_mode == 1  and self.counter:
+                if self.twitter_mode  and self.counter:
                     self.tweet()
 
                 # Shake it, Fuzz it !
@@ -554,15 +655,12 @@ class Station(Thread):
                             items = rss_item_list,)
 
         if self.feeds_rss:
-            f = open(rss_file, 'w')
+            f = open(rss_file + '.xml', 'w')
             rss.write_xml(f, 'utf-8')
             f.close()
 
         if self.feeds_json:
-            path, fn = os.path.split(rss_file)
-            base, ext = os.path.splitext(fn)
-            json_file = os.path.join(self.feeds_dir, base + '.json')
-            f = open(json_file, 'w')
+            f = open(rss_file + '.json', 'w')
             f.write(json.dumps(json_data, separators=(',',':')))
             f.close()