Mercurial > audlegacy-plugins
comparison src/flac112/plugin.c @ 511:5f2145032f46 trunk
[svn] - removed http code from flac 112 plugin; still have to remove http options from gui
| author | giacomo |
|---|---|
| date | Mon, 22 Jan 2007 08:27:39 -0800 |
| parents | 0dd1ff7e5ba7 |
| children | 5be9b8f7ac03 |
comparison
equal
deleted
inserted
replaced
| 510:48e9efba7eb0 | 511:5f2145032f46 |
|---|---|
| 43 #include "plugin_common/all.h" | 43 #include "plugin_common/all.h" |
| 44 #include "grabbag.h" | 44 #include "grabbag.h" |
| 45 #include "replaygain_synthesis.h" | 45 #include "replaygain_synthesis.h" |
| 46 #include "configure.h" | 46 #include "configure.h" |
| 47 #include "charset.h" | 47 #include "charset.h" |
| 48 #include "http.h" | |
| 49 #include "tag.h" | 48 #include "tag.h" |
| 50 | 49 |
| 51 #ifdef min | 50 #ifdef min |
| 52 #undef min | 51 #undef min |
| 53 #endif | 52 #endif |
| 84 | 83 |
| 85 typedef FLAC__StreamDecoderWriteStatus (*WriteCallback) (const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); | 84 typedef FLAC__StreamDecoderWriteStatus (*WriteCallback) (const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); |
| 86 typedef void (*MetadataCallback) (const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); | 85 typedef void (*MetadataCallback) (const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); |
| 87 typedef void (*ErrorCallback) (const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); | 86 typedef void (*ErrorCallback) (const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); |
| 88 | 87 |
| 89 typedef struct { | 88 #define NUM_DECODER_TYPES 1 |
| 90 FLAC__bool seekable; | |
| 91 void* (*new_decoder) (void); | |
| 92 FLAC__bool (*set_source) (void *decoder, const char* source); | |
| 93 FLAC__bool (*unset_source) (void *decoder); | |
| 94 FLAC__bool (*set_md5_checking) (void *decoder, FLAC__bool value); | |
| 95 FLAC__bool (*set_metadata_ignore_all) (void *decoder); | |
| 96 FLAC__bool (*set_metadata_respond) (void *decoder, FLAC__MetadataType type); | |
| 97 FLAC__bool (*set_write_callback) (void *decoder, WriteCallback value); | |
| 98 FLAC__bool (*set_metadata_callback) (void *decoder, MetadataCallback value); | |
| 99 FLAC__bool (*set_error_callback) (void *decoder, ErrorCallback value); | |
| 100 FLAC__bool (*set_client_data) (void *decoder, void *value); | |
| 101 FLAC__bool (*decoder_init) (void *decoder); | |
| 102 void (*safe_decoder_finish) (void *decoder); | |
| 103 void (*safe_decoder_delete) (void *decoder); | |
| 104 FLAC__bool (*process_until_end_of_metadata) (void *decoder); | |
| 105 FLAC__bool (*process_single) (void *decoder); | |
| 106 FLAC__bool (*is_eof) (void *decoder); | |
| 107 } decoder_funcs_t; | |
| 108 | |
| 109 #define NUM_DECODER_TYPES 2 | |
| 110 typedef enum { | 89 typedef enum { |
| 111 DECODER_FILE, | 90 DECODER_FILE |
| 112 DECODER_HTTP | |
| 113 } decoder_t; | 91 } decoder_t; |
| 114 | 92 |
| 115 static void FLAC_XMMS__init(); | 93 static void FLAC_XMMS__init(); |
| 116 static int FLAC_XMMS__is_our_file(char *filename); | 94 static int FLAC_XMMS__is_our_file(char *filename); |
| 117 static int FLAC_XMMS__is_our_file_from_vfs(char *filename, VFSFile *vfsfile); | 95 static int FLAC_XMMS__is_our_file_from_vfs(char *filename, VFSFile *vfsfile); |
| 123 static void FLAC_XMMS__cleanup(); | 101 static void FLAC_XMMS__cleanup(); |
| 124 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length); | 102 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length); |
| 125 | 103 |
| 126 static void *play_loop_(void *arg); | 104 static void *play_loop_(void *arg); |
| 127 | 105 |
| 128 static FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fnsp); | 106 static FLAC__bool safe_decoder_init_(const char *filename, void *decoder); |
| 129 static void file_decoder_safe_decoder_finish_(void *decoder); | 107 static void file_decoder_safe_decoder_finish_(void *decoder); |
| 130 static void file_decoder_safe_decoder_delete_(void *decoder); | 108 static void file_decoder_safe_decoder_delete_(void *decoder); |
| 131 static FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); | 109 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); |
| 132 static void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); | 110 static void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); |
| 133 static void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); | 111 static void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); |
| 134 | 112 static FLAC__bool file_decoder_is_eof(void *decoder); |
| 135 static void init_decoder_func_tables(); | 113 |
| 136 static decoder_t source_to_decoder_type (const char *source); | 114 static decoder_t source_to_decoder_type (const char *source); |
| 137 | 115 |
| 138 gchar *flac_fmts[] = { "flac", NULL }; | 116 gchar *flac_fmts[] = { "flac", NULL }; |
| 139 | 117 |
| 140 InputPlugin flac_ip = | 118 InputPlugin flac_ip = |
| 183 | 161 |
| 184 #define BITRATE_HIST_SEGMENT_MSEC 500 | 162 #define BITRATE_HIST_SEGMENT_MSEC 500 |
| 185 /* 500ms * 50 = 25s should be enough */ | 163 /* 500ms * 50 = 25s should be enough */ |
| 186 #define BITRATE_HIST_SIZE 50 | 164 #define BITRATE_HIST_SIZE 50 |
| 187 static unsigned bitrate_history_[BITRATE_HIST_SIZE]; | 165 static unsigned bitrate_history_[BITRATE_HIST_SIZE]; |
| 188 | |
| 189 /* A table of sets of decoder functions, indexed by decoder_t */ | |
| 190 static const decoder_funcs_t* DECODER_FUNCS[NUM_DECODER_TYPES]; | |
| 191 | |
| 192 static decoder_funcs_t const * decoder_func_table_, * decoder_func_table2; | |
| 193 | 166 |
| 194 | 167 |
| 195 InputPlugin *get_iplugin_info() | 168 InputPlugin *get_iplugin_info() |
| 196 { | 169 { |
| 197 flac_ip.description = g_strdup_printf(_("FLAC Audio Plugin")); | 170 flac_ip.description = g_strdup_printf(_("FLAC Audio Plugin")); |
| 284 flac_cfg.stream.save_http_path = homedir(); | 257 flac_cfg.stream.save_http_path = homedir(); |
| 285 } | 258 } |
| 286 bmp_cfg_db_get_bool(db, "flac", "stream.cast_title_streaming", &flac_cfg.stream.cast_title_streaming); | 259 bmp_cfg_db_get_bool(db, "flac", "stream.cast_title_streaming", &flac_cfg.stream.cast_title_streaming); |
| 287 bmp_cfg_db_get_bool(db, "flac", "stream.use_udp_channel", &flac_cfg.stream.use_udp_channel); | 260 bmp_cfg_db_get_bool(db, "flac", "stream.use_udp_channel", &flac_cfg.stream.use_udp_channel); |
| 288 | 261 |
| 289 init_decoder_func_tables(); | 262 decoder_ = FLAC__seekable_stream_decoder_new(); |
| 290 decoder_func_table_ = DECODER_FUNCS [DECODER_FILE]; | |
| 291 decoder_ = decoder_func_table_ -> new_decoder(); | |
| 292 | 263 |
| 293 bmp_cfg_db_get_bool(db, NULL, "use_proxy", &flac_cfg.stream.use_proxy); | 264 bmp_cfg_db_get_bool(db, NULL, "use_proxy", &flac_cfg.stream.use_proxy); |
| 294 if(!bmp_cfg_db_get_string(db, NULL, "proxy_host", &flac_cfg.stream.proxy_host)) | 265 if(!bmp_cfg_db_get_string(db, NULL, "proxy_host", &flac_cfg.stream.proxy_host)) |
| 295 flac_cfg.stream.proxy_host = NULL; | 266 flac_cfg.stream.proxy_host = NULL; |
| 296 bmp_cfg_db_get_string(db, NULL, "proxy_port", &tmp); | 267 bmp_cfg_db_get_string(db, NULL, "proxy_port", &tmp); |
| 350 file_info_.has_replaygain = false; | 321 file_info_.has_replaygain = false; |
| 351 | 322 |
| 352 if(decoder_ == 0) | 323 if(decoder_ == 0) |
| 353 return; | 324 return; |
| 354 | 325 |
| 355 if(!safe_decoder_init_(filename, &decoder_, &decoder_func_table_)) | 326 if(!safe_decoder_init_(filename, decoder_)) |
| 356 return; | 327 return; |
| 357 | 328 |
| 358 if(file_info_.has_replaygain && flac_cfg.output.replaygain.enable) { | 329 if(file_info_.has_replaygain && flac_cfg.output.replaygain.enable) { |
| 359 if(flac_cfg.output.resolution.replaygain.bps_out == 8) { | 330 if(flac_cfg.output.resolution.replaygain.bps_out == 8) { |
| 360 file_info_.sample_format = FMT_U8; | 331 file_info_.sample_format = FMT_U8; |
| 365 file_info_.sample_format_bytes_per_sample = 2; | 336 file_info_.sample_format_bytes_per_sample = 2; |
| 366 } | 337 } |
| 367 else { | 338 else { |
| 368 /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */ | 339 /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */ |
| 369 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", flac_cfg.output.resolution.replaygain.bps_out); | 340 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", flac_cfg.output.resolution.replaygain.bps_out); |
| 370 decoder_func_table_ -> safe_decoder_finish(decoder_); | 341 file_decoder_safe_decoder_finish_(decoder_); |
| 371 return; | 342 return; |
| 372 } | 343 } |
| 373 } | 344 } |
| 374 else { | 345 else { |
| 375 if(file_info_.bits_per_sample == 8) { | 346 if(file_info_.bits_per_sample == 8) { |
| 381 file_info_.sample_format_bytes_per_sample = 2; | 352 file_info_.sample_format_bytes_per_sample = 2; |
| 382 } | 353 } |
| 383 else { | 354 else { |
| 384 /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */ | 355 /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */ |
| 385 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", file_info_.bits_per_sample); | 356 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", file_info_.bits_per_sample); |
| 386 decoder_func_table_ -> safe_decoder_finish(decoder_); | 357 file_decoder_safe_decoder_finish_(decoder_); |
| 387 return; | 358 return; |
| 388 } | 359 } |
| 389 } | 360 } |
| 390 FLAC__replaygain_synthesis__init_dither_context(&file_info_.dither_context, file_info_.sample_format_bytes_per_sample * 8, flac_cfg.output.resolution.replaygain.noise_shaping); | 361 FLAC__replaygain_synthesis__init_dither_context(&file_info_.dither_context, file_info_.sample_format_bytes_per_sample * 8, flac_cfg.output.resolution.replaygain.noise_shaping); |
| 391 file_info_.is_playing = true; | 362 file_info_.is_playing = true; |
| 392 | 363 |
| 393 if(flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) { | 364 if(flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) { |
| 394 audio_error_ = true; | 365 audio_error_ = true; |
| 395 decoder_func_table_ -> safe_decoder_finish(decoder_); | 366 file_decoder_safe_decoder_finish_(decoder_); |
| 396 return; | 367 return; |
| 397 } | 368 } |
| 398 | 369 |
| 399 file_info_.title = flac_format_song_title(filename); | 370 file_info_.title = flac_format_song_title(filename); |
| 400 flac_ip.set_info(file_info_.title, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels); | 371 flac_ip.set_info(file_info_.title, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels); |
| 411 if(file_info_.play_thread_open) { | 382 if(file_info_.play_thread_open) { |
| 412 file_info_.play_thread_open = false; | 383 file_info_.play_thread_open = false; |
| 413 g_thread_join(decode_thread_); | 384 g_thread_join(decode_thread_); |
| 414 } | 385 } |
| 415 flac_ip.output->close_audio(); | 386 flac_ip.output->close_audio(); |
| 416 decoder_func_table_ -> safe_decoder_finish (decoder_); | 387 file_decoder_safe_decoder_finish_(decoder_); |
| 417 } | 388 } |
| 418 } | 389 } |
| 419 | 390 |
| 420 void FLAC_XMMS__pause(short p) | 391 void FLAC_XMMS__pause(short p) |
| 421 { | 392 { |
| 422 flac_ip.output->pause(p); | 393 flac_ip.output->pause(p); |
| 423 } | 394 } |
| 424 | 395 |
| 425 void FLAC_XMMS__seek(int time) | 396 void FLAC_XMMS__seek(int time) |
| 426 { | 397 { |
| 427 if (decoder_func_table_->seekable) { | 398 file_info_.seek_to_in_sec = time; |
| 428 file_info_.seek_to_in_sec = time; | 399 file_info_.eof = false; |
| 429 file_info_.eof = false; | 400 |
| 430 | 401 while(file_info_.seek_to_in_sec != -1) |
| 431 while(file_info_.seek_to_in_sec != -1) | 402 xmms_usleep(10000); |
| 432 xmms_usleep(10000); | |
| 433 } | |
| 434 } | 403 } |
| 435 | 404 |
| 436 int FLAC_XMMS__get_time() | 405 int FLAC_XMMS__get_time() |
| 437 { | 406 { |
| 438 if(audio_error_) | 407 if(audio_error_) |
| 472 if (flac_cfg.stream.proxy_pass) { | 441 if (flac_cfg.stream.proxy_pass) { |
| 473 g_free(flac_cfg.stream.proxy_pass); | 442 g_free(flac_cfg.stream.proxy_pass); |
| 474 flac_cfg.stream.proxy_pass = NULL; | 443 flac_cfg.stream.proxy_pass = NULL; |
| 475 } | 444 } |
| 476 | 445 |
| 477 decoder_func_table_ -> safe_decoder_delete(decoder_); | 446 file_decoder_safe_decoder_delete_(decoder_); |
| 478 decoder_ = 0; | 447 decoder_ = 0; |
| 479 } | 448 } |
| 480 | 449 |
| 481 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec) | 450 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec) |
| 482 { | 451 { |
| 523 if(!file_info_.eof) { | 492 if(!file_info_.eof) { |
| 524 while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) { | 493 while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) { |
| 525 unsigned s; | 494 unsigned s; |
| 526 | 495 |
| 527 s = sample_buffer_last_ - sample_buffer_first_; | 496 s = sample_buffer_last_ - sample_buffer_first_; |
| 528 if(decoder_func_table_ -> is_eof(decoder_)) { | 497 if(file_decoder_is_eof(decoder_)) { |
| 529 file_info_.eof = true; | 498 file_info_.eof = true; |
| 530 break; | 499 break; |
| 531 } | 500 } |
| 532 else if (!decoder_func_table_ -> process_single(decoder_)) { | 501 else if (!FLAC__seekable_stream_decoder_process_single(decoder_)) { |
| 533 /*@@@ this should probably be a dialog */ | 502 /*@@@ this should probably be a dialog */ |
| 534 fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n"); | 503 fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n"); |
| 535 file_info_.eof = true; | 504 file_info_.eof = true; |
| 536 break; | 505 break; |
| 537 } | 506 } |
| 538 blocksize = sample_buffer_last_ - sample_buffer_first_ - s; | 507 blocksize = sample_buffer_last_ - sample_buffer_first_ - s; |
| 539 decode_position_frame_last = decode_position_frame; | 508 decode_position_frame_last = decode_position_frame; |
| 540 if(!decoder_func_table_->seekable || !FLAC__seekable_stream_decoder_get_decode_position(decoder_, &decode_position_frame)) | 509 if(!FLAC__seekable_stream_decoder_get_decode_position(decoder_, &decode_position_frame)) |
| 541 decode_position_frame = 0; | 510 decode_position_frame = 0; |
| 542 } | 511 } |
| 543 if(sample_buffer_last_ - sample_buffer_first_ > 0) { | 512 if(sample_buffer_last_ - sample_buffer_first_ > 0) { |
| 544 const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE); | 513 const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE); |
| 545 int bytes = n * file_info_.channels * file_info_.sample_format_bytes_per_sample; | 514 int bytes = n * file_info_.channels * file_info_.sample_format_bytes_per_sample; |
| 574 xmms_usleep(10000); | 543 xmms_usleep(10000); |
| 575 } | 544 } |
| 576 } | 545 } |
| 577 else | 546 else |
| 578 xmms_usleep(10000); | 547 xmms_usleep(10000); |
| 579 if(decoder_func_table_->seekable && file_info_.seek_to_in_sec != -1) { | 548 if(file_info_.seek_to_in_sec != -1) { |
| 580 const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec; | 549 const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec; |
| 581 unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); | 550 unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); |
| 582 if(FLAC__seekable_stream_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) { | 551 if(FLAC__seekable_stream_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) { |
| 583 flac_ip.output->flush(file_info_.seek_to_in_sec * 1000); | 552 flac_ip.output->flush(file_info_.seek_to_in_sec * 1000); |
| 584 bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; | 553 bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; |
| 598 flac_ip.set_info(file_info_.title, file_info_.length_in_msec, bitrate_history_[bh_index_o], file_info_.sample_rate, file_info_.channels); | 567 flac_ip.set_info(file_info_.title, file_info_.length_in_msec, bitrate_history_[bh_index_o], file_info_.sample_rate, file_info_.channels); |
| 599 } | 568 } |
| 600 } | 569 } |
| 601 } | 570 } |
| 602 | 571 |
| 603 decoder_func_table_ -> safe_decoder_finish(decoder_); | 572 file_decoder_safe_decoder_finish_(decoder_); |
| 604 | 573 |
| 605 /* are these two calls necessary? */ | 574 /* are these two calls necessary? */ |
| 606 flac_ip.output->buffer_free(); | 575 flac_ip.output->buffer_free(); |
| 607 flac_ip.output->buffer_free(); | 576 flac_ip.output->buffer_free(); |
| 608 | 577 |
| 739 FLAC__seekable_stream_decoder_set_length_callback(decoder, file_decoder_length_callback); | 708 FLAC__seekable_stream_decoder_set_length_callback(decoder, file_decoder_length_callback); |
| 740 FLAC__seekable_stream_decoder_set_eof_callback(decoder, file_decoder_eof_callback); | 709 FLAC__seekable_stream_decoder_set_eof_callback(decoder, file_decoder_eof_callback); |
| 741 return FLAC__seekable_stream_decoder_init( (FLAC__SeekableStreamDecoder*) decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK; | 710 return FLAC__seekable_stream_decoder_init( (FLAC__SeekableStreamDecoder*) decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK; |
| 742 } | 711 } |
| 743 | 712 |
| 744 static const decoder_funcs_t FILE_DECODER_FUNCTIONS = { | 713 static decoder_t source_to_decoder_type (const char *source) |
| 745 true, | 714 { |
| 746 (void* (*) (void)) FLAC__seekable_stream_decoder_new, | 715 /* NOTE: in Audacious, always use DECODER_FILE to pick files via VFS */ |
| 747 (FLAC__bool (*) (void *, const char*)) file_decoder_set_source, | 716 return DECODER_FILE; |
| 748 (FLAC__bool (*) (void *)) file_decoder_unset_source, | 717 } |
| 749 (FLAC__bool (*) (void *, FLAC__bool)) FLAC__seekable_stream_decoder_set_md5_checking, | 718 |
| 750 (FLAC__bool (*) (void *)) FLAC__seekable_stream_decoder_set_metadata_ignore_all, | 719 FLAC__bool safe_decoder_init_(const char *filename, void *decoder) |
| 751 (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__seekable_stream_decoder_set_metadata_respond, | 720 { |
| 752 (FLAC__bool (*) (void *, WriteCallback)) FLAC__seekable_stream_decoder_set_write_callback, | 721 if(decoder == 0) |
| 753 (FLAC__bool (*) (void *, MetadataCallback)) FLAC__seekable_stream_decoder_set_metadata_callback, | 722 return false; |
| 754 (FLAC__bool (*) (void *, ErrorCallback)) FLAC__seekable_stream_decoder_set_error_callback, | 723 |
| 755 (FLAC__bool (*) (void *, void *)) FLAC__seekable_stream_decoder_set_client_data, | 724 file_decoder_safe_decoder_finish_(decoder); |
| 756 (FLAC__bool (*) (void *)) file_decoder_init, | 725 |
| 757 (void (*) (void *)) file_decoder_safe_decoder_finish_, | 726 file_decoder_set_source(decoder,filename); |
| 758 (void (*) (void *)) file_decoder_safe_decoder_delete_, | 727 FLAC__seekable_stream_decoder_set_md5_checking(decoder,false); |
| 759 (FLAC__bool (*) (void *)) FLAC__seekable_stream_decoder_process_until_end_of_metadata, | 728 FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder); |
| 760 (FLAC__bool (*) (void *)) FLAC__seekable_stream_decoder_process_single, | 729 FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); |
| 761 file_decoder_is_eof | 730 FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); |
| 762 }; | 731 FLAC__seekable_stream_decoder_set_write_callback(decoder, write_callback_); |
| 763 | 732 FLAC__seekable_stream_decoder_set_metadata_callback(decoder, metadata_callback_); |
| 764 /*********** HTTP decoder functions */ | 733 FLAC__seekable_stream_decoder_set_error_callback(decoder, error_callback_); |
| 765 | 734 FLAC__seekable_stream_decoder_set_client_data(decoder, &file_info_); |
| 766 static gchar *url_ = NULL; | 735 |
| 767 | 736 if ( !file_decoder_init(decoder) ) |
| 768 static FLAC__bool http_decoder_set_url (void *decoder, const char* url) | 737 { |
| 769 { | 738 file_decoder_unset_source(decoder); |
| 770 (void) decoder; | 739 return false; |
| 771 url_ = g_strdup (url); | 740 } |
| 741 | |
| 742 if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder)) | |
| 743 { | |
| 744 file_decoder_unset_source(decoder); | |
| 745 return false; | |
| 746 } | |
| 747 | |
| 772 return true; | 748 return true; |
| 773 } | 749 } |
| 774 | 750 |
| 775 static FLAC__bool http_decoder_unset_url (void *decoder) | 751 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) |
| 776 { | |
| 777 (void) decoder; | |
| 778 if ( url_ != NULL ) | |
| 779 { | |
| 780 g_free(url_); | |
| 781 url_ = NULL; | |
| 782 } | |
| 783 return true; | |
| 784 } | |
| 785 | |
| 786 static FLAC__StreamDecoderReadStatus http_decoder_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) | |
| 787 { | |
| 788 (void) decoder; | |
| 789 (void) client_data; | |
| 790 *bytes = flac_http_read (buffer, *bytes); | |
| 791 return *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; | |
| 792 } | |
| 793 | |
| 794 static FLAC__bool http_decoder_init (void *decoder) | |
| 795 { | |
| 796 flac_http_open (url_, 0); | |
| 797 http_decoder_unset_url(decoder); | |
| 798 FLAC__stream_decoder_set_read_callback (decoder, http_decoder_read_callback); | |
| 799 return FLAC__stream_decoder_init( (FLAC__StreamDecoder*) decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; | |
| 800 } | |
| 801 | |
| 802 static FLAC__bool http_decoder_set_md5_checking (void *decoder, FLAC__bool value) | |
| 803 { | |
| 804 return false; | |
| 805 } | |
| 806 | |
| 807 static void http_decoder_safe_decoder_finish_(void *decoder) | |
| 808 { | |
| 809 if(decoder && FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) { | |
| 810 FLAC__stream_decoder_finish((FLAC__StreamDecoder *) decoder); | |
| 811 flac_http_close(); | |
| 812 } | |
| 813 } | |
| 814 | |
| 815 static void http_decoder_safe_decoder_delete_(void *decoder) | |
| 816 { | |
| 817 if(decoder) { | |
| 818 http_decoder_safe_decoder_finish_(decoder); | |
| 819 FLAC__stream_decoder_delete( (FLAC__StreamDecoder *) decoder); | |
| 820 } | |
| 821 } | |
| 822 | |
| 823 static FLAC__bool http_decoder_is_eof(void *decoder) | |
| 824 { | |
| 825 return FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) == FLAC__STREAM_DECODER_END_OF_STREAM; | |
| 826 } | |
| 827 | |
| 828 static const decoder_funcs_t HTTP_DECODER_FUNCTIONS = { | |
| 829 false, | |
| 830 (void* (*) (void)) FLAC__stream_decoder_new, | |
| 831 (FLAC__bool (*) (void *, const char*)) http_decoder_set_url, | |
| 832 (FLAC__bool (*) (void *)) http_decoder_unset_url, | |
| 833 (FLAC__bool (*) (void *, FLAC__bool)) http_decoder_set_md5_checking, | |
| 834 (FLAC__bool (*) (void *)) FLAC__stream_decoder_set_metadata_ignore_all, | |
| 835 (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__stream_decoder_set_metadata_respond, | |
| 836 (FLAC__bool (*) (void *, WriteCallback)) FLAC__stream_decoder_set_write_callback, | |
| 837 (FLAC__bool (*) (void *, MetadataCallback)) FLAC__stream_decoder_set_metadata_callback, | |
| 838 (FLAC__bool (*) (void *, ErrorCallback)) FLAC__stream_decoder_set_error_callback, | |
| 839 (FLAC__bool (*) (void *, void *)) FLAC__stream_decoder_set_client_data, | |
| 840 (FLAC__bool (*) (void *)) http_decoder_init, | |
| 841 (void (*) (void *)) http_decoder_safe_decoder_finish_, | |
| 842 (void (*) (void *)) http_decoder_safe_decoder_delete_, | |
| 843 (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_until_end_of_metadata, | |
| 844 (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_single, | |
| 845 http_decoder_is_eof | |
| 846 }; | |
| 847 | |
| 848 static decoder_funcs_t const *decoder_func_table_; | |
| 849 | |
| 850 static void init_decoder_func_tables() | |
| 851 { | |
| 852 DECODER_FUNCS [DECODER_FILE] = & FILE_DECODER_FUNCTIONS; | |
| 853 DECODER_FUNCS [DECODER_HTTP] = & HTTP_DECODER_FUNCTIONS; | |
| 854 } | |
| 855 | |
| 856 static decoder_t source_to_decoder_type (const char *source) | |
| 857 { | |
| 858 /* NOTE: in Audacious, always use DECODER_FILE to pick files via VFS; | |
| 859 http flac stream support is not used */ | |
| 860 return DECODER_FILE; | |
| 861 | |
| 862 /* return strncasecmp(source, "http://", 7) ? DECODER_FILE : DECODER_HTTP; */ | |
| 863 } | |
| 864 | |
| 865 static void change_decoder_if_needed (decoder_t new_decoder_type, void **decoderp, decoder_funcs_t const ** fntabp) | |
| 866 { | |
| 867 const decoder_funcs_t *new_fn_table = DECODER_FUNCS [new_decoder_type]; | |
| 868 if (*fntabp != new_fn_table) { | |
| 869 (*fntabp)->safe_decoder_delete(*decoderp); | |
| 870 *fntabp = new_fn_table; | |
| 871 *decoderp = new_fn_table -> new_decoder(); | |
| 872 } | |
| 873 } | |
| 874 | |
| 875 FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fntabp) | |
| 876 { | |
| 877 if(decoderp == 0 || *decoderp == 0) | |
| 878 return false; | |
| 879 | |
| 880 (*fntabp)->safe_decoder_finish(*decoderp); | |
| 881 | |
| 882 change_decoder_if_needed(source_to_decoder_type(filename), decoderp, fntabp); | |
| 883 | |
| 884 { | |
| 885 decoder_funcs_t const *fntab = *fntabp; | |
| 886 void *decoder = *decoderp; | |
| 887 | |
| 888 decoder = *decoderp; | |
| 889 fntab = *fntabp; | |
| 890 | |
| 891 fntab -> set_source(decoder, filename); | |
| 892 fntab -> set_md5_checking(decoder, false); | |
| 893 fntab -> set_metadata_ignore_all(decoder); | |
| 894 fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); | |
| 895 fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); | |
| 896 fntab -> set_write_callback(decoder, write_callback_); | |
| 897 fntab -> set_metadata_callback(decoder, metadata_callback_); | |
| 898 fntab -> set_error_callback(decoder, error_callback_); | |
| 899 fntab -> set_client_data(decoder, &file_info_); | |
| 900 if(!fntab -> decoder_init(decoder)) | |
| 901 { | |
| 902 fntab -> unset_source(decoder); | |
| 903 return false; | |
| 904 } | |
| 905 | |
| 906 if(!fntab -> process_until_end_of_metadata(decoder)) | |
| 907 { | |
| 908 fntab -> unset_source(decoder); | |
| 909 return false; | |
| 910 } | |
| 911 } | |
| 912 | |
| 913 return true; | |
| 914 } | |
| 915 | |
| 916 FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) | |
| 917 { | 752 { |
| 918 file_info_struct *file_info = (file_info_struct *)client_data; | 753 file_info_struct *file_info = (file_info_struct *)client_data; |
| 919 const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize; | 754 const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize; |
| 920 const unsigned bits_per_sample = file_info->bits_per_sample; | 755 const unsigned bits_per_sample = file_info->bits_per_sample; |
| 921 FLAC__byte *sample_buffer_start; | 756 FLAC__byte *sample_buffer_start; |
| 971 sample_buffer_last_ += wide_samples; | 806 sample_buffer_last_ += wide_samples; |
| 972 | 807 |
| 973 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; | 808 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; |
| 974 } | 809 } |
| 975 | 810 |
| 976 void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data) | 811 void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) |
| 977 { | 812 { |
| 978 file_info_struct *file_info = (file_info_struct *)client_data; | 813 file_info_struct *file_info = (file_info_struct *)client_data; |
| 979 (void)decoder; | 814 (void)decoder; |
| 980 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { | 815 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { |
| 981 FLAC__ASSERT(metadata->data.stream_info.total_samples < FLAC__U64L(0x100000000)); /* this plugin can only handle < 4 gigasamples */ | 816 FLAC__ASSERT(metadata->data.stream_info.total_samples < FLAC__U64L(0x100000000)); /* this plugin can only handle < 4 gigasamples */ |
| 992 file_info->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit); | 827 file_info->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit); |
| 993 } | 828 } |
| 994 } | 829 } |
| 995 } | 830 } |
| 996 | 831 |
| 997 void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) | 832 void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) |
| 998 { | 833 { |
| 999 file_info_struct *file_info = (file_info_struct *)client_data; | 834 file_info_struct *file_info = (file_info_struct *)client_data; |
| 1000 (void)decoder; | 835 (void)decoder; |
| 1001 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) | 836 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) |
| 1002 file_info->abort_flag = true; | 837 file_info->abort_flag = true; |
