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