user correct playlist parser from dict
[enigma2.git] / lib / python / Plugins / Extensions / MediaPlayer / plugin.py
index 22fe7c5d6a731f39b0c28ee45c5b9e06955c59a3..ed1a88747925e24d2dd16522e729c0fbbafb7c78 100644 (file)
@@ -1,4 +1,4 @@
-from os import path as os_path, remove as os_remove, listdir as os_listdir, popen
+from os import path as os_path, remove as os_remove, listdir as os_listdir
 from time import strftime
 from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation
 from Screens.Screen import Screen
 from time import strftime
 from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation
 from Screens.Screen import Screen
@@ -14,10 +14,12 @@ from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCO
 from Components.ServicePosition import ServicePositionGauge
 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
 from Components.ServicePosition import ServicePositionGauge
 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
-from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications
+from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport
 from ServiceReference import ServiceReference
 from Screens.ChoiceBox import ChoiceBox
 from Screens.HelpMenu import HelpableScreen
 from ServiceReference import ServiceReference
 from Screens.ChoiceBox import ChoiceBox
 from Screens.HelpMenu import HelpableScreen
+from Components.Harddisk import harddiskmanager
+from Tools.Directories import fileExists, pathExists
 import random
 
 class MyPlayList(PlayList):
 import random
 
 class MyPlayList(PlayList):
@@ -42,7 +44,7 @@ class MediaPixmap(Pixmap):
                        self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
                return Pixmap.applySkin(self, desktop, screen)
 
                        self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
                return Pixmap.applySkin(self, desktop, screen)
 
-class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, HelpableScreen):
+class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen):
        ALLOW_SUSPEND = True
        ENABLE_RESUME_SUPPORT = True
 
        ALLOW_SUSPEND = True
        ENABLE_RESUME_SUPPORT = True
 
@@ -52,6 +54,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
                InfoBarNotifications.__init__(self)
                InfoBarBase.__init__(self)
                InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
                InfoBarNotifications.__init__(self)
                InfoBarBase.__init__(self)
+               InfoBarSubtitleSupport.__init__(self)
                HelpableScreen.__init__(self)
                self.summary = None
                self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
                HelpableScreen.__init__(self)
                self.summary = None
                self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
@@ -63,7 +66,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self.addPlaylistParser(PlaylistIOInternal, "e2pls")
 
                # 'None' is magic to start at the list of mountpoints
                self.addPlaylistParser(PlaylistIOInternal, "e2pls")
 
                # 'None' is magic to start at the list of mountpoints
-               self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
+               self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
                self["filelist"] = self.filelist
 
                self.playlist = MyPlayList()
                self["filelist"] = self.filelist
 
                self.playlist = MyPlayList()
@@ -123,6 +126,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
                                "shift_stop": (self.clear_playlist, _("clear playlist")),
                                "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
                                "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
                                "shift_stop": (self.clear_playlist, _("clear playlist")),
                                "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
+                               "subtitles": (self.subtitleSelection, _("Subtitle selection")),
                        }, -2)
 
                self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        }, -2)
 
                self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
@@ -165,7 +169,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self.coverArtFileName = ""
                self.isAudioCD = False
                self.AudioCD_albuminfo = {}
                self.coverArtFileName = ""
                self.isAudioCD = False
                self.AudioCD_albuminfo = {}
-               
+               self.savePlaylistOnExit = True
+
                self.playlistIOInternal = PlaylistIOInternal()
                list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
                if list:
                self.playlistIOInternal = PlaylistIOInternal()
                list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
                if list:
@@ -175,7 +180,9 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
-                               iPlayableService.evUpdatedInfo: self.__evUpdatedInfo
+                               iPlayableService.evUpdatedInfo: self.__evUpdatedInfo,
+                               iPlayableService.evUser+11: self.__evDecodeError,
+                               iPlayableService.evUser+12: self.__evPluginError
                        })
 
        def doNothing(self):
                        })
 
        def doNothing(self):
@@ -192,7 +199,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        self.playlistIOInternal.clear()
                        for x in self.playlist.list:
                                self.playlistIOInternal.addService(ServiceReference(x[0]))
                        self.playlistIOInternal.clear()
                        for x in self.playlist.list:
                                self.playlistIOInternal.addService(ServiceReference(x[0]))
-                       if not self.isAudioCD:
+                       if self.savePlaylistOnExit:
                                self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
                        self.close()
 
                                self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
                        self.close()
 
@@ -216,6 +223,18 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
                self.readTitleInformation()
 
                print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
                self.readTitleInformation()
 
