8f92df5e1232eb8ba9bd8c7e52650c3d453fba37
[enigma2.git] / lib / python / Screens / MediaPlayer.py
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
21
22 import os
23
24 class MediaPlayer(Screen, InfoBarSeek):
25         ALLOW_SUSPEND = True
26         
27         def __init__(self, session, args = None):
28                 Screen.__init__(self, session)
29                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
30                 self.session.nav.stopService()
31
32                 self.playlistparsers = {}
33                 self.addPlaylistParser(PlaylistIOM3U, "m3u")
34                 self.addPlaylistParser(PlaylistIOPLS, "pls")
35                 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
36
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
39
40                 self.playlist = PlayList()
41                 self["playlist"] = self.playlist
42                 
43                 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
44                 
45                 self["currenttext"] = Label("")
46                 
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()
58                 
59                 #self["text"] = Input("1234", maxSize=True, type=Input.NUMBER)
60
61                 class MoviePlayerActionMap(NumberActionMap):
62                         def __init__(self, player, contexts = [ ], actions = { }, prio=0):
63                                 NumberActionMap.__init__(self, contexts, actions, prio)
64                                 self.player = player
65
66                         def action(self, contexts, action):
67                                 self.player.show()
68                                 return NumberActionMap.action(self, contexts, action)
69
70                 self["actions"] = MoviePlayerActionMap(self, ["OkCancelActions", "DirectionActions", "NumberActions", "MediaPlayerSeekActions"],
71                 {
72                         "ok": self.ok,
73                         "cancel": self.exit,
74                         
75                         "right": self.rightDown,
76                         "rightRepeated": self.doNothing,
77                         "rightUp": self.rightUp,
78                         "left": self.leftDown,
79                         "leftRepeated": self.doNothing,
80                         "leftUp": self.leftUp,
81                         
82                         "up": self.up,
83                         "upRepeated": self.up,
84                         "down": self.down,
85                         "downRepeated": self.down,
86                         
87                         "play": self.playEntry,
88                         "pause": self.pauseEntry,
89                         "stop": self.stopEntry,
90                         
91                         "previous": self.previousEntry,
92                         "next": self.nextEntry,
93                         
94                         "menu": self.showMenu,
95                         
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
106         }, -2)
107
108                 InfoBarSeek.__init__(self)
109
110                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
111                         {
112                                 #iPlayableService.evStart: self.__serviceStarted,
113                                 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
114
115                                 iPlayableService.evEOF: self.__evEOF,
116 #                               iPlayableService.evSOF: self.__evSOF,
117                         })
118
119                 self.onClose.append(self.delMPTimer)
120                 self.onClose.append(self.__onClose)
121                 
122                 self.righttimer = False
123                 self.rightKeyTimer = eTimer()
124                 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
125
126                 self.lefttimer = False
127                 self.leftKeyTimer = eTimer()
128                 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
129                 
130                 self.infoTimer = eTimer()
131                 self.infoTimer.timeout.get().append(self.infoTimerFire)
132                 self.infoTimer.start(500)
133                 
134                 self.currList = "filelist"
135
136                 self.coverArtFileName = ""
137                 
138                 self.playlistIOInternal = PlaylistIOInternal()
139                 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
140                 if list:
141                         for x in list:
142                                 self.playlist.addFile(x.ref)
143                         self.playlist.updateList()              
144                 
145         def doNothing(self):
146                 pass
147         
148         def exit(self):
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"))
153                 self.close()
154         
155         def checkSkipShowHideLock(self):
156                 self.updatedSeekState()
157         
158         def __evEOF(self):
159                 self.nextEntry()
160         
161         def __onClose(self):
162                 self.session.nav.playService(self.oldService)
163         
164         def delMPTimer(self):
165                 del self.rightKeyTimer
166                 del self.leftKeyTimer
167                 del self.infoTimer
168                 
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),
176                                                                                  clear = True)
177                         self.updateCoverArtPixmap( currPlay.info().getName() )
178                 else:
179                         self.updateMusicInformation()
180                         self.updateCoverArtPixmap( "" )
181         
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)
188
189         def updateSingleMusicInformation(self, name, info, clear):
190                 if info != "" or clear:
191                         if self[name].getText() != info:
192                                 self[name].setText(info)
193
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)
206
207         def fwdTimerFire(self):
208                 self.fwdKeyTimer.stop()
209                 self.fwdtimer = False
210                 self.nextEntry()
211         
212         def rwdTimerFire(self):
213                 self.rwdKeyTimer.stop()
214                 self.rwdtimer = False
215                 self.previousEntry()
216         
217         def leftDown(self):
218                 self.lefttimer = True
219                 self.leftKeyTimer.start(1000)
220
221         def rightDown(self):
222                 self.righttimer = True
223                 self.rightKeyTimer.start(1000)
224                 
225         def leftUp(self):
226                 if self.lefttimer:
227                         self.leftKeyTimer.stop()
228                         self.lefttimer = False
229                         self[self.currList].pageUp()
230     
231         def rightUp(self):
232                 if self.righttimer:
233                         self.rightKeyTimer.stop()
234                         self.righttimer = False
235                         self[self.currList].pageDown()
236                         
237         def leftTimerFire(self):
238                 self.leftKeyTimer.stop()
239                 self.lefttimer = False
240                 self.switchToFileList()
241         
242         def rightTimerFire(self):
243                 self.rightKeyTimer.stop()
244                 self.righttimer = False
245                 self.switchToPlayList()
246                                 
247         def switchToFileList(self):
248                 self.currList = "filelist"
249                 self.filelist.selectionEnabled(1)
250                 self.playlist.selectionEnabled(0)
251                 self.updateCurrentInfo()
252                 
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()
259                 
260         def up(self):
261                 self[self.currList].up()
262                 self.updateCurrentInfo()
263
264         def down(self):
265                 self[self.currList].down()
266                 self.updateCurrentInfo()
267
268         def updateCurrentInfo(self):
269                 text = ""
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()
275                 
276                 self["currenttext"].setText(os.path.basename(text))
277     
278         def ok(self):
279                 if self.currList == "filelist":
280                         if self.filelist.canDescent():
281                                 self.filelist.descent()
282                                 self.updateCurrentInfo()
283                         else:
284                                 self.copyFile()
285                 if self.currList == "playlist":
286                         selection = self["playlist"].getSelection()
287                         self.changeEntry(self.playlist.getSelectionIndex())
288
289         def keyNumberGlobal(self, number):
290                 pass
291         
292         def showMenu(self):
293                 menu = []
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"))
298                         else:
299                                 menu.append((_("add file to playlist"), "copy"))
300                 else:
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)
306                 
307         def menuCallback(self, choice):
308                 if choice is None:
309                         return
310                 
311                 if choice[1] == "copydir":
312                         self.copyDirectory(self.filelist.getSelection()[0])
313                 elif choice[1] == "copy":
314                         self.copyFile()
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():
321                                 self.stopEntry()
322                         self.deleteEntry()
323                 elif choice[1] == "clear":
324                         self.stopEntry()
325                         self.playlist.clear()
326                         self.switchToFileList()
327                 elif choice[1] == "hide":
328                         self.hide()
329
330         def copyDirectory(self, directory):
331                 filelist = FileList(directory, useServiceRef = True, isTop = True)
332                 
333                 for x in filelist.getFileList():
334                         if x[0][1] == True: #isDir
335                                 self.copyDirectory(x[0][0])
336                         else:
337                                 self.playlist.addFile(x[0][0])
338                 self.playlist.updateList()
339         
340         ADDPLAYLIST = 0
341         REPLACEPLAYLIST = 1
342         
343         def copyFile(self):
344                 if self.filelist.getServiceRef().type == 4098: # playlist
345                         list = []
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)
349                 else:
350                         self.playlist.addFile(self.filelist.getServiceRef())
351                         self.playlist.updateList()
352                         if len(self.playlist) == 1:
353                                 self.changeEntry(0)
354
355         def addPlaylistParser(self, parser, extension):
356                 self.playlistparsers[extension] = parser
357
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:
365                                         self.stopEntry()
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())
370                                         for x in list:
371                                                 self.playlist.addFile(x.ref)
372                                 
373
374         def nextEntry(self):
375                 next = self.playlist.getCurrentIndex() + 1
376                 if next < len(self.playlist):
377                         self.changeEntry(next)
378         
379         def previousEntry(self):
380                 next = self.playlist.getCurrentIndex() - 1
381                 if next >= 0:
382                         self.changeEntry(next)
383                         
384         def deleteEntry(self):
385                 self.playlist.deleteFile(self.playlist.getSelectionIndex())
386                 self.playlist.updateList()
387                 if len(self.playlist) == 0:
388                         self.switchToFileList()
389                 
390         def changeEntry(self, index):
391                 self.playlist.setCurrentPlaying(index)
392                 self.playEntry()
393         
394         def playEntry(self):
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()
403                                 
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()
421         
422         def pauseEntry(self):
423                 self.pauseService()
424                 
425         def stopEntry(self):
426                 self.playlist.stopFile()
427                 self.session.nav.playService(None)
428                 self.updateMusicInformation(clear=True)
429
430         def unPauseService(self):
431                 self.setSeekState(self.SEEK_STATE_PLAY)
432
433
434