]> git.parisson.com Git - deefuzzer.git/commitdiff
New MediaBase class for common media object functionality
authorachbed <github@achbed.org>
Tue, 27 Jan 2015 23:13:47 +0000 (17:13 -0600)
committerachbed <github@achbed.org>
Tue, 27 Jan 2015 23:13:47 +0000 (17:13 -0600)
Refactored MP3, OGG, WebM classes to use MediaBase
Station now uses common MediaBase functions to get artist, title, and song info

deefuzzer/station.py
deefuzzer/tools/__init__.py
deefuzzer/tools/mediabase.py [new file with mode: 0644]
deefuzzer/tools/mp3.py
deefuzzer/tools/ogg.py
deefuzzer/tools/webm.py

index 4cef3faee4bff0476375feb6adc8d50abd93167d..1e2ae72610e98d85515e0e6e928457d1d4b9e828 100644 (file)
@@ -95,6 +95,8 @@ class Station(Thread):
         self.logqueue = logqueue
         self.m3u = m3u
 
+        self.current_media_obj = MediaBase()
+
         if 'station_statusfile' in self.station:
             self.statusfile = station['station_statusfile']
             try:
@@ -452,24 +454,12 @@ class Station(Thread):
         if len(self.new_tracks):
             new_tracks_objs = self.media_to_objs(self.new_tracks)
             for media_obj in new_tracks_objs:
-                title = ''
-                artist = ''
-                if 'title' in media_obj.metadata:
-                    title = media_obj.metadata['title']
-                if 'artist' in media_obj.metadata:
-                    artist = media_obj.metadata['artist']
-                if not (title or artist):
-                    song = str(media_obj.file_name)
-                else:
-                    song = artist + ' - ' + title
-
-                song = song.encode('utf-8')
-                artist = artist.encode('utf-8')
+                title, artist, song = self.get_songmeta(media_obj)
 
                 artist_names = artist.split(' ')
                 artist_tags = ' #'.join(list(set(artist_names) - {'&', '-'}))
-                message = '#NEWTRACK ! %s #%s on #%s RSS: ' % \
-                          (song.replace('_', ' '), artist_tags, self.short_name)
+                message = '#NEWTRACK ! %s %s on #%s' % \
+                          (song, artist_tags.strip(), self.short_name)
                 message = message[:113] + self.feeds_url
                 self.update_twitter(message)
 
@@ -547,30 +537,20 @@ class Station(Thread):
     def media_to_objs(self, media_list):
         media_objs = []
         for media in media_list:
+            file_meta = MediaBase()
             file_name, file_title, file_ext = get_file_info(media)
             self.q.get(1)
             try:
                 if file_ext.lower() == 'mp3' or mimetypes.guess_type(media)[0] == 'audio/mpeg':
-                    try:
-                        file_meta = Mp3(media)
-                    except:
-                        continue
+                    file_meta = Mp3(media)
                 elif file_ext.lower() == 'ogg' or mimetypes.guess_type(media)[0] == 'audio/ogg':
-                    try:
-                        file_meta = Ogg(media)
-                    except:
-                        continue
+                    file_meta = Ogg(media)
                 elif file_ext.lower() == 'webm' or mimetypes.guess_type(media)[0] == 'video/webm':
-                    try:
-                        file_meta = WebM(media)
-                    except:
-                        continue
-                if self.feeds_showfilename:
-                    file_meta.metadata['filename'] = file_name.decode("utf-8")  # decode needed for some weird filenames
-                if self.feeds_showfilepath:
-                    file_meta.metadata['filepath'] = media.decode("utf-8")  # decode needed for some weird filenames
+                    file_meta = WebM(media)
             except:
                 pass
+            file_meta.metadata['filename'] = file_name.decode("utf-8")  # decode needed for some weird filenames
+            file_meta.metadata['filepath'] = media.decode("utf-8")  # decode needed for some weird filenames
             self.q.task_done()
             media_objs.append(file_meta)
         return media_objs
@@ -602,18 +582,16 @@ class Station(Thread):
 
             for key in media.metadata.keys():
                 if media.metadata[key] != '':
