decode id3 cover art images embedded into mp3 files and show them in mediaplayer
[vuplus_dvbapp] / lib / python / Plugins / Extensions / MediaPlayer / plugin.py
index b12e03e..b6d87a6 100644 (file)
@@ -1,6 +1,6 @@
 from os import path as os_path, remove as os_remove, listdir as os_listdir
 from time import strftime
-from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, loadPic
+from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, ePicLoad
 from ServiceReference import ServiceReference
 from Screens.Screen import Screen
 from Screens.HelpMenu import HelpableScreen
@@ -21,6 +21,7 @@ from Components.Harddisk import harddiskmanager
 from Components.config import config
 from Tools.Directories import fileExists, pathExists, resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
 from settings import MediaPlayerSettings
+from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
 import random
 
 class MyPlayList(PlayList):
@@ -34,18 +35,58 @@ class MyPlayList(PlayList):
                self.oldCurrPlaying = -1
 
 class MediaPixmap(Pixmap):
+       def __init__(self):
+               Pixmap.__init__(self)
+               self.coverArtFileName = ""
+               self.picload = ePicLoad()
+               self.picload.PictureData.get().append(self.paintCoverArtPixmapCB)
+               self.coverFileNames = ["folder.png", "folder.jpg"]
+
        def applySkin(self, desktop, screen):
-               self.default_pixmap = None
+               from Tools.LoadPixmap import LoadPixmap
                if self.skinAttributes is not None:
                        for (attrib, value) in self.skinAttributes:
                                if attrib == "pixmap":
-                                       self.default_pixmap = value
+                                       noCoverFile = value
                                        break
-               if self.default_pixmap is None:
-                       self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
-               self.coverFileNames = ["folder.png", "folder.jpg"]
+               if noCoverFile is None:
+                       noCoverFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
+               self.noCoverPixmap = LoadPixmap(noCoverFile)
                return Pixmap.applySkin(self, desktop, screen)
 
+       def onShow(self):
+               Pixmap.onShow(self)
+               sc = AVSwitch().getFramebufferScale()
+               #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB)
+               self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
+
+       def paintCoverArtPixmapCB(self, picInfo=None):
+               ptr = self.picload.getData()
+               if ptr != None:
+                       self.instance.setPixmap(ptr.__deref__())
+
+       def updateCoverArt(self, path):
+               while not path.endswith("/"):
+                       path = path[:-1]
+               new_coverArtFileName = None
+               for filename in self.coverFileNames:
+                       if fileExists(path + filename):
+                               new_coverArtFileName = path + filename
+               if self.coverArtFileName != new_coverArtFileName:
+                       self.coverArtFileName = new_coverArtFileName
+                       if new_coverArtFileName:
+                               self.picload.startDecode(self.coverArtFileName)
+                       else:
+                               self.showDefaultCover()
+
+       def showDefaultCover(self):
+               self.instance.setPixmap(self.noCoverPixmap)
+
+       def embeddedCoverArt(self):
+               print "[embeddedCoverArt] found"
+               self.coverArtFileName = "/tmp/.id3coverart"
+               self.picload.startDecode(self.coverArtFileName)
+
 class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen):
        ALLOW_SUSPEND = True
        ENABLE_RESUME_SUPPORT = True
@@ -73,7 +114,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self["filelist"] = self.filelist
 
                self.playlist = MyPlayList()
-               #self.playlist = PlayList()
                self.is_closing = False
                self.delname = ""
                self["playlist"] = self.playlist
@@ -96,6 +136,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self["repeat"] = MultiPixmap()
 
                self.seek_target = None
+               hotplugNotifier.append(self.hotplugCB)
 
                class MoviePlayerActionMap(NumberActionMap):
                        def __init__(self, player, contexts = [ ], actions = { }, prio=0):
@@ -167,11 +208,9 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self.leftKeyTimer.callback.append(self.leftTimerFire)
 
                self.currList = "filelist"
-
-               self.coverArtFileName = ""
                self.isAudioCD = False
                self.AudioCD_albuminfo = {}
-
+               self.cdAudioTrackFiles = []
                self.applySettings()
 
                self.playlistIOInternal = PlaylistIOInternal()
@@ -185,7 +224,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        {
                                iPlayableService.evUpdatedInfo: self.__evUpdatedInfo,
                                iPlayableService.evUser+11: self.__evDecodeError,
-                               iPlayableService.evUser+12: self.__evPluginError
+                               iPlayableService.evUser+12: self.__evPluginError,
+                               iPlayableService.evUser+13: self["coverArt"].embeddedCoverArt
                        })
 
        def doNothing(self):
