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()
287 if self.currList == "playlist":
288 selection = self["playlist"].getSelection()
289 self.changeEntry(self.playlist.getSelectionIndex())
291 def keyNumberGlobal(self, number):
292 if number == 5: # enable seeking
293 if self.seek_target is None:
294 (len, pos) = self["PositionGauge"].get()
296 if self.isSeekable() and len != 0:
297 self.seek_target = pos
299 self.seekAbsolute(self.seek_target)
300 self.seek_target = None
301 elif number == 2: # abort
302 self.seek_target = None
303 elif (number == 4 or number == 6) and self.seek_target is not None:
304 (len, pos) = self["PositionGauge"].get()
307 self.seek_target -= len / 10
309 self.seek_target += len / 10
311 if self.seek_target > len * 9 / 10:
312 self.seek_target = len * 9 / 10
314 if self.seek_target < 0:
317 print "seek target is now", self.seek_target
321 def updateSeek(self):
322 if self.seek_target is None:
323 self["PositionGauge"].seek_pointer = False
325 self["PositionGauge"].seek_pointer = True
326 self["PositionGauge"].seek_pointer_position = self.seek_target
331 if self.currList == "filelist":
332 menu.append((_("switch to playlist"), "playlist"))
333 if self.filelist.canDescent():
334 menu.append((_("add directory to playlist"), "copydir"))
336 menu.append((_("add file to playlist"), "copy"))
338 menu.append((_("switch to filelist"), "filelist"))
339 menu.append((_("delete"), "delete"))
340 menu.append((_("clear playlist"), "clear"))
341 menu.append((_("hide player"), "hide"));
342 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
344 def menuCallback(self, choice):
348 if choice[1] == "copydir":
349 self.copyDirectory(self.filelist.getSelection()[0])
350 elif choice[1] == "copy":
352 elif choice[1] == "playlist":
353 self.switchToPlayList()
354 elif choice[1] == "filelist":
355 self.switchToFileList()
356 elif choice[1] == "delete":
357 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
360 elif choice[1] == "clear":
362 self.playlist.clear()
363 self.switchToFileList()
364 elif choice[1] == "hide":
367 def copyDirectory(self, directory):
368 filelist = FileList(directory, useServiceRef = True, isTop = True)
370 for x in filelist.getFileList():
371 if x[0][1] == True: #isDir
372 self.copyDirectory(x[0][0])
374 self.playlist.addFile(x[0][0])
375 self.playlist.updateList()
381 if self.filelist.getServiceRef().type == 4098: # playlist
383 list.append((_("Add files to playlist"), (self.ADDPLAYLIST, self.filelist.getServiceRef())))
384 list.append((_("Replace current playlist"), (self.REPLACEPLAYLIST, self.filelist.getServiceRef())))
385 self.session.openWithCallback(self.playlistCallback, ChoiceBox, title=_("You selected a playlist"), list = list)
387 self.playlist.addFile(self.filelist.getServiceRef())
388 self.playlist.updateList()
389 if len(self.playlist) == 1:
392 def addPlaylistParser(self, parser, extension):
393 self.playlistparsers[extension] = parser
395 def playlistCallback(self, answer):
396 if answer is not None:
397 extension = answer[1][1].getPath()[answer[1][1].getPath().rfind('.') + 1:]
398 print "extension:", extension
399 if self.playlistparsers.has_key(extension):
400 playlist = self.playlistparsers[extension]()
401 if answer[1][0] == self.REPLACEPLAYLIST:
403 self.playlist.clear()
404 self.switchToFileList()
405 if answer[1][0] == self.REPLACEPLAYLIST or answer[1][0] == self.ADDPLAYLIST:
406 list = playlist.open(answer[1][1].getPath())
408 self.playlist.addFile(x.ref)
412 next = self.playlist.getCurrentIndex() + 1
413 if next < len(self.playlist):
414 self.changeEntry(next)
416 def previousEntry(self):
417 next = self.playlist.getCurrentIndex() - 1
419 self.changeEntry(next)
421 def deleteEntry(self):
422 self.playlist.deleteFile(self.playlist.getSelectionIndex())
423 self.playlist.updateList()
424 if len(self.playlist) == 0:
425 self.switchToFileList()
427 def changeEntry(self, index):
428 self.playlist.setCurrentPlaying(index)
432 if len(self.playlist.getServiceRefList()):
433 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
434 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
435 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
436 info = eServiceCenter.getInstance().info(currref)
437 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
438 self["title"].setText(description)
439 self.unPauseService()
441 def updatedSeekState(self):
442 if self.seekstate == self.SEEK_STATE_PAUSE:
443 self.playlist.pauseFile()
444 elif self.seekstate == self.SEEK_STATE_PLAY:
445 self.playlist.playFile()
446 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
447 self.SEEK_STATE_FF_4X,
448 self.SEEK_STATE_FF_8X,
449 self.SEEK_STATE_FF_32X,
450 self.SEEK_STATE_FF_64X,
451 self.SEEK_STATE_FF_128X):
452 self.playlist.forwardFile()
453 elif self.seekstate in ( self.SEEK_STATE_BACK_16X,
454 self.SEEK_STATE_BACK_32X,
455 self.SEEK_STATE_BACK_64X,
456 self.SEEK_STATE_BACK_128X,):
457 self.playlist.rewindFile()
459 def pauseEntry(self):
463 self.playlist.stopFile()
464 self.session.nav.playService(None)
465 self.updateMusicInformation(clear=True)
467 def unPauseService(self):
468 self.setSeekState(self.SEEK_STATE_PLAY)