Display actual song names for Audio CDs with CD-Text feature (requires libcdio)
authorAndreas Frisch <andreas.frisch@multimedia-labs.de>
Fri, 25 Jul 2008 13:09:51 +0000 (13:09 +0000)
committerAndreas Frisch <andreas.frisch@multimedia-labs.de>
Fri, 25 Jul 2008 13:09:51 +0000 (13:09 +0000)
lib/python/Components/MediaPlayer.py
lib/python/Plugins/Extensions/MediaPlayer/plugin.py
lib/service/servicemp3.cpp

index 84f7bec..50de290 100644 (file)
@@ -22,7 +22,10 @@ ForwardIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/i
 
 def PlaylistEntryComponent(serviceref, state):
        res = [ serviceref ]
 
 def PlaylistEntryComponent(serviceref, state):
        res = [ serviceref ]
-       res.append((eListboxPythonMultiContent.TYPE_TEXT,25, 0, 470, 32, 0, RT_VALIGN_CENTER, path.split(serviceref.getPath().split('/')[-1])[1]))
+       text = serviceref.getName()
+       if text is "":
+               text = path.split(serviceref.getPath().split('/')[-1])[1]
+       res.append((eListboxPythonMultiContent.TYPE_TEXT,25, 0, 470, 32, 0, RT_VALIGN_CENTER, text))
        png = None
        if state == STATE_PLAY:
                png = PlayIcon
        png = None
        if state == STATE_PLAY:
                png = PlayIcon
index 0613ed0..f87978b 100644 (file)
@@ -1,6 +1,6 @@
-from os import path as os_path, remove as os_remove, listdir as os_listdir
+from os import path as os_path, remove as os_remove, listdir as os_listdir, popen
 from time import strftime
 from time import strftime
-from enigma import eTimer, eServiceCenter, iServiceInformation
+from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation
 from Screens.Screen import Screen
 from Screens.MessageBox import MessageBox
 from Screens.InputBox import InputBox
 from Screens.Screen import Screen
 from Screens.MessageBox import MessageBox
 from Screens.InputBox import InputBox
@@ -12,7 +12,7 @@ from Components.FileList import FileList
 from Components.MediaPlayer import PlayList
 from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
 from Components.ServicePosition import ServicePositionGauge
 from Components.MediaPlayer import PlayList
 from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
 from Components.ServicePosition import ServicePositionGauge
-from Components.ServiceEventTracker import InfoBarBase
+from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications
 from ServiceReference import ServiceReference
 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications
 from ServiceReference import ServiceReference
@@ -162,6 +162,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
                self.coverArtFileName = ""
                self.isAudioCD = False
 
                self.coverArtFileName = ""
                self.isAudioCD = False
+               self.AudioCD_albuminfo = {}
 
                self.playlistIOInternal = PlaylistIOInternal()
                list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
 
                self.playlistIOInternal = PlaylistIOInternal()
                list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
@@ -170,6 +171,11 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                self.playlist.addFile(x.ref)
                        self.playlist.updateList()
 
                                self.playlist.addFile(x.ref)
                        self.playlist.updateList()
 
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evUpdatedInfo: self.__evUpdatedInfo
+                       })
+
        def doNothing(self):
                pass
 
        def doNothing(self):
                pass
 
@@ -200,6 +206,14 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
        def __onClose(self):
                self.session.nav.playService(self.oldService)
 
        def __onClose(self):
                self.session.nav.playService(self.oldService)
 
+       def __evUpdatedInfo(self):
+               currPlay = self.session.nav.getCurrentService()
+               currenttitle = currPlay.info().getInfo(iServiceInformation.sCurrentTitle)
+               totaltitles = currPlay.info().getInfo(iServiceInformation.sTotalTitles)
+               sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
+               print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
+               self.readTitleInformation()
+
        def delMPTimer(self):
                del self.rightKeyTimer
                del self.leftKeyTimer
        def delMPTimer(self):
                del self.rightKeyTimer
                del self.leftKeyTimer
