Merge lp:~barcc/repeat-one-song/one-second-issue into lp:repeat-one-song/trunk

Proposed by B. Clausius
Status: Merged
Approved by: Eduardo Mucelli Rezende Oliveira
Approved revision: 15
Merged at revision: 16
Proposed branch: lp:~barcc/repeat-one-song/one-second-issue
Merge into: lp:repeat-one-song/trunk
Diff against target: 122 lines (+43/-25)
1 file modified
__init__.py (+43/-25)
To merge this branch: bzr merge lp:~barcc/repeat-one-song/one-second-issue
Reviewer Review Type Date Requested Status
Eduardo Mucelli Rezende Oliveira Approve
B. Clausius (community) Needs Fixing
Review via email: mp+39285@code.launchpad.net

Description of the change

This change solves this issues:
 * last second from a song is cut off
 * if the song duration is wrong (too long) the song is not repeated at all
 * the play count is not incremented
Unfortunately this introduces another issue: If a song is playing and the user selects an other song, the plugin gets confused. Somehow in the playing-song-changed signal there should be differentiated between user initiated and end of song.

To post a comment you must log in.
Revision history for this message
Eduardo Mucelli Rezende Oliveira (eduardo-mucelli) wrote :

First of all, thanks for you effort to make this plugin better. My first approach when I started it was to call the do_previous with the same kind of "state machine" you did in the callback method on_song_change. Consequently, the erroneous behavior which happens when the user changes a song by himself happened to me, the same one that you pointed out -- and I totally agree with you about that there should be a way to differentiate its sources.

The last second cut off I guess is not a big deal, but I agree it is a problem. The play count can be fixed using rhythmdb, and I'd not realized until the moment, thanks again.

One awesome thing that the do_previous approach (I guess it) has, is the possibility to fix the crossfader problem reported by another user. I was wondering that last night.

Anyway, I'm really restricted about the time, and I will check everything out to answer your merge proposal.

Thanks B Clausius

14. By B. Clausius

Use the end-of-stream signal to initiate repetition.

15. By B. Clausius

Merge from trunk

Revision history for this message
B. Clausius (barcc) wrote :

I found out, how to connect to the end-of-stream signal. I think this fixes all issues mentioned above.

Revision history for this message
Eduardo Mucelli Rezende Oliveira (eduardo-mucelli) wrote :

You're right, B Clausius. Anyway, over here, the on_gst_player_eos callback is not feeding the method with 4 parameters, but with 3. I defined 0 to the "early" parameter in order to it works. Works like a charm, congratulations.

Revision history for this message
Eduardo Mucelli Rezende Oliveira (eduardo-mucelli) wrote :

Thanks for your efforts. I will change the "early" parameter as I commented and pack it as version 0.0.6.

review: Approve
Revision history for this message
B. Clausius (barcc) wrote :

There is a bug in my code, if the song is the last song in the list, it does not work. To do a "do_previous" there must have been a next song of course. I will look at it.

review: Needs Fixing
16. By B. Clausius

Activate repeat when activating repeat-one to ensure that a next song is available even for the last song in a list.

Revision history for this message
Eduardo Mucelli Rezende Oliveira (eduardo-mucelli) wrote :

Nice workaround.

Revision history for this message
Eduardo Mucelli Rezende Oliveira (eduardo-mucelli) wrote :

