John McNeil wrote:
>
> * I still have everything in one function, because splitting it into
> one function for each state would, of course, require its own function
> definition, all of which would be basically the same, there's code
> that would need to be duplicated across some of them because it runs
> on multiple transitions, main.py would need to be able to call each of
> the functions depending on the state instead of just calling a single
> one, and so on. Overall it'd be less readable, have more code, and in
> particular more *redundant* code.
>

What would be redundant?

>
> +        if prevstate != 'play' and state != 'stop':
> +            # Track played or resumed, scrob_prev_time must be updated
> +            # as Sonata has not been playing since its last update
> +            self.scrob_prev_time = time.time()

This only happens when prevstate != state and state == play

> +        elif prevstate == 'play' and state != 'play':
> +            # Track paused or stopped, update play duration with time
> +            # between now and when Sonata started playing this track.
> +            self.scrob_playing_duration += time.time() - self.scrob_prev_time

Ok, this happens twice. When we pause and when we stop. I think its ok
to duplicate one line.

> +        if prevstate == 'stop':
> +            # New track playing, prepare to submit it later.
> +            if audioscrobbler is not None:
> +                self.scrob_start_time = ""
> +                self.scrob_playing_duration = 0
> +                if self.config.as_enabled and songinfo:
> +                    # No need to check if the song is 30 seconds or longer,
> +                    # audioscrobbler.py takes care of that.
> +                    if 'time' in songinfo:
> +                        self.np(songinfo)
> +                        self.scrob_start_time = 
> str(int(self.scrob_prev_time))

This happens when state == play

> +        elif state == 'stop':
> +            # Track stopped playing, submit it if the submission criteria 
> have
> +            # been met. The song must have been playing for at least 4 
> minutes
> +            # or have been at least halfway into its total length to be 
> submitted.
> +            prevlen = float(mpdh.get(prevsonginfo, 'time'))
> +            if self.scrob_playing_duration >= min(4*60, prevlen/2):
> +                if self.scrob_start_time:
> +                    self.post(prevsonginfo)
>  

Obviously this happens when state == stop

We already have code to detect state transitions. Your detection of song
changes is about the only thing main.py doesn't detect. I was thinking
more of this approach (applied on top of your patch as it helped me get
started). Look good?

diff --git a/sonata/main.py b/sonata/main.py
index c41fdc5..1923c26 100644
--- a/sonata/main.py
+++ b/sonata/main.py
@@ -1433,6 +1433,8 @@ def handle_change_status(self):
                 elif HAVE_EGG and self.eggtrayheight:
                     self.eggtrayfile = self.find_path('sonata.png')
                     
self.trayimage.set_from_pixbuf(img.get_pixbuf_of_size(gtk.gdk.pixbuf_new_from_file(self.eggtrayfile),
 self.eggtrayheight)[0])
+                if self.config.as_enabled:
+                    self.scrobbler.stop()
             elif self.status['state'] == 'pause':
                 self.ppbutton.set_image(ui.image(stock=gtk.STOCK_MEDIA_PLAY, 
stocksize=gtk.ICON_SIZE_BUTTON))
                 
self.ppbutton.get_child().get_child().get_children()[1].set_text('')
@@ -1443,6 +1445,8 @@ def handle_change_status(self):
                 elif HAVE_EGG and self.eggtrayheight:
                     self.eggtrayfile = self.find_path('sonata_pause.png')
                     
self.trayimage.set_from_pixbuf(img.get_pixbuf_of_size(gtk.gdk.pixbuf_new_from_file(self.eggtrayfile),
 self.eggtrayheight)[0])
+                if self.config.as_enabled:
+                    self.scrobbler.pause()
             elif self.status['state'] == 'play':
                 self.ppbutton.set_image(ui.image(stock=gtk.STOCK_MEDIA_PAUSE, 
stocksize=gtk.ICON_SIZE_BUTTON))
                 
self.ppbutton.get_child().get_child().get_children()[1].set_text('')
@@ -1457,6 +1461,8 @@ def handle_change_status(self):
                 elif HAVE_EGG and self.eggtrayheight:
                     self.eggtrayfile = self.find_path('sonata_play.png')
                     
self.trayimage.set_from_pixbuf(img.get_pixbuf_of_size(gtk.gdk.pixbuf_new_from_file(self.eggtrayfile),
 self.eggtrayheight)[0])
+                if self.config.as_enabled:
+                    self.scrobbler.play(self.songinfo)
 
             self.playing_song_change()
             if self.status_is_play_or_pause():
@@ -1479,27 +1485,20 @@ def handle_change_status(self):
                 self.mpd_updated_db()
         self.mpd_update_queued = False
 
-        if self.config.as_enabled:
-            prevstate = self.prevstatus['state'] if self.prevstatus else 'stop'
-            state = self.status['state'] if self.status else 'stop'
-            if self.prevstatus and 'time' in self.prevstatus:
+        # Handle changed songs for scrobbler
+        if self.config.as_enabled and (self.prevstatus and
+           self.prevstatus['state'] != 'stop') and self.prevsonginfo:
+            if 'time' in self.prevstatus:
                 prevpos, prevlen = map(float, 
self.prevstatus['time'].split(':'))
             if self.status and 'time' in self.status:
                 pos, len = map(float, self.status['time'].split(':'))
