Author: duncan
Date: Wed Nov 14 15:03:38 2007
New Revision: 10117

Log:
[ 1831371 ] Additional LastFM plugin - different features
>From John Molohan on behalf of Erik Petterson


Added:
   branches/rel-1-7/freevo/Docs/plugins/audioscrobbler.txt   (contents, props 
changed)
   branches/rel-1-7/freevo/src/plugins/audioscrobbler.py   (contents, props 
changed)
   branches/rel-1/freevo/Docs/plugins/audioscrobbler.txt   (contents, props 
changed)
   branches/rel-1/freevo/src/plugins/audioscrobbler.py   (contents, props 
changed)

Added: branches/rel-1-7/freevo/Docs/plugins/audioscrobbler.txt
==============================================================================
--- (empty file)
+++ branches/rel-1-7/freevo/Docs/plugins/audioscrobbler.txt     Wed Nov 14 
15:03:38 2007
@@ -0,0 +1,62 @@
+*******************************************
+*                                        *
+*            audioscrobbler.py           *
+*                                        *
+*Submit song information to AudioScrobbler*
+*                                        *
+*    Written by Erik /ikea/ Petterson    *
+*******************************************
+
+
+____________________________________
+|            * Contact *          |
+| email: [EMAIL PROTECTED]  |
+| irc: #freevo @ irc.freenode.net  |
+------------------------------------
+
+Please mail me if you have strange problems or if you got everything up and 
running.
+Want to keep track of the number of users to see if I should keep developing 
this plugin.
+
+This is for the 2.5.x series of Freevo, might not work with all versions of 
Python and Freevo though.
+Tested and reported to work with: Freevo 1.5.3 and Python 2.3
+
+Copyright Erik Pettersson
+The code is under the GNU Public License (see COPYING for more info)
+
+
+This program 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.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MER-
+CHANTABILITY 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 this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+
+*** INSTALL ***
+
+The only things you need for this plugin is three lines in the configuration 
file for Freevo.
+
+
+plugin.activate('audioscrobbler')
+AS_USER = 'username'
+AS_PASSWORD = 'password'
+
+
+There is one optional for debugging (spams alot, so I don't use the normal 
debug option).
+AS_DEBUG = True 
+
+No need to set it to False if you don't want to use it.
+
+If you run into problems, *please* turn debug on and email all the info to me. 
Thanks.
+
+
+Erik Pettersson