+                    if key == 'filepath' and not self.feeds_showfilepath:
+                        continue
+                    if key == 'filename' and not self.feeds_showfilename:
+                        continue
                     media_description += media_description_item % (key.capitalize(),
                                                                    media.metadata[key])
                     json_item[key] = media.metadata[key]
             media_description += '</table>'
 
-            title = media.metadata['title']
-            artist = media.metadata['artist']
-            if not (title or artist):
-                song = str(media.file_title)
-            else:
-                song = artist + ' - ' + title
-
+            title, artist, song = self.get_songmeta(media)
             media_absolute_playtime += media.length
 
             if self.feeds_enclosure == '1':
@@ -674,11 +652,7 @@ class Station(Thread):
 
     def set_relay_mode(self):
         self.prefix = '#nowplaying #LIVE'
-        self.title = self.channel.description.encode('utf-8')
-        self.artist = self.relay_author.encode('utf-8')
-        self.title = self.title.replace('_', ' ')
-        self.artist = self.artist.replace('_', ' ')
-        self.song = self.artist + ' - ' + self.title
+        self.get_currentsongmeta()
 
         if self.type == 'stream-m':
             relay = URLReader(self.relay_url)
@@ -688,28 +662,40 @@ class Station(Thread):
         else:
             self.stream = self.player.relay_read()
 
-    def set_read_mode(self):
-        self.prefix = '#nowplaying'
-        self.current_media_obj = self.media_to_objs([self.media])
+    def get_songmeta(self, mediaobj):
+        title = ""
+        artist = ""
+        song = ""
+
         try:
-            self.title = self.current_media_obj[0].metadata['title']
-            self.artist = self.current_media_obj[0].metadata['artist']
+            title = mediaobj.get_title()
+            artist = mediaobj.get_artist()
+            song = mediaobj.get_song(True)
         except:
-            self.title = 'title'
-            self.artist = 'artist'
+            pass
 
-        self.title = self.title.replace('_', ' ')
-        self.artist = self.artist.replace('_', ' ')
+        return title, artist, song
 
-        if not (self.title or self.artist):
-            song = str(self.current_media_obj[0].file_name)
-        else:
-            song = self.artist + ' - ' + self.title
+    def get_currentsongmeta(self):
+        self.title = ""
+        self.artist = ""
+        self.song = ""
+        self.current_media_obj = MediaBase()
+
+        try:
+            m = self.media_to_objs([self.media])
+            self.current_media_obj = m[0]
+        except:
+            pass
+
+        self.title, self.artist, self.song = self.get_songmeta(self.current_media_obj)
+
+    def set_read_mode(self):
+        self.prefix = '#nowplaying'
+        self.get_currentsongmeta()
 
-        self.song = song.encode('utf-8')
-        self.artist = self.artist.encode('utf-8')
         self.metadata_file = self.metadata_dir + os.sep + self.current_media_obj[0].file_name + '.xml'
-        self.update_feeds(self.current_media_obj, self.feeds_current_file, '(currently playing)')
+        self.update_feeds([self.current_media_obj], self.feeds_current_file, '(currently playing)')
         self._info('DeeFuzzing:  id = %s, name = %s'
                    % (self.id, self.current_media_obj[0].file_name))
         self.player.set_media(self.media)
@@ -730,8 +716,6 @@ class Station(Thread):
     def update_twitter_current(self):
         if not self.__twitter_should_update():
             return
-        # artist_names = self.artist.split(' ')
-        # artist_tags = ' #'.join(list(set(artist_names) - {'&', '-'}))
         message = '%s %s on #%s' % (self.prefix, self.song, self.short_name)
         tags = '#' + ' #'.join(self.twitter_tags)
         message = message + ' ' + tags
index 6dc964d9781e6cccac6654b14402eed67417d60b..276c19803c3f4cb1b058fb25624b0a1727c1355c 100644 (file)
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 from xmltodict import *
 from PyRSS2Gen import *
+from mediabase import *
 from mp3 import *
 from ogg import *
 from webm import *
