1 from enigma import eTimer, iPlayableService, eServiceCenter, iServiceInformation, eSize
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Components.ActionMap import NumberActionMap
5 from Components.Label import Label
6 from Components.Input import Input
7 from Components.GUIComponent import *
8 from Components.Pixmap import Pixmap
9 from Components.Label import Label
10 from Components.FileList import FileEntryComponent, FileList
11 from Components.MediaPlayer import PlayList, PlaylistEntryComponent
12 from Plugins.Plugin import PluginDescriptor
13 from Tools.Directories import resolveFilename, SCOPE_MEDIA, SCOPE_CONFIG, SCOPE_SKIN_IMAGE
14 from Components.ServicePosition import ServicePositionGauge
15 from Screens.ChoiceBox import ChoiceBox
16 from Components.ServiceEventTracker import ServiceEventTracker
17 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
18 from Screens.InfoBarGenerics import InfoBarSeek
19 from ServiceReference import ServiceReference
20 from Screens.ChoiceBox import ChoiceBox
24 class MediaPlayer(Screen, InfoBarSeek):
27 def __init__(self, session, args = None):
28 Screen.__init__(self, session)
29 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
30 self.session.nav.stopService()
32 self.playlistparsers = {}
33 self.addPlaylistParser(PlaylistIOM3U, "m3u")
34 self.addPlaylistParser(PlaylistIOPLS, "pls")
35 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
37 # 'None' is magic to start at the list of mountpoints
38 self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True)
39 self["filelist"] = self.filelist
41 self.playlist = PlayList()
42 self["playlist"] = self.playlist
44 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
46 self["currenttext"] = Label("")
48 self["artisttext"] = Label(_("Artist:"))
49 self["artist"] = Label("")
50 self["titletext"] = Label(_("Title:"))
51 self["title"] = Label("")
52 self["albumtext"] = Label(_("Album:"))
53 self["album"] = Label("")
54 self["yeartext"] = Label(_("Year:"))
55 self["year"] = Label("")
56 self["genretext"] = Label(_("Genre:"))
57 self["genre"] = Label("")
58 self["coverArt"] = Pixmap()
60 self.seek_target = None
62 #self["text"] = Input("1234", maxSize=True, type=Input.NUMBER)
64 class MoviePlayerActionMap(NumberActionMap):
65 def __init__(self, player, contexts = [ ], actions = { }, prio=0):
66 NumberActionMap.__init__(self, contexts, actions, prio)
69 def action(self, contexts, action):
71 return NumberActionMap.action(self, contexts, action)
73 self["actions"] = MoviePlayerActionMap(self, ["OkCancelActions", "DirectionActions", "NumberActions", "MediaPlayerSeekActions"],
78 "right": self.rightDown,
79 "rightRepeated": self.doNothing,
80 "rightUp": self.rightUp,
81 "left": self.leftDown,
82 "leftRepeated": self.doNothing,
83 "leftUp": self.leftUp,
86 "upRepeated": self.up,
88 "downRepeated": self.down,
90 "play": self.playEntry,
91 "pause": self.pauseEntry,
92 "stop": self.stopEntry,
94 "previous": self.previousEntry,
95 "next": self.nextEntry,
97 "menu": self.showMenu,
99 "1": self.keyNumberGlobal,
100 "2": self.keyNumberGlobal,
101 "3": self.keyNumberGlobal,
102 "4": self.keyNumberGlobal,
103 "5": self.keyNumberGlobal,
104 "6": self.keyNumberGlobal,
105 "7": self.keyNumberGlobal,
106 "8": self.keyNumberGlobal,
107 "9": self.keyNumberGlobal,
108 "0": self.keyNumberGlobal
111 InfoBarSeek.__init__(self)
113 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
115 #iPlayableService.evStart: self.__serviceStarted,
116 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
118 iPlayableService.evEOF: self.__evEOF,
119 # iPlayableService.evSOF: self.__evSOF,
122 self.onClose.append(self.delMPTimer)
123 self.onClose.append(self.__onClose)
125 self.righttimer = False
126 self.rightKeyTimer = eTimer()
127 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
129 self.lefttimer = False
130 self.leftKeyTimer = eTimer()
131 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
133 self.infoTimer = eTimer()
134 self.infoTimer.timeout.get().append(self.infoTimerFire)
135 self.infoTimer.start(500)
137 self.currList = "filelist"
139 self.coverArtFileName = ""
141 self.playlistIOInternal = PlaylistIOInternal()
142 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
145 self.playlist.addFile(x.ref)
146 self.playlist.updateList()
152 self.playlistIOInternal.clear()
153 for x in self.playlist.list:
154 self.playlistIOInternal.addService(ServiceReference(x[0]))
155 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
158 def checkSkipShowHideLock(self):
159 self.updatedSeekState()
165 self.session.nav.playService(self.oldService)
167 def delMPTimer(self):
168 del self.rightKeyTimer
169 del self.leftKeyTimer
172 def infoTimerFire(self):
173 currPlay = self.session.nav.getCurrentService()
174 if currPlay is not None:
175 self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
176 title = currPlay.info().getInfoString(iServiceInformation.sTitle),
177 album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
178 genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
180 self.updateCoverArtPixmap( currPlay.info().getName() )
182 self.updateMusicInformation()
183 self.updateCoverArtPixmap( "" )
185 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
186 self.updateSingleMusicInformation("artist", artist, clear)
187 self.updateSingleMusicInformation("title", title, clear)
188 self.updateSingleMusicInformation("album", album, clear)
189 self.updateSingleMusicInformation("year", year, clear)
190 self.updateSingleMusicInformation("genre", genre, clear)
192 def updateSingleMusicInformation(self, name, info, clear):
193 if info != "" or clear:
194 if self[name].getText() != info:
195 self[name].setText(info)
197 def updateCoverArtPixmap(self, currentServiceName):
198 filename = currentServiceName
199 # The "getName" usually adds something like "MP3 File:" infront of filename
200 # Get rid of this...by finding the first "/"
201 filename = filename[filename.find("/"):]
202 path = os.path.dirname(filename)
203 pngname = path + "/" + "folder.png"
204 if not os.path.exists(pngname):
205 pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png")
206 if self.coverArtFileName != pngname:
207 self.coverArtFileName = pngname
208 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
210 def fwdTimerFire(self):
211 self.fwdKeyTimer.stop()
212 self.fwdtimer = False
215 def rwdTimerFire(self):
216 self.rwdKeyTimer.stop()
217 self.rwdtimer = False
221 self.lefttimer = True
222 self.leftKeyTimer.start(1000)
225 self.righttimer = True
226 self.rightKeyTimer.start(1000)
230 self.leftKeyTimer.stop()
231 self.lefttimer = False
232 self[self.currList].pageUp()
236 self.rightKeyTimer.stop()
237 self.righttimer = False
238 self[self.currList].pageDown()
240 def leftTimerFire(self):
241 self.leftKeyTimer.stop()
242 self.lefttimer = False
243 self.switchToFileList()
245 def rightTimerFire(self):
246 self.rightKeyTimer.stop()
247 self.righttimer = False
248 self.switchToPlayList()
250 def switchToFileList(self):
251 self.currList = "filelist"
252 self.filelist.selectionEnabled(1)
253 self.playlist.selectionEnabled(0)
254 self.updateCurrentInfo()
256 def switchToPlayList(self):
257 if len(self.playlist) != 0:
258 self.currList = "playlist"
259 self.filelist.selectionEnabled(0)
260 self.playlist.selectionEnabled(1)
261 self.updateCurrentInfo()
264 self[self.currList].up()
265 self.updateCurrentInfo()
268 self[self.currList].down()
269 self.updateCurrentInfo()
271 def updateCurrentInfo(self):
273 if self.currList == "filelist":
274 if not self.filelist.canDescent():
275 r = self.filelist.getServiceRef()
279 if self.currList == "playlist":
280 t = self.playlist.getSelection()
285 self["currenttext"].setText(os.path.basename(text))
288 if self.currList == "filelist":
289 if self.filelist.canDescent():
290 self.filelist.descent()
291 self.updateCurrentInfo()
294 self.playlist.clear()
295 self.copyDirectory(os.path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
296 self.playServiceRefEntry(self.filelist.getServiceRef())
298 if self.currList == "playlist":
299 selection = self["playlist"].getSelection()
300 self.changeEntry(self.playlist.getSelectionIndex())
302 def keyNumberGlobal(self, number):
303 if number == 5: # enable seeking
304 if self.seek_target is None:
305 (len, pos) = self["PositionGauge"].get()
307 if self.isSeekable() and len != 0:
308 self.seek_target = pos
310 self.seekAbsolute(self.seek_target)
311 self.seek_target = None
312 elif number == 2: # abort
313 self.seek_target = None
314 elif (number == 4 or number == 6) and self.seek_target is not None:
315 (len, pos) = self["PositionGauge"].get()
318 self.seek_target -= len / 10
320 self.seek_target += len / 10
322 if self.seek_target > len * 9 / 10:
323 self.seek_target = len * 9 / 10
325 if self.seek_target < 0:
328 print "seek target is now", self.seek_target
332 def updateSeek(self):
333 if self.seek_target is None:
334 self["PositionGauge"].seek_pointer = False
336 self["PositionGauge"].seek_pointer = True
337 self["PositionGauge"].seek_pointer_position = self.seek_target
342 if self.currList == "filelist":
343 menu.append((_("switch to playlist"), "playlist"))
344 if self.filelist.canDescent():
345 menu.append((_("add directory to playlist"), "copydir"))
347 menu.append((_("add file to playlist"), "copy"))
349 menu.append((_("switch to filelist"), "filelist"))
350 menu.append((_("delete"), "delete"))
351 menu.append((_("clear playlist"), "clear"))
352 menu.append((_("hide player"), "hide"));
353 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
355 def menuCallback(self, choice):
359 if choice[1] == "copydir":
360 self.copyDirectory(self.filelist.getSelection()[0])
361 elif choice[1] == "copy":
363 elif choice[1] == "playlist":
364 self.switchToPlayList()
365 elif choice[1] == "filelist":
366 self.switchToFileList()
367 elif choice[1] == "delete":
368 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
371 elif choice[1] == "clear":
373 self.playlist.clear()
374 self.switchToFileList()
375 elif choice[1] == "hide":
378 def copyDirectory(self, directory, recursive = True):
379 print "copyDirectory", directory
380 filelist = FileList(directory, useServiceRef = True, isTop = True)
382 for x in filelist.getFileList():
383 if x[0][1] == True: #isDir
385 self.copyDirectory(x[0][0])
387 self.playlist.addFile(x[0][0])
388 self.playlist.updateList()
394 if self.filelist.getServiceRef().type == 4098: # playlist
396 list.append((_("Add files to playlist"), (self.ADDPLAYLIST, self.filelist.getServiceRef())))
397 list.append((_("Replace current playlist"), (self.REPLACEPLAYLIST, self.filelist.getServiceRef())))
398 self.session.openWithCallback(self.playlistCallback, ChoiceBox, title=_("You selected a playlist"), list = list)
400 self.playlist.addFile(self.filelist.getServiceRef())
401 self.playlist.updateList()
402 if len(self.playlist) == 1:
405 def addPlaylistParser(self, parser, extension):
406 self.playlistparsers[extension] = parser
408 def playlistCallback(self, answer):
409 if answer is not None:
410 extension = answer[1][1].getPath()[answer[1][1].getPath().rfind('.') + 1:]
411 print "extension:", extension
412 if self.playlistparsers.has_key(extension):
413 playlist = self.playlistparsers[extension]()
414 if answer[1][0] == self.REPLACEPLAYLIST:
416 self.playlist.clear()
417 self.switchToFileList()
418 if answer[1][0] == self.REPLACEPLAYLIST or answer[1][0] == self.ADDPLAYLIST:
419 list = playlist.open(answer[1][1].getPath())
421 self.playlist.addFile(x.ref)
425 next = self.playlist.getCurrentIndex() + 1
426 if next < len(self.playlist):
427 self.changeEntry(next)
429 def previousEntry(self):
430 next = self.playlist.getCurrentIndex() - 1
432 self.changeEntry(next)
434 def deleteEntry(self):
435 self.playlist.deleteFile(self.playlist.getSelectionIndex())
436 self.playlist.updateList()
437 if len(self.playlist) == 0:
438 self.switchToFileList()
440 def changeEntry(self, index):
441 self.playlist.setCurrentPlaying(index)
444 def playServiceRefEntry(self, serviceref):
445 serviceRefList = self.playlist.getServiceRefList()
446 for count in range(len(serviceRefList)):
447 if serviceRefList[count] == serviceref:
448 self.changeEntry(count)
452 if len(self.playlist.getServiceRefList()):
453 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
454 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
455 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
456 info = eServiceCenter.getInstance().info(currref)
457 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
458 self["title"].setText(description)
459 self.unPauseService()
461 def updatedSeekState(self):
462 if self.seekstate == self.SEEK_STATE_PAUSE:
463 self.playlist.pauseFile()
464 elif self.seekstate == self.SEEK_STATE_PLAY:
465 self.playlist.playFile()
466 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
467 self.SEEK_STATE_FF_4X,
468 self.SEEK_STATE_FF_8X,
469 self.SEEK_STATE_FF_32X,
470 self.SEEK_STATE_FF_64X,
471 self.SEEK_STATE_FF_128X):
472 self.playlist.forwardFile()
473 elif self.seekstate in ( self.SEEK_STATE_BACK_16X,
474 self.SEEK_STATE_BACK_32X,
475 self.SEEK_STATE_BACK_64X,
476 self.SEEK_STATE_BACK_128X,):
477 self.playlist.rewindFile()
479 def pauseEntry(self):
483 self.playlist.stopFile()
484 self.session.nav.playService(None)
485 self.updateMusicInformation(clear=True)
487 def unPauseService(self):
488 self.setSeekState(self.SEEK_STATE_PLAY)