From: Todd Z. <tm...@po...> - 2009-03-17 23:21:51
|
A conversation in #gtkpod the other day reminded me that a good while ago we had a thread¹ about preferring audiofile (aka album) gain over radio (aka track) gain when both are found, as well as preferring gain values stored by mp3gain in the APE tag of a file over the value stored in the LAME tag. Tino Keitel even submitted a patch to implement this, but it seems that it never got applied. So, belatedly, here's that patch again (with some minor changes). For good measure, I've also added support for reading gain values from some commonly used ID3 tags. I believe these are the tags that are used by players like Foobar2k and some others. MPD respects these same tags. As usual, a good, close look over my C code is very welcome. I'd be surprised if I got everything right. I tested with various tags (missing, incomplete, etc.), to hopefully catch any egregious programming errors. ¹ http://sourceforge.net/mailarchive/forum.php?thread_name=20070716115931.GA1099%40dose.home.local&forum_name=gtkpod-questions Tino Keitel (1): Prefer Audiophile (Album) over Radio (Track) gain Todd Zullinger (1): Read ReplayGain values from ID3 tags ChangeLog | 17 +++++ src/mp3file.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 224 insertions(+), 13 deletions(-) -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The more corrupt the state, the more numerous the laws. -- Tacitus, Roman senator and historian (A.D. c.56-c.115) |
From: I s. MJ <is...@gm...> - 2009-03-22 00:38:20
|
Thanks to Todd for pulling together ID3 support for replaygain. It is working well for me. I built upon his patches by adding a couple of options in the prefs file and modifying mp3file.c 1. replaygain_offset: A simple offset value that is added to the replaygain tagged value before being written to the ipod. ReplayGain normalizes to a fixed level (normally 89 dB SPA) and I've found that typical normalization values are -6dB to -10dB (the track is louder than 89dB). Adding an offset effectively changes the reference level, i.e. an offset of 10dB makes the reference level 99 dB SPA and thus the final normalization value range 0dB to +4dB. The tracks are still normalized but play louder. 2. replaygain_mode_album_priority: TRUE causes soundcheck to be set using the album_gain value (formerly known as "audiophile gain"). FALSE causes soundcheck to be set using the track_gain value (formerly known as "radio gain"). The logic test isn't bullet proof. It works for all cases except for one: If we prefer track_gain (album_priority=FALSE) but gd.radio_gain is not set then no soundcheck value is written (it won't fallback to gd.audiophile_gain). I made the assumption that if album gain is set, we can rely on track_gain being set. The following patch should be applied after Todd's previous two patches are applied. See https://sourceforge.net/mailarchive/forum.php?thread_name=20090317232140.GF2 1456%40inocybe.teonanacatl.org&forum_name=gtkpod-devel I changed mp3file.c to be revision 2278a to indicate that this doesn't directly patch the svn code. I would like to build an options dialog in the GUI but glade seems to be buggy, I'll make another post about that. -Greg Index: src/prefs.c =================================================================== --- src/prefs.c (revision 2278) +++ src/prefs.c (working copy) @@ -322,8 +322,12 @@ prefs_set_int("tm_sortcol", TM_COLUMN_TITLE); prefs_set_int("tm_sort", SORT_NONE); - /* New conversion preferences */ - prefs_set_int("conversion_target_format", TARGET_FORMAT_MP3); + /* New conversion preferences */ + prefs_set_int("conversion_target_format", TARGET_FORMAT_MP3); + + /* ReplayGain prefs */ + prefs_set_int("replaygain_offset", 0); + prefs_set_int("replaygain_mode_album_priority", TRUE); } /* Initialize default variable-length list entries */ Index: src/mp3file.c =================================================================== --- src/mp3file.c (revision 2278a) +++ src/mp3file.c (working copy) @@ -193,6 +193,7 @@ #include "itdb.h" #include "file.h" #include "misc.h" +#include "prefs.h" /* MIN_CONSEC_GOOD_FRAMES defines how many consecutive valid MP3 frames @@ -2441,6 +2442,11 @@ gboolean mp3_read_soundcheck (const gchar *path, Track *track) { GainData gd; + gint replaygain_offset; + gint replaygain_mode_album_priority; + + replaygain_offset = prefs_get_int ("replaygain_offset"); + replaygain_mode_album_priority = prefs_get_int ("replaygain_mode_album_priority"); g_return_val_if_fail (track, FALSE); @@ -2451,9 +2457,9 @@ gd.peak_signal_set = FALSE; mp3_get_track_id3_replaygain (path, &gd); - if (gd.audiophile_gain_set) + if (gd.audiophile_gain_set && replaygain_mode_album_priority) { - track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain); + track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain + replaygain_offset); #if LOCALDEBUG printf("using id3 album gain\n"); #endif @@ -2461,7 +2467,7 @@ } if (gd.radio_gain_set) { - track->soundcheck = replaygain_to_soundcheck (gd.radio_gain); + track->soundcheck = replaygain_to_soundcheck (gd.radio_gain + replaygain_offset); #if LOCALDEBUG printf("using id3 radio gain\n"); #endif @@ -2469,9 +2475,9 @@ } mp3_get_track_ape_replaygain (path, &gd); - if (gd.audiophile_gain_set) + if (gd.audiophile_gain_set && replaygain_mode_album_priority) { - track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain); + track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain + replaygain_offset); #if LOCALDEBUG printf("using ape album gain\n"); #endif @@ -2479,7 +2485,7 @@ } if (gd.radio_gain_set) { - track->soundcheck = replaygain_to_soundcheck (gd.radio_gain); + track->soundcheck = replaygain_to_soundcheck (gd.radio_gain + replaygain_offset); #if LOCALDEBUG printf("using ape radio gain\n"); #endif @@ -2487,9 +2493,9 @@ } mp3_get_track_lame_replaygain (path, &gd); - if (gd.audiophile_gain_set) + if (gd.audiophile_gain_set && replaygain_mode_album_priority) { - track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain); + track->soundcheck = replaygain_to_soundcheck (gd.audiophile_gain + replaygain_offset); #if LOCALDEBUG /* This is highly unlikely, lame does not write audiofile gain. */ printf("using lame album gain\n"); @@ -2498,7 +2504,7 @@ } if (gd.radio_gain_set) { - track->soundcheck = replaygain_to_soundcheck (gd.radio_gain); + track->soundcheck = replaygain_to_soundcheck (gd.radio_gain + replaygain_offset); #if LOCALDEBUG printf("using lame radio gain\n"); #endif |
From: Greg <is...@gm...> - 2009-04-01 04:42:54
|
I added a gui interface to configure the ReplayGain preferences that I created in the previous patch. Again, this patch depends on the previous two patches from Todd and the my previous one: http://sourceforge.net/mailarchive/message.php?msg_name=c461c7560903211738r5d099a7ek77b13c0e3d724009%40mail.gmail.com I put the ReplayGain dialog box as a button on the "music" tab of the main prefs dialog. It seemed logical to me but I'm open to other suggestions. It looks like line wrapping may be an issue in this message, let me know if you would like an actual file... Cheers, Greg Index: src/prefsdlg.c =================================================================== --- src/prefsdlg.c (revision 2278) +++ src/prefsdlg.c (working copy) @@ -1294,3 +1294,45 @@ { sort_window_create (); } + +/* + glade callback +*/ +G_MODULE_EXPORT void on_replaygain_clicked (GtkButton *sender, gpointer e) +{ + GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_replaygain_dialog"); + GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_replaygain_dialog"); + GtkWidget *mode_album_radio = gtkpod_xml_get_widget (xml, "mode_album"); + GtkWidget *mode_track_radio = gtkpod_xml_get_widget (xml, "mode_track"); + + gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog)); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "replaygain_offset")), prefs_get_int("replaygain_offset")); + if(prefs_get_int("replaygain_mode_album_priority")) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_album_radio), TRUE); + else + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_track_radio), TRUE); + + glade_xml_signal_autoconnect (xml); + gtk_dialog_run (GTK_DIALOG (dlg)); + gtk_widget_destroy (dlg); + g_object_unref (xml); +} + +/* + glade callback +*/ +G_MODULE_EXPORT void on_replaygain_mode_album_toggled (GtkToggleButton *sender, gpointer e) +{ + gboolean active = gtk_toggle_button_get_active (sender); + + prefs_set_int ("replaygain_mode_album_priority", active); +} + +/* + glade callback +*/ +G_MODULE_EXPORT void on_replaygain_offset_value_changed (GtkSpinButton *sender, gpointer e) +{ + prefs_set_int ("replaygain_offset", gtk_spin_button_get_value_as_int (sender)); +} Index: data/gtkpod.glade =================================================================== --- data/gtkpod.glade (revision 2278) +++ data/gtkpod.glade (working copy) @@ -10440,6 +10440,19 @@ <property name="position">2</property> </packing> </child> + <child> + <widget class="GtkButton" id="replaygain"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">ReplayGain...</property> + <property name="response_id">0</property> + <signal name="clicked" handler="on_replaygain_clicked"/> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> @@ -13654,4 +13667,245 @@ </widget> </child> </widget> + <widget class="GtkDialog" id="prefs_replaygain_dialog"> + <property name="border_width">5</property> + <property name="title" translatable="yes">ReplayGain Preferences</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox19"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox45"> + <property name="visible">True</property> + <property name="border_width">7</property> + <property name="spacing">18</property> + <child> + <widget class="GtkLabel" id="label118"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">The following settings control how gtkpod handles ReplayGain values previously tagged to music files</property> + <property name="wrap">True</property> + <property name="width_chars">63</property> + </widget> + </child> + <child> + <widget class="GtkFrame" id="frame27"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <child> + <widget class="GtkAlignment" id="alignment12"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox45"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label119"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Select the prefered value to use</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment46"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox57"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkRadioButton" id="mode_album"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Album gain (formerly "audiophile gain")</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_replaygain_mode_album_toggled"/> + </widget> + </child> + <child> + <widget class="GtkRadioButton" id="mode_track"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Track gain (formerly "radio gain")</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">mode_album</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label120"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Mode</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame28"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <child> + <widget class="GtkAlignment" id="alignment48"> + <property name="visible">True</property> + <property name="top_padding">6</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="vbox58"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label121"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Select an offset value to add to the ReplayGain value</property> + </widget> + </child> + <child> + <widget class="GtkAlignment" id="alignment49"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkHBox" id="hbox52"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkSpinButton" id="replaygain_offset"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="adjustment">0 -20 20 1 10 10</property> + <property name="climb_rate">1</property> + <signal name="value_changed" handler="on_replaygain_offset_value_changed"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label124"> + <property name="visible">True</property> + <property name="label" translatable="yes">dB</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label125"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Offset</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox51"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label51"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">These setting will only apply to newly added and/or synchronized tracks. This could result in tracks that are normalized to different levels until re-sychronized.</property> + <property name="wrap">True</property> + <property name="width_chars">63</property> + </widget> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area19"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="rg_close"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-close</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> </glade-interface> |
From: Todd Z. <tm...@po...> - 2009-04-12 22:36:36
|
Greg wrote: > I added a gui interface to configure the ReplayGain preferences that > I created in the previous patch. Nice. Sorry I haven't made time to test much yet. I played a bit with it yesterday though. I didn't test all of the various possible scenarios. > I put the ReplayGain dialog box as a button on the "music" tab of > the main prefs dialog. It seemed logical to me but I'm open to other > suggestions. That seems about as reasonable as any other place. You could argue that the metadata tab would be good too. But I'm not sure if either one is significantly better than the other. :) > It looks like line wrapping may be an issue in this message, let me > know if you would like an actual file... The line wrapping was easier to figure out than the tabs which were converted to spaces. Funky cut-and-paste perhaps? ;) I tried to simplify the UI a little, let me know what you think. I'll attach an updated patch series against svn rev 2309. -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A person who smiles in the face of adversity ... probably has a scapegoat. |
From: Dudy K. <ko...@gm...> - 2009-04-13 07:51:43
|
What frame stores replay gain information in ID3? It doesn't seem like part of the standard... On Mon, Apr 13, 2009 at 1:36 AM, Todd Zullinger <tm...@po...> wrote: > Greg wrote: > > I added a gui interface to configure the ReplayGain preferences that > > I created in the previous patch. > > Nice. Sorry I haven't made time to test much yet. I played a bit > with it yesterday though. I didn't test all of the various possible > scenarios. > > > I put the ReplayGain dialog box as a button on the "music" tab of > > the main prefs dialog. It seemed logical to me but I'm open to other > > suggestions. > > That seems about as reasonable as any other place. You could argue > that the metadata tab would be good too. But I'm not sure if either > one is significantly better than the other. :) > > > It looks like line wrapping may be an issue in this message, let me > > know if you would like an actual file... > > The line wrapping was easier to figure out than the tabs which were > converted to spaces. Funky cut-and-paste perhaps? ;) > > I tried to simplify the UI a little, let me know what you think. I'll > attach an updated patch series against svn rev 2309. > > -- > Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp<http://www.pobox.com/%7Etmz/pgp> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > A person who smiles in the face of adversity ... probably has a > scapegoat. > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by: > High Quality Requirements in a Collaborative Environment. > Download a free trial of Rational Requirements Composer Now! > http://p.sf.net/sfu/www-ibm-com > _______________________________________________ > Gtkpod-devel mailing list > Gtk...@li... > https://lists.sourceforge.net/lists/listinfo/gtkpod-devel > > |
From: Todd Z. <tm...@po...> - 2009-04-13 12:07:09
|
Dudy Kohen wrote: > What frame stores replay gain information in ID3? It doesn't seem > like part of the standard... In this case, the support is for TXXX frames formatted as a few players support (mpd, for example). The frames are named replaygain_album_gain and replaygain_track_gain. The ID3v2.4 spec does have an RVA2 frame (and XRVA is often used in ID3v2.3 to hold the same data). Patches are welcome to support those frames as well. Like most things ID3 related, the RVA2 specification is over-engineered and thus widely ignored in the wild. Supporting RVA2/XRVA may well be simpler using taglib though. ;) -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you can't change your mind, do you wonder if you still have one? |
From: Dudy K. <ko...@gm...> - 2009-04-15 09:00:02
|
Support for TXXX has been implemented in the TagLib C bindings. (by me, just now) Is RVA2 a text frame? On Mon, Apr 13, 2009 at 3:06 PM, Todd Zullinger <tm...@po...> wrote: > Dudy Kohen wrote: > > What frame stores replay gain information in ID3? It doesn't seem > > like part of the standard... > > In this case, the support is for TXXX frames formatted as a few > players support (mpd, for example). The frames are named > replaygain_album_gain and replaygain_track_gain. > > The ID3v2.4 spec does have an RVA2 frame (and XRVA is often used in > ID3v2.3 to hold the same data). Patches are welcome to support those > frames as well. Like most things ID3 related, the RVA2 specification > is over-engineered and thus widely ignored in the wild. > > Supporting RVA2/XRVA may well be simpler using taglib though. ;) > > -- > Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp<http://www.pobox.com/%7Etmz/pgp> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > If you can't change your mind, do you wonder if you still have one? > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by: > High Quality Requirements in a Collaborative Environment. > Download a free trial of Rational Requirements Composer Now! > http://p.sf.net/sfu/www-ibm-com > _______________________________________________ > Gtkpod-devel mailing list > Gtk...@li... > https://lists.sourceforge.net/lists/listinfo/gtkpod-devel > > |
From: Todd Z. <tm...@po...> - 2009-04-15 14:58:19
|
Dudy Kohen wrote: > Is RVA2 a text frame? It's described in section 4.11 of http://id3.org/id3v2.4.0-frames. So it's yet another convoluted ID3v2 frame. :) -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The worst thing about history is that every time it repeats itself, the price goes up. -- Pillar |
From: Dudy K. <ko...@gm...> - 2009-04-15 16:07:48
|
Read the spec, I'm not crazy enough to implement this in the C bindings of taglib, but maybe it'll be in 1.6... On Wed, Apr 15, 2009 at 5:58 PM, Todd Zullinger <tm...@po...> wrote: > Dudy Kohen wrote: > > Is RVA2 a text frame? > > It's described in section 4.11 of http://id3.org/id3v2.4.0-frames. So > it's yet another convoluted ID3v2 frame. :) > > -- > Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp<http://www.pobox.com/%7Etmz/pgp> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > The worst thing about history is that every time it repeats itself, > the price goes up. > -- Pillar > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by: > High Quality Requirements in a Collaborative Environment. > Download a free trial of Rational Requirements Composer Now! > http://p.sf.net/sfu/www-ibm-com > _______________________________________________ > Gtkpod-devel mailing list > Gtk...@li... > https://lists.sourceforge.net/lists/listinfo/gtkpod-devel > > |
From: Todd Z. <tm...@po...> - 2009-04-15 16:28:37
|
Dudy Kohen wrote: > Read the spec, I'm not crazy enough to implement this in the C > bindings of taglib, but maybe it'll be in 1.6... Heh. No worries. I do think there's a limit to how much anyone can expect out of ID3 tags. :) -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I have to decide between two equally frightening options. If I wanted to do that, I'd vote. -- Duckman |