+       def __evDecodeError(self):
+               currPlay = self.session.nav.getCurrentService()
+               sVideoType = currPlay.info().getInfoString(iServiceInformation.sVideoType)
+               print "[__evDecodeError] video-codec %s can't be decoded by hardware" % (sVideoType)
+               self.session.open(MessageBox, _("This Dreambox can't decode %s video streams!") % sVideoType, type = MessageBox.TYPE_INFO,timeout = 20 )
+
+       def __evPluginError(self):
+               currPlay = self.session.nav.getCurrentService()
+               message = currPlay.info().getInfoString(iServiceInformation.sUser+12)
+               print "[__evPluginError]" , message
+               self.session.open(MessageBox, message, type = MessageBox.TYPE_INFO,timeout = 20 )
+
        def delMPTimer(self):
                del self.rightKeyTimer
                del self.leftKeyTimer
        def delMPTimer(self):
                del self.rightKeyTimer
                del self.leftKeyTimer
@@ -227,7 +246,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
                        sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
                        sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
                        sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
                        sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
                        sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
-                       sYear = ""
+                       sYear = currPlay.info().getInfoString(iServiceInformation.sTimeCreate)
 
                        if sTitle == "":
                                if not self.isAudioCD:
 
                        if sTitle == "":
                                if not self.isAudioCD:
@@ -266,7 +285,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        path = path[:-1]
                pngname = path + "folder.png"
                
                        path = path[:-1]
                pngname = path + "folder.png"
                
-               if not os_path.exists(pngname):
+               if not fileExists(pngname):
                        pngname = self["coverArt"].default_pixmap
                if self.coverArtFileName != pngname:
                        self.coverArtFileName = pngname
                        pngname = self["coverArt"].default_pixmap
                if self.coverArtFileName != pngname:
                        self.coverArtFileName = pngname
@@ -440,6 +459,9 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                menu.append((_("load playlist"), "loadplaylist"));
                menu.append((_("delete saved playlist"), "deleteplaylist"));
                menu.append((_("repeat playlist"), "repeat"));
                menu.append((_("load playlist"), "loadplaylist"));
                menu.append((_("delete saved playlist"), "deleteplaylist"));
                menu.append((_("repeat playlist"), "repeat"));
+               drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
+               if pathExists(drivepath):
+                       menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
@@ -482,6 +504,34 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        else:
                                self.repeat = True
                                self["repeat"].setPixmapNum(1)
                        else:
                                self.repeat = True
                                self["repeat"].setPixmapNum(1)
+               elif choice[1] == "audiocd":
+                       from Components.Scanner import scanDevice
+                       drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
+                       self.cdAudioTrackFiles = []
+                       res = scanDevice(drivepath)
+                       list = [ (r.description, r, res[r], self.session) for r in res ]
+                       if list:
+                               (desc, scanner, files, session) = list[0]
+                               for file in files:
+                                       if file.mimetype == "audio/x-cda":
+                                               self.cdAudioTrackFiles.append(file.path)
+                       self.playAudioCD()
+
+       def playAudioCD(self):
+               from enigma import eServiceReference
+               from Plugins.Extensions.CDInfo.plugin import Query
+
+               if len(self.cdAudioTrackFiles):
+                       self.playlist.clear()
+                       self.savePlaylistOnExit = False
+                       self.isAudioCD = True
+                       for file in self.cdAudioTrackFiles:
+                               ref = eServiceReference(4097, 0, file)
+                               self.playlist.addFile(ref)
+                       cdinfo = Query(self)
+                       cdinfo.scan()
+                       self.changeEntry(0)
+                       self.switchToPlayList()
 
        def showEventInformation(self):
                from Screens.EventView import EventViewSimple
 
        def showEventInformation(self):
                from Screens.EventView import EventViewSimple
@@ -542,12 +592,13 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
        def PlaylistSelected(self,path):
                if path is not None:
                        self.clear_playlist()
        def PlaylistSelected(self,path):
                if path is not None:
                        self.clear_playlist()
-                       self.playlistIOInternal = PlaylistIOInternal()
-                       list = self.playlistIOInternal.open(path[1])
-                       if list:
+                       extension = path[0].rsplit('.',1)[-1]
+                       if self.playlistparsers.has_key(extension):
+                               playlist = self.playlistparsers[extension]()
+                               list = playlist.open(path[1])
                                for x in list:
                                        self.playlist.addFile(x.ref)
                                for x in list:
                                        self.playlist.addFile(x.ref)
-                               self.playlist.updateList()
+                       self.playlist.updateList()
 
        def delete_saved_playlist(self):
                listpath = []
 
        def delete_saved_playlist(self):
                listpath = []
@@ -674,10 +725,10 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                currref = self.playlist.getServiceRefList()[idx]
                                text = self.getIdentifier(currref)
                                text = ">"+text
                                currref = self.playlist.getServiceRefList()[idx]
                                text = self.getIdentifier(currref)
                                text = ">"+text
