diff options
-rw-r--r-- | deadbeef.h | 19 | ||||
-rw-r--r-- | junklib.c | 20 | ||||
-rw-r--r-- | playlist.c | 87 | ||||
-rw-r--r-- | playlist.h | 7 | ||||
-rw-r--r-- | plugins.c | 2 | ||||
-rw-r--r-- | plugins/ffap/ffap.c | 15 | ||||
-rw-r--r-- | plugins/ffmpeg/ffmpeg.c | 1 | ||||
-rw-r--r-- | plugins/flac/flac.c | 13 | ||||
-rw-r--r-- | plugins/gtkui/plcommon.c | 1 | ||||
-rw-r--r-- | plugins/gtkui/trkproperties.c | 4 | ||||
-rw-r--r-- | plugins/mpgmad/mpgmad.c | 5 | ||||
-rw-r--r-- | plugins/sndfile/sndfile.c | 2 | ||||
-rw-r--r-- | plugins/vorbis/vorbis.c | 7 | ||||
-rw-r--r-- | plugins/wavpack/wavpack.c | 3 |
14 files changed, 166 insertions, 20 deletions
@@ -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); @@ -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) { @@ -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; +} @@ -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 @@ -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; } |