Added: branches/rel-1-7/freevo/src/plugins/audioscrobbler.py
==============================================================================
--- (empty file)
+++ branches/rel-1-7/freevo/src/plugins/audioscrobbler.py       Wed Nov 14 
15:03:38 2007
@@ -0,0 +1,323 @@
+#From Python
+import os, re, sys, re, urllib, md5, time, locale, math
+
+# From Freevo
+import plugin, config, rc
+from event import *
+
+
+#
+# Some parts here are from the LCD plugin.
+#
+# The rest is the creation of Erik Pettersson
+# irc: ikea/ieka on irc.freenode.org
+# lastfm: ieka
+# mail: tankdriverikea AT gmail DOT com
+# mail: petterson.erik AT gmail DOT com
+#
+# This code is under the GPL License
+#
+
+
+# TODO Re-login code sleeps, is that allowed?
+# TODO Change from 'tst' to 'frv' or whatever Russ finds appropiate
+# TODO Add support for batch-sending (This will be there for Freevo 2.0 - 
maybe)
+
+
+class PluginInterface(plugin.DaemonPlugin):
+    """
+    Submit information to the AudioScrobbler project about tracks played
+    Written by Erik Pettersson, [EMAIL PROTECTED]
+    plugin.activate('audioscrobbler')
+    AS_USER = 'username'
+    AS_PASSWORD = 'password'
+    """
+
+    def __init__(self):
+        """
+        Set up the basics, register with Freevo and connect
+        """
+
+        plugin.DaemonPlugin.__init__(self)
+
+        # DeamonPlugin internal settings.
+        self.poll_interval = 3000
+        self.poll_menu_only = False
+        self.event_listener = 1
+
+        # Register ourselves
+        plugin.register( self, "audioscrobbler" )
+
+        # Internal Plugin Setting
+        self.playitem = False
+        self.failed_retries = 0
+        self.logged_in = False
+        self.lastsong = ''
+        self.sleep_timeout = 0
+        self.elapsed = 0
+
+        # Read configuration
+        self.read_conf()
+        self.login()
+
+    def read_conf(self):
+        """
+        Read from config file, if everything isn't set we die. (I get less 
email this way:)
+        """
+        d = self.utf8(config.AS_USER)
+        try:
+            self.USER =                 self.utf8(config.AS_USER)
+            self.PASSWORD =             config.AS_PASSWORD
+
+        except:
+            print 'AudioScrobbler Plugin: You did not enter account 
information in the configuration file: Exiting (AS_USER and AS_PASSWORD is 
required)'
+            self.shutdown()
+
+        try:
+            self.debug = config.AS_DEBUG
+        except:
+            self.debug = False
+
+
+    def login(self): #TODO If we fail we shouldn't not retry right away, but 
can we really sleep like this?
+        """
+        Login, each session is ok for 30 mins or something like that
+        """
+        if self.failed_retries > 15:
+            print "AudioScrobbler plugin: Tried to login 15 times and failed 
on 15 occasions: Exiting"
+            self.shutdown()
+
+        login_string = 
'http://post.audioscrobbler.com/?hs=true&p=1.1&c=fvo&v=1.0&u=' + self.USER
+
+        try:
+            lo = urllib.urlopen(login_string)
+            lo = lo.read()
+        except:
+            print "AudioScrobbler plugin: Fail to receive data from server, 
sleeping and retrying later"
+            self.failed_retries += 1
+            self.sleep_timeout = time.time()
+            return
+
+        match = re.match(u'.*?BADUSER.*', lo)
+        if match:
+            print "AudioScrobbler plugin: Bad username: Exiting"
+            self.shutdown()
+
+        match = re.search(u'INTERVAL\s(\d+)\n', lo)
+        if match:
+            self.interval = match.groups(1)[0]
+
+        match = re.match(u'(\.*?)\n.*', lo)
+        if match:
+            if match.groups(1)[0] != 'UPTODATE':
+                print "AudioScrobbler plugin: I'm old, I'm old! Please update 
me!"
+                print "AudioScrobbler plugin: ", match.groups(1)[0]
+
+        match = re.match(u'.*?\n(.*?)\n.*', lo)
+        if match:
+            self.challenge = match.groups(1)[0]
+        else:
+            print "AudioScrobbler plugin: Didn't find challenge string, 
retrying"
+            self.failed_retries += 1
+            return
+
+        match = re.match( u'.*?\n.*?\n(.*?)\n.*', lo)
+        if match:
+            self.submiturl = match.groups(1)[0]
+        else:
+            print "AudioScrobbler plugin: Didn't find submit url, retrying"
+            self.failed_retries += 1
+            return # If we didn't get this we ass-ume that their server is 
down and try to re-login
+
+
+        self.challenge_reply = md5.md5( md5.md5(self.PASSWORD).hexdigest() + 
self.challenge ).hexdigest()
+        self.challenge_reply = self.utf8(self.challenge_reply)
+        self.logged_in = True
+        self.failed_reties = 0
+
+
+    def poll(self):
+        """
+        Run this code every self.poll_interval seconds
+        """
+
+        if self.sleep_timeout:
+            if math.ceil(time.time() - self.sleep_timeout) > 30*60:
+                self.sleep_timeout = False
+                return
+
+        if not self.logged_in:
+            self.login()
+
+        if self.playitem and self.logged_in:
+            self.draw( ( 'player', self.playitem ), None)
+
+
+    def shutdown(self):
+        """
+        Kill ourselves
+        """
+        print 'AudioScrobbler plugin: I have shut down'
+        plugin.shutdown(plugin_name='audioscrobbler')
+        sys.exit() # Ugly hack to shut down the plugin
+
+
+    def draw(self, ( ttype, object ), osd):
+        """
+        This is from the LCD plugin. With some modification.
+        I don't know what this does, or how it does it so I'll just let it be 
for now.
+        Original docstring:
+        'Draw' the information on the LCD display.
+        """
+        if ttype != 'player':
+            return
+        player = object
+        title  = player.getattr( 'title' )
+        album = None
+        if not title:
+            title = player.getattr( 'name' )
+
+
+        if player.type == 'audio':
+            playing = '__audio'
+            if player.getattr( 'trackno' ):
+                song    = player.getattr( 'trackno' )
+                artist  = player.getattr( 'artist' )
+                length  = player.getattr( 'length' )
+                album   = player.getattr( 'album' )
+                elapsed = int(player.elapsed)
+                length = str(int(length.split(":")[0])*60 + 
int(length.split(":")[1]))
+                self.elapsed += 1 # Erm. This function gets called every 
second altho' it shouldn't be. Let's build on a bug :>
+
+                if length > 30:         # We do not send unless the song is 
longer than 30 seconds
+                    if self.elapsed > 240 or self.elapsed > int(length)/2:   # 
We send only when 240 seconds or 50% have elapsed. Adhering to Audioscrobbler 
rules
+                        self.submit_song(artist, title, length, album)
+
+
+
+    def submit_song(self, artist, track, length, album=''):
+        """
+        Send song information to AudioScrobbler. I'm ashamed of this part, 
it's butt ugly...
+        """
+        if self.debug:
+            print "AudioScrobbler Debug: Got song:", str(artist), str(track), 
str(length), str(album)
+
+        if self.lastsong == artist + track:
+            return
+        if album == None:
+            album = ''
+
+        # Doing weak filtering
+        filter = [None, '', 'track', 'artist', 'group', 'band', 'song']
+        if artist.lower() not in filter and track.lower() not in filter:
+            if album == None:
+                album = ''
+
+            params = {
+                                        'u': self.urlenc(self.USER),
+                                        's': self.urlenc(self.challenge_reply),
+                                        'a[0]': self.urlenc(artist),
+                                        't[0]': self.urlenc(track),
+                                        'b[0]': self.urlenc(album),
+                                        'm[0]': '', #TODO Who got this for 
their mp3's? Add support some day
+                                        'l[0]': length,
+                                        'i[0]': self.urlenc( 
time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()) )
+                      }
+            cparams = ''
+            for n in params:
+                cparams += n + '=' + params[n] + '&'
+            cparams = cparams.rstrip('&').replace('+', '%20')
+            cparams = self.utf8(cparams)
+            try:
+                dl = urllib.urlopen(self.submiturl, cparams)
+                dl = dl.read()
+            except:
+                self.logged_in = False
+                return
+
+            match = re.search(u'BADAUTH', dl)
+            if match:
+                print "AudioScrobbler plugin: Failed to submit info: Bad 
password or username: Exiting"
+                self.shutdown()
+
+            match = re.match(u'FAILED.*', dl)
+            if match:
+                print "AudioScrobbler plugin: Failed to submit info (unknown 
reason): Printing debug info and exiting"
+                print "AudioScrobbler plugin: Debug info:" + dl
+                self.shutdown()
+
+            if self.debug:
+                match = re.search(u'OK', dl)
+                if match and self.debug:
+                    print "AudioScrobbler DEBUG: INFORMATION SENT, I REPEAT, 
INFORMATION SENT!"
+                    print str(dl)
+
+            match = re.search(u'INTERVAL (\d+)', dl)
+            if match:
+                self.interval = int(match.group(1))
+
+                if self.interval > self.poll_interval: # Can we really sleep 
here?
+                    print 'AudioScrobbler plugin: SORRY, ugly hack, have to 
sleep here. Locks up Freevo but adheres the Last FM rules. Again, Im sorry.'
+                    time.sleep(self.interval-self.poll_interval)
+
+            self.lastsong = artist + track
+
+
+    def urlenc(self, s):
+        return urllib.urlencode( {'':s} ).lstrip('=')
+
+
+    def eventhandler(self, event, menuw=None):
+        """
+        Get events from Freevo
+        """
+        if event == PLAY_START:
+            self.playitem = event.arg
+            self.elapsed = 0
+
+        if event == PLAY_END:
+            self.playitem = False
+            self.elapsed = 0
+
+        if event == STOP:
+            self.playitem =  False
+            self.elapsed = 0
+
+        if event == PLAYLIST_NEXT:
+            self.elapsed = 0
+
+        if event == SEEK:
+            self.elapsed = 0
+
+
+        return 0
+
+
+    def utf8(self, s):
+        """
+        From kaa.base:
+        Returns a UTF-8 string, converting from other character sets if
+        necessary.
+        """
+        return self.str_to_unicode(s).encode("utf-8")
+
+
+    def str_to_unicode(self, s):
+        """
+        From kaa.base:
+        Attempts to convert a string of unknown character set to a unicode
+        string.  First it tries to decode the string based on the locale's
+        preferred encoding, and if that fails, fall back to UTF-8 and then
+        latin-1.  If all fails, it will force encoding to the preferred
+        charset, replacing unknown characters.
+        """
+        if type(s) == unicode or s == None:
+            return s
+
+        for c in (locale.getpreferredencoding(), "utf-8", "latin-1"):
+            try:
+                return s.decode(c)
+            except UnicodeDecodeError:
+                pass
+
+        return s.decode(local.getpreferredencoding(), "replace")