@@ -207,15 +221,23 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
        def readTitleInformation(self):
                currPlay = self.session.nav.getCurrentService()
                if currPlay is not None:
        def readTitleInformation(self):
                currPlay = self.session.nav.getCurrentService()
                if currPlay is not None:
-                       stitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
-                       if stitle == "":
-                               stitle = currPlay.info().getName().split('/')[-1]
-
-                       self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
-                                                                                title = stitle,
-                                                                                album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
-                                                                                genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
-                                                                                clear = True)
+                       sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
+                       sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
+                       sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
+                       sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
+
+                       if sTitle == "":
+                               sTitle = currPlay.info().getName().split('/')[-1]
+
+                       if self.AudioCD_albuminfo:
+                               if sAlbum == "" and "TITLE" in self.AudioCD_albuminfo:
+                                       sAlbum = self.AudioCD_albuminfo["TITLE"]
+                               if sGenre == "" and "GENRE" in self.AudioCD_albuminfo:
+                                       sGenre = self.AudioCD_albuminfo["GENRE"]
+                               if sArtist == "" and "PERFORMER" in self.AudioCD_albuminfo:
+                                       sArtist = self.AudioCD_albuminfo["PERFORMER"]
+
+                       self.updateMusicInformation( artist = sArtist, title = sTitle, album = sAlbum, genre = sGenre, clear = True )
                else:
                        self.updateMusicInformation()
 
                else:
                        self.updateMusicInformation()
 
@@ -304,6 +326,13 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
        def hideAfterResume(self):
                self.hide()
 
        def hideAfterResume(self):
                self.hide()
 
+       def getIdentifier(self, ref):
+               if self.isAudioCD:
+                       return ref.getName()
+               else:
+                       text = ref.getPath()
+                       return text.split('/')[-1]
+
        # FIXME: maybe this code can be optimized 
        def updateCurrentInfo(self):
                text = ""
        # FIXME: maybe this code can be optimized 
        def updateCurrentInfo(self):
                text = ""
@@ -351,16 +380,14 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        if t is None:
                                return
                        #display current selected entry on LCD
                        if t is None:
                                return
                        #display current selected entry on LCD
-                       text = t.getPath()
-                       text = text.split('/')[-1]
+                       text = self.getIdentifier(t)
                        self.summaries.setText(text,1)
                        self["currenttext"].setText(text)
                        idx = self.playlist.getSelectionIndex()
                        idx += 1
                        if idx < len(self.playlist):
                                currref = self.playlist.getServiceRefList()[idx]
                        self.summaries.setText(text,1)
                        self["currenttext"].setText(text)
                        idx = self.playlist.getSelectionIndex()
                        idx += 1
                        if idx < len(self.playlist):
                                currref = self.playlist.getServiceRefList()[idx]
-                               text = currref.getPath()
-                               text = text.split('/')[-1]
+                               text = self.getIdentifier(currref)
                                self.summaries.setText(text,3)
                        else:
                                self.summaries.setText(" ",3)
                                self.summaries.setText(text,3)
                        else:
                                self.summaries.setText(" ",3)
@@ -368,8 +395,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        idx += 1
                        if idx < len(self.playlist):
                                currref = self.playlist.getServiceRefList()[idx]
                        idx += 1
                        if idx < len(self.playlist):
                                currref = self.playlist.getServiceRefList()[idx]
-                               text = currref.getPath()
-                               text = text.split('/')[-1]
+                               text = self.getIdentifier(currref)
                                self.summaries.setText(text,4)
                        else:
                                self.summaries.setText(" ",4)
                                self.summaries.setText(text,4)
                        else:
                                self.summaries.setText(" ",4)
@@ -628,13 +654,12 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                # display just playing musik on LCD
                                idx = self.playlist.getCurrentIndex()
                                currref = self.playlist.getServiceRefList()[idx]
                                # display just playing musik on LCD
                                idx = self.playlist.getCurrentIndex()
                                currref = self.playlist.getServiceRefList()[idx]
