Fix Mediaplayer crash for WAV playback and add basic Audio CD support (needs kernel...
[enigma2.git] / lib / python / Plugins / Extensions / MediaPlayer / plugin.py
1 from os import path as os_path, remove as os_remove, listdir as os_listdir
2 from time import strftime
3 from enigma import eTimer, eServiceCenter, iServiceInformation
4 from Screens.Screen import Screen
5 from Screens.MessageBox import MessageBox
6 from Screens.InputBox import InputBox
7 from Components.ActionMap import NumberActionMap, HelpableActionMap
8 from Components.Label import Label
9 from Components.Pixmap import Pixmap
10 from Components.Label import Label
11 from Components.FileList import FileList
12 from Components.MediaPlayer import PlayList
13 from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
14 from Components.ServicePosition import ServicePositionGauge
15 from Components.ServiceEventTracker import InfoBarBase
16 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
17 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications
18 from ServiceReference import ServiceReference
19 from Screens.ChoiceBox import ChoiceBox
20 from Screens.HelpMenu import HelpableScreen
21 import random
22
23 class MyPlayList(PlayList):
24         def __init__(self):
25                 PlayList.__init__(self)
26
27         def PlayListShuffle(self):
28                 random.shuffle(self.list)
29                 self.l.setList(self.list)
30                 self.currPlaying = -1
31                 self.oldCurrPlaying = -1
32
33 class MediaPixmap(Pixmap):
34         def applySkin(self, desktop, screen):
35                 self.default_pixmap = None
36                 if self.skinAttributes is not None:
37                         for (attrib, value) in self.skinAttributes:
38                                 if attrib == "pixmap":
39                                         self.default_pixmap = value
40                                         break
41                 if self.default_pixmap is None:
42                         self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
43                 return Pixmap.applySkin(self, desktop, screen)
44
45 class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, HelpableScreen):
46         ALLOW_SUSPEND = True
47         ENABLE_RESUME_SUPPORT = True
48
49         def __init__(self, session, args = None):
50                 Screen.__init__(self, session)
51                 InfoBarAudioSelection.__init__(self)
52                 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
53                 InfoBarNotifications.__init__(self)
54                 InfoBarBase.__init__(self)
55                 HelpableScreen.__init__(self)
56                 self.summary = None
57                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
58                 self.session.nav.stopService()
59
60                 self.playlistparsers = {}
61                 self.addPlaylistParser(PlaylistIOM3U, "m3u")
62                 self.addPlaylistParser(PlaylistIOPLS, "pls")
63                 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
64
65                 # 'None' is magic to start at the list of mountpoints
66                 self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
67                 self["filelist"] = self.filelist
68
69                 self.playlist = MyPlayList()
70                 #self.playlist = PlayList()
71                 self.is_closing = False
72                 self.delname = ""
73                 self["playlist"] = self.playlist
74
75                 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
76
77                 self["currenttext"] = Label("")
78
79                 self["artisttext"] = Label(_("Artist:"))
80                 self["artist"] = Label("")
81                 self["titletext"] = Label(_("Title:"))
82                 self["title"] = Label("")
83                 self["albumtext"] = Label(_("Album:"))
84                 self["album"] = Label("")
85                 self["yeartext"] = Label(_("Year:"))
86                 self["year"] = Label("")
87                 self["genretext"] = Label(_("Genre:"))
88                 self["genre"] = Label("")
89                 self["coverArt"] = MediaPixmap()
90
91                 self.seek_target = None
92
93                 class MoviePlayerActionMap(NumberActionMap):
94                         def __init__(self, player, contexts = [ ], actions = { }, prio=0):
95                                 NumberActionMap.__init__(self, contexts, actions, prio)
96                                 self.player = player
97
98                         def action(self, contexts, action):
99                                 self.player.show()
100                                 return NumberActionMap.action(self, contexts, action)
101
102
103                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", 
104                         {
105                                 "ok": (self.ok, _("add file to playlist")),
106                                 "cancel": (self.exit, _("exit mediaplayer")),
107                         }, -2)
108
109                 self["MediaPlayerActions"] = HelpableActionMap(self, "MediaPlayerActions", 
110                         {
111                                 "play": (self.xplayEntry, _("play entry")),
112                                 "pause": (self.pauseEntry, _("pause")),
113                                 "stop": (self.stopEntry, _("stop entry")),
114                                 "previous": (self.previousMarkOrEntry, _("play from previous mark or playlist entry")),
115                                 "next": (self.nextMarkOrEntry, _("play from next mark or playlist entry")),
116                                 "menu": (self.showMenu, _("menu")),
117                                 "skipListbegin": (self.skip_listbegin, _("jump to listbegin")),
118                                 "skipListend": (self.skip_listend, _("jump to listend")),
119                                 "prevBouquet": (self.switchToPlayList, _("switch to playlist")),
120                                 "nextBouquet": (self.switchToFileList, _("switch to filelist")),
121                                 "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
122                                 "shift_stop": (self.clear_playlist, _("clear playlist")),
123                                 "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
124                         }, -2)
125
126                 self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
127                         {
128                                 "showEventInfo": (self.showEventInformation, _("show event details")),
129                         })
130
131                 self["actions"] = MoviePlayerActionMap(self, ["DirectionActions"], 
132                 {
133                         "right": self.rightDown,
134                         "rightRepeated": self.doNothing,
135                         "rightUp": self.rightUp,
136                         "left": self.leftDown,
137                         "leftRepeated": self.doNothing,
138                         "leftUp": self.leftUp,
139
140                         "up": self.up,
141                         "upRepeated": self.up,
142                         "upUp": self.doNothing,
143                         "down": self.down,
144                         "downRepeated": self.down,
145                         "downUp": self.doNothing,
146                 }, -2)
147
148                 InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions")
149
150                 self.onClose.append(self.delMPTimer)
151                 self.onClose.append(self.__onClose)
152
153                 self.righttimer = False
154                 self.rightKeyTimer = eTimer()
155                 self.rightKeyTimer.callback.append(self.rightTimerFire)
156
157                 self.lefttimer = False
158                 self.leftKeyTimer = eTimer()
159                 self.leftKeyTimer.callback.append(self.leftTimerFire)
160
161                 self.currList = "filelist"
162
163                 self.coverArtFileName = ""
164                 self.isAudioCD = False
165
166                 self.playlistIOInternal = PlaylistIOInternal()
167                 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
168                 if list:
169                         for x in list:
170                                 self.playlist.addFile(x.ref)
171                         self.playlist.updateList()
172
173         def doNothing(self):
174                 pass
175
176         def createSummary(self):
177                 return MediaPlayerLCDScreen
178
179         def exit(self):
180                 self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5)
181
182         def exitCB(self, answer):
183                 if answer == True:
184                         self.playlistIOInternal.clear()
185                         for x in self.playlist.list:
186                                 self.playlistIOInternal.addService(ServiceReference(x[0]))
187                         if not self.isAudioCD:
188                                 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
189                         self.close()
190
191         def checkSkipShowHideLock(self):
192                 self.updatedSeekState()
193
194         def doEofInternal(self, playing):
195                 if playing:
196                         self.nextEntry()
197                 else:
198                         self.show()
199
200         def __onClose(self):
201                 self.session.nav.playService(self.oldService)
202
203         def delMPTimer(self):
204                 del self.rightKeyTimer
205                 del self.leftKeyTimer
206
207         def readTitleInformation(self):
208                 currPlay = self.session.nav.getCurrentService()
209                 if currPlay is not None:
210                         stitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
211                         if stitle == "":
212                                 stitle = currPlay.info().getName().split('/')[-1]
213
214                         self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
215                                                                                  title = stitle,
216                                                                                  album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
217                                                                                  genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
218                                                                                  clear = True)
219                 else:
220                         self.updateMusicInformation()
221
222         def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
223                 self.updateSingleMusicInformation("artist", artist, clear)
224                 self.updateSingleMusicInformation("title", title, clear)
225                 self.updateSingleMusicInformation("album", album, clear)
226                 self.updateSingleMusicInformation("year", year, clear)
227                 self.updateSingleMusicInformation("genre", genre, clear)
228
229         def updateSingleMusicInformation(self, name, info, clear):
230                 if info != "" or clear:
231                         if self[name].getText() != info:
232                                 self[name].setText(info)
233
234         def updateCoverArtPixmap(self, path):
235                 while not path.endswith("/"):
236                         path = path[:-1]
237                 pngname = path + "folder.png"
238                 
239                 if not os_path.exists(pngname):
240                         pngname = self["coverArt"].default_pixmap
241                 if self.coverArtFileName != pngname:
242                         self.coverArtFileName = pngname
243                         self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
244
245         def leftDown(self):
246                 self.lefttimer = True
247                 self.leftKeyTimer.start(1000)
248
249         def rightDown(self):
250                 self.righttimer = True
251                 self.rightKeyTimer.start(1000)
252
253         def leftUp(self):
254                 if self.lefttimer:
255                         self.leftKeyTimer.stop()
256                         self.lefttimer = False
257                         self[self.currList].pageUp()
258                         self.updateCurrentInfo()
259
260         def rightUp(self):
261                 if self.righttimer:
262                         self.rightKeyTimer.stop()
263                         self.righttimer = False
264                         self[self.currList].pageDown()
265                         self.updateCurrentInfo()
266
267         def leftTimerFire(self):
268                 self.leftKeyTimer.stop()
269                 self.lefttimer = False
270                 self.switchToFileList()
271
272         def rightTimerFire(self):
273                 self.rightKeyTimer.stop()
274                 self.righttimer = False
275                 self.switchToPlayList()
276
277         def switchToFileList(self):
278                 self.currList = "filelist"
279                 self.filelist.selectionEnabled(1)
280                 self.playlist.selectionEnabled(0)
281                 self.updateCurrentInfo()
282
283         def switchToPlayList(self):
284                 if len(self.playlist) != 0:
285                         self.currList = "playlist"
286                         self.filelist.selectionEnabled(0)
287                         self.playlist.selectionEnabled(1)
288                         self.updateCurrentInfo()
289
290         def up(self):
291                 self[self.currList].up()
292                 self.updateCurrentInfo()
293
294         def down(self):
295                 self[self.currList].down()
296                 self.updateCurrentInfo()
297
298         def showAfterSeek(self):
299                 self.show()
300
301         def showAfterCuesheetOperation(self):
302                 self.show()
303
304         def hideAfterResume(self):
305                 self.hide()
306
307         # FIXME: maybe this code can be optimized 
308         def updateCurrentInfo(self):
309                 text = ""
310                 if self.currList == "filelist":
311                         idx = self.filelist.getSelectionIndex()
312                         r = self.filelist.list[idx]
313                         text = r[1][7]
314                         if r[0][1] == True:
315                                 if len(text) < 2:
316                                         text += " "
317                                 if text[:2] != "..":
318                                         text = "/" + text
319                         self.summaries.setText(text,1)
320
321                         idx += 1
322                         if idx < len(self.filelist.list):
323                                 r = self.filelist.list[idx]
324                                 text = r[1][7]
325                                 if r[0][1] == True:
326                                         text = "/" + text
327                                 self.summaries.setText(text,3)
328                         else:
329                                 self.summaries.setText(" ",3)
330
331                         idx += 1
332                         if idx < len(self.filelist.list):
333                                 r = self.filelist.list[idx]
334                                 text = r[1][7]
335                                 if r[0][1] == True:
336                                         text = "/" + text
337                                 self.summaries.setText(text,4)
338                         else:
339                                 self.summaries.setText(" ",4)
340
341                         text = ""
342                         if not self.filelist.canDescent():
343                                 r = self.filelist.getServiceRef()
344                                 if r is None:
345                                         return
346                                 text = r.getPath()
347                                 self["currenttext"].setText(os_path.basename(text))
348
349                 if self.currList == "playlist":
350                         t = self.playlist.getSelection()
351                         if t is None:
352                                 return
353                         #display current selected entry on LCD
354                         text = t.getPath()
355                         text = text.split('/')[-1]
356                         self.summaries.setText(text,1)
357                         self["currenttext"].setText(text)
358                         idx = self.playlist.getSelectionIndex()
359                         idx += 1
360                         if idx < len(self.playlist):
361                                 currref = self.playlist.getServiceRefList()[idx]
362                                 text = currref.getPath()
363                                 text = text.split('/')[-1]
364                                 self.summaries.setText(text,3)
365                         else:
366                                 self.summaries.setText(" ",3)
367
368                         idx += 1
369                         if idx < len(self.playlist):
370                                 currref = self.playlist.getServiceRefList()[idx]
371                                 text = currref.getPath()
372                                 text = text.split('/')[-1]
373                                 self.summaries.setText(text,4)
374                         else:
375                                 self.summaries.setText(" ",4)
376
377         def ok(self):
378                 if self.currList == "filelist":
379                         if self.filelist.canDescent():
380                                 self.filelist.descent()
381                                 self.updateCurrentInfo()
382                         else:
383                                 self.copyFile()
384
385                 if self.currList == "playlist":
386                         selection = self["playlist"].getSelection()
387                         self.changeEntry(self.playlist.getSelectionIndex())
388
389         def showMenu(self):
390                 menu = []
391                 if self.currList == "filelist":
392                         if self.filelist.canDescent():
393                                 menu.append((_("add directory to playlist"), "copydir"))
394                         else:
395                                 menu.append((_("add files to playlist"), "copyfiles"))
396                         menu.append((_("switch to playlist"), "playlist"))
397                 else:
398                         menu.append((_("switch to filelist"), "filelist"))
399
400                         menu.append((_("shuffle playlist"), "shuffle"))
401
402                         menu.append((_("delete"), "delete"))
403                         menu.append((_("clear playlist"), "clear"))
404                 menu.append((_("hide player"), "hide"));
405                 menu.append((_("save playlist"), "saveplaylist"));
406                 menu.append((_("load playlist"), "loadplaylist"));
407                 menu.append((_("delete saved playlist"), "deleteplaylist"));
408                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
409
410         def menuCallback(self, choice):
411                 if choice is None:
412                         return
413
414                 if choice[1] == "copydir":
415                         self.copyDirectory(self.filelist.getSelection()[0])
416                 elif choice[1] == "copyfiles":
417                         self.stopEntry()
418                         self.playlist.clear()
419                         self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
420                         self.playServiceRefEntry(self.filelist.getServiceRef())
421                 elif choice[1] == "playlist":
422                         self.switchToPlayList()
423                 elif choice[1] == "filelist":
424                         self.switchToFileList()
425                 elif choice[1] == "delete":
426                         if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
427                                 self.stopEntry()
428                         self.deleteEntry()
429                 elif choice[1] == "clear":
430                         self.stopEntry()
431                         self.playlist.clear()
432                         self.switchToFileList()
433                 elif choice[1] == "hide":
434                         self.hide()
435                 elif choice[1] == "saveplaylist":
436                         self.save_playlist()
437                 elif choice[1] == "loadplaylist":
438                         self.load_playlist()
439                 elif choice[1] == "deleteplaylist":
440                         self.delete_saved_playlist()
441                 elif choice[1] == "shuffle":
442                         self.playlist.PlayListShuffle()
443
444
445         def showEventInformation(self):
446                 from Screens.EventView import EventViewSimple
447                 from ServiceReference import ServiceReference
448                 evt = self[self.currList].getCurrentEvent()
449                 if evt:
450                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
451
452         # also works on filelist (?)
453         def getCurrent(self):
454                 return self["playlist"].getCurrent()
455
456         def deletePlaylistEntry(self):
457                 if self.currList == "playlist":
458                         if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
459                                 self.stopEntry()
460                         self.deleteEntry()
461
462         def skip_listbegin(self):
463                 if self.currList == "filelist":
464                         self.filelist.moveToIndex(0)
465                 else:
466                         self.playlist.moveToIndex(0)
467                 self.updateCurrentInfo()
468
469         def skip_listend(self):
470                 if self.currList == "filelist":
471                         idx = len(self.filelist.list)
472                         self.filelist.moveToIndex(idx - 1)
473                 else:
474                         self.playlist.moveToIndex(len(self.playlist)-1)
475                 self.updateCurrentInfo()
476
477         def save_playlist(self):
478                 self.session.openWithCallback(self.save_playlist2,InputBox, title=_("Please enter filename (empty = use current date)"),windowTitle = _("Save Playlist"))
479
480         def save_playlist2(self, name):
481                 if name is not None:
482                         name = name.strip()
483                         if name == "":
484                                 name = strftime("%y%m%d_%H%M%S")
485                         name += ".e2pls"
486                         self.playlistIOInternal.clear()
487                         for x in self.playlist.list:
488                                 self.playlistIOInternal.addService(ServiceReference(x[0]))
489                         self.playlistIOInternal.save(resolveFilename(SCOPE_PLAYLIST) + name)
490
491         def load_playlist(self):
492                 listpath = []
493                 playlistdir = resolveFilename(SCOPE_PLAYLIST)
494                 try:
495                         for i in os_listdir(playlistdir):
496                                 listpath.append((i,playlistdir + i))
497                 except IOError,e:
498                         print "Error while scanning subdirs ",e
499                 self.session.openWithCallback(self.PlaylistSelected, ChoiceBox, title=_("Please select a playlist..."), list = listpath)
500
501         def PlaylistSelected(self,path):
502                 if path is not None:
503                         self.clear_playlist()
504                         self.playlistIOInternal = PlaylistIOInternal()
505                         list = self.playlistIOInternal.open(path[1])
506                         if list:
507                                 for x in list:
508                                         self.playlist.addFile(x.ref)
509                                 self.playlist.updateList()
510
511         def delete_saved_playlist(self):
512                 listpath = []
513                 playlistdir = resolveFilename(SCOPE_PLAYLIST)
514                 try:
515                         for i in os_listdir(playlistdir):
516                                 listpath.append((i,playlistdir + i))
517                 except IOError,e:
518                         print "Error while scanning subdirs ",e
519                 self.session.openWithCallback(self.DeletePlaylistSelected, ChoiceBox, title=_("Please select a playlist to delete..."), list = listpath)
520
521         def DeletePlaylistSelected(self,path):
522                 if path is not None:
523                         self.delname = path[1]
524                         self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (path[1]))
525
526         def deleteConfirmed(self, confirmed):
527                 if confirmed:
528                         os_remove(self.delname)
529
530         def clear_playlist(self):
531                 self.stopEntry()
532                 self.playlist.clear()
533                 self.switchToFileList()
534
535         def copyDirectory(self, directory, recursive = True):
536                 print "copyDirectory", directory
537                 filelist = FileList(directory, useServiceRef = True, isTop = True)
538
539                 for x in filelist.getFileList():
540                         if x[0][1] == True: #isDir
541                                 if recursive:
542                                         self.copyDirectory(x[0][0])
543                         else:
544                                 self.playlist.addFile(x[0][0])
545                 self.playlist.updateList()
546
547         def copyFile(self):
548                 if self.filelist.getServiceRef().type == 4098: # playlist
549                         ServiceRef = self.filelist.getServiceRef()
550                         extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:]
551                         print "extension:", extension
552                         if self.playlistparsers.has_key(extension):
553                                 playlist = self.playlistparsers[extension]()
554                                 list = playlist.open(ServiceRef.getPath())
555                                 for x in list:
556                                         self.playlist.addFile(x.ref)
557                 else:
558                         self.playlist.addFile(self.filelist.getServiceRef())
559                         self.playlist.updateList()
560                         if len(self.playlist) == 1:
561                                 self.changeEntry(0)
562
563         def addPlaylistParser(self, parser, extension):
564                 self.playlistparsers[extension] = parser
565
566         def nextEntry(self):
567                 next = self.playlist.getCurrentIndex() + 1
568                 if next < len(self.playlist):
569                         self.changeEntry(next)
570
571         def nextMarkOrEntry(self):
572                 if not self.jumpPreviousNextMark(lambda x: x):
573                         next = self.playlist.getCurrentIndex() + 1
574                         if next < len(self.playlist):
575                                 self.changeEntry(next)
576                         else:
577                                 self.doSeek(-1)
578
579         def previousMarkOrEntry(self):
580                 if not self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True):
581                         next = self.playlist.getCurrentIndex() - 1
582                         if next >= 0:
583                                 self.changeEntry(next)
584
585         def deleteEntry(self):
586                 self.playlist.deleteFile(self.playlist.getSelectionIndex())
587                 self.playlist.updateList()
588                 if len(self.playlist) == 0:
589                         self.switchToFileList()
590
591         def changeEntry(self, index):
592                 self.playlist.setCurrentPlaying(index)
593                 self.playEntry()
594
595         def playServiceRefEntry(self, serviceref):
596                 serviceRefList = self.playlist.getServiceRefList()
597                 for count in range(len(serviceRefList)):
598                         if serviceRefList[count] == serviceref:
599                                 self.changeEntry(count)
600                                 break
601                         
602         def xplayEntry(self):
603                 if self.currList == "playlist":
604                         self.playEntry()
605                 else:
606                         self.stopEntry()
607                         self.playlist.clear()
608                         sel = self.filelist.getSelection()
609                         if sel:
610                                 if sel[1]: # can descent
611                                         # add directory to playlist
612                                         self.copyDirectory(sel[0])
613                                 else:
614                                         # add files to playlist
615                                         self.copyDirectory(os_path.dirname(sel[0].getPath()) + "/", recursive = False)
616                         if len(self.playlist) > 0:
617                                 self.changeEntry(0)
618         
619         def playEntry(self):
620                 if len(self.playlist.getServiceRefList()):
621                         needsInfoUpdate = False
622                         currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
623                         if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
624                                 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
625                                 info = eServiceCenter.getInstance().info(currref)
626                                 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
627                                 self["title"].setText(description)
628                                 # display just playing musik on LCD
629                                 idx = self.playlist.getCurrentIndex()
630                                 currref = self.playlist.getServiceRefList()[idx]
631                                 text = currref.getPath()
632                                 text = text.split('/')[-1]
633                                 text = ">"+text
634                                 ext = text[-3:].lower()
635
636                                 # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
637                                 if ext not in ["mp3", "wav", "ogg"]:
638                                         self.hide()
639                                 else:
640                                         needsInfoUpdate = True
641                                 self.summaries.setText(text,1)
642
643                                 # get the next two entries
644                                 idx += 1
645                                 if idx < len(self.playlist):
646                                         currref = self.playlist.getServiceRefList()[idx]
647                                         text = currref.getPath()
648                                         text = text.split('/')[-1]
649                                         self.summaries.setText(text,3)
650                                 else:
651                                         self.summaries.setText(" ",3)
652
653                                 idx += 1
654                                 if idx < len(self.playlist):
655                                         currref = self.playlist.getServiceRefList()[idx]
656                                         text = currref.getPath()
657                                         text = text.split('/')[-1]
658                                         self.summaries.setText(text,4)
659                                 else:
660                                         self.summaries.setText(" ",4)
661                         else:
662                                 idx = self.playlist.getCurrentIndex()
663                                 currref = self.playlist.getServiceRefList()[idx]
664                                 text = currref.getPath()
665                                 ext = text[-3:].lower()
666                                 if ext not in ["mp3", "wav", "ogg"]:
667                                         self.hide()
668                                 else:
669                                         needsInfoUpdate = True
670
671                         self.unPauseService()
672                         if needsInfoUpdate == True:
673                                 self.updateCoverArtPixmap(currref.getPath())
674                         else:
675                                 pngname = self["coverArt"].default_pixmap
676                                 self.coverArtFileName = pngname
677                                 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
678                         self.readTitleInformation()
679
680         def updatedSeekState(self):
681                 if self.seekstate == self.SEEK_STATE_PAUSE:
682                         self.playlist.pauseFile()
683                 elif self.seekstate == self.SEEK_STATE_PLAY:
684                         self.playlist.playFile()
685                 elif self.isStateForward(self.seekstate):
686                         self.playlist.forwardFile()
687                 elif self.isStateBackward(self.seekstate):
688                         self.playlist.rewindFile()
689
690         def pauseEntry(self):
691                 self.pauseService()
692                 self.show()
693
694         def stopEntry(self):
695                 self.playlist.stopFile()
696                 self.session.nav.playService(None)
697                 self.updateMusicInformation(clear=True)
698                 self.show()
699
700         def unPauseService(self):
701                 self.setSeekState(self.SEEK_STATE_PLAY)
702
703
704 class MediaPlayerLCDScreen(Screen):
705         skin = """
706         <screen position="0,0" size="132,64" title="LCD Text">
707                 <widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
708                 <widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
709                 <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
710         </screen>"""
711
712         def __init__(self, session, parent):
713                 Screen.__init__(self, session)
714                 self["text1"] = Label("Mediaplayer")
715                 self["text3"] = Label("")
716                 self["text4"] = Label("")
717
718         def setText(self, text, line):
719                 print "lcd set text:", text, line
720                 if len(text) > 10:
721                         if text[-4:] == ".mp3":
722                                 text = text[:-4]
723                 textleer = "    "
724                 text = text + textleer*10
725                 if line == 1:
726                         self["text1"].setText(text)
727                 elif line == 3:
728                         self["text3"].setText(text)
729                 elif line == 4:
730                         self["text4"].setText(text)
731
732 def main(session, **kwargs):
733         session.open(MediaPlayer)
734
735 def menu(menuid, **kwargs):
736         if menuid == "mainmenu":
737                 return [(_("Media player"), main, "media_player", 45)]
738         return []
739
740 def filescan_open(list, session, **kwargs):
741         from enigma import eServiceReference
742
743         mp = session.open(MediaPlayer)
744
745         mp.switchToPlayList()
746         for file in list:
747                 ref = eServiceReference(4097, 0, file.path)
748                 mp.playlist.addFile(ref)
749
750         # TODO: rather play first than last file?
751         mp.playServiceRefEntry(ref)
752         mp.playlist.updateList()
753
754 def audioCD_open(list, session, **kwargs):
755         from enigma import eServiceReference
756
757         mp = session.open(MediaPlayer)
758
759         mp.playlist.clear()
760         mp.isAudioCD = True
761
762         mp.switchToPlayList()
763         for file in list:
764                 ref = eServiceReference(4097, 0, file.path)
765                 mp.playlist.addFile(ref)
766
767         # TODO: rather play first than last file?
768         mp.playServiceRefEntry(ref)
769         mp.playlist.updateList()
770         mp.changeEntry(0)
771
772 def filescan(**kwargs):
773         from Components.Scanner import Scanner, ScanPath
774         return [
775                 Scanner(mimetypes = ["video/mpeg"],
776                         paths_to_scan =
777                                 [
778                                         ScanPath(path = "", with_subdirs = False),
779                                 ],
780                         name = "Movie",
781                         description = "View Movies...",
782                         openfnc = filescan_open,
783                 ),
784                 Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg"],
785                         paths_to_scan =
786                                 [
787                                         ScanPath(path = "", with_subdirs = False),
788                                 ],
789                         name = "Music",
790                         description = "Play Music...",
791                         openfnc = filescan_open,
792                 ),
793                 Scanner(mimetypes = ["audio/x-cda", "audio/x-wav"],
794                         paths_to_scan =
795                                 [
796                                         ScanPath(path = "", with_subdirs = False),
797                                 ],
798                         name = "Audio-CD",
799                         description = "Play Audio-CD...",
800                         openfnc = audioCD_open,
801                 )
802         ]
803
804 from Plugins.Plugin import PluginDescriptor
805 def Plugins(**kwargs):
806         return [
807                 PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu),
808                 PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
809         ]