Mercurial > audlegacy
comparison src/audacious/playback.c @ 3319:d4f6507cded3 trunk
added a system that allows input plugins to signal to the core (actually, they MUST do it) that they're ready for playback and it's safe to call their stop function; this fixes a nasty race condition that triggered on fast track-switching
author | Giacomo Lozito <james@develia.org> |
---|---|
date | Fri, 10 Aug 2007 21:58:19 +0200 |
parents | b26dc3482ce7 |
children | 6f6f38157229 |
comparison
equal
deleted
inserted
replaced
3318:6e3ae4fd65f1 | 3319:d4f6507cded3 |
---|---|
59 #include "playback.h" | 59 #include "playback.h" |
60 #include "playback_evlisteners.h" | 60 #include "playback_evlisteners.h" |
61 | 61 |
62 static int song_info_timeout_source = 0; | 62 static int song_info_timeout_source = 0; |
63 | 63 |
64 | |
65 static gint | |
66 playback_set_pb_ready(InputPlayback *playback) | |
67 { | |
68 g_mutex_lock(playback->pb_ready_mutex); | |
69 playback->pb_ready_val = 1; | |
70 g_cond_signal(playback->pb_ready_cond); | |
71 g_mutex_unlock(playback->pb_ready_mutex); | |
72 return 0; | |
73 } | |
74 | |
75 static gint | |
76 playback_wait_for_pb_ready(InputPlayback *playback) | |
77 { | |
78 g_mutex_lock(playback->pb_ready_mutex); | |
79 while (playback->pb_ready_val != 1) | |
80 g_cond_wait(playback->pb_ready_cond, playback->pb_ready_mutex); | |
81 g_mutex_unlock(playback->pb_ready_mutex); | |
82 return 0; | |
83 } | |
84 | |
64 void | 85 void |
65 playback_eof(void) | 86 playback_eof(void) |
66 { | 87 { |
67 event_queue("playback eof", playlist_get_active()); | 88 event_queue("playback eof", playlist_get_active()); |
68 } | 89 } |
184 if ((playback = get_current_input_playback()) == NULL) | 205 if ((playback = get_current_input_playback()) == NULL) |
185 return; | 206 return; |
186 | 207 |
187 if (ip_data.playing) | 208 if (ip_data.playing) |
188 { | 209 { |
210 /* wait for plugin to signal it has reached | |
211 the 'playback safe state' before stopping */ | |
212 playback_wait_for_pb_ready(playback); | |
213 | |
189 if (playback_get_paused() == TRUE) | 214 if (playback_get_paused() == TRUE) |
190 { | 215 { |
191 if (get_written_time() > 0) | 216 if (get_written_time() > 0) |
192 output_flush(get_written_time()); /* to avoid noise */ | 217 output_flush(get_written_time()); /* to avoid noise */ |
193 playback_pause(); | 218 playback_pause(); |
194 } | 219 } |
195 | 220 |
196 ip_data.playing = FALSE; | 221 ip_data.playing = FALSE; |
197 | 222 |
198 if (playback->plugin->stop) | 223 if (playback->plugin->stop) |
199 playback->plugin->stop(playback); | 224 playback->plugin->stop(playback); |
200 | 225 |
201 if (playback->thread != NULL) | 226 if (playback->thread != NULL) |
202 g_thread_join(playback->thread); | 227 g_thread_join(playback->thread); |
203 | 228 |
204 free_vis_data(); | 229 free_vis_data(); |
205 ip_data.paused = FALSE; | 230 ip_data.paused = FALSE; |
206 | 231 |
207 g_free(playback->filename); | 232 if (playback->pb_ready_mutex) |
208 g_free(playback); | 233 g_mutex_free(playback->pb_ready_mutex); |
209 set_current_input_playback(NULL); | 234 if (playback->pb_ready_cond) |
235 g_cond_free(playback->pb_ready_cond); | |
236 | |
237 g_free(playback->filename); | |
238 g_free(playback); | |
239 set_current_input_playback(NULL); | |
210 } | 240 } |
211 | 241 |
212 ip_data.buffering = FALSE; | 242 ip_data.buffering = FALSE; |
213 ip_data.playing = FALSE; | 243 ip_data.playing = FALSE; |
214 | 244 |
243 { | 273 { |
244 InputPlayback *playback = (InputPlayback *) data; | 274 InputPlayback *playback = (InputPlayback *) data; |
245 | 275 |
246 playback->plugin->play_file(playback); | 276 playback->plugin->play_file(playback); |
247 | 277 |
278 /* if play_file has not reached the 'safe state' before returning (an error | |
279 occurred), set the playback ready value to 1 now, to allow for proper stop */ | |
280 playback_set_pb_ready(playback); | |
281 | |
248 if (!playback->error && ip_data.playing) | 282 if (!playback->error && ip_data.playing) |
249 playback_eof(); | 283 playback_eof(); |
250 else if (playback->error) | 284 else if (playback->error) |
251 playback_error(); | 285 playback_error(); |
252 | 286 |
299 | 333 |
300 playback->plugin = entry->decoder; | 334 playback->plugin = entry->decoder; |
301 playback->output = &psuedo_output_plugin; | 335 playback->output = &psuedo_output_plugin; |
302 playback->filename = g_strdup(entry->filename); | 336 playback->filename = g_strdup(entry->filename); |
303 playback->thread = g_thread_self(); | 337 playback->thread = g_thread_self(); |
338 playback->pb_ready_mutex = g_mutex_new(); | |
339 playback->pb_ready_cond = g_cond_new(); | |
340 playback->pb_ready_val = 0; | |
341 playback->set_pb_ready = playback_set_pb_ready; | |
304 | 342 |
305 set_current_input_playback(playback); | 343 set_current_input_playback(playback); |
306 | 344 |
307 g_thread_create(playback_monitor_thread, playback, TRUE, NULL); | 345 g_thread_create(playback_monitor_thread, playback, TRUE, NULL); |
308 | 346 |