X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/567cf170322df2e897871787255c50bd522e6313..1c06b6ba897cb3d36b69dc66a69df35f0e16f171:/lib/python/Plugins/Extensions/MediaPlayer/plugin.py diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index 3207c09c..42800b5c 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -1,23 +1,26 @@ from os import path as os_path, remove as os_remove, listdir as os_listdir from time import strftime -from enigma import eTimer, iPlayableService, eServiceCenter, iServiceInformation +from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, ePicLoad +from ServiceReference import ServiceReference from Screens.Screen import Screen +from Screens.HelpMenu import HelpableScreen from Screens.MessageBox import MessageBox from Screens.InputBox import InputBox +from Screens.ChoiceBox import ChoiceBox +from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport from Components.ActionMap import NumberActionMap, HelpableActionMap from Components.Label import Label -from Components.Pixmap import Pixmap -from Components.Label import Label +from Components.Pixmap import Pixmap,MultiPixmap 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.ServiceEventTracker import ServiceEventTracker +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 Screens.ChoiceBox import ChoiceBox -from Screens.HelpMenu import HelpableScreen +from Components.AVSwitch import AVSwitch +from Components.Harddisk import harddiskmanager +from Components.config import config +from Tools.Directories import fileExists, pathExists, resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE +from settings import MediaPlayerSettings import random class MyPlayList(PlayList): @@ -30,7 +33,61 @@ class MyPlayList(PlayList): self.currPlaying = -1 self.oldCurrPlaying = -1 -class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, HelpableScreen): +class MediaPixmap(Pixmap): + def __init__(self): + Pixmap.__init__(self) + self.coverArtFileName = "" + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.paintCoverArtPixmapCB) + self.coverFileNames = ["folder.png", "folder.jpg"] + + def applySkin(self, desktop, screen): + from Tools.LoadPixmap import LoadPixmap + noCoverFile = None + if self.skinAttributes is not None: + for (attrib, value) in self.skinAttributes: + if attrib == "pixmap": + noCoverFile = value + break + if noCoverFile is None: + noCoverFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png") + self.noCoverPixmap = LoadPixmap(noCoverFile) + return Pixmap.applySkin(self, desktop, screen) + + def onShow(self): + Pixmap.onShow(self) + sc = AVSwitch().getFramebufferScale() + #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB) + self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], False, 1, "#00000000")) + + def paintCoverArtPixmapCB(self, picInfo=None): + ptr = self.picload.getData() + if ptr != None: + self.instance.setPixmap(ptr.__deref__()) + + def updateCoverArt(self, path): + while not path.endswith("/"): + path = path[:-1] + new_coverArtFileName = None + for filename in self.coverFileNames: + if fileExists(path + filename): + new_coverArtFileName = path + filename + if self.coverArtFileName != new_coverArtFileName: + self.coverArtFileName = new_coverArtFileName + if new_coverArtFileName: + self.picload.startDecode(self.coverArtFileName) + else: + self.showDefaultCover() + + def showDefaultCover(self): + self.instance.setPixmap(self.noCoverPixmap) + + def embeddedCoverArt(self): + print "[embeddedCoverArt] found" + self.coverArtFileName = "/tmp/.id3coverart" + self.picload.startDecode(self.coverArtFileName) + +class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen): ALLOW_SUSPEND = True ENABLE_RESUME_SUPPORT = True @@ -39,6 +96,8 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup InfoBarAudioSelection.__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() @@ -50,11 +109,11 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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) + defaultDir = config.mediaplayer.defaultDir.getValue() + self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() - #self.playlist = PlayList() self.is_closing = False self.delname = "" self["playlist"] = self.playlist @@ -63,20 +122,24 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self["currenttext"] = Label("") - self["artisttext"] = Label(_("Artist:")) + self["artisttext"] = Label(_("Artist")+':') self["artist"] = Label("") - self["titletext"] = Label(_("Title:")) + self["titletext"] = Label(_("Title")+':') self["title"] = Label("") - self["albumtext"] = Label(_("Album:")) + self["albumtext"] = Label(_("Album")+':') self["album"] = Label("") - self["yeartext"] = Label(_("Year:")) + self["yeartext"] = Label(_("Year")+':') self["year"] = Label("") - self["genretext"] = Label(_("Genre:")) + self["genretext"] = Label(_("Genre")+':') self["genre"] = Label("") - self["coverArt"] = Pixmap() + self["coverArt"] = MediaPixmap() + self["repeat"] = MultiPixmap() self.seek_target = None + from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier + hotplugNotifier.append(self.hotplugCB) + class MoviePlayerActionMap(NumberActionMap): def __init__(self, player, contexts = [ ], actions = { }, prio=0): NumberActionMap.__init__(self, contexts, actions, prio) @@ -86,7 +149,6 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self.player.show() return NumberActionMap.action(self, contexts, action) - self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", { "ok": (self.ok, _("add file to playlist")), @@ -95,11 +157,11 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self["MediaPlayerActions"] = HelpableActionMap(self, "MediaPlayerActions", { - "play": (self.playEntry, _("play entry")), + "play": (self.xplayEntry, _("play entry")), "pause": (self.pauseEntry, _("pause")), "stop": (self.stopEntry, _("stop entry")), - "previous": (self.previousEntry, _("play previous playlist entry")), - "next": (self.nextEntry, _("play next playlist entry")), + "previous": (self.previousMarkOrEntry, _("play from previous mark or playlist entry")), + "next": (self.nextMarkOrEntry, _("play from next mark or playlist entry")), "menu": (self.showMenu, _("menu")), "skipListbegin": (self.skip_listbegin, _("jump to listbegin")), "skipListend": (self.skip_listend, _("jump to listend")), @@ -108,6 +170,7 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup "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", @@ -134,32 +197,22 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions") - self.__event_tracker = ServiceEventTracker(screen=self, eventmap= - { - #iPlayableService.evStart: self.__serviceStarted, - #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged, - - iPlayableService.evEOF: self.__evEOF, - }) - self.onClose.append(self.delMPTimer) self.onClose.append(self.__onClose) self.righttimer = False self.rightKeyTimer = eTimer() - self.rightKeyTimer.timeout.get().append(self.rightTimerFire) + self.rightKeyTimer.callback.append(self.rightTimerFire) self.lefttimer = False self.leftKeyTimer = eTimer() - self.leftKeyTimer.timeout.get().append(self.leftTimerFire) - - self.infoTimer = eTimer() - self.infoTimer.timeout.get().append(self.infoTimerFire) - self.infoTimer.start(500) + self.leftKeyTimer.callback.append(self.leftTimerFire) self.currList = "filelist" - - self.coverArtFileName = "" + self.isAudioCD = False + self.AudioCD_albuminfo = {} + self.cdAudioTrackFiles = [] + self.applySettings() self.playlistIOInternal = PlaylistIOInternal() list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls")) @@ -168,6 +221,15 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self.playlist.addFile(x.ref) self.playlist.updateList() + self.__event_tracker = ServiceEventTracker(screen=self, eventmap= + { + iPlayableService.evUpdatedInfo: self.__evUpdatedInfo, + iPlayableService.evUser+10: self.__evAudioDecodeError, + iPlayableService.evUser+11: self.__evVideoDecodeError, + iPlayableService.evUser+12: self.__evPluginError, + iPlayableService.evUser+13: self["coverArt"].embeddedCoverArt + }) + def doNothing(self): pass @@ -175,46 +237,89 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup return MediaPlayerLCDScreen def exit(self): - self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5) - - def exitCB(self, answer): - if answer == True: - 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 self.savePlaylistOnExit: self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls")) - self.close() + if config.mediaplayer.saveDirOnExit.getValue(): + config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory()) + config.mediaplayer.defaultDir.save() + from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier + hotplugNotifier.remove(self.hotplugCB) + del self["coverArt"].picload + self.close() def checkSkipShowHideLock(self): self.updatedSeekState() - def __evEOF(self): - self.nextEntry() + def doEofInternal(self, playing): + if playing: + self.nextEntry() + else: + self.show() def __onClose(self): self.session.nav.playService(self.oldService) + def __evUpdatedInfo(self): + currPlay = self.session.nav.getCurrentService() + sTagTrackNumber = currPlay.info().getInfo(iServiceInformation.sTagTrackNumber) + sTagTrackCount = currPlay.info().getInfo(iServiceInformation.sTagTrackCount) + sTagTitle = currPlay.info().getInfoString(iServiceInformation.sTagTitle) + print "[__evUpdatedInfo] title %d of %d (%s)" % (sTagTrackNumber, sTagTrackCount, sTagTitle) + self.readTitleInformation() + + def __evAudioDecodeError(self): + currPlay = self.session.nav.getCurrentService() + sTagAudioCodec = currPlay.info().getInfoString(iServiceInformation.sTagAudioCodec) + print "[__evAudioDecodeError] audio-codec %s can't be decoded by hardware" % (sTagAudioCodec) + self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sTagAudioCodec, type = MessageBox.TYPE_INFO,timeout = 20 ) + + def __evVideoDecodeError(self): + currPlay = self.session.nav.getCurrentService() + sTagVideoCodec = currPlay.info().getInfoString(iServiceInformation.sTagVideoCodec) + print "[__evVideoDecodeError] video-codec %s can't be decoded by hardware" % (sTagVideoCodec) + self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sTagVideoCodec, 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 - del self.infoTimer - def infoTimerFire(self): + 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) - self.updateCoverArtPixmap( currPlay.info().getName() ) + sTitle = currPlay.info().getInfoString(iServiceInformation.sTagTitle) + sAlbum = currPlay.info().getInfoString(iServiceInformation.sTagAlbum) + sGenre = currPlay.info().getInfoString(iServiceInformation.sTagGenre) + sArtist = currPlay.info().getInfoString(iServiceInformation.sTagArtist) + sYear = currPlay.info().getInfoString(iServiceInformation.sTagDate) + + if sTitle == "": + if not self.isAudioCD: + sTitle = currPlay.info().getName().split('/')[-1] + else: + sTitle = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getName() + + 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 "artist" in self.AudioCD_albuminfo: + sArtist = self.AudioCD_albuminfo["artist"] + if "year" in self.AudioCD_albuminfo: + sYear = self.AudioCD_albuminfo["year"] + + self.updateMusicInformation( sArtist, sTitle, sAlbum, sYear, sGenre, clear = True ) else: self.updateMusicInformation() - self.updateCoverArtPixmap( "" ) def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False): self.updateSingleMusicInformation("artist", artist, clear) @@ -228,20 +333,6 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup if self[name].getText() != info: self[name].setText(info) - def updateCoverArtPixmap(self, currentServiceName): - filename = currentServiceName - # The "getName" usually adds something like "MP3 File:" infront of filename - # Get rid of this...by finding the first "/" - # FIXME: this should be fixed in the servicemp3.cpp handler - filename = filename[filename.find("/"):] - path = os_path.dirname(filename) - pngname = path + "/" + "folder.png" - if not os_path.exists(pngname): - pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png") - if self.coverArtFileName != pngname: - self.coverArtFileName = pngname - self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName) - def leftDown(self): self.lefttimer = True self.leftKeyTimer.start(1000) @@ -296,7 +387,7 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self.updateCurrentInfo() def showAfterSeek(self): - self.show() + pass def showAfterCuesheetOperation(self): self.show() @@ -304,6 +395,13 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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 = "" @@ -351,16 +449,14 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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] - text = currref.getPath() - text = text.split('/')[-1] + text = self.getIdentifier(currref) self.summaries.setText(text,3) else: self.summaries.setText(" ",3) @@ -368,8 +464,7 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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) @@ -388,23 +483,28 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup def showMenu(self): menu = [] + if len(self.cdAudioTrackFiles): + menu.insert(0,(_("Play Audio-CD..."), "audiocd")) if self.currList == "filelist": if self.filelist.canDescent(): menu.append((_("add directory to playlist"), "copydir")) else: menu.append((_("add files to playlist"), "copyfiles")) menu.append((_("switch to playlist"), "playlist")) + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("delete file"), "deletefile")) else: menu.append((_("switch to filelist"), "filelist")) - - menu.append((_("shuffle playlist"), "shuffle")) - - menu.append((_("delete"), "delete")) menu.append((_("clear playlist"), "clear")) + menu.append((_("Delete entry"), "deleteentry")) + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("shuffle playlist"), "shuffle")) menu.append((_("hide player"), "hide")); - menu.append((_("save playlist"), "saveplaylist")); menu.append((_("load playlist"), "loadplaylist")); - menu.append((_("delete saved playlist"), "deleteplaylist")); + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("save playlist"), "saveplaylist")); + menu.append((_("delete saved playlist"), "deleteplaylist")); + menu.append((_("Edit settings"), "settings")) self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu) def menuCallback(self, choice): @@ -416,20 +516,19 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup elif choice[1] == "copyfiles": self.stopEntry() self.playlist.clear() + self.isAudioCD = False self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False) self.playServiceRefEntry(self.filelist.getServiceRef()) elif choice[1] == "playlist": self.switchToPlayList() elif choice[1] == "filelist": self.switchToFileList() - elif choice[1] == "delete": + elif choice[1] == "deleteentry": if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex(): self.stopEntry() self.deleteEntry() elif choice[1] == "clear": - self.stopEntry() - self.playlist.clear() - self.switchToFileList() + self.clear_playlist() elif choice[1] == "hide": self.hide() elif choice[1] == "saveplaylist": @@ -440,7 +539,35 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup self.delete_saved_playlist() elif choice[1] == "shuffle": self.playlist.PlayListShuffle() + elif choice[1] == "deletefile": + self.deleteFile() + elif choice[1] == "settings": + self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self) + elif choice[1] == "audiocd": + 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 applySettings(self): + self.savePlaylistOnExit = config.mediaplayer.savePlaylistOnExit.getValue() + if config.mediaplayer.repeat.getValue() == True: + self["repeat"].setPixmapNum(1) + else: + self["repeat"].setPixmapNum(0) def showEventInformation(self): from Screens.EventView import EventViewSimple @@ -501,12 +628,13 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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) - self.playlist.updateList() + self.playlist.updateList() def delete_saved_playlist(self): listpath = [] @@ -525,35 +653,102 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup def deleteConfirmed(self, confirmed): if confirmed: - os_remove(self.delname) + try: + os_remove(self.delname) + except OSError,e: + print "delete failed:", e + self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) def clear_playlist(self): + self.isAudioCD = False self.stopEntry() self.playlist.clear() self.switchToFileList() def copyDirectory(self, directory, recursive = True): print "copyDirectory", directory - filelist = FileList(directory, useServiceRef = True, isTop = True) + if directory == '/': + print "refusing to operate on /" + return + filelist = FileList(directory, useServiceRef = True, showMountpoints = False, isTop = True) for x in filelist.getFileList(): if x[0][1] == True: #isDir if recursive: - self.copyDirectory(x[0][0]) - else: + if x[0][0] != directory: + self.copyDirectory(x[0][0]) + elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097: self.playlist.addFile(x[0][0]) self.playlist.updateList() + def deleteFile(self): + if self.currList == "filelist": + self.service = self.filelist.getServiceRef() + else: + self.service = self.playlist.getSelection() + if self.service is None: + return + if self.service.type != 4098 and self.session.nav.getCurrentlyPlayingServiceReference() is not None: + if self.service == self.session.nav.getCurrentlyPlayingServiceReference(): + self.stopEntry() + + serviceHandler = eServiceCenter.getInstance() + offline = serviceHandler.offlineOperations(self.service) + info = serviceHandler.info(self.service) + name = info and info.getName(self.service) + result = False + if offline is not None: + # simulate first + if not offline.deleteFromDisk(1): + result = True + if result == True: + self.session.openWithCallback(self.deleteConfirmed_offline, MessageBox, _("Do you really want to delete %s?") % (name)) + else: + self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR) + + def deleteConfirmed_offline(self, confirmed): + if confirmed: + serviceHandler = eServiceCenter.getInstance() + offline = serviceHandler.offlineOperations(self.service) + result = False + if offline is not None: + # really delete! + if not offline.deleteFromDisk(0): + result = True + if result == False: + self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) + else: + self.removeListEntry() + + def removeListEntry(self): + currdir = self.filelist.getCurrentDirectory() + self.filelist.changeDir(currdir) + deleteend = False + while not deleteend: + index = 0 + deleteend = True + if len(self.playlist) > 0: + for x in self.playlist.list: + if self.service == x[0]: + self.playlist.deleteFile(index) + deleteend = False + break + index += 1 + self.playlist.updateList() + if self.currList == "playlist": + if len(self.playlist) == 0: + self.switchToFileList() + def copyFile(self): if self.filelist.getServiceRef().type == 4098: # playlist ServiceRef = self.filelist.getServiceRef() extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:] - print "extension:", extension if self.playlistparsers.has_key(extension): playlist = self.playlistparsers[extension]() list = playlist.open(ServiceRef.getPath()) for x in list: self.playlist.addFile(x.ref) + self.playlist.updateList() else: self.playlist.addFile(self.filelist.getServiceRef()) self.playlist.updateList() @@ -567,11 +762,23 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup next = self.playlist.getCurrentIndex() + 1 if next < len(self.playlist): self.changeEntry(next) + elif ( len(self.playlist) > 0 ) and ( config.mediaplayer.repeat.getValue() == True ): + self.stopEntry() + self.changeEntry(0) - def previousEntry(self): - next = self.playlist.getCurrentIndex() - 1 - if next >= 0: - self.changeEntry(next) + def nextMarkOrEntry(self): + if not self.jumpPreviousNextMark(lambda x: x): + next = self.playlist.getCurrentIndex() + 1 + if next < len(self.playlist): + self.changeEntry(next) + else: + self.doSeek(-1) + + def previousMarkOrEntry(self): + if not self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True): + next = self.playlist.getCurrentIndex() - 1 + if next >= 0: + self.changeEntry(next) def deleteEntry(self): self.playlist.deleteFile(self.playlist.getSelectionIndex()) @@ -589,9 +796,29 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup if serviceRefList[count] == serviceref: self.changeEntry(count) break - + + def xplayEntry(self): + if self.currList == "playlist": + self.playEntry() + else: + self.stopEntry() + self.playlist.clear() + self.isAudioCD = False + sel = self.filelist.getSelection() + if sel: + if sel[1]: # can descent + # add directory to playlist + self.copyDirectory(sel[0]) + else: + # add files to playlist + self.copyDirectory(os_path.dirname(sel[0].getPath()) + "/", recursive = False) + if len(self.playlist) > 0: + self.changeEntry(0) + def playEntry(self): if len(self.playlist.getServiceRefList()): + audio_extensions = (".mp2", ".mp3", ".wav", ".ogg", "flac", "m4a") + needsInfoUpdate = False currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()] if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference(): self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]) @@ -601,22 +828,22 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup # 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() + ext = text[-4:].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 audio_extensions and not self.isAudioCD: self.hide() + else: + needsInfoUpdate = True self.summaries.setText(text,1) # get the next two entries 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) @@ -624,8 +851,7 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup 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) @@ -633,36 +859,36 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup idx = self.playlist.getCurrentIndex() currref = self.playlist.getServiceRefList()[idx] text = currref.getPath() - ext = text[-3:].lower() - if ext not in ["mp3", "wav", "ogg"]: + ext = text[-4:].lower() + if ext not in audio_extensions and not self.isAudioCD: self.hide() + else: + needsInfoUpdate = True + self.unPauseService() + if needsInfoUpdate == True: + path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath() + self["coverArt"].updateCoverArt(path) + else: + self["coverArt"].showDefaultCover() + self.readTitleInformation() def updatedSeekState(self): if self.seekstate == self.SEEK_STATE_PAUSE: self.playlist.pauseFile() elif self.seekstate == self.SEEK_STATE_PLAY: self.playlist.playFile() - elif self.seekstate in ( self.SEEK_STATE_FF_2X, - self.SEEK_STATE_FF_4X, - self.SEEK_STATE_FF_8X, - self.SEEK_STATE_FF_16X, - self.SEEK_STATE_FF_32X, - self.SEEK_STATE_FF_48X, - self.SEEK_STATE_FF_64X, - self.SEEK_STATE_FF_128X): + elif self.isStateForward(self.seekstate): self.playlist.forwardFile() - elif self.seekstate in ( self.SEEK_STATE_BACK_8X, - self.SEEK_STATE_BACK_16X, - self.SEEK_STATE_BACK_32X, - self.SEEK_STATE_BACK_48X, - self.SEEK_STATE_BACK_64X, - self.SEEK_STATE_BACK_128X): + elif self.isStateBackward(self.seekstate): self.playlist.rewindFile() 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() @@ -672,7 +898,28 @@ class MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSup def unPauseService(self): self.setSeekState(self.SEEK_STATE_PLAY) - + + def subtitleSelection(self): + from Screens.Subtitles import Subtitles + self.session.open(Subtitles, self) + + def hotplugCB(self, dev, media_state): + if dev == harddiskmanager.getCD(): + if media_state == "1": + from Components.Scanner import scanDevice + devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()) + self.cdAudioTrackFiles = [] + res = scanDevice(devpath) + 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) + else: + self.cdAudioTrackFiles = [] + if self.isAudioCD: + self.clear_playlist() class MediaPlayerLCDScreen(Screen): skin = """ @@ -689,7 +936,6 @@ class MediaPlayerLCDScreen(Screen): self["text4"] = Label("") def setText(self, text, line): - print "lcd set text:", text, line if len(text) > 10: if text[-4:] == ".mp3": text = text[:-4] @@ -703,49 +949,86 @@ class MediaPlayerLCDScreen(Screen): self["text4"].setText(text) def main(session, **kwargs): - session.open(MediaPlayer) + session.open(MediaPlayer) def menu(menuid, **kwargs): if menuid == "mainmenu": - return [(_("Media player"), main)] + return [(_("Media player"), main, "media_player", 45)] return [] def filescan_open(list, session, **kwargs): from enigma import eServiceReference mp = session.open(MediaPlayer) + mp.playlist.clear() + mp.savePlaylistOnExit = False - mp.switchToPlayList() 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) - # 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) + mp.cdAudioTrackFiles = [] + for file in list: + mp.cdAudioTrackFiles.append(file.path) + mp.playAudioCD() def filescan(**kwargs): from Components.Scanner import Scanner, ScanPath - return [ - Scanner(mimetypes = ["video/mpeg"], + mediatypes = [ + Scanner(mimetypes = ["video/mpeg", "video/MP2T", "video/x-msvideo"], paths_to_scan = [ ScanPath(path = "", with_subdirs = False), ], name = "Movie", - description = "View Movies...", + description = _("View Movies..."), + openfnc = filescan_open, + ), + 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"], + Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg", "audio/x-flac"], paths_to_scan = [ ScanPath(path = "", with_subdirs = False), ], name = "Music", - description = "Play Music...", + description = _("Play Music..."), openfnc = filescan_open, - ) - ] + )] + try: + from Plugins.Extensions.CDInfo.plugin import Query + mediatypes.append( + Scanner(mimetypes = ["audio/x-cda"], + paths_to_scan = + [ + ScanPath(path = "", with_subdirs = False), + ], + name = "Audio-CD", + description = _("Play Audio-CD..."), + openfnc = audioCD_open, + )) + return mediatypes + except ImportError: + return mediatypes from Plugins.Plugin import PluginDescriptor def Plugins(**kwargs):