comparison src/madplug/decoder.c @ 611:3f7a52adfe0e trunk

[svn] merge recent changes from yaz's branch. - stable shoutcast playback. - tag handling improvement. - view track detail on streaming won't crash. (disabled.) - filepopup for streaming is partially supported. filepopup displays track name and stream name, but not updated automatically.
author yaz
date Tue, 06 Feb 2007 12:11:42 -0800
parents 862190d39e00
children ca4cd00ca0c8
comparison
equal deleted inserted replaced
610:862190d39e00 611:3f7a52adfe0e
25 #include <signal.h> 25 #include <signal.h>
26 26
27 #include <audacious/plugin.h> 27 #include <audacious/plugin.h>
28 #include <audacious/output.h> 28 #include <audacious/output.h>
29 #include <audacious/util.h> 29 #include <audacious/util.h>
30 #include <sys/time.h>
30 #include "plugin.h" 31 #include "plugin.h"
31 #include "input.h" 32 #include "input.h"
32 33
33 #define BUFFER_SIZE 16*1024 34 #define BUFFER_SIZE 16*1024
34 #define N_AVERAGE_FRAMES 10 35 #define N_AVERAGE_FRAMES 10
150 output[pos++] = (sample >> 0) & 0xff; 151 output[pos++] = (sample >> 0) & 0xff;
151 output[pos++] = (sample >> 8) & 0xff; 152 output[pos++] = (sample >> 8) & 0xff;
152 } 153 }
153 } 154 }
154 assert(pos == olen); 155 assert(pos == olen);
155 if (info->playback->playing == 0) 156 if (!info->playback->playing)
156 return; 157 return;
157 produce_audio(mad_plugin->output->written_time(), 158 produce_audio(info->playback->output->written_time(),
158 FMT_S16_LE, MAD_NCHANNELS(header), olen, output, NULL); 159 FMT_S16_LE, MAD_NCHANNELS(header), olen, output, &(info->playback->playing));
159 if (info->playback->playing == 0) 160 if (!info->playback->playing)
160 return; 161 return;
161 g_free(output); 162 g_free(output);
162 } 163 }
163 164
164 /** 165 /**
243 #endif /* DEBUG */ 244 #endif /* DEBUG */
244 continue; 245 continue;
245 } 246 }
246 info->frames++; 247 info->frames++;
247 #ifdef DEBUG 248 #ifdef DEBUG
249 #ifdef DEBUG_INTENSIVELY
248 g_message("duration = %lu", 250 g_message("duration = %lu",
249 mad_timer_count(header.duration, 251 mad_timer_count(header.duration,
250 MAD_UNITS_MILLISECONDS)); 252 MAD_UNITS_MILLISECONDS));
251 g_message("size = %d", stream.next_frame - stream.this_frame); 253 g_message("size = %d", stream.next_frame - stream.this_frame);
254 #endif
252 #endif 255 #endif
253 mad_timer_add(&info->duration, header.duration); 256 mad_timer_add(&info->duration, header.duration);
254 data_used += stream.next_frame - stream.this_frame; 257 data_used += stream.next_frame - stream.this_frame;
255 if (info->frames == 1) { 258 if (info->frames == 1) {
256 /* most of these *should* remain constant */ 259 /* most of these *should* remain constant */
299 } 302 }
300 303
301 if (fast && info->frames >= N_AVERAGE_FRAMES) { 304 if (fast && info->frames >= N_AVERAGE_FRAMES) {
302 float frame_size = ((double) data_used) / N_AVERAGE_FRAMES; 305 float frame_size = ((double) data_used) / N_AVERAGE_FRAMES;
303 info->frames = (info->size - tagsize) / frame_size; 306 info->frames = (info->size - tagsize) / frame_size;
304 //int frame_frac = (info->size - tagsize) % frame_size;
305 info->duration.seconds /= N_AVERAGE_FRAMES; 307 info->duration.seconds /= N_AVERAGE_FRAMES;
306 info->duration.fraction /= N_AVERAGE_FRAMES; 308 info->duration.fraction /= N_AVERAGE_FRAMES;
307 mad_timer_multiply(&info->duration, info->frames); 309 mad_timer_multiply(&info->duration, info->frames);
308 #ifdef DEBUG 310 #ifdef DEBUG
309 g_message("using fast playtime calculation"); 311 g_message("using fast playtime calculation");
310 g_message("data used = %d [tagsize=%d framesize=%f]", 312 g_message("data used = %d [tagsize=%d framesize=%f]",
311 data_used, tagsize, frame_size); 313 data_used, tagsize, frame_size);
312 //g_message ("frame_size = %f [frac=%d]", frame_size, frame_frac);
313 g_message("frames = %d, frequecy = %d, channels = %d", 314 g_message("frames = %d, frequecy = %d, channels = %d",
314 info->frames, info->freq, info->channels); 315 info->frames, info->freq, info->channels);
315 long millis = mad_timer_count(info->duration, 316 long millis = mad_timer_count(info->duration,
316 MAD_UNITS_MILLISECONDS); 317 MAD_UNITS_MILLISECONDS);
317 g_message("duration = %lu:%lu", millis / 1000 / 60, 318 g_message("duration = %lu:%lu", millis / 1000 / 60,
333 xing_finish(&info->xing); 334 xing_finish(&info->xing);
334 335
335 #ifdef DEBUG 336 #ifdef DEBUG
336 g_message("e: scan_file"); 337 g_message("e: scan_file");
337 #endif /* DEBUG */ 338 #endif /* DEBUG */
338 return (info->frames != 0 || info->remote == TRUE); 339 // return info->frames != 0;
340 return (info->frames != 0 || info->remote == TRUE); // suspicious
339 } 341 }
340 342
341 gpointer decode_loop(gpointer arg) 343 gpointer decode_loop(gpointer arg)
342 { 344 {
343 unsigned char buffer[BUFFER_SIZE]; 345 unsigned char buffer[BUFFER_SIZE];
344 int len; 346 int len;
345 int seek_skip = 0; 347 gboolean seek_skip = FALSE;
346 int remainder = 0; 348 int remainder = 0;
347 gint tlen; 349 gint tlen;
348 350
349 /* mad structs */ 351 /* mad structs */
350 struct mad_stream stream; 352 struct mad_stream stream;
361 /* init mad stuff */ 363 /* init mad stuff */
362 mad_frame_init(&frame); 364 mad_frame_init(&frame);
363 mad_stream_init(&stream); 365 mad_stream_init(&stream);
364 mad_synth_init(&synth); 366 mad_synth_init(&synth);
365 367
366 if (!mad_plugin->output-> 368 if(!info->playback){
367 open_audio(info->fmt, info->freq, info->channels)) { 369 g_print("decode: playback == NULL\n");
370 return NULL;
371 }
372
373 if (!info->playback->output->open_audio(info->fmt, info->freq, info->channels)) {
374 g_mutex_lock(pb_mutex);
375 info->playback->error = TRUE;
376 info->playback->eof = 1;
377 g_mutex_unlock(pb_mutex);
368 audmad_error("failed to open audio output: %s", 378 audmad_error("failed to open audio output: %s",
369 mad_plugin->output->description); 379 info->playback->output->description);
370 g_message("failed to open audio output: %s", 380 g_message("failed to open audio output: %s",
371 mad_plugin->output->description); 381 info->playback->output->description);
372 return NULL; 382 return NULL;
373 } 383 }
374 384
375 /* set mainwin title */ 385 /* set mainwin title */
376 if (info->title) 386 if (info->title)
377 g_free(info->title); 387 g_free(info->title);
378 info->title = 388 info->title =
379 xmms_get_titlestring(xmms_get_gentitle_format(), info->tuple); 389 xmms_get_titlestring(xmms_get_gentitle_format(), info->tuple);
380 390
391
381 tlen = (gint) mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS), 392 tlen = (gint) mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS),
382 393
383 mad_plugin->set_info(info->title, 394 mad_plugin->set_info(info->title,
384 tlen == 0 ? -1 : tlen, 395 tlen == 0 ? -1 : tlen,
385 info->bitrate, info->freq, info->channels); 396 info->bitrate, info->freq, info->channels);
386 397
387 /* main loop */ 398 /* main loop */
388 do { 399 do {
389 if (info->playback->playing == 0) { 400 if (!info->playback->playing) {
390 #ifdef DEBUG 401 #ifdef DEBUG
391 g_message("decode: stop signaled"); 402 g_message("decode: stop signaled");
392 #endif /* DEBUG */ 403 #endif /* DEBUG */
393 break; 404 break;
394 } 405 }
425 if (mad_frame_decode(&frame, &stream) == 0) { 436 if (mad_frame_decode(&frame, &stream) == 0) {
426 mad_timer_add(&info->pos, frame.header.duration); 437 mad_timer_add(&info->pos, frame.header.duration);
427 if (--skip == 0) 438 if (--skip == 0)
428 mad_synth_frame(&synth, &frame); 439 mad_synth_frame(&synth, &frame);
429 } 440 }
430 else if (!MAD_RECOVERABLE(stream.error)) 441 else if (!MAD_RECOVERABLE(stream.error)) {
442 g_mutex_lock(pb_mutex);
443 info->playback->error = TRUE;
444 info->playback->eof = 1;
445 g_mutex_unlock(pb_mutex);
431 break; 446 break;
447 }
432 } 448 }
433 while (skip); 449 while (skip);
434 seek_skip = 0; 450 seek_skip = FALSE;
435 } 451 }
436 452
437 while (!info->playback->playing == 0) { 453 while (info->playback->playing) {
438 if (info->seek != -1 && !info->remote) { 454 if (info->seek != -1 && !info->remote) {
439 #ifdef DEBUG 455 #ifdef DEBUG
440 g_message("seeking: %d", info->seek); 456 g_message("seeking: %d", info->seek);
441 #endif 457 #endif
442 int new_position; 458 int new_position;
446 info->seek = seconds; 462 info->seek = seconds;
447 463
448 mad_timer_set(&info->pos, info->seek, 0, 0); 464 mad_timer_set(&info->pos, info->seek, 0, 0);
449 new_position = 465 new_position =
450 ((double) info->seek / (double) seconds) * info->size; 466 ((double) info->seek / (double) seconds) * info->size;
467
468 if(new_position < 0)
469 new_position = 0;
451 #ifdef DEBUG 470 #ifdef DEBUG
452 g_message("seeking to: %d bytes", new_position); 471 g_message("seeking to: %d bytes", new_position);
453 #endif 472 #endif
454 if (vfs_fseek(info->infile, new_position, SEEK_SET) == -1) 473 if (vfs_fseek(info->infile, new_position, SEEK_SET) == -1)
455 audmad_error("failed to seek to: %d", new_position); 474 audmad_error("failed to seek to: %d", new_position);
456 mad_frame_mute(&frame); 475 mad_frame_mute(&frame);
457 mad_synth_mute(&synth); 476 mad_synth_mute(&synth);
458 stream.error = MAD_ERROR_BUFLEN; 477 stream.error = MAD_ERROR_BUFLEN;
459 mad_plugin->output->flush(mad_timer_count 478 info->playback->output->flush(mad_timer_count(info->pos, MAD_UNITS_MILLISECONDS));
460 (info->pos,
461 MAD_UNITS_MILLISECONDS));
462 stream.sync = 0; 479 stream.sync = 0;
463 info->seek = -1; 480 info->seek = -1;
464 seek_skip = 1; 481 seek_skip = TRUE;
465 break; 482 break;
466 } 483 }
467 484
468 if (mad_header_decode(&frame.header, &stream) == -1) { 485 if (mad_header_decode(&frame.header, &stream) == -1) {
469 if (!MAD_RECOVERABLE(stream.error)) 486 if (!MAD_RECOVERABLE(stream.error)) {
470 break; 487 break;
488 }
471 if (stream.error == MAD_ERROR_LOSTSYNC) { 489 if (stream.error == MAD_ERROR_LOSTSYNC) {
472 /* ignore LOSTSYNC due to ID3 tags */ 490 /* ignore LOSTSYNC due to ID3 tags */
473 int tagsize = id3_tag_query(stream.this_frame, 491 int tagsize = id3_tag_query(stream.this_frame,
474 stream.bufend - 492 stream.bufend -
475 stream.this_frame); 493 stream.this_frame);
498 516
499 info->current_frame++; 517 info->current_frame++;
500 518
501 if (info->freq != frame.header.samplerate 519 if (info->freq != frame.header.samplerate
502 || info->channels != 520 || info->channels !=
503 (guint) MAD_NCHANNELS(&frame.header)) 521 (guint) MAD_NCHANNELS(&frame.header)) {
504 {
505 tlen = mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS);
506 #ifdef DEBUG 522 #ifdef DEBUG
507 g_message("re-opening audio due to change in audio type"); 523 g_message("re-opening audio due to change in audio type");
508 g_message("old: frequency = %d, channels = %d", info->freq, 524 g_message("old: frequency = %d, channels = %d", info->freq,
509 info->channels); 525 info->channels);
510 g_message("new: frequency = %d, channels = %d", 526 g_message("new: frequency = %d, channels = %d",
511 frame.header.samplerate, 527 frame.header.samplerate,
512 (guint) MAD_NCHANNELS(&frame.header)); 528 (guint) MAD_NCHANNELS(&frame.header));
513 #endif /* DEBUG */ 529 #endif /* DEBUG */
514
515 info->freq = frame.header.samplerate; 530 info->freq = frame.header.samplerate;
516 info->channels = MAD_NCHANNELS(&frame.header); 531 info->channels = MAD_NCHANNELS(&frame.header);
517 mad_plugin->output->close_audio(); 532 info->playback->output->close_audio();
518 if (!mad_plugin->output->open_audio(info->fmt, info->freq, 533 if (!info->playback->output->open_audio(info->fmt, info->freq,
519 info->channels)) { 534 info->channels)) {
535 g_mutex_lock(pb_mutex);
536 info->playback->error = TRUE;
537 info->playback->eof = 1;
538 g_mutex_unlock(pb_mutex);
520 audmad_error("failed to re-open audio output: %s", 539 audmad_error("failed to re-open audio output: %s",
521 mad_plugin->output->description); 540 info->playback->output->description);
522 } 541 }
523 542 }
524 mad_plugin->set_info(info->title, 543 if (!info->playback->playing)
525 tlen != 0 ? tlen : -1,
526 info->bitrate, info->freq, info->channels);
527 }
528 if (info->playback->playing == 0)
529 break; 544 break;
530 mad_synth_frame(&synth, &frame); 545 mad_synth_frame(&synth, &frame);
531 mad_stream_sync(&stream); 546 mad_stream_sync(&stream);
547
532 write_output(info, &synth.pcm, &frame.header); 548 write_output(info, &synth.pcm, &frame.header);
533 mad_timer_add(&info->pos, frame.header.duration); 549 mad_timer_add(&info->pos, frame.header.duration);
534 } 550 }
535 } 551 }
536 while (stream.error == MAD_ERROR_BUFLEN); 552 while (stream.error == MAD_ERROR_BUFLEN);
538 /* free mad stuff */ 554 /* free mad stuff */
539 mad_frame_finish(&frame); 555 mad_frame_finish(&frame);
540 mad_stream_finish(&stream); 556 mad_stream_finish(&stream);
541 mad_synth_finish(&synth); 557 mad_synth_finish(&synth);
542 558
543 if (!info->playback->playing == 0) { 559 if (info->playback->playing) {
544 mad_plugin->output->buffer_free(); 560 GTimeVal sleeptime;
545 mad_plugin->output->buffer_free(); 561
546 while (mad_plugin->output->buffer_playing()) { 562 info->playback->output->buffer_free();
563 info->playback->output->buffer_free();
564 while (info->playback->output->buffer_playing()) {
547 #ifdef DEBUG 565 #ifdef DEBUG
548 g_message("f: buffer_playing=%d", 566 g_message("f: buffer_playing=%d",
549 mad_plugin->output->buffer_playing()); 567 info->playback->output->buffer_playing());
550 #endif 568 #endif
551 xmms_usleep(10000); 569 g_get_current_time(&sleeptime);
552 if (info->playback->playing == 0) 570 sleeptime.tv_usec += 500000;
571 if(sleeptime.tv_usec >= 1000000) {
572 sleeptime.tv_sec += 1;
573 sleeptime.tv_usec -= 1000000;
574 }
575
576 g_mutex_lock(mad_mutex);
577 g_cond_timed_wait(mad_cond, mad_mutex, &sleeptime);
578 if (!info->playback->playing) {
579 g_mutex_unlock(mad_mutex);
553 break; 580 break;
581 }
582 g_mutex_unlock(mad_mutex);
554 } 583 }
555 } 584 }
556 #ifdef DEBUG 585 #ifdef DEBUG
557 g_message("e: decode"); 586 g_message("e: decode");
558 #endif /* DEBUG */ 587 #endif /* DEBUG */
559 588
560 bmp_title_input_free(info->tuple); 589 bmp_title_input_free(info->tuple);
561 info->tuple = NULL; 590 info->tuple = NULL;
562 591
563 mad_plugin->output->close_audio(); 592 info->playback->output->close_audio();
593 g_mutex_lock(mad_mutex);
564 info->playback->playing = 0; 594 info->playback->playing = 0;
595 g_mutex_unlock(mad_mutex);
565 g_thread_exit(0); 596 g_thread_exit(0);
566 return NULL; /* dummy */ 597 return NULL; /* dummy */
567 } 598 }