Mercurial > audlegacy-plugins
comparison src/madplug/plugin.c @ 2341:59addab003d7
- reworked replaygain to use individual pre-gain for the files with RG info and the rest.
- default pre-gain have been changed to +6dB for with RG, +0dB for the rest.
- new clipping prevention feature using track peak information has been implemented.
- reworked preferences dialog. widgets have been categorized by function and all changes will take effect immediately. and also, cancel button can reverts all changes have been done in the current session.
- some keys in preferences have been changed.
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Thu, 31 Jan 2008 15:22:15 +0900 |
parents | 47d7a45b26a0 |
children | fd8271f07747 |
comparison
equal
deleted
inserted
replaced
2340:47d7a45b26a0 | 2341:59addab003d7 |
---|---|
38 #include "tuple.h" | 38 #include "tuple.h" |
39 | 39 |
40 /* | 40 /* |
41 * Global variables | 41 * Global variables |
42 */ | 42 */ |
43 struct audmad_config_t audmad_config; /**< global configuration */ | 43 audmad_config_t *audmad_config; /**< global configuration */ |
44 GMutex *mad_mutex; | 44 GMutex *mad_mutex; |
45 GMutex *pb_mutex; | 45 GMutex *pb_mutex; |
46 GCond *mad_cond; | 46 GCond *mad_cond; |
47 | 47 |
48 /* | 48 /* |
77 * | 77 * |
78 * Return pointer within filename to its extenstion, or NULL if | 78 * Return pointer within filename to its extenstion, or NULL if |
79 * filename has no extension. | 79 * filename has no extension. |
80 * | 80 * |
81 */ | 81 */ |
82 static gchar *extname(const char *filename) | 82 static gchar * |
83 extname(const char *filename) | |
83 { | 84 { |
84 gchar *ext = strrchr(filename, '.'); | 85 gchar *ext = strrchr(filename, '.'); |
85 | 86 |
86 if (ext != NULL) | 87 if (ext != NULL) |
87 ++ext; | 88 ++ext; |
88 | 89 |
89 return ext; | 90 return ext; |
90 } | 91 } |
91 | 92 |
92 | 93 |
93 void audmad_config_compute(struct audmad_config_t *config) | 94 void |
95 audmad_config_compute(audmad_config_t *config) | |
94 { | 96 { |
95 /* set some config parameters by parsing text fields | 97 /* set some config parameters by parsing text fields |
96 (RG default gain, etc..) | 98 (RG default gain, etc..) |
97 */ | 99 */ |
98 const gchar *text; | 100 const gchar *text; |
99 gdouble x; | 101 gdouble x; |
100 | 102 |
101 text = config->pregain_db; | 103 text = config->replaygain.preamp0_db; |
102 if ( text != NULL ) | 104 if ( text != NULL ) |
103 x = g_strtod(text, NULL); | 105 x = g_strtod(text, NULL); |
104 else | 106 else |
105 x = 0; | 107 x = 0; |
106 config->pregain_scale = (x != 0) ? pow(10.0, x / 20) : 1; | 108 config->replaygain.preamp0_scale = (x != 0) ? pow(10.0, x / 20) : 1; |
107 AUDDBG("pregain=[%s] -> %g -> %g\n", text, x, config->pregain_scale); | 109 AUDDBG("RG.preamp0=[%s] -> %g -> %g\n", text, x, config->preamp0_scale); |
108 text = config->replaygain.default_db; | 110 |
111 text = config->replaygain.preamp1_db; | |
109 if ( text != NULL ) | 112 if ( text != NULL ) |
110 x = g_strtod(text, NULL); | 113 x = g_strtod(text, NULL); |
111 else | 114 else |
112 x = 0; | 115 x = 0; |
113 config->replaygain.default_scale = (x != 0) ? pow(10.0, x / 20) : 1; | 116 config->replaygain.preamp1_scale = (x != 0) ? pow(10.0, x / 20) : 1; |
114 AUDDBG("RG.default=[%s] -> %g -> %g\n", text, x, | 117 AUDDBG("RG.preamp1=[%s] -> %g -> %g\n", text, x, |
115 config->replaygain.default_scale); | 118 config->replaygain.preamp1_scale); |
116 } | 119 |
117 | 120 text = config->replaygain.preamp2_db; |
118 static void audmad_init() | 121 if ( text != NULL ) |
122 x = g_strtod(text, NULL); | |
123 else | |
124 x = 0; | |
125 config->replaygain.preamp2_scale = (x != 0) ? pow(10.0, x / 20) : 1; | |
126 AUDDBG("RG.preamp2=[%s] -> %g -> %g\n", text, x, | |
127 config->replaygain.preamp2_scale); | |
128 } | |
129 | |
130 static void | |
131 audmad_init() | |
119 { | 132 { |
120 ConfigDb *db = NULL; | 133 ConfigDb *db = NULL; |
121 | 134 |
122 audmad_config.fast_play_time_calc = TRUE; | 135 audmad_config = g_malloc0(sizeof(audmad_config_t)); |
123 audmad_config.use_xing = TRUE; | 136 |
124 audmad_config.dither = TRUE; | 137 audmad_config->dither = TRUE; |
125 audmad_config.sjis = FALSE; | 138 audmad_config->force_reopen_audio = FALSE; |
126 audmad_config.hard_limit = FALSE; | 139 audmad_config->fast_play_time_calc = TRUE; |
127 audmad_config.replaygain.enable = TRUE; | 140 audmad_config->use_xing = TRUE; |
128 audmad_config.replaygain.track_mode = FALSE; | 141 audmad_config->sjis = FALSE; |
129 audmad_config.title_override = FALSE; | 142 audmad_config->show_avg_vbr_bitrate = TRUE; |
130 audmad_config.show_avg_vbr_bitrate = TRUE; | 143 audmad_config->replaygain.enable = TRUE; |
131 audmad_config.force_reopen_audio = FALSE; | 144 audmad_config->replaygain.track_mode = FALSE; |
145 audmad_config->replaygain.anti_clip = FALSE; | |
146 audmad_config->replaygain.hard_limit = FALSE; | |
147 audmad_config->title_override = FALSE; | |
148 | |
132 | 149 |
133 db = aud_cfg_db_open(); | 150 db = aud_cfg_db_open(); |
134 if (db) { | 151 if (db) { |
152 //audio | |
153 aud_cfg_db_get_bool(db, "MAD", "dither", &audmad_config->dither); | |
154 aud_cfg_db_get_bool(db, "MAD", "force_reopen_audio", | |
155 &audmad_config->force_reopen_audio); | |
156 | |
157 //metadata | |
135 aud_cfg_db_get_bool(db, "MAD", "fast_play_time_calc", | 158 aud_cfg_db_get_bool(db, "MAD", "fast_play_time_calc", |
136 &audmad_config.fast_play_time_calc); | 159 &audmad_config->fast_play_time_calc); |
137 aud_cfg_db_get_bool(db, "MAD", "use_xing", | 160 aud_cfg_db_get_bool(db, "MAD", "use_xing", |
138 &audmad_config.use_xing); | 161 &audmad_config->use_xing); |
139 aud_cfg_db_get_bool(db, "MAD", "dither", &audmad_config.dither); | 162 aud_cfg_db_get_bool(db, "MAD", "sjis", &audmad_config->sjis); |
140 aud_cfg_db_get_bool(db, "MAD", "sjis", &audmad_config.sjis); | 163 |
141 aud_cfg_db_get_bool(db, "MAD", "hard_limit", | 164 //misc |
142 &audmad_config.hard_limit); | 165 aud_cfg_db_get_bool(db, "MAD", "show_avg_vbr_bitrate", |
143 aud_cfg_db_get_string(db, "MAD", "pregain_db", | 166 &audmad_config->show_avg_vbr_bitrate); |
144 &audmad_config.pregain_db); | 167 |
168 //gain control | |
169 aud_cfg_db_get_string(db, "MAD", "RG.preamp0_db", | |
170 &audmad_config->replaygain.preamp0_db); | |
145 aud_cfg_db_get_bool(db, "MAD", "RG.enable", | 171 aud_cfg_db_get_bool(db, "MAD", "RG.enable", |
146 &audmad_config.replaygain.enable); | 172 &audmad_config->replaygain.enable); |
147 aud_cfg_db_get_bool(db, "MAD", "RG.track_mode", | 173 aud_cfg_db_get_bool(db, "MAD", "RG.track_mode", |
148 &audmad_config.replaygain.track_mode); | 174 &audmad_config->replaygain.track_mode); |
149 aud_cfg_db_get_string(db, "MAD", "RG.default_db", | 175 aud_cfg_db_get_string(db, "MAD", "RG.preamp1_db", |
150 &audmad_config.replaygain.default_db); | 176 &audmad_config->replaygain.preamp1_db); |
177 aud_cfg_db_get_string(db, "MAD", "RG.preamp2_db", | |
178 &audmad_config->replaygain.preamp2_db); | |
179 aud_cfg_db_get_bool(db, "MAD", "RG.anti_clip", | |
180 &audmad_config->replaygain.anti_clip); | |
181 aud_cfg_db_get_bool(db, "MAD", "RG.hard_limit", | |
182 &audmad_config->replaygain.hard_limit); | |
183 | |
184 //text | |
151 aud_cfg_db_get_bool(db, "MAD", "title_override", | 185 aud_cfg_db_get_bool(db, "MAD", "title_override", |
152 &audmad_config.title_override); | 186 &audmad_config->title_override); |
153 aud_cfg_db_get_string(db, "MAD", "id3_format", | 187 aud_cfg_db_get_string(db, "MAD", "id3_format", |
154 &audmad_config.id3_format); | 188 &audmad_config->id3_format); |
155 aud_cfg_db_get_bool(db, "MAD", "show_avg_vbr_bitrate", | |
156 &audmad_config.show_avg_vbr_bitrate); | |
157 aud_cfg_db_get_bool(db, "MAD", "force_reopen_audio", | |
158 &audmad_config.force_reopen_audio); | |
159 | 189 |
160 aud_cfg_db_close(db); | 190 aud_cfg_db_close(db); |
161 } | 191 } |
162 | 192 |
163 mad_mutex = g_mutex_new(); | 193 mad_mutex = g_mutex_new(); |
164 pb_mutex = g_mutex_new(); | 194 pb_mutex = g_mutex_new(); |
165 mad_cond = g_cond_new(); | 195 mad_cond = g_cond_new(); |
166 audmad_config_compute(&audmad_config); | 196 audmad_config_compute(audmad_config); |
167 | 197 |
168 if (!audmad_config.pregain_db) | 198 if (!audmad_config->replaygain.preamp0_db) |
169 audmad_config.pregain_db = g_strdup("+0.00"); | 199 audmad_config->replaygain.preamp0_db = g_strdup("+0.00"); |
170 | 200 |
171 if (!audmad_config.replaygain.default_db) | 201 if (!audmad_config->replaygain.preamp1_db) |
172 audmad_config.replaygain.default_db = g_strdup("-9.00"); | 202 audmad_config->replaygain.preamp1_db = g_strdup("+6.00"); |
173 | 203 if (!audmad_config->replaygain.preamp2_db) |
174 if (!audmad_config.id3_format) | 204 audmad_config->replaygain.preamp2_db = g_strdup("+0.00"); |
175 audmad_config.id3_format = g_strdup(""); | 205 |
206 if (!audmad_config->id3_format) | |
207 audmad_config->id3_format = g_strdup("(none)"); | |
176 | 208 |
177 init_gen_rand(4357); | 209 init_gen_rand(4357); |
178 | 210 |
179 aud_mime_set_plugin("audio/mpeg", mad_plugin); | 211 aud_mime_set_plugin("audio/mpeg", mad_plugin); |
180 } | 212 } |
181 | 213 |
182 static void audmad_cleanup() | 214 static void |
183 { | 215 audmad_cleanup() |
184 g_free(audmad_config.pregain_db); | 216 { |
185 g_free(audmad_config.replaygain.default_db); | 217 g_free(audmad_config->replaygain.preamp0_db); |
186 g_free(audmad_config.id3_format); | 218 g_free(audmad_config->replaygain.preamp1_db); |
187 | 219 g_free(audmad_config->replaygain.preamp2_db); |
188 audmad_config.pregain_db = NULL; | 220 g_free(audmad_config->id3_format); |
189 audmad_config.replaygain.default_db = NULL; | 221 g_free(audmad_config); |
190 audmad_config.id3_format = NULL; | 222 |
191 | |
192 g_cond_free(mad_cond); | 223 g_cond_free(mad_cond); |
193 g_mutex_free(mad_mutex); | 224 g_mutex_free(mad_mutex); |
194 g_mutex_free(pb_mutex); | 225 g_mutex_free(pb_mutex); |
195 } | 226 } |
196 | 227 |
197 static gboolean mp3_head_check(guint32 head, gint *frameSize) | 228 static gboolean |
229 mp3_head_check(guint32 head, gint *frameSize) | |
198 { | 230 { |
199 gint version, layer, bitIndex, bitRate, sampleIndex, sampleRate, padding; | 231 gint version, layer, bitIndex, bitRate, sampleIndex, sampleRate, padding; |
200 | 232 |
201 /* http://www.mp3-tech.org/programmer/frame_header.html | 233 /* http://www.mp3-tech.org/programmer/frame_header.html |
202 * Bits 21-31 must be set (frame sync) | 234 * Bits 21-31 must be set (frame sync) |
280 return FALSE; | 312 return FALSE; |
281 | 313 |
282 return TRUE; | 314 return TRUE; |
283 } | 315 } |
284 | 316 |
285 static int mp3_head_convert(const guchar * hbuf) | 317 static int |
318 mp3_head_convert(const guchar * hbuf) | |
286 { | 319 { |
287 return ((unsigned long) hbuf[0] << 24) | | 320 return ((unsigned long) hbuf[0] << 24) | |
288 ((unsigned long) hbuf[1] << 16) | | 321 ((unsigned long) hbuf[1] << 16) | |
289 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; | 322 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; |
290 } | 323 } |
291 | 324 |
292 // audacious vfs fast version | 325 // audacious vfs fast version |
293 static int audmad_is_our_fd(char *filename, VFSFile *fin) | 326 static int |
327 audmad_is_our_fd(char *filename, VFSFile *fin) | |
294 { | 328 { |
295 guint32 check; | 329 guint32 check; |
296 gchar *ext = extname(filename); | 330 gchar *ext = extname(filename); |
297 gint cyc = 0, chkcount = 0, chksize = 4096; | 331 gint cyc = 0, chkcount = 0, chksize = 4096; |
298 guchar buf[4]; | 332 guchar buf[4]; |
374 | 408 |
375 return 1; | 409 return 1; |
376 } | 410 } |
377 | 411 |
378 // audacious vfs version | 412 // audacious vfs version |
379 static int audmad_is_our_file(char *filename) | 413 static int |
414 audmad_is_our_file(char *filename) | |
380 { | 415 { |
381 VFSFile *fin = NULL; | 416 VFSFile *fin = NULL; |
382 gint rtn; | 417 gint rtn; |
383 | 418 |
384 fin = aud_vfs_fopen(filename, "rb"); | 419 fin = aud_vfs_fopen(filename, "rb"); |
390 aud_vfs_fclose(fin); | 425 aud_vfs_fclose(fin); |
391 | 426 |
392 return rtn; | 427 return rtn; |
393 } | 428 } |
394 | 429 |
395 static void audmad_stop(InputPlayback *playback) | 430 static void |
431 audmad_stop(InputPlayback *playback) | |
396 { | 432 { |
397 AUDDBG("f: audmad_stop\n"); | 433 AUDDBG("f: audmad_stop\n"); |
398 g_mutex_lock(mad_mutex); | 434 g_mutex_lock(mad_mutex); |
399 info.playback = playback; | 435 info.playback = playback; |
400 g_mutex_unlock(mad_mutex); | 436 g_mutex_unlock(mad_mutex); |
415 | 451 |
416 } | 452 } |
417 AUDDBG("e: audmad_stop\n"); | 453 AUDDBG("e: audmad_stop\n"); |
418 } | 454 } |
419 | 455 |
420 static void audmad_play_file(InputPlayback *playback) | 456 static void |
457 audmad_play_file(InputPlayback *playback) | |
421 { | 458 { |
422 gboolean rtn; | 459 gboolean rtn; |
423 gchar *url = playback->filename; | 460 gchar *url = playback->filename; |
424 | 461 |
425 #ifdef AUD_DEBUG | 462 #ifdef AUD_DEBUG |
434 g_message("error initialising input"); | 471 g_message("error initialising input"); |
435 return; | 472 return; |
436 } | 473 } |
437 | 474 |
438 // remote access must use fast scan. | 475 // remote access must use fast scan. |
439 rtn = input_get_info(&info, aud_vfs_is_remote(url) ? TRUE : audmad_config.fast_play_time_calc); | 476 rtn = input_get_info(&info, aud_vfs_is_remote(url) ? TRUE : audmad_config->fast_play_time_calc); |
440 | 477 |
441 if (rtn == FALSE) { | 478 if (rtn == FALSE) { |
442 g_message("error reading input info"); | 479 g_message("error reading input info"); |
443 /* | 480 /* |
444 * return; | 481 * return; |
454 decode_thread = g_thread_self(); | 491 decode_thread = g_thread_self(); |
455 playback->set_pb_ready(playback); | 492 playback->set_pb_ready(playback); |
456 decode_loop(&info); | 493 decode_loop(&info); |
457 } | 494 } |
458 | 495 |
459 static void audmad_pause(InputPlayback *playback, short paused) | 496 static void |
497 audmad_pause(InputPlayback *playback, short paused) | |
460 { | 498 { |
461 g_mutex_lock(pb_mutex); | 499 g_mutex_lock(pb_mutex); |
462 info.playback = playback; | 500 info.playback = playback; |
463 g_mutex_unlock(pb_mutex); | 501 g_mutex_unlock(pb_mutex); |
464 playback->output->pause(paused); | 502 playback->output->pause(paused); |
465 } | 503 } |
466 | 504 |
467 static void audmad_mseek(InputPlayback *playback, gulong millisecond) | 505 static void |
506 audmad_mseek(InputPlayback *playback, gulong millisecond) | |
468 { | 507 { |
469 g_mutex_lock(pb_mutex); | 508 g_mutex_lock(pb_mutex); |
470 info.playback = playback; | 509 info.playback = playback; |
471 info.seek = millisecond; | 510 info.seek = millisecond; |
472 g_mutex_unlock(pb_mutex); | 511 g_mutex_unlock(pb_mutex); |
473 } | 512 } |
474 | 513 |
475 static void audmad_seek(InputPlayback *playback, gint time) | 514 static void |
515 audmad_seek(InputPlayback *playback, gint time) | |
476 { | 516 { |
477 audmad_mseek(playback, time * 1000); | 517 audmad_mseek(playback, time * 1000); |
478 } | 518 } |
479 | 519 |
480 /** | 520 /** |
494 if (input_init(&myinfo, url, NULL) == FALSE) { | 534 if (input_init(&myinfo, url, NULL) == FALSE) { |
495 AUDDBG("error initialising input\n"); | 535 AUDDBG("error initialising input\n"); |
496 return; | 536 return; |
497 } | 537 } |
498 | 538 |
499 if (input_get_info(&myinfo, info.remote ? TRUE : audmad_config.fast_play_time_calc) == TRUE) { | 539 if (input_get_info(&myinfo, info.remote ? TRUE : audmad_config->fast_play_time_calc) == TRUE) { |
500 if(aud_tuple_get_string(myinfo.tuple, -1, "track-name")) | 540 if(aud_tuple_get_string(myinfo.tuple, -1, "track-name")) |
501 *title = g_strdup(aud_tuple_get_string(myinfo.tuple, -1, "track-name")); | 541 *title = g_strdup(aud_tuple_get_string(myinfo.tuple, -1, "track-name")); |
502 else | 542 else |
503 *title = g_strdup(url); | 543 *title = g_strdup(url); |
504 | 544 |
524 AUDDBG("audmad_fill_info(): error initialising input\n"); | 564 AUDDBG("audmad_fill_info(): error initialising input\n"); |
525 return FALSE; | 565 return FALSE; |
526 } | 566 } |
527 | 567 |
528 info->fileinfo_request = FALSE; /* we don't need to read tuple again */ | 568 info->fileinfo_request = FALSE; /* we don't need to read tuple again */ |
529 return input_get_info(info, aud_vfs_is_remote(fd->uri) ? TRUE : audmad_config.fast_play_time_calc); | 569 return input_get_info(info, aud_vfs_is_remote(fd->uri) ? TRUE : audmad_config->fast_play_time_calc); |
530 } | 570 } |
531 | 571 |
532 static void audmad_about() | 572 static void |
573 audmad_about() | |
533 { | 574 { |
534 static GtkWidget *aboutbox; | 575 static GtkWidget *aboutbox; |
535 gchar *scratch; | 576 gchar *scratch; |
536 | 577 |
537 if (aboutbox != NULL) | 578 if (aboutbox != NULL) |
566 | 607 |
567 /** | 608 /** |
568 * Display a GTK box containing the given error message. | 609 * Display a GTK box containing the given error message. |
569 * Taken from mpg123 plugin. | 610 * Taken from mpg123 plugin. |
570 */ | 611 */ |
571 void audmad_error(char *error, ...) | 612 void |
613 audmad_error(char *error, ...) | |
572 { | 614 { |
573 #ifndef NOGUI | 615 #ifndef NOGUI |
574 if (!error_dialog) { | 616 if (!error_dialog) { |
575 va_list args; | 617 va_list args; |
576 char string[256]; | 618 char string[256]; |
588 #endif /* !NOGUI */ | 630 #endif /* !NOGUI */ |
589 } | 631 } |
590 | 632 |
591 extern void audmad_configure(); | 633 extern void audmad_configure(); |
592 | 634 |
593 static void __set_and_free(Tuple *tuple, gint nfield, gchar *name, gchar *value) | 635 static void |
636 __set_and_free(Tuple *tuple, gint nfield, gchar *name, gchar *value) | |
594 { | 637 { |
595 aud_tuple_associate_string(tuple, nfield, name, value); | 638 aud_tuple_associate_string(tuple, nfield, name, value); |
596 g_free(value); | 639 g_free(value); |
597 } | 640 } |
598 | 641 |
599 // tuple stuff | 642 // tuple stuff |
600 static Tuple *__audmad_get_song_tuple(char *filename, VFSFile *fd) | 643 static Tuple * |
644 __audmad_get_song_tuple(char *filename, VFSFile *fd) | |
601 { | 645 { |
602 Tuple *tuple = NULL; | 646 Tuple *tuple = NULL; |
603 gchar *string = NULL; | 647 gchar *string = NULL; |
604 | 648 |
605 struct id3_file *id3file = NULL; | 649 struct id3_file *id3file = NULL; |
747 | 791 |
748 AUDDBG("e: mad: audmad_get_song_tuple\n"); | 792 AUDDBG("e: mad: audmad_get_song_tuple\n"); |
749 return tuple; | 793 return tuple; |
750 } | 794 } |
751 | 795 |
752 static Tuple *audmad_get_song_tuple(char *filename) | 796 static Tuple * |
797 audmad_get_song_tuple(char *filename) | |
753 { | 798 { |
754 return __audmad_get_song_tuple(filename, NULL); | 799 return __audmad_get_song_tuple(filename, NULL); |
755 } | 800 } |
756 | 801 |
757 static Tuple *audmad_probe_for_tuple(char *filename, VFSFile *fd) | 802 static Tuple * |
803 audmad_probe_for_tuple(char *filename, VFSFile *fd) | |
758 { | 804 { |
759 if (!audmad_is_our_fd(filename, fd)) | 805 if (!audmad_is_our_fd(filename, fd)) |
760 return NULL; | 806 return NULL; |
761 | 807 |
762 aud_vfs_rewind(fd); | 808 aud_vfs_rewind(fd); |