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 self.filelist = FileList(resolveFilename(SCOPE_MEDIA), matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True)
38 self["filelist"] = self.filelist
40 self.playlist = PlayList()
41 self["playlist"] = self.playlist
43 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
45 self["currenttext"] = Label("")
47 self["artisttext"] = Label(_("Artist:"))
48 self["artist"] = Label("")
49 self["titletext"] = Label(_("Title:"))
50 self["title"] = Label("")
51 self["albumtext"] = Label(_("Album:"))
52 self["album"] = Label("")
53 self["yeartext"] = Label(_("Year:"))
54 self["year"] = Label("")
55 self["genretext"] = Label(_("Genre:"))
56 self["genre"] = Label("")
57 self["coverArt"] = Pixmap()
59 self.seek_target = None
61 #self["text"] = Input("1234", maxSize=True, type=Input.NUMBER)
63 class MoviePlayerActionMap(NumberActionMap):
64 def __init__(self, player, contexts = [ ], actions = { }, prio=0):
65 NumberActionMap.__init__(self, contexts, actions, prio)
68 def action(self, contexts, action):
70 return NumberActionMap.action(self, contexts, action)
72 self["actions"] = MoviePlayerActionMap(self, ["OkCancelActions", "DirectionActions", "NumberActions", "MediaPlayerSeekActions"],
77 "right": self.rightDown,
78 "rightRepeated": self.doNothing,
79 "rightUp": self.rightUp,
80 "left": self.leftDown,
81 "leftRepeated": self.doNothing,
82 "leftUp": self.leftUp,
85 "upRepeated": self.up,
87 "downRepeated": self.down,
89 "play": self.playEntry,
90 "pause": self.pauseEntry,
91 "stop": self.stopEntry,
93 "previous": self.previousEntry,
94 "next": self.nextEntry,
96 "menu": self.showMenu,
98 "1": self.keyNumberGlobal,
99 "2": self.keyNumberGlobal,
100 "3": self.keyNumberGlobal,
101 "4": self.keyNumberGlobal,
102 "5": self.keyNumberGlobal,
103 "6": self.keyNumberGlobal,
104 "7": self.keyNumberGlobal,
105 "8": self.keyNumberGlobal,
106 "9": self.keyNumberGlobal,
107 "0": self.keyNumberGlobal
110 InfoBarSeek.__init__(self)
112 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
114 #iPlayableService.evStart: self.__serviceStarted,
115 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
117 iPlayableService.evEOF: self.__evEOF,
118 # iPlayableService.evSOF: self.__evSOF,
121 self.onClose.append(self.delMPTimer)
122 self.onClose.append(self.__onClose)
124 self.righttimer = False
125 self.rightKeyTimer = eTimer()
126 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
128 self.lefttimer = False
129 self.leftKeyTimer = eTimer()
130 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
132 self.infoTimer = eTimer()
133 self.infoTimer.timeout.get().append(self.infoTimerFire)
134 self.infoTimer.start(500)
136 self.currList = "filelist"
138 self.coverArtFileName = ""
140 self.playlistIOInternal = PlaylistIOInternal()
141 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
144 self.playlist.addFile(x.ref)
145 self.playlist.updateList()
151 self.playlistIOInternal.clear()
152 for x in self.playlist.list:
153 self.playlistIOInternal.addService(ServiceReference(x[0]))
154 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
157 def checkSkipShowHideLock(self):
158 self.updatedSeekState()
164 self.session.nav.playService(self.oldService)
166 def delMPTimer(self):
167 del self.rightKeyTimer
168 del self.leftKeyTimer
171 def infoTimerFire(self):
172 currPlay = self.session.nav.getCurrentService()
173 if currPlay is not None:
174 self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
175 title = currPlay.info().getInfoString(iServiceInformation.sTitle),
176 album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
177 genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
179 self.updateCoverArtPixmap( currPlay.info().getName() )
181 self.updateMusicInformation()
182 self.updateCoverArtPixmap( "" )
184 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
185 self.updateSingleMusicInformation("artist", artist, clear)
186 self.updateSingleMusicInformation("title", title, clear)
187 self.updateSingleMusicInformation("album", album, clear)
188 self.updateSingleMusicInformation("year", year, clear)
189 self.updateSingleMusicInformation("genre", genre, clear)
191 def updateSingleMusicInformation(self, name, info, clear):
192 if info != "" or clear:
193 if self[name].getText() != info:
194 self[name].setText(info)
196 def updateCoverArtPixmap(self, currentServiceName):
197 filename = currentServiceName
198 # The "getName" usually adds something like "MP3 File:" infront of filename
199 # Get rid of this...by finding the first "/"
200 filename = filename[filename.find("/"):]
201 path = os.path.dirname(filename)
202 pngname = path + "/" + "folder.png"
203 if not os.path.exists(pngname):
204 pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png")
205 if self.coverArtFileName != pngname:
206 self.coverArtFileName = pngname
207 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
209 def fwdTimerFire(self):
210 self.fwdKeyTimer.stop()
211 self.fwdtimer = False
214 def rwdTimerFire(self):
215 self.rwdKeyTimer.stop()
216 self.rwdtimer = False
220 self.lefttimer = True
221 self.leftKeyTimer.start(1000)
224 self.righttimer = True
225 self.rightKeyTimer.start(1000)
229 self.leftKeyTimer.stop()
230 self.lefttimer = False
231 self[self.currList].pageUp()
235 self.rightKeyTimer.stop()
236 self.righttimer = False
237 self[self.currList].pageDown()
239 def leftTimerFire(self):
240 self.leftKeyTimer.stop()
241 self.lefttimer = False
242 self.switchToFileList()
244 def rightTimerFire(self):
245 self.rightKeyTimer.stop()
246 self.righttimer = False
247 self.switchToPlayList()
249 def switchToFileList(self):
250 self.currList = "filelist"
251 self.filelist.selectionEnabled(1)
252 self.playlist.selectionEnabled(0)
253 self.updateCurrentInfo()
255 def switchToPlayList(self):
256 if len(self.playlist) != 0:
257 self.currList = "playlist"
258 self.filelist.selectionEnabled(0)
259 self.playlist.selectionEnabled(1)
260 self.updateCurrentInfo()
263 self[self.currList].up()
264 self.updateCurrentInfo()
267 self[self.currList].down()
268 self.updateCurrentInfo()
270 def updateCurrentInfo(self):
272 if self.currList == "filelist":
273 if not self.filelist.canDescent():
274 text = self.filelist.getServiceRef().getPath()
275 if self.currList == "playlist":
276 text = self.playlist.getSelection().getPath()
278 self["currenttext"].setText(os.path.basename(text))
281 if self.currList == "filelist":
282 if self.filelist.canDescent():
283 self.filelist.descent()
284 self.updateCurrentInfo()
286 self.playlist.clear()
287 self.copyDirectory(os.path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
288 self.playServiceRefEntry(self.filelist.getServiceRef())
290 if self.currList == "playlist":
291 selection = self["playlist"].getSelection()
292 self.changeEntry(self.playlist.getSelectionIndex())
294 def keyNumberGlobal(self, number):
295 if number == 5: # enable seeking
296 if self.seek_target is None:
297 (len, pos) = self["PositionGauge"].get()
299 if self.isSeekable() and len != 0:
300 self.seek_target = pos
302 self.seekAbsolute(self.seek_target)
303 self.seek_target = None
304 elif number == 2: # abort
305 self.seek_target = None
306 elif (number == 4 or number == 6) and self.seek_target is not None:
307 (len, pos) = self["PositionGauge"].get()
310 self.seek_target -= len / 10
312 self.seek_target += len / 10
314 if self.seek_target > len * 9 / 10:
315 self.seek_target = len * 9 / 10
317 if self.seek_target < 0:
320 print "seek target is now", self.seek_target
324 def updateSeek(self):
325 if self.seek_target is None:
326 self["PositionGauge"].seek_pointer = False
328 self["PositionGauge"].seek_pointer = True
329 self["PositionGauge"].seek_pointer_position = self.seek_target
334 if self.currList == "filelist":
335 menu.append((_("switch to playlist"), "playlist"))
336 if self.filelist.canDescent():
337 menu.append((_("add directory to playlist"), "copydir"))
339 menu.append((_("add file to playlist"), "copy"))
341 menu.append((_("switch to filelist"), "filelist"))
342 menu.append((_("delete"), "delete"))
343 menu.append((_("clear playlist"), "clear"))
344 menu.append((_("hide player"), "hide"));
345 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
347 def menuCallback(self, choice):
351 if choice[1] == "copydir":
352 self.copyDirectory(self.filelist.getSelection()[0])
353 elif choice[1] == "copy":
355 elif choice[1] == "playlist":
356 self.switchToPlayList()
357 elif choice[1] == "filelist":
358 self.switchToFileList()
359 elif choice[1] == "delete":
360 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
363 elif choice[1] == "clear":
365 self.playlist.clear()
366 self.switchToFileList()
367 elif choice[1] == "hide":
370 def copyDirectory(self, directory, recursive = True):
371 print "copyDirectory", directory
372 filelist = FileList(directory, useServiceRef = True, isTop = True)
374 for x in filelist.getFileList():
375 if x[0][1] == True: #isDir
377 self.copyDirectory(x[0][0])
379 self.playlist.addFile(x[0][0])
380 self.playlist.updateList()
386 if self.filelist.getServiceRef().type == 4098: # playlist
388 list.append((_("Add files to playlist"), (self.ADDPLAYLIST, self.filelist.getServiceRef())))
389 list.append((_("Replace current playlist"), (self.REPLACEPLAYLIST, self.filelist.getServiceRef())))
390 self.session.openWithCallback(self.playlistCallback, ChoiceBox, title=_("You selected a playlist"), list = list)
392 self.playlist.addFile(self.filelist.getServiceRef())
393 self.playlist.updateList()
394 if len(self.playlist) == 1:
397 def addPlaylistParser(self, parser, extension):
398 self.playlistparsers[extension] = parser
400 def playlistCallback(self, answer):
401 if answer is not None:
402 extension = answer[1][1].getPath()[answer[1][1].getPath().rfind('.') + 1:]
403 print "extension:", extension
404 if self.playlistparsers.has_key(extension):
405 playlist = self.playlistparsers[extension]()
406 if answer[1][0] == self.REPLACEPLAYLIST:
408 self.playlist.clear()
409 self.switchToFileList()
410 if answer[1][0] == self.REPLACEPLAYLIST or answer[1][0] == self.ADDPLAYLIST:
411 list = playlist.open(answer[1][1].getPath())
413 self.playlist.addFile(x.ref)
417 next = self.playlist.getCurrentIndex() + 1
418 if next < len(self.playlist):
419 self.changeEntry(next)
421 def previousEntry(self):
422 next = self.playlist.getCurrentIndex() - 1
424 self.changeEntry(next)
426 def deleteEntry(self):
427 self.playlist.deleteFile(self.playlist.getSelectionIndex())
428 self.playlist.updateList()
429 if len(self.playlist) == 0:
430 self.switchToFileList()
432 def changeEntry(self, index):
433 self.playlist.setCurrentPlaying(index)
436 def playServiceRefEntry(self, serviceref):
437 serviceRefList = self.playlist.getServiceRefList()
438 for count in range(len(serviceRefList)):
439 if serviceRefList[count] == serviceref:
440 self.changeEntry(count)
444 if len(self.playlist.getServiceRefList()):
445 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
446 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
447 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
448 info = eServiceCenter.getInstance().info(currref)
449 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
450 self["title"].setText(description)
451 self.unPauseService()
453 def updatedSeekState(self):
454 if self.seekstate == self.SEEK_STATE_PAUSE:
455 self.playlist.pauseFile()
456 elif self.seekstate == self.SEEK_STATE_PLAY:
457 self.playlist.playFile()
458 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
459 self.SEEK_STATE_FF_4X,
460 self.SEEK_STATE_FF_8X,
461 self.SEEK_STATE_FF_32X,
462 self.SEEK_STATE_FF_64X,
463 self.SEEK_STATE_FF_128X):
464 self.playlist.forwardFile()
465 elif self.seekstate in ( self.SEEK_STATE_BACK_16X,
466 self.SEEK_STATE_BACK_32X,
467 self.SEEK_STATE_BACK_64X,
468 self.SEEK_STATE_BACK_128X,):
469 self.playlist.rewindFile()
471 def pauseEntry(self):
475 self.playlist.stopFile()
476 self.session.nav.playService(None)
477 self.updateMusicInformation(clear=True)
479 def unPauseService(self):
480 self.setSeekState(self.SEEK_STATE_PLAY)