I've found a couple of problems with the Scrobble Free plugin, and so
here's a pair of patches to fix them:

First, the scrobbler always scrobbles the track, regardless of how much
has been played.  This is because the "tick" signal uses nanoseconds for
its elapsed time value, and the elapsed time in nanoseconds is
practically always greater than half the track duration in seconds.
Maybe if you had a really long track, or managed to play only a *very*
short bit of the track...

The solution is to use the shell's elapsed-changed signal instead of the
player's tick signal.  An alternative would be to divide the tick
'elapsed' parameter by 1000000000 (one billion).  The fix is in
tick-elapsed_changed.patch (attached)

The second problem is that Scrobble Free uses the player's current
position in the track as the elapsed play time, rather than using the
actual amount of time that the track has been playing.  This means that
if you seek past the halfway point and then skip to the next track, the
track will be scrobbled regardless of how much was actually played.
Conversely, if you play more than halfway through and then seek to the
beginning and then skip, the track will not be scrobbled.  This may be
useful for forcing a track to be scrobbled or not, but is IMO incorrect
behaviour.

Third, tracks of 30 seconds or less are scrobbled, which is incorrect.

Fourth, a minor spelling error was corrected (in debug output;
"scrobbing" -> "scrobbling"

Fixes for these last three problems can be found in
"elapsedplaytime.patch" (attached)

Hopefully someone will find these useful.
--- __init__.py	2009-05-12 08:28:47.000000000 -0500
+++ __init__new.py	2009-08-06 20:21:05.000000000 -0500
@@ -71,14 +71,13 @@
         self.current_track = None
         self.queue = []
 
-        self.player_cb_ids = (
-            self.player.props.player.connect('tick', self._tick_cb),
-            )
         self.shellplayer_cb_ids = (
             self.player.connect('playing-song-changed',
                                 self._playing_entry_changed_cb),
             self.player.connect('playing-changed',
-                                self._playing_changed_cb)
+                                self._playing_changed_cb),
+            self.player.connect('elapsed-changed',
+                                self._elapsed_changed_cb)
             )
         self.db_cb_ids = (
             self.db.connect('entry-extra-metadata-notify',
@@ -103,9 +102,6 @@
         return [s for s in self.scrobblers if s.enabled]
 
     def deactivate(self, shell):
-        for id in self.player_cb_ids:
-            self.player.props.player.disconnect(id)
-
         for id in self.shellplayer_cb_ids:
             self.player.disconnect(id)
 
@@ -210,7 +206,7 @@
                     print e
         return False # don't run again
 
-    def _tick_cb(self, player, stream_data, elapsed, duration):
+    def _elapsed_changed_cb(self, player, elapsed):
         track = self.current_track
 
         # the reported elapsed time occasionally jumps to zero at the
--- __init__new.py	2009-08-06 20:21:05.000000000 -0500
+++ __init__new2.py	2009-08-06 20:58:59.000000000 -0500
@@ -37,6 +37,7 @@
 MAX_CONNECT_RETRY = 3
 PLAY_DELAY = 10
 SCROBBLE_DELAY = 240
+SCROBBLE_MINLENGTH = 30
 
 CLIENT_ID='rbx'
 CLIENT_VER=str(rb.__version__)
@@ -75,9 +76,7 @@
             self.player.connect('playing-song-changed',
                                 self._playing_entry_changed_cb),
             self.player.connect('playing-changed',
-                                self._playing_changed_cb),
-            self.player.connect('elapsed-changed',
-                                self._elapsed_changed_cb)
+                                self._playing_changed_cb)
             )
         self.db_cb_ids = (
             self.db.connect('entry-extra-metadata-notify',
@@ -198,7 +197,7 @@
         queue = self.queue
         while queue:
             track = queue.pop(0)
-            print 'scrobbing: %s' % track
+            print 'scrobbling: %s' % track
             for scrobbler in self.enabled_scrobblers:
                 try:
                     scrobbler.sendScrobble(track)
@@ -214,17 +213,21 @@
         if track.elapsed < elapsed:
             track.elapsed = elapsed
 
+
+    def _playing_changed_cb(self, player, playing):
+        track = self.current_track
         if track.shouldPlay:
             track.played = True
             gobject.idle_add(self._process_playing, track)
-
-    def _playing_changed_cb(self, player, playing):
-        # XXX not sure we care
-        pass
+        if playing:
+            track.started_play = int(time.time())
+        else:
+            if int(time.time()) > self.started_play:
+                track.elapsed += int(time.time()) - track.started_play
 
     def _playing_entry_changed_cb(self, player, entry):
         print 'entry changed'
-
+            
         # queue the current track for scrobbling, if needed
         track = self.current_track
         if track and track.shouldScrobble:
@@ -417,7 +420,8 @@
 
 
     def __init__(self, artist, album, title, track, duration, mbid):
-        self.started = int(time.time())
+        self.started = int(time.time()) # time the track was started
+        self.started_play = 0 # most recent time 'play' was pressed in current track
         self.elapsed = 0
         self.played = False
 
@@ -435,9 +439,21 @@
 
     @property
     def shouldScrobble(self):
+        if self.started_play > self.started:
+            # The track was paused at some point 
+            if int(time.time()) > self.started_play:
+                # The clock hasn't gone backwards...
+                self.elapsed += int(time.time()) - self.started_play
+        else:
+            if int(time.time()) > self.started:
+                self.elapsed += int(time.time()) - self.started
+        print 'elapsed: %d' % self.elapsed
+        print 'duration: %d' % self.duration
+
         # XXX also ensure wall clock elapsed time is reasonable
-        return (self.elapsed > (self.duration // 2) or
-                self.elapsed > SCROBBLE_DELAY)
+        return ((self.elapsed > (self.duration // 2) or
+                self.elapsed > SCROBBLE_DELAY) and 
+                self.duration > SCROBBLE_MINLENGTH)
 
     def __str__(self):
         return '<Track %s>' % self.__dict__

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Libre-fm mailing list
[email protected]
http://lists.autonomo.us/mailman/listinfo/libre-fm

Reply via email to