try using cdiocddasrc for external usb optical drives too and make audio cd primary...
[openblackhole/openblackhole-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, popen
2 from time import strftime
3 from enigma import iPlayableService, 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 ServiceEventTracker, 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                 self.AudioCD_albuminfo = {}
166
167                 self.playlistIOInternal = PlaylistIOInternal()
168                 list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
169                 if list:
170                         for x in list:
171                                 self.playlist.addFile(x.ref)
172                         self.playlist.updateList()
173
174                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
175                         {
176                                 iPlayableService.evUpdatedInfo: self.__evUpdatedInfo
177                         })
178
179         def doNothing(self):
180                 pass
181
182         def createSummary(self):
183                 return MediaPlayerLCDScreen
184
185         def exit(self):
186                 self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5)
187
188         def exitCB(self, answer):
189                 if answer == True:
190                         self.playlistIOInternal.clear()
191                         for x in self.playlist.list:
192                                 self.playlistIOInternal.addService(ServiceReference(x[0]))
193                         if not self.isAudioCD:
194                                 self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
195                         self.close()
196
197         def checkSkipShowHideLock(self):
198                 self.updatedSeekState()
199
200         def doEofInternal(self, playing):
201                 if playing:
202                         self.nextEntry()
203                 else:
204                         self.show()
205
206         def __onClose(self):
207                 self.session.nav.playService(self.oldService)
208
209         def __evUpdatedInfo(self):
210                 currPlay = self.session.nav.getCurrentService()
211                 currenttitle = currPlay.info().getInfo(iServiceInformation.sCurrentTitle)
212                 totaltitles = currPlay.info().getInfo(iServiceInformation.sTotalTitles)
213                 sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
214                 print "[__evUpdatedInfo] title %d of %d (%s)" % (currenttitle, totaltitles, sTitle)
215                 self.readTitleInformation()
216
217         def delMPTimer(self):
218                 del self.rightKeyTimer
219                 del self.leftKeyTimer
220
221         def readTitleInformation(self):
222                 currPlay = self.session.nav.getCurrentService()
223                 if currPlay is not None:
224                         sTitle = currPlay.info().getInfoString(iServiceInformation.sTitle)
225                         sAlbum = currPlay.info().getInfoString(iServiceInformation.sAlbum)
226                         sGenre = currPlay.info().getInfoString(iServiceInformation.sGenre)
227                         sArtist = currPlay.info().getInfoString(iServiceInformation.sArtist)
228                         sYear = ""
229
230                         if sTitle == "":
231                                 if not self.isAudioCD:
232                                         sTitle = currPlay.info().getName().split('/')[-1]
233                                 else:
234                                         sTitle = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getName()
235
236                         if self.AudioCD_albuminfo:
237                                 if sAlbum == "" and "title" in self.AudioCD_albuminfo:
238                                         sAlbum = self.AudioCD_albuminfo["title"]
239                                 if sGenre == "" and "genre" in self.AudioCD_albuminfo:
240                                         sGenre = self.AudioCD_albuminfo["genre"]
241                                 if sArtist == "" and "artist" in self.AudioCD_albuminfo:
242                                         sArtist = self.AudioCD_albuminfo["artist"]
243                                 if "year" in self.AudioCD_albuminfo:
244                                         sYear = self.AudioCD_albuminfo["year"]
245
246                         self.updateMusicInformation( sArtist, sTitle, sAlbum, sYear, sGenre, clear = True )
247                 else:
248                         self.updateMusicInformation()
249
250         def updateMusicInformation(self, artist = "", title = "", album = "", year = "", genre = "", clear = False):
251                 self.updateSingleMusicInformation("artist", artist, clear)
252                 self.updateSingleMusicInformation("title", title, clear)
253                 self.updateSingleMusicInformation("album", album, clear)
254                 self.updateSingleMusicInformation("year", year, clear)
255                 self.updateSingleMusicInformation("genre", genre, clear)
256
257         def updateSingleMusicInformation(self, name, info, clear):
258                 if info != "" or clear:
259                         if self[name].getText() != info:
260                                 self[name].setText(info)
261
262         def updateCoverArtPixmap(self, path):
263                 while not path.endswith("/"):
264                         path = path[:-1]
265                 pngname = path + "folder.png"
266                 
267                 if not os_path.exists(pngname):
268                         pngname = self["coverArt"].default_pixmap
269                 if self.coverArtFileName != pngname:
270                         self.coverArtFileName = pngname
271                         self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
272
273         def leftDown(self):
274                 self.lefttimer = True
275                 self.leftKeyTimer.start(1000)
276
277         def rightDown(self):
278                 self.righttimer = True
279                 self.rightKeyTimer.start(1000)
280
281         def leftUp(self):
282                 if self.lefttimer:
283                         self.leftKeyTimer.stop()
284                         self.lefttimer = False
285                         self[self.currList].pageUp()
286                         self.updateCurrentInfo()
287
288         def rightUp(self):
289                 if self.righttimer:
290                         self.rightKeyTimer.stop()
291                         self.righttimer = False
292                         self[self.currList].pageDown()
293                         self.updateCurrentInfo()
294
295         def leftTimerFire(self):
296                 self.leftKeyTimer.stop()
297                 self.lefttimer = False
298                 self.switchToFileList()
299
300         def rightTimerFire(self):
301                 self.rightKeyTimer.stop()
302                 self.righttimer = False
303                 self.switchToPlayList()
304
305         def switchToFileList(self):
306                 self.currList = "filelist"
307                 self.filelist.selectionEnabled(1)
308                 self.playlist.selectionEnabled(0)
309                 self.updateCurrentInfo()
310
311         def switchToPlayList(self):
312                 if len(self.playlist) != 0:
313                         self.currList = "playlist"
314                         self.filelist.selectionEnabled(0)
315                         self.playlist.selectionEnabled(1)
316                         self.updateCurrentInfo()
317
318         def up(self):
319                 self[self.currList].up()
320                 self.updateCurrentInfo()
321
322         def down(self):
323                 self[self.currList].down()
324                 self.updateCurrentInfo()
325
326         def showAfterSeek(self):
327                 self.show()
328
329         def showAfterCuesheetOperation(self):
330                 self.show()
331
332         def hideAfterResume(self):
333                 self.hide()
334
335         def getIdentifier(self, ref):
336                 if self.isAudioCD:
337                         return ref.getName()
338                 else:
339                         text = ref.getPath()
340                         return text.split('/')[-1]
341
342         # FIXME: maybe this code can be optimized 
343         def updateCurrentInfo(self):
344                 text = ""
345                 if self.currList == "filelist":
346                         idx = self.filelist.getSelectionIndex()
347                         r = self.filelist.list[idx]
348                         text = r[1][7]
349                         if r[0][1] == True:
350                                 if len(text) < 2:
351                                         text += " "
352                                 if text[:2] != "..":
353                                         text = "/" + text
354                         self.summaries.setText(text,1)
355
356                         idx += 1
357                         if idx < len(self.filelist.list):
358                                 r = self.filelist.list[idx]
359                                 text = r[1][7]
360                                 if r[0][1] == True:
361                                         text = "/" + text
362                                 self.summaries.setText(text,3)
363                         else:
364                                 self.summaries.setText(" ",3)
365
366                         idx += 1
367                         if idx < len(self.filelist.list):
368                                 r = self.filelist.list[idx]
369                                 text = r[1][7]
370                                 if r[0][1] == True:
371                                         text = "/" + text
372                                 self.summaries.setText(text,4)
373                         else:
374                                 self.summaries.setText(" ",4)
375
376                         text = ""
377                         if not self.filelist.canDescent():
378                                 r = self.filelist.getServiceRef()
379                                 if r is None:
380                                         return
381                                 text = r.getPath()
382                                 self["currenttext"].setText(os_path.basename(text))
383
384                 if self.currList == "playlist":
385                         t = self.playlist.getSelection()
386                         if t is None:
387                                 return
388                         #display current selected entry on LCD
389                         text = self.getIdentifier(t)
390                         self.summaries.setText(text,1)
391                         self["currenttext"].setText(text)
392                         idx = self.playlist.getSelectionIndex()
393                         idx += 1
394                         if idx < len(self.playlist):
395                                 currref = self.playlist.getServiceRefList()[idx]
396                                 text = self.getIdentifier(currref)
397                                 self.summaries.setText(text,3)
398                         else:
399                                 self.summaries.setText(" ",3)
400
401                         idx += 1
402                         if idx < len(self.playlist):
403                                 currref = self.playlist.getServiceRefList()[idx]
404                                 text = self.getIdentifier(currref)
405                                 self.summaries.setText(text,4)
406                         else:
407                                 self.summaries.setText(" ",4)
408
409         def ok(self):
410                 if self.currList == "filelist":
411                         if self.filelist.canDescent():
412                                 self.filelist.descent()
413                                 self.updateCurrentInfo()
414                         else:
415                                 self.copyFile()
416
417                 if self.currList == "playlist":
418                         selection = self["playlist"].getSelection()
419                         self.changeEntry(self.playlist.getSelectionIndex())
420
421         def showMenu(self):
422                 menu = []
423                 if self.currList == "filelist":
424                         if self.filelist.canDescent():
425                                 menu.append((_("add directory to playlist"), "copydir"))
426                         else:
427                                 menu.append((_("add files to playlist"), "copyfiles"))
428                         menu.append((_("switch to playlist"), "playlist"))
429                 else:
430                         menu.append((_("switch to filelist"), "filelist"))
431
432                         menu.append((_("shuffle playlist"), "shuffle"))
433
434                         menu.append((_("delete"), "delete"))
435                         menu.append((_("clear playlist"), "clear"))
436                 menu.append((_("hide player"), "hide"));
437                 menu.append((_("save playlist"), "saveplaylist"));
438                 menu.append((_("load playlist"), "loadplaylist"));
439                 menu.append((_("delete saved playlist"), "deleteplaylist"));
440                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
441
442         def menuCallback(self, choice):
443                 if choice is None:
444                         return
445
446                 if choice[1] == "copydir":
447                         self.copyDirectory(self.filelist.getSelection()[0])
448                 elif choice[1] == "copyfiles":
449                         self.stopEntry()
450                         self.playlist.clear()
451                         self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
452                         self.playServiceRefEntry(self.filelist.getServiceRef())
453                 elif choice[1] == "playlist":
454                         self.switchToPlayList()
455                 elif choice[1] == "filelist":
456                         self.switchToFileList()
457                 elif choice[1] == "delete":
458                         if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
459                                 self.stopEntry()
460                         self.deleteEntry()
461                 elif choice[1] == "clear":
462                         self.stopEntry()
463                         self.playlist.clear()
464                         self.switchToFileList()
465                 elif choice[1] == "hide":
466                         self.hide()
467                 elif choice[1] == "saveplaylist":
468                         self.save_playlist()
469                 elif choice[1] == "loadplaylist":
470                         self.load_playlist()
471                 elif choice[1] == "deleteplaylist":
472                         self.delete_saved_playlist()
473                 elif choice[1] == "shuffle":
474                         self.playlist.PlayListShuffle()
475
476
477         def showEventInformation(self):
478                 from Screens.EventView import EventViewSimple
479                 from ServiceReference import ServiceReference
480                 evt = self[self.currList].getCurrentEvent()
481                 if evt:
482                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
483
484         # also works on filelist (?)
485         def getCurrent(self):
486                 return self["playlist"].getCurrent()
487
488         def deletePlaylistEntry(self):
489                 if self.currList == "playlist":
490                         if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
491                                 self.stopEntry()
492                         self.deleteEntry()
493
494         def skip_listbegin(self):
495                 if self.currList == "filelist":
496                         self.filelist.moveToIndex(0)
497                 else:
498                         self.playlist.moveToIndex(0)
499                 self.updateCurrentInfo()
500
501         def skip_listend(self):
502                 if self.currList == "filelist":
503                         idx = len(self.filelist.list)
504                         self.filelist.moveToIndex(idx - 1)
505                 else:
506                         self.playlist.moveToIndex(len(self.playlist)-1)
507                 self.updateCurrentInfo()
508
509         def save_playlist(self):
510                 self.session.openWithCallback(self.save_playlist2,InputBox, title=_("Please enter filename (empty = use current date)"),windowTitle = _("Save Playlist"))
511
512         def save_playlist2(self, name):
513                 if name is not None:
514                         name = name.strip()
515                         if name == "":
516                                 name = strftime("%y%m%d_%H%M%S")
517                         name += ".e2pls"
518                         self.playlistIOInternal.clear()
519                         for x in self.playlist.list:
520                                 self.playlistIOInternal.addService(ServiceReference(x[0]))
521                         self.playlistIOInternal.save(resolveFilename(SCOPE_PLAYLIST) + name)
522
523         def load_playlist(self):
524                 listpath = []
525                 playlistdir = resolveFilename(SCOPE_PLAYLIST)
526                 try:
527                         for i in os_listdir(playlistdir):
528                                 listpath.append((i,playlistdir + i))
529                 except IOError,e:
530                         print "Error while scanning subdirs ",e
531                 self.session.openWithCallback(self.PlaylistSelected, ChoiceBox, title=_("Please select a playlist..."), list = listpath)
532
533         def PlaylistSelected(self,path):
534                 if path is not None:
535                         self.clear_playlist()
536                         self.playlistIOInternal = PlaylistIOInternal()
537                         list = self.playlistIOInternal.open(path[1])
538                         if list:
539                                 for x in list:
540                                         self.playlist.addFile(x.ref)
541                                 self.playlist.updateList()
542
543         def delete_saved_playlist(self):
544                 listpath = []
545                 playlistdir = resolveFilename(SCOPE_PLAYLIST)
546                 try:
547                         for i in os_listdir(playlistdir):
548                                 listpath.append((i,playlistdir + i))
549                 except IOError,e:
550                         print "Error while scanning subdirs ",e
551                 self.session.openWithCallback(self.DeletePlaylistSelected, ChoiceBox, title=_("Please select a playlist to delete..."), list = listpath)
552
553         def DeletePlaylistSelected(self,path):
554                 if path is not None:
555                         self.delname = path[1]
556                         self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (path[1]))
557
558         def deleteConfirmed(self, confirmed):
559                 if confirmed:
560                         os_remove(self.delname)
561
562         def clear_playlist(self):
563                 self.stopEntry()
564                 self.playlist.clear()
565                 self.switchToFileList()
566
567         def copyDirectory(self, directory, recursive = True):
568                 print "copyDirectory", directory
569                 filelist = FileList(directory, useServiceRef = True, isTop = True)
570
571                 for x in filelist.getFileList():
572                         if x[0][1] == True: #isDir
573                                 if recursive:
574                                         self.copyDirectory(x[0][0])
575                         else:
576                                 self.playlist.addFile(x[0][0])
577                 self.playlist.updateList()
578
579         def copyFile(self):
580                 if self.filelist.getServiceRef().type == 4098: # playlist
581                         ServiceRef = self.filelist.getServiceRef()
582                         extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:]
583                         print "extension:", extension
584                         if self.playlistparsers.has_key(extension):
585                                 playlist = self.playlistparsers[extension]()
586                                 list = playlist.open(ServiceRef.getPath())
587                                 for x in list:
588                                         self.playlist.addFile(x.ref)
589                 else:
590                         self.playlist.addFile(self.filelist.getServiceRef())
591                         self.playlist.updateList()
592                         if len(self.playlist) == 1:
593                                 self.changeEntry(0)
594
595         def addPlaylistParser(self, parser, extension):
596                 self.playlistparsers[extension] = parser
597
598         def nextEntry(self):
599                 next = self.playlist.getCurrentIndex() + 1
600                 if next < len(self.playlist):
601                         self.changeEntry(next)
602
603         def nextMarkOrEntry(self):
604                 if not self.jumpPreviousNextMark(lambda x: x):
605                         next = self.playlist.getCurrentIndex() + 1
606                         if next < len(self.playlist):
607                                 self.changeEntry(next)
608                         else:
609                                 self.doSeek(-1)
610
611         def previousMarkOrEntry(self):
612                 if not self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True):
613                         next = self.playlist.getCurrentIndex() - 1
614                         if next >= 0:
615                                 self.changeEntry(next)
616
617         def deleteEntry(self):
618                 self.playlist.deleteFile(self.playlist.getSelectionIndex())
619                 self.playlist.updateList()
620                 if len(self.playlist) == 0:
621                         self.switchToFileList()
622
623         def changeEntry(self, index):
624                 self.playlist.setCurrentPlaying(index)
625                 self.playEntry()
626
627         def playServiceRefEntry(self, serviceref):
628                 serviceRefList = self.playlist.getServiceRefList()
629                 for count in range(len(serviceRefList)):
630                         if serviceRefList[count] == serviceref:
631                                 self.changeEntry(count)
632                                 break
633                         
634         def xplayEntry(self):
635                 if self.currList == "playlist":
636                         self.playEntry()
637                 else:
638                         self.stopEntry()
639                         self.playlist.clear()
640                         sel = self.filelist.getSelection()
641                         if sel:
642                                 if sel[1]: # can descent
643                                         # add directory to playlist
644                                         self.copyDirectory(sel[0])
645                                 else:
646                                         # add files to playlist
647                                         self.copyDirectory(os_path.dirname(sel[0].getPath()) + "/", recursive = False)
648                         if len(self.playlist) > 0:
649                                 self.changeEntry(0)
650         
651         def playEntry(self):
652                 if len(self.playlist.getServiceRefList()):
653                         needsInfoUpdate = False
654                         currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()]
655                         if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference():
656                                 self.session.nav.playService(self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()])
657                                 info = eServiceCenter.getInstance().info(currref)
658                                 description = info and info.getInfoString(currref, iServiceInformation.sDescription) or ""
659                                 self["title"].setText(description)
660                                 # display just playing musik on LCD
661                                 idx = self.playlist.getCurrentIndex()
662                                 currref = self.playlist.getServiceRefList()[idx]
663                                 text = self.getIdentifier(currref)
664                                 text = ">"+text
665                                 ext = text[-3:].lower()
666
667                                 # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead 
668                                 if ext not in ["mp3", "wav", "ogg"] and not self.isAudioCD:
669                                         self.hide()
670                                 else:
671                                         needsInfoUpdate = True
672                                 self.summaries.setText(text,1)
673
674                                 # get the next two entries
675                                 idx += 1
676                                 if idx < len(self.playlist):
677                                         currref = self.playlist.getServiceRefList()[idx]
678                                         text = self.getIdentifier(currref)
679                                         self.summaries.setText(text,3)
680                                 else:
681                                         self.summaries.setText(" ",3)
682
683                                 idx += 1
684                                 if idx < len(self.playlist):
685                                         currref = self.playlist.getServiceRefList()[idx]
686                                         text = self.getIdentifier(currref)
687                                         self.summaries.setText(text,4)
688                                 else:
689                                         self.summaries.setText(" ",4)
690                         else:
691                                 idx = self.playlist.getCurrentIndex()
692                                 currref = self.playlist.getServiceRefList()[idx]
693                                 text = currref.getPath()
694                                 ext = text[-3:].lower()
695                                 if ext not in ["mp3", "wav", "ogg"] and not self.isAudioCD:
696                                         self.hide()
697                                 else:
698                                         needsInfoUpdate = True
699
700                         self.unPauseService()
701                         if needsInfoUpdate == True:
702                                 self.updateCoverArtPixmap(currref.getPath())
703                         else:
704                                 pngname = self["coverArt"].default_pixmap
705                                 self.coverArtFileName = pngname
706                                 self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
707                         self.readTitleInformation()
708
709         def updatedSeekState(self):
710                 if self.seekstate == self.SEEK_STATE_PAUSE:
711                         self.playlist.pauseFile()
712                 elif self.seekstate == self.SEEK_STATE_PLAY:
713                         self.playlist.playFile()
714                 elif self.isStateForward(self.seekstate):
715                         self.playlist.forwardFile()
716                 elif self.isStateBackward(self.seekstate):
717                         self.playlist.rewindFile()
718
719         def pauseEntry(self):
720                 self.pauseService()
721                 self.show()
722
723         def stopEntry(self):
724                 self.playlist.stopFile()
725                 self.session.nav.playService(None)
726                 self.updateMusicInformation(clear=True)
727                 self.show()
728
729         def unPauseService(self):
730                 self.setSeekState(self.SEEK_STATE_PLAY)
731
732 class MediaPlayerLCDScreen(Screen):
733         skin = """
734         <screen position="0,0" size="132,64" title="LCD Text">
735                 <widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
736                 <widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
737                 <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
738         </screen>"""
739
740         def __init__(self, session, parent):
741                 Screen.__init__(self, session)
742                 self["text1"] = Label("Mediaplayer")
743                 self["text3"] = Label("")
744                 self["text4"] = Label("")
745
746         def setText(self, text, line):
747                 print "lcd set text:", text, line
748                 if len(text) > 10:
749                         if text[-4:] == ".mp3":
750                                 text = text[:-4]
751                 textleer = "    "
752                 text = text + textleer*10
753                 if line == 1:
754                         self["text1"].setText(text)
755                 elif line == 3:
756                         self["text3"].setText(text)
757                 elif line == 4:
758                         self["text4"].setText(text)
759
760 def main(session, **kwargs):
761         session.open(MediaPlayer)
762
763 def menu(menuid, **kwargs):
764         if menuid == "mainmenu":
765                 return [(_("Media player"), main, "media_player", 45)]
766         return []
767
768 def filescan_open(list, session, **kwargs):
769         from enigma import eServiceReference
770
771         mp = session.open(MediaPlayer)
772
773         mp.switchToPlayList()
774         for file in list:
775                 ref = eServiceReference(4097, 0, file.path)
776                 mp.playlist.addFile(ref)
777
778         # TODO: rather play first than last file?
779         mp.playServiceRefEntry(ref)
780         mp.playlist.updateList()
781
782 def audioCD_open(list, session, **kwargs):
783         from enigma import eServiceReference
784
785         mp = session.open(MediaPlayer)
786
787         mp.playlist.clear()
788         mp.isAudioCD = True
789
790         for file in list:
791                 ref = eServiceReference(4097, 0, file.path)
792                 mp.playlist.addFile(ref)
793         from Plugins.Extensions.CDInfo.plugin import Query
794         cdinfo = Query(mp)
795         cdinfo.scan()
796
797         mp.changeEntry(0)
798         mp.switchToPlayList()
799
800 def filescan(**kwargs):
801         from Components.Scanner import Scanner, ScanPath
802         mediatypes = [
803                 Scanner(mimetypes = ["video/mpeg"],
804                         paths_to_scan =
805                                 [
806                                         ScanPath(path = "", with_subdirs = False),
807                                 ],
808                         name = "Movie",
809                         description = "View Movies...",
810                         openfnc = filescan_open,
811                 ),
812                 Scanner(mimetypes = ["audio/mpeg", "audio/x-wav", "application/ogg"],
813                         paths_to_scan =
814                                 [
815                                         ScanPath(path = "", with_subdirs = False),
816                                 ],
817                         name = "Music",
818                         description = "Play Music...",
819                         openfnc = filescan_open,
820                 )]
821         try:
822                 from Plugins.Extensions.CDInfo.plugin import Query
823                 mediatypes.insert(0,Scanner(mimetypes = ["audio/x-cda", "audio/x-wav"],
824                         paths_to_scan =
825                                 [
826                                         ScanPath(path = "", with_subdirs = False),
827                                 ],
828                         name = "Audio-CD",
829                         description = "Play Audio-CD...",
830                         openfnc = audioCD_open,
831                 ))
832                 return mediatypes
833         except ImportError:
834                 return mediatypes
835
836 from Plugins.Plugin import PluginDescriptor
837 def Plugins(**kwargs):
838         return [
839                 PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu),
840                 PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
841         ]