summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-17 22:23:46 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-17 22:23:46 +0200
commitf7b69992c780be685f014808118a94aef3d87fed (patch)
tree9943c9ad1475f0042c3a5ef9497177f34879fc49
parentf29d6657ba7d4d08967fb369bae2e1b3c033bb53 (diff)
added flags to each track in playlist, which bumped dbpl version to 1.2;
list of file tags is no longer written as metadata string, but as flags; fixed couple of memory leaks; blocked metadata editing in subtracks; blocked metadata editing if playlist file format is less than 1.2;
-rw-r--r--deadbeef.h19
-rw-r--r--junklib.c20
-rw-r--r--playlist.c87
-rw-r--r--playlist.h7
-rw-r--r--plugins.c2
-rw-r--r--plugins/ffap/ffap.c15
-rw-r--r--plugins/ffmpeg/ffmpeg.c1
-rw-r--r--plugins/flac/flac.c13
-rw-r--r--plugins/gtkui/plcommon.c1
-rw-r--r--plugins/gtkui/trkproperties.c4
-rw-r--r--plugins/mpgmad/mpgmad.c5
-rw-r--r--plugins/sndfile/sndfile.c2
-rw-r--r--plugins/vorbis/vorbis.c7
-rw-r--r--plugins/wavpack/wavpack.c3
14 files changed, 166 insertions, 20 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 7ef38310..7b449e18 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -79,6 +79,22 @@ extern "C" {
#define PL_MAIN 0
#define PL_SEARCH 1
+enum {
+ DDB_IS_SUBTRACK = (1<<0), // file is not single-track, might have metainfo in external file
+ DDB_IS_READONLY = (1<<1), // check this flag to block tag writing (e.g. in iso.wv)
+ DDB_HAS_EMBEDDED_CUESHEET = (1<<2),
+
+ DDB_TAG_ID3V1 = (1<<8),
+ DDB_TAG_ID3V22 = (1<<9),
+ DDB_TAG_ID3V23 = (1<<10),
+ DDB_TAG_ID3V24 = (1<<11),
+ DDB_TAG_APEV2 = (1<<12),
+ DDB_TAG_VORBISCOMMENTS = (1<<13),
+ DDB_TAG_CUESHEET = (1<<14),
+
+ DDB_TAG_MASK = 0x0000ff00
+};
+
// playlist item
// these are "public" fields, available to plugins
typedef struct DB_playItem_s {
@@ -392,6 +408,7 @@ typedef struct {
%g genre
%c comment
%r copyright
+ %T tags
more to come
*/
int (*pl_format_title) (DB_playItem_t *it, int idx, char *s, int size, int id, const char *fmt);
@@ -416,6 +433,8 @@ typedef struct {
DB_metaInfo_t * (*pl_get_metadata) (DB_playItem_t *it);
void (*pl_set_item_duration) (DB_playItem_t *it, float duration);
float (*pl_get_item_duration) (DB_playItem_t *it);
+ uint32_t (*pl_get_item_flags) (DB_playItem_t *it);
+ void (*pl_set_item_flags) (DB_playItem_t *it, uint32_t flags);
void (*pl_sort) (int iter, int id, const char *format, int ascending);
void (*pl_items_copy_junk)(DB_playItem_t *from, DB_playItem_t *first, DB_playItem_t *last);
diff --git a/junklib.c b/junklib.c
index c74978f8..625bb657 100644
--- a/junklib.c
+++ b/junklib.c
@@ -555,7 +555,9 @@ junk_id3v1_read (playItem_t *it, DB_FILE *fp) {
pl_add_meta (it, "track", s);
}
- pl_append_meta (it, "tags", "ID3v1");
+ uint32_t f = pl_get_item_flags (it);
+ f |= DDB_TAG_ID3V1;
+ pl_set_item_flags (it, f);
return 0;
}
@@ -782,7 +784,9 @@ junk_apev2_read_full (playItem_t *it, DB_apev2_tag_t *tag_store, DB_FILE *fp) {
uint32_t flags = extract_i32_le (&header[20]);
trace ("APEv%d, size=%d, items=%d, flags=%x\n", version, size, numitems, flags);
- pl_append_meta (it, "tags", "APEv2");
+ uint32_t f = pl_get_item_flags (it);
+ f |= DDB_TAG_APEV2;
+ pl_set_item_flags (it, f);
// now seek to beginning of the tag (exluding header)
if (deadbeef->fseek (fp, -size, SEEK_CUR) == -1) {
@@ -2828,13 +2832,19 @@ junk_id3v2_read_full (playItem_t *it, DB_id3v2_tag_t *tag_store, DB_FILE *fp) {
}
if (it) {
if (version_major == 2) {
- pl_append_meta (it, "tags", "ID3v2.2");
+ uint32_t f = pl_get_item_flags (it);
+ f |= DDB_TAG_ID3V22;
+ pl_set_item_flags (it, f);
}
else if (version_major == 3) {
- pl_append_meta (it, "tags", "ID3v2.3");
+ uint32_t f = pl_get_item_flags (it);
+ f |= DDB_TAG_ID3V23;
+ pl_set_item_flags (it, f);
}
else if (version_major == 4) {
- pl_append_meta (it, "tags", "ID3v2.4");
+ uint32_t f = pl_get_item_flags (it);
+ f |= DDB_TAG_ID3V24;
+ pl_set_item_flags (it, f);
}
}
if (!err && it) {
diff --git a/playlist.c b/playlist.c
index 0d648f3c..49ece821 100644
--- a/playlist.c
+++ b/playlist.c
@@ -47,10 +47,12 @@
#define DEBUG_LOCKING 0
// file format revision history
+// 1.1->1.2 changelog:
+// added flags field
// 1.0->1.1 changelog:
// added sample-accurate seek positions for sub-tracks
#define PLAYLIST_MAJOR_VER 1
-#define PLAYLIST_MINOR_VER 1
+#define PLAYLIST_MINOR_VER 2
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(fmt,...)
@@ -686,6 +688,7 @@ pl_process_cue_track (playItem_t *after, const char *fname, playItem_t **prev, c
if (date[0]) {
pl_add_meta (it, "year", date);
}
+ it->_flags |= DDB_IS_SUBTRACK;
after = pl_insert_item (after, it);
pl_item_unref (it);
*prev = it;
@@ -789,7 +792,12 @@ pl_insert_cue_from_buffer (playItem_t *after, playItem_t *origin, const uint8_t
}
// copy metadata from embedded tags
playItem_t *first = ins ? ins->next[PL_MAIN] : playlist->head[PL_MAIN];
- pl_append_meta (origin, "tags", "cuesheet");
+ uint32_t f = pl_get_item_flags (origin);
+ f |= DDB_TAG_CUESHEET;
+ if (pl_find_meta (origin, "cuesheet")) {
+ f |= DDB_HAS_EMBEDDED_CUESHEET;
+ }
+ pl_set_item_flags (origin, f);
pl_items_copy_junk (origin, first, after);
UNLOCK;
return after;
@@ -1704,6 +1712,9 @@ pl_save (const char *fname) {
if (fwrite (&it->replaygain_track_peak, 1, 4, fp) != 4) {
goto save_fail;
}
+ if (fwrite (&it->_flags, 1, 4, fp) != 4) {
+ goto save_fail;
+ }
int16_t nm = 0;
DB_metaInfo_t *m;
@@ -1822,20 +1833,24 @@ pl_load (const char *fname) {
goto load_fail;
}
if (strncmp (magic, "DBPL", 4)) {
+ trace ("bad signature\n");
goto load_fail;
}
if (fread (&majorver, 1, 1, fp) != 1) {
goto load_fail;
}
if (majorver != PLAYLIST_MAJOR_VER) {
+ trace ("bad majorver=%d\n", majorver);
goto load_fail;
}
if (fread (&minorver, 1, 1, fp) != 1) {
goto load_fail;
}
- if (minorver != PLAYLIST_MINOR_VER) {
+ if (minorver < 1/*PLAYLIST_MINOR_VER*/) {
+ trace ("bad minorver=%d\n", minorver);
goto load_fail;
}
+ trace ("playlist version=%d.%d\n", majorver, minorver);
uint32_t cnt;
if (fread (&cnt, 1, 4, fp) != 4) {
goto load_fail;
@@ -1940,7 +1955,17 @@ pl_load (const char *fname) {
if (it->replaygain_track_peak == 0) {
it->replaygain_track_peak = 1;
}
- // printf ("loading file %s\n", it->fname);
+ if (minorver >= 2) {
+ if (fread (&it->_flags, 1, 4, fp) != 4) {
+ goto load_fail;
+ }
+ }
+ else {
+ if (it->tracknum != 0) {
+ it->_flags |= DDB_IS_READONLY; // to prevent editing metadata in subsongs
+ }
+ }
+
int16_t nm = 0;
if (fread (&nm, 1, 2, fp) != 2) {
goto load_fail;
@@ -2238,6 +2263,7 @@ pl_format_title (playItem_t *it, int idx, char *s, int size, int id, const char
char dur[50];
char elp[50];
char fno[50];
+ char tags[200];
const char *artist = NULL;
const char *album = NULL;
const char *track = NULL;
@@ -2381,7 +2407,44 @@ pl_format_title (playItem_t *it, int idx, char *s, int size, int id, const char
meta = filename;
}
else if (*fmt == 'T') {
- meta = pl_find_meta (it, "tags");
+// meta = pl_find_meta (it, "tags");
+ char *t = tags;
+ char *e = tags + sizeof (tags);
+ int c;
+ *t = 0;
+
+ if (it->_flags & DDB_TAG_ID3V1) {
+ c = snprintf (t, e-t, "ID3v1 | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_ID3V22) {
+ c = snprintf (t, e-t, "ID3v2.2 | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_ID3V23) {
+ c = snprintf (t, e-t, "ID3v2.3 | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_ID3V24) {
+ c = snprintf (t, e-t, "ID3v2.4 | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_APEV2) {
+ c = snprintf (t, e-t, "APEv2 | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_VORBISCOMMENTS) {
+ c = snprintf (t, e-t, "VorbisComments | ");
+ t += c;
+ }
+ if (it->_flags & DDB_TAG_CUESHEET) {
+ c = snprintf (t, e-t, "CueSheet | ");
+ t += c;
+ }
+ if (t != tags) {
+ *(t - 3) = 0;
+ }
+ meta = tags;
}
else {
*s++ = *fmt;
@@ -2814,3 +2877,17 @@ pl_items_copy_junk (playItem_t *from, playItem_t *first, playItem_t *last) {
UNLOCK;
}
+uint32_t
+pl_get_item_flags (playItem_t *it) {
+ LOCK;
+ uint32_t flags = it->_flags;
+ UNLOCK;
+ return flags;
+}
+
+void
+pl_set_item_flags (playItem_t *it, uint32_t flags) {
+ LOCK;
+ it->_flags = flags;
+ UNLOCK;
+}
diff --git a/playlist.h b/playlist.h
index 74434cf5..d3d258a2 100644
--- a/playlist.h
+++ b/playlist.h
@@ -39,6 +39,7 @@ typedef struct playItem_s {
float replaygain_track_peak;
// private area, must not be visible to plugins
float _duration; // in seconds
+ uint32_t _flags;
int _refc;
struct playItem_s *next[PL_MAX_ITERATORS]; // next item in linked list
struct playItem_s *prev[PL_MAX_ITERATORS]; // prev item in linked list
@@ -233,6 +234,12 @@ pl_set_item_duration (playItem_t *it, float duration);
float
pl_get_item_duration (playItem_t *it);
+uint32_t
+pl_get_item_flags (playItem_t *it);
+
+void
+pl_set_item_flags (playItem_t *it, uint32_t flags);
+
// returns number of characters printed, not including trailing 0
// [a]rtist, [t]itle, al[b]um, [l]ength, track[n]umber
int
diff --git a/plugins.c b/plugins.c
index f8d8a5a4..f8765d7c 100644
--- a/plugins.c
+++ b/plugins.c
@@ -135,6 +135,8 @@ static DB_functions_t deadbeef_api = {
.pl_get_for_idx_and_iter = (DB_playItem_t * (*) (int idx, int iter))pl_get_for_idx_and_iter,
.pl_set_item_duration = (void (*) (DB_playItem_t *it, float duration))pl_set_item_duration,
.pl_get_item_duration = (float (*) (DB_playItem_t *it))pl_get_item_duration,
+ .pl_get_item_flags = (uint32_t (*) (DB_playItem_t *it))pl_get_item_flags,
+ .pl_set_item_flags = (void (*) (DB_playItem_t *it, uint32_t flags))pl_set_item_flags,
.pl_sort = pl_sort,
.pl_items_copy_junk = (void (*)(DB_playItem_t *from, DB_playItem_t *first, DB_playItem_t *last))pl_items_copy_junk,
.pl_get_totaltime = pl_get_totaltime,
diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c
index db3a505d..60ba9b18 100644
--- a/plugins/ffap/ffap.c
+++ b/plugins/ffap/ffap.c
@@ -1729,25 +1729,28 @@ ffap_insert (DB_playItem_t *after, const char *fname) {
deadbeef->fclose (fp);
ape_free_ctx (&ape_ctx);
- DB_playItem_t *cue = deadbeef->pl_insert_cue (after, it, ape_ctx.totalsamples, ape_ctx.samplerate);
- if (cue) {
- deadbeef->pl_item_unref (it);
- return cue;
- }
-
// embedded cue
deadbeef->pl_lock ();
const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
+ DB_playItem_t *cue = NULL;
if (cuesheet) {
cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), ape_ctx.totalsamples, ape_ctx.samplerate);
if (cue) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
deadbeef->pl_unlock ();
return cue;
}
}
deadbeef->pl_unlock ();
+ cue = deadbeef->pl_insert_cue (after, it, ape_ctx.totalsamples, ape_ctx.samplerate);
+ if (cue) {
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
+ return cue;
+ }
+
deadbeef->pl_add_meta (it, "title", NULL);
after = deadbeef->pl_insert_item (after, it);
deadbeef->pl_item_unref (it);
diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c
index e157fd45..3030e349 100644
--- a/plugins/ffmpeg/ffmpeg.c
+++ b/plugins/ffmpeg/ffmpeg.c
@@ -504,6 +504,7 @@ ffmpeg_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
if (cue) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
return cue;
}
// now the track is ready, insert into playlist
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index 0de7c7c6..5edb9526 100644
--- a/plugins/flac/flac.c
+++ b/plugins/flac/flac.c
@@ -541,7 +541,10 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str
}
}
deadbeef->pl_add_meta (it, "title", NULL);
- deadbeef->pl_add_meta (it, "tags", "VorbisComments");
+ uint32_t f = deadbeef->pl_get_item_flags (it);
+ f &= ~DDB_TAG_MASK;
+ f |= DDB_TAG_VORBISCOMMENTS;
+ deadbeef->pl_set_item_flags (it, f);
}
}
@@ -663,6 +666,7 @@ cflac_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *last = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), info.totalsamples, info.info.samplerate);
if (last) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (last);
return last;
}
}
@@ -673,6 +677,8 @@ cflac_insert (DB_playItem_t *after, const char *fname) {
if (info.file) {
deadbeef->fclose (info.file);
}
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue_after);
trace ("flac: loaded external cuesheet\n");
return cue_after;
}
@@ -748,7 +754,10 @@ cflac_read_metadata (DB_playItem_t *it) {
FLAC__metadata_iterator_delete (iter);
err = 0;
deadbeef->pl_add_meta (it, "title", NULL);
- deadbeef->pl_add_meta (it, "tags", "VorbisComments");
+ uint32_t f = deadbeef->pl_get_item_flags (it);
+ f &= ~DDB_TAG_MASK;
+ f |= DDB_TAG_VORBISCOMMENTS;
+ deadbeef->pl_set_item_flags (it, f);
error:
if (chain) {
FLAC__metadata_chain_delete (chain);
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
index 483c797f..b46a4926 100644
--- a/plugins/gtkui/plcommon.c
+++ b/plugins/gtkui/plcommon.c
@@ -256,6 +256,7 @@ main_properties_activate (GtkMenuItem *menuitem,
return;
}
show_track_properties_dlg (it);
+ deadbeef->pl_item_unref (it);
}
void
diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c
index 29611262..6f5c9ef6 100644
--- a/plugins/gtkui/trkproperties.c
+++ b/plugins/gtkui/trkproperties.c
@@ -108,7 +108,9 @@ show_track_properties_dlg (DB_playItem_t *it) {
int allow_editing = 0;
- if (deadbeef->is_local_file (it->fname)) {
+ int is_subtrack = deadbeef->pl_get_item_flags (it) & DDB_IS_SUBTRACK;
+
+ if (!is_subtrack && deadbeef->is_local_file (it->fname)) {
// get decoder plugin by id
DB_decoder_t *dec = NULL;
if (it->decoder_id) {
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 9cd51c2d..2dc1a88d 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -1152,6 +1152,10 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
it->fname = strdup (fname);
deadbeef->rewind (fp);
+ // reset tags
+ uint32_t f = deadbeef->pl_get_item_flags (it);
+ f &= ~DDB_TAG_MASK;
+ deadbeef->pl_set_item_flags (it, f);
/*int apeerr = */deadbeef->junk_apev2_read (it, fp);
/*int v2err = */deadbeef->junk_id3v2_read (it, fp);
/*int v1err = */deadbeef->junk_id3v1_read (it, fp);
@@ -1164,6 +1168,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, it, buffer.duration*buffer.samplerate, buffer.samplerate);
if (cue_after) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue_after);
return cue_after;
}
diff --git a/plugins/sndfile/sndfile.c b/plugins/sndfile/sndfile.c
index 09469206..e9467788 100644
--- a/plugins/sndfile/sndfile.c
+++ b/plugins/sndfile/sndfile.c
@@ -235,6 +235,8 @@ sndfile_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
if (cue_after) {
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue_after);
return cue_after;
}
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 6e589c2e..a5a873ab 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -125,7 +125,10 @@ update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc) {
}
}
deadbeef->pl_add_meta (it, "title", NULL);
- deadbeef->pl_add_meta (it, "tags", "VorbisComments");
+ uint32_t f = deadbeef->pl_get_item_flags (it);
+ f &= ~DDB_TAG_MASK;
+ f |= DDB_TAG_VORBISCOMMENTS;
+ deadbeef->pl_set_item_flags (it, f);
}
static DB_fileinfo_t *
@@ -405,6 +408,7 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) {
DB_playItem_t *cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
if (cue) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
return cue;
}
@@ -414,6 +418,7 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) {
cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
if (cue) {
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
return cue;
}
}
diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c
index f3205570..f54f0603 100644
--- a/plugins/wavpack/wavpack.c
+++ b/plugins/wavpack/wavpack.c
@@ -293,6 +293,7 @@ wv_insert (DB_playItem_t *after, const char *fname) {
deadbeef->fclose (fp);
WavpackCloseFile (ctx);
deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (last);
return last;
}
}
@@ -301,6 +302,8 @@ wv_insert (DB_playItem_t *after, const char *fname) {
if (cue_after) {
deadbeef->fclose (fp);
WavpackCloseFile (ctx);
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue_after);
return cue_after;
}