Added: branches/rel-1/freevo/Docs/plugins/audioscrobbler.txt
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/Docs/plugins/audioscrobbler.txt       Wed Nov 14 
15:03:38 2007
@@ -0,0 +1,62 @@
+*******************************************
+*                                        *
+*            audioscrobbler.py           *
+*                                        *
+*Submit song information to AudioScrobbler*
+*                                        *
+*    Written by Erik /ikea/ Petterson    *
+*******************************************
+
+
+____________________________________
+|            * Contact *          |
+| email: [EMAIL PROTECTED]  |
+| irc: #freevo @ irc.freenode.net  |
+------------------------------------
+
+Please mail me if you have strange problems or if you got everything up and 
running.
+Want to keep track of the number of users to see if I should keep developing 
this plugin.
+
+This is for the 2.5.x series of Freevo, might not work with all versions of 
Python and Freevo though.
+Tested and reported to work with: Freevo 1.5.3 and Python 2.3
+
+Copyright Erik Pettersson
+The code is under the GNU Public License (see COPYING for more info)
+
+
+This program 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.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MER-
+CHANTABILITY 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 this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+
+*** INSTALL ***
+
+The only things you need for this plugin is three lines in the configuration 
file for Freevo.
+
+
+plugin.activate('audioscrobbler')
+AS_USER = 'username'
+AS_PASSWORD = 'password'
+
+
+There is one optional for debugging (spams alot, so I don't use the normal 
debug option).
+AS_DEBUG = True 
+
+No need to set it to False if you don't want to use it.
+
+If you run into problems, *please* turn debug on and email all the info to me. 
Thanks.
+
+
+Erik Pettersson

