CurrentSong.py :  » Network » emesene » emesene-1.6.2 » plugins_base » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » emesene 
emesene » emesene 1.6.2 » plugins_base » CurrentSong.py
# -*- coding: utf-8 -*-

#   This file is part of emesene.
#
#    Emesene is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    emesene is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with emesene; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
import os
import gtk
import socket
import urllib
import urllib2
import gobject
import re

import Plugin
import currentSong

import paths

COVERART_PATH = os.path.join(paths.HOME_DIR, '.covers', '')
BANSHEE_PATH = os.path.join(paths.HOME_DIR, '.cache/album-art','')

PLUGIN_DESCRIPTION = _( 'Show a personal message with the current song' \
    ' played in multiple players.' )
PLUGIN_AUTHORS = { 'Mariano Guerra' : 'luismarianoguerra gmail com' }
PLUGIN_WEBSITE = 'http://emesene.org'
PLUGIN_DISPLAYNAME = _( 'CurrentSong' )
PLUGIN_NAME = 'CurrentSong'

class MainClass( Plugin.Plugin ):
    '''Main plugin class'''
    description = PLUGIN_DESCRIPTION
    authors = PLUGIN_AUTHORS
    website = PLUGIN_WEBSITE
    displayName = PLUGIN_DISPLAYNAME
    name = PLUGIN_NAME
    
    def __init__( self, controller, msn ):
        '''Constructor'''
        
        Plugin.Plugin.__init__( self, controller, msn, 1000 )
        self.theme = controller.theme
        
        self.controller = controller
        
        self.description = PLUGIN_DESCRIPTION
        self.authors = PLUGIN_AUTHORS
        self.website = PLUGIN_WEBSITE
        self.displayName = PLUGIN_DISPLAYNAME
        self.name = PLUGIN_NAME
        
        self.configWindow = None
        self.statusLabel = None
        self.customConfigWidget = None
        self.usingDummy = True
        self.dictCommand = None
        
        self.Slash = controller.Slash
        self.config = controller.config
        self.config.readPluginConfig(self.name)
        
        self.setPlayer( self.config.getPluginValue( self.name, 'player', \
            'CurrentSong' ) )
        self.player.setStyle( self.config.getPluginValue( self.name, 'style', \
            '%title - %artist (%album)' ) )
        self.avatar = self.config.getPluginValue(self.name, 'avatar', \
            '0') == '1'
        self.remotefetch = self.config.getPluginValue(self.name, \
            'remotefetch', '0') == '1'
        
        self.updateCustomConf()
        self.timeout = 0
        self.mediaEnabledId = 0
        self.coverAvatar = Plugin.Function( self.getCoverAvatar, \
            self.setCoverAvatar )
        
    def start( self ):
        '''start the plugin'''
        if not os.path.isdir(COVERART_PATH):
            os.mkdir(COVERART_PATH)
        
        if not self.usingDummy:
            self.player.start()
        
        self.timeout = gobject.timeout_add(self.period, self.action)
        self.Slash.register('currentsong', self.currentSongHandler, \
            _('currentsong command'))
        self.Slash.register('np', self.nowplaying, \
            _('Send what you are listening to'))
        
        self.controller.mainWindow.userPanel.mediaButton.show()

        self.mediaEnabledId = self.controller.config.connect(
            'change::mediaEnabled', self.onMediaEnabled)
            
        self.enabled = True

        self.original_avatar = self.config.user['avatarPath']

        self.doNotSaveAvatar = False

        self.updateAvatarId = self.controller.connect('avatar-changed', self.updateAvatar)    

    def updateAvatar(self, controller, path=None):
        if path == None:
            path = self.config.user['avatarPath']

        if not self.doNotSaveAvatar:
            self.original_avatar = path

    def showHelp(self):
        msg = 'Help:'
        for (cmd, val) in self.dictCommand.iteritems():
            msg += '\n ' + str(cmd) + '\t' + str(val[1])
        return msg

    def playerChanged( self, combo ):
        newplayer = combo.get_active_text()
        self.setPlayer(newplayer)
        self.updateStatus()
        self.updateCustomConf() 
        self.dictCommand = self.player.dictCommand
        self.customConfigWidget.refresh(self.player.customConfig)

    def currentSongHandler(self, slashAction):
        name = None
        param = None
        
        try:
            cmd = slashAction.getParams().split(" ", 1)
            name = cmd[0]
            param = cmd[1]
        except:
            pass
        
        if name != None and self.dictCommand.has_key(name):
            retval, msg = self.dictCommand[name][0](param)
            if self.dictCommand[name][2]:
                slashAction.outputText( msg , retval )
            else:
                slashAction.outputText( msg )
        else:
            slashAction.outputText(self.showHelp())
    
    def nowplaying(self, slashAction):
        if self.player.cmd_Show(True)[0] == False:
            slashAction.outputText(_('Not playing'))
        else:
            slashAction.outputText(_('now playing: ')+ \
                self.player.cmd_Show(True)[1], True)

    def stop( self ):    
        '''stop the plugin'''
        
        if not self.usingDummy:
            self.player.stop()
        
        if self.timeout:
            gobject.source_remove(self.timeout)

        self.msn.changeCurrentMedia( '' )
        self.Slash.unregister('currentsong')
        self.Slash.unregister('np')
        
        self.controller.mainWindow.userPanel.mediaButton.hide()
        self.controller.mainWindow.userPanel.mediaButton.set_active(False)
        
        if self.avatar and self.original_avatar:
            self.controller.changeAvatar(self.original_avatar)

        self.controller.config.disconnect(self.mediaEnabledId)
        
        self.enabled = False

        self.controller.disconnect(self.updateAvatarId)

    def onMediaEnabled(self, config, value, oldvalue):
        '''Called when the media button is toggled'''
        # print "Current song plugin: onMediaEnabled ["+value+"]"
        
        self.action(True)

        if self.avatar and value == "0" and self.original_avatar:
            self.controller.changeAvatar(self.original_avatar)
       
    def action(self, force=False):
        if not self.enabled or not self.config.user['mediaEnabled']:
            return True
        
        if not self.usingDummy:
            try:
                check = self.player.check()
            except Exception, e:
                print 'Error in player.check():', e
                self.setPlayer(None)
                check = True
            
            # USEFUL for LAST.FM plug 
            # self.controller.emit('media-changed',self.player.getSongDict())
            # dx note: wtf?

            if force or check: 
                self.player.setStyle(self.config.getPluginValue( self.name, 'style', \
                '%title - %artist (%album)' ))
                currentsong = self.player.getCurrentSong()\
                    .decode("utf-8", "replace").encode("utf-8")
                sdict = self.player.getSongDict()
                
                self.msn.changeCurrentMedia( currentsong, sdict)
                if self.avatar:
                    self.coverAvatar(self.remotefetch)
        else:
            self.setPlayer( self.config.getPluginValue( self.name, 'player', \
                'CurrentSong' ) )

        return True

    def getCoverAvatar(self, remote):
        ''' get avatar cover art '''
        path = self.player.getCoverPath()
        if path and os.path.exists(path):
            print "Current song plugin : getCoverPath : [" + path + "]"
            return path

        path = self.search_local_image()  
        if path and os.path.exists(path):
            print "Current song plugin : getCoverPath : [" + path + "]"
            return path

        if remote:
            try:
                path = self.search_remote_image()
                print "Current song plugin : getCoverPath : [" + path + "]"
                return path
            except:
                # handle connection errors
                pass

    def setCoverAvatar(self, path):
        ''' set avatar cover art '''
        if path != None and os.path.exists(path):
            self.doNotSaveAvatar = True
            self.controller.changeAvatar(path)
            self.doNotSaveAvatar = False
            return True
        if not self.player.isPlaying() or not self.player.isRunning():
            if self.original_avatar:
                self.doNotSaveAvatar = True
                self.controller.changeAvatar(self.original_avatar)
                self.doNotSaveAvatar = False
            return False
        return False

    def is_on_path(self, fname):
        for p in os.environ['PATH'].split(os.pathsep):
            if os.path.isfile(os.path.join(p, fname)):
                return True
        
    def getPluginNames( self ):
        return [ x for x in dir( currentSong ) \
                 if not x.startswith( "__" ) \
                 and x != 'CurrentSong' ]
        
    def setPlayer( self, name ):
        players = self.getPluginNames()     
        
        if name == _('Autodetect'):
            for n in players:
                if n.lower() != 'lastfm':
                    print "Current song plugin: Trying " + n
                    if self._setPlayer(n, players) == 'loaded':
                        if not self.usingDummy and self.player.isRunning():
                            return
        else:
            self._setPlayer(name, players)
        
    def _setPlayer(self, name, players):
        '''try to set the player object to the name given by the name parameter'''

        self.playername = name
        
        error = '' 
        if name in players:
            try:
                self.player = getattr(currentSong, name)()
                self.usingDummy = False
                self.action()
            except Exception, e:
                print "error initializing CurrentSong player:", e
                error = e
            else:
                self.player.log('info', _('Player: ') + name)
                status, message = self.player.getStatus()
                self.player.log(status and 'info' or 'error', \
                    'getStatus: ' + message)

                if not status:
                    self.player.status = 'error'
                
                self.dictCommand = self.player.dictCommand
                return 'loaded'
        self.player = currentSong.CurrentSong()
        self.usingDummy = True
        if error:
            return error
        
    def check( self ):
        '''check if everything is OK to start the plugin
        return a tuple whith a boolean and a message
        if OK -> ( True , 'some message' )
        else -> ( False , 'error message' )'''
        
        return (True, 'Ok')
   
    def updateCustomConf( self ):
        for key in self.player.customConfig.keys():
            self.player.customConfig[key] = \
                self.config.getPluginValue( self.name, \
                str(self.playername + "_" + key), \
                self.player.customConfig[key] )     

        self.player.updateConfig()

    def search_local_image(self):
        '''searches in the local covers cache
        returns None if no local image found'''
        
        artist = self.player.artist.encode('utf8')
        album = self.player.album.encode('utf8')
        
        bartist = re.sub("\W", "", artist).lower()
        balbum = re.sub("\W", "", album).lower()
        file_dsc = BANSHEE_PATH + bartist + '-' + balbum + '.jpg'
        if os.path.exists(file_dsc):
            return file_dsc
        
        file_dsc = COVERART_PATH + artist + '-' + album + '.jpg'
        if os.path.exists(file_dsc):
            return file_dsc
        return None

    def search_remote_image(self):

        imgfound = None

        artist = self.player.artist.encode('utf8')
        album = self.player.album.encode('utf8')
        
        if len(artist) == 0 and len(album) == 0:
            return None

        dest_filename = COVERART_PATH + artist + '-' + album + '.jpg'

        url = "http://www.albumart.org/index.php?srchkey=" + \
            urllib.quote_plus(artist) + "+" + urllib.quote_plus(album) + \
            "&itempage=1&newsearch=1&searchindex=Music"

        # This is useful to see if we're searching for the right song
        print "Current song plugin: " + url

        albumart = urllib.urlopen(url).read()
        image_url = ""

        for line in albumart.split("\n"):
    
            if "http://www.albumart.org/images/zoom-icon.jpg" in line:
                image_url = line.partition('src="')[2].partition('"')[0]
    
            if image_url:
                urllib.urlretrieve(image_url, dest_filename)
                imgfound = dest_filename
                break

        return imgfound

    def configure( self ):
        '''display a configuration dialog'''

        style = self.config.getPluginValue(self.name, 'style', \
            '%title - %artist (%album)')
        player = self.config.getPluginValue(self.name, 'player', 'Amarok')
        avatar = self.config.getPluginValue(self.name, 'avatar', '0') == '1'
        remotefetch = self.config.getPluginValue(self.name, \
            'remotefetch', '0') == '1'

        #self.updateCustomConf()
        plugin_names = self.getPluginNames()
        plugin_names.insert(0, _('Autodetect'))
        l = []
        # name, optionType, label, description, value, options
        l.append(Plugin.Option('style', str, _('Display style'), \
            _('Change display style of the song you are listening, possible ' \
            'variables are %title, %artist and %album'), style))
        l.append(Plugin.Option('player', list, _('Music player'), \
            _('Select the music player that you are using'), player, \
            plugin_names, self.playerChanged))
        
        self.statusLabel = gtk.Label()
        status_timeout = gobject.timeout_add(2000, self.updateStatus)
        self.updateStatus()
        logsButton = gtk.Button( _('Show logs') )
        logsButton.connect('clicked', self.showLogs)
        hbox = gtk.HBox()
        hbox.pack_start(self.statusLabel, True, True)
        hbox.pack_start(logsButton)
        status = Plugin.Option('status', gtk.Widget, '', '', hbox)
        l.append(status)

        l.append(Plugin.Option('avatar', bool, _('Change Avatar'), \
            _('Change Avatar'), avatar))
        l.append(Plugin.Option( 'remotefetch', bool, \
            _( 'Get cover art from web' ), _( 'Get cover art from web' ), \
            remotefetch ))
        
        custom = Plugin.Option('custom', dict, _('Custom config'), \
            _('Custom config'), None, self.player.customConfig)
        l.append(custom)

        self.configWindow = Plugin.ConfigWindow( _( 'Config Plugin' ), l )
        self.customConfigWidget = custom.widget
        response = self.configWindow.run()

        if status_timeout:
            # this stops the update status timeout
            gobject.source_remove(status_timeout)

        if response != None:
            if response.has_key( 'player' ):
                self.setPlayer( response[ 'player' ].value )
                self.config.setPluginValue( self.name, 'player', \
                    response[ 'player' ].value )
            if response.has_key( 'style' ):
                self.player.setStyle( response[ 'style' ].value )
                self.config.setPluginValue( self.name, 'style', \
                    response['style'].value )
            if response.has_key('avatar'):
                self.avatar = response['avatar'].value
                self.config.setPluginValue(self.name, 'avatar', \
                    str(int(response['avatar'].value)))
            if response.has_key('remotefetch'):
                self.remotefetch =  response[ 'remotefetch' ].value 
                self.config.setPluginValue( self.name, 'remotefetch', \
                    str(int(response[ 'remotefetch' ].value)))
            if response.has_key('custom'):
                self.player.customConfig = self.customConfigWidget.data
                for key in self.player.customConfig.keys():
                    self.config.setPluginValue(self.name, \
                        str(self.playername + "_" + key), \
                        self.player.customConfig[key])
                self.player.updateConfig()
        self.configWindow = None
        self.statusLabel = None
        return True

    def updateStatus( self ):
        '''updates the status label'''
        if hasattr(self.player, 'status'):
            status = self.player.status
        else:
            status = _('unknown')

        if self.statusLabel:
            self.statusLabel.set_markup(_('Status:') + ' <b>%s</b>' % status)
            return True
        else:
            return False
        
    def showLogs( self, button ):
        '''Display an error log window'''
        log = []
        if hasattr(self.player, '_log'):
            log = self.player._log
        
        win = gtk.Dialog( _('Logs'), self.configWindow, \
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, \
            (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) )
        win.set_default_size(300, 400)
        model = gtk.ListStore(str, str)
        tree = gtk.TreeView(model)
        crtkey = gtk.CellRendererText()
        crtvalue = gtk.CellRendererText()

        col1 = gtk.TreeViewColumn(_('Type'), crtkey, text=0)
        col2 = gtk.TreeViewColumn(_('Value'), crtvalue, text=1)
        tree.append_column(col1)
        tree.append_column(col2)
        for item in log:
            model.append(item)
        win.vbox.pack_start(tree)
        win.show_all()
        win.run()
        win.destroy()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.