summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-06 23:40:33 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-06 23:40:33 +0200
commit4cf0cf6185fffcd26ed4db15a832647d7409d86a (patch)
tree3d19eec29b216536ad09b2dd80b96a3dab75fc26
parent9c6e2108adbcedccee5a2984b1d8ffc57e6b1087 (diff)
moved high level id3v2/apev2/id3v1 tag writer into junklib;
added tag writer to wavpack plugin
-rw-r--r--deadbeef.h9
-rw-r--r--junklib.c334
-rw-r--r--junklib.h3
-rw-r--r--plugins.c1
-rw-r--r--plugins/gtkui/callbacks.h16
-rw-r--r--plugins/gtkui/deadbeef.glade367
-rw-r--r--plugins/gtkui/interface.c100
-rw-r--r--plugins/gtkui/prefwin.c44
-rw-r--r--plugins/mpgmad/mpgmad.c332
-rw-r--r--plugins/wavpack/wavpack.c27
10 files changed, 814 insertions, 419 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 87d7deaf..2162c90c 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -104,6 +104,14 @@ typedef struct DB_metaInfo_s {
} DB_metaInfo_t;
// FIXME: that needs to be in separate plugin
+
+#define JUNK_STRIP_ID3V2 1
+#define JUNK_STRIP_APEV2 2
+#define JUNK_STRIP_ID3V1 4
+#define JUNK_WRITE_ID3V2 8
+#define JUNK_WRITE_APEV2 16
+#define JUNK_WRITE_ID3V1 32
+
typedef struct DB_id3v2_frame_s {
struct DB_id3v2_frame_s *next;
char id[5];
@@ -454,6 +462,7 @@ typedef struct {
const char * (*junk_detect_charset) (const char *s);
int (*junk_recode) (const char *in, int inlen, char *out, int outlen, const char *cs);
int (*junk_iconv) (const char *in, int inlen, char *out, int outlen, const char *cs_in, const char *cs_out);
+ int (*junk_rewrite_tags) (DB_playItem_t *it, uint32_t flags, int id3v2_version, const char *id3v1_encoding);
// vfs
DB_FILE* (*fopen) (const char *fname);
void (*fclose) (DB_FILE *f);
diff --git a/junklib.c b/junklib.c
index 887e243b..698ba8d5 100644
--- a/junklib.c
+++ b/junklib.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include <errno.h>
#include <ctype.h>
+#include <unistd.h>
#include "playlist.h"
#include "utf8.h"
#include "plugins.h"
@@ -2778,3 +2779,336 @@ junk_recode (const char *in, int inlen, char *out, int outlen, const char *cs) {
return junk_iconv (in, inlen, out, outlen, cs, UTF8);
}
+int
+junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const char *id3v1_encoding) {
+ int err = -1;
+ char *buffer = NULL;
+ DB_FILE *fp = NULL;
+ FILE *out = NULL;
+
+ // get options
+ int strip_id3v2 = junk_flags & JUNK_STRIP_ID3V2;
+ int strip_id3v1 = junk_flags & JUNK_STRIP_ID3V1;
+ int strip_apev2 = junk_flags & JUNK_STRIP_APEV2;
+ int write_id3v2 = junk_flags & JUNK_WRITE_ID3V2;
+ int write_id3v1 = junk_flags & JUNK_WRITE_ID3V1;
+ int write_apev2 = junk_flags & JUNK_WRITE_APEV2;
+
+ // find the beginning and the end of audio data
+ fp = deadbeef->fopen (it->fname);
+ if (!fp) {
+ return -1;
+ }
+
+ int fsize = deadbeef->fgetlength (fp);
+ int id3v2_size = 0;
+ int id3v2_start = deadbeef->junk_id3v2_find (fp, &id3v2_size);
+ if (id3v2_start == -1) {
+ id3v2_size = -1;
+ }
+
+ int32_t apev2_size;
+ uint32_t flags, numitems;
+ int apev2_start = deadbeef->junk_apev2_find (fp, &apev2_size, &flags, &numitems);
+ if (apev2_start == -1) {
+ apev2_start = 0;
+ }
+
+ if (!strip_apev2 && !write_apev2) {
+ apev2_start = 0;
+ }
+
+ int id3v1_start = deadbeef->junk_id3v1_find (fp);
+ if (id3v1_start == -1) {
+ id3v1_start = 0;
+ }
+
+ int header = id3v2_start + id3v2_size;
+ int footer = fsize;
+
+ if (id3v1_start > 0) {
+ footer = id3v1_start;
+ }
+ if (apev2_start > 0) {
+ footer = min (footer, apev2_start);
+ }
+
+ // mapping between ddb metadata names and id3v2/apev2 names
+ const char *md[] = {
+ "artist", "TPE1", "Artist",
+ "band", "TPE2", NULL,
+ "disc", "TPOS", "Media",
+ "title", "TIT2", "Title",
+ "album", "TALB", "Album",
+ "copyright", "TCOP", "Copyright",
+ "genre", "TCON", "Genre",
+ "vendor", "TENC", NULL,
+ "performer", "TPE3", NULL,
+ "composer", "TCOM", "Composer",
+ "year", NULL, "Year",
+ "comment", NULL, "Comment",
+ "copyright", NULL, "Copyright",
+ "cuesheet", NULL, "Cuesheet",
+ NULL
+ };
+ // "TRCK" -- special case
+ // "TYER"/"TDRC" -- special case
+
+ // open output file
+ out = NULL;
+ char tmppath[PATH_MAX];
+ snprintf (tmppath, sizeof (tmppath), "%s.temp", it->fname);
+
+ out = fopen (tmppath, "w+b");
+ trace ("will write tags into %s\n", tmppath);
+ if (!out) {
+ fprintf (stderr, "cmp3_write_metadata: failed to open temp file %s\n", tmppath);
+ goto error;
+ }
+
+ DB_id3v2_tag_t id3v2;
+ DB_apev2_tag_t apev2;
+
+ memset (&id3v2, 0, sizeof (id3v2));
+ memset (&apev2, 0, sizeof (apev2));
+
+ if (!strip_id3v2 && !write_id3v2 && id3v2_size > 0) {
+ if (deadbeef->fseek (fp, id3v2_start, SEEK_SET) == -1) {
+ trace ("cmp3_write_metadata: failed to seek to original id3v2 tag position in %s\n", it->fname);
+ goto error;
+ }
+ uint8_t *buf = malloc (id3v2_size);
+ if (!buf) {
+ trace ("cmp3_write_metadata: failed to alloc %d bytes for id3v2 tag\n", id3v2_size);
+ goto error;
+ }
+ if (deadbeef->fread (buf, 1, id3v2_size, fp) != id3v2_size) {
+ trace ("cmp3_write_metadata: failed to read original id3v2 tag from %s\n", it->fname);
+ free (buf);
+ goto error;
+ }
+ if (fwrite (buf, 1, id3v2_size, out) != id3v2_size) {
+ trace ("cmp3_write_metadata: failed to copy original id3v2 tag from %s to temp file\n", it->fname);
+ free (buf);
+ goto error;
+ }
+ free (buf);
+ }
+ else if (write_id3v2) {
+ if (id3v2_size <= 0 || strip_id3v2 || deadbeef->junk_id3v2_read_full (NULL, &id3v2, fp) != 0) {
+ deadbeef->junk_id3v2_free (&id3v2);
+ memset (&id3v2, 0, sizeof (id3v2));
+ id3v2.version[0] = id3v2_version;
+ }
+ // convert to required version
+ while (id3v2.version[0] != id3v2_version) {
+ DB_id3v2_tag_t converted;
+ memset (&converted, 0, sizeof (converted));
+ if (id3v2.version[0] == 2) {
+ if (deadbeef->junk_id3v2_convert_22_to_24 (&id3v2, &converted) != 0) {
+ goto error;
+ }
+ deadbeef->junk_id3v2_free (&id3v2);
+ memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
+ continue;
+ }
+ else if (id3v2.version[0] == 3) {
+ if (deadbeef->junk_id3v2_convert_23_to_24 (&id3v2, &converted) != 0) {
+ goto error;
+ }
+ deadbeef->junk_id3v2_free (&id3v2);
+ memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
+ continue;
+ }
+ else if (id3v2.version[0] == 4) {
+ if (deadbeef->junk_id3v2_convert_24_to_23 (&id3v2, &converted) != 0) {
+ goto error;
+ }
+ deadbeef->junk_id3v2_free (&id3v2);
+ memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
+ continue;
+ }
+ }
+
+ DB_id3v2_frame_t *(*add_frame) (DB_id3v2_tag_t *tag, const char *frame_id, const char *value);
+ if (id3v2_version == 3) {
+ add_frame = deadbeef->junk_id3v2_add_text_frame_23;
+ }
+ else {
+ add_frame = deadbeef->junk_id3v2_add_text_frame_24;
+ }
+
+ // add all basic frames
+ for (int i = 0; md[i]; i += 3) {
+ if (md[i+1]) {
+ const char *val = pl_find_meta (it, md[i]);
+ if (val) {
+ deadbeef->junk_id3v2_remove_frames (&id3v2, md[i+1]);
+ add_frame (&id3v2, md[i+1], val);
+ }
+ }
+ }
+
+ // add tracknumber/totaltracks
+ const char *track = pl_find_meta (it, "track");
+ const char *totaltracks = pl_find_meta (it, "numtracks");
+ if (track && totaltracks) {
+ char s[100];
+ snprintf (s, sizeof (s), "%s/%s", track, totaltracks);
+ junk_id3v2_remove_frames (&id3v2, "TRCK");
+ add_frame (&id3v2, "TRCK", s);
+ }
+ else if (track) {
+ junk_id3v2_remove_frames (&id3v2, "TRCK");
+ add_frame (&id3v2, "TRCK", track);
+ }
+
+ // add year/date
+ const char *year = pl_find_meta (it, "year");
+ if (year) {
+ // FIXME: format check
+ if (id3v2.version[0] == 3) {
+ junk_id3v2_remove_frames (&id3v2, "TYER");
+ add_frame (&id3v2, "TYER", year);
+ }
+ else {
+ junk_id3v2_remove_frames (&id3v2, "TDRC");
+ add_frame (&id3v2, "TDRC", year);
+ }
+ }
+
+ // write tag
+ if (junk_id3v2_write (out, &id3v2) != 0) {
+ trace ("cmp3_write_metadata: failed to write id3v2 tag to %s\n", it->fname)
+ goto error;
+ }
+ }
+
+ // now write audio data
+ buffer = malloc (8192);
+ deadbeef->fseek (fp, header, SEEK_SET);
+ int writesize = fsize;
+ if (footer > 0) {
+ writesize -= (fsize - footer);
+ }
+ writesize -= header;
+ trace ("writesize: %d, id3v1_start: %d, apev2_start: %d, footer: %d\n", writesize, id3v1_start, apev2_start, footer);
+
+ while (writesize > 0) {
+ int rb = min (8192, writesize);
+ rb = deadbeef->fread (buffer, 1, rb, fp);
+ if (rb < 0) {
+ fprintf (stderr, "junk_write_id3v2: error reading input data\n");
+ goto error;
+ }
+ if (fwrite (buffer, 1, rb, out) != rb) {
+ fprintf (stderr, "junk_write_id3v2: error writing output file\n");
+ goto error;
+ }
+ if (rb == 0) {
+ break; // eof
+ }
+ writesize -= rb;
+ }
+
+ if (!write_apev2 && !strip_apev2 && apev2_start != 0) {
+ if (deadbeef->fseek (fp, apev2_start, SEEK_SET) == -1) {
+ trace ("cmp3_write_metadata: failed to seek to original apev2 tag position in %s\n", it->fname);
+ goto error;
+ }
+ uint8_t *buf = malloc (apev2_size);
+ if (!buf) {
+ trace ("cmp3_write_metadata: failed to alloc %d bytes for apev2 tag\n", apev2_size);
+ goto error;
+ }
+ if (deadbeef->fread (buf, 1, apev2_size, fp) != apev2_size) {
+ trace ("cmp3_write_metadata: failed to read original apev2 tag from %s\n", it->fname);
+ free (buf);
+ goto error;
+ }
+ if (fwrite (buf, 1, apev2_size, out) != apev2_size) {
+ trace ("cmp3_write_metadata: failed to copy original apev2 tag from %s to temp file\n", it->fname);
+ free (buf);
+ goto error;
+ }
+ free (buf);
+ }
+ else if (write_apev2) {
+ if (!strip_apev2 || junk_apev2_read_full (NULL, &apev2, fp) != 0) {
+ deadbeef->junk_apev2_free (&apev2);
+ memset (&apev2, 0, sizeof (apev2));
+ }
+ // add all basic frames
+ for (int i = 0; md[i]; i += 3) {
+ if (md[i+2]) {
+ const char *val = pl_find_meta (it, md[i]);
+ if (val) {
+ junk_apev2_remove_frames (&apev2, md[i+2]);
+ junk_apev2_add_text_frame (&apev2, md[i+2], val);
+ }
+ }
+ }
+
+ // add tracknumber/totaltracks
+ const char *track = pl_find_meta (it, "track");
+ const char *totaltracks = pl_find_meta (it, "numtracks");
+ if (track && totaltracks) {
+ char s[100];
+ snprintf (s, sizeof (s), "%s/%s", track, totaltracks);
+ junk_apev2_remove_frames (&apev2, "Track");
+ junk_apev2_add_text_frame (&apev2, "Track", s);
+ }
+ else if (track) {
+ junk_apev2_remove_frames (&apev2, "Track");
+ junk_apev2_add_text_frame (&apev2, "Track", track);
+ }
+
+ // write tag
+ if (deadbeef->junk_apev2_write (out, &apev2, 0, 1) != 0) {
+ trace ("cmp3_write_metadata: failed to write apev2 tag to %s\n", it->fname)
+ goto error;
+ }
+ }
+
+ if (!write_id3v1 && !strip_id3v1 && id3v1_start != 0) {
+ if (deadbeef->fseek (fp, id3v1_start, SEEK_SET) == -1) {
+ trace ("cmp3_write_metadata: failed to seek to original id3v1 tag position in %s\n", it->fname);
+ goto error;
+ }
+ char buf[128];
+ if (deadbeef->fread (buf, 1, 128, fp) != 128) {
+ trace ("cmp3_write_metadata: failed to read original id3v1 tag from %s\n", it->fname);
+ goto error;
+ }
+ if (fwrite (buf, 1, 128, out) != 128) {
+ trace ("cmp3_write_metadata: failed to copy id3v1 tag from %s to temp file\n", it->fname);
+ goto error;
+ }
+ }
+ else if (write_id3v1) {
+ if (junk_id3v1_write (out, it) != 0) {
+ trace ("cmp3_write_metadata: failed to write id3v1 tag to %s\n", it->fname)
+ goto error;
+ }
+ }
+
+ err = 0;
+error:
+ if (fp) {
+ deadbeef->fclose (fp);
+ }
+ if (out) {
+ fclose (out);
+ }
+ if (buffer) {
+ free (buffer);
+ }
+ if (!err) {
+ rename (tmppath, it->fname);
+ }
+ else {
+ unlink (tmppath);
+ }
+ return err;
+}
+
diff --git a/junklib.h b/junklib.h
index b9ac948d..2521fa91 100644
--- a/junklib.h
+++ b/junklib.h
@@ -104,4 +104,7 @@ junk_iconv (const char *in, int inlen, char *out, int outlen, const char *cs_in,
int
junk_recode (const char *in, int inlen, char *out, int outlen, const char *cs);
+int
+junk_rewrite_tags (struct playItem_s *it, uint32_t junk_flags, int id3v2_version, const char *id3v1_encoding);
+
#endif // __JUNKLIB_H
diff --git a/plugins.c b/plugins.c
index 6f5d57ba..ba056b33 100644
--- a/plugins.c
+++ b/plugins.c
@@ -210,6 +210,7 @@ static DB_functions_t deadbeef_api = {
.junk_detect_charset = junk_detect_charset,
.junk_recode = junk_recode,
.junk_iconv = junk_iconv,
+ .junk_rewrite_tags = (int (*) (DB_playItem_t *it, uint32_t flags, int id3v2_version, const char *id3v1_encoding))junk_rewrite_tags,
// vfs
.fopen = vfs_fopen,
.fclose = vfs_fclose,
diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h
index 876bfa2f..d397a0da 100644
--- a/plugins/gtkui/callbacks.h
+++ b/plugins/gtkui/callbacks.h
@@ -913,3 +913,19 @@ on_listview_selected_text_color_set (GtkColorButton *colorbutton,
void
on_listview_cursor_color_set (GtkColorButton *colorbutton,
gpointer user_data);
+
+void
+on_wv_write_apev2_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+on_wv_write_id3v1_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+on_wv_strip_apev2_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
+
+void
+on_wv_strip_id3v1_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade
index 03eb8cf4..3606c124 100644
--- a/plugins/gtkui/deadbeef.glade
+++ b/plugins/gtkui/deadbeef.glade
@@ -3753,102 +3753,248 @@ SOCKS5_HOSTNAME</property>
</child>
<child>
- <widget class="GtkFrame" id="frame6">
+ <widget class="GtkHBox" id="hbox41">
<property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="label_yalign">0.5</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">0</property>
<child>
- <widget class="GtkAlignment" id="alignment4">
+ <widget class="GtkFrame" id="frame6">
<property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">1</property>
- <property name="yscale">1</property>
- <property name="top_padding">0</property>
- <property name="bottom_padding">0</property>
- <property name="left_padding">12</property>
- <property name="right_padding">0</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
- <widget class="GtkVBox" id="vbox20">
- <property name="border_width">12</property>
+ <widget class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">8</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
<child>
- <widget class="GtkHBox" id="hbox37">
+ <widget class="GtkVBox" id="vbox20">
+ <property name="border_width">12</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child>
- <widget class="GtkCheckButton" id="ape_write_id3v2">
+ <widget class="GtkHBox" id="hbox37">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Write ID3v2.4</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_ape_write_id3v2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:42 GMT"/>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkCheckButton" id="ape_write_id3v2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Write ID3v2.4</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_ape_write_id3v2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:42 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="ape_write_apev2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Write APEv2</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_ape_write_apev2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:46 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="ape_write_apev2">
+ <widget class="GtkHBox" id="hbox45">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Write APEv2</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_ape_write_apev2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:46 GMT"/>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkCheckButton" id="ape_strip_id3v2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Strip ID3v2</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_ape_strip_id3v2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:50 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="ape_strip_apev2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Strip APEv2</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_ape_strip_apev2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:54 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
</widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
</child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label70">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;APE&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame7">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
<child>
- <widget class="GtkHBox" id="hbox41">
+ <widget class="GtkVBox" id="vbox_wv">
+ <property name="border_width">12</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child>
- <widget class="GtkCheckButton" id="ape_strip_id3v2">
+ <widget class="GtkHBox" id="hbox44">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Strip ID3v2</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_ape_strip_id3v2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:50 GMT"/>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkCheckButton" id="wv_write_apev2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Write APEv2</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_wv_write_apev2_toggled" last_modification_time="Tue, 06 Apr 2010 19:36:17 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="wv_write_id3v1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Write ID3v1</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_wv_write_id3v1_toggled" last_modification_time="Tue, 06 Apr 2010 19:36:13 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
@@ -3858,17 +4004,50 @@ SOCKS5_HOSTNAME</property>
</child>
<child>
- <widget class="GtkCheckButton" id="ape_strip_apev2">
+ <widget class="GtkHBox" id="hbox43">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Strip APEv2</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_ape_strip_apev2_toggled" last_modification_time="Tue, 30 Mar 2010 20:44:54 GMT"/>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkCheckButton" id="wv_strip_apev2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Strip APEv2</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_wv_strip_apev2_toggled" last_modification_time="Tue, 06 Apr 2010 19:40:53 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="wv_strip_id3v1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Strip ID3v1</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_wv_strip_id3v1_toggled" last_modification_time="Tue, 06 Apr 2010 19:40:57 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
@@ -3877,37 +4056,37 @@ SOCKS5_HOSTNAME</property>
</packing>
</child>
</widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
</child>
</widget>
</child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label70">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;APE&lt;/b&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <child>
+ <widget class="GtkLabel" id="label79">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;WavPack&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
</widget>
<packing>
- <property name="type">label_item</property>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
</widget>
@@ -4287,7 +4466,7 @@ SOCKS5_HOSTNAME</property>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c
index f6fce1d2..b195f329 100644
--- a/plugins/gtkui/interface.c
+++ b/plugins/gtkui/interface.c
@@ -1473,16 +1473,27 @@ create_prefwin (void)
GtkWidget *label71;
GtkWidget *id3v1_encoding;
GtkWidget *label68;
+ GtkWidget *hbox41;
GtkWidget *frame6;
GtkWidget *alignment4;
GtkWidget *vbox20;
GtkWidget *hbox37;
GtkWidget *ape_write_id3v2;
GtkWidget *ape_write_apev2;
- GtkWidget *hbox41;
+ GtkWidget *hbox45;
GtkWidget *ape_strip_id3v2;
GtkWidget *ape_strip_apev2;
GtkWidget *label70;
+ GtkWidget *frame7;
+ GtkWidget *alignment5;
+ GtkWidget *vbox_wv;
+ GtkWidget *hbox44;
+ GtkWidget *wv_write_apev2;
+ GtkWidget *wv_write_id3v1;
+ GtkWidget *hbox43;
+ GtkWidget *wv_strip_apev2;
+ GtkWidget *wv_strip_id3v1;
+ GtkWidget *label79;
GtkWidget *label67;
GtkWidget *hpaned1;
GtkWidget *scrolledwindow2;
@@ -1518,7 +1529,7 @@ create_prefwin (void)
notebook2 = gtk_notebook_new ();
gtk_widget_show (notebook2);
- gtk_box_pack_start (GTK_BOX (dialog_vbox2), notebook2, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox2), notebook2, FALSE, TRUE, 0);
vbox10 = gtk_vbox_new (FALSE, 8);
gtk_widget_show (vbox10);
@@ -2023,9 +2034,13 @@ create_prefwin (void)
gtk_frame_set_label_widget (GTK_FRAME (frame5), label68);
gtk_label_set_use_markup (GTK_LABEL (label68), TRUE);
+ hbox41 = gtk_hbox_new (TRUE, 0);
+ gtk_widget_show (hbox41);
+ gtk_box_pack_start (GTK_BOX (vbox18), hbox41, FALSE, TRUE, 0);
+
frame6 = gtk_frame_new (NULL);
gtk_widget_show (frame6);
- gtk_box_pack_start (GTK_BOX (vbox18), frame6, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox41), frame6, TRUE, TRUE, 0);
gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_NONE);
alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1);
@@ -2050,23 +2065,67 @@ create_prefwin (void)
gtk_widget_show (ape_write_apev2);
gtk_box_pack_start (GTK_BOX (hbox37), ape_write_apev2, FALSE, FALSE, 0);
- hbox41 = gtk_hbox_new (FALSE, 8);
- gtk_widget_show (hbox41);
- gtk_box_pack_start (GTK_BOX (vbox20), hbox41, TRUE, TRUE, 0);
+ hbox45 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox45);
+ gtk_box_pack_start (GTK_BOX (vbox20), hbox45, TRUE, TRUE, 0);
ape_strip_id3v2 = gtk_check_button_new_with_mnemonic ("Strip ID3v2");
gtk_widget_show (ape_strip_id3v2);
- gtk_box_pack_start (GTK_BOX (hbox41), ape_strip_id3v2, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox45), ape_strip_id3v2, FALSE, FALSE, 0);
ape_strip_apev2 = gtk_check_button_new_with_mnemonic ("Strip APEv2");
gtk_widget_show (ape_strip_apev2);
- gtk_box_pack_start (GTK_BOX (hbox41), ape_strip_apev2, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox45), ape_strip_apev2, FALSE, FALSE, 0);
label70 = gtk_label_new ("<b>APE</b>");
gtk_widget_show (label70);
gtk_frame_set_label_widget (GTK_FRAME (frame6), label70);
gtk_label_set_use_markup (GTK_LABEL (label70), TRUE);
+ frame7 = gtk_frame_new (NULL);
+ gtk_widget_show (frame7);
+ gtk_box_pack_start (GTK_BOX (hbox41), frame7, TRUE, TRUE, 0);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_NONE);
+
+ alignment5 = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_widget_show (alignment5);
+ gtk_container_add (GTK_CONTAINER (frame7), alignment5);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment5), 0, 0, 12, 0);
+
+ vbox_wv = gtk_vbox_new (FALSE, 8);
+ gtk_widget_show (vbox_wv);
+ gtk_container_add (GTK_CONTAINER (alignment5), vbox_wv);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox_wv), 12);
+
+ hbox44 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox44);
+ gtk_box_pack_start (GTK_BOX (vbox_wv), hbox44, FALSE, FALSE, 0);
+
+ wv_write_apev2 = gtk_check_button_new_with_mnemonic ("Write APEv2");
+ gtk_widget_show (wv_write_apev2);
+ gtk_box_pack_start (GTK_BOX (hbox44), wv_write_apev2, FALSE, FALSE, 0);
+
+ wv_write_id3v1 = gtk_check_button_new_with_mnemonic ("Write ID3v1");
+ gtk_widget_show (wv_write_id3v1);
+ gtk_box_pack_start (GTK_BOX (hbox44), wv_write_id3v1, FALSE, FALSE, 0);
+
+ hbox43 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox43);
+ gtk_box_pack_start (GTK_BOX (vbox_wv), hbox43, FALSE, FALSE, 0);
+
+ wv_strip_apev2 = gtk_check_button_new_with_mnemonic ("Strip APEv2");
+ gtk_widget_show (wv_strip_apev2);
+ gtk_box_pack_start (GTK_BOX (hbox43), wv_strip_apev2, FALSE, FALSE, 0);
+
+ wv_strip_id3v1 = gtk_check_button_new_with_mnemonic ("Strip ID3v1");
+ gtk_widget_show (wv_strip_id3v1);
+ gtk_box_pack_start (GTK_BOX (hbox43), wv_strip_id3v1, FALSE, FALSE, 0);
+
+ label79 = gtk_label_new ("<b>WavPack</b>");
+ gtk_widget_show (label79);
+ gtk_frame_set_label_widget (GTK_FRAME (frame7), label79);
+ gtk_label_set_use_markup (GTK_LABEL (label79), TRUE);
+
label67 = gtk_label_new ("Tag writer");
gtk_widget_show (label67);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 5), label67);
@@ -2287,6 +2346,18 @@ create_prefwin (void)
g_signal_connect ((gpointer) ape_strip_apev2, "toggled",
G_CALLBACK (on_ape_strip_apev2_toggled),
NULL);
+ g_signal_connect ((gpointer) wv_write_apev2, "toggled",
+ G_CALLBACK (on_wv_write_apev2_toggled),
+ NULL);
+ g_signal_connect ((gpointer) wv_write_id3v1, "toggled",
+ G_CALLBACK (on_wv_write_id3v1_toggled),
+ NULL);
+ g_signal_connect ((gpointer) wv_strip_apev2, "toggled",
+ G_CALLBACK (on_wv_strip_apev2_toggled),
+ NULL);
+ g_signal_connect ((gpointer) wv_strip_id3v1, "toggled",
+ G_CALLBACK (on_wv_strip_id3v1_toggled),
+ NULL);
g_signal_connect ((gpointer) pref_pluginlist, "cursor_changed",
G_CALLBACK (on_pref_pluginlist_cursor_changed),
NULL);
@@ -2396,16 +2467,27 @@ create_prefwin (void)
GLADE_HOOKUP_OBJECT (prefwin, label71, "label71");
GLADE_HOOKUP_OBJECT (prefwin, id3v1_encoding, "id3v1_encoding");
GLADE_HOOKUP_OBJECT (prefwin, label68, "label68");
+ GLADE_HOOKUP_OBJECT (prefwin, hbox41, "hbox41");
GLADE_HOOKUP_OBJECT (prefwin, frame6, "frame6");
GLADE_HOOKUP_OBJECT (prefwin, alignment4, "alignment4");
GLADE_HOOKUP_OBJECT (prefwin, vbox20, "vbox20");
GLADE_HOOKUP_OBJECT (prefwin, hbox37, "hbox37");
GLADE_HOOKUP_OBJECT (prefwin, ape_write_id3v2, "ape_write_id3v2");
GLADE_HOOKUP_OBJECT (prefwin, ape_write_apev2, "ape_write_apev2");
- GLADE_HOOKUP_OBJECT (prefwin, hbox41, "hbox41");
+ GLADE_HOOKUP_OBJECT (prefwin, hbox45, "hbox45");
GLADE_HOOKUP_OBJECT (prefwin, ape_strip_id3v2, "ape_strip_id3v2");
GLADE_HOOKUP_OBJECT (prefwin, ape_strip_apev2, "ape_strip_apev2");
GLADE_HOOKUP_OBJECT (prefwin, label70, "label70");
+ GLADE_HOOKUP_OBJECT (prefwin, frame7, "frame7");
+ GLADE_HOOKUP_OBJECT (prefwin, alignment5, "alignment5");
+ GLADE_HOOKUP_OBJECT (prefwin, vbox_wv, "vbox_wv");
+ GLADE_HOOKUP_OBJECT (prefwin, hbox44, "hbox44");
+ GLADE_HOOKUP_OBJECT (prefwin, wv_write_apev2, "wv_write_apev2");
+ GLADE_HOOKUP_OBJECT (prefwin, wv_write_id3v1, "wv_write_id3v1");
+ GLADE_HOOKUP_OBJECT (prefwin, hbox43, "hbox43");
+ GLADE_HOOKUP_OBJECT (prefwin, wv_strip_apev2, "wv_strip_apev2");
+ GLADE_HOOKUP_OBJECT (prefwin, wv_strip_id3v1, "wv_strip_id3v1");
+ GLADE_HOOKUP_OBJECT (prefwin, label79, "label79");
GLADE_HOOKUP_OBJECT (prefwin, label67, "label67");
GLADE_HOOKUP_OBJECT (prefwin, hpaned1, "hpaned1");
GLADE_HOOKUP_OBJECT (prefwin, scrolledwindow2, "scrolledwindow2");
diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c
index 55a50f41..256debb0 100644
--- a/plugins/gtkui/prefwin.c
+++ b/plugins/gtkui/prefwin.c
@@ -453,6 +453,10 @@ on_preferences_activate (GtkMenuItem *menuitem,
int ape_strip_apev2 = deadbeef->conf_get_int ("ape.strip_apev2", 0);
int ape_write_id3v2 = deadbeef->conf_get_int ("ape.write_id3v2", 0);
int ape_write_apev2 = deadbeef->conf_get_int ("ape.write_apev2", 1);
+ int wv_strip_apev2 = deadbeef->conf_get_int ("wv.strip_apev2", 0);
+ int wv_strip_id3v1 = deadbeef->conf_get_int ("wv.strip_id3v1", 0);
+ int wv_write_apev2 = deadbeef->conf_get_int ("wv.write_apev2", 1);
+ int wv_write_id3v1 = deadbeef->conf_get_int ("wv.write_id3v1", 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "strip_id3v2")), strip_id3v2);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "strip_id3v1")), strip_id3v1);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "strip_apev2")), strip_apev2);
@@ -466,6 +470,11 @@ on_preferences_activate (GtkMenuItem *menuitem,
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "ape_write_apev2")), ape_write_apev2);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "ape_write_id3v2")), ape_write_id3v2);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "wv_strip_id3v1")), wv_strip_id3v1);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "wv_strip_apev2")), wv_strip_apev2);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "wv_write_apev2")), wv_write_apev2);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "wv_write_id3v1")), wv_write_id3v1);
+
gtk_dialog_run (GTK_DIALOG (prefwin));
gtk_widget_destroy (prefwin);
prefwin = NULL;
@@ -566,6 +575,13 @@ on_pref_close_send_to_tray_clicked (GtkButton *button,
}
void
+on_mmb_delete_playlist_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("gtkui.mmb_delete_playlist", gtk_toggle_button_get_active (togglebutton));
+}
+
+void
on_pref_pluginlist_cursor_changed (GtkTreeView *treeview,
gpointer user_data)
{
@@ -950,10 +966,34 @@ on_ape_strip_apev2_toggled (GtkToggleButton *togglebutton,
deadbeef->conf_set_int ("ape.strip_apev2", gtk_toggle_button_get_active (togglebutton));
}
+
void
-on_mmb_delete_playlist_toggled (GtkToggleButton *togglebutton,
+on_wv_write_apev2_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
- deadbeef->conf_set_int ("gtkui.mmb_delete_playlist", gtk_toggle_button_get_active (togglebutton));
+ deadbeef->conf_set_int ("wv.write_apev2", gtk_toggle_button_get_active (togglebutton));
+}
+
+
+void
+on_wv_write_id3v1_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("wv.write_id3v1", gtk_toggle_button_get_active (togglebutton));
+}
+
+void
+on_wv_strip_apev2_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("wv.strip_apev2", gtk_toggle_button_get_active (togglebutton));
+}
+
+
+void
+on_wv_strip_id3v1_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("wv.strip_id3v1", gtk_toggle_button_get_active (togglebutton));
}
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 98b20e85..9a6e4def 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -1189,335 +1189,41 @@ cmp3_read_metadata (DB_playItem_t *it) {
int
cmp3_write_metadata (DB_playItem_t *it) {
- int err = -1;
- char *buffer = NULL;
- DB_FILE *fp = NULL;
- FILE *out = NULL;
-
// get options
+
int strip_id3v2 = deadbeef->conf_get_int ("mp3.strip_id3v2", 0);
int strip_id3v1 = deadbeef->conf_get_int ("mp3.strip_id3v2", 0);
int strip_apev2 = deadbeef->conf_get_int ("mp3.strip_apev2", 0);
int write_id3v2 = deadbeef->conf_get_int ("mp3.write_id3v2", 1);
int write_id3v1 = deadbeef->conf_get_int ("mp3.write_id3v1", 0);
int write_apev2 = deadbeef->conf_get_int ("mp3.write_apev2", 1);
- int id3v2_version = deadbeef->conf_get_int ("mp3.id3v2_version", 3);
- if (id3v2_version != 3 && id3v2_version != 4) {
- id3v2_version = 3;
- }
- const char *id3v1_encoding = deadbeef->conf_get_str ("mp3.id3v1_encoding", "iso8859-1");
-
- // find the beginning and the end of audio data
- fp = deadbeef->fopen (it->fname);
- if (!fp) {
- return -1;
- }
-
- int fsize = deadbeef->fgetlength (fp);
- int id3v2_size = 0;
- int id3v2_start = deadbeef->junk_id3v2_find (fp, &id3v2_size);
- if (id3v2_start == -1) {
- id3v2_size = -1;
- }
- int32_t apev2_size;
- uint32_t flags, numitems;
- int apev2_start = deadbeef->junk_apev2_find (fp, &apev2_size, &flags, &numitems);
- if (apev2_start == -1) {
- apev2_start = 0;
+ uint32_t junk_flags = 0;
+ if (strip_id3v2) {
+ junk_flags |= JUNK_STRIP_ID3V2;
}
-
- if (!strip_apev2 && !write_apev2) {
- apev2_start = 0;
+ if (strip_id3v1) {
+ junk_flags |= JUNK_STRIP_ID3V1;
}
-
- int id3v1_start = deadbeef->junk_id3v1_find (fp);
- if (id3v1_start == -1) {
- id3v1_start = 0;
+ if (strip_apev2) {
+ junk_flags |= JUNK_STRIP_APEV2;
}
-
- int header = id3v2_start + id3v2_size;
- int footer = fsize;
-
- if (id3v1_start > 0) {
- footer = id3v1_start;
+ if (write_id3v2) {
+ junk_flags |= JUNK_WRITE_ID3V2;
}
- if (apev2_start > 0) {
- footer = min (footer, apev2_start);
+ if (write_id3v1) {
+ junk_flags |= JUNK_WRITE_ID3V1;
}
-
- // mapping between ddb metadata names and id3v2/apev2 names
- const char *md[] = {
- "artist", "TPE1", "Artist",
- "band", "TPE2", NULL,
- "disc", "TPOS", "Media",
- "title", "TIT2", "Title",
- "album", "TALB", "Album",
- "copyright", "TCOP", "Copyright",
- "genre", "TCON", "Genre",
- "vendor", "TENC", NULL,
- "performer", "TPE3", NULL,
- "composer", "TCOM", "Composer",
- "year", NULL, "Year",
- "comment", NULL, "Comment",
- "copyright", NULL, "Copyright",
- "cuesheet", NULL, "Cuesheet",
- NULL
- };
- // "TRCK" -- special case
- // "TYER"/"TDRC" -- special case
-
- // open output file
- out = NULL;
- char tmppath[PATH_MAX];
- snprintf (tmppath, sizeof (tmppath), "%s.temp.mp3", it->fname);
-
- out = fopen (tmppath, "w+b");
- trace ("will write tags into %s\n", tmppath);
- if (!out) {
- fprintf (stderr, "cmp3_write_metadata: failed to open temp file %s\n", tmppath);
- goto error;
+ if (write_apev2) {
+ junk_flags |= JUNK_WRITE_APEV2;
}
- DB_id3v2_tag_t id3v2;
- DB_apev2_tag_t apev2;
-
- memset (&id3v2, 0, sizeof (id3v2));
- memset (&apev2, 0, sizeof (apev2));
-
- if (!strip_id3v2 && !write_id3v2 && id3v2_size > 0) {
- if (deadbeef->fseek (fp, id3v2_start, SEEK_SET) == -1) {
- trace ("cmp3_write_metadata: failed to seek to original id3v2 tag position in %s\n", it->fname);
- goto error;
- }
- uint8_t *buf = malloc (id3v2_size);
- if (!buf) {
- trace ("cmp3_write_metadata: failed to alloc %d bytes for id3v2 tag\n", id3v2_size);
- goto error;
- }
- if (deadbeef->fread (buf, 1, id3v2_size, fp) != id3v2_size) {
- trace ("cmp3_write_metadata: failed to read original id3v2 tag from %s\n", it->fname);
- free (buf);
- goto error;
- }
- if (fwrite (buf, 1, id3v2_size, out) != id3v2_size) {
- trace ("cmp3_write_metadata: failed to copy original id3v2 tag from %s to temp file\n", it->fname);
- free (buf);
- goto error;
- }
- free (buf);
- }
- else if (write_id3v2) {
- if (id3v2_size <= 0 || strip_id3v2 || deadbeef->junk_id3v2_read_full (NULL, &id3v2, fp) != 0) {
- deadbeef->junk_id3v2_free (&id3v2);
- memset (&id3v2, 0, sizeof (id3v2));
- id3v2.version[0] = id3v2_version;
- }
- // convert to required version
- while (id3v2.version[0] != id3v2_version) {
- DB_id3v2_tag_t converted;
- memset (&converted, 0, sizeof (converted));
- if (id3v2.version[0] == 2) {
- if (deadbeef->junk_id3v2_convert_22_to_24 (&id3v2, &converted) != 0) {
- goto error;
- }
- deadbeef->junk_id3v2_free (&id3v2);
- memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
- continue;
- }
- else if (id3v2.version[0] == 3) {
- if (deadbeef->junk_id3v2_convert_23_to_24 (&id3v2, &converted) != 0) {
- goto error;
- }
- deadbeef->junk_id3v2_free (&id3v2);
- memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
- continue;
- }
- else if (id3v2.version[0] == 4) {
- if (deadbeef->junk_id3v2_convert_24_to_23 (&id3v2, &converted) != 0) {
- goto error;
- }
- deadbeef->junk_id3v2_free (&id3v2);
- memcpy (&id3v2, &converted, sizeof (DB_id3v2_tag_t));
- continue;
- }
- }
-
- DB_id3v2_frame_t *(*add_frame) (DB_id3v2_tag_t *tag, const char *frame_id, const char *value);
- if (id3v2_version == 3) {
- add_frame = deadbeef->junk_id3v2_add_text_frame_23;
- }
- else {
- add_frame = deadbeef->junk_id3v2_add_text_frame_24;
- }
-
- // add all basic frames
- for (int i = 0; md[i]; i += 3) {
- if (md[i+1]) {
- const char *val = deadbeef->pl_find_meta (it, md[i]);
- if (val) {
- deadbeef->junk_id3v2_remove_frames (&id3v2, md[i+1]);
- add_frame (&id3v2, md[i+1], val);
- }
- }
- }
-
- // add tracknumber/totaltracks
- const char *track = deadbeef->pl_find_meta (it, "track");
- const char *totaltracks = deadbeef->pl_find_meta (it, "numtracks");
- if (track && totaltracks) {
- char s[100];
- snprintf (s, sizeof (s), "%s/%s", track, totaltracks);
- deadbeef->junk_id3v2_remove_frames (&id3v2, "TRCK");
- add_frame (&id3v2, "TRCK", s);
- }
- else if (track) {
- deadbeef->junk_id3v2_remove_frames (&id3v2, "TRCK");
- add_frame (&id3v2, "TRCK", track);
- }
-
- // add year/date
- const char *year = deadbeef->pl_find_meta (it, "year");
- if (year) {
- // FIXME: format check
- if (id3v2.version[0] == 3) {
- deadbeef->junk_id3v2_remove_frames (&id3v2, "TYER");
- add_frame (&id3v2, "TYER", year);
- }
- else {
- deadbeef->junk_id3v2_remove_frames (&id3v2, "TDRC");
- add_frame (&id3v2, "TDRC", year);
- }
- }
-
- // write tag
- if (deadbeef->junk_id3v2_write (out, &id3v2) != 0) {
- trace ("cmp3_write_metadata: failed to write id3v2 tag to %s\n", it->fname)
- goto error;
- }
- }
-
- // now write audio data
- buffer = malloc (8192);
- deadbeef->fseek (fp, header, SEEK_SET);
- int writesize = fsize;
- if (footer > 0) {
- writesize -= (fsize - footer);
- }
- writesize -= header;
- trace ("writesize: %d, id3v1_start: %d, apev2_start: %d, footer: %d\n", writesize, id3v1_start, apev2_start, footer);
-
- while (writesize > 0) {
- int rb = min (8192, writesize);
- rb = deadbeef->fread (buffer, 1, rb, fp);
- if (rb < 0) {
- fprintf (stderr, "junk_write_id3v2: error reading input data\n");
- goto error;
- }
- if (fwrite (buffer, 1, rb, out) != rb) {
- fprintf (stderr, "junk_write_id3v2: error writing output file\n");
- goto error;
- }
- if (rb == 0) {
- break; // eof
- }
- writesize -= rb;
- }
-
- if (!write_apev2 && !strip_apev2 && apev2_start != 0) {
- if (deadbeef->fseek (fp, apev2_start, SEEK_SET) == -1) {
- trace ("cmp3_write_metadata: failed to seek to original apev2 tag position in %s\n", it->fname);
- goto error;
- }
- uint8_t *buf = malloc (apev2_size);
- if (!buf) {
- trace ("cmp3_write_metadata: failed to alloc %d bytes for apev2 tag\n", apev2_size);
- goto error;
- }
- if (deadbeef->fread (buf, 1, apev2_size, fp) != apev2_size) {
- trace ("cmp3_write_metadata: failed to read original apev2 tag from %s\n", it->fname);
- free (buf);
- goto error;
- }
- if (fwrite (buf, 1, apev2_size, out) != apev2_size) {
- trace ("cmp3_write_metadata: failed to copy original apev2 tag from %s to temp file\n", it->fname);
- free (buf);
- goto error;
- }
- free (buf);
- }
- else if (write_apev2) {
- if (!strip_apev2 || deadbeef->junk_apev2_read_full (NULL, &apev2, fp) != 0) {
- deadbeef->junk_apev2_free (&apev2);
- memset (&apev2, 0, sizeof (apev2));
- }
- // add all basic frames
- for (int i = 0; md[i]; i += 3) {
- if (md[i+2]) {
- const char *val = deadbeef->pl_find_meta (it, md[i]);
- if (val) {
- deadbeef->junk_apev2_remove_frames (&apev2, md[i+2]);
- deadbeef->junk_apev2_add_text_frame (&apev2, md[i+2], val);
- }
- }
- }
-
- // add tracknumber/totaltracks
- const char *track = deadbeef->pl_find_meta (it, "track");
- const char *totaltracks = deadbeef->pl_find_meta (it, "numtracks");
- if (track && totaltracks) {
- char s[100];
- snprintf (s, sizeof (s), "%s/%s", track, totaltracks);
- deadbeef->junk_apev2_remove_frames (&apev2, "Track");
- deadbeef->junk_apev2_add_text_frame (&apev2, "Track", s);
- }
- else if (track) {
- deadbeef->junk_apev2_remove_frames (&apev2, "Track");
- deadbeef->junk_apev2_add_text_frame (&apev2, "Track", track);
- }
-
- // write tag
- if (deadbeef->junk_apev2_write (out, &apev2, 0, 1) != 0) {
- trace ("cmp3_write_metadata: failed to write apev2 tag to %s\n", it->fname)
- goto error;
- }
- }
-
- if (!write_id3v1 && !strip_id3v1 && id3v1_start != 0) {
- if (deadbeef->fseek (fp, id3v1_start, SEEK_SET) == -1) {
- trace ("cmp3_write_metadata: failed to seek to original id3v1 tag position in %s\n", it->fname);
- goto error;
- }
- char buf[128];
- if (deadbeef->fread (buf, 1, 128, fp) != 128) {
- trace ("cmp3_write_metadata: failed to read original id3v1 tag from %s\n", it->fname);
- goto error;
- }
- if (fwrite (buf, 1, 128, out) != 128) {
- trace ("cmp3_write_metadata: failed to copy id3v1 tag from %s to temp file\n", it->fname);
- goto error;
- }
- }
- else if (write_id3v1) {
- if (deadbeef->junk_id3v1_write (out, it) != 0) {
- trace ("cmp3_write_metadata: failed to write id3v1 tag to %s\n", it->fname)
- goto error;
- }
- }
-
- err = 0;
-error:
- if (fp) {
- deadbeef->fclose (fp);
- }
- if (out) {
- fclose (out);
- }
- if (buffer) {
- free (buffer);
+ int id3v2_version = deadbeef->conf_get_int ("mp3.id3v2_version", 3);
+ if (id3v2_version != 3 && id3v2_version != 4) {
+ id3v2_version = 3;
}
-// unlink (tmppath);
- return err;
+ const char *id3v1_encoding = deadbeef->conf_get_str ("mp3.id3v1_encoding", "iso8859-1");
+ return deadbeef->junk_rewrite_tags (it, junk_flags, id3v2_version, id3v1_encoding);
}
static const char *exts[] = {
diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c
index ffbd1bd1..f3205570 100644
--- a/plugins/wavpack/wavpack.c
+++ b/plugins/wavpack/wavpack.c
@@ -330,7 +330,31 @@ wv_read_metadata (DB_playItem_t *it) {
return 0;
}
-static const char * exts[] = { "wv", NULL };
+int
+wv_write_metadata (DB_playItem_t *it) {
+ int strip_apev2 = deadbeef->conf_get_int ("wv.strip_apev2", 0);
+ int strip_id3v1 = deadbeef->conf_get_int ("wv.strip_id3v1", 0);
+ int write_apev2 = deadbeef->conf_get_int ("wv.write_apev2", 1);
+ int write_id3v1 = deadbeef->conf_get_int ("wv.write_id3v1", 0);
+
+ uint32_t junk_flags = 0;
+ if (strip_id3v1) {
+ junk_flags |= JUNK_STRIP_ID3V1;
+ }
+ if (strip_apev2) {
+ junk_flags |= JUNK_STRIP_APEV2;
+ }
+ if (write_id3v1) {
+ junk_flags |= JUNK_WRITE_ID3V1;
+ }
+ if (write_apev2) {
+ junk_flags |= JUNK_WRITE_APEV2;
+ }
+
+ return deadbeef->junk_rewrite_tags (it, junk_flags, 0, NULL);
+}
+
+static const char *exts[] = { "wv", NULL };
static const char *filetypes[] = { "wv", NULL };
// define plugin interface
@@ -353,6 +377,7 @@ static DB_decoder_t plugin = {
.seek_sample = wv_seek_sample,
.insert = wv_insert,
.read_metadata = wv_read_metadata,
+ .write_metadata = wv_write_metadata,
.exts = exts,
.filetypes = filetypes
};