diff --git a/deefuzzer/tools/mediabase.py b/deefuzzer/tools/mediabase.py
new file mode 100644 (file)
index 0000000..4474e63
--- /dev/null
@@ -0,0 +1,127 @@
+__author__ = 'Dennis Wallace'
+
+import tempfile
+
+class MediaBase(object):
+    """Base Media class.  All media objects should inherit from this class
+    to allow common functions to be used in core code.  See MP3 and OGG classes
+    for examples on how to configure a subclass."""
+
+    def __init__(self):
+        object.__init__(self)
+
+        # Set the following five values in an inherited subclass.
+
+        # A text string describing this media type
+        self.description = ''
+
+        # A text string declaring the MIME Type for this media type
+        self.mime_type = ''
+
+        # A text string declaring the common file extension for this media type
+        self.extension = ''
+
+        # A text string declaring the media format.  The self.format property
+        # should be unique across all subclasses inherited from MediaBase.
+        self.format = ''
+
+        # tagdata contains a dictionary of tags to use to gather metadata from the sourceobj
+        self.tagdata = {}
+
+        self.media = None
+        self.item_id = ''
+        self.source = None
+        self.options = {}
+        self.bitrate_default = 0
+        self.info = None
+        self.bitrate = 0
+        self.length = 0
+        self.metadata = {
+            'title': '',
+            'artist': '',
+            'album': '',
+            'date': '',
+            'comment': '',
+            'country': '',
+            'genre': '',
+            'copyright': ''
+        }
+
+        # sourceobj contains the metadata information for the referenced object
+        self.sourceobj = {}
+
+        self.media_info = []
+        self.file_name = ''
+        self.file_title = ''
+        self.file_ext = ''
+        self.size = 0
+
+        # A more cross-platform way to do this
+        self.cache_dir = tempfile.gettempdir()
+
+    def get_format(self):
+        """Gets the format string of the media type"""
+        return self.format
+
+    def get_file_extension(self):
+        """Gets the actual file extension string of the media"""
+        return self.file_ext
+
+    def get_mime_type(self):
+        """Gets the MIME Type string for this media type"""
+        return self.mime_type
+
+    def get_description(self):
+        """Gets the description string for this media type"""
+        return self.description
+
+    def set_cache_dir(self, path):
+        """Sets an alternate location for temporary cache files used in this media object"""
+        self.cache_dir = path
+
+    def get_file_metadata(self):
+        """Returns the metadata for the media, filtered by the tagdata dictionary for this media type"""
+        metadata = {}
+        for key in self.tagdata.keys():
+            metadata[key] = ''
+            try:
+                metadata[key] = self.sourceobj[key][0]
+            except:
+                try:
+                    if self.tagdata[key] != '':
+                        metadata[key] = self.sourceobj[self.tagdata[key]][0]
+                except:
+                    pass
+        return metadata
+
+    def __get_metadata_value(self, key, clean=False):
+        """Returns a metadata value for a give key.  If clean is True, then the resulting string will
+        be cleaned before it is returned.  If the key does not exist, an empty string is returned."""
+        if key not in self.metadata:
+            return ''
+        r = self.metadata[key]
+        if clean:
+            r = r.replace('_',' ').strip()
+        return r.encode('utf-8')
+
+    def get_title(self):
+        """Returns the cleaned title for this media"""
+        return self.__get_metadata_value('title', True)
+
+    def get_artist(self):
+        """Returns the cleaned artist for this media"""
+        return self.__get_metadata_value('artist', True)
+
+    def get_song(self, usefn=True):
+        """Returns a string in the form "artist - title" for this media.  If either artist or title are blank,
+        only the non-blank field is returned.  If both fields are blank, and the usefn parameter is True, then
+        the filename is returned instead.  Otherwise, an empty string is returned."""
+        a = self.__get_metadata_value('artist', True)
+        t = self.__get_metadata_value('title', True)
+        if len(a) == 0 and len(t) == 0 and usefn:
+            a = self.file_name.encode('utf-8')
+        r = a
+        if len(a) > 0 and len(t) > 0:
+            r += ' - '
+        r += t
+        return r
index 4581300db3fd5a7472fe1b9336e703e313cac64a..fbb102012ab85f54bb987a915bcc082b8f0ece95 100644 (file)
@@ -50,17 +50,21 @@ EasyID3.valid_keys["country"] = "TXXX:COUNTRY:'XXX'"
 EasyID3.RegisterTXXXKey("country", "COUNTRY")
 
 
