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