Mercurial > audlegacy-plugins
changeset 611:3f7a52adfe0e trunk
[svn] merge recent changes from yaz's branch.
- stable shoutcast playback.
- tag handling improvement.
- view track detail on streaming won't crash. (disabled.)
- filepopup for streaming is partially supported. filepopup displays track name and stream name, but not updated automatically.
author | yaz |
---|---|
date | Tue, 06 Feb 2007 12:11:42 -0800 |
parents | 862190d39e00 |
children | 951b24719ce9 |
files | ChangeLog src/madplug/configure.c src/madplug/decoder.c src/madplug/fileinfo.c src/madplug/input.c src/madplug/input.h src/madplug/plugin.c src/madplug/plugin.h src/madplug/replaygain.c |
diffstat | 9 files changed, 807 insertions(+), 179 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Feb 05 12:28:01 2007 -0800 +++ b/ChangeLog Tue Feb 06 12:11:42 2007 -0800 @@ -1,3 +1,24 @@ +2007-02-05 20:28:01 +0000 William Pitcock <nenolod@sacredspiral.co.uk> + revision [1306] + - add madplug. It is not yet hooked up, I'll do that later. + + trunk/src/madplug/Makefile | 25 + + trunk/src/madplug/configure.c | 251 ++++++++++ + trunk/src/madplug/decoder.c | 567 ++++++++++++++++++++++++ + trunk/src/madplug/dither.c | 115 ++++ + trunk/src/madplug/fileinfo.c | 644 +++++++++++++++++++++++++++ + trunk/src/madplug/input.c | 518 ++++++++++++++++++++++ + trunk/src/madplug/input.h | 35 + + trunk/src/madplug/mp3.xpm | 963 +++++++++++++++++++++++++++++++++++++++++ + trunk/src/madplug/plugin.c | 568 ++++++++++++++++++++++++ + trunk/src/madplug/plugin.h | 131 +++++ + trunk/src/madplug/replaygain.c | 254 ++++++++++ + trunk/src/madplug/replaygain.h | 44 + + trunk/src/madplug/xing.c | 91 +++ + trunk/src/madplug/xing.h | 48 ++ + 14 files changed, 4254 insertions(+) + + 2007-02-05 00:43:27 +0000 Giacomo Lozito <james@develia.org> revision [1304] - aosd: avoid collision between playback start trigger and titlechange trigger, that occurred when the next file in playlist was played
--- a/src/madplug/configure.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/configure.c Tue Feb 06 12:11:42 2007 -0800 @@ -27,7 +27,7 @@ static GtkWidget *configure_win = NULL; static GtkWidget *vbox; -static GtkWidget *fast_playback, *use_xing, *dither; +static GtkWidget *fast_playback, *use_xing, *dither, *sjis; static GtkWidget *RG_enable, *RG_track_mode, *RG_default, *pregain, *hard_limit; static GtkWidget *title_id3_box, *title_tag_desc; @@ -47,6 +47,8 @@ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_xing)); audmad_config.dither = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dither)); + audmad_config.sjis = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sjis)); audmad_config.replaygain.enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(RG_enable)); @@ -69,6 +71,7 @@ audmad_config.fast_play_time_calc); bmp_cfg_db_set_bool(db, "MAD", "use_xing", audmad_config.use_xing); bmp_cfg_db_set_bool(db, "MAD", "dither", audmad_config.dither); + bmp_cfg_db_set_bool(db, "MAD", "sjis", audmad_config.sjis); bmp_cfg_db_set_bool(db, "MAD", "hard_limit", audmad_config.hard_limit); bmp_cfg_db_set_string(db, "MAD", "pregain_db", @@ -102,6 +105,116 @@ gtk_widget_set_sensitive(title_tag_desc, override); } +#if 0 +// derived from xmms-mad. +void audmad_configure(void) +{ + GtkWidget *bbox, *ok, *cancel; + GtkWidget *label, *RG_default_hbox, *pregain_hbox; + + if (configure_win != NULL) { + gdk_window_raise(configure_win->window); + return; + } + + configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(configure_win), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &configure_win); + gtk_signal_connect(GTK_OBJECT(configure_win), "destroy", + GTK_SIGNAL_FUNC(configure_destroy), &configure_win); + gtk_window_set_title(GTK_WINDOW(configure_win), + "MAD Input Plugin Configuration"); + gtk_window_set_policy(GTK_WINDOW(configure_win), FALSE, FALSE, FALSE); + gtk_container_border_width(GTK_CONTAINER(configure_win), 10); + + vbox = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(configure_win), vbox); + + fast_playback = + gtk_check_button_new_with_label("Use fast playtime calculation"); + gtk_box_pack_start(GTK_BOX(vbox), fast_playback, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fast_playback), + audmad_config.fast_play_time_calc); + + use_xing = gtk_check_button_new_with_label("Parse XING headers"); + gtk_box_pack_start(GTK_BOX(vbox), use_xing, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_xing), + audmad_config.use_xing); + + dither = + gtk_check_button_new_with_label + ("Dither output when rounding to 16-bit"); + gtk_box_pack_start(GTK_BOX(vbox), dither, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dither), + audmad_config.dither); + + sjis = gtk_check_button_new_with_label("Use SJIS to write ID3 tags instead of UTF-8"); + gtk_box_pack_start(GTK_BOX(vbox), sjis, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sjis), audmad_config.sjis); + + /* SKR added config : */ + RG_enable = gtk_check_button_new_with_label("Enable replaygain"); + gtk_box_pack_start(GTK_BOX(vbox), RG_enable, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(RG_enable), + audmad_config.replaygain.enable); + RG_track_mode = + gtk_check_button_new_with_label("Prefer TRACK replaygain"); + gtk_box_pack_start(GTK_BOX(vbox), RG_track_mode, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(RG_track_mode), + audmad_config.replaygain.track_mode); + + hard_limit = + gtk_check_button_new_with_label + ("hard-limit samples (prevent clipping)"); + gtk_box_pack_start(GTK_BOX(vbox), hard_limit, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hard_limit), + audmad_config.hard_limit); + + label = gtk_label_new("gain to use if no RG tag (dB):"); + RG_default_hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), RG_default_hbox, TRUE, TRUE, 0); + RG_default = gtk_entry_new(); + gtk_widget_set_usize(RG_default, 80, -1); + gtk_entry_set_text(GTK_ENTRY(RG_default), + audmad_config.replaygain.default_db); + gtk_box_pack_start(GTK_BOX(RG_default_hbox), label, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(RG_default_hbox), RG_default, FALSE, TRUE, + 0); + + label = gtk_label_new("Pre-gain (dB):"); + pregain_hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), pregain_hbox, TRUE, TRUE, 0); + pregain = gtk_entry_new(); + gtk_widget_set_usize(pregain, 80, -1); + gtk_entry_set_text(GTK_ENTRY(pregain), audmad_config.pregain_db); + gtk_box_pack_start(GTK_BOX(pregain_hbox), label, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(pregain_hbox), pregain, FALSE, TRUE, 0); + + + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); + gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); + + ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect(GTK_OBJECT(ok), "clicked", + GTK_SIGNAL_FUNC(configure_win_ok), NULL); + GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0); + gtk_widget_grab_default(ok); + + cancel = gtk_button_new_with_label("Cancel"); + gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", + GTK_SIGNAL_FUNC(gtk_widget_destroy), + GTK_OBJECT(configure_win)); + GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); + + gtk_widget_show_all(configure_win); +} +#endif + void audmad_configure(void) { GtkWidget *bbox, *ok, *cancel; @@ -147,6 +260,10 @@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_xing), audmad_config.use_xing); + sjis = gtk_check_button_new_with_label("Use SJIS to write ID3 tags instead of UTF-8"); + gtk_box_pack_start(GTK_BOX(vbox2), sjis, TRUE, TRUE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sjis), audmad_config.sjis); + dither = gtk_check_button_new_with_label (_("Dither output when rounding to 16-bit"));
--- a/src/madplug/decoder.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/decoder.c Tue Feb 06 12:11:42 2007 -0800 @@ -27,6 +27,7 @@ #include <audacious/plugin.h> #include <audacious/output.h> #include <audacious/util.h> +#include <sys/time.h> #include "plugin.h" #include "input.h" @@ -152,11 +153,11 @@ } } assert(pos == olen); - if (info->playback->playing == 0) + if (!info->playback->playing) return; - produce_audio(mad_plugin->output->written_time(), - FMT_S16_LE, MAD_NCHANNELS(header), olen, output, NULL); - if (info->playback->playing == 0) + produce_audio(info->playback->output->written_time(), + FMT_S16_LE, MAD_NCHANNELS(header), olen, output, &(info->playback->playing)); + if (!info->playback->playing) return; g_free(output); } @@ -245,11 +246,13 @@ } info->frames++; #ifdef DEBUG +#ifdef DEBUG_INTENSIVELY g_message("duration = %lu", mad_timer_count(header.duration, MAD_UNITS_MILLISECONDS)); g_message("size = %d", stream.next_frame - stream.this_frame); #endif +#endif mad_timer_add(&info->duration, header.duration); data_used += stream.next_frame - stream.this_frame; if (info->frames == 1) { @@ -301,7 +304,6 @@ if (fast && info->frames >= N_AVERAGE_FRAMES) { float frame_size = ((double) data_used) / N_AVERAGE_FRAMES; info->frames = (info->size - tagsize) / frame_size; - //int frame_frac = (info->size - tagsize) % frame_size; info->duration.seconds /= N_AVERAGE_FRAMES; info->duration.fraction /= N_AVERAGE_FRAMES; mad_timer_multiply(&info->duration, info->frames); @@ -309,7 +311,6 @@ g_message("using fast playtime calculation"); g_message("data used = %d [tagsize=%d framesize=%f]", data_used, tagsize, frame_size); - //g_message ("frame_size = %f [frac=%d]", frame_size, frame_frac); g_message("frames = %d, frequecy = %d, channels = %d", info->frames, info->freq, info->channels); long millis = mad_timer_count(info->duration, @@ -335,14 +336,15 @@ #ifdef DEBUG g_message("e: scan_file"); #endif /* DEBUG */ - return (info->frames != 0 || info->remote == TRUE); +// return info->frames != 0; + return (info->frames != 0 || info->remote == TRUE); // suspicious } gpointer decode_loop(gpointer arg) { unsigned char buffer[BUFFER_SIZE]; int len; - int seek_skip = 0; + gboolean seek_skip = FALSE; int remainder = 0; gint tlen; @@ -363,12 +365,20 @@ mad_stream_init(&stream); mad_synth_init(&synth); - if (!mad_plugin->output-> - open_audio(info->fmt, info->freq, info->channels)) { + if(!info->playback){ + g_print("decode: playback == NULL\n"); + return NULL; + } + + if (!info->playback->output->open_audio(info->fmt, info->freq, info->channels)) { + g_mutex_lock(pb_mutex); + info->playback->error = TRUE; + info->playback->eof = 1; + g_mutex_unlock(pb_mutex); audmad_error("failed to open audio output: %s", - mad_plugin->output->description); + info->playback->output->description); g_message("failed to open audio output: %s", - mad_plugin->output->description); + info->playback->output->description); return NULL; } @@ -378,6 +388,7 @@ info->title = xmms_get_titlestring(xmms_get_gentitle_format(), info->tuple); + tlen = (gint) mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS), mad_plugin->set_info(info->title, @@ -386,7 +397,7 @@ /* main loop */ do { - if (info->playback->playing == 0) { + if (!info->playback->playing) { #ifdef DEBUG g_message("decode: stop signaled"); #endif /* DEBUG */ @@ -427,14 +438,19 @@ if (--skip == 0) mad_synth_frame(&synth, &frame); } - else if (!MAD_RECOVERABLE(stream.error)) + else if (!MAD_RECOVERABLE(stream.error)) { + g_mutex_lock(pb_mutex); + info->playback->error = TRUE; + info->playback->eof = 1; + g_mutex_unlock(pb_mutex); break; + } } while (skip); - seek_skip = 0; + seek_skip = FALSE; } - while (!info->playback->playing == 0) { + while (info->playback->playing) { if (info->seek != -1 && !info->remote) { #ifdef DEBUG g_message("seeking: %d", info->seek); @@ -448,6 +464,9 @@ mad_timer_set(&info->pos, info->seek, 0, 0); new_position = ((double) info->seek / (double) seconds) * info->size; + + if(new_position < 0) + new_position = 0; #ifdef DEBUG g_message("seeking to: %d bytes", new_position); #endif @@ -456,18 +475,17 @@ mad_frame_mute(&frame); mad_synth_mute(&synth); stream.error = MAD_ERROR_BUFLEN; - mad_plugin->output->flush(mad_timer_count - (info->pos, - MAD_UNITS_MILLISECONDS)); + info->playback->output->flush(mad_timer_count(info->pos, MAD_UNITS_MILLISECONDS)); stream.sync = 0; info->seek = -1; - seek_skip = 1; + seek_skip = TRUE; break; } if (mad_header_decode(&frame.header, &stream) == -1) { - if (!MAD_RECOVERABLE(stream.error)) + if (!MAD_RECOVERABLE(stream.error)) { break; + } if (stream.error == MAD_ERROR_LOSTSYNC) { /* ignore LOSTSYNC due to ID3 tags */ int tagsize = id3_tag_query(stream.this_frame, @@ -500,9 +518,7 @@ if (info->freq != frame.header.samplerate || info->channels != - (guint) MAD_NCHANNELS(&frame.header)) - { - tlen = mad_timer_count(info->duration, MAD_UNITS_MILLISECONDS); + (guint) MAD_NCHANNELS(&frame.header)) { #ifdef DEBUG g_message("re-opening audio due to change in audio type"); g_message("old: frequency = %d, channels = %d", info->freq, @@ -511,24 +527,24 @@ frame.header.samplerate, (guint) MAD_NCHANNELS(&frame.header)); #endif /* DEBUG */ - info->freq = frame.header.samplerate; info->channels = MAD_NCHANNELS(&frame.header); - mad_plugin->output->close_audio(); - if (!mad_plugin->output->open_audio(info->fmt, info->freq, + info->playback->output->close_audio(); + if (!info->playback->output->open_audio(info->fmt, info->freq, info->channels)) { + g_mutex_lock(pb_mutex); + info->playback->error = TRUE; + info->playback->eof = 1; + g_mutex_unlock(pb_mutex); audmad_error("failed to re-open audio output: %s", - mad_plugin->output->description); + info->playback->output->description); } - - mad_plugin->set_info(info->title, - tlen != 0 ? tlen : -1, - info->bitrate, info->freq, info->channels); } - if (info->playback->playing == 0) + if (!info->playback->playing) break; mad_synth_frame(&synth, &frame); mad_stream_sync(&stream); + write_output(info, &synth.pcm, &frame.header); mad_timer_add(&info->pos, frame.header.duration); } @@ -540,17 +556,30 @@ mad_stream_finish(&stream); mad_synth_finish(&synth); - if (!info->playback->playing == 0) { - mad_plugin->output->buffer_free(); - mad_plugin->output->buffer_free(); - while (mad_plugin->output->buffer_playing()) { + if (info->playback->playing) { + GTimeVal sleeptime; + + info->playback->output->buffer_free(); + info->playback->output->buffer_free(); + while (info->playback->output->buffer_playing()) { #ifdef DEBUG g_message("f: buffer_playing=%d", - mad_plugin->output->buffer_playing()); + info->playback->output->buffer_playing()); #endif - xmms_usleep(10000); - if (info->playback->playing == 0) + g_get_current_time(&sleeptime); + sleeptime.tv_usec += 500000; + if(sleeptime.tv_usec >= 1000000) { + sleeptime.tv_sec += 1; + sleeptime.tv_usec -= 1000000; + } + + g_mutex_lock(mad_mutex); + g_cond_timed_wait(mad_cond, mad_mutex, &sleeptime); + if (!info->playback->playing) { + g_mutex_unlock(mad_mutex); break; + } + g_mutex_unlock(mad_mutex); } } #ifdef DEBUG @@ -560,8 +589,10 @@ bmp_title_input_free(info->tuple); info->tuple = NULL; - mad_plugin->output->close_audio(); + info->playback->output->close_audio(); + g_mutex_lock(mad_mutex); info->playback->playing = 0; + g_mutex_unlock(mad_mutex); g_thread_exit(0); return NULL; /* dummy */ }
--- a/src/madplug/fileinfo.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/fileinfo.c Tue Feb 06 12:11:42 2007 -0800 @@ -62,6 +62,8 @@ if (data == NULL) return; + /* printf ("updating id3: %s: %s\n", frame_name, data); */ + /* * An empty string removes the frame altogether. */ @@ -77,31 +79,37 @@ id3_tag_attachframe(tag, frame); } - if (frame_name == ID3_FRAME_COMMENT) { + // setup ucs4 string + if(audmad_config.sjis) { + ucs4 = id3_latin1_ucs4duplicate((id3_latin1_t *) data); + } + else { + ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) data); + } + + // set encoding + field = id3_frame_field(frame, 0); + id3_field_settextencoding(field, audmad_config.sjis ? ID3_FIELD_TEXTENCODING_ISO_8859_1 : + ID3_FIELD_TEXTENCODING_UTF_8); + + // setup genre code + if (!strcmp(frame_name, ID3_FRAME_GENRE)) { + char *tmp; + int index = id3_genre_number(ucs4); + g_free(ucs4); + tmp = g_strdup_printf("%d", index); + ucs4 = id3_latin1_ucs4duplicate((unsigned char *) tmp); + } + + // write string + if (!strcmp(frame_name, ID3_FRAME_COMMENT)) { field = id3_frame_field(frame, 3); field->type = ID3_FIELD_TYPE_STRINGFULL; + res = id3_field_setfullstring(field, ucs4); } else { field = id3_frame_field(frame, 1); field->type = ID3_FIELD_TYPE_STRINGLIST; - } - - id3_field_settextencoding(field, ID3_FIELD_TEXTENCODING_UTF_8); - - ucs4 = id3_utf8_ucs4duplicate((const unsigned char *) data); - - if (frame_name == ID3_FRAME_GENRE) { - char *tmp; - int index = id3_genre_number(ucs4); - g_free(ucs4); - tmp = g_strdup_printf("%d", index); - ucs4 = id3_utf8_ucs4duplicate((unsigned char *) tmp); - } - - if (frame_name == ID3_FRAME_COMMENT) { - res = id3_field_setfullstring(field, ucs4); - } - else { res = id3_field_setstrings(field, 1, &ucs4); } @@ -117,10 +125,10 @@ static void save_cb(GtkWidget * w, gpointer data) { - gchar *text; + gchar *text, *sjis; struct id3_file *id3file; struct id3_tag *id3tag; - char *codeset; + char *encoding; if (info.remote) return; @@ -130,55 +138,78 @@ if (!id3file) { id3tag = id3_tag_new(); id3_tag_clearframes(id3tag); + id3tag->options |= ID3_TAG_OPTION_ID3V1; if (!id3file) { xmms_show_message("File Info", "Couldn't open file!", "Ok", FALSE, NULL, NULL); return; } } - id3tag = id3_file_tag(id3file); + id3_tag_options(id3tag, ID3_TAG_OPTION_ID3V1, ~0); /* enables id3v1 */ +// id3_tag_options(id3tag, ID3_TAG_OPTION_ID3V1, 0); /* disables id3v1 */ if (!id3tag) { id3tag = id3_tag_new(); } + encoding = audmad_config.sjis ? "SJIS" : "UTF-8"; + text = gtk_editable_get_chars(GTK_EDITABLE(title_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_TITLE, text); + sjis = g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_TITLE, sjis); free(text); + free(sjis); text = gtk_editable_get_chars(GTK_EDITABLE(artist_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_ARTIST, text); + sjis = g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_ARTIST, sjis); free(text); + free(sjis); text = gtk_editable_get_chars(GTK_EDITABLE(album_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_ALBUM, text); + sjis = + g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_ALBUM, sjis); free(text); + free(sjis); text = gtk_editable_get_chars(GTK_EDITABLE(year_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_YEAR, text); + sjis = + g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_YEAR, sjis); free(text); + free(sjis); text = gtk_editable_get_chars(GTK_EDITABLE(comment_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_COMMENT, text); + sjis = + g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_COMMENT, sjis); free(text); + free(sjis); text = gtk_editable_get_chars(GTK_EDITABLE(tracknum_entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_TRACK, text); + sjis = + g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_TRACK, sjis); free(text); + free(sjis); - text = - gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(genre_combo)->entry), + text = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(genre_combo)->entry), 0, -1); - update_id3_frame(id3tag, ID3_FRAME_GENRE, text); + sjis = g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL); + update_id3_frame(id3tag, ID3_FRAME_GENRE, sjis); free(text); + free(sjis); if (id3_file_update(id3file) != 0) { xmms_show_message("File Info", "Couldn't write tag!", "Ok", FALSE, NULL, NULL); } id3_file_close(id3file); +// gtk_widget_destroy(window); } +#if 0 static void remove_id3_cb(GtkWidget * w, gpointer data) { struct id3_file *id3file; @@ -211,6 +242,277 @@ gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE); } +#endif + +static void remove_id3_cb(GtkWidget * w, gpointer data) +{ + struct id3_file *id3file; + struct id3_tag *id3tag; + + /* read tag from file */ + id3file = id3_file_open(info.filename, ID3_FILE_MODE_READWRITE); + if (!id3file) + return; + + id3tag = id3_file_tag(id3file); + if(id3tag) { + /* since current libid3tag cannot delete tag completely, just add a dummy. */ + const char *dummy = ""; + update_id3_frame(id3tag, ID3_FRAME_TITLE, dummy); + update_id3_frame(id3tag, ID3_FRAME_ARTIST, dummy); + update_id3_frame(id3tag, ID3_FRAME_ALBUM, dummy); + update_id3_frame(id3tag, ID3_FRAME_YEAR, dummy); + update_id3_frame(id3tag, ID3_FRAME_TRACK, dummy); + update_id3_frame(id3tag, ID3_FRAME_GENRE, "Other"); + update_id3_frame(id3tag, ID3_FRAME_COMMENT, dummy); + + if (id3_file_update(id3file) != 0) { + xmms_show_message("File Info", "Couldn't write tag!", "OK", FALSE, + NULL, NULL); + } + } + + id3_file_close(id3file); + + gtk_entry_set_text(GTK_ENTRY(title_entry), ""); + gtk_entry_set_text(GTK_ENTRY(artist_entry), ""); + gtk_entry_set_text(GTK_ENTRY(album_entry), ""); + gtk_entry_set_text(GTK_ENTRY(comment_entry), ""); + gtk_entry_set_text(GTK_ENTRY(year_entry), ""); + gtk_entry_set_text(GTK_ENTRY(tracknum_entry), ""); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), ""); + gtk_widget_set_sensitive(GTK_WIDGET(w), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE); + +// gtk_widget_destroy(window); +} + +#if 0 +void create_window() +{ + GtkWidget *vbox, *hbox, *left_vbox, *table; + GtkWidget *mpeg_frame, *mpeg_box; + GtkWidget *label, *filename_hbox; + GtkWidget *bbox, *save, *remove_id3, *cancel; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); + gtk_signal_connect(GTK_OBJECT(window), "destroy", + GTK_SIGNAL_FUNC(close_window), &window); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + + vbox = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(window), vbox); + + filename_hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0); + + label = gtk_label_new("Filename:"); + gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0); + filename_entry = gtk_entry_new(); + gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE); + gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, + 0); + + hbox = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + + left_vbox = gtk_vbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0); + + id3_frame = gtk_frame_new("ID3 Tag:"); + gtk_box_pack_start(GTK_BOX(left_vbox), id3_frame, FALSE, FALSE, 0); + + table = gtk_table_new(5, 5, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 5); + gtk_container_add(GTK_CONTAINER(id3_frame), table); + + label = gtk_label_new("Title:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, + GTK_FILL, 5, 5); + + title_entry = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Artist:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, + GTK_FILL, 5, 5); + + artist_entry = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(table), artist_entry, 1, 4, 1, 2, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Album:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, + GTK_FILL, 5, 5); + + album_entry = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Comment:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, + GTK_FILL, 5, 5); + + comment_entry = gtk_entry_new(); + gtk_table_attach(GTK_TABLE(table), comment_entry, 1, 4, 3, 4, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Year:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, + GTK_FILL, 5, 5); + + year_entry = gtk_entry_new(); + gtk_widget_set_usize(year_entry, 40, -1); + gtk_table_attach(GTK_TABLE(table), year_entry, 1, 2, 4, 5, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Track number:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5, GTK_FILL, + GTK_FILL, 5, 5); + + tracknum_entry = gtk_entry_new(); + gtk_widget_set_usize(tracknum_entry, 40, -1); + gtk_table_attach(GTK_TABLE(table), tracknum_entry, 3, 4, 4, 5, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + label = gtk_label_new("Genre:"); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, + GTK_FILL, 5, 5); + + genre_combo = gtk_combo_new(); + gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), + FALSE); + if (!genre_list) { + int i = 0; + const id3_ucs4_t *ucs4 = id3_genre_index(i); + while (ucs4) { + genre_list = + g_list_append(genre_list, id3_ucs4_latin1duplicate(ucs4)); + i++; + ucs4 = id3_genre_index(i); + } + } + gtk_combo_set_popdown_strings(GTK_COMBO(genre_combo), genre_list); + + gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, + GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); + + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); + gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0); + + save = gtk_button_new_with_label("Save"); + gtk_signal_connect(GTK_OBJECT(save), "clicked", + GTK_SIGNAL_FUNC(save_cb), NULL); + GTK_WIDGET_SET_FLAGS(save, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 0); + gtk_widget_grab_default(save); + + remove_id3 = gtk_button_new_with_label("Remove ID3"); + gtk_signal_connect(GTK_OBJECT(remove_id3), "clicked", + GTK_SIGNAL_FUNC(remove_id3_cb), NULL); + GTK_WIDGET_SET_FLAGS(remove_id3, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), remove_id3, TRUE, TRUE, 0); + + cancel = gtk_button_new_with_label("Cancel"); + gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", + GTK_SIGNAL_FUNC(gtk_widget_destroy), + GTK_OBJECT(window)); + GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); + + mpeg_frame = gtk_frame_new("MPEG Info:"); + gtk_box_pack_start(GTK_BOX(hbox), mpeg_frame, FALSE, FALSE, 0); + + mpeg_box = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(mpeg_frame), mpeg_box); + gtk_container_set_border_width(GTK_CONTAINER(mpeg_box), 10); + gtk_box_set_spacing(GTK_BOX(mpeg_box), 0); + + mpeg_level = gtk_label_new(""); + gtk_widget_set_usize(mpeg_level, 120, -2); + gtk_misc_set_alignment(GTK_MISC(mpeg_level), 0, 0); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_level, FALSE, FALSE, 0); + + mpeg_bitrate = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_bitrate), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_bitrate), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_bitrate, FALSE, FALSE, 0); + + mpeg_samplerate = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_samplerate), 0, 0); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_samplerate, FALSE, FALSE, + 0); + + mpeg_flags = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_flags), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_flags), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_flags, FALSE, FALSE, 0); + + mpeg_frames = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_frames), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_frames), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_frames, FALSE, FALSE, 0); + + mpeg_duration = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_duration), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_duration), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_duration, FALSE, FALSE, 0); + + mpeg_replaygain = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_replaygain), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_replaygain), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_replaygain, FALSE, FALSE, + 0); + mpeg_replaygain2 = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_replaygain2), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_replaygain2), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_replaygain2, FALSE, FALSE, + 0); + mpeg_replaygain3 = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_replaygain3), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_replaygain3), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_replaygain3, FALSE, FALSE, + 0); + mpeg_replaygain4 = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_replaygain4), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_replaygain4), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_replaygain4, FALSE, FALSE, + 0); + mp3gain1 = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mp3gain1), 0, 0); + gtk_label_set_justify(GTK_LABEL(mp3gain1), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mp3gain1, FALSE, FALSE, 0); + mp3gain2 = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mp3gain2), 0, 0); + gtk_label_set_justify(GTK_LABEL(mp3gain2), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mp3gain2, FALSE, FALSE, 0); + + mpeg_fileinfo = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(mpeg_fileinfo), 0, 0); + gtk_label_set_justify(GTK_LABEL(mpeg_fileinfo), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_fileinfo, FALSE, FALSE, 0); + + gtk_widget_show_all(window); +} +#endif static void change_buttons(GtkWidget * object) @@ -500,7 +802,7 @@ #ifndef NOGUI gchar *title; gchar message[128]; - static char const *const layer_str[3] = { "MPEG-1 Layer I", "MPEG-1 Layer II", "MPEG-1 Layer III" }; + static char const *const layer_str[3] = { "I", "II", "III" }; static char const *const mode_str[4] = { ("single channel"), ("dual channel"), "joint stereo", "stereo" }; @@ -509,13 +811,20 @@ #ifdef DEBUG g_message("f: audmad_get_file_info: %s\n", filename); #endif + input_init(&info, filename); + + if (!strncasecmp("http://", filename, strlen("http://")) || + !strncasecmp("https://", filename, strlen("https://"))) { + info.remote = TRUE; + return; //tentative + } + utf_filename = str_to_utf8(filename); create_window(); - input_init(&info, filename); - input_get_info(&info, FALSE); + input_get_info(&info, info.remote ? TRUE : audmad_config.fast_play_time_calc); - title = g_strdup_printf("%s - Audacious", g_basename(filename)); + title = g_strdup_printf("File Info - %s", g_basename(filename)); gtk_window_set_title(GTK_WINDOW(window), title); g_free(title); @@ -545,13 +854,13 @@ id3_frame_to_entry(ID3_FRAME_TRACK, GTK_ENTRY(tracknum_entry)); id3_frame_to_entry(ID3_FRAME_COMMENT, GTK_ENTRY(comment_entry)); - snprintf(message, 127, "%s", layer_str[info.mpeg_layer - 1]); + snprintf(message, 127, "Layer %s", layer_str[info.mpeg_layer - 1]); gtk_label_set_text(GTK_LABEL(mpeg_level), message); if (info.vbr) { snprintf(message, 127, "VBR (avg. %d kbps)", info.bitrate / 1000); } else { - snprintf(message, 127, "%d KBit/s", info.bitrate / 1000); + snprintf(message, 127, "%d kbps", info.bitrate / 1000); } gtk_label_set_text(GTK_LABEL(mpeg_bitrate), message); snprintf(message, 127, "%d Hz", info.freq);
--- a/src/madplug/input.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/input.c Tue Feb 06 12:11:42 2007 -0800 @@ -66,6 +66,14 @@ extern gboolean scan_file(struct mad_info_t *info, gboolean fast); +// new VFS handles url. +static void input_parse_url(struct mad_info_t *info) +{ + info->filename = g_strdup(info->url); + return; +} + + /** * init the mad_info_t struct. */ @@ -101,12 +109,13 @@ info->mp3gain_minmax_str = 0; info->tuple = NULL; - info->filename = g_strdup(url); + + input_parse_url(info); info->infile = vfs_fopen(info->filename, "rb"); - if (info->infile == NULL) + if (info->infile == NULL) { return FALSE; - + } // obtain file size vfs_fseek(info->infile, 0, SEEK_END); info->size = vfs_ftell(info->infile); @@ -114,7 +123,6 @@ info->remote = info->size == 0 ? TRUE : FALSE; #ifdef DEBUG - g_message("i: info->size == %lu", info->size); g_message("e: input_init"); #endif return TRUE; @@ -159,7 +167,7 @@ tail = (id3_ucs4_t *)string + mad_ucs4len((id3_ucs4_t *)string); - ret = g_malloc0(1024); // realloc() is too picky + ret = g_malloc0(1024); for(ptr = (id3_ucs4_t *)string; *ptr != 0 && ptr <= tail; ptr++) { if(*ptr == '(') { @@ -168,7 +176,6 @@ end++; } end++; //include trailing ')' -// ret = g_realloc(ret, BYTES(end - ptr + 1)); memcpy(ret, ptr, BYTES(end - ptr)); ret_len += (end - ptr); *(ret + ret_len) = 0; //terminate @@ -192,7 +199,6 @@ tmp_len = mad_ucs4len(genre); -// ret = g_realloc(ret, BYTES(ret_len + tmp_len + 1)); memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); ret_len += tmp_len; @@ -231,14 +237,12 @@ tmp_len = mad_ucs4len(genre); -// ret = g_realloc(ret, BYTES(ret_len + tmp_len + 1)); memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); ret_len += tmp_len; *(ret + ret_len) = 0; //terminate } else { // plain text -// ret = g_realloc(ret, BYTES(end - ptr + 1)); #ifdef DEBUG printf("plain!\n"); printf("ret_len = %d\n", ret_len); @@ -257,16 +261,19 @@ gchar *input_id3_get_string(struct id3_tag * tag, char *frame_name) { gchar *rtn; + gchar *rtn2; const id3_ucs4_t *string_const; id3_ucs4_t *string; + id3_ucs4_t *ucsptr; struct id3_frame *frame; union id3_field *field; + gboolean flagutf = FALSE; frame = id3_tag_findframe(tag, frame_name, 0); if (!frame) return NULL; - if (frame_name == ID3_FRAME_COMMENT) + if (!strcmp(frame_name, ID3_FRAME_COMMENT)) field = id3_frame_field(frame, 3); else field = id3_frame_field(frame, 1); @@ -274,7 +281,7 @@ if (!field) return NULL; - if (frame_name == ID3_FRAME_COMMENT) + if (!strcmp(frame_name, ID3_FRAME_COMMENT)) string_const = id3_field_getfullstring(field); else string_const = id3_field_getstrings(field, 0); @@ -284,21 +291,38 @@ string = mad_ucs4dup((id3_ucs4_t *)string_const); - if (frame_name == ID3_FRAME_GENRE) { + if (!strcmp(frame_name, ID3_FRAME_GENRE)) { id3_ucs4_t *string2 = NULL; string2 = mad_parse_genre(string); g_free((void *)string); string = string2; } - { - id3_utf8_t *string2 = id3_ucs4_utf8duplicate(string); - rtn = str_to_utf8(string2); - g_free(string2); + ucsptr = (id3_ucs4_t *)string; + while (*ucsptr) { + if (*ucsptr > 0x000000ffL) { + flagutf = TRUE; + break; + } + ucsptr++; } + if (flagutf) { #ifdef DEBUG - g_print("i: string = %s\n", rtn); + g_print("aud-mad: flagutf!\n"); +#endif + rtn = (gchar *)id3_ucs4_utf8duplicate(string); + } + else { + rtn = (gchar *)id3_ucs4_latin1duplicate(string); + rtn2 = str_to_utf8(rtn); + free(rtn); + rtn = rtn2; + } + g_free(string); + string = NULL; +#ifdef DEBUG + g_print("string = %s\n", rtn); #endif return rtn; } @@ -379,15 +403,14 @@ input_read_replaygain(info); /* scan mp3 file, decoding headers unless fast_scan is set */ - if (scan_file(info, fast_scan) == FALSE) + if (scan_file(info, fast_scan) == FALSE) { return FALSE; - + } /* reset the input file to the start */ - vfs_rewind(info->infile); + vfs_fseek(info->infile, 0, SEEK_SET); info->offset = 0; - if (info->remote) - { + if(info->remote){ gchar *stream_name = vfs_get_metadata(info->infile, "stream-name"); gchar *track_name = vfs_get_metadata(info->infile, "track-name"); gchar *tmp = NULL; @@ -407,8 +430,7 @@ } /* use the filename for the title as a last resort */ - if (!info->title) - { + if (!info->title) { char *pos = strrchr(info->filename, DIR_SEPARATOR); if (pos) info->title = g_strdup(pos + 1); @@ -423,29 +445,33 @@ } + /** * Read data from the source given my madinfo into the buffer * provided. Return the number of bytes read. * @return 0 on EOF * @return -1 on error */ +// this function may be called before info->playback initialized. int input_get_data(struct mad_info_t *madinfo, guchar * buffer, int buffer_size) { int len = 0; #ifdef DEBUG -// g_message ("f: input_get_data: %d", buffer_size); +#ifdef DEBUG_INTENSIVELY + g_message ("f: input_get_data: %d", buffer_size); #endif - +#endif /* simply read to data from the file */ - len = vfs_fread(buffer, 1, buffer_size, madinfo->infile); + len = vfs_fread(buffer, 1, buffer_size, madinfo->infile); //vfs_fread returns num of element. - if (len == 0 && madinfo->playback) - madinfo->playback->eof = TRUE; - - if (madinfo->remote) - { + if(len == 0){ + if(madinfo->playback) + madinfo->playback->eof = TRUE; + } + + if(madinfo->remote) { gchar *stream_name = vfs_get_metadata(madinfo->infile, "stream-name"); gchar *track_name = vfs_get_metadata(madinfo->infile, "track-name"); gchar *tmp = NULL; @@ -459,13 +485,15 @@ madinfo->tuple->album_name = g_strdup(stream_name); tmp = g_strdup_printf("%s (%s)", track_name, stream_name); mad_plugin->set_info(tmp, - -1, // indicates the stream is unseekable - madinfo->bitrate, madinfo->freq, madinfo->channels); + -1, // indicate the stream is unseekable + madinfo->bitrate, madinfo->freq, madinfo->channels); g_free(tmp); g_free(stream_name); g_free(track_name); } - + #ifdef DEBUG -// g_message ("e: input_get_data: size=%d offset=%d", len, madinfo->offset); +#ifdef DEBUG_INTENSIVELY + g_message ("e: input_get_data: size=%d offset=%d", len, madinfo->offset); +#endif #endif madinfo->offset += len; return len;
--- a/src/madplug/input.h Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/input.h Tue Feb 06 12:11:42 2007 -0800 @@ -23,13 +23,11 @@ #define INPUT_H #include "plugin.h" - gboolean input_init(struct mad_info_t *songinfo, const gchar * url); gboolean input_term(struct mad_info_t *songinfo); gboolean input_get_info(struct mad_info_t *songinfo, gboolean fast_scan); gint input_get_data(struct mad_info_t *songinfo, guchar * buffer, gint buffer_size); -gint input_udp_read(); gchar *input_id3_get_string(struct id3_tag *tag, char *frame_name); #endif /* ! INPUT_H */
--- a/src/madplug/plugin.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/plugin.c Tue Feb 06 12:11:42 2007 -0800 @@ -37,8 +37,10 @@ * Global variables */ struct audmad_config_t audmad_config; /**< global configuration */ -static GStaticMutex mutex; InputPlugin *mad_plugin = NULL; +GMutex *mad_mutex; +GMutex *pb_mutex; +GCond *mad_cond; /* * static variables @@ -69,6 +71,7 @@ return ext; } + void audmad_config_compute(struct audmad_config_t *config) { /* set some config parameters by parsing text fields @@ -99,6 +102,7 @@ audmad_config.fast_play_time_calc = TRUE; audmad_config.use_xing = TRUE; audmad_config.dither = TRUE; + audmad_config.sjis = FALSE; audmad_config.pregain_db = "+0.00"; audmad_config.replaygain.enable = TRUE; audmad_config.replaygain.track_mode = FALSE; @@ -112,6 +116,7 @@ bmp_cfg_db_get_bool(db, "MAD", "use_xing", &audmad_config.use_xing); bmp_cfg_db_get_bool(db, "MAD", "dither", &audmad_config.dither); + bmp_cfg_db_get_bool(db, "MAD", "sjis", &audmad_config.sjis); bmp_cfg_db_get_bool(db, "MAD", "hard_limit", &audmad_config.hard_limit); bmp_cfg_db_get_string(db, "MAD", "pregain_db", @@ -122,15 +127,13 @@ &audmad_config.replaygain.track_mode); bmp_cfg_db_get_string(db, "MAD", "RG.default_db", &audmad_config.replaygain.default_db); - bmp_cfg_db_get_bool(db, "MAD", "title_override", - &audmad_config.title_override); - bmp_cfg_db_get_string(db, "MAD", "id3_format", - &audmad_config.id3_format); bmp_cfg_db_close(db); } - g_static_mutex_init(&mutex); + mad_mutex = g_mutex_new(); + pb_mutex = g_mutex_new(); + mad_cond = g_cond_new(); audmad_config_compute(&audmad_config); } @@ -183,6 +186,8 @@ ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; } +#if 0 +// XXX: can't add remote stream from add URL dialog. temporally disabled. // audacious vfs fast version static int audmad_is_our_fd(char *filename, VFSFile *fin) { @@ -238,6 +243,64 @@ return 1; } +#endif + +// this function will be replaced soon. +static int audmad_is_our_fd(char *filename, VFSFile *fin) +{ + int rtn = 0; + guchar check[4]; + + info.remote = FALSE; //awkward... + +#ifdef DEBUG + g_message("audmad: filename = %s\n", filename); +#endif + + // 0. if url is beginning with http://, take it blindly. + if (!strncasecmp("http://", filename, strlen("http://")) || + !strncasecmp("https://", filename, strlen("https://"))) { + g_message("audmad: remote\n"); + info.remote = TRUE; + return 1; //ours + } + + // 1. check embeded signature + if (fin && vfs_fread(check, 1, 4, fin) == 4) { + /* + * or three bytes are "ID3" + */ + if (mp3_head_check(check)) { + rtn = 1; + } + else if (memcmp(check, "ID3", 3) == 0) { + rtn = 1; + } + else if (memcmp(check, "RIFF", 4) == 0) { + vfs_fseek(fin, 4, SEEK_CUR); + vfs_fread(check, 1, 4, fin); + + if (memcmp(check, "RMP3", 4) == 0) { + rtn = 1; + } + } + } + // 2. exclude files with folloing extensions + if (strcasecmp("flac", filename + strlen(filename) - 4) == 0 || + strcasecmp("mpc", filename + strlen(filename) - 3) == 0 || + strcasecmp("tta", filename + strlen(filename) - 3) == 0) { + rtn = 0; + goto tail; + } + + // 3. if we haven't found any signature, take the files with .mp3 extension. + if (rtn == 0 && strcasecmp("mp3", filename + strlen(filename) - 3) == 0) { + rtn = 1; + } + + tail: + return rtn; +} // audacious vfs version static int audmad_is_our_file(char *filename) @@ -261,9 +324,17 @@ #ifdef DEBUG g_message("f: audmad_stop"); #endif /* DEBUG */ - g_static_mutex_lock(&mutex); + g_mutex_lock(mad_mutex); + info.playback = playback; + g_mutex_unlock(mad_mutex); + if (decode_thread) { + + g_mutex_lock(mad_mutex); info.playback->playing = 0; + g_mutex_unlock(mad_mutex); + g_cond_signal(mad_cond); + #ifdef DEBUG g_message("waiting for thread"); #endif /* DEBUG */ @@ -273,11 +344,13 @@ #endif /* DEBUG */ input_term(&info); decode_thread = NULL; + } - g_static_mutex_unlock(&mutex); +#ifdef DEBUG + g_message("e: audmad_stop"); +#endif /* DEBUG */ } - static void audmad_play_file(InputPlayback *playback) { gboolean rtn; @@ -307,20 +380,28 @@ static void audmad_pause(InputPlayback *playback, short paused) { - mad_plugin->output->pause(paused); + g_mutex_lock(pb_mutex); + info.playback = playback; + g_mutex_unlock(pb_mutex); + playback->output->pause(paused); } static void audmad_seek(InputPlayback *playback, int time) { + g_mutex_lock(pb_mutex); + info.playback = playback; /* xmms gives us the desired seek time in seconds */ info.seek = time; + g_mutex_unlock(pb_mutex); + } /** * Scan the given file or URL. * Fills in the title string and the track length in milliseconds. */ -void audmad_get_song_info(char *url, char **title, int *length) +static void +audmad_get_song_info(char *url, char **title, int *length) { struct mad_info_t myinfo; #ifdef DEBUG @@ -329,19 +410,18 @@ input_init(&myinfo, url); - if (input_get_info(&myinfo, audmad_config.fast_play_time_calc) == TRUE) - { - *title = strdup(myinfo.title); + if (input_get_info(&myinfo, info.remote ? TRUE : audmad_config.fast_play_time_calc) == TRUE) { + if(myinfo.tuple->track_name) + *title = strdup(myinfo.tuple->track_name); + else + *title = strdup(url); *length = mad_timer_count(myinfo.duration, MAD_UNITS_MILLISECONDS); } - else - { + else { *title = strdup(url); *length = -1; } - input_term(&myinfo); - #ifdef DEBUG g_message("e: audmad_get_song_info"); #endif /* DEBUG */ @@ -409,6 +489,7 @@ extern void audmad_get_file_info(char *filename); extern void audmad_configure(); + // tuple stuff static TitleInput *audmad_get_song_tuple(char *filename) { @@ -428,9 +509,28 @@ } #endif - if ((file = vfs_fopen(filename, "rb")) != NULL) { + // can't re-open remote stream + if(info.remote){ tuple = bmp_title_input_new(); + tuple->track_name = vfs_get_metadata(info.infile, "track-name"); + tuple->album_name = vfs_get_metadata(info.infile, "stream-name"); +#ifdef DEBUG + printf("audmad_get_song_tuple: track_name = %s\n", tuple->track_name); + printf("audmad_get_song_tuple: stream_name = %s\n", tuple->album_name); +#endif + tuple->file_name = g_path_get_basename(filename); + tuple->file_path = g_path_get_dirname(filename); + tuple->file_ext = extname(filename); + tuple->length = -1; + tuple->mtime = 0; // this indicates streaming + + return tuple; + } + + if ((file = vfs_fopen(filename, "rb")) != NULL) { + + tuple = bmp_title_input_new(); id3file = id3_file_open(filename, ID3_FILE_MODE_READONLY); if (id3file) { @@ -466,7 +566,7 @@ int length = 0; audmad_get_song_info(filename, &dummy, &length); tuple->length = length; - g_free(dummy); + g_free(dummy); } // track number @@ -485,22 +585,32 @@ tuple->comment = input_id3_get_string(tag, ID3_FRAME_COMMENT); - // mtime -// tuple->mtime = audmad_get_mtime(filename); - } id3_file_close(id3file); } + else { + tuple->file_name = g_path_get_basename(filename); + tuple->file_path = g_path_get_dirname(filename); + tuple->file_ext = extname(filename); + // length + { + char *dummy = NULL; + int length = 0; + audmad_get_song_info(filename, &dummy, &length); + tuple->length = length; + g_free(dummy); + } + } vfs_fclose(file); } #ifdef DEBUG g_message("e: mad: audmad_get_song_tuple"); #endif - tuple->formatter = NULL; //ensure return tuple; } + /** * Retrieve meta-information about URL. * For local files this means ID3 tag etc. @@ -509,10 +619,12 @@ { TitleInput *tuple = NULL; +#ifdef DEBUG g_message("f: mad_get_info: %s", info->filename); - - if (info->remote) +#endif + if (info->remote) { return TRUE; + } tuple = audmad_get_song_tuple(info->filename); info->title = xmms_get_titlestring(audmad_config.title_override == TRUE ? @@ -534,9 +646,11 @@ info->title = g_strdup(pos + 1); else info->title = g_strdup(info->filename); - } + } +#ifdef DEBUG g_message("e: mad_get_info"); +#endif return TRUE; }
--- a/src/madplug/plugin.h Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/plugin.h Tue Feb 06 12:11:42 2007 -0800 @@ -22,13 +22,14 @@ #ifndef AUD_MAD_H #define AUD_MAD_H -//#define DEBUG 1 -#undef DEBUG +#define DEBUG 1 +/* #define DEBUG_INTENSIVELY 1 */ +/* #define DEBUG_DITHER 1 */ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "MADPlug" -#include "config.h" +//#include "config.h" // is it needed when in src tree? #undef PACKAGE #define PACKAGE "audacious-plugins" @@ -39,7 +40,9 @@ #include <unistd.h> #include <audacious/plugin.h> #include <audacious/titlestring.h> +#include <audacious/util.h> #include <audacious/strings.h> +#include <audacious/vfs.h> #include <audacious/i18n.h> #include <id3tag.h> #include <mad.h> @@ -48,8 +51,11 @@ struct mad_info_t { + /* InputPlayback */ InputPlayback *playback; - int seek; + + /* flags */ + gint seek; /**< seek time in seconds */ /* state */ guint current_frame;/**< current mp3 frame */ @@ -94,9 +100,8 @@ VFSFile *infile; gint offset; - gint remote; - struct streamdata_t *sdata; - /**< stream data for remote connections */ + gboolean remote; + }; struct audmad_config_t @@ -105,6 +110,7 @@ gboolean fast_play_time_calc; gboolean use_xing; gboolean dither; + gboolean sjis; gboolean hard_limit; gchar *pregain_db; // gain applied to samples at decoding stage. gdouble pregain_scale; // pow(10, pregain/20) @@ -119,6 +125,11 @@ gchar *id3_format; }; +// gcond +extern GMutex *mad_mutex; +extern GMutex *pb_mutex; +extern GCond *mad_cond; + void audmad_config_compute(struct audmad_config_t *config); // compute scale values from "_db" strings
--- a/src/madplug/replaygain.c Mon Feb 05 12:28:01 2007 -0800 +++ b/src/madplug/replaygain.c Tue Feb 06 12:11:42 2007 -0800 @@ -58,7 +58,7 @@ // Reads APE v2.0 tag ending at current pos in fp -static int ReadAPE2Tag(VFSFile * fp, struct mad_info_t *file) +static int ReadAPE2Tag(VFSFile * fp, struct mad_info_t *file_info) { unsigned long vsize; unsigned long isize; @@ -110,12 +110,12 @@ gdouble *scale = NULL; gchar **str = NULL; if (uncase_strcmp(p, "REPLAYGAIN_ALBUM_GAIN") == 0) { - scale = &file->replaygain_album_scale; - str = &file->replaygain_album_str; + scale = &file_info->replaygain_album_scale; + str = &file_info->replaygain_album_str; } if (uncase_strcmp(p, "REPLAYGAIN_TRACK_GAIN") == 0) { - scale = &file->replaygain_track_scale; - str = &file->replaygain_track_str; + scale = &file_info->replaygain_track_scale; + str = &file_info->replaygain_track_str; } if (str != NULL) { assert(scale != NULL); @@ -125,12 +125,12 @@ //* case of peak info tags : */ str = NULL; if (uncase_strcmp(p, "REPLAYGAIN_TRACK_PEAK") == 0) { - scale = &file->replaygain_track_peak; - str = &file->replaygain_track_peak_str; + scale = &file_info->replaygain_track_peak; + str = &file_info->replaygain_track_peak_str; } if (uncase_strcmp(p, "REPLAYGAIN_ALBUM_PEAK") == 0) { - scale = &file->replaygain_album_peak; - str = &file->replaygain_album_peak_str; + scale = &file_info->replaygain_album_peak; + str = &file_info->replaygain_album_peak_str; } if (str != NULL) { *scale = g_strtod(p + isize + 1, NULL); @@ -143,15 +143,15 @@ -> 1.501*gain dB */ if (uncase_strcmp(p, "MP3GAIN_UNDO") == 0) { - str = &file->mp3gain_undo_str; - scale = &file->mp3gain_undo; + str = &file_info->mp3gain_undo_str; + scale = &file_info->mp3gain_undo; assert(4 < vsize); /* this tag is +left,+right */ *str = g_strndup(p + isize + 1, vsize); *scale = 1.50515 * atoi(*str); } if (uncase_strcmp(p, "MP3GAIN_MINMAX") == 0) { - str = &file->mp3gain_minmax_str; - scale = &file->mp3gain_minmax; + str = &file_info->mp3gain_minmax_str; + scale = &file_info->mp3gain_minmax; *str = g_strndup(p + isize + 1, vsize); assert(4 < vsize); /* this tag is min,max */ *scale = 1.50515 * (atoi((*str) + 4) - atoi(*str)); @@ -194,18 +194,18 @@ return last_match + 1 - 8 + sizeof(struct APETagFooterStruct) - N; } -void input_read_replaygain(struct mad_info_t *file) +void input_read_replaygain(struct mad_info_t *file_info) { - file->has_replaygain = FALSE; - file->replaygain_album_scale = -1; - file->replaygain_track_scale = -1; - file->mp3gain_undo = -77; - file->mp3gain_minmax = -77; + file_info->has_replaygain = FALSE; + file_info->replaygain_album_scale = -1; + file_info->replaygain_track_scale = -1; + file_info->mp3gain_undo = -77; + file_info->mp3gain_minmax = -77; VFSFile *fp; - if ((fp = vfs_fopen(file->filename, "rb")) == NULL) + if ((fp = vfs_fopen(file_info->filename, "rb")) == NULL) return; if (vfs_fseek(fp, 0L, SEEK_END) != 0) { @@ -219,7 +219,7 @@ // try skipping an id3 tag vfs_fseek(fp, pos, SEEK_SET); vfs_fseek(fp, try * -128, SEEK_CUR); - res = ReadAPE2Tag(fp, file); + res = ReadAPE2Tag(fp, file_info); ++try; } if (res != 0) { @@ -229,7 +229,7 @@ if (offs <= 0) { // found ! vfs_fseek(fp, pos, SEEK_SET); vfs_fseek(fp, offs, SEEK_CUR); - res = ReadAPE2Tag(fp, file); + res = ReadAPE2Tag(fp, file_info); if (res != 0) { g_message ("hmpf, was supposed to find a tag.. offs=%d, res=%d", @@ -238,17 +238,16 @@ } } #ifdef DEBUG -//#if 1 if (res == 0) { // got APE tags, show the result printf("RG album scale= %g, RG track scale = %g, in %s \n", - file->replaygain_album_scale, - file->replaygain_track_scale, file->filename); + file_info->replaygain_album_scale, + file_info->replaygain_track_scale, file_info->filename); } #endif - if (file->replaygain_album_scale != -1 - || file->replaygain_track_scale != -1) - file->has_replaygain = TRUE; + if (file_info->replaygain_album_scale != -1 + || file_info->replaygain_track_scale != -1) + file_info->has_replaygain = TRUE; vfs_fclose(fp); }