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)
151 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
153 "ok": (self.ok, _("add file to playlist")),
154 "cancel": (self.exit, _("exit mediaplayer")),
157 self["MediaPlayerActions"] = HelpableActionMap(self, "MediaPlayerActions",
159 "play": (self.xplayEntry, _("play entry")),
160 "pause": (self.pauseEntry, _("pause")),
161 "stop": (self.stopEntry, _("stop entry")),
162 "previous": (self.previousMarkOrEntry, _("play from previous mark or playlist entry")),
163 "next": (self.nextMarkOrEntry, _("play from next mark or playlist entry")),
164 "menu": (self.showMenu, _("menu")),
165 "skipListbegin": (self.skip_listbegin, _("jump to listbegin")),
166 "skipListend": (self.skip_listend, _("jump to listend")),
167 "prevBouquet": (self.switchToPlayList, _("switch to playlist")),
168 "nextBouquet": (self.switchToFileList, _("switch to filelist")),
169 "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
170 "shift_stop": (self.clear_playlist, _("clear playlist")),
171 "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
172 "subtitles": (self.subtitleSelection, _("Subtitle selection")),
175 self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
177 "showEventInfo": (self.showEventInformation, _("show event details")),
180 self["actions"] = MoviePlayerActionMap(self, ["DirectionActions"],
182 "right": self.rightDown,
183 "rightRepeated": self.doNothing,
184 "rightUp": self.rightUp,
185 "left": self.leftDown,
186 "leftRepeated": self.doNothing,
187 "leftUp": self.leftUp,
190 "upRepeated": self.up,
191 "upUp": self.doNothing,
193 "downRepeated": self.down,
194 "downUp": self.doNothing,
197 InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions")
199 self.onClose.append(self.delMPTimer)
200 self.onClose.append(self.__onClose)
202 self.righttimer = False
203 self.rightKeyTimer = eTimer()
204 self.rightKeyTimer.callback.append(self.rightTimerFire)
206 self.lefttimer = False
207 self.leftKeyTimer = eTimer()
208 self.leftKeyTimer.callback.append(self.leftTimerFire)
210 self.currList = "filelist"
211 self.isAudioCD = False
212 self.AudioCD_albuminfo = {}
213 self.cdAudioTrackFiles = []
216 self.playlistIOInternal = PlaylistIOInternal()
217 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
220 self.playlist.addFile(x.ref)
221 self.playlist.updateList()
223 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
225 iPlayableService.evUpdatedInfo: self.__evUpdatedInfo,
226 iPlayableService.evUser+10: self.__evAudioDecodeError,
227 iPlayableService.evUser+11: self.__evVideoDecodeError,
228 iPlayableService.evUser+12: self.__evPluginError,
229 iPlayableService.evUser+13: self["coverArt"].embeddedCoverArt
235 def createSummary(self):
236 return MediaPlayerLCDScreen
239 self.playlistIOInternal.clear()
240 for x in self.playlist.list:
241 self.playlistIOInternal.addService(ServiceReference(x[0]))
242 if self.savePlaylistOnExit:
243 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
244 if config.mediaplayer.saveDirOnExit.getValue():
245 config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory())
246 config.mediaplayer.defaultDir.save()
247 hotplugNotifier.remove(self.hotplugCB)
248 del self["coverArt"].picload
251 def checkSkipShowHideLock(self):
252 self.updatedSeekState()
254 def doEofInternal(self, playing):
261 self.session.nav.playService(self.oldService)
263 def __evUpdatedInfo(self):
264 currPlay = self.session.nav.getCurrentService()
265 currenttitle = currPlay.info().getInfo(iServiceInformation.sCurrentTitle)
266 totaltitles = currPlay.info().getInfo(iServiceInformation.sTotalTitles)
267 sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
268 print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
269 self.readTitleInformation()
271 def __evAudioDecodeError(self):
272 currPlay = self.session.nav.getCurrentService()
273 sAudioType = currPlay.info().getInfoString(iServiceInformation.sUser+10)
274 print "[__evAudioDecodeError] audio-codec %s can't be decoded by hardware" % (sAudioType)
275 self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sAudioType, type = MessageBox.TYPE_INFO,timeout = 20 )
277 def __evVideoDecodeError(self):
278 currPlay = self.session.nav.getCurrentService()
279 sVideoType = currPlay.info().getInfoString(iServiceInformation.sVideoType)
280 print "[__evVideoDecodeError] video-codec %s can't be decoded by hardware" % (sVideoType)
281 self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sVideoType, type = MessageBox.TYPE_INFO,timeout = 20 )
283 def __evPluginError(self):
284 currPlay = self.session.nav.getCurrentService()
285 message = currPlay.info().getInfoString(iServiceInformation.sUser+12)
286 print "[__evPluginError]" , message
287 self.session.open(MessageBox, message, type = MessageBox.TYPE_INFO,timeout = 20 )
289 def delMPTimer(self):
290 del self.rightKeyTimer
291 del self.leftKeyTimer
293 def readTitleInformation(self):
294 currPlay = self.session.nav.getCurrentService()
295 if currPlay is not None:
296 sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
297 sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
298 sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
299 sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
300 sYear = currPlay.info().getInfoString(iServiceInformation.sTimeCreate)
303 if not self.isAudioCD:
304 sTitle = currPlay.info().getName().split('/')[-1]
306 sTitle = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getName()
308 if self.AudioCD_albuminfo:
309 if sAlbum == "" and "title" in self.AudioCD_albuminfo:
310 sAlbum = self.AudioCD_albuminfo["title"]
311 if sGenre == "" and "genre" in self.AudioCD_albuminfo:
312 sGenre = self.AudioCD_albuminfo["genre"]
313 if sArtist == "" and "artist" in self.AudioCD_albuminfo:
314 sArtist = self.AudioCD_albuminfo["artist"]
315 if "year" in self.AudioCD_albuminfo:
316 sYear = self.AudioCD_albuminfo["year"]
318 self.updateMusicInformation( sArtist, sTitle, sAlbum, sYear, sGenre, clear = True )
320 self.updateMusicInformation()
322 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
323 self.updateSingleMusicInformation("artist", artist, clear)
324 self.updateSingleMusicInformation("title", title, clear)
325 self.updateSingleMusicInformation("album", album, clear)
326 self.updateSingleMusicInformation("year", year, clear)
327 self.updateSingleMusicInformation("genre", genre, clear)
329 def updateSingleMusicInformation(self, name, info, clear):
330 if info != "" or clear:
331 if self[name].getText() != info:
332 self[name].setText(info)
335 self.lefttimer = True
336 self.leftKeyTimer.start(1000)
339 self.righttimer = True
340 self.rightKeyTimer.start(1000)
344 self.leftKeyTimer.stop()
345 self.lefttimer = False
346 self[self.currList].pageUp()
347 self.updateCurrentInfo()
351 self.rightKeyTimer.stop()
352 self.righttimer = False
353 self[self.currList].pageDown()
354 self.updateCurrentInfo()
356 def leftTimerFire(self):
357 self.leftKeyTimer.stop()
358 self.lefttimer = False
359 self.switchToFileList()
361 def rightTimerFire(self):
362 self.rightKeyTimer.stop()
363 self.righttimer = False
364 self.switchToPlayList()
366 def switchToFileList(self):
367 self.currList = "filelist"
368 self.filelist.selectionEnabled(1)
369 self.playlist.selectionEnabled(0)
370 self.updateCurrentInfo()
372 def switchToPlayList(self):
373 if len(self.playlist) != 0:
374 self.currList = "playlist"
375 self.filelist.selectionEnabled(0)
376 self.playlist.selectionEnabled(1)
377 self.updateCurrentInfo()
380 self[self.currList].up()
381 self.updateCurrentInfo()
384 self[self.currList].down()
385 self.updateCurrentInfo()
387 def showAfterSeek(self):
390 def showAfterCuesheetOperation(self):
393 def hideAfterResume(self):
396 def getIdentifier(self, ref):
401 return text.split('/')[-1]
403 # FIXME: maybe this code can be optimized
404 def updateCurrentInfo(self):
406 if self.currList == "filelist":
407 idx = self.filelist.getSelectionIndex()
408 r = self.filelist.list[idx]
415 self.summaries.setText(text,1)
418 if idx < len(self.filelist.list):
419 r = self.filelist.list[idx]
423 self.summaries.setText(text,3)
425 self.summaries.setText(" ",3)
428 if idx < len(self.filelist.list):
429 r = self.filelist.list[idx]
433 self.summaries.setText(text,4)
435 self.summaries.setText(" ",4)
438 if not self.filelist.canDescent():
439 r = self.filelist.getServiceRef()
443 self["currenttext"].setText(os_path.basename(text))
445 if self.currList == "playlist":
446 t = self.playlist.getSelection()
449 #display current selected entry on LCD
450 text = self.getIdentifier(t)
451 self.summaries.setText(text,1)
452 self["currenttext"].setText(text)
453 idx = self.playlist.getSelectionIndex()
455 if idx < len(self.playlist):
456 currref = self.playlist.getServiceRefList()[idx]
457 text = self.getIdentifier(currref)
458 self.summaries.setText(text,3)
460 self.summaries.setText(" ",3)
463 if idx < len(self.playlist):
464 currref = self.playlist.getServiceRefList()[idx]
465 text = self.getIdentifier(currref)
466 self.summaries.setText(text,4)
468 self.summaries.setText(" ",4)
471 if self.currList == "filelist":
472 if self.filelist.canDescent():
473 self.filelist.descent()
474 self.updateCurrentInfo()
478 if self.currList == "playlist":
479 selection = self["playlist"].getSelection()
480 self.changeEntry(self.playlist.getSelectionIndex())
484 if len(self.cdAudioTrackFiles):
485 menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
486 if self.currList == "filelist":
487 if self.filelist.canDescent():
488 menu.append((_("add directory to playlist"), "copydir"))
490 menu.append((_("add files to playlist"), "copyfiles"))
491 menu.append((_("switch to playlist"), "playlist"))
492 if config.usage.setup_level.index >= 1: # intermediate+
493 menu.append((_("delete file"), "deletefile"))
495 menu.append((_("switch to filelist"), "filelist"))
496 menu.append((_("clear playlist"), "clear"))
497 menu.append((_("Delete entry"), "deleteentry"))
498 if config.usage.setup_level.index >= 1: # intermediate+
499 menu.append((_("shuffle playlist"), "shuffle"))
500 menu.append((_("hide player"), "hide"));
501 menu.append((_("load playlist"), "loadplaylist"));
502 if config.usage.setup_level.index >= 1: # intermediate+
503 menu.append((_("save playlist"), "saveplaylist"));
504 menu.append((_("delete saved playlist"), "deleteplaylist"));
505 menu.append((_("Edit settings"), "settings"))
506 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
508 def menuCallback(self, choice):
512 if choice[1] == "copydir":
513 self.copyDirectory(self.filelist.getSelection()[0])
514 elif choice[1] == "copyfiles":
516 self.playlist.clear()
517 self.isAudioCD = False
518 self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
519 self.playServiceRefEntry(self.filelist.getServiceRef())
520 elif choice[1] == "playlist":
521 self.switchToPlayList()
522 elif choice[1] == "filelist":
523 self.switchToFileList()
524 elif choice[1] == "deleteentry":
525 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
528 elif choice[1] == "clear":
529 self.clear_playlist()
530 elif choice[1] == "hide":
532 elif choice[1] == "saveplaylist":
534 elif choice[1] == "loadplaylist":
536 elif choice[1] == "deleteplaylist":
537 self.delete_saved_playlist()
538 elif choice[1] == "shuffle":
539 self.playlist.PlayListShuffle()
540 elif choice[1] == "deletefile":
542 elif choice[1] == "settings":
543 self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self)
544 elif choice[1] == "audiocd":
547 def playAudioCD(self):
548 from enigma import eServiceReference
549 from Plugins.Extensions.CDInfo.plugin import Query
551 if len(self.cdAudioTrackFiles):
552 self.playlist.clear()
553 self.savePlaylistOnExit = False
554 self.isAudioCD = True
555 for file in self.cdAudioTrackFiles:
556 ref = eServiceReference(4097, 0, file)
557 self.playlist.addFile(ref)
561 self.switchToPlayList()
563 def applySettings(self):
564 self.savePlaylistOnExit = config.mediaplayer.savePlaylistOnExit.getValue()
565 if config.mediaplayer.repeat.getValue() == True:
566 self["repeat"].setPixmapNum(1)
568 self["repeat"].setPixmapNum(0)
570 def showEventInformation(self):
571 from Screens.EventView import EventViewSimple
572 from ServiceReference import ServiceReference
573 evt = self[self.currList].getCurrentEvent()
575 self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
577 # also works on filelist (?)
578 def getCurrent(self):
579 return self["playlist"].getCurrent()
581 def deletePlaylistEntry(self):
582 if self.currList == "playlist":
583 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
587 def skip_listbegin(self):
588 if self.currList == "filelist":
589 self.filelist.moveToIndex(0)
591 self.playlist.moveToIndex(0)
592 self.updateCurrentInfo()
594 def skip_listend(self):
595 if self.currList == "filelist":
596 idx = len(self.filelist.list)
597 self.filelist.moveToIndex(idx - 1)
599 self.playlist.moveToIndex(len(self.playlist)-1)
600 self.updateCurrentInfo()
602 def save_playlist(self):
603 self.session.openWithCallback(self.save_playlist2,InputBox, title=_("Please enter filename (empty = use current date)"),windowTitle = _("Save Playlist"))
605 def save_playlist2(self, name):
609 name = strftime("%y%m%d_%H%M%S")
611 self.playlistIOInternal.clear()
612 for x in self.playlist.list:
613 self.playlistIOInternal.addService(ServiceReference(x[0]))
614 self.playlistIOInternal.save(resolveFilename(SCOPE_PLAYLIST) + name)
616 def load_playlist(self):
618 playlistdir = resolveFilename(SCOPE_PLAYLIST)
620 for i in os_listdir(playlistdir):
621 listpath.append((i,playlistdir + i))
623 print "Error while scanning subdirs ",e
624 self.session.openWithCallback(self.PlaylistSelected, ChoiceBox, title=_("Please select a playlist..."), list = listpath)
626 def PlaylistSelected(self,path):
628 self.clear_playlist()
629 extension = path[0].rsplit('.',1)[-1]
630 if self.playlistparsers.has_key(extension):
631 playlist = self.playlistparsers[extension]()
632 list = playlist.open(path[1])
634 self.playlist.addFile(x.ref)
635 self.playlist.updateList()
637 def delete_saved_playlist(self):
639 playlistdir = resolveFilename(SCOPE_PLAYLIST)
641 for i in os_listdir(playlistdir):
642 listpath.append((i,playlistdir + i))
644 print "Error while scanning subdirs ",e
645 self.session.openWithCallback(self.DeletePlaylistSelected, ChoiceBox, title=_("Please select a playlist to delete..."), list = listpath)
647 def DeletePlaylistSelected(self,path):
649 self.delname = path[1]
650 self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (path[1]))
652 def deleteConfirmed(self, confirmed):
655 os_remove(self.delname)
657 print "delete failed:", e
658 self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
660 def clear_playlist(self):
661 self.isAudioCD = False
663 self.playlist.clear()
664 self.switchToFileList()
666 def copyDirectory(self, directory, recursive = True):
667 print "copyDirectory", directory
669 print "refusing to operate on /"
671 filelist = FileList(directory, useServiceRef = True, showMountpoints = False, isTop = True)
673 for x in filelist.getFileList():
674 if x[0][1] == True: #isDir
676 if x[0][0] != directory:
677 self.copyDirectory(x[0][0])
678 elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097:
679 self.playlist.addFile(x[0][0])
680 self.playlist.updateList()
682 def deleteFile(self):
683 if self.currList == "filelist":
684 self.service = self.filelist.getServiceRef()
686 self.service = self.playlist.getSelection()
687 if self.service is None:
689 if self.service.type != 4098 and self.session.nav.getCurrentlyPlayingServiceReference() is not None:
690 if self.service == self.session.nav.getCurrentlyPlayingServiceReference():
693 serviceHandler = eServiceCenter.getInstance()
694 offline = serviceHandler.offlineOperations(self.service)
695 info = serviceHandler.info(self.service)
696 name = info and info.getName(self.service)
698 if offline is not None:
700 if not offline.deleteFromDisk(1):
703 self.session.openWithCallback(self.deleteConfirmed_offline, MessageBox, _("Do you really want to delete %s?") % (name))
705 self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)
707 def deleteConfirmed_offline(self, confirmed):
709 serviceHandler = eServiceCenter.getInstance()
710 offline = serviceHandler.offlineOperations(self.service)
712 if offline is not None:
714 if not offline.deleteFromDisk(0):
717 self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
719 self.removeListEntry()
721 def removeListEntry(self):
722 currdir = self.filelist.getCurrentDirectory()
723 self.filelist.changeDir(currdir)
728 if len(self.playlist) > 0:
729 for x in self.playlist.list:
730 if self.service == x[0]:
731 self.playlist.deleteFile(index)
735 self.playlist.updateList()
736 if self.currList == "playlist":
737 if len(self.playlist) == 0:
738 self.switchToFileList()
741 if self.filelist.getServiceRef().type == 4098: # playlist
742 ServiceRef = self.filelist.getServiceRef()
743 extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:]
744 if self.playlistparsers.has_key(extension):
745 playlist = self.playlistparsers[extension]()
746 list = playlist.open(ServiceRef.getPath())
748 self.playlist.addFile(x.ref)
749 self.playlist.updateList()
751 self.playlist.addFile(self.filelist.getServiceRef())
752 self.playlist.updateList()
753 if len(self.playlist) == 1:
756 def addPlaylistParser(self, parser, extension):
757 self.playlistparsers[extension] = parser
760 next = self.playlist.getCurrentIndex() + 1
761 if next < len(self.playlist):
762 self.changeEntry(next)
763 elif ( len(self.playlist) > 0 ) and ( config.mediaplayer.repeat.getValue() == True ):
767 def nextMarkOrEntry(self):
768 if not self.jumpPreviousNextMark(lambda x: x):
769 next = self.playlist.getCurrentIndex() + 1
770 if next < len(self.playlist):
771 self.changeEntry(next)
775 def previousMarkOrEntry(self):
776 if not self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True):
777 next = self.playlist.getCurrentIndex() - 1
779 self.changeEntry(next)
781 def deleteEntry(self):
782 self.playlist.deleteFile(self.playlist.getSelectionIndex())
783 self.playlist.updateList()
784 if len(self.playlist) == 0:
785 self.switchToFileList()
787 def changeEntry(self, index):
788 self.playlist.setCurrentPlaying(index)
791 def playServiceRefEntry(self, serviceref):
792 serviceRefList = self.playlist.getServiceRefList()
793 for count in range(len(serviceRefList)):
794 if serviceRefList[count] == serviceref:
795 self.changeEntry(count)
798 def xplayEntry(self):
799 if self.currList == "playlist":
803 self.playlist.clear()
804 self.isAudioCD = False
805 sel = self.filelist.getSelection()
807 if sel[1]: # can descent
808 # add directory to playlist
809 self.copyDirectory(sel[0])
811 # add files to playlist
812 self.copyDirectory(os_path.dirname(sel[0].getPath()) + "/", recursive = False)
813 if len(self.playlist) > 0:
817 if len(self.playlist.getServiceRefList()):
818 audio_extensions = (".mp2", ".mp3", ".wav", ".ogg", "flac", "m4a")
819 needsInfoUpdate = False
820 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
821 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
822 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
823 info = eServiceCenter.getInstance().info(currref)
824 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
825 self["title"].setText(description)
826 # display just playing musik on LCD
827 idx = self.playlist.getCurrentIndex()
828 currref = self.playlist.getServiceRefList()[idx]
829 text = self.getIdentifier(currref)
831 ext = text[-4:].lower()
833 # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead
834 if ext not in audio_extensions and not self.isAudioCD:
837 needsInfoUpdate = True
838 self.summaries.setText(text,1)
840 # get the next two entries
842 if idx < len(self.playlist):
843 currref = self.playlist.getServiceRefList()[idx]
844 text = self.getIdentifier(currref)
845 self.summaries.setText(text,3)
847 self.summaries.setText(" ",3)
850 if idx < len(self.playlist):
851 currref = self.playlist.getServiceRefList()[idx]
852 text = self.getIdentifier(currref)
853 self.summaries.setText(text,4)
855 self.summaries.setText(" ",4)
857 idx = self.playlist.getCurrentIndex()
858 currref = self.playlist.getServiceRefList()[idx]
859 text = currref.getPath()
860 ext = text[-4:].lower()
861 if ext not in audio_extensions and not self.isAudioCD:
864 needsInfoUpdate = True
866 self.unPauseService()
867 if needsInfoUpdate == True:
868 path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath()
869 self["coverArt"].updateCoverArt(path)
871 self["coverArt"].showDefaultCover()
872 self.readTitleInformation()
874 def updatedSeekState(self):
875 if self.seekstate == self.SEEK_STATE_PAUSE:
876 self.playlist.pauseFile()
877 elif self.seekstate == self.SEEK_STATE_PLAY:
878 self.playlist.playFile()
879 elif self.isStateForward(self.seekstate):
880 self.playlist.forwardFile()
881 elif self.isStateBackward(self.seekstate):
882 self.playlist.rewindFile()
884 def pauseEntry(self):
886 if self.seekstate == self.SEEK_STATE_PAUSE:
892 self.playlist.stopFile()
893 self.session.nav.playService(None)
894 self.updateMusicInformation(clear=True)
897 def unPauseService(self):
898 self.setSeekState(self.SEEK_STATE_PLAY)
900 def subtitleSelection(self):
901 from Screens.Subtitles import Subtitles
902 self.session.open(Subtitles)
904 def hotplugCB(self, dev, media_state):
905 if dev == harddiskmanager.getCD():
906 if media_state == "1":
907 from Components.Scanner import scanDevice
908 devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
909 self.cdAudioTrackFiles = []
910 res = scanDevice(devpath)
911 list = [ (r.description, r, res[r], self.session) for r in res ]
913 (desc, scanner, files, session) = list[0]
915 if file.mimetype == "audio/x-cda":
916 self.cdAudioTrackFiles.append(file.path)
918 self.cdAudioTrackFiles = []
920 self.clear_playlist()
922 class MediaPlayerLCDScreen(Screen):
924 <screen position="0,0" size="132,64" title="LCD Text">
925 <widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
926 <widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
927 <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
930 def __init__(self, session, parent):
931 Screen.__init__(self, session)
932 self["text1"] = Label("Mediaplayer")
933 self["text3"] = Label("")
934 self["text4"] = Label("")
936 def setText(self, text, line):
938 if text[-4:] == ".mp3":
941 text = text + textleer*10
943 self["text1"].setText(text)
945 self["text3"].setText(text)
947 self["text4"].setText(text)
949 def main(session, **kwargs):
950 session.open(MediaPlayer)
952 def menu(menuid, **kwargs):
953 if menuid == "mainmenu":
954 return [(_("Media player"), main, "media_player", 45)]
957 def filescan_open(list, session, **kwargs):
958 from enigma import eServiceReference
960 mp = session.open(MediaPlayer)
962 mp.savePlaylistOnExit = False
965 if file.mimetype == "video/MP2T":
969 ref = eServiceReference(stype, 0, file.path)
970 mp.playlist.addFile(ref)
973 mp.switchToPlayList()
975 def audioCD_open(list, session, **kwargs):
976 from enigma import eServiceReference
978 mp = session.open(MediaPlayer)
979 mp.cdAudioTrackFiles = []
981 mp.cdAudioTrackFiles.append(file.path)
984 def filescan(**kwargs):
985 from Components.Scanner import Scanner, ScanPath
987 Scanner(mimetypes = ["video/mpeg", "video/MP2T", "video/x-msvideo"],
990 ScanPath(path = "", with_subdirs = False),
993 description = _("View Movies..."),
994 openfnc = filescan_open,
996 Scanner(mimetypes = ["video/x-vcd"],
999 ScanPath(path = "mpegav", with_subdirs = False),
1000 ScanPath(path = "MPEGAV", with_subdirs = False),
1003 description = _("View Video CD..."),
1004 openfnc = filescan_open,
1006 Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg", "audio/x-flac"],
1009 ScanPath(path = "", with_subdirs = False),
1012 description = _("Play Music..."),
1013 openfnc = filescan_open,
1016 from Plugins.Extensions.CDInfo.plugin import Query
1018 Scanner(mimetypes = ["audio/x-cda"],
1021 ScanPath(path = "", with_subdirs = False),
1024 description = _("Play Audio-CD..."),
1025 openfnc = audioCD_open,
1031 from Plugins.Plugin import PluginDescriptor
1032 def Plugins(**kwargs):
1034 PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu),
1035 PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)