1 from os import path as os_path, remove as os_remove, listdir as os_listdir
2 from time import strftime
3 from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, ePicLoad
4 from ServiceReference import ServiceReference
5 from Screens.Screen import Screen
6 from Screens.HelpMenu import HelpableScreen
7 from Screens.MessageBox import MessageBox
8 from Screens.InputBox import InputBox
9 from Screens.ChoiceBox import ChoiceBox
10 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport
11 from Components.ActionMap import NumberActionMap, HelpableActionMap
12 from Components.Label import Label
13 from Components.Pixmap import Pixmap,MultiPixmap
14 from Components.FileList import FileList
15 from Components.MediaPlayer import PlayList
16 from Components.ServicePosition import ServicePositionGauge
17 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
18 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
19 from Components.AVSwitch import AVSwitch
20 from Components.Harddisk import harddiskmanager
21 from Components.config import config
22 from Tools.Directories import fileExists, pathExists, resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
23 from settings import MediaPlayerSettings
24 from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
27 class MyPlayList(PlayList):
29 PlayList.__init__(self)
31 def PlayListShuffle(self):
32 random.shuffle(self.list)
33 self.l.setList(self.list)
35 self.oldCurrPlaying = -1
37 class MediaPixmap(Pixmap):
40 self.coverArtFileName = ""
41 self.picload = ePicLoad()
42 self.picload.PictureData.get().append(self.paintCoverArtPixmapCB)
43 self.coverFileNames = ["folder.png", "folder.jpg"]
45 def applySkin(self, desktop, screen):
46 from Tools.LoadPixmap import LoadPixmap
48 if self.skinAttributes is not None:
49 for (attrib, value) in self.skinAttributes:
50 if attrib == "pixmap":
53 if noCoverFile is None:
54 noCoverFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
55 self.noCoverPixmap = LoadPixmap(noCoverFile)
56 return Pixmap.applySkin(self, desktop, screen)
60 sc = AVSwitch().getFramebufferScale()
61 #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
62 self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
64 def paintCoverArtPixmapCB(self, picInfo=None):
65 ptr = self.picload.getData()
67 self.instance.setPixmap(ptr.__deref__())
69 def updateCoverArt(self, path):
70 while not path.endswith("/"):
72 new_coverArtFileName = None
73 for filename in self.coverFileNames:
74 if fileExists(path + filename):
75 new_coverArtFileName = path + filename
76 if self.coverArtFileName != new_coverArtFileName:
77 self.coverArtFileName = new_coverArtFileName
78 if new_coverArtFileName:
79 self.picload.startDecode(self.coverArtFileName)
81 self.showDefaultCover()
83 def showDefaultCover(self):
84 self.instance.setPixmap(self.noCoverPixmap)
86 def embeddedCoverArt(self):
87 print "[embeddedCoverArt] found"
88 self.coverArtFileName = "/tmp/.id3coverart"
89 self.picload.startDecode(self.coverArtFileName)
91 class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen):
93 ENABLE_RESUME_SUPPORT = True
95 def __init__(self, session, args = None):
96 Screen.__init__(self, session)
97 InfoBarAudioSelection.__init__(self)
98 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
99 InfoBarNotifications.__init__(self)
100 InfoBarBase.__init__(self)
101 InfoBarSubtitleSupport.__init__(self)
102 HelpableScreen.__init__(self)
104 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
105 self.session.nav.stopService()
107 self.playlistparsers = {}
108 self.addPlaylistParser(PlaylistIOM3U, "m3u")
109 self.addPlaylistParser(PlaylistIOPLS, "pls")
110 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
112 # 'None' is magic to start at the list of mountpoints
113 defaultDir = config.mediaplayer.defaultDir.getValue()
114 self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|mkv|mp4|m4a|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
115 self["filelist"] = self.filelist
117 self.playlist = MyPlayList()
118 self.is_closing = False
120 self["playlist"] = self.playlist
122 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
124 self["currenttext"] = Label("")
126 self["artisttext"] = Label(_("Artist")+':')
127 self["artist"] = Label("")
128 self["titletext"] = Label(_("Title")+':')
129 self["title"] = Label("")
130 self["albumtext"] = Label(_("Album")+':')
131 self["album"] = Label("")
132 self["yeartext"] = Label(_("Year")+':')
133 self["year"] = Label("")
134 self["genretext"] = Label(_("Genre")+':')
135 self["genre"] = Label("")
136 self["coverArt"] = MediaPixmap()
137 self["repeat"] = MultiPixmap()
139 self.seek_target = None
140 hotplugNotifier.append(self.hotplugCB)
142 class MoviePlayerActionMap(NumberActionMap):
143 def __init__(self, player, contexts = [ ], actions = { }, prio=0):
144 NumberActionMap.__init__(self, contexts, actions, prio)
147 def action(self, contexts, action):
149 return NumberActionMap.action(self, contexts, action)
152 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
154 "ok": (self.ok, _("add file to playlist")),
155 "cancel": (self.exit, _("exit mediaplayer")),
158 self["MediaPlayerActions"] = HelpableActionMap(self, "MediaPlayerActions",
160 "play": (self.xplayEntry, _("play entry")),
161 "pause": (self.pauseEntry, _("pause")),
162 "stop": (self.stopEntry, _("stop entry")),
163 "previous": (self.previousMarkOrEntry, _("play from previous mark or playlist entry")),
164 "next": (self.nextMarkOrEntry, _("play from next mark or playlist entry")),
165 "menu": (self.showMenu, _("menu")),
166 "skipListbegin": (self.skip_listbegin, _("jump to listbegin")),
167 "skipListend": (self.skip_listend, _("jump to listend")),
168 "prevBouquet": (self.switchToPlayList, _("switch to playlist")),
169 "nextBouquet": (self.switchToFileList, _("switch to filelist")),
170 "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
171 "shift_stop": (self.clear_playlist, _("clear playlist")),
172 "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
173 "subtitles": (self.subtitleSelection, _("Subtitle selection")),
176 self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
178 "showEventInfo": (self.showEventInformation, _("show event details")),
181 self["actions"] = MoviePlayerActionMap(self, ["DirectionActions"],
183 "right": self.rightDown,
184 "rightRepeated": self.doNothing,
185 "rightUp": self.rightUp,
186 "left": self.leftDown,
187 "leftRepeated": self.doNothing,
188 "leftUp": self.leftUp,
191 "upRepeated": self.up,
192 "upUp": self.doNothing,
194 "downRepeated": self.down,
195 "downUp": self.doNothing,
198 InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions")
200 self.onClose.append(self.delMPTimer)
201 self.onClose.append(self.__onClose)
203 self.righttimer = False
204 self.rightKeyTimer = eTimer()
205 self.rightKeyTimer.callback.append(self.rightTimerFire)
207 self.lefttimer = False
208 self.leftKeyTimer = eTimer()
209 self.leftKeyTimer.callback.append(self.leftTimerFire)
211 self.currList = "filelist"
212 self.isAudioCD = False
213 self.AudioCD_albuminfo = {}
214 self.cdAudioTrackFiles = []
217 self.playlistIOInternal = PlaylistIOInternal()
218 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
221 self.playlist.addFile(x.ref)
222 self.playlist.updateList()
224 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
226 iPlayableService.evUpdatedInfo: self.__evUpdatedInfo,
227 iPlayableService.evUser+10: self.__evAudioDecodeError,
228 iPlayableService.evUser+11: self.__evVideoDecodeError,
229 iPlayableService.evUser+12: self.__evPluginError,
230 iPlayableService.evUser+13: self["coverArt"].embeddedCoverArt
236 def createSummary(self):
237 return MediaPlayerLCDScreen
240 self.playlistIOInternal.clear()
241 for x in self.playlist.list:
242 self.playlistIOInternal.addService(ServiceReference(x[0]))
243 if self.savePlaylistOnExit:
244 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
245 if config.mediaplayer.saveDirOnExit.getValue():
246 config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory())
247 config.mediaplayer.defaultDir.save()
248 hotplugNotifier.remove(self.hotplugCB)
249 del self["coverArt"].picload
252 def checkSkipShowHideLock(self):
253 self.updatedSeekState()
255 def doEofInternal(self, playing):
262 self.session.nav.playService(self.oldService)
264 def __evUpdatedInfo(self):
265 currPlay = self.session.nav.getCurrentService()
266 currenttitle = currPlay.info().getInfo(iServiceInformation.sCurrentTitle)
267 totaltitles = currPlay.info().getInfo(iServiceInformation.sTotalTitles)
268 sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
269 print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
270 self.readTitleInformation()
272 def __evAudioDecodeError(self):
273 currPlay = self.session.nav.getCurrentService()
274 sAudioType = currPlay.info().getInfoString(iServiceInformation.sUser+10)
275 print "[__evAudioDecodeError] audio-codec %s can't be decoded by hardware" % (sAudioType)
276 self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sAudioType, type = MessageBox.TYPE_INFO,timeout = 20 )
278 def __evVideoDecodeError(self):
279 currPlay = self.session.nav.getCurrentService()
280 sVideoType = currPlay.info().getInfoString(iServiceInformation.sVideoType)
281 print "[__evVideoDecodeError] video-codec %s can't be decoded by hardware" % (sVideoType)
282 self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sVideoType, type = MessageBox.TYPE_INFO,timeout = 20 )
284 def __evPluginError(self):
285 currPlay = self.session.nav.getCurrentService()
286 message = currPlay.info().getInfoString(iServiceInformation.sUser+12)
287 print "[__evPluginError]" , message
288 self.session.open(MessageBox, message, type = MessageBox.TYPE_INFO,timeout = 20 )
290 def delMPTimer(self):
291 del self.rightKeyTimer
292 del self.leftKeyTimer
294 def readTitleInformation(self):
295 currPlay = self.session.nav.getCurrentService()
296 if currPlay is not None:
297 sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
298 sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
299 sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
300 sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
301 sYear = currPlay.info().getInfoString(iServiceInformation.sTimeCreate)
304 if not self.isAudioCD:
305 sTitle = currPlay.info().getName().split('/')[-1]
307 sTitle = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getName()
309 if self.AudioCD_albuminfo:
310 if sAlbum == "" and "title" in self.AudioCD_albuminfo:
311 sAlbum = self.AudioCD_albuminfo["title"]
312 if sGenre == "" and "genre" in self.AudioCD_albuminfo:
313 sGenre = self.AudioCD_albuminfo["genre"]
314 if sArtist == "" and "artist" in self.AudioCD_albuminfo:
315 sArtist = self.AudioCD_albuminfo["artist"]
316 if "year" in self.AudioCD_albuminfo:
317 sYear = self.AudioCD_albuminfo["year"]
319 self.updateMusicInformation( sArtist, sTitle, sAlbum, sYear, sGenre, clear = True )
321 self.updateMusicInformation()
323 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
324 self.updateSingleMusicInformation("artist", artist, clear)
325 self.updateSingleMusicInformation("title", title, clear)
326 self.updateSingleMusicInformation("album", album, clear)
327 self.updateSingleMusicInformation("year", year, clear)
328 self.updateSingleMusicInformation("genre", genre, clear)
330 def updateSingleMusicInformation(self, name, info, clear):
331 if info != "" or clear:
332 if self[name].getText() != info:
333 self[name].setText(info)
336 self.lefttimer = True
337 self.leftKeyTimer.start(1000)
340 self.righttimer = True
341 self.rightKeyTimer.start(1000)
345 self.leftKeyTimer.stop()
346 self.lefttimer = False
347 self[self.currList].pageUp()
348 self.updateCurrentInfo()
352 self.rightKeyTimer.stop()
353 self.righttimer = False
354 self[self.currList].pageDown()
355 self.updateCurrentInfo()
357 def leftTimerFire(self):
358 self.leftKeyTimer.stop()
359 self.lefttimer = False
360 self.switchToFileList()
362 def rightTimerFire(self):
363 self.rightKeyTimer.stop()
364 self.righttimer = False
365 self.switchToPlayList()
367 def switchToFileList(self):
368 self.currList = "filelist"
369 self.filelist.selectionEnabled(1)
370 self.playlist.selectionEnabled(0)
371 self.updateCurrentInfo()
373 def switchToPlayList(self):
374 if len(self.playlist) != 0:
375 self.currList = "playlist"
376 self.filelist.selectionEnabled(0)
377 self.playlist.selectionEnabled(1)
378 self.updateCurrentInfo()
381 self[self.currList].up()
382 self.updateCurrentInfo()
385 self[self.currList].down()
386 self.updateCurrentInfo()
388 def showAfterSeek(self):
391 def showAfterCuesheetOperation(self):
394 def hideAfterResume(self):
397 def getIdentifier(self, ref):
402 return text.split('/')[-1]
404 # FIXME: maybe this code can be optimized
405 def updateCurrentInfo(self):
407 if self.currList == "filelist":
408 idx = self.filelist.getSelectionIndex()
409 r = self.filelist.list[idx]
416 self.summaries.setText(text,1)
419 if idx < len(self.filelist.list):
420 r = self.filelist.list[idx]
424 self.summaries.setText(text,3)
426 self.summaries.setText(" ",3)
429 if idx < len(self.filelist.list):
430 r = self.filelist.list[idx]
434 self.summaries.setText(text,4)
436 self.summaries.setText(" ",4)
439 if not self.filelist.canDescent():
440 r = self.filelist.getServiceRef()
444 self["currenttext"].setText(os_path.basename(text))
446 if self.currList == "playlist":
447 t = self.playlist.getSelection()
450 #display current selected entry on LCD
451 text = self.getIdentifier(t)
452 self.summaries.setText(text,1)
453 self["currenttext"].setText(text)
454 idx = self.playlist.getSelectionIndex()
456 if idx < len(self.playlist):
457 currref = self.playlist.getServiceRefList()[idx]
458 text = self.getIdentifier(currref)
459 self.summaries.setText(text,3)
461 self.summaries.setText(" ",3)
464 if idx < len(self.playlist):
465 currref = self.playlist.getServiceRefList()[idx]
466 text = self.getIdentifier(currref)
467 self.summaries.setText(text,4)
469 self.summaries.setText(" ",4)
472 if self.currList == "filelist":
473 if self.filelist.canDescent():
474 self.filelist.descent()
475 self.updateCurrentInfo()
479 if self.currList == "playlist":
480 selection = self["playlist"].getSelection()
481 self.changeEntry(self.playlist.getSelectionIndex())
485 if len(self.cdAudioTrackFiles):
486 menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
487 if self.currList == "filelist":
488 if self.filelist.canDescent():
489 menu.append((_("add directory to playlist"), "copydir"))
491 menu.append((_("add files to playlist"), "copyfiles"))
492 menu.append((_("switch to playlist"), "playlist"))
493 if config.usage.setup_level.index >= 1: # intermediate+
494 menu.append((_("delete file"), "deletefile"))
496 menu.append((_("switch to filelist"), "filelist"))
497 menu.append((_("clear playlist"), "clear"))
498 menu.append((_("Delete entry"), "deleteentry"))
499 if config.usage.setup_level.index >= 1: # intermediate+
500 menu.append((_("shuffle playlist"), "shuffle"))
501 menu.append((_("hide player"), "hide"));
502 menu.append((_("load playlist"), "loadplaylist"));
503 if config.usage.setup_level.index >= 1: # intermediate+
504 menu.append((_("save playlist"), "saveplaylist"));
505 menu.append((_("delete saved playlist"), "deleteplaylist"));
506 menu.append((_("Edit settings"), "settings"))
507 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
509 def menuCallback(self, choice):
513 if choice[1] == "copydir":
514 self.copyDirectory(self.filelist.getSelection()[0])
515 elif choice[1] == "copyfiles":
517 self.playlist.clear()
518 self.isAudioCD = False
519 self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
520 self.playServiceRefEntry(self.filelist.getServiceRef())
521 elif choice[1] == "playlist":
522 self.switchToPlayList()
523 elif choice[1] == "filelist":
524 self.switchToFileList()
525 elif choice[1] == "deleteentry":
526 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
529 elif choice[1] == "clear":
530 self.clear_playlist()
531 elif choice[1] == "hide":
533 elif choice[1] == "saveplaylist":
535 elif choice[1] == "loadplaylist":
537 elif choice[1] == "deleteplaylist":
538 self.delete_saved_playlist()
539 elif choice[1] == "shuffle":
540 self.playlist.PlayListShuffle()
541 elif choice[1] == "deletefile":
543 elif choice[1] == "settings":
544 self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self)
545 elif choice[1] == "audiocd":
548 def playAudioCD(self):
549 from enigma import eServiceReference
550 from Plugins.Extensions.CDInfo.plugin import Query
552 if len(self.cdAudioTrackFiles):
553 self.playlist.clear()
554 self.savePlaylistOnExit = False
555 self.isAudioCD = True
556 for file in self.cdAudioTrackFiles:
557 ref = eServiceReference(4097, 0, file)
558 self.playlist.addFile(ref)
562 self.switchToPlayList()
564 def applySettings(self):
565 self.savePlaylistOnExit = config.mediaplayer.savePlaylistOnExit.getValue()
566 if config.mediaplayer.repeat.getValue() == True:
567 self["repeat"].setPixmapNum(1)
569 self["repeat"].setPixmapNum(0)
571 def showEventInformation(self):
572 from Screens.EventView import EventViewSimple
573 from ServiceReference import ServiceReference
574 evt = self[self.currList].getCurrentEvent()
576 self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
578 # also works on filelist (?)
579 def getCurrent(self):
580 return self["playlist"].getCurrent()
582 def deletePlaylistEntry(self):
583 if self.currList == "playlist":
584 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
588 def skip_listbegin(self):
589 if self.currList == "filelist":
590 self.filelist.moveToIndex(0)
592 self.playlist.moveToIndex(0)
593 self.updateCurrentInfo()
595 def skip_listend(self):
596 if self.currList == "filelist":
597 idx = len(self.filelist.list)
598 self.filelist.moveToIndex(idx - 1)
600 self.playlist.moveToIndex(len(self.playlist)-1)
601 self.updateCurrentInfo()
603 def save_playlist(self):
604 self.session.openWithCallback(self.save_playlist2,InputBox, title=_("Please enter filename (empty = use current date)"),windowTitle = _("Save Playlist"))
606 def save_playlist2(self, name):
610 name = strftime("%y%m%d_%H%M%S")
612 self.playlistIOInternal.clear()
613 for x in self.playlist.list:
614 self.playlistIOInternal.addService(ServiceReference(x[0]))
615 self.playlistIOInternal.save(resolveFilename(SCOPE_PLAYLIST) + name)
617 def load_playlist(self):
619 playlistdir = resolveFilename(SCOPE_PLAYLIST)
621 for i in os_listdir(playlistdir):
622 listpath.append((i,playlistdir + i))
624 print "Error while scanning subdirs ",e
625 self.session.openWithCallback(self.PlaylistSelected, ChoiceBox, title=_("Please select a playlist..."), list = listpath)
627 def PlaylistSelected(self,path):
629 self.clear_playlist()
630 extension = path[0].rsplit('.',1)[-1]
631 if self.playlistparsers.has_key(extension):
632 playlist = self.playlistparsers[extension]()
633 list = playlist.open(path[1])
635 self.playlist.addFile(x.ref)
636 self.playlist.updateList()
638 def delete_saved_playlist(self):
640 playlistdir = resolveFilename(SCOPE_PLAYLIST)
642 for i in os_listdir(playlistdir):
643 listpath.append((i,playlistdir + i))
645 print "Error while scanning subdirs ",e
646 self.session.openWithCallback(self.DeletePlaylistSelected, ChoiceBox, title=_("Please select a playlist to delete..."), list = listpath)
648 def DeletePlaylistSelected(self,path):
650 self.delname = path[1]
651 self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (path[1]))
653 def deleteConfirmed(self, confirmed):
656 os_remove(self.delname)
658 print "delete failed:", e
659 self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
661 def clear_playlist(self):
662 self.isAudioCD = False
664 self.playlist.clear()
665 self.switchToFileList()
667 def copyDirectory(self, directory, recursive = True):
668 print "copyDirectory", directory
670 print "refusing to operate on /"
672 filelist = FileList(directory, useServiceRef = True, showMountpoints = False, isTop = True)
674 for x in filelist.getFileList():
675 if x[0][1] == True: #isDir
677 if x[0][0] != directory:
678 self.copyDirectory(x[0][0])
679 elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097:
680 self.playlist.addFile(x[0][0])
681 self.playlist.updateList()
683 def deleteFile(self):
684 if self.currList == "filelist":
685 self.service = self.filelist.getServiceRef()
687 self.service = self.playlist.getSelection()
688 if self.service is None:
690 if self.service.type != 4098 and self.session.nav.getCurrentlyPlayingServiceReference() is not None:
691 if self.service == self.session.nav.getCurrentlyPlayingServiceReference():
694 serviceHandler = eServiceCenter.getInstance()
695 offline = serviceHandler.offlineOperations(self.service)
696 info = serviceHandler.info(self.service)
697 name = info and info.getName(self.service)
699 if offline is not None:
701 if not offline.deleteFromDisk(1):
704 self.session.openWithCallback(self.deleteConfirmed_offline, MessageBox, _("Do you really want to delete %s?") % (name))
706 self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)
708 def deleteConfirmed_offline(self, confirmed):
710 serviceHandler = eServiceCenter.getInstance()
711 offline = serviceHandler.offlineOperations(self.service)
713 if offline is not None:
715 if not offline.deleteFromDisk(0):
718 self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
720 self.removeListEntry()
722 def removeListEntry(self):
723 currdir = self.filelist.getCurrentDirectory()
724 self.filelist.changeDir(currdir)
729 if len(self.playlist) > 0:
730 for x in self.playlist.list:
731 if self.service == x[0]:
732 self.playlist.deleteFile(index)
736 self.playlist.updateList()
737 if self.currList == "playlist":
738 if len(self.playlist) == 0:
739 self.switchToFileList()
742 if self.filelist.getServiceRef().type == 4098: # playlist
743 ServiceRef = self.filelist.getServiceRef()
744 extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:]
745 if self.playlistparsers.has_key(extension):
746 playlist = self.playlistparsers[extension]()
747 list = playlist.open(ServiceRef.getPath())
749 self.playlist.addFile(x.ref)
750 self.playlist.updateList()
752 self.playlist.addFile(self.filelist.getServiceRef())
753 self.playlist.updateList()
754 if len(self.playlist) == 1:
757 def addPlaylistParser(self, parser, extension):
758 self.playlistparsers[extension] = parser
761 next = self.playlist.getCurrentIndex() + 1
762 if next < len(self.playlist):
763 self.changeEntry(next)
764 elif ( len(self.playlist) > 0 ) and ( config.mediaplayer.repeat.getValue() == True ):
768 def nextMarkOrEntry(self):
769 if not self.jumpPreviousNextMark(lambda x: x):
770 next = self.playlist.getCurrentIndex() + 1
771 if next < len(self.playlist):
772 self.changeEntry(next)
776 def previousMarkOrEntry(self):
777 if not self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True):
778 next = self.playlist.getCurrentIndex() - 1
780 self.changeEntry(next)
782 def deleteEntry(self):
783 self.playlist.deleteFile(self.playlist.getSelectionIndex())
784 self.playlist.updateList()
785 if len(self.playlist) == 0:
786 self.switchToFileList()
788 def changeEntry(self, index):
789 self.playlist.setCurrentPlaying(index)
792 def playServiceRefEntry(self, serviceref):
793 serviceRefList = self.playlist.getServiceRefList()
794 for count in range(len(serviceRefList)):
795 if serviceRefList[count] == serviceref:
796 self.changeEntry(count)
799 def xplayEntry(self):
800 if self.currList == "playlist":
804 self.playlist.clear()
805 self.isAudioCD = False
806 sel = self.filelist.getSelection()
808 if sel[1]: # can descent
809 # add directory to playlist
810 self.copyDirectory(sel[0])
812 # add files to playlist
813 self.copyDirectory(os_path.dirname(sel[0].getPath()) + "/", recursive = False)
814 if len(self.playlist) > 0:
818 if len(self.playlist.getServiceRefList()):
819 audio_extensions = (".mp2", ".mp3", ".wav", ".ogg", "flac", "m4a")
820 needsInfoUpdate = False
821 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
822 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
823 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
824 info = eServiceCenter.getInstance().info(currref)
825 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
826 self["title"].setText(description)
827 # display just playing musik on LCD
828 idx = self.playlist.getCurrentIndex()
829 currref = self.playlist.getServiceRefList()[idx]
830 text = self.getIdentifier(currref)
832 ext = text[-4:].lower()
834 # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead
835 if ext not in audio_extensions and not self.isAudioCD:
838 needsInfoUpdate = True
839 self.summaries.setText(text,1)
841 # get the next two entries
843 if idx < len(self.playlist):
844 currref = self.playlist.getServiceRefList()[idx]
845 text = self.getIdentifier(currref)
846 self.summaries.setText(text,3)
848 self.summaries.setText(" ",3)
851 if idx < len(self.playlist):
852 currref = self.playlist.getServiceRefList()[idx]
853 text = self.getIdentifier(currref)
854 self.summaries.setText(text,4)
856 self.summaries.setText(" ",4)
858 idx = self.playlist.getCurrentIndex()
859 currref = self.playlist.getServiceRefList()[idx]
860 text = currref.getPath()
861 ext = text[-4:].lower()
862 if ext not in audio_extensions and not self.isAudioCD:
865 needsInfoUpdate = True
867 self.unPauseService()
868 if needsInfoUpdate == True:
869 path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath()
870 self["coverArt"].updateCoverArt(path)
872 self["coverArt"].showDefaultCover()
873 self.readTitleInformation()
875 def updatedSeekState(self):
876 if self.seekstate == self.SEEK_STATE_PAUSE:
877 self.playlist.pauseFile()
878 elif self.seekstate == self.SEEK_STATE_PLAY:
879 self.playlist.playFile()
880 elif self.isStateForward(self.seekstate):
881 self.playlist.forwardFile()
882 elif self.isStateBackward(self.seekstate):
883 self.playlist.rewindFile()
885 def pauseEntry(self):
887 if self.seekstate == self.SEEK_STATE_PAUSE:
893 self.playlist.stopFile()
894 self.session.nav.playService(None)
895 self.updateMusicInformation(clear=True)
898 def unPauseService(self):
899 self.setSeekState(self.SEEK_STATE_PLAY)
901 def subtitleSelection(self):
902 from Screens.Subtitles import Subtitles
903 self.session.open(Subtitles)
905 def hotplugCB(self, dev, media_state):
906 if dev == harddiskmanager.getCD():
907 if media_state == "1":
908 from Components.Scanner import scanDevice
909 devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
910 self.cdAudioTrackFiles = []
911 res = scanDevice(devpath)
912 list = [ (r.description, r, res[r], self.session) for r in res ]
914 (desc, scanner, files, session) = list[0]
916 if file.mimetype == "audio/x-cda":
917 self.cdAudioTrackFiles.append(file.path)
919 self.cdAudioTrackFiles = []
921 self.clear_playlist()
923 class MediaPlayerLCDScreen(Screen):
925 <screen position="0,0" size="132,64" title="LCD Text">
926 <widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
927 <widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
928 <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
931 def __init__(self, session, parent):
932 Screen.__init__(self, session)
933 self["text1"] = Label("Mediaplayer")
934 self["text3"] = Label("")
935 self["text4"] = Label("")
937 def setText(self, text, line):
939 if text[-4:] == ".mp3":
942 text = text + textleer*10
944 self["text1"].setText(text)
946 self["text3"].setText(text)
948 self["text4"].setText(text)
950 def main(session, **kwargs):
951 session.open(MediaPlayer)
953 def menu(menuid, **kwargs):
954 if menuid == "mainmenu":
955 return [(_("Media player"), main, "media_player", 45)]
958 def filescan_open(list, session, **kwargs):
959 from enigma import eServiceReference
961 mp = session.open(MediaPlayer)
963 mp.savePlaylistOnExit = False
966 if file.mimetype == "video/MP2T":
970 ref = eServiceReference(stype, 0, file.path)
971 mp.playlist.addFile(ref)
974 mp.switchToPlayList()
976 def audioCD_open(list, session, **kwargs):
977 from enigma import eServiceReference
979 mp = session.open(MediaPlayer)
980 mp.cdAudioTrackFiles = []
982 mp.cdAudioTrackFiles.append(file.path)
985 def filescan(**kwargs):
986 from Components.Scanner import Scanner, ScanPath
988 Scanner(mimetypes = ["video/mpeg", "video/MP2T", "video/x-msvideo"],
991 ScanPath(path = "", with_subdirs = False),
994 description = _("View Movies..."),
995 openfnc = filescan_open,
997 Scanner(mimetypes = ["video/x-vcd"],
1000 ScanPath(path = "mpegav", with_subdirs = False),
1001 ScanPath(path = "MPEGAV", with_subdirs = False),
1004 description = _("View Video CD..."),
1005 openfnc = filescan_open,
1007 Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg", "audio/x-flac"],
1010 ScanPath(path = "", with_subdirs = False),
1013 description = _("Play Music..."),
1014 openfnc = filescan_open,
1017 from Plugins.Extensions.CDInfo.plugin import Query
1019 Scanner(mimetypes = ["audio/x-cda"],
1022 ScanPath(path = "", with_subdirs = False),
1025 description = _("Play Audio-CD..."),
1026 openfnc = audioCD_open,
1032 from Plugins.Plugin import PluginDescriptor
1033 def Plugins(**kwargs):
1035 PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu),
1036 PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)