add 'weight' for menu entries (including plugins), so they can be sorted, patch by...
[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, iPlayableService, 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 ServiceEventTracker
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 MediaPlayer(Screen, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, HelpableScreen):
34         ALLOW_SUSPEND = True
35         ENABLE_RESUME_SUPPORT = True
36
37         def __init__(self, session, args = None):
38                 Screen.__init__(self, session)
39                 InfoBarAudioSelection.__init__(self)
40                 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
41                 InfoBarNotifications.__init__(self)
42                 HelpableScreen.__init__(self)
43                 self.summary = None
44                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
45                 self.session.nav.stopService()
46
47                 self.playlistparsers = {}
48                 self.addPlaylistParser(PlaylistIOM3U, "m3u")
49                 self.addPlaylistParser(PlaylistIOPLS, "pls")
50                 self.addPlaylistParser(PlaylistIOInternal, "e2pls")
51
52                 # 'None' is magic to start at the list of mountpoints
53                 self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob)", useServiceRef = True)
54                 self["filelist"] = self.filelist
55
56                 self.playlist = MyPlayList()
57                 #self.playlist = PlayList()
58                 self.is_closing = False
59                 self.delname = ""
60                 self["playlist"] = self.playlist
61
62                 self["PositionGauge"] = ServicePositionGauge(self.session.nav)
63
64                 self["currenttext"] = Label("")
65
66                 self["artisttext"] = Label(_("Artist:"))
67                 self["artist"] = Label("")
68                 self["titletext"] = Label(_("Title:"))
69                 self["title"] = Label("")
70                 self["albumtext"] = Label(_("Album:"))
71                 self["album"] = Label("")
72                 self["yeartext"] = Label(_("Year:"))
73                 self["year"] = Label("")
74                 self["genretext"] = Label(_("Genre:"))
75                 self["genre"] = Label("")
76                 self["coverArt"] = Pixmap()
77
78                 self.seek_target = None
79
80                 class MoviePlayerActionMap(NumberActionMap):
81                         def __init__(self, player, contexts = [ ], actions = { }, prio=0):
82                                 NumberActionMap.__init__(self, contexts, actions, prio)
83                                 self.player = player
84
85                         def action(self, contexts, action):
86                                 self.player.show()
87                                 return NumberActionMap.action(self, contexts, action)
88
89
90                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", 
91                         {
92                                 "ok": (self.ok, _("add file to playlist")),
93                                 "cancel": (self.exit, _("exit mediaplayer")),
94                         }, -2)
95
96                 self["MediaPlayerActions"] = HelpableActionMap(self, "MediaPlayerActions", 
97                         {
98                                 "play": (self.playEntry, _("play entry")),
99                                 "pause": (self.pauseEntry, _("pause")),
100                                 "stop": (self.stopEntry, _("stop entry")),
101                                 "previous": (self.previousEntry, _("play previous playlist entry")),
102                                 "next": (self.nextEntry, _("play next playlist entry")),
103                                 "menu": (self.showMenu, _("menu")),
104                                 "skipListbegin": (self.skip_listbegin, _("jump to listbegin")),
105                                 "skipListend": (self.skip_listend, _("jump to listend")),
106                                 "prevBouquet": (self.switchToPlayList, _("switch to playlist")),
107                                 "nextBouquet": (self.switchToFileList, _("switch to filelist")),
108                                 "delete": (self.deletePlaylistEntry, _("delete playlist entry")),
109                                 "shift_stop": (self.clear_playlist, _("clear playlist")),
110                                 "shift_record": (self.playlist.PlayListShuffle, _("shuffle playlist")),
111                         }, -2)
112
113                 self["InfobarEPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
114                         {
115                                 "showEventInfo": (self.showEventInformation, _("show event details")),
116                         })
117
118                 self["actions"] = MoviePlayerActionMap(self, ["DirectionActions"], 
119                 {
120                         "right": self.rightDown,
121                         "rightRepeated": self.doNothing,
122                         "rightUp": self.rightUp,
123                         "left": self.leftDown,
124                         "leftRepeated": self.doNothing,
125                         "leftUp": self.leftUp,
126
127                         "up": self.up,
128                         "upRepeated": self.up,
129                         "upUp": self.doNothing,
130                         "down": self.down,
131                         "downRepeated": self.down,
132                         "downUp": self.doNothing,
133                 }, -2)
134
135                 InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions")
136
137                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
138                         {
139                                 #iPlayableService.evStart: self.__serviceStarted,
140                                 #iPlayableService.evSeekableStatusChanged: InfoBarSeek.__seekableStatusChanged,
141
142                                 iPlayableService.evEOF: self.__evEOF,
143                         })
144
145                 self.onClose.append(self.delMPTimer)
146                 self.onClose.append(self.__onClose)
147
148                 self.righttimer = False
149                 self.rightKeyTimer = eTimer()
150                 self.rightKeyTimer.timeout.get().append(self.rightTimerFire)
151
152                 self.lefttimer = False
153                 self.leftKeyTimer = eTimer()
154                 self.leftKeyTimer.timeout.get().append(self.leftTimerFire)
155
156                 self.infoTimer = eTimer()
157                 self.infoTimer.timeout.get().append(self.infoTimerFire)
158                 self.infoTimer.start(500)
159
160                 self.currList = "filelist"
161
162                 self.coverArtFileName = ""
163
164                 self.playlistIOInternal = PlaylistIOInternal()
165                 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
166                 if list:
167                         for x in list:
168                                 self.playlist.addFile(x.ref)
169                         self.playlist.updateList()
170
171         def doNothing(self):
172                 pass
173
174         def createSummary(self):
175                 return MediaPlayerLCDScreen
176
177         def exit(self):
178                 self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5)
179
180         def exitCB(self, answer):
181                 if answer == True:
182                         self.playlistIOInternal.clear()
183                         for x in self.playlist.list:
184                                 self.playlistIOInternal.addService(ServiceReference(x[0]))
185                         self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
186                         self.close()
187
188         def checkSkipShowHideLock(self):
189                 self.updatedSeekState()
190
191         def __evEOF(self):
192                 self.nextEntry()
193
194         def __onClose(self):
195                 self.session.nav.playService(self.oldService)
196
197         def delMPTimer(self):
198                 del self.rightKeyTimer
199                 del self.leftKeyTimer
200                 del self.infoTimer
201
202         def infoTimerFire(self):
203                 currPlay = self.session.nav.getCurrentService()
204                 if currPlay is not None:
205                         stitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
206                         if stitle == "":
207                                 stitle = currPlay.info().getName().split('/')[-1]
208
209                         self.updateMusicInformation( artist = currPlay.info().getInfoString(iServiceInformation.sArtist),
210                                                                                  title = stitle,
211                                                                                  album = currPlay.info().getInfoString(iServiceInformation.sAlbum),
212                                                                                  genre = currPlay.info().getInfoString(iServiceInformation.sGenre),
213                                                                                  clear = True)
214                         self.updateCoverArtPixmap( currPlay.info().getName() )
215                 else:
216                         self.updateMusicInformation()
217                         self.updateCoverArtPixmap( "" )
218
219         def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
220                 self.updateSingleMusicInformation("artist", artist, clear)
221                 self.updateSingleMusicInformation("title", title, clear)
222                 self.updateSingleMusicInformation("album", album, clear)
223                 self.updateSingleMusicInformation("year", year, clear)
224                 self.updateSingleMusicInformation("genre", genre, clear)
225
226         def updateSingleMusicInformation(self, name, info, clear):
227                 if info != "" or clear:
228                         if self[name].getText() != info:
229                                 self[name].setText(info)
230
231         def updateCoverArtPixmap(self, currentServiceName):
232                 filename = currentServiceName
233                 # The "getName" usually adds something like "MP3 File:" infront of filename
234                 # Get rid of this...by finding the first "/"
235                 # FIXME: this should be fixed in the servicemp3.cpp handler
236                 filename = filename[filename.find("/"):]
237                 path = os_path.dirname(filename)
238                 pngname = path + "/" + "folder.png"
239                 if not os_path.exists(pngname):
240                         pngname = resolveFilename(SCOPE_SKIN_IMAGE, "no_coverArt.png")
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 previousEntry(self):
572                 next = self.playlist.getCurrentIndex() - 1
573                 if next >= 0:
574                         self.changeEntry(next)
575
576         def deleteEntry(self):
577                 self.playlist.deleteFile(self.playlist.getSelectionIndex())
578                 self.playlist.updateList()
579                 if len(self.playlist) == 0:
580                         self.switchToFileList()
581
582         def changeEntry(self, index):
583                 self.playlist.setCurrentPlaying(index)
584                 self.playEntry()
585
586         def playServiceRefEntry(self, serviceref):
587                 serviceRefList = self.playlist.getServiceRefList()
588                 for count in range(len(serviceRefList)):
589                         if serviceRefList[count] == serviceref:
590                                 self.changeEntry(count)
591                                 break
592
593         def playEntry(self):
594                 if len(self.playlist.getServiceRefList()):
595                         currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
596                         if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
597                                 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
598                                 info = eServiceCenter.getInstance().info(currref)
599                                 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
600                                 self["title"].setText(description)
601                                 # display just playing musik on LCD
602                                 idx = self.playlist.getCurrentIndex()
603                                 currref = self.playlist.getServiceRefList()[idx]
604                                 text = currref.getPath()
605                                 text = text.split('/')[-1]
606                                 text = ">"+text
607                                 ext = text[-3:].lower()
608
609                                 # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
610                                 if ext not in ["mp3", "wav", "ogg"]:
611                                         self.hide()
612                                 self.summaries.setText(text,1)
613
614                                 # get the next two entries
615                                 idx += 1
616                                 if idx < len(self.playlist):
617                                         currref = self.playlist.getServiceRefList()[idx]
618                                         text = currref.getPath()
619                                         text = text.split('/')[-1]
620                                         self.summaries.setText(text,3)
621                                 else:
622                                         self.summaries.setText(" ",3)
623
624                                 idx += 1
625                                 if idx < len(self.playlist):
626                                         currref = self.playlist.getServiceRefList()[idx]
627                                         text = currref.getPath()
628                                         text = text.split('/')[-1]
629                                         self.summaries.setText(text,4)
630                                 else:
631                                         self.summaries.setText(" ",4)
632                         else:
633                                 idx = self.playlist.getCurrentIndex()
634                                 currref = self.playlist.getServiceRefList()[idx]
635                                 text = currref.getPath()
636                                 ext = text[-3:].lower()
637                                 if ext not in ["mp3", "wav", "ogg"]:
638                                         self.hide()
639                         self.unPauseService()
640
641         def updatedSeekState(self):
642                 if self.seekstate == self.SEEK_STATE_PAUSE:
643                         self.playlist.pauseFile()
644                 elif self.seekstate == self.SEEK_STATE_PLAY:
645                         self.playlist.playFile()
646                 elif self.seekstate in ( self.SEEK_STATE_FF_2X,
647                                                                  self.SEEK_STATE_FF_4X,
648                                                                  self.SEEK_STATE_FF_8X,
649                                                                  self.SEEK_STATE_FF_16X,
650                                                                  self.SEEK_STATE_FF_32X,
651                                                                  self.SEEK_STATE_FF_48X,
652                                                                  self.SEEK_STATE_FF_64X,
653                                                                  self.SEEK_STATE_FF_128X):
654                         self.playlist.forwardFile()
655                 elif self.seekstate in ( self.SEEK_STATE_BACK_8X,
656                                                                  self.SEEK_STATE_BACK_16X,
657                                                                  self.SEEK_STATE_BACK_32X,
658                                                                  self.SEEK_STATE_BACK_48X,
659                                                                  self.SEEK_STATE_BACK_64X,
660                                                                  self.SEEK_STATE_BACK_128X):
661                         self.playlist.rewindFile()
662
663         def pauseEntry(self):
664                 self.pauseService()
665                 self.show()
666
667         def stopEntry(self):
668                 self.playlist.stopFile()
669                 self.session.nav.playService(None)
670                 self.updateMusicInformation(clear=True)
671                 self.show()
672
673         def unPauseService(self):
674                 self.setSeekState(self.SEEK_STATE_PLAY)
675
676
677 class MediaPlayerLCDScreen(Screen):
678         skin = """
679         <screen position="0,0" size="132,64" title="LCD Text">
680                 <widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
681                 <widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
682                 <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
683         </screen>"""
684
685         def __init__(self, session, parent):
686                 Screen.__init__(self, session)
687                 self["text1"] = Label("Mediaplayer")
688                 self["text3"] = Label("")
689                 self["text4"] = Label("")
690
691         def setText(self, text, line):
692                 print "lcd set text:", text, line
693                 if len(text) > 10:
694                         if text[-4:] == ".mp3":
695                                 text = text[:-4]
696                 textleer = "    "
697                 text = text + textleer*10
698                 if line == 1:
699                         self["text1"].setText(text)
700                 elif line == 3:
701                         self["text3"].setText(text)
702                 elif line == 4:
703                         self["text4"].setText(text)
704
705 def main(session, **kwargs):
706         session.open(MediaPlayer)
707
708 def menu(menuid, **kwargs):
709         if menuid == "mainmenu":
710                 return [(_("Media player"), main, "media_player", None)]
711         return []
712
713 def filescan_open(list, session, **kwargs):
714         from enigma import eServiceReference
715
716         mp = session.open(MediaPlayer)
717
718         mp.switchToPlayList()
719         for file in list:
720                 ref = eServiceReference(4097, 0, file.path)
721                 mp.playlist.addFile(ref)
722
723         # TODO: rather play first than last file?
724         mp.playServiceRefEntry(ref)
725         mp.playlist.updateList()
726
727 def filescan(**kwargs):
728         from Components.Scanner import Scanner, ScanPath
729         return [
730                 Scanner(mimetypes = ["video/mpeg"],
731                         paths_to_scan =
732                                 [
733                                         ScanPath(path = "", with_subdirs = False),
734                                 ],
735                         name = "Movie",
736                         description = "View Movies...",
737                         openfnc = filescan_open,
738                 ),
739                 Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg"],
740                         paths_to_scan =
741                                 [
742                                         ScanPath(path = "", with_subdirs = False),
743                                 ],
744                         name = "Music",
745                         description = "Play Music...",
746                         openfnc = filescan_open,
747                 )
748         ]
749
750 from Plugins.Plugin import PluginDescriptor
751 def Plugins(**kwargs):
752         return [
753                 PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu),
754                 PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
755         ]