Changeset 462

Show
Ignore:
Timestamp:
09/22/06 22:42:22 (2 years ago)
Author:
nicfit
Message:

Spiffy playlists

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Makefile.in

    r425 r462  
    187187        mkdir -p www/mesk/releases 
    188188        mkdir www/mesk/releases/gentoo 
    189         # TODO 
     189        # FIXME 
    190190        #cp README.html ChangeLog COPYING NEWS TODO THANKS www/mesk 
    191191        #cd www/mesk && ln -s README.html index.html 
    192192        cp ${DIST_GZ} www/mesk/releases 
    193193        cp etc/mesk-${EBUILD_VERSION}.ebuild www/mesk/releases/gentoo 
    194         tar czvf ${DIST_WWW} www 
     194        cd www && tar czvf ${DIST_WWW} mesk 
    195195        rm -rf www 
    196  
    197 push-www: 
    198         scp ${DIST_WWW} nicfit:. 
    199         ssh nicfit 'tar xzvf ${DIST_WWW}' 
    200196 
    201197sloccount: 
  • trunk/src/audio_control.py

    r419 r462  
    571571            src.meta_data.year = unicode(str(taglist['date'].year), 'utf-8') 
    572572        if 'track-number' in keys: 
    573             src.meta_data.track_num = taglist['track-number'] 
     573            src.meta_data.track_num = int(taglist['track-number']) 
    574574        if 'track-count' in keys: 
    575             src.meta_data.track_total = taglist['track-count'] 
     575            src.meta_data.track_total = int(taglist['track-count']) 
    576576        if 'duration' in keys: 
    577             src.meta_data.time_secs = taglist['duration'] / gst.SECOND 
     577            src.meta_data.time_secs = int(taglist['duration']) / gst.SECOND 
    578578        self.emit('tag-update', src) 
    579579 
  • trunk/src/mesk/audio/__init__.py

    r453 r462  
    7676    '''Thrown when a audio format is not supported''' 
    7777 
    78 def load(uri): 
     78def load(uri, meta_data=None): 
    7979    '''Given a URI, attempt to load an AudioSource.  If this cannot be done, 
    8080    a UnsupportedFormat exception, or other related error is thrown.''' 
     
    9292    else: 
    9393        factory = supported_mimetypes[mt] 
    94         src = factory(uri
     94        src = factory(uri, meta_data
    9595    return src 
  • trunk/src/mesk/audio/mp3.py

    r453 r462  
    5252class Mp3AudioSource(AudioSource): 
    5353 
    54     def __init__(self, uri): 
    55         AudioSource.__init__(self, uri
     54    def __init__(self, uri, meta_data=None): 
     55        AudioSource.__init__(self, uri, meta_data
    5656 
    57         if self.uri.scheme == 'file': 
    58             self.meta_data = Mp3MetaData(self.uri) 
    59         elif self.uri.scheme in ['http', 'https']: 
    60             self.meta_data = Mp3MetaData() 
    61         else: 
    62             raise UnsupportedScheme('\'%s\' URI scheme is not supported' % \ 
    63                                     uri.scheme) 
     57        if not self.meta_data: 
     58            if self.uri.scheme == 'file': 
     59                self.meta_data = Mp3MetaData(self.uri) 
     60            elif self.uri.scheme in ['http', 'https']: 
     61                self.meta_data = Mp3MetaData() 
     62            else: 
     63                raise UnsupportedScheme('\'%s\' URI scheme is not supported' % \ 
     64                                        uri.scheme) 
    6465 
    6566        # Use URI if we don't have a title 
  • trunk/src/mesk/audio/oggvorbis.py

    r453 r462  
    3535from ogg.vorbis import VorbisFile, VorbisError 
    3636class OggAudioSource(AudioSource): 
    37     def __init__(self, uri): 
    38         AudioSource.__init__(self, uri) 
    39         if self.uri.scheme == 'file': 
    40             self.meta_data = OggMetaData(self.uri) 
    41         elif self.uri.scheme in ['http', 'https']: 
    42             self.meta_data = OggMetaData() 
    43         else: 
    44             raise UnsupportedScheme('\'%s\' URI scheme is not supported' % \ 
    45                                     uri.scheme) 
     37    def __init__(self, uri, meta_data=None): 
     38        AudioSource.__init__(self, uri, meta_data) 
     39 
     40        if not self.meta_data: 
     41            if self.uri.scheme == 'file': 
     42                self.meta_data = OggMetaData(self.uri) 
     43            elif self.uri.scheme in ['http', 'https']: 
     44                self.meta_data = OggMetaData() 
     45            else: 
     46                raise UnsupportedScheme('\'%s\' URI scheme is not supported' % \ 
     47                                        uri.scheme) 
    4648 
    4749        # Use URI if we don't have a title 
  • trunk/src/mesk/audio/source.py

    r391 r462  
    4444 
    4545class AudioSource: 
    46     def __init__(self, uri): 
     46    def __init__(self, uri, meta_data): 
    4747        self.uri = mesk.uri.make_uri(uri) 
    48         self.meta_data = AudioMetaData() 
     48        self.meta_data = meta_data 
    4949 
    5050    def get_native_tag(self): 
  • trunk/src/mesk/playlist/__init__.py

    r455 r462  
    4545        continue 
    4646 
    47 def load(pl_uri): 
     47def load(pl_uri, name=None): 
    4848    '''Load a playlist, currently only m3u is supported''' 
    4949 
    50     pl = Playlist(
     50    pl = Playlist(name
    5151    pl_path = mesk.uri.unescape(pl_uri.path) 
    5252    pl_ext = os.path.splitext(pl_path)[1] 
     
    8080 
    8181class Playlist: 
    82     def __init__(self, name = None): 
     82    def __init__(self, name=None): 
    8383        self.name = name 
    8484        # AudioSource objects managed my this playlist and the index of the 
  • trunk/src/mesk/playlist/xspf.py

    r455 r462  
    1818#  $Id$ 
    1919################################################################################ 
     20import mesk.log, mesk.audio 
    2021 
    2122NAME = 'Spiff' 
     
    2627mimetypes.add_type(MIME_TYPES[0], EXTENSIONS[0]) 
    2728 
     29XSPF_NS = 'http://xspf.org/ns/0/' 
     30META_YEAR = 'http://mesk.nicfit.net/playlist/year' 
     31META_CURRENT = 'http://mesk.nicfit.net/playlist/current' 
     32META_SHUFFLE = 'http://mesk.nicfit.net/playlist/shuffle' 
     33META_REPEAT = 'http://mesk.nicfit.net/playlist/repeat' 
     34 
    2835def load(pl_data, pl): 
    29     pass 
     36    import xml.dom, xml.dom.minidom 
     37    pl_dom = xml.dom.minidom.parse(pl_data) 
     38    pl_elem = pl_dom.getElementsByTagNameNS(XSPF_NS, 'playlist')[0] 
     39 
     40    # Playlist state 
     41    pl.set_curr_index(-1) 
     42    pl.set_shuffle(False) 
     43    pl.set_repeat(False) 
     44    for meta_elem in pl_elem.getElementsByTagName('meta'): 
     45        if meta_elem.getAttribute('rel') == META_CURRENT: 
     46            try: 
     47                pl.set_curr_index(int(_get_elem_text(meta_elem))) 
     48            except IndexError: 
     49                pass 
     50        elif meta_elem.getAttribute('rel') == META_SHUFFLE: 
     51            pl.set_shuffle(True) 
     52        elif meta_elem.getAttribute('rel') == META_REPEAT: 
     53            pl.set_repeat(True) 
     54 
     55    list_elem = pl_elem.getElementsByTagName('trackList')[0] 
     56    for track_elem in list_elem.getElementsByTagName('track'): 
     57        uri = track_elem.getElementsByTagName('location') 
     58        if not uri: 
     59            mesk.log.warn('<location/> URI required in XSPF playlist tracks') 
     60            continue 
     61 
     62        meta_data = mesk.audio.source.AudioMetaData() 
     63        for elem in track_elem.childNodes: 
     64            if elem.nodeType == elem.ELEMENT_NODE: 
     65                if elem.tagName == 'title': 
     66                    meta_data.title = _get_elem_text(elem) 
     67                elif elem.tagName == 'creator': 
     68                    meta_data.artist = _get_elem_text(elem) 
     69                elif elem.tagName == 'album': 
     70                    meta_data.album = _get_elem_text(elem) 
     71                elif elem.tagName == 'duration': 
     72                    meta_data.time_secs = int(_get_elem_text(elem)) / 1000 
     73                elif elem.tagName == 'trackNum': 
     74                    meta_data.trac_num = int(_get_elem_text(elem)) 
     75                elif (elem.tagName == 'meta' and 
     76                      elem.getAttribute('rel') == META_YEAR): 
     77                    meta_data.year = _get_elem_text(elem) 
     78 
     79        # FIXME: 
     80        #meta_data = None 
     81 
     82        try: 
     83            src = mesk.audio.load(_get_elem_text(uri[0]), meta_data) 
     84        except Exception, ex: 
     85            mesk.log.warn(str(ex)) 
     86        else: 
     87            pl.append(src) 
    3088 
    3189def save(pl_path, pl): 
     90    import xml.sax.saxutils as saxutils 
     91    def pad(n): 
     92        return ' ' * n 
     93 
    3294    fp = file(pl_path, 'w') 
    3395    # We are only serializing pl, so building a DOM would just waste time. 
     96    fp.write('<?xml version="1.0" encoding="UTF-8"?>\n') 
    3497    fp.write('<playlist xmlns="http://xspf.org/ns/0/" ' 
    3598             'xmlns:mesk="http://mesk.nicfit.net" version="1">\n') 
    3699    indent = 2 
    37     fp.write((' ' * indent) + '<title>%s</title>\n' % 'FIXME') 
    38     fp.write((' ' * indent) + '<creator>%s</creator>\n' % 'Mesk') 
    39     fp.write((' ' * indent) + '<annotation>%s</annotation>\n' % 'Mesk Playlist') 
    40     fp.write((' ' * indent) + '<trackList>\n') 
     100    fp.write(pad(indent) + '<title>%s</title>\n' % saxutils.escape(pl.name)) 
     101    fp.write(pad(indent) + 
     102             '<info>Made with Mesk-http://mesk.nicfit.net/</info>\n') 
     103    fp.write(pad(indent) + '<meta rel="%s">%d</meta>\n' % 
     104                           (META_CURRENT, pl.get_curr_index())) 
     105    if pl.is_shuffled(): 
     106        fp.write(pad(indent) + '<meta rel="%s">%d</meta>\n' % 
     107                               (META_SHUFFLE, int(pl.is_shuffled()))) 
     108    if pl.is_repeating(): 
     109        fp.write(pad(indent) + '<meta rel="%s">%d</meta>\n' % 
     110                               (META_REPEAT, int(pl.is_repeating()))) 
     111 
     112    fp.write(pad(indent) + '<trackList>\n') 
    41113    indent += 2 
    42114    for s in pl: 
    43         fp.write((' ' * indent) + '<track>\n') 
    44         indent +=2 
    45         fp.write((' ' * indent) + '<location>%s</location>\n' % str(s.uri)) 
    46         indent -=2 
    47         fp.write((' ' * indent) + '</track>\n') 
     115        fp.write(pad(indent) + '<track>\n') 
     116        indent += 2 
     117 
     118        fp.write(pad(indent) + '<location>%s</location>\n' % 
     119                               saxutils.escape(str(s.uri))) 
     120        if s.meta_data.time_secs: 
     121            fp.write(pad(indent) + '<duration>%d</duration>\n' % 
     122                                   (s.meta_data.time_secs * 1000)) 
     123        if s.meta_data.title: 
     124            t = saxutils.escape(s.meta_data.title.encode('utf-8')) 
     125            fp.write(pad(indent) + '<title>%s</title>\n' % t) 
     126        if s.meta_data.artist: 
     127            a = saxutils.escape(s.meta_data.artist.encode('utf-8')) 
     128            fp.write(pad(indent) + '<creator>%s</creator>\n' % a) 
     129        if s.meta_data.album: 
     130            a = saxutils.escape(s.meta_data.album.encode('utf-8')) 
     131            fp.write(pad(indent) + '<album>%s</album>\n' % a) 
     132        if s.meta_data.track_num is not None: 
     133            fp.write(pad(indent) + 
     134                     '<trackNum>%d</trackNum>\n' % s.meta_data.track_num) 
     135        if s.meta_data.year is not None: 
     136            fp.write(pad(indent) + '<meta rel="%s">%d</meta>\n' % 
     137                                   (META_YEAR, int(s.meta_data.year))) 
     138 
     139        indent -= 2 
     140        fp.write(pad(indent) + '</track>\n') 
    48141 
    49142    indent -= 2 
    50     fp.write((' ' * indent) + '</trackList>\n') 
     143    fp.write(pad(indent) + '</trackList>\n') 
    51144    fp.write('</playlist>\n') 
    52145    fp.close() 
    53146 
     147 
     148def _get_elem_text(elem): 
     149    nodelist = elem.childNodes 
     150    txt = u'' 
     151    for node in nodelist: 
     152        if node.nodeType == node.TEXT_NODE: 
     153            txt = txt + node.data 
     154    return txt 
  • trunk/src/playlist_control.py

    r456 r462  
    181181 
    182182        # Load playlist 
    183         pl = mesk.playlist.load(self._pl_config.uri) 
     183        # FIXME 
     184        import time 
     185        t1 = time.time() 
     186        pl = mesk.playlist.load(self._pl_config.uri, name=self._pl_config.name) 
     187        t2 = time.time() 
     188        print "Playlist load time: %fs" % (t2 - t1) 
    184189        pl.set_shuffle(self._pl_config.shuffle) 
    185190        pl.set_repeat(self._pl_config.repeat) 
     
    217222        def _save_cb(): 
    218223            self._pl_config.update(self._playlist) 
    219             mesk.playlist.m3u.save(mesk.uri.unescape(self._pl_config.uri.path), 
    220                                    self._playlist) 
     224            mesk.playlist.xspf.save(mesk.uri.unescape(self._pl_config.uri.path), 
     225                                    self._playlist) 
    221226            # FIXME 
    222             mesk.playlist.xspf.save('../pl.xspf', self._playlist) 
     227            #mesk.playlist.xspf.save('../pl.xspf', self._playlist) 
    223228 
    224229            self._debug_show_playlist() 
     
    499504        # Update state 
    500505        self.name = new_name 
     506        self._playlist.name = new_name 
    501507        self._pl_config.set_name(new_name) 
    502508        self._update_tab_label()