-                               text = currref.getPath()
-                               text = text.split('/')[-1]
+                               text = self.getIdentifier(currref)
                                text = ">"+text
                                ext = text[-3:].lower()
 
                                # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
                                text = ">"+text
                                ext = text[-3:].lower()
 
                                # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
-                               if ext not in ["mp3", "wav", "ogg"]:
+                               if ext not in ["mp3", "wav", "ogg"] and not self.isAudioCD:
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
@@ -644,8 +669,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                idx += 1
                                if idx < len(self.playlist):
                                        currref = self.playlist.getServiceRefList()[idx]
                                idx += 1
                                if idx < len(self.playlist):
                                        currref = self.playlist.getServiceRefList()[idx]
-                                       text = currref.getPath()
-                                       text = text.split('/')[-1]
+                                       text = self.getIdentifier(currref)
                                        self.summaries.setText(text,3)
                                else:
                                        self.summaries.setText(" ",3)
                                        self.summaries.setText(text,3)
                                else:
                                        self.summaries.setText(" ",3)
@@ -653,8 +677,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                idx += 1
                                if idx < len(self.playlist):
                                        currref = self.playlist.getServiceRefList()[idx]
                                idx += 1
                                if idx < len(self.playlist):
                                        currref = self.playlist.getServiceRefList()[idx]
-                                       text = currref.getPath()
-                                       text = text.split('/')[-1]
+                                       text = self.getIdentifier(currref)
                                        self.summaries.setText(text,4)
                                else:
                                        self.summaries.setText(" ",4)
                                        self.summaries.setText(text,4)
                                else:
                                        self.summaries.setText(" ",4)
@@ -663,7 +686,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                currref = self.playlist.getServiceRefList()[idx]
                                text = currref.getPath()
                                ext = text[-3:].lower()
                                currref = self.playlist.getServiceRefList()[idx]
                                text = currref.getPath()
                                ext = text[-3:].lower()
-                               if ext not in ["mp3", "wav", "ogg"]:
+                               if ext not in ["mp3", "wav", "ogg"] and not self.isAudioCD:
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
@@ -760,14 +783,29 @@ def audioCD_open(list, session, **kwargs):
        mp.isAudioCD = True
 
        mp.switchToPlayList()
        mp.isAudioCD = True
 
        mp.switchToPlayList()
+       cdtext = popen('cdtextinfo -l').read()
+       tracklist = []
+       if cdtext is not "":
+               tracklist = cdtext.splitlines()
+               cdtext = popen('cdtextinfo -a').read()
+               if cdtext is not "":
+                       albumtags = cdtext.splitlines()
+                       for tag in albumtags:
+                               tag = tag.split(':',1)
+                               mp.AudioCD_albuminfo[tag[0]] = tag[1]
+                       print mp.AudioCD_albuminfo
+       idx = 0
        for file in list:
                ref = eServiceReference(4097, 0, file.path)
        for file in list:
                ref = eServiceReference(4097, 0, file.path)
+               if idx < len(tracklist):
+                       track = tracklist[idx]
+                       ref.setName("%d - %s" % (int(track.split(':',1)[0]), track.split(':')[1]))
+                       idx += 1
                mp.playlist.addFile(ref)
 
                mp.playlist.addFile(ref)
 
-       # TODO: rather play first than last file?
-       mp.playServiceRefEntry(ref)
-       mp.playlist.updateList()
        mp.changeEntry(0)
        mp.changeEntry(0)
+       mp.playlist.updateList()
+       mp.switchToPlayList()
 
 def filescan(**kwargs):
        from Components.Scanner import Scanner, ScanPath
 
 def filescan(**kwargs):
        from Components.Scanner import Scanner, ScanPath