-                               ext = text[-3:].lower()
+                               ext = text[-4:].lower()
 
                                # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
 
                                # 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"] and not self.isAudioCD:
+                               if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD:
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
@@ -703,8 +754,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                                idx = self.playlist.getCurrentIndex()
                                currref = self.playlist.getServiceRefList()[idx]
                                text = currref.getPath()
                                idx = self.playlist.getCurrentIndex()
                                currref = self.playlist.getServiceRefList()[idx]
                                text = currref.getPath()
-                               ext = text[-3:].lower()
-                               if ext not in ["mp3", "wav", "ogg"] and not self.isAudioCD:
+                               ext = text[-4:].lower()
+                               if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD:
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
                                        self.hide()
                                else:
                                        needsInfoUpdate = True
@@ -730,7 +781,10 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
        def pauseEntry(self):
                self.pauseService()
 
        def pauseEntry(self):
                self.pauseService()
-               self.show()
+               if self.seekstate == self.SEEK_STATE_PAUSE:
+                       self.show()
+               else:
+                       self.hide()
 
        def stopEntry(self):
                self.playlist.stopFile()
 
        def stopEntry(self):
                self.playlist.stopFile()
@@ -740,6 +794,10 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
        def unPauseService(self):
                self.setSeekState(self.SEEK_STATE_PLAY)
 
        def unPauseService(self):
                self.setSeekState(self.SEEK_STATE_PLAY)
+               
+       def subtitleSelection(self):
+               from Screens.Subtitles import Subtitles
+               self.session.open(Subtitles)            
 
 class MediaPlayerLCDScreen(Screen):
        skin = """
 
 class MediaPlayerLCDScreen(Screen):
        skin = """
@@ -781,38 +839,33 @@ def filescan_open(list, session, **kwargs):
        from enigma import eServiceReference
 
        mp = session.open(MediaPlayer)
        from enigma import eServiceReference
 
        mp = session.open(MediaPlayer)
+       mp.playlist.clear()
+       mp.savePlaylistOnExit = False
 
 
-       mp.switchToPlayList()
        for file in list:
        for file in list:
-               ref = eServiceReference(4097, 0, file.path)
+               if file.mimetype == "video/MP2T":
+                       stype = 1
+               else:
+                       stype = 4097
+               ref = eServiceReference(stype, 0, file.path)
                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.switchToPlayList()
 
 def audioCD_open(list, session, **kwargs):
        from enigma import eServiceReference
 
        mp = session.open(MediaPlayer)
 
 def audioCD_open(list, session, **kwargs):
        from enigma import eServiceReference
 
        mp = session.open(MediaPlayer)
-
-       mp.playlist.clear()
-       mp.isAudioCD = True
-
+       mp.cdAudioTrackFiles = []
        for file in list:
        for file in list:
-               ref = eServiceReference(4097, 0, file.path)
-               mp.playlist.addFile(ref)
-       from Plugins.Extensions.CDInfo.plugin import Query
-       cdinfo = Query(mp)
-       cdinfo.scan()
-
-       mp.changeEntry(0)
-       mp.switchToPlayList()
+               mp.cdAudioTrackFiles.append(file.path)
+       mp.playAudioCD()
 
 def filescan(**kwargs):
        from Components.Scanner import Scanner, ScanPath
        mediatypes = [
 
 def filescan(**kwargs):
        from Components.Scanner import Scanner, ScanPath
        mediatypes = [
-               Scanner(mimetypes = ["video/mpeg"],
+               Scanner(mimetypes = ["video/mpeg", "video/MP2T", "video/x-msvideo"],
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),
@@ -821,7 +874,17 @@ def filescan(**kwargs):
                        description = "View Movies...",
                        openfnc = filescan_open,
                ),
                        description = "View Movies...",
                        openfnc = filescan_open,
                ),
-               Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg"],
+               Scanner(mimetypes = ["video/x-vcd"],
+                       paths_to_scan =
+                               [
+                                       ScanPath(path = "mpegav", with_subdirs = False),
+                                       ScanPath(path = "MPEGAV", with_subdirs = False),
+                               ],
+                       name = "Video CD",
+                       description = "View Video CD...",
+                       openfnc = filescan_open,
+               ),
+               Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg", "audio/x-flac"],
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),
@@ -832,7 +895,8 @@ def filescan(**kwargs):
                )]
        try:
                from Plugins.Extensions.CDInfo.plugin import Query
                )]
        try:
                from Plugins.Extensions.CDInfo.plugin import Query
-               mediatypes.insert(0,Scanner(mimetypes = ["audio/x-cda", "audio/x-wav"],
+               mediatypes.append(
+               Scanner(mimetypes = ["audio/x-cda"],
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),
                        paths_to_scan =
                                [
                                        ScanPath(path = "", with_subdirs = False),