-            prevfilename = mpdh.get(self.prevsonginfo, 'file') if 
self.prevsonginfo else ''
+            prevfilename = mpdh.get(self.prevsonginfo, 'file')
             filename = mpdh.get(self.songinfo, 'file') if self.songinfo else ''
 
-            if prevstate != 'stop' and state != 'stop' and\
-               ((prevfilename != filename) or # New file is playing
-                (prevlen-prevpos <= 2 and pos <= 2)): # The same file appears 
to have been played again from the start
-                # We pass in prevsonginfo twice because this is how it'd look
-                # to scrobbler.handle_change_status() if it had really stopped
-                self.scrobbler.handle_change_status('play', 'stop', 
self.prevsonginfo, self.prevsonginfo)
-                # Same concept here
-                self.scrobbler.handle_change_status('stop', 'play', 
self.songinfo, self.songinfo)
-            # State transition
-            elif prevstate != state:
-                self.scrobbler.handle_change_status(prevstate, state, 
self.prevsonginfo, self.songinfo)
+            if ((prevfilename != filename) or
+                (prevlen-prevpos <= 2 and pos <= 2)):
+                self.scrobbler.song_change(self.songinfo)
+
 
     def mpd_updated_db(self):
         self.library.view_caches_reset()
diff --git a/sonata/scrobbler.py b/sonata/scrobbler.py
index 1e203d7..f365d5b 100644
--- a/sonata/scrobbler.py
+++ b/sonata/scrobbler.py
@@ -26,6 +26,9 @@ def __init__(self, config):
 
         self.scrob = None
         self.scrob_post = None
+        self.playing_song = None
+        self.scrob_playing_duration = 0
+        self.scrob_prev_time = time.time()
 
     def import_module(self, _show_error=False):
         """Import the audioscrobbler module"""
@@ -64,36 +67,42 @@ def init_thread(self):
         if self.scrob_post:
             self.retrieve_cache()
 
-    def handle_change_status(self, prevstate, state, prevsonginfo, songinfo):
-        """Handle changes to play status, submitting info as appropriate"""
-
-        if prevstate != 'play' and state != 'stop':
-            # Track played or resumed, scrob_prev_time must be updated
-            # as Sonata has not been playing since its last update
-            self.scrob_prev_time = time.time()
-        elif prevstate == 'play' and state != 'play':
-            # Track paused or stopped, update play duration with time
-            # between now and when Sonata started playing this track.
-            self.scrob_playing_duration += time.time() - self.scrob_prev_time
-        if prevstate == 'stop':
-            # New track playing, prepare to submit it later.
-            if audioscrobbler is not None:
-                self.scrob_start_time = ""
-                self.scrob_playing_duration = 0
-                if self.config.as_enabled and songinfo:
-                    # No need to check if the song is 30 seconds or longer,
-                    # audioscrobbler.py takes care of that.
-                    if 'time' in songinfo:
-                        self.np(songinfo)
-                        self.scrob_start_time = str(int(self.scrob_prev_time))
-        elif state == 'stop':
-            # Track stopped playing, submit it if the submission criteria have
-            # been met. The song must have been playing for at least 4 minutes
-            # or have been at least halfway into its total length to be 
submitted.
-            prevlen = float(mpdh.get(prevsonginfo, 'time'))
-            if self.scrob_playing_duration >= min(4*60, prevlen/2):
-                if self.scrob_start_time:
-                    self.post(prevsonginfo)
+    def play(self, songinfo):
+        self.scrob_prev_time = time.time()
+        self.playing_song = songinfo
+
+        # New track playing, prepare to submit it later.
+        if audioscrobbler is not None:
+            self.scrob_start_time = ""
+            if self.config.as_enabled and songinfo:
+                # No need to check if the song is 30 seconds or longer,
+                # audioscrobbler.py takes care of that.
+                if 'time' in songinfo:
+                    self.np(songinfo)
+                    self.scrob_start_time = str(int(self.scrob_prev_time))
+
+    def pause(self):
+        self.scrob_playing_duration += time.time() - self.scrob_prev_time
+
+    def stop(self):
+        if self.playing_song is None:
+            # Stopped player at start
+            return
+
+        self.scrob_playing_duration += time.time() - self.scrob_prev_time
+
+        # The song must have been playing for at least 4 minutes or have been
+        # at least halfway into its total length to be submitted.
+        len = float(mpdh.get(self.playing_song, 'time'))
+        if self.scrob_playing_duration >= min(4*60, len/2):
+            if self.scrob_start_time:
+                self.post(self.playing_song)
+
+        self.scrob_playing_duration = 0
+
+    def song_change(self, songinfo):
+        self.stop()
+        self.play(songinfo)
 
     def auth_changed(self):
         """Try to re-authenticate"""



_______________________________________________
Sonata-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/sonata-users

Reply via email to