Mercurial > audlegacy-plugins
comparison src/flac/plugin.c @ 96:63bde7ca7ad0 trunk
[svn] First attempt at porting our FLAC plugin to API 1.1.3 (completely incompatible, as usual!). Needs more work and a version-sensitize FLAC checker.
| author | chainsaw |
|---|---|
| date | Sat, 21 Oct 2006 09:21:12 -0700 |
| parents | 3da1b8942b8b |
| children | a19f24790f3c |
comparison
equal
deleted
inserted
replaced
| 95:b5a1b762f586 | 96:63bde7ca7ad0 |
|---|---|
| 1 /* libxmms-flac - XMMS FLAC input plugin | 1 /* libxmms-flac - XMMS FLAC input plugin |
| 2 * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson | 2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson |
| 3 * | 3 * |
| 4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
| 6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
| 7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
| 14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software | 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 */ | 17 */ |
| 18 | 18 |
| 19 #include <limits.h> | |
| 19 #include <stdlib.h> | 20 #include <stdlib.h> |
| 20 #include <string.h> | 21 #include <string.h> |
| 21 #include <stdio.h> | 22 #include <stdio.h> |
| 22 #include <glib.h> | 23 #include <glib.h> |
| 23 #include <pwd.h> | 24 #include <pwd.h> |
| 51 #ifdef min | 52 #ifdef min |
| 52 #undef min | 53 #undef min |
| 53 #endif | 54 #endif |
| 54 #define min(x,y) ((x)<(y)?(x):(y)) | 55 #define min(x,y) ((x)<(y)?(x):(y)) |
| 55 | 56 |
| 56 /* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ | |
| 57 #ifdef _MSC_VER | |
| 58 #define FLAC__U64L(x) x | |
| 59 #else | |
| 60 #define FLAC__U64L(x) x##LLU | |
| 61 #endif | |
| 62 | |
| 63 extern void FLAC_XMMS__file_info_box(char *filename); | 57 extern void FLAC_XMMS__file_info_box(char *filename); |
| 64 | 58 |
| 65 typedef struct { | 59 typedef struct { |
| 66 FLAC__bool abort_flag; | 60 FLAC__bool abort_flag; |
| 67 FLAC__bool is_playing; | 61 FLAC__bool is_playing; |
| 62 FLAC__bool is_http_source; | |
| 68 FLAC__bool eof; | 63 FLAC__bool eof; |
| 69 FLAC__bool play_thread_open; /* if true, is_playing must also be true */ | 64 FLAC__bool play_thread_open; /* if true, is_playing must also be true */ |
| 70 unsigned total_samples; | 65 FLAC__uint64 total_samples; |
| 71 unsigned bits_per_sample; | 66 unsigned bits_per_sample; |
| 72 unsigned channels; | 67 unsigned channels; |
| 73 unsigned sample_rate; | 68 unsigned sample_rate; |
| 74 unsigned length_in_msec; | 69 int length_in_msec; /* int (instead of FLAC__uint64) only because that's what XMMS uses; seeking won't work right if this maxes out */ |
| 75 gchar *title; | 70 gchar *title; |
| 76 AFormat sample_format; | 71 AFormat sample_format; |
| 77 unsigned sample_format_bytes_per_sample; | 72 unsigned sample_format_bytes_per_sample; |
| 78 int seek_to_in_sec; | 73 int seek_to_in_sec; |
| 79 FLAC__bool has_replaygain; | 74 FLAC__bool has_replaygain; |
| 80 double replay_scale; | 75 double replay_scale; |
| 81 DitherContext dither_context; | 76 DitherContext dither_context; |
| 82 } file_info_struct; | 77 } stream_data_struct; |
| 83 | |
| 84 typedef FLAC__StreamDecoderWriteStatus (*WriteCallback) (const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); | |
| 85 typedef void (*MetadataCallback) (const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); | |
| 86 typedef void (*ErrorCallback) (const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); | |
| 87 | |
| 88 typedef struct { | |
| 89 FLAC__bool seekable; | |
| 90 void* (*new_decoder) (void); | |
| 91 FLAC__bool (*set_md5_checking) (void *decoder, FLAC__bool value); | |
| 92 FLAC__bool (*set_source) (void *decoder, const char* source); | |
| 93 FLAC__bool (*set_metadata_ignore_all) (void *decoder); | |
| 94 FLAC__bool (*set_metadata_respond) (void *decoder, FLAC__MetadataType type); | |
| 95 FLAC__bool (*set_write_callback) (void *decoder, WriteCallback value); | |
| 96 FLAC__bool (*set_metadata_callback) (void *decoder, MetadataCallback value); | |
| 97 FLAC__bool (*set_error_callback) (void *decoder, ErrorCallback value); | |
| 98 FLAC__bool (*set_client_data) (void *decoder, void *value); | |
| 99 FLAC__bool (*decoder_init) (void *decoder); | |
| 100 void (*safe_decoder_finish) (void *decoder); | |
| 101 void (*safe_decoder_delete) (void *decoder); | |
| 102 FLAC__bool (*process_until_end_of_metadata) (void *decoder); | |
| 103 FLAC__bool (*process_single) (void *decoder); | |
| 104 FLAC__bool (*is_eof) (void *decoder); | |
| 105 } decoder_funcs_t; | |
| 106 | |
| 107 #define NUM_DECODER_TYPES 2 | |
| 108 typedef enum { | |
| 109 DECODER_FILE, | |
| 110 DECODER_HTTP | |
| 111 } decoder_t; | |
| 112 | 78 |
| 113 static void FLAC_XMMS__init(); | 79 static void FLAC_XMMS__init(); |
| 114 static int FLAC_XMMS__is_our_file(char *filename); | 80 static int FLAC_XMMS__is_our_file(char *filename); |
| 115 static void FLAC_XMMS__play_file(char *filename); | 81 static void FLAC_XMMS__play_file(char *filename); |
| 116 static void FLAC_XMMS__stop(); | 82 static void FLAC_XMMS__stop(); |
| 120 static void FLAC_XMMS__cleanup(); | 86 static void FLAC_XMMS__cleanup(); |
| 121 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length); | 87 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length); |
| 122 | 88 |
| 123 static void *play_loop_(void *arg); | 89 static void *play_loop_(void *arg); |
| 124 | 90 |
| 125 static FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fnsp); | 91 static FLAC__bool safe_decoder_init_(const char *filename, FLAC__StreamDecoder *decoder); |
| 126 static void file_decoder_safe_decoder_finish_(void *decoder); | 92 static void safe_decoder_finish_(FLAC__StreamDecoder *decoder); |
| 127 static void file_decoder_safe_decoder_delete_(void *decoder); | 93 static void safe_decoder_delete_(FLAC__StreamDecoder *decoder); |
| 128 static FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); | 94 |
| 129 static void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); | 95 static FLAC__StreamDecoderReadStatus http_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); |
| 130 static void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); | 96 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); |
| 131 | 97 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); |
| 132 static void init_decoder_func_tables(); | 98 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); |
| 133 static decoder_t source_to_decoder_type (const char *source); | |
| 134 | 99 |
| 135 InputPlugin flac_ip = | 100 InputPlugin flac_ip = |
| 136 { | 101 { |
| 137 NULL, | 102 NULL, |
| 138 NULL, | 103 NULL, |
| 164 #define SAMPLES_PER_WRITE 512 | 129 #define SAMPLES_PER_WRITE 512 |
| 165 #define SAMPLE_BUFFER_SIZE ((FLAC__MAX_BLOCK_SIZE + SAMPLES_PER_WRITE) * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8)) | 130 #define SAMPLE_BUFFER_SIZE ((FLAC__MAX_BLOCK_SIZE + SAMPLES_PER_WRITE) * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8)) |
| 166 static FLAC__byte sample_buffer_[SAMPLE_BUFFER_SIZE]; | 131 static FLAC__byte sample_buffer_[SAMPLE_BUFFER_SIZE]; |
| 167 static unsigned sample_buffer_first_, sample_buffer_last_; | 132 static unsigned sample_buffer_first_, sample_buffer_last_; |
| 168 | 133 |
| 169 static void *decoder_ = 0, *decoder2 = 0; | 134 static FLAC__StreamDecoder *decoder_ = 0, *decoder2 = 0; |
| 170 static file_info_struct file_info_; | 135 static stream_data_struct stream_data_; |
| 171 static GThread *decode_thread_; | 136 static GThread *decode_thread_; |
| 172 static FLAC__bool audio_error_ = false; | 137 static FLAC__bool audio_error_ = false; |
| 173 static FLAC__bool is_big_endian_host_; | 138 static FLAC__bool is_big_endian_host_; |
| 174 | 139 |
| 175 #define BITRATE_HIST_SEGMENT_MSEC 500 | 140 #define BITRATE_HIST_SEGMENT_MSEC 500 |
| 176 /* 500ms * 50 = 25s should be enough */ | 141 /* 500ms * 50 = 25s should be enough */ |
| 177 #define BITRATE_HIST_SIZE 50 | 142 #define BITRATE_HIST_SIZE 50 |
| 178 static unsigned bitrate_history_[BITRATE_HIST_SIZE]; | 143 static unsigned bitrate_history_[BITRATE_HIST_SIZE]; |
| 179 | 144 |
| 180 /* A table of sets of decoder functions, indexed by decoder_t */ | 145 #ifdef SUPPORT_ATTRIBUTE_VISIBILITY |
| 181 static const decoder_funcs_t* DECODER_FUNCS[NUM_DECODER_TYPES]; | 146 InputPlugin *get_iplugin_info() __attribute__((visibility("default"))); |
| 182 | 147 #endif |
| 183 static decoder_funcs_t const * decoder_func_table_, * decoder_func_table2; | |
| 184 | |
| 185 | 148 |
| 186 InputPlugin *get_iplugin_info() | 149 InputPlugin *get_iplugin_info() |
| 187 { | 150 { |
| 188 flac_ip.description = g_strdup_printf(_("FLAC Audio Plugin")); | 151 flac_ip.description = g_strdup_printf(_("FLAC Audio Plugin")); |
| 189 return &flac_ip; | 152 return &flac_ip; |
| 190 } | 153 } |
| 191 | 154 |
| 192 void set_track_info(const char* title, int length_in_msec) | 155 void set_track_info(const char* title, int length_in_msec) |
| 193 { | 156 { |
| 194 if (file_info_.is_playing) { | 157 if (stream_data_.is_playing) { |
| 195 flac_ip.set_info((char*) title, length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels); | 158 flac_ip.set_info((char*) title, length_in_msec, stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample, stream_data_.sample_rate, stream_data_.channels); |
| 196 } | 159 } |
| 197 } | 160 } |
| 198 | 161 |
| 199 static gchar* homedir() | 162 static gchar* homedir() |
| 200 { | 163 { |
| 212 endpwent(); | 175 endpwent(); |
| 213 } | 176 } |
| 214 return result; | 177 return result; |
| 215 } | 178 } |
| 216 | 179 |
| 180 static FLAC__bool is_http_source(const char *source) | |
| 181 { | |
| 182 return 0 == strncasecmp(source, "http://", 7); | |
| 183 } | |
| 184 | |
| 217 void FLAC_XMMS__init() | 185 void FLAC_XMMS__init() |
| 218 { | 186 { |
| 219 ConfigDb *db; | 187 ConfigDb *db; |
| 220 FLAC__uint32 test = 1; | 188 FLAC__uint32 test = 1; |
| 221 gchar *tmp = NULL; | |
| 222 | 189 |
| 223 is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; | 190 is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; |
| 224 | 191 |
| 225 memset(&flac_cfg, 0, sizeof(flac_cfg)); | 192 flac_cfg.title.tag_override = FALSE; |
| 193 if (flac_cfg.title.tag_format) | |
| 194 g_free(flac_cfg.title.tag_format); | |
| 195 flac_cfg.title.convert_char_set = FALSE; | |
| 226 | 196 |
| 227 db = bmp_cfg_db_open(); | 197 db = bmp_cfg_db_open(); |
| 228 | 198 |
| 229 /* title */ | 199 /* title */ |
| 230 | 200 |
| 273 flac_cfg.stream.save_http_path = homedir(); | 243 flac_cfg.stream.save_http_path = homedir(); |
| 274 } | 244 } |
| 275 bmp_cfg_db_get_bool(db, "flac", "stream.cast_title_streaming", &flac_cfg.stream.cast_title_streaming); | 245 bmp_cfg_db_get_bool(db, "flac", "stream.cast_title_streaming", &flac_cfg.stream.cast_title_streaming); |
| 276 bmp_cfg_db_get_bool(db, "flac", "stream.use_udp_channel", &flac_cfg.stream.use_udp_channel); | 246 bmp_cfg_db_get_bool(db, "flac", "stream.use_udp_channel", &flac_cfg.stream.use_udp_channel); |
| 277 | 247 |
| 278 init_decoder_func_tables(); | |
| 279 decoder_func_table_ = DECODER_FUNCS [DECODER_FILE]; | |
| 280 decoder_ = decoder_func_table_ -> new_decoder(); | |
| 281 | |
| 282 bmp_cfg_db_get_bool(db, NULL, "use_proxy", &flac_cfg.stream.use_proxy); | 248 bmp_cfg_db_get_bool(db, NULL, "use_proxy", &flac_cfg.stream.use_proxy); |
| 283 bmp_cfg_db_get_string(db, NULL, "proxy_host", &flac_cfg.stream.proxy_host); | 249 bmp_cfg_db_get_string(db, NULL, "proxy_host", &flac_cfg.stream.proxy_host); |
| 284 bmp_cfg_db_get_string(db, NULL, "proxy_port", &tmp); | 250 bmp_cfg_db_get_string(db, NULL, "proxy_port", &tmp); |
| 285 | 251 |
| 286 if (tmp != NULL) | |
| 287 flac_cfg.stream.proxy_port = atoi(tmp); | |
| 288 | |
| 289 bmp_cfg_db_get_bool(db, NULL, "proxy_use_auth", &flac_cfg.stream.proxy_use_auth); | 252 bmp_cfg_db_get_bool(db, NULL, "proxy_use_auth", &flac_cfg.stream.proxy_use_auth); |
| 290 bmp_cfg_db_get_string(db, NULL, "proxy_user", &flac_cfg.stream.proxy_user); | 253 bmp_cfg_db_get_string(db, NULL, "proxy_user", &flac_cfg.stream.proxy_user); |
| 291 bmp_cfg_db_get_string(db, NULL, "proxy_pass", &flac_cfg.stream.proxy_pass); | 254 bmp_cfg_db_get_string(db, NULL, "proxy_pass", &flac_cfg.stream.proxy_pass); |
| 292 | 255 |
| 256 decoder_ = FLAC__stream_decoder_new(); | |
| 293 bmp_cfg_db_close(db); | 257 bmp_cfg_db_close(db); |
| 294 } | 258 } |
| 295 | 259 |
| 296 int FLAC_XMMS__is_our_file(char *filename) | 260 int FLAC_XMMS__is_our_file(char *filename) |
| 297 { | 261 { |
| 298 FILE *f; | 262 FILE *f; |
| 299 FLAC__StreamMetadata streaminfo; | 263 FLAC__StreamMetadata streaminfo; |
| 300 | 264 |
| 301 if (source_to_decoder_type (filename) == DECODER_FILE) { | 265 if(!is_http_source(filename)) { |
| 302 if(0 == (f = fopen(filename, "r"))) | 266 if(0 == (f = fopen(filename, "r"))) |
| 303 return 0; | |
| 304 fclose(f); | |
| 305 if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) | |
| 306 return 0; | 267 return 0; |
| 307 return 1; | 268 fclose(f); |
| 308 } | 269 if(FLAC__metadata_get_streaminfo(filename, &streaminfo)) |
| 309 | 270 return 1; |
| 310 if(!safe_decoder_init_(filename, &decoder2, &decoder_func_table2)) | |
| 311 return 0; | 271 return 0; |
| 312 | 272 } |
| 313 decoder_func_table2 -> safe_decoder_finish(decoder2); | 273 |
| 274 if(!safe_decoder_init_(filename, decoder2)) | |
| 275 return 0; | |
| 276 | |
| 277 safe_decoder_finish_(decoder2); | |
| 314 return 1; | 278 return 1; |
| 315 } | 279 } |
| 316 | 280 |
| 317 void FLAC_XMMS__play_file(char *filename) | 281 void FLAC_XMMS__play_file(char *filename) |
| 318 { | 282 { |
| 319 FILE *f; | 283 FILE *f; |
| 320 | 284 |
| 321 sample_buffer_first_ = sample_buffer_last_ = 0; | 285 sample_buffer_first_ = sample_buffer_last_ = 0; |
| 322 audio_error_ = false; | 286 audio_error_ = false; |
| 323 file_info_.abort_flag = false; | 287 stream_data_.abort_flag = false; |
| 324 file_info_.is_playing = false; | 288 stream_data_.is_playing = false; |
| 325 file_info_.eof = false; | 289 stream_data_.is_http_source = is_http_source(filename); |
| 326 file_info_.play_thread_open = false; | 290 stream_data_.eof = false; |
| 327 file_info_.has_replaygain = false; | 291 stream_data_.play_thread_open = false; |
| 328 | 292 stream_data_.has_replaygain = false; |
| 329 if (source_to_decoder_type (filename) == DECODER_FILE) { | 293 |
| 294 if(!is_http_source(filename)) { | |
| 330 if(0 == (f = fopen(filename, "r"))) | 295 if(0 == (f = fopen(filename, "r"))) |
| 331 return; | 296 return; |
| 332 fclose(f); | 297 fclose(f); |
| 333 } | 298 } |
| 334 | 299 |
| 335 if(decoder_ == 0) | 300 if(decoder_ == 0) |
| 336 return; | 301 return; |
| 337 | 302 |
| 338 if(!safe_decoder_init_(filename, &decoder_, &decoder_func_table_)) | 303 if(!safe_decoder_init_(filename, decoder_)) |
| 339 return; | 304 return; |
| 340 | 305 |
| 341 if(file_info_.has_replaygain && flac_cfg.output.replaygain.enable) { | 306 if(stream_data_.has_replaygain && flac_cfg.output.replaygain.enable) { |
| 342 if(flac_cfg.output.resolution.replaygain.bps_out == 8) { | 307 if(flac_cfg.output.resolution.replaygain.bps_out == 8) { |
| 343 file_info_.sample_format = FMT_U8; | 308 stream_data_.sample_format = FMT_U8; |
| 344 file_info_.sample_format_bytes_per_sample = 1; | 309 stream_data_.sample_format_bytes_per_sample = 1; |
| 345 } | 310 } |
| 346 else if(flac_cfg.output.resolution.replaygain.bps_out == 16) { | 311 else if(flac_cfg.output.resolution.replaygain.bps_out == 16) { |
| 347 file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE; | 312 stream_data_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE; |
| 348 file_info_.sample_format_bytes_per_sample = 2; | 313 stream_data_.sample_format_bytes_per_sample = 2; |
| 349 } | 314 } |
| 350 else { | 315 else { |
| 351 /*@@@ 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); */ | 316 /*@@@ 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); */ |
| 352 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", flac_cfg.output.resolution.replaygain.bps_out); | 317 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", flac_cfg.output.resolution.replaygain.bps_out); |
| 353 decoder_func_table_ -> safe_decoder_finish(decoder_); | 318 safe_decoder_finish_(decoder_); |
| 354 return; | 319 return; |
| 355 } | 320 } |
| 356 } | 321 } |
| 357 else { | 322 else { |
| 358 if(file_info_.bits_per_sample == 8) { | 323 if(stream_data_.bits_per_sample == 8) { |
| 359 file_info_.sample_format = FMT_U8; | 324 stream_data_.sample_format = FMT_U8; |
| 360 file_info_.sample_format_bytes_per_sample = 1; | 325 stream_data_.sample_format_bytes_per_sample = 1; |
| 361 } | 326 } |
| 362 else if(file_info_.bits_per_sample == 16 || (file_info_.bits_per_sample == 24 && flac_cfg.output.resolution.normal.dither_24_to_16)) { | 327 else if(stream_data_.bits_per_sample == 16 || (stream_data_.bits_per_sample == 24 && flac_cfg.output.resolution.normal.dither_24_to_16)) { |
| 363 file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE; | 328 stream_data_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE; |
| 364 file_info_.sample_format_bytes_per_sample = 2; | 329 stream_data_.sample_format_bytes_per_sample = 2; |
| 365 } | 330 } |
| 366 else { | 331 else { |
| 367 /*@@@ 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); */ | 332 /*@@@ 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); */ |
| 368 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", file_info_.bits_per_sample); | 333 fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", stream_data_.bits_per_sample); |
| 369 decoder_func_table_ -> safe_decoder_finish(decoder_); | 334 safe_decoder_finish_(decoder_); |
| 370 return; | 335 return; |
| 371 } | 336 } |
| 372 } | 337 } |
| 373 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); | 338 FLAC__replaygain_synthesis__init_dither_context(&stream_data_.dither_context, stream_data_.sample_format_bytes_per_sample * 8, flac_cfg.output.resolution.replaygain.noise_shaping); |
| 374 file_info_.is_playing = true; | 339 stream_data_.is_playing = true; |
| 375 | 340 |
| 376 if(flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) { | 341 if(flac_ip.output->open_audio(stream_data_.sample_format, stream_data_.sample_rate, stream_data_.channels) == 0) { |
| 377 audio_error_ = true; | 342 audio_error_ = true; |
| 378 decoder_func_table_ -> safe_decoder_finish(decoder_); | 343 safe_decoder_finish_(decoder_); |
| 379 return; | 344 return; |
| 380 } | 345 } |
| 381 | 346 |
| 382 file_info_.title = flac_format_song_title(filename); | 347 stream_data_.title = flac_format_song_title(filename); |
| 383 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); | 348 flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample, stream_data_.sample_rate, stream_data_.channels); |
| 384 | 349 |
| 385 file_info_.seek_to_in_sec = -1; | 350 stream_data_.seek_to_in_sec = -1; |
| 386 file_info_.play_thread_open = true; | 351 stream_data_.play_thread_open = true; |
| 387 decode_thread_ = g_thread_create((GThreadFunc)play_loop_, NULL, TRUE, NULL); | 352 decode_thread_ = g_thread_create((GThreadFunc)play_loop_, NULL, TRUE, NULL); |
| 388 } | 353 } |
| 389 | 354 |
| 390 void FLAC_XMMS__stop() | 355 void FLAC_XMMS__stop() |
| 391 { | 356 { |
| 392 if(file_info_.is_playing) { | 357 if(stream_data_.is_playing) { |
| 393 file_info_.is_playing = false; | 358 stream_data_.is_playing = false; |
| 394 if(file_info_.play_thread_open) { | 359 if(stream_data_.play_thread_open) { |
| 395 file_info_.play_thread_open = false; | 360 stream_data_.play_thread_open = false; |
| 396 g_thread_join(decode_thread_); | 361 g_thread_join(decode_thread_); |
| 397 } | 362 } |
| 398 flac_ip.output->close_audio(); | 363 flac_ip.output->close_audio(); |
| 399 decoder_func_table_ -> safe_decoder_finish (decoder_); | 364 safe_decoder_finish_(decoder_); |
| 400 } | 365 } |
| 401 } | 366 } |
| 402 | 367 |
| 403 void FLAC_XMMS__pause(short p) | 368 void FLAC_XMMS__pause(short p) |
| 404 { | 369 { |
| 405 flac_ip.output->pause(p); | 370 flac_ip.output->pause(p); |
| 406 } | 371 } |
| 407 | 372 |
| 408 void FLAC_XMMS__seek(int time) | 373 void FLAC_XMMS__seek(int time) |
| 409 { | 374 { |
| 410 if (decoder_func_table_->seekable) { | 375 if(!stream_data_.is_http_source) { |
| 411 file_info_.seek_to_in_sec = time; | 376 stream_data_.seek_to_in_sec = time; |
| 412 file_info_.eof = false; | 377 stream_data_.eof = false; |
| 413 | 378 |
| 414 while(file_info_.seek_to_in_sec != -1) | 379 while(stream_data_.seek_to_in_sec != -1) |
| 415 xmms_usleep(10000); | 380 xmms_usleep(10000); |
| 416 } | 381 } |
| 417 } | 382 } |
| 418 | 383 |
| 419 int FLAC_XMMS__get_time() | 384 int FLAC_XMMS__get_time() |
| 420 { | 385 { |
| 421 if(audio_error_) | 386 if(audio_error_) |
| 422 return -2; | 387 return -2; |
| 423 if(!file_info_.is_playing || (file_info_.eof && !flac_ip.output->buffer_playing())) | 388 if(!stream_data_.is_playing || (stream_data_.eof && !flac_ip.output->buffer_playing())) |
| 424 return -1; | 389 return -1; |
| 425 else | 390 else |
| 426 return flac_ip.output->output_time(); | 391 return flac_ip.output->output_time(); |
| 427 } | 392 } |
| 428 | 393 |
| 455 if (flac_cfg.stream.proxy_pass) { | 420 if (flac_cfg.stream.proxy_pass) { |
| 456 free(flac_cfg.stream.proxy_pass); | 421 free(flac_cfg.stream.proxy_pass); |
| 457 flac_cfg.stream.proxy_pass = NULL; | 422 flac_cfg.stream.proxy_pass = NULL; |
| 458 } | 423 } |
| 459 | 424 |
| 460 decoder_func_table_ -> safe_decoder_delete(decoder_); | 425 safe_decoder_delete_(decoder_); |
| 461 decoder_ = 0; | 426 decoder_ = 0; |
| 462 } | 427 } |
| 463 | 428 |
| 464 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec) | 429 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec) |
| 465 { | 430 { |
| 469 filename = ""; | 434 filename = ""; |
| 470 | 435 |
| 471 if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) { | 436 if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) { |
| 472 /* @@@ how to report the error? */ | 437 /* @@@ how to report the error? */ |
| 473 if(title) { | 438 if(title) { |
| 474 if (source_to_decoder_type (filename) == DECODER_FILE) { | 439 if (!is_http_source(filename)) { |
| 475 static const char *errtitle = "Invalid FLAC File: "; | 440 static const char *errtitle = "Invalid FLAC File: "; |
| 476 *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1); | 441 *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1); |
| 477 sprintf(*title, "%s\"%s\"", errtitle, filename); | 442 sprintf(*title, "%s\"%s\"", errtitle, filename); |
| 478 } else { | 443 } else { |
| 479 *title = NULL; | 444 *title = NULL; |
| 485 } | 450 } |
| 486 | 451 |
| 487 if(title) { | 452 if(title) { |
| 488 *title = flac_format_song_title(filename); | 453 *title = flac_format_song_title(filename); |
| 489 } | 454 } |
| 490 if(length_in_msec) | 455 if(length_in_msec) { |
| 491 *length_in_msec = (unsigned)((double)streaminfo.data.stream_info.total_samples / (double)streaminfo.data.stream_info.sample_rate * 1000.0 + 0.5); | 456 FLAC__uint64 l = (FLAC__uint64)((double)streaminfo.data.stream_info.total_samples / (double)streaminfo.data.stream_info.sample_rate * 1000.0 + 0.5); |
| 457 if (l > INT_MAX) | |
| 458 l = INT_MAX; | |
| 459 *length_in_msec = (int)l; | |
| 460 } | |
| 492 } | 461 } |
| 493 | 462 |
| 494 /*********************************************************************** | 463 /*********************************************************************** |
| 495 * local routines | 464 * local routines |
| 496 **********************************************************************/ | 465 **********************************************************************/ |
| 500 unsigned written_time_last = 0, bh_index_last_w = 0, bh_index_last_o = BITRATE_HIST_SIZE, blocksize = 1; | 469 unsigned written_time_last = 0, bh_index_last_w = 0, bh_index_last_o = BITRATE_HIST_SIZE, blocksize = 1; |
| 501 FLAC__uint64 decode_position_last = 0, decode_position_frame_last = 0, decode_position_frame = 0; | 470 FLAC__uint64 decode_position_last = 0, decode_position_frame_last = 0, decode_position_frame = 0; |
| 502 | 471 |
| 503 (void)arg; | 472 (void)arg; |
| 504 | 473 |
| 505 while(file_info_.is_playing) { | 474 while(stream_data_.is_playing) { |
| 506 if(!file_info_.eof) { | 475 if(!stream_data_.eof) { |
| 507 while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) { | 476 while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) { |
| 508 unsigned s; | 477 unsigned s; |
| 509 | 478 |
| 510 s = sample_buffer_last_ - sample_buffer_first_; | 479 s = sample_buffer_last_ - sample_buffer_first_; |
| 511 if(decoder_func_table_ -> is_eof(decoder_)) { | 480 if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_END_OF_STREAM) { |
| 512 file_info_.eof = true; | 481 stream_data_.eof = true; |
| 513 break; | 482 break; |
| 514 } | 483 } |
| 515 else if (!decoder_func_table_ -> process_single(decoder_)) { | 484 else if(!FLAC__stream_decoder_process_single(decoder_)) { |
| 516 /*@@@ this should probably be a dialog */ | 485 /*@@@ this should probably be a dialog */ |
| 517 fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n"); | 486 fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n"); |
| 518 file_info_.eof = true; | 487 stream_data_.eof = true; |
| 519 break; | 488 break; |
| 520 } | 489 } |
| 521 blocksize = sample_buffer_last_ - sample_buffer_first_ - s; | 490 blocksize = sample_buffer_last_ - sample_buffer_first_ - s; |
| 522 decode_position_frame_last = decode_position_frame; | 491 decode_position_frame_last = decode_position_frame; |
| 523 if(!decoder_func_table_->seekable || !FLAC__file_decoder_get_decode_position(decoder_, &decode_position_frame)) | 492 if(stream_data_.is_http_source || !FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame)) |
| 524 decode_position_frame = 0; | 493 decode_position_frame = 0; |
| 525 } | 494 } |
| 526 if(sample_buffer_last_ - sample_buffer_first_ > 0) { | 495 if(sample_buffer_last_ - sample_buffer_first_ > 0) { |
| 527 const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE); | 496 const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE); |
| 528 int bytes = n * file_info_.channels * file_info_.sample_format_bytes_per_sample; | 497 int bytes = n * stream_data_.channels * stream_data_.sample_format_bytes_per_sample; |
| 529 FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * file_info_.channels * file_info_.sample_format_bytes_per_sample; | 498 FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * stream_data_.channels * stream_data_.sample_format_bytes_per_sample; |
| 530 unsigned written_time, bh_index_w; | 499 unsigned written_time, bh_index_w; |
| 531 FLAC__uint64 decode_position; | 500 FLAC__uint64 decode_position; |
| 532 | 501 |
| 533 sample_buffer_first_ += n; | 502 sample_buffer_first_ += n; |
| 534 while(flac_ip.output->buffer_free() < (int)bytes && file_info_.is_playing && file_info_.seek_to_in_sec == -1) | 503 while(flac_ip.output->buffer_free() < (int)bytes && stream_data_.is_playing && stream_data_.seek_to_in_sec == -1) |
| 535 xmms_usleep(10000); | 504 xmms_usleep(10000); |
| 536 if(file_info_.is_playing && file_info_.seek_to_in_sec == -1) | 505 if(stream_data_.is_playing && stream_data_.seek_to_in_sec == -1) |
| 537 produce_audio(flac_ip.output->written_time(), file_info_.sample_format, | 506 produce_audio(flac_ip.output->written_time(), stream_data_.sample_format, |
| 538 file_info_.channels, bytes, sample_buffer_start, NULL); | 507 stream_data_.channels, bytes, sample_buffer_start, NULL); |
| 539 | 508 |
| 540 /* compute current bitrate */ | 509 /* compute current bitrate */ |
| 541 | 510 |
| 542 written_time = flac_ip.output->written_time(); | 511 written_time = flac_ip.output->written_time(); |
| 543 bh_index_w = written_time / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; | 512 bh_index_w = written_time / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; |
| 545 bh_index_last_w = bh_index_w; | 514 bh_index_last_w = bh_index_w; |
| 546 decode_position = decode_position_frame - (double)(sample_buffer_last_ - sample_buffer_first_) * (double)(decode_position_frame - decode_position_frame_last) / (double)blocksize; | 515 decode_position = decode_position_frame - (double)(sample_buffer_last_ - sample_buffer_first_) * (double)(decode_position_frame - decode_position_frame_last) / (double)blocksize; |
| 547 bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE - 1) % BITRATE_HIST_SIZE] = | 516 bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE - 1) % BITRATE_HIST_SIZE] = |
| 548 decode_position > decode_position_last && written_time > written_time_last ? | 517 decode_position > decode_position_last && written_time > written_time_last ? |
| 549 8000 * (decode_position - decode_position_last) / (written_time - written_time_last) : | 518 8000 * (decode_position - decode_position_last) / (written_time - written_time_last) : |
| 550 file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample; | 519 stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample; |
| 551 decode_position_last = decode_position; | 520 decode_position_last = decode_position; |
| 552 written_time_last = written_time; | 521 written_time_last = written_time; |
| 553 } | 522 } |
| 554 } | 523 } |
| 555 else { | 524 else { |
| 556 file_info_.eof = true; | 525 stream_data_.eof = true; |
| 557 xmms_usleep(10000); | 526 xmms_usleep(10000); |
| 558 } | 527 } |
| 559 } | 528 } |
| 560 else | 529 else |
| 561 xmms_usleep(10000); | 530 xmms_usleep(10000); |
| 562 if(decoder_func_table_->seekable && file_info_.seek_to_in_sec != -1) { | 531 if(!stream_data_.is_http_source && stream_data_.seek_to_in_sec != -1) { |
| 563 const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec; | 532 const double distance = (double)stream_data_.seek_to_in_sec * 1000.0 / (double)stream_data_.length_in_msec; |
| 564 unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); | 533 FLAC__uint64 target_sample = (FLAC__uint64)(distance * (double)stream_data_.total_samples); |
| 565 if(FLAC__file_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) { | 534 if(stream_data_.total_samples > 0 && target_sample >= stream_data_.total_samples) |
| 566 flac_ip.output->flush(file_info_.seek_to_in_sec * 1000); | 535 target_sample = stream_data_.total_samples - 1; |
| 536 if(FLAC__stream_decoder_seek_absolute(decoder_, target_sample)) { | |
| 537 flac_ip.output->flush(stream_data_.seek_to_in_sec * 1000); | |
| 567 bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; | 538 bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; |
| 568 if(!FLAC__file_decoder_get_decode_position(decoder_, &decode_position_frame)) | 539 if(!FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame)) |
| 569 decode_position_frame = 0; | 540 decode_position_frame = 0; |
| 570 file_info_.seek_to_in_sec = -1; | 541 stream_data_.eof = false; |
| 571 file_info_.eof = false; | |
| 572 sample_buffer_first_ = sample_buffer_last_ = 0; | 542 sample_buffer_first_ = sample_buffer_last_ = 0; |
| 573 } | 543 } |
| 544 else if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_SEEK_ERROR) { | |
| 545 /*@@@ this should probably be a dialog */ | |
| 546 fprintf(stderr, "libxmms-flac: SEEK ERROR\n"); | |
| 547 FLAC__stream_decoder_flush(decoder_); | |
| 548 stream_data_.eof = false; | |
| 549 sample_buffer_first_ = sample_buffer_last_ = 0; | |
| 550 } | |
| 551 stream_data_.seek_to_in_sec = -1; | |
| 574 } | 552 } |
| 575 else { | 553 else { |
| 576 /* display the right bitrate from history */ | 554 /* display the right bitrate from history */ |
| 577 unsigned bh_index_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; | 555 unsigned bh_index_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE; |
| 578 if(bh_index_o != bh_index_last_o && bh_index_o != bh_index_last_w && bh_index_o != (bh_index_last_w + 1) % BITRATE_HIST_SIZE) { | 556 if(bh_index_o != bh_index_last_o && bh_index_o != bh_index_last_w && bh_index_o != (bh_index_last_w + 1) % BITRATE_HIST_SIZE) { |
| 579 bh_index_last_o = bh_index_o; | 557 bh_index_last_o = bh_index_o; |
| 580 flac_ip.set_info(file_info_.title, file_info_.length_in_msec, bitrate_history_[bh_index_o], file_info_.sample_rate, file_info_.channels); | 558 flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, bitrate_history_[bh_index_o], stream_data_.sample_rate, stream_data_.channels); |
| 581 } | 559 } |
| 582 } | 560 } |
| 583 } | 561 } |
| 584 | 562 |
| 585 decoder_func_table_ -> safe_decoder_finish(decoder_); | 563 safe_decoder_finish_(decoder_); |
| 586 | 564 |
| 587 /* are these two calls necessary? */ | 565 /* are these two calls necessary? */ |
| 588 flac_ip.output->buffer_free(); | 566 flac_ip.output->buffer_free(); |
| 589 flac_ip.output->buffer_free(); | 567 flac_ip.output->buffer_free(); |
| 590 | 568 |
| 591 g_free(file_info_.title); | 569 g_free(stream_data_.title); |
| 592 | 570 |
| 593 g_thread_exit(NULL); | 571 g_thread_exit(NULL); |
| 594 return 0; /* to silence the compiler warning about not returning a value */ | 572 return 0; /* to silence the compiler warning about not returning a value */ |
| 595 } | 573 } |
| 596 | 574 |
| 597 /*********** File decoder functions */ | 575 FLAC__bool safe_decoder_init_(const char *filename, FLAC__StreamDecoder *decoder) |
| 598 | 576 { |
| 599 static FLAC__bool file_decoder_init (void *decoder) | 577 if(decoder == 0) |
| 600 { | 578 return false; |
| 601 return FLAC__file_decoder_init( (FLAC__FileDecoder*) decoder) == FLAC__FILE_DECODER_OK; | 579 |
| 602 } | 580 safe_decoder_finish_(decoder); |
| 603 | 581 |
| 604 static void file_decoder_safe_decoder_finish_(void *decoder) | 582 FLAC__stream_decoder_set_md5_checking(decoder, false); |
| 605 { | 583 FLAC__stream_decoder_set_metadata_ignore_all(decoder); |
| 606 if(decoder && FLAC__file_decoder_get_state((FLAC__FileDecoder *) decoder) != FLAC__FILE_DECODER_UNINITIALIZED) | 584 FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); |
| 607 FLAC__file_decoder_finish((FLAC__FileDecoder *) decoder); | 585 FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); |
| 608 } | 586 if(stream_data_.is_http_source) { |
| 609 | 587 flac_http_open(filename, 0); |
| 610 static void file_decoder_safe_decoder_delete_(void *decoder) | 588 if(FLAC__stream_decoder_init_stream(decoder, http_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, write_callback_, metadata_callback_, error_callback_, /*client_data=*/&stream_data_) != FLAC__STREAM_DECODER_INIT_STATUS_OK) |
| 589 return false; | |
| 590 } | |
| 591 else { | |
| 592 if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, /*client_data=*/&stream_data_) != FLAC__STREAM_DECODER_INIT_STATUS_OK) | |
| 593 return false; | |
| 594 } | |
| 595 | |
| 596 if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) | |
| 597 return false; | |
| 598 | |
| 599 return true; | |
| 600 } | |
| 601 | |
| 602 void safe_decoder_finish_(FLAC__StreamDecoder *decoder) | |
| 603 { | |
| 604 if(decoder && FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) | |
| 605 FLAC__stream_decoder_finish(decoder); | |
| 606 if(stream_data_.is_http_source) | |
| 607 flac_http_close(); | |
| 608 } | |
| 609 | |
| 610 void safe_decoder_delete_(FLAC__StreamDecoder *decoder) | |
| 611 { | 611 { |
| 612 if(decoder) { | 612 if(decoder) { |
| 613 file_decoder_safe_decoder_finish_(decoder); | 613 safe_decoder_finish_(decoder); |
| 614 FLAC__file_decoder_delete( (FLAC__FileDecoder *) decoder); | 614 FLAC__stream_decoder_delete(decoder); |
| 615 } | 615 } |
| 616 } | 616 } |
| 617 | 617 |
| 618 static FLAC__bool file_decoder_is_eof(void *decoder) | 618 FLAC__StreamDecoderReadStatus http_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) |
| 619 { | 619 { |
| 620 return FLAC__file_decoder_get_state((FLAC__FileDecoder *) decoder) == FLAC__FILE_DECODER_END_OF_FILE; | 620 (void)decoder; |
| 621 } | 621 (void)client_data; |
| 622 | 622 *bytes = flac_http_read(buffer, *bytes); |
| 623 static const decoder_funcs_t FILE_DECODER_FUNCTIONS = { | |
| 624 true, | |
| 625 (void* (*) (void)) FLAC__file_decoder_new, | |
| 626 (FLAC__bool (*) (void *, FLAC__bool)) FLAC__file_decoder_set_md5_checking, | |
| 627 (FLAC__bool (*) (void *, const char*)) FLAC__file_decoder_set_filename, | |
| 628 (FLAC__bool (*) (void *)) FLAC__file_decoder_set_metadata_ignore_all, | |
| 629 (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__file_decoder_set_metadata_respond, | |
| 630 (FLAC__bool (*) (void *, WriteCallback)) FLAC__file_decoder_set_write_callback, | |
| 631 (FLAC__bool (*) (void *, MetadataCallback)) FLAC__file_decoder_set_metadata_callback, | |
| 632 (FLAC__bool (*) (void *, ErrorCallback)) FLAC__file_decoder_set_error_callback, | |
| 633 (FLAC__bool (*) (void *, void *)) FLAC__file_decoder_set_client_data, | |
| 634 (FLAC__bool (*) (void *)) file_decoder_init, | |
| 635 (void (*) (void *)) file_decoder_safe_decoder_finish_, | |
| 636 (void (*) (void *)) file_decoder_safe_decoder_delete_, | |
| 637 (FLAC__bool (*) (void *)) FLAC__file_decoder_process_until_end_of_metadata, | |
| 638 (FLAC__bool (*) (void *)) FLAC__file_decoder_process_single, | |
| 639 file_decoder_is_eof | |
| 640 }; | |
| 641 | |
| 642 /*********** HTTP decoder functions */ | |
| 643 | |
| 644 static gchar *url_; | |
| 645 | |
| 646 static FLAC__bool http_decoder_set_md5_checking (void *decoder, FLAC__bool value) | |
| 647 { | |
| 648 (void) value; | |
| 649 // operation unsupported | |
| 650 return FLAC__stream_decoder_get_state ((const FLAC__StreamDecoder *) decoder) == | |
| 651 FLAC__STREAM_DECODER_UNINITIALIZED; | |
| 652 } | |
| 653 | |
| 654 static FLAC__bool http_decoder_set_url (void *decoder, const char* url) | |
| 655 { | |
| 656 (void) decoder; | |
| 657 url_ = g_strdup (url); | |
| 658 return true; | |
| 659 } | |
| 660 | |
| 661 static FLAC__StreamDecoderReadStatus http_decoder_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) | |
| 662 { | |
| 663 (void) decoder; | |
| 664 (void) client_data; | |
| 665 *bytes = flac_http_read (buffer, *bytes); | |
| 666 return *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; | 623 return *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; |
| 667 } | 624 } |
| 668 | 625 |
| 669 static FLAC__bool http_decoder_init (void *decoder) | 626 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) |
| 670 { | 627 { |
| 671 flac_http_open (url_, 0); | 628 stream_data_struct *stream_data = (stream_data_struct *)client_data; |
| 672 g_free (url_); | 629 const unsigned channels = stream_data->channels, wide_samples = frame->header.blocksize; |
| 673 FLAC__stream_decoder_set_read_callback (decoder, http_decoder_read_callback); | 630 const unsigned bits_per_sample = stream_data->bits_per_sample; |
| 674 return FLAC__stream_decoder_init( (FLAC__StreamDecoder*) decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; | |
| 675 } | |
| 676 | |
| 677 static void http_decoder_safe_decoder_finish_(void *decoder) | |
| 678 { | |
| 679 if(decoder && FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) { | |
| 680 FLAC__stream_decoder_finish((FLAC__StreamDecoder *) decoder); | |
| 681 flac_http_close(); | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 static void http_decoder_safe_decoder_delete_(void *decoder) | |
| 686 { | |
| 687 if(decoder) { | |
| 688 http_decoder_safe_decoder_finish_(decoder); | |
| 689 FLAC__stream_decoder_delete( (FLAC__StreamDecoder *) decoder); | |
| 690 } | |
| 691 } | |
| 692 | |
| 693 static FLAC__bool http_decoder_is_eof(void *decoder) | |
| 694 { | |
| 695 return FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) == FLAC__STREAM_DECODER_END_OF_STREAM; | |
| 696 } | |
| 697 | |
| 698 static const decoder_funcs_t HTTP_DECODER_FUNCTIONS = { | |
| 699 false, | |
| 700 (void* (*) (void)) FLAC__stream_decoder_new, | |
| 701 http_decoder_set_md5_checking, | |
| 702 (FLAC__bool (*) (void *, const char*)) http_decoder_set_url, | |
| 703 (FLAC__bool (*) (void *)) FLAC__stream_decoder_set_metadata_ignore_all, | |
| 704 (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__stream_decoder_set_metadata_respond, | |
| 705 (FLAC__bool (*) (void *, WriteCallback)) FLAC__stream_decoder_set_write_callback, | |
| 706 (FLAC__bool (*) (void *, MetadataCallback)) FLAC__stream_decoder_set_metadata_callback, | |
| 707 (FLAC__bool (*) (void *, ErrorCallback)) FLAC__stream_decoder_set_error_callback, | |
| 708 (FLAC__bool (*) (void *, void *)) FLAC__stream_decoder_set_client_data, | |
| 709 (FLAC__bool (*) (void *)) http_decoder_init, | |
| 710 (void (*) (void *)) http_decoder_safe_decoder_finish_, | |
| 711 (void (*) (void *)) http_decoder_safe_decoder_delete_, | |
| 712 (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_until_end_of_metadata, | |
| 713 (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_single, | |
| 714 http_decoder_is_eof | |
| 715 }; | |
| 716 | |
| 717 static decoder_funcs_t const *decoder_func_table_; | |
| 718 | |
| 719 static void init_decoder_func_tables() | |
| 720 { | |
| 721 DECODER_FUNCS [DECODER_FILE] = & FILE_DECODER_FUNCTIONS; | |
| 722 DECODER_FUNCS [DECODER_HTTP] = & HTTP_DECODER_FUNCTIONS; | |
| 723 } | |
| 724 | |
| 725 static decoder_t source_to_decoder_type (const char *source) | |
| 726 { | |
| 727 return strncasecmp(source, "http://", 7) ? DECODER_FILE : DECODER_HTTP; | |
| 728 } | |
| 729 | |
| 730 static void change_decoder_if_needed (decoder_t new_decoder_type, void **decoderp, decoder_funcs_t const ** fntabp) | |
| 731 { | |
| 732 const decoder_funcs_t *new_fn_table = DECODER_FUNCS [new_decoder_type]; | |
| 733 if (*fntabp != new_fn_table) { | |
| 734 (*fntabp)->safe_decoder_delete(*decoderp); | |
| 735 *fntabp = new_fn_table; | |
| 736 *decoderp = new_fn_table -> new_decoder(); | |
| 737 } | |
| 738 } | |
| 739 | |
| 740 FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fntabp) | |
| 741 { | |
| 742 if(decoderp == 0 || *decoderp == 0) | |
| 743 return false; | |
| 744 | |
| 745 (*fntabp)->safe_decoder_finish(*decoderp); | |
| 746 | |
| 747 change_decoder_if_needed(source_to_decoder_type(filename), decoderp, fntabp); | |
| 748 | |
| 749 { | |
| 750 decoder_funcs_t const *fntab = *fntabp; | |
| 751 void *decoder = *decoderp; | |
| 752 | |
| 753 decoder = *decoderp; | |
| 754 fntab = *fntabp; | |
| 755 | |
| 756 fntab -> set_md5_checking(decoder, false); | |
| 757 fntab -> set_source(decoder, filename); | |
| 758 fntab -> set_metadata_ignore_all(decoder); | |
| 759 fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); | |
| 760 fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); | |
| 761 fntab -> set_write_callback(decoder, write_callback_); | |
| 762 fntab -> set_metadata_callback(decoder, metadata_callback_); | |
| 763 fntab -> set_error_callback(decoder, error_callback_); | |
| 764 fntab -> set_client_data(decoder, &file_info_); | |
| 765 if(!fntab -> decoder_init(decoder)) | |
| 766 return false; | |
| 767 | |
| 768 if(!fntab -> process_until_end_of_metadata(decoder)) | |
| 769 return false; | |
| 770 } | |
| 771 | |
| 772 return true; | |
| 773 } | |
| 774 | |
| 775 FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) | |
| 776 { | |
| 777 file_info_struct *file_info = (file_info_struct *)client_data; | |
| 778 const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize; | |
| 779 const unsigned bits_per_sample = file_info->bits_per_sample; | |
| 780 FLAC__byte *sample_buffer_start; | 631 FLAC__byte *sample_buffer_start; |
| 781 | 632 |
| 782 (void)decoder; | 633 (void)decoder; |
| 783 | 634 |
| 784 if(file_info->abort_flag) | 635 if(stream_data->abort_flag) |
| 785 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; | 636 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; |
| 786 | 637 |
| 787 if((sample_buffer_last_ + wide_samples) > (SAMPLE_BUFFER_SIZE / (channels * file_info->sample_format_bytes_per_sample))) { | 638 if((sample_buffer_last_ + wide_samples) > (SAMPLE_BUFFER_SIZE / (channels * stream_data->sample_format_bytes_per_sample))) { |
| 788 memmove(sample_buffer_, sample_buffer_ + sample_buffer_first_ * channels * file_info->sample_format_bytes_per_sample, (sample_buffer_last_ - sample_buffer_first_) * channels * file_info->sample_format_bytes_per_sample); | 639 memmove(sample_buffer_, sample_buffer_ + sample_buffer_first_ * channels * stream_data->sample_format_bytes_per_sample, (sample_buffer_last_ - sample_buffer_first_) * channels * stream_data->sample_format_bytes_per_sample); |
| 789 sample_buffer_last_ -= sample_buffer_first_; | 640 sample_buffer_last_ -= sample_buffer_first_; |
| 790 sample_buffer_first_ = 0; | 641 sample_buffer_first_ = 0; |
| 791 } | 642 } |
| 792 sample_buffer_start = sample_buffer_ + sample_buffer_last_ * channels * file_info->sample_format_bytes_per_sample; | 643 sample_buffer_start = sample_buffer_ + sample_buffer_last_ * channels * stream_data->sample_format_bytes_per_sample; |
| 793 if(file_info->has_replaygain && flac_cfg.output.replaygain.enable) { | 644 if(stream_data->has_replaygain && flac_cfg.output.replaygain.enable) { |
| 794 FLAC__replaygain_synthesis__apply_gain( | 645 FLAC__replaygain_synthesis__apply_gain( |
| 795 sample_buffer_start, | 646 sample_buffer_start, |
| 796 !is_big_endian_host_, | 647 !is_big_endian_host_, |
| 797 file_info->sample_format_bytes_per_sample == 1, /* unsigned_data_out */ | 648 stream_data->sample_format_bytes_per_sample == 1, /* unsigned_data_out */ |
| 798 buffer, | 649 buffer, |
| 799 wide_samples, | 650 wide_samples, |
| 800 channels, | 651 channels, |
| 801 bits_per_sample, | 652 bits_per_sample, |
| 802 file_info->sample_format_bytes_per_sample * 8, | 653 stream_data->sample_format_bytes_per_sample * 8, |
| 803 file_info->replay_scale, | 654 stream_data->replay_scale, |
| 804 flac_cfg.output.replaygain.hard_limit, | 655 flac_cfg.output.replaygain.hard_limit, |
| 805 flac_cfg.output.resolution.replaygain.dither, | 656 flac_cfg.output.resolution.replaygain.dither, |
| 806 &file_info->dither_context | 657 &stream_data->dither_context |
| 807 ); | 658 ); |
| 808 } | 659 } |
| 809 else if(is_big_endian_host_) { | 660 else if(is_big_endian_host_) { |
| 810 FLAC__plugin_common__pack_pcm_signed_big_endian( | 661 FLAC__plugin_common__pack_pcm_signed_big_endian( |
| 811 sample_buffer_start, | 662 sample_buffer_start, |
| 812 buffer, | 663 buffer, |
| 813 wide_samples, | 664 wide_samples, |
| 814 channels, | 665 channels, |
| 815 bits_per_sample, | 666 bits_per_sample, |
| 816 file_info->sample_format_bytes_per_sample * 8 | 667 stream_data->sample_format_bytes_per_sample * 8 |
| 817 ); | 668 ); |
| 818 } | 669 } |
| 819 else { | 670 else { |
| 820 FLAC__plugin_common__pack_pcm_signed_little_endian( | 671 FLAC__plugin_common__pack_pcm_signed_little_endian( |
| 821 sample_buffer_start, | 672 sample_buffer_start, |
| 822 buffer, | 673 buffer, |
| 823 wide_samples, | 674 wide_samples, |
| 824 channels, | 675 channels, |
| 825 bits_per_sample, | 676 bits_per_sample, |
| 826 file_info->sample_format_bytes_per_sample * 8 | 677 stream_data->sample_format_bytes_per_sample * 8 |
| 827 ); | 678 ); |
| 828 } | 679 } |
| 829 | 680 |
| 830 sample_buffer_last_ += wide_samples; | 681 sample_buffer_last_ += wide_samples; |
| 831 | 682 |
| 832 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; | 683 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; |
| 833 } | 684 } |
| 834 | 685 |
| 835 void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data) | 686 void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) |
| 836 { | 687 { |
| 837 file_info_struct *file_info = (file_info_struct *)client_data; | 688 stream_data_struct *stream_data = (stream_data_struct *)client_data; |
| 838 (void)decoder; | 689 (void)decoder; |
| 839 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { | 690 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { |
| 840 FLAC__ASSERT(metadata->data.stream_info.total_samples < FLAC__U64L(0x100000000)); /* this plugin can only handle < 4 gigasamples */ | 691 stream_data->total_samples = metadata->data.stream_info.total_samples; |
| 841 file_info->total_samples = (unsigned)(metadata->data.stream_info.total_samples&0xffffffff); | 692 stream_data->bits_per_sample = metadata->data.stream_info.bits_per_sample; |
| 842 file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample; | 693 stream_data->channels = metadata->data.stream_info.channels; |
| 843 file_info->channels = metadata->data.stream_info.channels; | 694 stream_data->sample_rate = metadata->data.stream_info.sample_rate; |
| 844 file_info->sample_rate = metadata->data.stream_info.sample_rate; | 695 { |
| 845 file_info->length_in_msec = (unsigned)((double)file_info->total_samples / (double)file_info->sample_rate * 1000.0 + 0.5); | 696 FLAC__uint64 l = (FLAC__uint64)((double)stream_data->total_samples / (double)stream_data->sample_rate * 1000.0 + 0.5); |
| 697 if (l > INT_MAX) | |
| 698 l = INT_MAX; | |
| 699 stream_data->length_in_msec = (int)l; | |
| 700 } | |
| 846 } | 701 } |
| 847 else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { | 702 else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { |
| 848 double gain, peak; | 703 double reference, gain, peak; |
| 849 if(grabbag__replaygain_load_from_vorbiscomment(metadata, flac_cfg.output.replaygain.album_mode, &gain, &peak)) { | 704 if(grabbag__replaygain_load_from_vorbiscomment(metadata, flac_cfg.output.replaygain.album_mode, /*strict=*/false, &reference, &gain, &peak)) { |
| 850 file_info->has_replaygain = true; | 705 stream_data->has_replaygain = true; |
| 851 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); | 706 stream_data->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit); |
| 852 } | 707 } |
| 853 } | 708 } |
| 854 } | 709 } |
| 855 | 710 |
| 856 void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) | 711 void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) |
| 857 { | 712 { |
| 858 file_info_struct *file_info = (file_info_struct *)client_data; | 713 stream_data_struct *stream_data = (stream_data_struct *)client_data; |
| 859 (void)decoder; | 714 (void)decoder; |
| 860 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) | 715 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) |
| 861 file_info->abort_flag = true; | 716 stream_data->abort_flag = true; |
| 862 } | 717 } |