index c004d03..fb76728 100644 (file)
@@ -140,8 +140,9 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp
        int is_mp3 = !strcasecmp(ext, ".mp3"); /* force mp3 instead of decodebin */
        int is_video = is_mpeg_ps || is_mpeg_ts || is_matroska || is_avi;
        int is_streaming = !strncmp(filename, "http://", 7);
        int is_mp3 = !strcasecmp(ext, ".mp3"); /* force mp3 instead of decodebin */
        int is_video = is_mpeg_ps || is_mpeg_ts || is_matroska || is_avi;
        int is_streaming = !strncmp(filename, "http://", 7);
+       int is_AudioCD = !(strncmp(filename, "/autofs/hda/track-", 18) || strcasecmp(ext, ".wav"));
        
        
-       eDebug("filename: %s, is_mpeg_ps: %d, is_mpeg_ts: %d, is_video: %d, is_streaming: %d, is_mp3: %d, is_matroska: %d, is_avi: %d", filename, is_mpeg_ps, is_mpeg_ts, is_video, is_streaming, is_mp3, is_matroska, is_avi);
+       eDebug("filename: %s, is_mpeg_ps: %d, is_mpeg_ts: %d, is_video: %d, is_streaming: %d, is_mp3: %d, is_matroska: %d, is_avi: %d, is_AudioCD: %d", filename, is_mpeg_ps, is_mpeg_ts, is_video, is_streaming, is_mp3, is_matroska, is_avi, is_AudioCD);
        
        int is_audio = !is_video;
        
        
        int is_audio = !is_video;
        
@@ -151,9 +152,17 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp
        if (!m_gst_pipeline)
                eWarning("failed to create pipeline");
 
        if (!m_gst_pipeline)
                eWarning("failed to create pipeline");
 
-       if (!is_streaming)
+       if (is_AudioCD)
+       {
+               source = gst_element_factory_make ("cdiocddasrc", "cda-source");
+               if (source)
+                       g_object_set (G_OBJECT (source), "device", "/dev/cdroms/cdrom0", NULL);
+               else
+                       is_AudioCD = 0;
+       }
+       if ( !is_streaming && !is_AudioCD )
                source = gst_element_factory_make ("filesrc", "file-source");
                source = gst_element_factory_make ("filesrc", "file-source");
-       else
+       else if ( is_streaming ) 
        {
                source = gst_element_factory_make ("neonhttpsrc", "http-source");
                if (source)
        {
                source = gst_element_factory_make ("neonhttpsrc", "http-source");
                if (source)
@@ -162,9 +171,16 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp
 
        if (!source)
                eWarning("failed to create %s", is_streaming ? "neonhttpsrc" : "filesrc");
 
        if (!source)
                eWarning("failed to create %s", is_streaming ? "neonhttpsrc" : "filesrc");
-       else
                                /* configure source */
                                /* configure source */
+       else if (!is_AudioCD)
                g_object_set (G_OBJECT (source), "location", filename, NULL);
                g_object_set (G_OBJECT (source), "location", filename, NULL);
+       else
+       { 
+               int track = atoi(filename+18);
+               eDebug("play audio CD track #%i",track);
+               if (track > 0)
+                       g_object_set (G_OBJECT (source), "track", track, NULL);
+       }
 
        if (is_audio)
        {
 
        if (is_audio)
        {
@@ -249,7 +265,14 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp
        {
                gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_pipeline)), gstBusSyncHandler, this);
 
        {
                gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_pipeline)), gstBusSyncHandler, this);
 
-               if (is_audio)
+               if (is_AudioCD)
+               {
+                       queue_audio = gst_element_factory_make("queue", "queue_audio");
+                       g_object_set (G_OBJECT (sink), "preroll-queue-len", 80, NULL);
+                       gst_bin_add_many (GST_BIN (m_gst_pipeline), source, queue_audio, conv, sink, NULL);
+                       gst_element_link_many(source, queue_audio, conv, sink, NULL);
+               }
+               else if (is_audio)
                {
                        queue_audio = gst_element_factory_make("queue", "queue_audio");
 
                {
                        queue_audio = gst_element_factory_make("queue", "queue_audio");