-class Mp3:
+class Mp3(MediaBase):
     """A MP3 file object"""
 
-    def __init__(self, media):
-        self.media = media
-        self.item_id = ''
+    def __init__(self, newmedia):
+        MediaBase.__init__(self)
+
+        self.description = "MPEG audio Layer III"
+        self.mime_type = 'audio/mpeg'
+        self.extension = 'mp3'
+        self.format = 'MP3'
+
+        self.media = newmedia
         self.source = self.media
-        self.options = {}
         self.bitrate_default = 192
-        self.cache_dir = os.sep + 'tmp'
-        self.keys2id3 = {
+        self.tagdata = {
             'title': 'TIT2',
             'artist': 'TPE1',
             'album': 'TALB',
@@ -70,8 +74,8 @@ class Mp3:
             'genre': 'TCON',
             'copyright': 'TCOP'
         }
-        self.mp3 = MP3(self.media, ID3=EasyID3)
-        self.info = self.mp3.info
+        self.sourceobj = MP3(self.media, ID3=EasyID3)
+        self.info = self.sourceobj.info
         self.bitrate = self.bitrate_default
         try:
             self.bitrate = int(self.info.bitrate / 1024)
@@ -92,47 +96,19 @@ class Mp3:
                 'copyright': ''
             }
 
-        self.description = self.get_description()
-        self.mime_type = self.get_mime_type()
         self.media_info = get_file_info(self.media)
         self.file_name = self.media_info[0]
         self.file_title = self.media_info[1]
         self.file_ext = self.media_info[2]
-        self.extension = self.get_file_extension()
-        self.size = os.path.getsize(media)
-        # self.args = self.get_args()
-
-    def get_format(self):
-        return 'MP3'
-
-    def get_file_extension(self):
-        return 'mp3'
-
-    def get_mime_type(self):
-        return 'audio/mpeg'
-
-    def get_description(self):
-        return "MPEG audio Layer III"
-
-    def get_file_metadata(self):
-        metadata = {}
-        for key in self.keys2id3.keys():
-            try:
-                metadata[key] = self.mp3[key][0]
-            except:
-                try:
-                    metadata[key] = self.mp3[self.keys2id3[key]][0]
-                except:
-                    metadata[key] = ''
-        return metadata
+        self.size = os.path.getsize(mediabase)
 
     def write_tags(self):
         """Write all ID3v2.4 tags by mapping dub2id3_dict dictionnary with the
             respect of mutagen classes and methods"""
 