I will pack it in the 0.0.6 and generate a Stable version with only the basic function.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '__init__.py'
--- __init__.py 2010-10-27 20:49:54 +0000
+++ __init__.py 2010-11-03 18:11:53 +0000
@@ -44,6 +44,10 @@
44 </ui>44 </ui>
45 """45 """
4646
47ONE_SONG_STATE_NORMAL = 0
48ONE_SONG_STATE_EOS = 1
49ONE_SONG_STATE_REPEAT = 2
50
47class RepeatOneSong (rb.Plugin):51class RepeatOneSong (rb.Plugin):
4852
49 def switch_repeat_status(self, control):53 def switch_repeat_status(self, control):
@@ -51,6 +55,20 @@
51 # mas a boa pratica eh colocar as acoes em um grupo e busca-la com o get_action55 # mas a boa pratica eh colocar as acoes em um grupo e busca-la com o get_action
52 action = self.action_group.get_action('RepeatOne') # seleciona a acao de repetir a musica atual56 action = self.action_group.get_action('RepeatOne') # seleciona a acao de repetir a musica atual
53 self.repeat = action.get_active() # indica se o botao esta marcado, ou desmarcado57 self.repeat = action.get_active() # indica se o botao esta marcado, ou desmarcado
58 player = self.shell.props.shell_player
59 if self.repeat:
60 shuffle,self.repeat_all = player.get_playback_state()
61 player.set_playback_state(shuffle, 1)
62 else:
63 shuffle,repeat_all = player.get_playback_state()
64 player.set_playback_state(shuffle, self.repeat_all)
65
66 def switch_repeat_all_status(self, action):
67 if not action.get_active() and self.repeat:
68 self.repeat = False
69 self.repeat_all = 0
70 action_repeat_one = self.action_group.get_action('RepeatOne')
71 action_repeat_one.set_active(False)
5472
55 def load_local_language(self):73 def load_local_language(self):
56 """Carrega a traducao para o idioma local caso exista. Caso contrario, o ingles sera usado"""74 """Carrega a traducao para o idioma local caso exista. Caso contrario, o ingles sera usado"""
@@ -91,6 +109,9 @@
91 manager.insert_action_group(self.action_group, 0)109 manager.insert_action_group(self.action_group, 0)
92 self.uid = manager.add_ui_from_string(ui_str) # mescla xml definido com o do RB110 self.uid = manager.add_ui_from_string(ui_str) # mescla xml definido com o do RB
93 manager.ensure_update()111 manager.ensure_update()
112
113 action = manager.get_action('/ToolBar/Repeat')
114 action.connect("activate", self.switch_repeat_all_status)
94115
95 def __init__(self):116 def __init__(self):
96 rb.Plugin.__init__(self)117 rb.Plugin.__init__(self)
@@ -101,17 +122,23 @@
101 self.duration = None122 self.duration = None
102 self.repeat = False123 self.repeat = False
103124
104 self.number_of_repetitions = self.get_gconf_number_of_repetitions() # inicializa com o valor do campo125 self.number_of_repetitions = 0
126 self.one_song_state = ONE_SONG_STATE_NORMAL
105 127
106 self.load_local_language()128 self.load_local_language()
107 self.load_icon() # necessary load icon first ...129 self.load_icon() # necessary load icon first ...
108 self.generate_ui() # ... because it is used here 130 self.generate_ui() # ... because it is used here
109131
110 player = self.shell.props.shell_player132 player = self.shell.props.shell_player
111 player.connect('elapsed-changed', self.on_elapsed_change) # receives a signal every single second that the song is being played
112 player.connect('playing-song-changed', self.on_song_change) # mudou a musica. o player.do_next() invoca o on_elapsed_changed133 player.connect('playing-song-changed', self.on_song_change) # mudou a musica. o player.do_next() invoca o on_elapsed_changed
134 player.props.player.connect('eos', self.on_gst_player_eos)
113135
114 def deactivate(self, shell): # when unloading applet136 def deactivate(self, shell): # when unloading applet
137 if self.repeat:
138 player = self.shell.props.shell_player
139 shuffle,repeat_all = player.get_playback_state()
140 player.set_playback_state(shuffle, self.repeat_all)
141
115 for attr in (self.db, self.shell, self.duration, self.repeat): # delete global attributes if possible142 for attr in (self.db, self.shell, self.duration, self.repeat): # delete global attributes if possible
116 if attr:143 if attr:
117 del attr144 del attr
@@ -120,36 +147,27 @@
120 manager.remove_action_group(self.action_group)147 manager.remove_action_group(self.action_group)
121 manager.ensure_update()148 manager.ensure_update()
122149
123 def on_elapsed_change(self, player, time):150 def on_gst_player_eos(self, gst_player, stream_data, early):
124 if (self.repeat): # se o botao de repetir foi acionado, ver switch_repeat_status151 if self.number_of_repetitions != 0 and self.repeat:
125 duration = player.get_playing_song_duration() # the current song duration152 self.one_song_state = ONE_SONG_STATE_EOS
126 if (duration > 0): # in the exact moment the first song is played, the duration is -1153 if self.number_of_repetitions > 0:
127 if (time >= duration - 1): # one second before the song finishes154 self.number_of_repetitions -= 1
128 if (self.number_of_repetitions > 0): # existem repeticoes para serem feitas155
129 self.increment_play_count(player.get_playing_entry()) # incrementa o contador do numero de vezes que a musica foi tocada
130 player.set_playing_time(0) # restart the song
131 self.number_of_repetitions -= 1 # atualiza o numero da repeticao atual
132 elif (self.number_of_repetitions == 0): # acabaram-se as repeticoes
133 player.do_next() # vai invocar o on_song_changed
134 else: # == -1 repeticoes infinitas
135 self.increment_play_count(player.get_playing_entry())
136 player.set_playing_time(0) # restart the song
137
138 def increment_play_count(self, song):
139 current_count = self.db.entry_get (song, rhythmdb.PROP_PLAY_COUNT)
140 self.db.set (song, rhythmdb.PROP_PLAY_COUNT, current_count + 1)
141
142 def on_song_change(self, player, time): # quando mudar a musica ...156 def on_song_change(self, player, time): # quando mudar a musica ...
143 self.number_of_repetitions = self.get_gconf_number_of_repetitions() # ... reinicia o numero de repeticoes157 if self.one_song_state == ONE_SONG_STATE_EOS:
144158 self.one_song_state = ONE_SONG_STATE_REPEAT
159 player.do_previous()
160 elif self.one_song_state == ONE_SONG_STATE_REPEAT:
161 self.one_song_state = ONE_SONG_STATE_NORMAL
162 else:
163 self.number_of_repetitions = self.get_gconf_number_of_repetitions()
164
145 def get_gconf_number_of_repetitions(self): # le do arquivo /apps/rhythmbox/plugins/repeat-one-song/gconf.xml ...165 def get_gconf_number_of_repetitions(self): # le do arquivo /apps/rhythmbox/plugins/repeat-one-song/gconf.xml ...
146 client = gconf.client_get_default()166 client = gconf.client_get_default()
147 try:167 try:
148 key_value = client.get_value(gconf_keys['number_of_repetitions']) # ... o valor do atributo number_of_repetitions168 key_value = client.get_value(gconf_keys['number_of_repetitions']) # ... o valor do atributo number_of_repetitions
149 print ("[+] The gconf attribute number_of_repetitions was read successfully")
150 except StandardError:169 except StandardError:
151 key_value = -1170 key_value = -1
152 print ("[-] Problem to read gconf attribute number_of_repetitions")
153 return key_value171 return key_value
154172
155 def create_configure_dialog(self, dialog=None):173 def create_configure_dialog(self, dialog=None):

Subscribers

People subscribed via source and target branches