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):
25 def __init__(self, session, args = None):
26 Screen.__init__(self, session)
27 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
28 self.session.nav.stopService()
30 self.playlistparsers = {}
31 self.addPlaylistParser(PlaylistIOM3U, "m3u")
32 self.addPlaylistParser(PlaylistIOPLS, "pls")
33 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
35 self.filelist = FileList(resolveFilename(SCOPE_MEDIA), matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True)
36 self["filelist"] = self.filelist
38 self.playlist = PlayList()
39 self["playlist"] = self.playlist
41 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
43 self["currenttext"] = Label("")
45 self["artisttext"] = Label(_("Artist:"))
46 self["artist"] = Label("")
47 self["titletext"] = Label(_("Title:"))
48 self["title"] = Label("")
49 self["albumtext"] = Label(_("Album:"))
50 self["album"] = Label("")
51 self["yeartext"] = Label(_("Year:"))
52 self["year"] = Label("")
53 self["genretext"] = Label(_("Genre:"))
54 self["genre"] = Label("")
55 self["coverArt"] = Pixmap()
57 #self["text"] = Input("1234", maxSize=True, type=Input.NUMBER)
59 class MoviePlayerActionMap(NumberActionMap):
60 def __init__(self, player, contexts = [ ], actions = { }, prio=0):
61 NumberActionMap.__init__(self, contexts, actions, prio)
64 def action(self, contexts, action):
66 return NumberActionMap.action(self, contexts, action)
68 self["actions"] = MoviePlayerActionMap(self, ["OkCancelActions", "DirectionActions", "NumberActions", "MediaPlayerSeekActions"],
73 "right": self.rightDown,
74 "rightRepeated": self.doNothing,
75 "rightUp": self.rightUp,
76 "left": self.leftDown,
77 "leftRepeated": self.doNothing,
78 "leftUp": self.leftUp,
81 "upRepeated": self.up,
83 "downRepeated": self.down,
85 "play": self.playEntry,
86 "pause": self.pauseEntry,
87 "stop": self.stopEntry,
89 "previous": self.previousEntry,
90 "next": self.nextEntry,
92 "menu": self.showMenu,
94 "1": self.keyNumberGlobal,
95 "2": self.keyNumberGlobal,
96 "3": self.keyNumberGlobal,
97 "4": self.keyNumberGlobal,
98 "5": self.keyNumberGlobal,
99 "6": self.keyNumberGlobal,
100 "7": self.keyNumberGlobal,
101 "8": self.keyNumberGlobal,
102 "9": self.keyNumberGlobal,
103 "0": self.keyNumberGlobal
106 InfoBarSeek.__init__(self)
108 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
110 #iPlayableService.evStart: self.__serviceStarted,
111 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
113 iPlayableService.evEOF: self.__evEOF,
114 # iPlayableService.evSOF: self.__evSOF,
117 self.onClose.append(self.delMPTimer)
118 self.onClose.append(self.__onClose)
120 self.righttimer = False
121 self.rightKeyTimer = eTimer()
122 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
124 self.lefttimer = False
125 self.leftKeyTimer = eTimer()
126 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
128 self.infoTimer = eTimer()
129 self.infoTimer.timeout.get().append(self.infoTimerFire)
130 self.infoTimer.start(500)
132 self.currList = "filelist"
134 self.coverArtFileName = ""
136 self.playlistIOInternal = PlaylistIOInternal()
137 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
140 self.playlist.addFile(x.ref)
141 self.playlist.updateList()
147 self.playlistIOInternal.clear()
148 for x in self.playlist.list:
149 self.playlistIOInternal.addService(ServiceReference(x[0]))
150 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
153 def checkSkipShowHideLock(self):
154 self.updatedSeekState()
160 self.session.nav.playService(self.oldService)
162 def delMPTimer(self):
163 del self.rightKeyTimer
164 del self.leftKeyTimer
167 def infoTimerFire(self):
168 currPlay = self.session.nav.getCurrentService()
169 if currPlay is not None:
170 self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
171 title = currPlay.info().getInfoString(iServiceInformation.sTitle),
172 album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
173 genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
175 self.updateCoverArtPixmap( currPlay.info().getName() )
177 self.updateMusicInformation()
178 self.updateCoverArtPixmap( "" )
180 def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
181 self.updateSingleMusicInformation("artist", artist, clear)
182 self.updateSingleMusicInformation("title", title, clear)
183 self.updateSingleMusicInformation("album", album, clear)
184 self.updateSingleMusicInformation("year", year, clear)
185 self.updateSingleMusicInformation("genre", genre, clear)
187 def updateSingleMusicInformation(self, name, info, clear):
188 if info != "" or clear:
189 if self[name].getText() != info:
190 self[name].setText(info)
192 def updateCoverArtPixmap(self, currentServiceName):
193 filename = currentServiceName
194 # The "getName" usually adds something like "MP3 File:" infront of filename
195 # Get rid of this...by finding the first "/"
196 filename = filename[filename.find("/"):]
197 path = os.path.dirname(filename)
198 pngname = path + "/" + "folder.png"
199 if not os.path.exists(pngname):
200 pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png")
201 if self.coverArtFileName != pngname:
202 self.coverArtFileName = pngname
203 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
205 def fwdTimerFire(self):
206 self.fwdKeyTimer.stop()
207 self.fwdtimer = False
210 def rwdTimerFire(self):
211 self.rwdKeyTimer.stop()
212 self.rwdtimer = False
216 self.lefttimer = True
217 self.leftKeyTimer.start(1000)
220 self.righttimer = True
221 self.rightKeyTimer.start(1000)
225 self.leftKeyTimer.stop()
226 self.lefttimer = False
227 self[self.currList].pageUp()
231 self.rightKeyTimer.stop()
232 self.righttimer = False
233 self[self.currList].pageDown()
235 def leftTimerFire(self):
236 self.leftKeyTimer.stop()
237 self.lefttimer = False
238 self.switchToFileList()
240 def rightTimerFire(self):
241 self.rightKeyTimer.stop()
242 self.righttimer = False
243 self.switchToPlayList()
245 def switchToFileList(self):
246 self.currList = "filelist"
247 self.filelist.selectionEnabled(1)
248 self.playlist.selectionEnabled(0)
249 self.updateCurrentInfo()
251 def switchToPlayList(self):
252 if len(self.playlist) != 0:
253 self.currList = "playlist"
254 self.filelist.selectionEnabled(0)
255 self.playlist.selectionEnabled(1)
256 self.updateCurrentInfo()
259 self[self.currList].up()
260 self.updateCurrentInfo()
263 self[self.currList].down()
264 self.updateCurrentInfo()
266 def updateCurrentInfo(self):
268 if self.currList == "filelist":
269 if not self.filelist.canDescent():
270 text = self.filelist.getServiceRef().getPath()
271 if self.currList == "playlist":
272 text = self.playlist.getSelection().getPath()
274 self["currenttext"].setText(os.path.basename(text))
277 if self.currList == "filelist":
278 if self.filelist.canDescent():
279 self.filelist.descent()
280 self.updateCurrentInfo()
283 if self.currList == "playlist":
284 selection = self["playlist"].getSelection()
285 self.changeEntry(self.playlist.getSelectionIndex())
287 def keyNumberGlobal(self, number):
292 if self.currList == "filelist":
293 menu.append((_("switch to playlist"), "playlist"))
294 if self.filelist.canDescent():
295 menu.append((_("add directory to playlist"), "copydir"))
297 menu.append((_("add file to playlist"), "copy"))
299 menu.append((_("switch to filelist"), "filelist"))
300 menu.append((_("delete"), "delete"))
301 menu.append((_("clear playlist"), "clear"))
302 menu.append((_("hide player"), "hide"));
303 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
305 def menuCallback(self, choice):
309 if choice[1] == "copydir":
310 self.copyDirectory(self.filelist.getSelection()[0])
311 elif choice[1] == "copy":
313 elif choice[1] == "playlist":
314 self.switchToPlayList()
315 elif choice[1] == "filelist":
316 self.switchToFileList()
317 elif choice[1] == "delete":
318 if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
321 elif choice[1] == "clear":
323 self.playlist.clear()
324 self.switchToFileList()
325 elif choice[1] == "hide":
328 def copyDirectory(self, directory):
329 filelist = FileList(directory, useServiceRef = True, isTop = True)
331 for x in filelist.getFileList():
332 if x[0][1] == True: #isDir
333 self.copyDirectory(x[0][0])
335 self.playlist.addFile(x[0][0])
336 self.playlist.updateList()
342 if self.filelist.getServiceRef().type == 4098: # playlist
344 list.append((_("Add files to playlist"), (self.ADDPLAYLIST, self.filelist.getServiceRef())))
345 list.append((_("Replace current playlist"), (self.REPLACEPLAYLIST, self.filelist.getServiceRef())))
346 self.session.openWithCallback(self.playlistCallback, ChoiceBox, title=_("You selected a playlist"), list = list)
348 self.playlist.addFile(self.filelist.getServiceRef())
349 self.playlist.updateList()
350 if len(self.playlist) == 1:
353 def addPlaylistParser(self, parser, extension):
354 self.playlistparsers[extension] = parser
356 def playlistCallback(self, answer):
357 if answer is not None:
358 extension = answer[1][1].getPath()[answer[1][1].getPath().rfind('.') + 1:]
359 print "extension:", extension
360 if self.playlistparsers.has_key(extension):
361 playlist = self.playlistparsers[extension]()
362 if answer[1][0] == self.REPLACEPLAYLIST:
364 self.playlist.clear()
365 self.switchToFileList()
366 if answer[1][0] == self.REPLACEPLAYLIST or answer[1][0] == self.ADDPLAYLIST:
367 list = playlist.open(answer[1][1].getPath())
369 self.playlist.addFile(x.ref)
373 next = self.playlist.getCurrentIndex() + 1
374 if next < len(self.playlist):
375 self.changeEntry(next)
377 def previousEntry(self):
378 next = self.playlist.getCurrentIndex() - 1
380 self.changeEntry(next)
382 def deleteEntry(self):
383 self.playlist.deleteFile(self.playlist.getSelectionIndex())
384 self.playlist.updateList()
385 if len(self.playlist) == 0:
386 self.switchToFileList()
388 def changeEntry(self, index):
389 self.playlist.setCurrentPlaying(index)
393 if len(self.playlist.getServiceRefList()):
394 currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
395 if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
396 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
397 info = eServiceCenter.getInstance().info(currref)
398 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
399 self["title"].setText(description)
400 self.unPauseService()
402 def updatedSeekState(self):
403 if self.seekstate == self.SEEK_STATE_PAUSE:
404 self.playlist.pauseFile()
405 elif self.seekstate == self.SEEK_STATE_PLAY:
406 self.playlist.playFile()
407 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
408 self.SEEK_STATE_FF_4X,
409 self.SEEK_STATE_FF_8X,
410 self.SEEK_STATE_FF_32X,
411 self.SEEK_STATE_FF_64X,
412 self.SEEK_STATE_FF_128X):
413 self.playlist.forwardFile()
414 elif self.seekstate in ( self.SEEK_STATE_BACK_16X,
415 self.SEEK_STATE_BACK_32X,
416 self.SEEK_STATE_BACK_64X,
417 self.SEEK_STATE_BACK_128X,):
418 self.playlist.rewindFile()
420 def pauseEntry(self):
424 self.playlist.stopFile()
425 self.session.nav.playService(None)
426 self.updateMusicInformation(clear=True)
428 def unPauseService(self):
429 self.setSeekState(self.SEEK_STATE_PLAY)