-        self.mp3.add_tags()
-        self.mp3.tags['TIT2'] = id3.TIT2(encoding=2, text=u'text')
-        self.mp3.save()
+        self.sourceobj.add_tags()
+        self.sourceobj.tags['TIT2'] = id3.TIT2(encoding=2, text=u'text')
+        self.sourceobj.save()
 
         '''
         # media_id3 = id3.ID3(self.media)
index a970f8ae707567b5f33acaac0b4112db0ca9f1fa..c9834c8fdf9ce6362cbaefba2c9598e3fae2e801 100644 (file)
@@ -43,55 +43,45 @@ from mutagen.oggvorbis import OggVorbis
 from utils import *
 
 
-class Ogg:
+class Ogg(MediaBase):
     """An OGG file object"""
 
     def __init__(self, media):
+        MediaBase.__init__(self)
+
+        self.description = "OGG Vorbis"
+        self.mime_type = 'audio/ogg'
+        self.extension = 'ogg'
+        self.format = 'OGG'
+
         self.media = media
-        self.ogg = OggVorbis(self.media)
-        self.item_id = ''
+        self.sourceobj = OggVorbis(self.media)
         self.source = self.media
-        self.options = {}
         self.bitrate_default = '192'
-        self.cache_dir = os.sep + 'tmp'
-        self.keys2ogg = {
-            'title': 'title',
-            'artist': 'artist',
-            'album': 'album',
-            'date': 'date',
-            'comment': 'comment',
-            'genre': 'genre',
-            'copyright': 'copyright'
+
+        self.tagdata = {
+            'title': '',
+            'artist': '',
+            'album': '',
+            'date': '',
+            'comment': '',
+            'genre': '',
+            'copyright': ''
         }
-        self.info = self.ogg.info
+
+        self.info = self.sourceobj.info
         self.bitrate = int(str(self.info.bitrate)[:-3])
         self.length = datetime.timedelta(0, self.info.length)
         self.metadata = self.get_file_metadata()
-        self.description = self.get_description()
-        self.mime_type = self.get_mime_type()
         self.media_info = get_file_info(self.media)
         self.file_name = self.media_info[0]
         self.file_title = self.media_info[1]
         self.file_ext = self.media_info[2]
-        self.extension = self.get_file_extension()
         self.size = os.path.getsize(media)
-        # self.args = self.get_args()
-
-    def get_format(self):
-        return 'OGG'
-
-    def get_file_extension(self):
-        return 'ogg'
-
-    def get_mime_type(self):
-        return 'audio/ogg'
-
-    def get_description(self):
-        return 'OGG Vorbis'
 
     def get_file_info(self):
         try:
-            file_out1, file_out2 = os.popen4('ogginfo "' + self.dest + '"')
+            file_out1, file_out2 = os.popen4('ogginfo "' + self.source + '"')
             info = []
             for line in file_out2.readlines():
                 info.append(clean_word(line[:-1]))
@@ -100,31 +90,21 @@ class Ogg:
         except:
             raise IOError('ExporterError: file does not exist.')
 
-    def set_cache_dir(self, path):
-        self.cache_dir = path
-
-    def get_file_metadata(self):
-        metadata = {}
-        for key in self.keys2ogg.keys():
-            try:
-                metadata[key] = self.ogg[key][0]
-            except:
-                metadata[key] = ''
-        return metadata
-
     def decode(self):
+        if not self.item_id:
+            raise IOError('ExporterError: Required item_id parameter not set.')
         try:
-            os.system('oggdec -o "' + self.cache_dir + os.sep + self.item_id +
-                      '.wav" "' + self.source + '"')
-            return self.cache_dir + os.sep + self.item_id + '.wav'
+            p = os.path.join(self.cache_dir, (self.item_id + '.wav'))
+            os.system('oggdec -o "' + p + '" "' + self.source + '"')
+            return p
         except:
             raise IOError('ExporterError: decoder is not compatible.')
 
     def write_tags(self):
         # self.ogg.add_tags()
         for tag in self.metadata.keys():
-            self.ogg[tag] = str(self.metadata[tag])
-        self.ogg.save()
+            self.sourceobj[tag] = str(self.metadata[tag])
+        self.sourceobj.save()
 
     def get_args(self, options=None):
         """Get process options and return arguments for the encoder"""
@@ -145,8 +125,9 @@ class Ogg:
         for tag in self.metadata.keys():
             value = clean_word(self.metadata[tag])
             args.append('-c %s="%s"' % (tag, value))
-            if tag in self.dub2args_dict:
-                arg = self.dub2args_dict[tag]
-                args.append('-c %s="%s"' % (arg, value))
+            if tag in self.tagdata:
+                arg = self.tagdata[tag]
+                if arg:
+                    args.append('-c %s="%s"' % (arg, value))
 
         return args
index 389149da89192c56ba2494001a019cbf2a280f09..fc7d25e665beab8dcf13ae35b46dbcef3c262c30 100644 (file)
@@ -42,15 +42,18 @@ import datetime
 from utils import *
 
 
-class WebM(object):
+class WebM(MediaBase):
     """An WebM file object"""
 
     def __init__(self, media):
-        self.media = media
-        self.item_id = ''
-        self.source = self.media
+        MediaBase.__init__(self)
+
+        self.description = "WebM"
         self.mime_type = 'video/webm'
         self.extension = 'webm'
-        self.description = 'WebM'
+        self.format = 'WebM'
+
+        self.media = media
+        self.source = self.media
         self.metadata = {}
         self.file_name, self.file_title, self.file_ext = get_file_info(media)