@@ -203,6 +243,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                if config.mediaplayer.saveDirOnExit.getValue():
                        config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory())
                        config.mediaplayer.defaultDir.save()
+               hotplugNotifier.remove(self.hotplugCB)
+               del self["coverArt"].picload
                self.close()
 
        def checkSkipShowHideLock(self):
@@ -282,19 +324,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        if self[name].getText() != info:
                                self[name].setText(info)
 
-       def updateCoverArtPixmap(self, path):
-               while not path.endswith("/"):
-                       path = path[:-1]
-               new_coverArtFileName = self["coverArt"].default_pixmap
-               for filename in self["coverArt"].coverFileNames:
-                       if fileExists(path + filename):
-                               new_coverArtFileName = path + filename
-               if self.coverArtFileName != new_coverArtFileName:
-                       self.coverArtFileName = new_coverArtFileName
-                       pixmap = loadPic(self.coverArtFileName, 116, 116, AVSwitch().getAspectRatioSetting()/2,1,0,0)
-                       if pixmap is not None:
-                               self["coverArt"].instance.setPixmap(pixmap.__deref__())
-
        def leftDown(self):
                self.lefttimer = True
                self.leftKeyTimer.start(1000)
@@ -445,6 +474,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
        def showMenu(self):
                menu = []
+               if len(self.cdAudioTrackFiles):
+                       menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
                if self.currList == "filelist":
                        if self.filelist.canDescent():
                                menu.append((_("add directory to playlist"), "copydir"))
@@ -462,9 +493,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                menu.append((_("load playlist"), "loadplaylist"));
                menu.append((_("delete saved playlist"), "deleteplaylist"));
                menu.append((_("Edit settings"), "settings"))
-               drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
-               if pathExists(drivepath):
-                       menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
@@ -504,16 +532,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                elif choice[1] == "settings":
                        self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self)
                elif choice[1] == "audiocd":
-                       from Components.Scanner import scanDevice
-                       drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
-                       self.cdAudioTrackFiles = []
-                       res = scanDevice(drivepath)
-                       list = [ (r.description, r, res[r], self.session) for r in res ]
-                       if list:
-                               (desc, scanner, files, session) = list[0]
-                               for file in files:
-                                       if file.mimetype == "audio/x-cda":
-                                               self.cdAudioTrackFiles.append(file.path)
                        self.playAudioCD()
 
        def playAudioCD(self):
@@ -626,7 +644,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        try:
                                os_remove(self.delname)
                        except OSError,e:
-                               self.session.open(MessageBox, _("Delete failed!, %s") %e, MessageBox.TYPE_ERROR)
+                               print "delete failed:", e
+                               self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
 
        def clear_playlist(self):
                self.isAudioCD = False
@@ -832,11 +851,9 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        self.unPauseService()
                        if needsInfoUpdate == True:
                                path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath()
-                               self.updateCoverArtPixmap(path)
+                               self["coverArt"].updateCoverArt(path)
                        else:
-                               pngname = self["coverArt"].default_pixmap
-                               self.coverArtFileName = pngname
-                               self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
+                               self["coverArt"].showDefaultCover()
                        self.readTitleInformation()
 
        def updatedSeekState(self):
@@ -867,7 +884,25 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                
        def subtitleSelection(self):
                from Screens.Subtitles import Subtitles
-               self.session.open(Subtitles)            
+               self.session.open(Subtitles)
+       
+       def hotplugCB(self, dev, media_state):
+               if dev == harddiskmanager.getCD():
+                       if media_state == "1":
+                               from Components.Scanner import scanDevice
+                               devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
+                               self.cdAudioTrackFiles = []
+                               res = scanDevice(devpath)
+                               list = [ (r.description, r, res[r], self.session) for r in res ]
+                               if list:
+                                       (desc, scanner, files, session) = list[0]
+                                       for file in files:
+                                               if file.mimetype == "audio/x-cda":
+                                                       self.cdAudioTrackFiles.append(file.path)
+                       else:
+                               self.cdAudioTrackFiles = []
+                               if self.isAudioCD:
+                                       self.clear_playlist()
 
 class MediaPlayerLCDScreen(Screen):
        skin = """