Mercurial > audlegacy-plugins
comparison src/cue/cuesheet.c @ 848:2452835bbfcf trunk
[svn] - make "stop after current song" work.
- now cuesheet plugin handles the end of file nicely.
- improve reliability.
author | yaz |
---|---|
date | Tue, 13 Mar 2007 09:37:27 -0700 |
parents | 29ae10725c4c |
children | def1af87ae1f |
comparison
equal
deleted
inserted
replaced
847:11278fe4764b | 848:2452835bbfcf |
---|---|
1 /* Audacious: An advanced media player. | 1 /* Audacious: An advanced media player. |
2 * cuesheet.c: Support cuesheets as a media container. | 2 * cuesheet.c: Support cuesheets as a media container. |
3 * | 3 * |
4 * Copyright (C) 2006 William Pitcock <nenolod -at- nenolod.net>. | 4 * Copyright (C) 2006 William Pitcock <nenolod -at- nenolod.net>. |
5 * Jonathan Schleifer <js@h3c.de> (only small fixes) | 5 * Jonathan Schleifer <js@h3c.de> (only small fixes) |
6 * | |
7 * Copyright (C) 2007 Yoshiki Yazawa <yaz@cc.rim.or.jp> (millisecond | |
8 * seek and multithreading) | |
6 * | 9 * |
7 * This file was hacked out of of xmms-cueinfo, | 10 * This file was hacked out of of xmms-cueinfo, |
8 * Copyright (C) 2003 Oskar Liljeblad | 11 * Copyright (C) 2003 Oskar Liljeblad |
9 * | 12 * |
10 * This software is copyrighted work licensed under the terms of the | 13 * This software is copyrighted work licensed under the terms of the |
13 */ | 16 */ |
14 #ifdef HAVE_CONFIG_H | 17 #ifdef HAVE_CONFIG_H |
15 #include "config.h" | 18 #include "config.h" |
16 #endif | 19 #endif |
17 | 20 |
18 #define DEBUG 1 | 21 /* #define DEBUG 1 */ |
19 | 22 |
20 #include <string.h> | 23 #include <string.h> |
21 #include <stdlib.h> | 24 #include <stdlib.h> |
22 #include <stdio.h> | 25 #include <stdio.h> |
23 #include <ctype.h> | 26 #include <ctype.h> |
56 static enum { | 59 static enum { |
57 STOP, | 60 STOP, |
58 RUN, | 61 RUN, |
59 EXIT, | 62 EXIT, |
60 } watchdog_state; | 63 } watchdog_state; |
64 | |
65 static InputPlayback *caller_ip = NULL; | |
66 GThread *exec_thread; | |
61 | 67 |
62 static gchar *cue_file = NULL; | 68 static gchar *cue_file = NULL; |
63 static gchar *cue_title = NULL; | 69 static gchar *cue_title = NULL; |
64 static gchar *cue_performer = NULL; | 70 static gchar *cue_performer = NULL; |
65 static gchar *cue_genre = NULL; | 71 static gchar *cue_genre = NULL; |
126 | 132 |
127 static void cue_cleanup(void) | 133 static void cue_cleanup(void) |
128 { | 134 { |
129 g_mutex_lock(cue_mutex); | 135 g_mutex_lock(cue_mutex); |
130 watchdog_state = EXIT; | 136 watchdog_state = EXIT; |
131 g_cond_signal(cue_cond); | |
132 g_mutex_unlock(cue_mutex); | 137 g_mutex_unlock(cue_mutex); |
138 g_cond_broadcast(cue_cond); | |
133 | 139 |
134 g_thread_join(watchdog_thread); | 140 g_thread_join(watchdog_thread); |
135 | 141 |
136 g_cond_free(cue_cond); | 142 g_cond_free(cue_cond); |
137 g_mutex_free(cue_mutex); | 143 g_mutex_free(cue_mutex); |
179 } | 185 } |
180 | 186 |
181 static void play(InputPlayback *data) | 187 static void play(InputPlayback *data) |
182 { | 188 { |
183 gchar *uri = data->filename; | 189 gchar *uri = data->filename; |
190 | |
191 #ifdef DEBUG | |
192 g_print("play: playback = %p\n", data); | |
193 #endif | |
194 | |
195 caller_ip = data; | |
184 /* this isn't a cue:// uri? */ | 196 /* this isn't a cue:// uri? */ |
185 if (strncasecmp("cue://", uri, 6)) | 197 if (strncasecmp("cue://", uri, 6)) |
186 { | 198 { |
187 gchar *tmp = g_strdup_printf("cue://%s?0", uri); | 199 gchar *tmp = g_strdup_printf("cue://%s?0", uri); |
188 play_cue_uri(data, tmp); | 200 play_cue_uri(data, tmp); |
282 bmp_title_input_free(tuple); | 294 bmp_title_input_free(tuple); |
283 } | 295 } |
284 | 296 |
285 static void seek(InputPlayback * data, gint time) | 297 static void seek(InputPlayback * data, gint time) |
286 { | 298 { |
299 #ifdef DEBUG | |
300 g_print("seek: playback = %p\n", data); | |
301 #endif | |
302 | |
287 if (real_ip != NULL) | 303 if (real_ip != NULL) |
288 real_ip->plugin->seek(real_ip, time); | 304 real_ip->plugin->seek(real_ip, time); |
289 } | 305 } |
290 | 306 |
291 static void stop(InputPlayback * data) | 307 static void stop(InputPlayback * data) |
292 { | 308 { |
309 #ifdef DEBUG | |
310 g_print("f: stop: playback = %p\n", data); | |
311 #endif | |
293 if (real_ip != NULL) | 312 if (real_ip != NULL) |
294 real_ip->plugin->stop(real_ip); | 313 real_ip->plugin->stop(real_ip); |
295 | 314 |
296 if (data != NULL) | 315 if (data != NULL) |
297 data->playing = 0; | 316 data->playing = 0; |
317 if (caller_ip != NULL) | |
318 caller_ip->playing = 0; | |
298 | 319 |
299 g_mutex_lock(cue_mutex); | 320 g_mutex_lock(cue_mutex); |
300 watchdog_state = STOP; | 321 watchdog_state = STOP; |
322 g_mutex_unlock(cue_mutex); | |
301 g_cond_signal(cue_cond); | 323 g_cond_signal(cue_cond); |
302 g_mutex_unlock(cue_mutex); | |
303 | 324 |
304 free_cue_info(); | 325 free_cue_info(); |
305 | 326 |
306 if (real_ip != NULL) { | 327 if (real_ip != NULL) { |
307 real_ip->plugin->set_info = cue_ip.set_info; | 328 real_ip->plugin->set_info = cue_ip.set_info; |
308 real_ip->plugin->output = NULL; | 329 real_ip->plugin->output = NULL; |
309 g_free(real_ip); | 330 g_free(real_ip); |
310 real_ip = NULL; | 331 real_ip = NULL; |
311 } | 332 } |
312 } | 333 #ifdef DEBUG |
334 g_print("e: stop\n"); | |
335 #endif | |
336 } | |
337 | |
338 static gpointer do_stop(gpointer data) | |
339 { | |
340 InputPlayback *playback = (InputPlayback *)data; | |
341 #ifdef DEBUG | |
342 g_print("f: do_stop\n"); | |
343 #endif | |
344 ip_data.stop = TRUE; | |
345 playback_stop(); | |
346 ip_data.stop = FALSE; | |
347 | |
348 gdk_threads_enter(); | |
349 mainwin_clear_song_info(); | |
350 gdk_threads_leave(); | |
351 | |
352 #ifdef DEBUG | |
353 g_print("e: do_stop\n"); | |
354 #endif | |
355 g_thread_exit(NULL); | |
356 } | |
357 | |
358 static gpointer do_prev(gpointer data) | |
359 { | |
360 Playlist *playlist = playlist_get_active(); | |
361 | |
362 #ifdef DEBUG | |
363 g_print("do_prev\n"); | |
364 #endif | |
365 playlist_prev(playlist); | |
366 g_thread_exit(NULL); | |
367 } | |
368 | |
369 static gpointer do_next(gpointer data) | |
370 { | |
371 Playlist *playlist = playlist_get_active(); | |
372 | |
373 #ifdef DEBUG | |
374 g_print("do_next\n"); | |
375 #endif | |
376 playlist_next(playlist); | |
377 g_thread_exit(NULL); | |
378 } | |
379 | |
313 | 380 |
314 static void cue_pause(InputPlayback * data, short p) | 381 static void cue_pause(InputPlayback * data, short p) |
315 { | 382 { |
316 if (real_ip != NULL) | 383 if (real_ip != NULL) |
317 real_ip->plugin->pause(real_ip, p); | 384 real_ip->plugin->pause(real_ip, p); |
345 gchar *dummy = NULL; | 412 gchar *dummy = NULL; |
346 InputPlugin *real_ip_plugin; | 413 InputPlugin *real_ip_plugin; |
347 | 414 |
348 #ifdef DEBUG | 415 #ifdef DEBUG |
349 g_print("f: play_cue_uri\n"); | 416 g_print("f: play_cue_uri\n"); |
350 #endif | 417 g_print("play_cue_uri: playback = %p\n", data); |
418 #endif | |
419 | |
351 /* stop watchdog thread */ | 420 /* stop watchdog thread */ |
352 g_mutex_lock(cue_mutex); | 421 g_mutex_lock(cue_mutex); |
353 watchdog_state = STOP; | 422 watchdog_state = STOP; |
423 g_mutex_unlock(cue_mutex); | |
354 g_cond_signal(cue_cond); | 424 g_cond_signal(cue_cond); |
355 g_mutex_unlock(cue_mutex); | |
356 | 425 |
357 if (_path != NULL && *_path == '?') | 426 if (_path != NULL && *_path == '?') |
358 { | 427 { |
359 *_path = '\0'; | 428 *_path = '\0'; |
360 _path++; | 429 _path++; |
394 real_ip->plugin->seek(real_ip, finetune_seek ? finetune_seek / 1000 : cue_tracks[track].index / 1000 + 1); | 463 real_ip->plugin->seek(real_ip, finetune_seek ? finetune_seek / 1000 : cue_tracks[track].index / 1000 + 1); |
395 | 464 |
396 /* kick watchdog thread */ | 465 /* kick watchdog thread */ |
397 g_mutex_lock(cue_mutex); | 466 g_mutex_lock(cue_mutex); |
398 watchdog_state = RUN; | 467 watchdog_state = RUN; |
468 g_mutex_unlock(cue_mutex); | |
399 g_cond_signal(cue_cond); | 469 g_cond_signal(cue_cond); |
400 g_mutex_unlock(cue_mutex); | 470 g_print("watchdog activated\n"); |
401 | 471 |
402 // in some plugins, NULL as 2nd arg causes crash. | 472 // in some plugins, NULL as 2nd arg causes crash. |
403 real_ip->plugin->get_song_info(cue_file, &dummy, &file_length); | 473 real_ip->plugin->get_song_info(cue_file, &dummy, &file_length); |
404 g_free(dummy); | 474 g_free(dummy); |
405 cue_tracks[last_cue_track].index = file_length; | 475 cue_tracks[last_cue_track].index = file_length; |
444 #ifdef DEBUG | 514 #ifdef DEBUG |
445 g_print("f: watchdog\n"); | 515 g_print("f: watchdog\n"); |
446 #endif | 516 #endif |
447 | 517 |
448 while(1) { | 518 while(1) { |
449 #if 0 | 519 #if 1 |
450 #if DEBUG | 520 #if DEBUG |
451 g_print("time = %d cur = %d cidx = %d nidx = %d\n", time, cur_cue_track, | 521 g_print("time = %d cur = %d cidx = %d nidx = %d last = %d\n", |
522 time, cur_cue_track, | |
452 cue_tracks[cur_cue_track].index, | 523 cue_tracks[cur_cue_track].index, |
453 cue_tracks[cur_cue_track+1].index); | 524 cue_tracks[cur_cue_track+1].index, last_cue_track); |
454 #endif | 525 #endif |
455 #endif | 526 #endif |
456 g_get_current_time(&sleep_time); | 527 g_get_current_time(&sleep_time); |
457 g_time_val_add(&sleep_time, 10000); // 10msec | 528 g_time_val_add(&sleep_time, 10000); // 10msec |
458 | 529 |
480 break; | 551 break; |
481 } | 552 } |
482 g_mutex_unlock(cue_mutex); | 553 g_mutex_unlock(cue_mutex); |
483 | 554 |
484 time = get_output_time(); | 555 time = get_output_time(); |
485 | 556 if(time == 0) |
486 if(time == 0 || (real_ip && real_ip->playing == 0)) | |
487 continue; | 557 continue; |
558 | |
559 #ifdef DEBUG | |
560 if(real_ip) { | |
561 g_print("real_ip->playing = %d\n", real_ip->playing); | |
562 if(real_ip->playing == 0) | |
563 g_print("not playing\n"); | |
564 if(!real_ip->output->buffer_playing()) | |
565 g_print("not buffer_playing\n"); | |
566 } | |
567 #endif | |
488 | 568 |
489 // prev track | 569 // prev track |
490 if (time < cue_tracks[cur_cue_track].index) | 570 if (time < cue_tracks[cur_cue_track].index) |
491 { | 571 { |
492 #ifdef DEBUG | 572 #ifdef DEBUG |
496 cue_tracks[cur_cue_track+1].index); | 576 cue_tracks[cur_cue_track+1].index); |
497 #endif | 577 #endif |
498 cur_cue_track--; | 578 cur_cue_track--; |
499 if (time >= cue_tracks[cur_cue_track].index) | 579 if (time >= cue_tracks[cur_cue_track].index) |
500 finetune_seek = time; | 580 finetune_seek = time; |
501 playlist_prev(playlist); | 581 exec_thread = g_thread_create(do_prev, NULL, FALSE, NULL); |
502 } | 582 } |
503 | 583 |
504 // next track | 584 // next track |
505 if (cur_cue_track != last_cue_track && (time > cue_tracks[cur_cue_track + 1].index)) | 585 if (cur_cue_track != last_cue_track && (time > cue_tracks[cur_cue_track + 1].index)) |
506 { | 586 { |
512 #endif | 592 #endif |
513 cur_cue_track++; | 593 cur_cue_track++; |
514 if (time <= cue_tracks[cur_cue_track].index) | 594 if (time <= cue_tracks[cur_cue_track].index) |
515 finetune_seek = time; | 595 finetune_seek = time; |
516 | 596 |
517 if(cfg.stopaftersong) | 597 if(cfg.stopaftersong) { |
518 stop(real_ip); | 598 exec_thread = g_thread_create(do_stop, (void *)real_ip, FALSE, NULL); |
599 } | |
519 else | 600 else |
520 playlist_next(playlist); | 601 exec_thread = g_thread_create(do_next, NULL, FALSE, NULL); |
521 } | 602 } |
603 | |
604 // end of file | |
605 if (cur_cue_track + 1 == last_cue_track && | |
606 cue_tracks[cur_cue_track + 1].index - time < 500) { // difference < 500ms | |
607 #ifdef DEBUG | |
608 g_print("eof reached\n"); | |
609 #endif | |
610 exec_thread = g_thread_create(do_stop, (void *)real_ip, FALSE, NULL); | |
611 } | |
612 | |
522 } | 613 } |
523 | 614 |
524 #ifdef DEBUG | 615 #ifdef DEBUG |
525 g_print("e: watchdog\n"); | 616 g_print("e: watchdog\n"); |
526 #endif | 617 #endif |