Added: branches/rel-1/freevo/src/plugins/audioscrobbler.py
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/src/plugins/audioscrobbler.py Wed Nov 14 15:03:38 2007
@@ -0,0 +1,323 @@
+#From Python
+import os, re, sys, re, urllib, md5, time, locale, math
+
+# From Freevo
+import plugin, config, rc
+from event import *
+
+
+#
+# Some parts here are from the LCD plugin.
+#
+# The rest is the creation of Erik Pettersson
+# irc: ikea/ieka on irc.freenode.org
+# lastfm: ieka
+# mail: tankdriverikea AT gmail DOT com
+# mail: petterson.erik AT gmail DOT com
+#
+# This code is under the GPL License
+#
+
+
+# TODO Re-login code sleeps, is that allowed?
+# TODO Change from 'tst' to 'frv' or whatever Russ finds appropiate
+# TODO Add support for batch-sending (This will be there for Freevo 2.0 - 
maybe)
+
+
+class PluginInterface(plugin.DaemonPlugin):
+    """
+    Submit information to the AudioScrobbler project about tracks played
+    Written by Erik Pettersson, [EMAIL PROTECTED]
+    plugin.activate('audioscrobbler')
+    AS_USER = 'username'
+    AS_PASSWORD = 'password'
+    """
+
+    def __init__(self):
+        """
+        Set up the basics, register with Freevo and connect
+        """
+
+        plugin.DaemonPlugin.__init__(self)
+
+        # DeamonPlugin internal settings.
+        self.poll_interval = 3000
+        self.poll_menu_only = False
+        self.event_listener = 1
+
+        # Register ourselves
+        plugin.register( self, "audioscrobbler" )
+
+        # Internal Plugin Setting
+        self.playitem = False
+        self.failed_retries = 0
+        self.logged_in = False
+        self.lastsong = ''
+        self.sleep_timeout = 0
+        self.elapsed = 0
+
+        # Read configuration
+        self.read_conf()
+        self.login()
+
+    def read_conf(self):
+        """
+        Read from config file, if everything isn't set we die. (I get less 
email this way:)
+        """
+        d = self.utf8(config.AS_USER)
+        try:
+            self.USER =                 self.utf8(config.AS_USER)
+            self.PASSWORD =             config.AS_PASSWORD
+
+        except:
+            print 'AudioScrobbler Plugin: You did not enter account 
information in the configuration file: Exiting (AS_USER and AS_PASSWORD is 
required)'
+            self.shutdown()
+
+        try:
+            self.debug = config.AS_DEBUG
+        except:
+            self.debug = False
+
+
+    def login(self): #TODO If we fail we shouldn't not retry right away, but 
can we really sleep like this?
+        """
+        Login, each session is ok for 30 mins or something like that
+        """
+        if self.failed_retries > 15:
+            print "AudioScrobbler plugin: Tried to login 15 times and failed 
on 15 occasions: Exiting"
+            self.shutdown()
+
+        login_string = 
'http://post.audioscrobbler.com/?hs=true&p=1.1&c=fvo&v=1.0&u=' + self.USER
+
+        try:
+            lo = urllib.urlopen(login_string)
+            lo = lo.read()
+        except:
+            print "AudioScrobbler plugin: Fail to receive data from server, 
sleeping and retrying later"
+            self.failed_retries += 1
+            self.sleep_timeout = time.time()
+            return
+
+        match = re.match(u'.*?BADUSER.*', lo)
+        if match:
+            print "AudioScrobbler plugin: Bad username: Exiting"
+            self.shutdown()
+
+        match = re.search(u'INTERVAL\s(\d+)\n', lo)
+        if match:
+            self.interval = match.groups(1)[0]
+
+        match = re.match(u'(\.*?)\n.*', lo)
+        if match:
+            if match.groups(1)[0] != 'UPTODATE':
+                print "AudioScrobbler plugin: I'm old, I'm old! Please update 
me!"
+                print "AudioScrobbler plugin: ", match.groups(1)[0]
+
+        match = re.match(u'.*?\n(.*?)\n.*', lo)
+        if match:
+            self.challenge = match.groups(1)[0]
+        else:
+            print "AudioScrobbler plugin: Didn't find challenge string, 
retrying"
+            self.failed_retries += 1
+            return
+
+        match = re.match( u'.*?\n.*?\n(.*?)\n.*', lo)
+        if match:
+            self.submiturl = match.groups(1)[0]
+        else:
+            print "AudioScrobbler plugin: Didn't find submit url, retrying"
+            self.failed_retries += 1
+            return # If we didn't get this we ass-ume that their server is 
down and try to re-login
+
+
+        self.challenge_reply = md5.md5( md5.md5(self.PASSWORD).hexdigest() + 
self.challenge ).hexdigest()
+        self.challenge_reply = self.utf8(self.challenge_reply)
+        self.logged_in = True
+        self.failed_reties = 0
+
+
+    def poll(self):
+        """
+        Run this code every self.poll_interval seconds
+        """
+
+        if self.sleep_timeout:
+            if math.ceil(time.time() - self.sleep_timeout) > 30*60:
+                self.sleep_timeout = False
+                return
+
+        if not self.logged_in:
+            self.login()
+
+        if self.playitem and self.logged_in:
+            self.draw( ( 'player', self.playitem ), None)
+
+
+    def shutdown(self):
+        """
+        Kill ourselves
+        """
+        print 'AudioScrobbler plugin: I have shut down'
+        plugin.shutdown(plugin_name='audioscrobbler')
+        sys.exit() # Ugly hack to shut down the plugin
+
+
+    def draw(self, ( ttype, object ), osd):
+        """
+        This is from the LCD plugin. With some modification.
+        I don't know what this does, or how it does it so I'll just let it be 
for now.
+        Original docstring:
+        'Draw' the information on the LCD display.
+        """
+        if ttype != 'player':
+            return
+        player = object
+        title  = player.getattr( 'title' )
+        album = None
+        if not title:
+            title = player.getattr( 'name' )
+
+
+        if player.type == 'audio':
+            playing = '__audio'
+            if player.getattr( 'trackno' ):
+                song    = player.getattr( 'trackno' )
+                artist  = player.getattr( 'artist' )
+                length  = player.getattr( 'length' )
+                album   = player.getattr( 'album' )
+                elapsed = int(player.elapsed)
+                length = str(int(length.split(":")[0])*60 + 
int(length.split(":")[1]))
+                self.elapsed += 1 # Erm. This function gets called every 
second altho' it shouldn't be. Let's build on a bug :>
+
+                if length > 30:         # We do not send unless the song is 
longer than 30 seconds
+                    if self.elapsed > 240 or self.elapsed > int(length)/2:   # 
We send only when 240 seconds or 50% have elapsed. Adhering to Audioscrobbler 
rules
+                        self.submit_song(artist, title, length, album)
+
+
+
+    def submit_song(self, artist, track, length, album=''):
+        """
+        Send song information to AudioScrobbler. I'm ashamed of this part, 
it's butt ugly...
+        """
+        if self.debug:
+            print "AudioScrobbler Debug: Got song:", str(artist), str(track), 
str(length), str(album)
+
+        if self.lastsong == artist + track:
+            return
+        if album == None:
+            album = ''
+
+        # Doing weak filtering
+        filter = [None, '', 'track', 'artist', 'group', 'band', 'song']
+        if artist.lower() not in filter and track.lower() not in filter:
+            if album == None:
+                album = ''
+
+            params = {
+                                        'u': self.urlenc(self.USER),
+                                        's': self.urlenc(self.challenge_reply),
+                                        'a[0]': self.urlenc(artist),
+                                        't[0]': self.urlenc(track),
+                                        'b[0]': self.urlenc(album),
+                                        'm[0]': '', #TODO Who got this for 
their mp3's? Add support some day
+                                        'l[0]': length,
+                                        'i[0]': self.urlenc( 
time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()) )
+                      }
+            cparams = ''
+            for n in params:
+                cparams += n + '=' + params[n] + '&'
+            cparams = cparams.rstrip('&').replace('+', '%20')
+            cparams = self.utf8(cparams)
+            try:
+                dl = urllib.urlopen(self.submiturl, cparams)
+                dl = dl.read()
+            except:
+                self.logged_in = False
+                return
+
+            match = re.search(u'BADAUTH', dl)
+            if match:
+                print "AudioScrobbler plugin: Failed to submit info: Bad 
password or username: Exiting"
+                self.shutdown()
+
+            match = re.match(u'FAILED.*', dl)
+            if match:
+                print "AudioScrobbler plugin: Failed to submit info (unknown 
reason): Printing debug info and exiting"
+                print "AudioScrobbler plugin: Debug info:" + dl
+                self.shutdown()
+
+            if self.debug:
+                match = re.search(u'OK', dl)
+                if match and self.debug:
+                    print "AudioScrobbler DEBUG: INFORMATION SENT, I REPEAT, 
INFORMATION SENT!"
+                    print str(dl)
+
+            match = re.search(u'INTERVAL (\d+)', dl)
+            if match:
+                self.interval = int(match.group(1))
+
+                if self.interval > self.poll_interval: # Can we really sleep 
here?
+                    print 'AudioScrobbler plugin: SORRY, ugly hack, have to 
sleep here. Locks up Freevo but adheres the Last FM rules. Again, Im sorry.'
+                    time.sleep(self.interval-self.poll_interval)
+
+            self.lastsong = artist + track
+
+
+    def urlenc(self, s):
+        return urllib.urlencode( {'':s} ).lstrip('=')
+
+
+    def eventhandler(self, event, menuw=None):
+        """
+        Get events from Freevo
+        """
+        if event == PLAY_START:
+            self.playitem = event.arg
+            self.elapsed = 0
+
+        if event == PLAY_END:
+            self.playitem = False
+            self.elapsed = 0
+
+        if event == STOP:
+            self.playitem =  False
+            self.elapsed = 0
+
+        if event == PLAYLIST_NEXT:
+            self.elapsed = 0
+
+        if event == SEEK:
+            self.elapsed = 0
+
+
+        return 0
+
+
+    def utf8(self, s):
+        """
+        From kaa.base:
+        Returns a UTF-8 string, converting from other character sets if
+        necessary.
+        """
+        return self.str_to_unicode(s).encode("utf-8")
+
+
+    def str_to_unicode(self, s):
+        """
+        From kaa.base:
+        Attempts to convert a string of unknown character set to a unicode
+        string.  First it tries to decode the string based on the locale's
+        preferred encoding, and if that fails, fall back to UTF-8 and then
+        latin-1.  If all fails, it will force encoding to the preferred
+        charset, replacing unknown characters.
+        """
+        if type(s) == unicode or s == None:
+            return s
+
+        for c in (locale.getpreferredencoding(), "utf-8", "latin-1"):
+            try:
+                return s.decode(c)
+            except UnicodeDecodeError:
+                pass
+
+        return s.decode(local.getpreferredencoding(), "replace")

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to