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["text"] = Input("1234", maxSize=True, type=Input.NUMBER)
61 class MoviePlayerActionMap(NumberActionMap):
62 def __init__(self, player, contexts = [ ], actions = { }, prio=0):
63 NumberActionMap.__init__(self, contexts, actions, prio)
66 def action(self, contexts, action):
68 return NumberActionMap.action(self, contexts, action)
70 self["actions"] = MoviePlayerActionMap(self, ["OkCancelActions", "DirectionActions", "NumberActions", "MediaPlayerSeekActions"],
75 "right": self.rightDown,
76 "rightRepeated": self.doNothing,
77 "rightUp": self.rightUp,
78 "left": self.leftDown,
79 "leftRepeated": self.doNothing,
80 "leftUp": self.leftUp,
83 "upRepeated": self.up,
85 "downRepeated": self.down,
87 "play": self.playEntry,
88 "pause": self.pauseEntry,
89 "stop": self.stopEntry,
91 "previous": self.previousEntry,
92 "next": self.nextEntry,
94 "menu": self.showMenu,
96 "1": self.keyNumberGlobal,
97 "2": self.keyNumberGlobal,
98 "3": self.keyNumberGlobal,
99 "4": self.keyNumberGlobal,
100 "5": self.keyNumberGlobal,
101 "6": self.keyNumberGlobal,
102 "7": self.keyNumberGlobal,
103 "8": self.keyNumberGlobal,
104 "9": self.keyNumberGlobal,
105 "0": self.keyNumberGlobal
108 InfoBarSeek.__init__(self)
110 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
112 #iPlayableService.evStart: self.__serviceStarted,
113 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
115 iPlayableService.evEOF: self.__evEOF,
116 # iPlayableService.evSOF: self.__evSOF,
119 self.onClose.append(self.delMPTimer)
120 self.onClose.append(self.__onClose)
122 self.righttimer = False
123 self.rightKeyTimer = eTimer()
124 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
126 self.lefttimer = False
127 self.leftKeyTimer = eTimer()
128 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
130 self.infoTimer = eTimer()
131 self.infoTimer.timeout.get().append(self.infoTimerFire)
132 self.infoTimer.start(500)
134 self.currList = "filelist"
136 self.coverArtFileName = ""
138 self.playlistIOInternal = PlaylistIOInternal()
139 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
142 self.playlist.addFile(x.ref)
143 self.playlist.updateList()
149 self.playlistIOInternal.clear()
150 for x in self.playlist.list:
151 self.playlistIOInternal.addService(ServiceReference(x[0]))
152 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
155 def checkSkipShowHideLock(self):
156 self.updatedSeekState()
162 self.session.nav.playService(self.oldService)
164 def delMPTimer(self):
165 del self.rightKeyTimer
166 del self.leftKeyTimer
169 def infoTimerFire(self):
170 currPlay = self.session.nav.getCurrentService()
171 if currPlay is not None:
172 self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
173 title = currPlay.info().getInfoString(iServiceInformation.sTitle),
174 album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
175 genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
177 self.updateCoverArtPixmap( currPlay.info().getName() )
179 self.updateMusicInformation()
180 self.updateCoverArtPixmap( "" )
182 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
183 self.updateSingleMusicInformation("artist", artist, clear)
184 self.updateSingleMusicInformation("title", title, clear)
185 self.updateSingleMusicInformation("album", album, clear)
186 self.updateSingleMusicInformation("year", year, clear)
187 self.updateSingleMusicInformation("genre", genre, clear)
189 def updateSingleMusicInformation(self, name, info, clear):
190 if info != "" or clear:
191 if self[name].getText() != info:
192 self[name].setText(info)
194 def updateCoverArtPixmap(self, currentServiceName):
195 filename = currentServiceName
196 # The "getName" usually adds something like "MP3 File:" infront of filename
197 # Get rid of this...by finding the first "/"
198 filename = filename[filename.find("/"):]
199 path = os.path.dirname(filename)
200 pngname = path + "/" + "folder.png"
201 if not os.path.exists(pngname):
202 pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png")
203 if self.coverArtFileName != pngname:
204 self.coverArtFileName = pngname
205 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
207 def fwdTimerFire(self):
208 self.fwdKeyTimer.stop()
209 self.fwdtimer = False
212 def rwdTimerFire(self):
213 self.rwdKeyTimer.stop()
214 self.rwdtimer = False
218 self.lefttimer = True
219 self.leftKeyTimer.start(1000)
222 self.righttimer = True
223 self.rightKeyTimer.start(1000)
227 self.leftKeyTimer.stop()
228 self.lefttimer = False
229 self[self.currList].pageUp()
233 self.rightKeyTimer.stop()
234 self.righttimer = False
235 self[self.currList].pageDown()
237 def leftTimerFire(self):
238 self.leftKeyTimer.stop()
239 self.lefttimer = False
240 self.switchToFileList()
242 def rightTimerFire(self):
243 self.rightKeyTimer.stop()
244 self.righttimer = False
245 self.switchToPlayList()
247 def switchToFileList(self):
248 self.currList = "filelist"
249 self.filelist.selectionEnabled(1)
250 self.playlist.selectionEnabled(0)
251 self.updateCurrentInfo()
253 def switchToPlayList(self):
254 if len(self.playlist) != 0:
255 self.currList = "playlist"
256 self.filelist.selectionEnabled(0)
257 self.playlist.selectionEnabled(1)
258 self.updateCurrentInfo()
261 self[self.currList].up()
262 self.updateCurrentInfo()
265 self[self.currList].down()
266 self.updateCurrentInfo()
268 def updateCurrentInfo(self):
270 if self.currList == "filelist":
271 if not self.filelist.canDescent():
272 text = self.filelist.getServiceRef().getPath()
273 if self.currList == "playlist":
274 text = self.playlist.getSelection().getPath()
276 self["currenttext"].setText(os.path.basename(text))
279 if self.currList == "filelist":
280 if self.filelist.canDescent():
281 self.filelist.descent()
282 self.updateCurrentInfo()
285 if self.currList == "playlist":
286 selection = self["playlist"].getSelection()
287 self.changeEntry(self.playlist.getSelectionIndex())
289 def keyNumberGlobal(self, number):
294 if self.currList == "filelist":
295 menu.append((_("switch to playlist"), "playlist"))
296 if self.filelist.canDescent():
297 menu.append((_("add directory to playlist"), "copydir"))
299 menu.append((_("add file to playlist"), "copy"))
301 menu.append((_("switch to filelist"), "filelist"))
302 menu.append((_("delete"), "delete"))
303 menu.append((_("clear playlist"), "clear"))
304 menu.append((_("hide player"), "hide"));
305 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
307 def menuCallback(self, choice):
311 if choice[1] == "copydir":
312 self.copyDirectory(self.filelist.getSelection()[0])
313 elif choice[1] == "copy":
315 elif choice[1] == "playlist":
316 self.switchToPlayList()
317 elif choice[1] == "filelist":
318 self.switchToFileList()
319 elif choice[1] == "delete":
320 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
323 elif choice[1] == "clear":
325 self.playlist.clear()
326 self.switchToFileList()
327 elif choice[1] == "hide":
330 def copyDirectory(self, directory):
331 filelist = FileList(directory, useServiceRef = True, isTop = True)
333 for x in filelist.getFileList():
334 if x[0][1] == True: #isDir
335 self.copyDirectory(x[0][0])
337 self.playlist.addFile(x[0][0])
338 self.playlist.updateList()
344 if self.filelist.getServiceRef().type == 4098: # playlist
346 list.append((_("Add files to playlist"), (self.ADDPLAYLIST, self.filelist.getServiceRef())))
347 list.append((_("Replace current playlist"), (self.REPLACEPLAYLIST, self.filelist.getServiceRef())))
348 self.session.openWithCallback(self.playlistCallback, ChoiceBox, title=_("You selected a playlist"), list = list)
350 self.playlist.addFile(self.filelist.getServiceRef())
351 self.playlist.updateList()
352 if len(self.playlist) == 1:
355 def addPlaylistParser(self, parser, extension):
356 self.playlistparsers[extension] = parser
358 def playlistCallback(self, answer):
359 if answer is not None:
360 extension = answer[1][1].getPath()[answer[1][1].getPath().rfind('.') + 1:]
361 print "extension:", extension
362 if self.playlistparsers.has_key(extension):
363 playlist = self.playlistparsers[extension]()
364 if answer[1][0] == self.REPLACEPLAYLIST:
366 self.playlist.clear()
367 self.switchToFileList()
368 if answer[1][0] == self.REPLACEPLAYLIST or answer[1][0] == self.ADDPLAYLIST:
369 list = playlist.open(answer[1][1].getPath())
371 self.playlist.addFile(x.ref)
375 next = self.playlist.getCurrentIndex() + 1
376 if next < len(self.playlist):
377 self.changeEntry(next)
379 def previousEntry(self):
380 next = self.playlist.getCurrentIndex() - 1
382 self.changeEntry(next)
384 def deleteEntry(self):
385 self.playlist.deleteFile(self.playlist.getSelectionIndex())
386 self.playlist.updateList()
387 if len(self.playlist) == 0:
388 self.switchToFileList()
390 def changeEntry(self, index):
391 self.playlist.setCurrentPlaying(index)
395 if len(self.playlist.getServiceRefList()):
396 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
397 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
398 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
399 info = eServiceCenter.getInstance().info(currref)
400 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
401 self["title"].setText(description)
402 self.unPauseService()
404 def updatedSeekState(self):
405 if self.seekstate == self.SEEK_STATE_PAUSE:
406 self.playlist.pauseFile()
407 elif self.seekstate == self.SEEK_STATE_PLAY:
408 self.playlist.playFile()
409 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
410 self.SEEK_STATE_FF_4X,
411 self.SEEK_STATE_FF_8X,
412 self.SEEK_STATE_FF_32X,
413 self.SEEK_STATE_FF_64X,
414 self.SEEK_STATE_FF_128X):
415 self.playlist.forwardFile()
416 elif self.seekstate in ( self.SEEK_STATE_BACK_16X,
417 self.SEEK_STATE_BACK_32X,
418 self.SEEK_STATE_BACK_64X,
419 self.SEEK_STATE_BACK_128X,):
420 self.playlist.rewindFile()
422 def pauseEntry(self):
426 self.playlist.stopFile()
427 self.session.nav.playService(None)
428 self.updateMusicInformation(clear=True)
430 def unPauseService(self):
431 self.setSeekState(self.SEEK_STATE_PLAY)