From 2d0b00f6bbd326790c053961ccec07106cb172c7 Mon Sep 17 00:00:00 2001 From: waker Date: Wed, 9 Mar 2011 11:38:38 +0100 Subject: moved most of track properties from playItem struct to metadata implemented track properties with multiple selection --- deadbeef.h | 23 ++- junklib.c | 46 +++--- playlist.c | 312 +++++++++++++++++++++++++--------------- playlist.h | 36 +++-- plugins.c | 17 ++- plugins/aac/aac.c | 26 ++-- plugins/adplug/adplug-db.cpp | 12 +- plugins/cdda/cdda.c | 12 +- plugins/dca/dcaplug.c | 8 +- plugins/ffap/ffap.c | 8 +- plugins/ffmpeg/ffmpeg.c | 26 ++-- plugins/flac/flac.c | 24 ++-- plugins/gme/cgme.c | 18 ++- plugins/gtkui/gtkui.c | 2 +- plugins/gtkui/mainplaylist.c | 6 +- plugins/gtkui/plcommon.c | 11 +- plugins/gtkui/trkproperties.c | 142 +++++++++--------- plugins/mpgmad/mpgmad.c | 16 +-- plugins/musepack/musepack.c | 30 ++-- plugins/notify/notify.c | 2 +- plugins/shellexec/shellexec.c | 2 +- plugins/sid/csid.cpp | 12 +- plugins/sndfile/sndfile.c | 8 +- plugins/tta/ttaplug.c | 16 +-- plugins/vorbis/vorbis.c | 35 +++-- plugins/vtx/vtx.c | 9 +- plugins/wavpack/wavpack.c | 12 +- plugins/wildmidi/wildmidiplug.c | 8 +- replaygain.c | 140 +++++++----------- replaygain.h | 3 + streamer.c | 44 +++--- 31 files changed, 555 insertions(+), 511 deletions(-) diff --git a/deadbeef.h b/deadbeef.h index 965625ef..d9fb9d81 100644 --- a/deadbeef.h +++ b/deadbeef.h @@ -104,19 +104,12 @@ enum { // playlist item // these are "public" fields, available to plugins typedef struct DB_playItem_s { - char *fname; // full pathname - const char *decoder_id; - int tracknum; // used for stuff like sid, nsf, cue (will be ignored by most codecs) int startsample; // start sample of track, or -1 for auto int endsample; // end sample of track, or -1 for auto int shufflerating; // sort order for shuffle mode float playtime; // actual playback time of this track in seconds time_t started_timestamp; // result of calling time(NULL) const char *filetype; // e.g. MP3 or OGG - float replaygain_album_gain; - float replaygain_album_peak; - float replaygain_track_gain; - float replaygain_track_peak; } DB_playItem_t; typedef struct DB_metaInfo_s { @@ -250,6 +243,14 @@ enum pl_column_t { DB_COLUMN_ID_MAX }; +// replaygain constants +enum { + DDB_REPLAYGAIN_ALBUMGAIN, + DDB_REPLAYGAIN_ALBUMPEAK, + DDB_REPLAYGAIN_TRACKGAIN, + DDB_REPLAYGAIN_TRACKPEAK, +}; + // message ids for communicating with player enum { M_SONGFINISHED, @@ -371,6 +372,7 @@ typedef struct { void (*plt_unlock) (void); // playlist tracks access DB_playItem_t * (*pl_item_alloc) (void); + DB_playItem_t * (*pl_item_alloc_init) (const char *fname, const char *decoder_id); void (*pl_item_ref) (DB_playItem_t *it); void (*pl_item_unref) (DB_playItem_t *it); void (*pl_item_copy) (DB_playItem_t *out, DB_playItem_t *in); @@ -441,8 +443,12 @@ typedef struct { // metainfo void (*pl_add_meta) (DB_playItem_t *it, const char *key, const char *value); void (*pl_append_meta) (DB_playItem_t *it, const char *key, const char *value); + void (*pl_set_meta_int) (DB_playItem_t *it, const char *key, int value); + void (*pl_set_meta_float) (DB_playItem_t *it, const char *key, float value); // must be used from within explicit pl_lock/unlock block const char *(*pl_find_meta) (DB_playItem_t *it, const char *key); + int (*pl_find_meta_int) (DB_playItem_t *it, const char *key, int def); + float (*pl_find_meta_float) (DB_playItem_t *it, const char *key, float def); void (*pl_replace_meta) (DB_playItem_t *it, const char *key, const char *value); void (*pl_delete_all_meta) (DB_playItem_t *it); DB_metaInfo_t * (*pl_get_metadata) (DB_playItem_t *it); @@ -452,6 +458,9 @@ typedef struct { 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); + // idx is one of DDB_REPLAYGAIN_* constants + void (*pl_set_item_replaygain) (DB_playItem_t *it, int idx, float value); + float (*pl_get_item_replaygain) (DB_playItem_t *it, int idx); // playqueue support int (*pl_playqueue_push) (DB_playItem_t *it); diff --git a/junklib.c b/junklib.c index 0204dfbf..87dd59f6 100644 --- a/junklib.c +++ b/junklib.c @@ -1110,19 +1110,19 @@ junk_apev2_add_frame (playItem_t *it, DB_apev2_tag_t *tag_store, DB_apev2_frame_ if (!frame_mapping[m]) { if (!strncasecmp (key, "replaygain_album_gain", 21)) { - it->replaygain_album_gain = atof (value); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (value)); trace ("album_gain=%s\n", value); } else if (!strncasecmp (key, "replaygain_album_peak", 21)) { - it->replaygain_album_peak = atof (value); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (value)); trace ("album_peak=%s\n", value); } else if (!strncasecmp (key, "replaygain_track_gain", 21)) { - it->replaygain_track_gain = atof (value); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (value)); trace ("track_gain=%s\n", value); } else if (!strncasecmp (key, "replaygain_track_peak", 21)) { - it->replaygain_track_peak = atof (value); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (value)); trace ("track_peak=%s\n", value); } else { @@ -2802,16 +2802,16 @@ junk_id3v2_load_txx (int version_major, playItem_t *it, uint8_t *readptr, int sy } if (!strcasecmp (txx, "replaygain_album_gain")) { - it->replaygain_album_gain = atof (val); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (val)); } else if (!strcasecmp (txx, "replaygain_album_peak")) { - it->replaygain_album_peak = atof (val); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (val)); } else if (!strcasecmp (txx, "replaygain_track_gain")) { - it->replaygain_track_gain = atof (val); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (val)); } else if (!strcasecmp (txx, "replaygain_track_peak")) { - it->replaygain_track_peak = atof (val); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (val)); } else { pl_append_meta (it, txx, val); @@ -3348,7 +3348,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const int write_apev2 = junk_flags & JUNK_WRITE_APEV2; // find the beginning and the end of audio data - fp = deadbeef->fopen (it->fname); + fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } @@ -3398,7 +3398,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const // open output file out = NULL; char tmppath[PATH_MAX]; - snprintf (tmppath, sizeof (tmppath), "%s.temp", it->fname); + snprintf (tmppath, sizeof (tmppath), "%s.temp", deadbeef->pl_find_meta (it, ":URI")); out = fopen (tmppath, "w+b"); trace ("will write tags into %s\n", tmppath); @@ -3415,7 +3415,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const 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); + trace ("cmp3_write_metadata: failed to seek to original id3v2 tag position in %s\n", deadbeef->pl_find_meta (it, ":URI")); goto error; } uint8_t *buf = malloc (id3v2_size); @@ -3424,12 +3424,12 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const 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); + trace ("cmp3_write_metadata: failed to read original id3v2 tag from %s\n", deadbeef->pl_find_meta (it, ":URI")); 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); + trace ("cmp3_write_metadata: failed to copy original id3v2 tag from %s to temp file\n", deadbeef->pl_find_meta (it, ":URI")); free (buf); goto error; } @@ -3532,7 +3532,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const // write tag if (junk_id3v2_write (out, &id3v2) != 0) { - trace ("cmp3_write_metadata: failed to write id3v2 tag to %s\n", it->fname) + trace ("cmp3_write_metadata: failed to write id3v2 tag to %s\n", deadbeef->pl_find_meta (it, ":URI")) goto error; } } @@ -3567,7 +3567,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const if (!write_apev2 && !strip_apev2 && apev2_start != 0) { trace ("copying original apev2 tag\n"); 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); + trace ("cmp3_write_metadata: failed to seek to original apev2 tag position in %s\n", deadbeef->pl_find_meta (it, ":URI")); goto error; } uint8_t *buf = malloc (apev2_size); @@ -3576,12 +3576,12 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const 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); + trace ("cmp3_write_metadata: failed to read original apev2 tag from %s\n", deadbeef->pl_find_meta (it, ":URI")); 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); + trace ("cmp3_write_metadata: failed to copy original apev2 tag from %s to temp file\n", deadbeef->pl_find_meta (it, ":URI")); free (buf); goto error; } @@ -3634,7 +3634,7 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const // 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) + trace ("cmp3_write_metadata: failed to write apev2 tag to %s\n", deadbeef->pl_find_meta (it, ":URI")) goto error; } } @@ -3642,23 +3642,23 @@ junk_rewrite_tags (playItem_t *it, uint32_t junk_flags, int id3v2_version, const if (!write_id3v1 && !strip_id3v1 && id3v1_start != 0) { trace ("copying original id3v1 tag %d %d %d\n", write_id3v1, strip_id3v1, id3v1_start); 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); + trace ("cmp3_write_metadata: failed to seek to original id3v1 tag position in %s\n", deadbeef->pl_find_meta (it, ":URI")); 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); + trace ("cmp3_write_metadata: failed to read original id3v1 tag from %s\n", deadbeef->pl_find_meta (it, ":URI")); 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); + trace ("cmp3_write_metadata: failed to copy id3v1 tag from %s to temp file\n", deadbeef->pl_find_meta (it, ":URI")); goto error; } } else if (write_id3v1) { trace ("writing new id3v1 tag\n"); if (junk_id3v1_write (out, it) != 0) { - trace ("cmp3_write_metadata: failed to write id3v1 tag to %s\n", it->fname) + trace ("cmp3_write_metadata: failed to write id3v1 tag to %s\n", deadbeef->pl_find_meta (it, ":URI")) goto error; } } @@ -3675,7 +3675,7 @@ error: free (buffer); } if (!err) { - rename (tmppath, it->fname); + rename (tmppath, deadbeef->pl_find_meta (it, ":URI")); } else { unlink (tmppath); diff --git a/playlist.c b/playlist.c index 3bd6af64..fc7fb6ee 100644 --- a/playlist.c +++ b/playlist.c @@ -556,7 +556,7 @@ plt_free (void) { for (playItem_t *it = playlists_head->head[PL_MAIN]; it; it = it->next[PL_MAIN]) { if (it->_refc > 1) { - fprintf (stderr, "\033[0;31mWARNING: playitem %p %s has refc=%d at delete time\033[37;0m\n", it, it->fname, it->_refc); + fprintf (stderr, "\033[0;31mWARNING: playitem %p %s has refc=%d at delete time\033[37;0m\n", it, pl_find_meta (it, ":URI"), it->_refc); } } @@ -849,14 +849,15 @@ pl_process_cue_track (playItem_t *after, const char *fname, playItem_t **prev, c } (*prev)->endsample = (prevtime * samplerate) - 1; pl_set_item_duration (*prev, (float)((*prev)->endsample - (*prev)->startsample + 1) / samplerate); - if ((*prev)->_duration < 0) { + if (pl_get_item_duration (*prev) < 0) { // might be bad cuesheet file, try to fix trace ("cuesheet seems to be corrupted, trying workaround\n"); //trace ("[bad:] calc endsample=%d, prevtime=%f, samplerate=%d, prev track duration=%f\n", (*prev)->endsample, prevtime, samplerate, (*prev)->duration); prevtime = f_index01; (*prev)->endsample = (prevtime * samplerate) - 1; - pl_set_item_duration (*prev, (float)((*prev)->endsample - (*prev)->startsample + 1) / samplerate); - if ((*prev)->_duration > 0) { + float dur = (float)((*prev)->endsample - (*prev)->startsample + 1) / samplerate; + pl_set_item_duration (*prev, dur); + if (dur > 0) { trace ("success :-D\n"); } else { @@ -871,10 +872,8 @@ pl_process_cue_track (playItem_t *after, const char *fname, playItem_t **prev, c trace ("pl_process_cue_track: invalid index01 (pregap=%s, index01=%s)\n", pregap, index01); return after; } - playItem_t *it = pl_item_alloc (); - it->decoder_id = plug_get_decoder_id (decoder_id); - it->fname = strdup (fname); - it->tracknum = atoi (track); + playItem_t *it = pl_item_alloc_init (fname, decoder_id); + pl_set_meta_int (it, ":TRACKNUM", atoi (track)); it->startsample = index01[0] ? f_index01 * samplerate : 0; it->endsample = -1; // will be filled by next read, or by decoder it->filetype = ftype; @@ -903,16 +902,16 @@ pl_process_cue_track (playItem_t *after, const char *fname, playItem_t **prev, c pl_add_meta (it, "year", date); } if (replaygain_album_gain[0]) { - it->replaygain_album_gain = atof (replaygain_album_gain); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (replaygain_album_gain)); } if (replaygain_album_peak[0]) { - it->replaygain_album_peak = atof (replaygain_album_peak); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (replaygain_album_peak)); } if (replaygain_track_gain[0]) { - it->replaygain_track_gain = atof (replaygain_track_gain); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (replaygain_track_gain)); } if (replaygain_track_peak[0]) { - it->replaygain_track_peak = atof (replaygain_track_peak); + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (replaygain_track_peak)); } it->_flags |= DDB_IS_SUBTRACK | DDB_TAG_CUESHEET; after = pl_insert_item (after, it); @@ -992,7 +991,7 @@ pl_insert_cue_from_buffer (playItem_t *after, playItem_t *origin, const uint8_t trace ("cue: adding track: %s %s %s\n", origin->fname, title, track); if (title[0]) { // add previous track - after = pl_process_cue_track (after, origin->fname, &prev, track, index00, index01, pregap, title, albumperformer, performer, albumtitle, genre, date, replaygain_album_gain, replaygain_album_peak, replaygain_track_gain, replaygain_track_peak, origin->decoder_id, origin->filetype, samplerate); + after = pl_process_cue_track (after, pl_find_meta (origin, ":URI"), &prev, track, index00, index01, pregap, title, albumperformer, performer, albumtitle, genre, date, replaygain_album_gain, replaygain_album_peak, replaygain_track_gain, replaygain_track_peak, pl_find_meta (origin, ":DECODER"), origin->filetype, samplerate); trace ("cue: added %p (%p)\n", after); } @@ -1036,7 +1035,7 @@ pl_insert_cue_from_buffer (playItem_t *after, playItem_t *origin, const uint8_t UNLOCK; return NULL; } - after = pl_process_cue_track (after, origin->fname, &prev, track, index00, index01, pregap, title, albumperformer, performer, albumtitle, genre, date, replaygain_album_gain, replaygain_album_peak, replaygain_track_gain, replaygain_track_peak, origin->decoder_id, origin->filetype, samplerate); + after = pl_process_cue_track (after, pl_find_meta (origin, ":URI"), &prev, track, index00, index01, pregap, title, albumperformer, performer, albumtitle, genre, date, replaygain_album_gain, replaygain_album_peak, replaygain_track_gain, replaygain_track_peak, pl_find_meta (origin, ":DECODER"), origin->filetype, samplerate); if (after) { trace ("last track endsample: %d\n", numsamples-1); after->endsample = numsamples-1; @@ -1062,9 +1061,10 @@ pl_insert_cue_from_buffer (playItem_t *after, playItem_t *origin, const uint8_t playItem_t * pl_insert_cue (playItem_t *after, playItem_t *origin, int numsamples, int samplerate) { trace ("pl_insert_cue numsamples=%d, samplerate=%d\n", numsamples, samplerate); - int len = strlen (origin->fname); + const char *fname = pl_find_meta (origin, ":URI"); + int len = strlen (fname); char cuename[len+5]; - strcpy (cuename, origin->fname); + strcpy (cuename, fname); strcpy (cuename+len, ".cue"); FILE *fp = fopen (cuename, "rb"); if (!fp) { @@ -1471,11 +1471,8 @@ pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(pla } } - playItem_t *it = pl_item_alloc (); - it->decoder_id = NULL; - it->fname = strdup (fname); + playItem_t *it = pl_item_alloc_init (fname, NULL); it->filetype = "content"; - it->_duration = -1; pl_add_meta (it, "title", NULL); after = plt_insert_item (addfiles_playlist ? addfiles_playlist : playlist, after, it); pl_item_unref (it); @@ -1661,8 +1658,9 @@ plt_remove_item (playlist_t *playlist, playItem_t *it) { } // totaltime - if (it->_duration > 0) { - playlist->totaltime -= it->_duration; + float dur = pl_get_item_duration (it); + if (dur > 0) { + playlist->totaltime -= dur; if (playlist->totaltime < 0) { playlist->totaltime = 0; } @@ -1785,8 +1783,9 @@ plt_insert_item (playlist_t *playlist, playItem_t *after, playItem_t *it) { it->played = 0; // totaltime - if (it->_duration > 0) { - playlist->totaltime += it->_duration; + float dur = pl_get_item_duration (it); + if (dur > 0) { + playlist->totaltime += dur; } GLOBAL_UNLOCK; @@ -1801,18 +1800,10 @@ pl_insert_item (playItem_t *after, playItem_t *it) { void pl_item_copy (playItem_t *out, playItem_t *it) { LOCK; - out->fname = strdup (it->fname); - out->decoder_id = it->decoder_id; - out->tracknum = it->tracknum; out->startsample = it->startsample; out->endsample = it->endsample; - pl_set_item_duration (out, it->_duration); out->shufflerating = it->shufflerating; out->filetype = it->filetype; - out->replaygain_album_gain = it->replaygain_album_gain; - out->replaygain_album_peak = it->replaygain_album_peak; - out->replaygain_track_gain = it->replaygain_track_gain; - out->replaygain_track_peak = it->replaygain_track_peak; out->started_timestamp = it->started_timestamp; out->next[PL_MAIN] = it->next[PL_MAIN]; out->prev[PL_MAIN] = it->prev[PL_MAIN]; @@ -1844,17 +1835,23 @@ playItem_t * pl_item_alloc (void) { playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); - it->replaygain_album_peak = 1; - it->replaygain_track_peak = 1; it->_refc = 1; return it; } +playItem_t * +pl_item_alloc_init (const char *fname, const char *decoder_id) { + playItem_t *it = pl_item_alloc (); + pl_add_meta (it, ":URI", fname); + pl_add_meta (it, ":DECODER", decoder_id); + return it; +} + void pl_item_ref (playItem_t *it) { LOCK; it->_refc++; - //trace ("\033[0;34m+it %p: refc=%d: %s\033[37;0m\n", it, it->_refc, it->fname); + //trace ("\033[0;34m+it %p: refc=%d: %s\033[37;0m\n", it, it->_refc, pl_find_meta (it, ":URI")); UNLOCK; } @@ -1862,9 +1859,6 @@ static void pl_item_free (playItem_t *it) { LOCK; if (it) { - if (it->fname) { - free (it->fname); - } while (it->meta) { DB_metaInfo_t *m = it->meta; it->meta = m->next; @@ -1881,12 +1875,12 @@ void pl_item_unref (playItem_t *it) { LOCK; it->_refc--; - //trace ("\033[0;31m-it %p: refc=%d: %s\033[37;0m\n", it, it->_refc, it->fname); + //trace ("\033[0;31m-it %p: refc=%d: %s\033[37;0m\n", it, it->_refc, pl_find_meta (it, ":URI")); if (it->_refc < 0) { trace ("\033[0;31mplaylist: bad refcount on item %p\033[37;0m\n", it); } if (it->_refc <= 0) { - //printf ("\033[0;31mdeleted %s\033[37;0m\n", it->fname); + //printf ("\033[0;31mdeleted %s\033[37;0m\n", pl_find_meta (it, ":URI")); pl_item_free (it); } UNLOCK; @@ -1912,12 +1906,12 @@ pl_add_meta (playItem_t *it, const char *key, const char *value) { if (!value || !*value) { if (!strcasecmp (key, "title")) { // cut filename without path and extension - const char *pext = it->fname + strlen (it->fname) - 1; - while (pext >= it->fname && *pext != '.') { + const char *pext = pl_find_meta (it, ":URI") + strlen (pl_find_meta (it, ":URI")) - 1; + while (pext >= pl_find_meta (it, ":URI") && *pext != '.') { pext--; } const char *pname = pext; - while (pname >= it->fname && *pname != '/') { + while (pname >= pl_find_meta (it, ":URI") && *pname != '/') { pname--; } if (*pname == '/') { @@ -2004,6 +1998,20 @@ pl_replace_meta (playItem_t *it, const char *key, const char *value) { UNLOCK; } +void +pl_set_meta_int (playItem_t *it, const char *key, int value) { + char s[20]; + snprintf (s, sizeof (s), "%d", value); + pl_replace_meta (it, key, s); +} + +void +pl_set_meta_float (playItem_t *it, const char *key, float value) { + char s[20]; + snprintf (s, sizeof (s), "%f", value); + pl_replace_meta (it, key, s); +} + const char * pl_find_meta (playItem_t *it, const char *key) { DB_metaInfo_t *m = it->meta; @@ -2016,6 +2024,18 @@ pl_find_meta (playItem_t *it, const char *key) { return NULL; } +int +pl_find_meta_int (playItem_t *it, const char *key, int def) { + const char *val = pl_find_meta (it, key); + return val ? atoi (val) : def; +} + +float +pl_find_meta_float (playItem_t *it, const char *key, float def) { + const char *val = pl_find_meta (it, key); + return val ? atof (val) : def; +} + DB_metaInfo_t * pl_get_metadata (playItem_t *it) { return it->meta; @@ -2085,29 +2105,32 @@ pl_save (const char *fname) { for (playItem_t *it = playlist->head[PL_MAIN]; it; it = it->next[PL_MAIN]) { uint16_t l; uint8_t ll; - l = strlen (it->fname); + const char *fname = pl_find_meta (it, ":URI"); + l = strlen (fname); if (fwrite (&l, 1, 2, fp) != 2) { goto save_fail; } - if (fwrite (it->fname, 1, l, fp) != l) { + if (fwrite (fname, 1, l, fp) != l) { goto save_fail; } - if (it->decoder_id) { - ll = strlen (it->decoder_id); + const char *decoder_id = pl_find_meta (it, ":DECODER"); + if (decoder_id) { + ll = strlen (decoder_id); if (fwrite (&ll, 1, 1, fp) != 1) { goto save_fail; } - if (fwrite (it->decoder_id, 1, ll, fp) != ll) { + if (fwrite (decoder_id, 1, ll, fp) != ll) { goto save_fail; } } - else { + else + { ll = 0; if (fwrite (&ll, 1, 1, fp) != 1) { goto save_fail; } } - l = it->tracknum; + l = pl_find_meta_int (it, ":TRACKNUM", 0); if (fwrite (&l, 1, 2, fp) != 2) { goto save_fail; } @@ -2129,16 +2152,20 @@ pl_save (const char *fname) { goto save_fail; } } - if (fwrite (&it->replaygain_album_gain, 1, 4, fp) != 4) { + float rg_albumgain = pl_get_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN); + float rg_albumpeak = pl_get_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK); + float rg_trackgain = pl_get_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN); + float rg_trackpeak = pl_get_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK); + if (fwrite (&rg_albumgain, 1, 4, fp) != 4) { goto save_fail; } - if (fwrite (&it->replaygain_album_peak, 1, 4, fp) != 4) { + if (fwrite (&rg_albumpeak, 1, 4, fp) != 4) { goto save_fail; } - if (fwrite (&it->replaygain_track_gain, 1, 4, fp) != 4) { + if (fwrite (&rg_trackgain, 1, 4, fp) != 4) { goto save_fail; } - if (fwrite (&it->replaygain_track_peak, 1, 4, fp) != 4) { + if (fwrite (&rg_trackpeak, 1, 4, fp) != 4) { goto save_fail; } if (fwrite (&it->_flags, 1, 4, fp) != 4) { @@ -2331,11 +2358,12 @@ pl_load (const char *fname) { if (fread (&l, 1, 2, fp) != 2) { goto load_fail; } - it->fname = malloc (l+1); - if (fread (it->fname, 1, l, fp) != l) { + char fname[l+1]; + if (fread (fname, 1, l, fp) != l) { goto load_fail; } - it->fname[l] = 0; + fname[l] = 0; + pl_add_meta (it, ":URI", fname); // decoder uint8_t ll; if (fread (&ll, 1, 1, fp) != 1) { @@ -2344,22 +2372,20 @@ pl_load (const char *fname) { if (ll >= 20) { goto load_fail; } + char decoder_id[20] = ""; if (ll) { - char decoder[20]; - if (fread (decoder, 1, ll, fp) != ll) { + if (fread (decoder_id, 1, ll, fp) != ll) { goto load_fail; } - decoder[ll] = 0; - it->decoder_id = plug_get_decoder_id (decoder); - } - else { - it->decoder_id = NULL; + decoder_id[ll] = 0; + pl_add_meta (it, ":DECODER", decoder_id); } // tracknum - if (fread (&l, 1, 2, fp) != 2) { + int16_t tracknum; + if (fread (&tracknum, 1, 2, fp) != 2) { goto load_fail; } - it->tracknum = l; + pl_set_meta_int (it, ":TRACKNUM", tracknum); // startsample if (fread (&it->startsample, 1, 4, fp) != 4) { goto load_fail; @@ -2369,11 +2395,12 @@ pl_load (const char *fname) { goto load_fail; } // duration - float d; - if (fread (&d, 1, 4, fp) != 4) { + if (fread (&it->_duration, 1, 4, fp) != 4) { goto load_fail; } - it->_duration = d; + char s[100]; + pl_format_time (it->_duration, s, sizeof(s)); + pl_replace_meta (it, ":DURATION", s); // get const filetype string from decoder uint8_t ft; if (fread (&ft, 1, 1, fp) != 1) { @@ -2388,8 +2415,8 @@ pl_load (const char *fname) { if (!strcmp (ftype, "content")) { it->filetype = "content"; } - else if (it->decoder_id) { - DB_decoder_t *dec = plug_get_decoder_for_id (it->decoder_id); + else if (decoder_id[0]) { + DB_decoder_t *dec = plug_get_decoder_for_id (decoder_id); if (dec && dec->filetypes) { for (int i = 0; dec->filetypes[i]; i++) { if (!strcasecmp (dec->filetypes[i], ftype)) { @@ -2400,34 +2427,55 @@ pl_load (const char *fname) { } } } - if (fread (&it->replaygain_album_gain, 1, 4, fp) != 4) { + + float f; + + if (fread (&f, 1, 4, fp) != 4) { goto load_fail; } - if (fread (&it->replaygain_album_peak, 1, 4, fp) != 4) { + if (f != 0) { + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, f); + } + + if (fread (&f, 1, 4, fp) != 4) { goto load_fail; } - if (it->replaygain_album_peak == 0) { - it->replaygain_album_peak = 1; + if (f == 0) { + f = 1; } - if (fread (&it->replaygain_track_gain, 1, 4, fp) != 4) { + if (f != 1) { + pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, f); + } + + if (fread (&f, 1, 4, fp) != 4) { goto load_fail; } - if (fread (&it->replaygain_track_peak, 1, 4, fp) != 4) { + if (f != 0) { + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, f); + } + + if (fread (&f, 1, 4, fp) != 4) { goto load_fail; } - if (it->replaygain_track_peak == 0) { - it->replaygain_track_peak = 1; + if (f == 0) { + f = 1; } + if (f != 1) { + pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, f); + } + + uint32_t flg = 0; if (minorver >= 2) { - if (fread (&it->_flags, 1, 4, fp) != 4) { + if (fread (&flg, 1, 4, fp) != 4) { goto load_fail; } } else { - if (it->startsample > 0 || it->endsample > 0 || it->tracknum > 0) { - it->_flags |= DDB_IS_SUBTRACK; + if (it->startsample > 0 || it->endsample > 0 || tracknum > 0) { + flg |= DDB_IS_SUBTRACK; } } + pl_set_item_flags (it, flg); int16_t nm = 0; if (fread (&nm, 1, 2, fp) != 2) { @@ -2627,15 +2675,56 @@ pl_set_item_duration (playItem_t *it, float duration) { } } it->_duration = duration; + char s[100]; + pl_format_time (it->_duration, s, sizeof(s)); + pl_replace_meta (it, ":DURATION", s); GLOBAL_UNLOCK; } float pl_get_item_duration (playItem_t *it) { - LOCK; - float d = it->_duration; - UNLOCK; - return d; + return it->_duration; +} + +static const char *rg_keys[] = { + ":REPLAYGAIN_ALBUMGAIN", + ":REPLAYGAIN_ALBUMPEAK", + ":REPLAYGAIN_TRACKGAIN", + ":REPLAYGAIN_TRACKPEAK" +}; + +void +pl_set_item_replaygain (playItem_t *it, int idx, float value) { + char s[100]; + switch (idx) { + case DDB_REPLAYGAIN_ALBUMGAIN: + case DDB_REPLAYGAIN_TRACKGAIN: + snprintf (s, sizeof (s), "%0.2f dB", value); + break; + case DDB_REPLAYGAIN_ALBUMPEAK: + case DDB_REPLAYGAIN_TRACKPEAK: + snprintf (s, sizeof (s), "%0.6f", value); + break; + default: + return; + } + pl_replace_meta (it, rg_keys[idx], s); +} + +float +pl_get_item_replaygain (playItem_t *it, int idx) { + if (idx < 0 || idx > DDB_REPLAYGAIN_TRACKPEAK) { + return 0; + } + + switch (idx) { + case DDB_REPLAYGAIN_ALBUMGAIN: + case DDB_REPLAYGAIN_TRACKGAIN: + return pl_find_meta_float (it, rg_keys[idx], 0); + case DDB_REPLAYGAIN_ALBUMPEAK: + case DDB_REPLAYGAIN_TRACKPEAK: + return pl_find_meta_float (it, rg_keys[idx], 1); + } } int @@ -2746,7 +2835,7 @@ pl_format_duration (playItem_t *it, const char *ret, char *dur, int size) { if (ret) { return ret; } - pl_format_time (it->_duration, dur, size); + pl_format_time (pl_get_item_duration (it), dur, size); return dur; } @@ -2897,8 +2986,8 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, } } else if (*fmt == 'f') { - meta = it->fname + strlen (it->fname) - 1; - while (meta > it->fname && (*meta) != '/') { + meta = pl_find_meta (it, ":URI") + strlen (pl_find_meta (it, ":URI")) - 1; + while (meta > pl_find_meta (it, ":URI") && (*meta) != '/') { meta--; } if (*meta == '/') { @@ -2906,7 +2995,7 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, } } else if (*fmt == 'F') { - meta = it->fname; + meta = pl_find_meta (it, ":URI"); } else if (*fmt == 'T') { char *t = tags; @@ -2953,8 +3042,8 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, } else if (*fmt == 'd') { // directory - const char *end = it->fname + strlen (it->fname) - 1; - while (end > it->fname && (*end) != '/') { + const char *end = pl_find_meta (it, ":URI") + strlen (pl_find_meta (it, ":URI")) - 1; + while (end > pl_find_meta (it, ":URI") && (*end) != '/') { end--; } if (*end != '/') { @@ -2963,7 +3052,7 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, else { const char *start = end; start--; - while (start > it->fname && (*start != '/')) { + while (start > pl_find_meta (it, ":URI") && (*start != '/')) { start--; } @@ -2981,8 +3070,8 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, } else if (*fmt == 'D') { // directory with path - const char *end = it->fname + strlen (it->fname) - 1; - while (end > it->fname && (*end) != '/') { + const char *end = pl_find_meta (it, ":URI") + strlen (pl_find_meta (it, ":URI")) - 1; + while (end > pl_find_meta (it, ":URI") && (*end) != '/') { end--; } if (*end != '/') { @@ -2990,9 +3079,9 @@ pl_format_title_int (const char *escape_chars, playItem_t *it, int idx, char *s, } else { // copy - int len = end - it->fname; + int len = end - pl_find_meta (it, ":URI"); len = min (len, sizeof (dirname)-1); - strncpy (dirname, it->fname, len); + strncpy (dirname, pl_find_meta (it, ":URI"), len); dirname[len] = 0; meta = dirname; } @@ -3111,7 +3200,9 @@ strcasecmp_numeric (const char *a, const char *b) { static int pl_sort_compare_str (playItem_t *a, playItem_t *b) { if (pl_sort_is_duration) { - return !pl_sort_ascending ? b->_duration * 100000 - a->_duration * 100000 : a->_duration * 100000 - b->_duration * 100000; + float dur_a = a->_duration * 100000; + float dur_b = b->_duration * 100000; + return !pl_sort_ascending ? dur_b - dur_a : dur_a - dur_b; } else if (pl_sort_is_track) { int t1; @@ -3411,7 +3502,7 @@ pl_search_process (const char *text) { if (*text) { for (DB_metaInfo_t *m = it->meta; m; m = m->next) { if (strcasecmp (m->key, "cuesheet") && utfcasestr (m->value, text)) { - //fprintf (stderr, "%s -> %s match (%s.%s)\n", text, m->value, it->fname, m->key); + //fprintf (stderr, "%s -> %s match (%s.%s)\n", text, m->value, pl_find_meta (it, ":URI"), m->key); // add to list it->next[PL_SEARCH] = NULL; if (playlist->tail[PL_SEARCH]) { @@ -3558,24 +3649,6 @@ pl_items_copy_junk (playItem_t *from, playItem_t *first, playItem_t *last) { } meta = meta->next; } -#if 0 - const char *metainfo[] = { - "year", "genre", "copyright", "vendor", "comment", "tags", "numtracks", "band", "performer", "composer", "disc", "title", "artist", "album", NULL - }; - for (int m = 0; metainfo[m]; m++) { - const char *data = pl_find_meta (from, metainfo[m]); - if (data) { - playItem_t *i; - for (i = first; ; i = i->next[PL_MAIN]) { - i->_flags = from->_flags; // stupid - pl_add_meta (i, metainfo[m], data); - if (i == last) { - break; - } - } - } - } -#endif UNLOCK; } @@ -3591,5 +3664,10 @@ void pl_set_item_flags (playItem_t *it, uint32_t flags) { LOCK; it->_flags = flags; + + char s[200]; + pl_format_title (it, -1, s, sizeof (s), -1, "%T"); + pl_replace_meta (it, ":TAGS", s); + pl_replace_meta (it, ":HAS_EMBEDDED_CUESHEET", (flags & DDB_HAS_EMBEDDED_CUESHEET) ? _("Yes") : _("No")); UNLOCK; } diff --git a/playlist.h b/playlist.h index 03692ae0..11e3cb63 100644 --- a/playlist.h +++ b/playlist.h @@ -23,22 +23,21 @@ #define PL_MAX_ITERATORS 2 +// predefined properties stored in metadata for storage unification: +// :URI - full pathname +// :DECODER - decoder id +// :TRACKNUM - subsong index (sid, nsf, cue, etc) +// :DURATION - length in seconds + typedef struct playItem_s { - char *fname; // full pathname - const char *decoder_id; - int tracknum; // used for stuff like sid, nsf, cue (will be ignored by most codecs) int startsample; int endsample; int shufflerating; // sort order for shuffle mode float playtime; // total playtime time_t started_timestamp; // result of calling time(NULL) const char *filetype; // e.g. MP3 or OGG - float replaygain_album_gain; - float replaygain_album_peak; - float replaygain_track_gain; - float replaygain_track_peak; // private area, must not be visible to plugins - float _duration; // in seconds + float _duration; uint32_t _flags; int _refc; struct playItem_s *next[PL_MAX_ITERATORS]; // next item in linked list @@ -171,6 +170,9 @@ pl_remove_item (playItem_t *i); playItem_t * pl_item_alloc (void); +playItem_t * +pl_item_alloc_init (const char *fname, const char *decoder_id); + void pl_item_ref (playItem_t *it); @@ -215,9 +217,21 @@ pl_append_meta (playItem_t *it, const char *key, const char *value); const char * pl_find_meta (playItem_t *it, const char *key); +int +pl_find_meta_int (playItem_t *it, const char *key, int def); + +float +pl_find_meta_float (playItem_t *it, const char *key, float def); + void pl_replace_meta (playItem_t *it, const char *key, const char *value); +void +pl_set_meta_int (playItem_t *it, const char *key, int value); + +void +pl_set_meta_float (playItem_t *it, const char *key, float value); + void pl_delete_all_meta (playItem_t *it); @@ -262,6 +276,12 @@ pl_set_item_duration (playItem_t *it, float duration); float pl_get_item_duration (playItem_t *it); +void +pl_set_item_replaygain (playItem_t *it, int idx, float value); + +float +pl_get_item_replaygain (playItem_t *it, int idx); + uint32_t pl_get_item_flags (playItem_t *it); diff --git a/plugins.c b/plugins.c index bb12d3dc..fedba88b 100644 --- a/plugins.c +++ b/plugins.c @@ -125,6 +125,7 @@ static DB_functions_t deadbeef_api = { .plt_lock = plt_lock, .plt_unlock = plt_unlock, .pl_item_alloc = (DB_playItem_t* (*)(void))pl_item_alloc, + .pl_item_alloc_init = (DB_playItem_t* (*)(const char *fname, const char *decoder_id))pl_item_alloc_init, .pl_item_ref = (void (*)(DB_playItem_t *))pl_item_ref, .pl_item_unref = (void (*)(DB_playItem_t *))pl_item_unref, .pl_item_copy = (void (*)(DB_playItem_t *, DB_playItem_t *))pl_item_copy, @@ -145,6 +146,8 @@ static DB_functions_t deadbeef_api = { .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_set_item_replaygain = (void (*)(DB_playItem_t *it, int idx, float value))pl_set_item_replaygain, + .pl_get_item_replaygain = (float (*)(DB_playItem_t *it, int idx))pl_get_item_replaygain, .pl_get_totaltime = pl_get_totaltime, .pl_getcount = pl_getcount, .pl_delete_selected = pl_delete_selected, @@ -174,7 +177,11 @@ static DB_functions_t deadbeef_api = { // metainfo .pl_add_meta = (void (*) (DB_playItem_t *, const char *, const char *))pl_add_meta, .pl_append_meta = (void (*) (DB_playItem_t *, const char *, const char *))pl_append_meta, + .pl_set_meta_int = (void (*) (DB_playItem_t *it, const char *key, int value))pl_set_meta_int, + .pl_set_meta_float = (void (*) (DB_playItem_t *it, const char *key, float value))pl_set_meta_float, .pl_find_meta = (const char *(*) (DB_playItem_t *, const char *))pl_find_meta, + .pl_find_meta_int = (int (*) (DB_playItem_t *it, const char *key, int def))pl_find_meta_int, + .pl_find_meta_float = (float (*) (DB_playItem_t *it, const char *key, float def))pl_find_meta_float, .pl_replace_meta = (void (*) (DB_playItem_t *, const char *, const char *))pl_replace_meta, .pl_delete_all_meta = (void (*) (DB_playItem_t *it))pl_delete_all_meta, .pl_get_metadata = (DB_metaInfo_t *(*)(DB_playItem_t *it))pl_get_metadata, @@ -403,7 +410,8 @@ plug_ev_unsubscribe (DB_plugin_t *plugin, int ev, DB_callback_t callback, uintpt float plug_playback_get_pos (void) { playItem_t *trk = streamer_get_playing_track (); - if (!trk || trk->_duration <= 0) { + float dur = pl_get_item_duration (trk); + if (!trk || dur <= 0) { if (trk) { pl_item_unref (trk); } @@ -412,19 +420,20 @@ plug_playback_get_pos (void) { if (trk) { pl_item_unref (trk); } - return streamer_get_playpos () * 100 / trk->_duration; + return streamer_get_playpos () * 100 / dur; } void plug_playback_set_pos (float pos) { playItem_t *trk = streamer_get_playing_track (); - if (!trk || trk->_duration <= 0) { + float dur = pl_get_item_duration (trk); + if (!trk || dur <= 0) { if (trk) { pl_item_unref (trk); } return; } - float t = pos * trk->_duration / 100.f; + float t = pos * dur / 100.f; if (trk) { pl_item_unref (trk); } diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c index ca76340a..332870e0 100644 --- a/plugins/aac/aac.c +++ b/plugins/aac/aac.c @@ -384,7 +384,7 @@ static int aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { aac_info_t *info = (aac_info_t *)_info; - info->file = deadbeef->fopen (it->fname); + info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->file) { return -1; } @@ -424,7 +424,7 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { if (!info->file->vfs->is_streaming ()) { #ifdef USE_MP4FF - trace ("aac_init: mp4ff_open_read %s\n", it->fname); + trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI")); info->mp4file = mp4ff_open_read (&info->mp4reader); if (info->mp4file) { int ntracks = mp4ff_total_tracks (info->mp4file); @@ -493,8 +493,8 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { } } #else - trace ("aac_init: MP4ReadProvider %s\n", it->fname); - info->mp4file = MP4ReadProvider (it->fname, 0, &info->mp4reader); + trace ("aac_init: MP4ReadProvider %s\n", deadbeef->pl_find_meta (it, ":URI")); + info->mp4file = MP4ReadProvider (deadbeef->pl_find_meta (it, ":URI"), 0, &info->mp4reader); info->mp4track = MP4FindTrackId(info->mp4file, 0, "audio", 0); trace ("aac_init: MP4FindTrackId returned %d\n", info->mp4track); if (info->mp4track >= 0) { @@ -991,24 +991,20 @@ aac_load_tags (DB_playItem_t *it, mp4ff_t *mp4) { free (s); } } - it->replaygain_track_gain = 0; - it->replaygain_track_peak = 1; - it->replaygain_album_gain = 0; - it->replaygain_album_peak = 1; if (mp4ff_meta_find_by_name(mp4, "replaygain_track_gain", &s)) { - it->replaygain_track_gain = atof (s); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (s)); free (s); } if (mp4ff_meta_find_by_name(mp4, "replaygain_track_peak", &s)) { - it->replaygain_track_peak = atof (s); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s)); free (s); } if (mp4ff_meta_find_by_name(mp4, "replaygain_album_gain", &s)) { - it->replaygain_album_gain = atof (s); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (s)); free (s); } if (mp4ff_meta_find_by_name(mp4, "replaygain_album_peak", &s)) { - it->replaygain_album_peak = atof (s); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (s)); free (s); } deadbeef->pl_add_meta (it, "title", NULL); @@ -1019,7 +1015,7 @@ aac_load_tags (DB_playItem_t *it, mp4ff_t *mp4) { int aac_read_metadata (DB_playItem_t *it) { #ifdef USE_MP4FF - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } @@ -1112,9 +1108,7 @@ aac_insert (DB_playItem_t *after, const char *fname) { } } - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = ftype; deadbeef->pl_set_item_duration (it, duration); trace ("duration: %f sec\n", duration); diff --git a/plugins/adplug/adplug-db.cpp b/plugins/adplug/adplug-db.cpp index 1f096727..973da0da 100644 --- a/plugins/adplug/adplug-db.cpp +++ b/plugins/adplug/adplug-db.cpp @@ -82,13 +82,13 @@ adplug_init (DB_fileinfo_t *_info, DB_playItem_t *it) { int channels = 2; info->opl = new CEmuopl (samplerate, bps == 16 ? true : false, channels == 2); // opl->settype (Copl::TYPE_OPL2); - info->decoder = CAdPlug::factory (it->fname, info->opl, CAdPlug::players); + info->decoder = CAdPlug::factory (deadbeef->pl_find_meta (it, ":URI"), info->opl, CAdPlug::players); if (!info->decoder) { - trace ("adplug: failed to open %s\n", it->fname); + trace ("adplug: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } - info->subsong = it->tracknum; + info->subsong = deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0); info->decoder->rewind (info->subsong); float dur = deadbeef->pl_get_item_duration (it); info->totalsamples = dur * samplerate; @@ -264,11 +264,9 @@ adplug_insert (DB_playItem_t *after, const char *fname) { if (dur < 0.1) { continue; } - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (adplug_plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, adplug_plugin.plugin.id); it->filetype = adplug_get_extension (fname); - it->tracknum = i; + deadbeef->pl_set_meta_int (it, ":TRACKNUM", i); deadbeef->pl_set_item_duration (it, dur); #if 0 // add metainfo diff --git a/plugins/cdda/cdda.c b/plugins/cdda/cdda.c index 2fe26360..1a2a0ec6 100644 --- a/plugins/cdda/cdda.c +++ b/plugins/cdda/cdda.c @@ -79,18 +79,18 @@ static int cda_init (DB_fileinfo_t *_info, DB_playItem_t *it) { cdda_info_t *info = (cdda_info_t *)_info; - trace ("cdda: init %s\n", it->fname); + trace ("cdda: init %s\n", deadbeef->pl_find_meta (it, ":URI")); - size_t l = strlen (it->fname); + size_t l = strlen (deadbeef->pl_find_meta (it, ":URI")); char location[l+1]; - memcpy (location, it->fname, l+1); + memcpy (location, deadbeef->pl_find_meta (it, ":URI"), l+1); char *nr = strchr (location, '#'); if (nr) { *nr = 0; nr++; } else { - trace ("cdda: bad name: %s\n", it->fname); + trace ("cdda: bad name: %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } int track_nr = atoi (nr); @@ -285,9 +285,7 @@ insert_single_track (CdIo_t* cdio, DB_playItem_t *after, const char* file, int t int sector_count = cdio_get_track_sec_count (cdio, track_nr); - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (tmp); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (tmp, plugin.plugin.id); it->filetype = "cdda"; deadbeef->pl_set_item_duration (it, (float)sector_count / 75.0); diff --git a/plugins/dca/dcaplug.c b/plugins/dca/dcaplug.c index c14032e1..034e5fdc 100644 --- a/plugins/dca/dcaplug.c +++ b/plugins/dca/dcaplug.c @@ -356,9 +356,9 @@ static int dts_init (DB_fileinfo_t *_info, DB_playItem_t *it) { ddb_dca_state_t *info = (ddb_dca_state_t *)_info; - info->file = deadbeef->fopen (it->fname); + info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->file) { - trace ("dca: failed to open %s\n", it->fname); + trace ("dca: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } @@ -606,9 +606,7 @@ dts_insert (DB_playItem_t *after, const char *fname) { dur = (float)totalsamples / state.sample_rate; } - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = filetype; deadbeef->pl_set_item_duration (it, dur); diff --git a/plugins/ffap/ffap.c b/plugins/ffap/ffap.c index 2559ea27..4c414a9f 100644 --- a/plugins/ffap/ffap.c +++ b/plugins/ffap/ffap.c @@ -690,7 +690,7 @@ ffap_init (DB_fileinfo_t *_info, DB_playItem_t *it) { ape_info_t *info = (ape_info_t*)_info; - info->fp = deadbeef->fopen (it->fname); + info->fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->fp) { return -1; } @@ -1764,9 +1764,7 @@ ffap_insert (DB_playItem_t *after, const char *fname) { float duration = ape_ctx.totalsamples / (float)ape_ctx.samplerate; DB_playItem_t *it = NULL; - it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "APE"; deadbeef->pl_set_item_duration (it, duration); @@ -1912,7 +1910,7 @@ ffap_seek (DB_fileinfo_t *_info, float seconds) { static int ffap_read_metadata (DB_playItem_t *it) { - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c index 8d718546..2eaf1cb9 100644 --- a/plugins/ffmpeg/ffmpeg.c +++ b/plugins/ffmpeg/ffmpeg.c @@ -103,19 +103,19 @@ ffmpeg_open (uint32_t hints) { static int ffmpeg_init (DB_fileinfo_t *_info, DB_playItem_t *it) { ffmpeg_info_t *info = (ffmpeg_info_t *)_info; - trace ("ffmpeg init %s\n", it->fname); + trace ("ffmpeg init %s\n", deadbeef->pl_find_meta (it, ":URI")); // prepare to decode the track // return -1 on failure int ret; - int l = strlen (it->fname); + int l = strlen (deadbeef->pl_find_meta (it, ":URI")); char *uri = alloca (l + sizeof (FF_PROTOCOL_NAME) + 1); int i; // construct uri memcpy (uri, FF_PROTOCOL_NAME, sizeof (FF_PROTOCOL_NAME)-1); memcpy (uri + sizeof (FF_PROTOCOL_NAME)-1, ":", 1); - memcpy (uri + sizeof (FF_PROTOCOL_NAME), it->fname, l); + memcpy (uri + sizeof (FF_PROTOCOL_NAME), deadbeef->pl_find_meta (it, ":URI"), l); uri[sizeof (FF_PROTOCOL_NAME) + l] = 0; trace ("ffmpeg: uri: %s\n", uri); @@ -150,10 +150,10 @@ ffmpeg_init (DB_fileinfo_t *_info, DB_playItem_t *it) { if (info->codec == NULL) { - trace ("ffmpeg can't decode %s\n", it->fname); + trace ("ffmpeg can't decode %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } - trace ("ffmpeg can decode %s\n", it->fname); + trace ("ffmpeg can decode %s\n", deadbeef->pl_find_meta (it, ":URI")); trace ("ffmpeg: codec=%s, stream=%d\n", info->codec->name, i); if (avcodec_open (info->ctx, info->codec) < 0) { @@ -537,13 +537,11 @@ ffmpeg_insert (DB_playItem_t *after, const char *fname) { int totalsamples = fctx->duration * samplerate / AV_TIME_BASE; - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); // FIXME: get proper codec it->filetype = filetypes[FT_UNKNOWN]; - if (!deadbeef->is_local_file (it->fname)) { + if (!deadbeef->is_local_file (deadbeef->pl_find_meta (it, ":URI"))) { deadbeef->pl_set_item_duration (it, -1); } else { @@ -555,7 +553,7 @@ ffmpeg_insert (DB_playItem_t *after, const char *fname) { int64_t fsize = -1; - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (fp) { if (!fp->vfs->is_streaming ()) { fsize = deadbeef->fgetlength (fp); @@ -693,19 +691,19 @@ ffmpeg_stop (void) { int ffmpeg_read_metadata (DB_playItem_t *it) { - trace ("ffmpeg_read_metadata: fname %s\n", it->fname); + trace ("ffmpeg_read_metadata: fname %s\n", deadbeef->pl_find_meta (it, ":URI")); AVCodec *codec = NULL; AVCodecContext *ctx = NULL; AVFormatContext *fctx = NULL; int ret; - int l = strlen (it->fname); + int l = strlen (deadbeef->pl_find_meta (it, ":URI")); char *uri = alloca (l + sizeof (FF_PROTOCOL_NAME) + 1); int i; // construct uri memcpy (uri, FF_PROTOCOL_NAME, sizeof (FF_PROTOCOL_NAME)-1); memcpy (uri + sizeof (FF_PROTOCOL_NAME)-1, ":", 1); - memcpy (uri + sizeof (FF_PROTOCOL_NAME), it->fname, l); + memcpy (uri + sizeof (FF_PROTOCOL_NAME), deadbeef->pl_find_meta (it, ":URI"), l); uri[sizeof (FF_PROTOCOL_NAME) + l] = 0; trace ("ffmpeg: uri: %s\n", uri); @@ -728,7 +726,7 @@ ffmpeg_read_metadata (DB_playItem_t *it) { } if (codec == NULL) { - trace ("ffmpeg can't decode %s\n", it->fname); + trace ("ffmpeg can't decode %s\n", deadbeef->pl_find_meta (it, ":URI")); av_close_input_file(fctx); return -1; } diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index 44311762..16514a90 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -204,10 +204,10 @@ cflac_open (uint32_t hints) { static int cflac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { - trace ("cflac_init %s\n", it->fname); + trace ("cflac_init %s\n", deadbeef->pl_find_meta (it, ":URI")); flac_info_t *info = (flac_info_t *)_info; - info->file = deadbeef->fopen (it->fname); + info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->file) { trace ("cflac_init failed to open file\n"); return -1; @@ -215,8 +215,8 @@ cflac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->flac_critical_error = 0; - const char *ext = it->fname + strlen (it->fname); - while (ext > it->fname && *ext != '/' && *ext != '.') { + const char *ext = deadbeef->pl_find_meta (it, ":URI") + strlen (deadbeef->pl_find_meta (it, ":URI")); + while (ext > deadbeef->pl_find_meta (it, ":URI") && *ext != '/' && *ext != '.') { ext--; } if (*ext == '.') { @@ -537,16 +537,16 @@ cflac_add_metadata (DB_playItem_t *it, char *s, int length) { deadbeef->pl_add_meta (it, "cuesheet", s + 9); } else if (!strncasecmp (s, "replaygain_album_gain=", 22)) { - it->replaygain_album_gain = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (s+22)); } else if (!strncasecmp (s, "replaygain_album_peak=", 22)) { - it->replaygain_album_peak = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (s+22)); } else if (!strncasecmp (s, "replaygain_track_gain=", 22)) { - it->replaygain_track_gain = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (s+22)); } else if (!strncasecmp (s, "replaygain_track_peak=", 22)) { - it->replaygain_track_peak = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s+22)); } else { const char *eq = strchr (s, '='); @@ -663,9 +663,7 @@ cflac_insert (DB_playItem_t *after, const char *fname) { // read all metadata FLAC__stream_decoder_set_md5_checking(decoder, 0); FLAC__stream_decoder_set_metadata_respond_all (decoder); - it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); info.it = it; if (skip > 0) { deadbeef->fseek (info.file, skip, SEEK_SET); @@ -757,7 +755,7 @@ cflac_read_metadata (DB_playItem_t *it) { trace ("cflac_read_metadata: FLAC__metadata_chain_new failed\n"); return -1; } - FLAC__bool res = FLAC__metadata_chain_read (chain, it->fname); + FLAC__bool res = FLAC__metadata_chain_read (chain, deadbeef->pl_find_meta (it, ":URI")); if (!res) { trace ("cflac_read_metadata: FLAC__metadata_chain_read failed\n"); goto error; @@ -822,7 +820,7 @@ cflac_write_metadata (DB_playItem_t *it) { trace ("cflac_write_metadata: FLAC__metadata_chain_new failed\n"); return -1; } - FLAC__bool res = FLAC__metadata_chain_read (chain, it->fname); + FLAC__bool res = FLAC__metadata_chain_read (chain, deadbeef->pl_find_meta (it, ":URI")); if (!res) { trace ("cflac_write_metadata: FLAC__metadata_chain_read failed\n"); goto error; diff --git a/plugins/gme/cgme.c b/plugins/gme/cgme.c index 3934f930..5b6a436f 100644 --- a/plugins/gme/cgme.c +++ b/plugins/gme/cgme.c @@ -113,18 +113,18 @@ cgme_init (DB_fileinfo_t *_info, DB_playItem_t *it) { int samplerate = deadbeef->conf_get_int ("synth.samplerate", 44100); gme_err_t res; - const char *ext = strrchr (it->fname, '.'); + const char *ext = strrchr (deadbeef->pl_find_meta (it, ":URI"), '.'); if (ext && !strcasecmp (ext, ".vgz")) { trace ("opening gzipped vgm...\n"); char *buffer; int sz; - if (!read_gzfile (it->fname, &buffer, &sz)) { + if (!read_gzfile (deadbeef->pl_find_meta (it, ":URI"), &buffer, &sz)) { res = gme_open_data (buffer, sz, &info->emu, samplerate); free (buffer); } } else { - DB_FILE *f = deadbeef->fopen (it->fname); + DB_FILE *f = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); int64_t sz = deadbeef->fgetlength (f); if (sz <= 0) { deadbeef->fclose (f); @@ -151,14 +151,14 @@ cgme_init (DB_fileinfo_t *_info, DB_playItem_t *it) { return -1; } gme_mute_voices (info->emu, info->cgme_voicemask); - gme_start_track (info->emu, it->tracknum); + gme_start_track (info->emu, deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0)); #ifdef GME_VERSION_055 gme_info_t *inf; - gme_track_info (info->emu, &inf, it->tracknum); + gme_track_info (info->emu, &inf, deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0)); #else track_info_t _inf; - gme_track_info (info->emu, &inf, it->tracknum); + gme_track_info (info->emu, &inf, deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0)); track_info_t *inf = &_inf; #endif @@ -298,9 +298,7 @@ cgme_insert (DB_playItem_t *after, const char *fname) { track_info_t *inf = &_inf; #endif if (!ret) { - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); char str[1024]; if (inf->song[0]) { snprintf (str, 1024, "%d %s - %s", i, inf->game, inf->song); @@ -309,7 +307,7 @@ cgme_insert (DB_playItem_t *after, const char *fname) { snprintf (str, 1024, "%d %s - ?", i, inf->game); } trace ("track subtune %d %s, length=%d\n", i, str, inf->length); - it->tracknum = i; + deadbeef->pl_set_meta_int (it, ":TRACKNUM", i); // add metadata cgme_add_meta (it, "system", inf->system); diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c index 539b6eb7..b25317d7 100644 --- a/plugins/gtkui/gtkui.c +++ b/plugins/gtkui/gtkui.c @@ -1081,7 +1081,7 @@ gtkui_add_file_info_cb (DB_playItem_t *it, void *data) { if (progress_is_aborted ()) { return -1; } - g_idle_add (gtkui_set_progress_text_idle, it->fname); + g_idle_add (gtkui_set_progress_text_idle, (gpointer)deadbeef->pl_find_meta (it, ":URI")); return 0; } diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c index fc86a058..9342f257 100644 --- a/plugins/gtkui/mainplaylist.c +++ b/plugins/gtkui/mainplaylist.c @@ -127,9 +127,9 @@ gboolean playlist_tooltip_handler (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer unused) { GtkWidget *pl = lookup_widget (mainwin, "playlist"); - DB_playItem_t *item = (DB_playItem_t *)ddb_listview_get_iter_from_coord (DDB_LISTVIEW (pl), 0, y); - if (item && item->fname) { - gtk_tooltip_set_text (tooltip, item->fname); + DB_playItem_t *it = (DB_playItem_t *)ddb_listview_get_iter_from_coord (DDB_LISTVIEW (pl), 0, y); + if (it) { + gtk_tooltip_set_text (tooltip, deadbeef->pl_find_meta (it, ":URI")); return TRUE; } return FALSE; diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c index 53965295..bffaa6c9 100644 --- a/plugins/gtkui/plcommon.c +++ b/plugins/gtkui/plcommon.c @@ -120,7 +120,7 @@ void draw_column_data (DdbListview *listview, GdkDrawable *drawable, DdbListview if (!album || !*album) { album = deadbeef->pl_find_meta (group_it, "title"); } - GdkPixbuf *pixbuf = get_cover_art (((DB_playItem_t *)group_it)->fname, artist, album, art_width); + GdkPixbuf *pixbuf = get_cover_art (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width); if (pixbuf) { int pw = gdk_pixbuf_get_width (pixbuf); int ph = gdk_pixbuf_get_height (pixbuf); @@ -238,14 +238,15 @@ main_reload_metadata_activate DdbListview *ps = DDB_LISTVIEW (g_object_get_data (G_OBJECT (menuitem), "ps")); DB_playItem_t *it = deadbeef->pl_get_first (PL_MAIN); while (it) { - if (deadbeef->pl_is_selected (it) && deadbeef->is_local_file (it->fname) && it->decoder_id) { + const char *decoder_id = deadbeef->pl_find_meta (it, ":DECODER"); + if (deadbeef->pl_is_selected (it) && deadbeef->is_local_file (deadbeef->pl_find_meta (it, ":URI")) && decoder_id) { uint32_t f = deadbeef->pl_get_item_flags (it); if (!(f & DDB_IS_SUBTRACK)) { f &= ~DDB_TAG_MASK; deadbeef->pl_set_item_flags (it, f); DB_decoder_t **decoders = deadbeef->plug_get_decoder_list (); for (int i = 0; decoders[i]; i++) { - if (!strcmp (decoders[i]->plugin.id, it->decoder_id)) { + if (!strcmp (decoders[i]->plugin.id, decoder_id)) { if (decoders[i]->read_metadata) { decoders[i]->read_metadata (it); } @@ -337,8 +338,8 @@ on_remove_from_disk_activate (GtkMenuItem *menuitem, DB_playItem_t *it = deadbeef->pl_get_first (PL_MAIN); while (it) { - if (deadbeef->pl_is_selected (it) && deadbeef->is_local_file (it->fname)) { - unlink (it->fname); + if (deadbeef->pl_is_selected (it) && deadbeef->is_local_file (deadbeef->pl_find_meta (it, ":URI"))) { + unlink (deadbeef->pl_find_meta (it, ":URI")); } DB_playItem_t *next = deadbeef->pl_get_next (it, PL_MAIN); deadbeef->pl_item_unref (it); diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c index 49be5b81..889e4984 100644 --- a/plugins/gtkui/trkproperties.c +++ b/plugins/gtkui/trkproperties.c @@ -49,7 +49,7 @@ static DB_playItem_t **tracks; static int numtracks; static int -build_key_list (const char ***pkeys) { +build_key_list (const char ***pkeys, int props) { int sz = 20; const char **keys = malloc (sizeof (const char *) * sz); if (!keys) { @@ -63,7 +63,7 @@ build_key_list (const char ***pkeys) { for (int i = 0; i < numtracks; i++) { DB_metaInfo_t *meta = deadbeef->pl_get_metadata (tracks[i]); while (meta) { - if (meta->key[0] != ':') { + if ((props && meta->key[0] == ':') || (!props && meta->key[0] != ':')) { int k = 0; for (; k < n; k++) { if (meta->key == keys[k]) { @@ -91,7 +91,17 @@ build_key_list (const char ***pkeys) { } static int -get_field_value (char *out, int size, const char *key) { +equals_ptr (const char *a, const char *b) { + return a == b; +} + +static int +equals_value (const char *a, const char *b) { + return !strcmp (a, b); +} + +static int +get_field_value (char *out, int size, const char *key, const char *(*getter)(DB_playItem_t *it, const char *key), int (*equals)(const char *a, const char *b)) { int multiple = 0; *out = 0; if (numtracks == 0) { @@ -101,14 +111,14 @@ get_field_value (char *out, int size, const char *key) { const char **prev = malloc (sizeof (const char *) * numtracks); memset (prev, 0, sizeof (const char *) * numtracks); for (int i = 0; i < numtracks; i++) { - const char *val = deadbeef->pl_find_meta (tracks[i], key); + const char *val = getter (tracks[i], key); if (val && val[0] == 0) { val = NULL; } if (i > 0) { int n = 0; for (; n < i; n++) { - if (prev[n] == val) { + if (equals (prev[n], val)) { break; } } @@ -134,7 +144,8 @@ get_field_value (char *out, int size, const char *key) { } } if (size <= 1) { - strcpy (out-2, "…"); + gchar *prev = g_utf8_prev_char (out-4); + strcpy (prev, "..."); } free (prev); return multiple; @@ -229,23 +240,38 @@ static const char *types[] = { NULL }; +static const char *hc_props[] = { + ":URI", "Location", + ":TRACKNUM", "Subtrack Index", + ":DURATION", "Duration", + ":TAGS", "Tag Type(s)", + ":HAS_EMBEDDED_CUESHEET", "Embedded Cuesheet", + ":DECODER", "Codec", + NULL +}; + static inline float amp_to_db (float amp) { return 20*log10 (amp); } void -add_field (GtkListStore *store, const char *key, const char *title) { +add_field (GtkListStore *store, const char *key, const char *title, int is_prop) { // get value to edit const char mult[] = _("[Multiple values] "); char val[1000]; size_t ml = strlen (mult); memcpy (val, mult, ml+1); - int n = get_field_value (val + ml, sizeof (val) - ml, key); + int n = get_field_value (val + ml, sizeof (val) - ml, key, deadbeef->pl_find_meta, equals_ptr); GtkTreeIter iter; gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, title, 1, n ? val : val + ml, 2, key, 3, n ? 1 : 0, -1); + if (!is_prop) { + gtk_list_store_set (store, &iter, 0, title, 1, n ? val : val + ml, 2, key, 3, n ? 1 : 0, -1); + } + else { + gtk_list_store_set (store, &iter, 0, title, 1, n ? val : val + ml, -1); + } } void @@ -257,17 +283,14 @@ trkproperties_fill_metadata (void) { gtk_list_store_clear (store); deadbeef->pl_lock (); - struct timeval tm1; - gettimeofday (&tm1, NULL); - const char **keys = NULL; - int nkeys = build_key_list (&keys); + int nkeys = build_key_list (&keys, 0); int k; // add "standard" fields for (int i = 0; types[i]; i += 2) { - add_field (store, types[i], _(types[i+1])); + add_field (store, types[i], _(types[i+1]), 0); } // add all other fields @@ -286,70 +309,35 @@ trkproperties_fill_metadata (void) { if (!types[i]) { snprintf (title, sizeof (title), "<%s>", keys[k]); } - add_field (store, keys[k], title); + add_field (store, keys[k], title, 0); } if (keys) { free (keys); } - // unknown fields and properties - if (numtracks == 1) { - DB_playItem_t *track = tracks[0]; - - DB_metaInfo_t *meta = deadbeef->pl_get_metadata (track); - while (meta) { - if (meta->key[0] == ':') { - int l = strlen (meta->key)-1; - char title[l+3]; - snprintf (title, sizeof (title), "<%s>", meta->key+1); - const char *value = meta->value; - - GtkTreeIter iter; - gtk_list_store_append (propstore, &iter); - gtk_list_store_set (propstore, &iter, 0, title, 1, value, -1); - meta = meta->next; - continue; + // hardcoded properties + for (int i = 0; hc_props[i]; i += 2) { + add_field (propstore, hc_props[i], _(hc_props[i+1]), 1); + } + // properties + keys = NULL; + nkeys = build_key_list (&keys, 1); + for (int k = 0; k < nkeys; k++) { + int i; + for (i = 0; hc_props[i]; i += 2) { + if (!strcmp (keys[k], hc_props[i])) { + break; } - meta = meta->next; } - - // properties - char temp[200]; - GtkTreeIter iter; - gtk_list_store_clear (propstore); - gtk_list_store_append (propstore, &iter); - gtk_list_store_set (propstore, &iter, 0, _("Location"), 1, track->fname, -1); - gtk_list_store_append (propstore, &iter); - snprintf (temp, sizeof (temp), "%d", track->tracknum); - gtk_list_store_set (propstore, &iter, 0, _("Subtrack Index"), 1, temp, -1); - gtk_list_store_append (propstore, &iter); - deadbeef->pl_format_time (deadbeef->pl_get_item_duration (track), temp, sizeof (temp)); - gtk_list_store_set (propstore, &iter, 0, _("Duration"), 1, temp, -1); - gtk_list_store_append (propstore, &iter); - deadbeef->pl_format_title (track, -1, temp, sizeof (temp), -1, "%T"); - gtk_list_store_set (propstore, &iter, 0, _("Tag Type(s)"), 1, temp, -1); - gtk_list_store_append (propstore, &iter); - gtk_list_store_set (propstore, &iter, 0, _("Embedded Cuesheet"), 1, (deadbeef->pl_get_item_flags (track) & DDB_HAS_EMBEDDED_CUESHEET) ? _("Yes") : _("No"), -1); - gtk_list_store_append (propstore, &iter); - gtk_list_store_set (propstore, &iter, 0, _("Codec"), 1, track->decoder_id, -1); - - gtk_list_store_append (propstore, &iter); - snprintf (temp, sizeof (temp), "%0.2f dB", track->replaygain_album_gain); - gtk_list_store_set (propstore, &iter, 0, "ReplayGain Album Gain", 1, temp, -1); - gtk_list_store_append (propstore, &iter); - snprintf (temp, sizeof (temp), "%0.6f", track->replaygain_album_peak); - gtk_list_store_set (propstore, &iter, 0, "ReplayGain Album Peak", 1, temp, -1); - - gtk_list_store_append (propstore, &iter); - snprintf (temp, sizeof (temp), "%0.2f dB", track->replaygain_track_gain); - gtk_list_store_set (propstore, &iter, 0, "ReplayGain Track Gain", 1, temp, -1); - gtk_list_store_append (propstore, &iter); - snprintf (temp, sizeof (temp), "%0.6f", track->replaygain_track_peak); - gtk_list_store_set (propstore, &iter, 0, "ReplayGain Track Peak", 1, temp, -1); - - struct timeval tm2; - gettimeofday (&tm2, NULL); - int ms = (tm2.tv_sec*1000+tm2.tv_usec/1000) - (tm1.tv_sec*1000+tm1.tv_usec/1000); + if (hc_props[i]) { + continue; + } + char title[1000]; + snprintf (title, sizeof (title), "<%s>", keys[k]+1); + add_field (propstore, keys[k], title, 1); + } + if (keys) { + free (keys); } deadbeef->pl_unlock (); @@ -402,13 +390,14 @@ show_track_properties_dlg (DB_playItem_t *it) { int is_subtrack = deadbeef->pl_get_item_flags (it) & DDB_IS_SUBTRACK; - if (!is_subtrack && deadbeef->is_local_file (it->fname)) { + if (!is_subtrack && deadbeef->is_local_file (deadbeef->pl_find_meta (it, ":URI"))) { // get decoder plugin by id DB_decoder_t *dec = NULL; - if (it->decoder_id) { + const char *decoder_id = deadbeef->pl_find_meta (it, ":DECODER"); + if (decoder_id) { DB_decoder_t **decoders = deadbeef->plug_get_decoder_list (); for (int i = 0; decoders[i]; i++) { - if (!strcmp (decoders[i]->plugin.id, it->decoder_id)) { + if (!strcmp (decoders[i]->plugin.id, decoder_id)) { dec = decoders[i]; break; } @@ -512,12 +501,13 @@ on_write_tags_clicked (GtkButton *button, gtk_tree_model_foreach (model, set_metadata_cb, NULL); for (int t = 0; t < numtracks; t++) { DB_playItem_t *track = tracks[t]; - if (track && track->decoder_id) { + const char *decoder_id = deadbeef->pl_find_meta (track, ":DECODER"); + if (track && decoder_id) { // find decoder DB_decoder_t *dec = NULL; DB_decoder_t **decoders = deadbeef->plug_get_decoder_list (); for (int i = 0; decoders[i]; i++) { - if (!strcmp (decoders[i]->plugin.id, track->decoder_id)) { + if (!strcmp (decoders[i]->plugin.id, decoder_id)) { dec = decoders[i]; if (dec->write_metadata) { dec->write_metadata (track); diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c index 51ac0115..2632a453 100644 --- a/plugins/mpgmad/mpgmad.c +++ b/plugins/mpgmad/mpgmad.c @@ -646,7 +646,7 @@ cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) { mpgmad_info_t *info = (mpgmad_info_t *)_info; _info->plugin = &plugin; memset (&info->buffer, 0, sizeof (info->buffer)); - info->buffer.file = deadbeef->fopen (it->fname); + info->buffer.file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->buffer.file) { return -1; } @@ -719,7 +719,7 @@ cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) { trace ("duration=%f, endsample=%d, totalsamples=%d\n", info->buffer.duration, info->buffer.endsample, info->buffer.totalsamples); } if (info->buffer.samplerate == 0) { - trace ("bad mpeg file: %f\n", it->fname); + trace ("bad mpeg file: %f\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } _info->fmt.bps = info->buffer.bitspersample; @@ -1192,13 +1192,11 @@ cmp3_insert (DB_playItem_t *after, const char *fname) { return NULL; } if (fp->vfs->is_streaming ()) { - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); deadbeef->fclose (fp); deadbeef->pl_add_meta (it, "title", NULL); deadbeef->pl_set_item_duration (it, -1); - it->filetype = NULL;//filetypes[0]; + it->filetype = NULL; after = deadbeef->pl_insert_item (after, it); deadbeef->pl_item_unref (it); return after; @@ -1259,9 +1257,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) { break; } } - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); deadbeef->rewind (fp); // reset tags @@ -1295,7 +1291,7 @@ cmp3_insert (DB_playItem_t *after, const char *fname) { int cmp3_read_metadata (DB_playItem_t *it) { - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } diff --git a/plugins/musepack/musepack.c b/plugins/musepack/musepack.c index 93a59376..26eede96 100644 --- a/plugins/musepack/musepack.c +++ b/plugins/musepack/musepack.c @@ -97,7 +97,7 @@ musepack_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->reader.get_size = musepack_vfs_get_size; info->reader.canseek = musepack_vfs_canseek; - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } @@ -377,11 +377,9 @@ musepack_insert (DB_playItem_t *after, const char *fname) { int i; for (i = 0; i < nchapters; i++) { const mpc_chap_info *ch = mpc_demux_chap (demux, i); - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "MusePack"; - it->tracknum = i; + deadbeef->pl_set_meta_int (it, ":TRACKNUM", i); it->startsample = ch->sample; it->endsample = totalsamples-1; float gain = gain_title, peak = peak_title; @@ -391,10 +389,10 @@ musepack_insert (DB_playItem_t *after, const char *fname) { if (ch->peak != 0) { peak = pow (10, ch->peak / (20.0 * 256.0)) / (1<<15); } - it->replaygain_album_gain = gain_album; - it->replaygain_album_peak = peak_album; - it->replaygain_track_gain = gain_title; - it->replaygain_track_peak = peak_title; + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, gain_album); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, peak_album); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, gain_title); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, peak_title); deadbeef->pl_set_item_flags (it, DDB_IS_SUBTRACK); if (!prev) { meta = deadbeef->pl_item_alloc (); @@ -432,17 +430,15 @@ musepack_insert (DB_playItem_t *after, const char *fname) { return after; } - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "MusePack"; deadbeef->pl_set_item_duration (it, dur); /*int apeerr = */deadbeef->junk_apev2_read (it, fp); - it->replaygain_album_gain = gain_album; - it->replaygain_album_peak = peak_album; - it->replaygain_track_gain = gain_title; - it->replaygain_track_peak = peak_title; + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, gain_album); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, peak_album); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, gain_title); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, peak_title); deadbeef->fclose (fp); @@ -486,7 +482,7 @@ musepack_insert (DB_playItem_t *after, const char *fname) { } static int musepack_read_metadata (DB_playItem_t *it) { - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } diff --git a/plugins/notify/notify.c b/plugins/notify/notify.c index ea382b16..6bd42ab8 100644 --- a/plugins/notify/notify.c +++ b/plugins/notify/notify.c @@ -200,7 +200,7 @@ static void show_notification (DB_playItem_t *track) { if (deadbeef->conf_get_int("notify.albumart", 0) && artwork_plugin) { const char *album = deadbeef->pl_find_meta (track, "album"); const char *artist = deadbeef->pl_find_meta (track, "artist"); - v_iconname = artwork_plugin->get_album_art (track->fname, artist, album, deadbeef->conf_get_int ("notify.albumart_size", 64), cover_avail_callback, NULL); + v_iconname = artwork_plugin->get_album_art (deadbeef->pl_find_meta (track, ":URI"), artist, album, deadbeef->conf_get_int ("notify.albumart_size", 64), cover_avail_callback, NULL); } if (!v_iconname) { v_iconname = strdup ("deadbeef"); diff --git a/plugins/shellexec/shellexec.c b/plugins/shellexec/shellexec.c index f61d255f..a2c60af4 100644 --- a/plugins/shellexec/shellexec.c +++ b/plugins/shellexec/shellexec.c @@ -102,7 +102,7 @@ shx_callback (Shx_action_t *action, DB_playItem_t *it) static DB_plugin_action_t * shx_get_actions (DB_playItem_t *it) { - int is_local = it ? deadbeef->is_local_file (it->fname) : 1; + int is_local = it ? deadbeef->is_local_file (deadbeef->pl_find_meta (it, ":URI")) : 1; Shx_action_t *action; for (action = actions; action; action = (Shx_action_t *)action->parent.next) diff --git a/plugins/sid/csid.cpp b/plugins/sid/csid.cpp index 6583761e..2e8d00a8 100644 --- a/plugins/sid/csid.cpp +++ b/plugins/sid/csid.cpp @@ -302,7 +302,7 @@ csid_init (DB_fileinfo_t *_info, DB_playItem_t *it) { // libsidplay crashes if file doesn't exist // so i have to check it here - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp ){ return -1; } @@ -321,9 +321,9 @@ csid_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->resid->sampling (samplerate); info->duration = deadbeef->pl_get_item_duration (it); - info->tune = new SidTune (it->fname); + info->tune = new SidTune (deadbeef->pl_find_meta (it, ":URI")); - info->tune->selectSong (it->tracknum+1); + info->tune->selectSong (deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0)+1); sid2_config_t conf; conf = info->sidplay->config (); conf.frequency = samplerate; @@ -514,10 +514,8 @@ csid_insert (DB_playItem_t *after, const char *fname) { for (int s = 0; s < tunes; s++) { trace ("select %d...\n", s); if (tune->selectSong (s+1)) { - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (sid_plugin.plugin.id); - it->fname = strdup (fname); - it->tracknum = s; + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, sid_plugin.plugin.id); + deadbeef->pl_set_meta_int (it, ":TRACKNUM", s); SidTuneInfo sidinfo; tune->getInfo (sidinfo); int i = sidinfo.numberOfInfoStrings; diff --git a/plugins/sndfile/sndfile.c b/plugins/sndfile/sndfile.c index 85c96907..57d09763 100644 --- a/plugins/sndfile/sndfile.c +++ b/plugins/sndfile/sndfile.c @@ -155,9 +155,9 @@ sndfile_init (DB_fileinfo_t *_info, DB_playItem_t *it) { sndfile_info_t *info = (sndfile_info_t*)_info; SF_INFO inf; - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { - trace ("sndfile: failed to open %s\n", it->fname); + trace ("sndfile: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } int fsize = deadbeef->fgetlength (fp); @@ -315,9 +315,7 @@ sndfile_insert (DB_playItem_t *after, const char *fname) { deadbeef->fclose (info.file); float duration = (float)totalsamples / samplerate; - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "wav"; deadbeef->pl_set_item_duration (it, duration); diff --git a/plugins/tta/ttaplug.c b/plugins/tta/ttaplug.c index cded5264..22df3ad0 100644 --- a/plugins/tta/ttaplug.c +++ b/plugins/tta/ttaplug.c @@ -61,14 +61,14 @@ static int tta_init (DB_fileinfo_t *_info, DB_playItem_t *it) { tta_info_t *info = (tta_info_t *)_info; - trace ("open_tta_file %s\n", it->fname); - if (open_tta_file (it->fname, &info->tta, 0) != 0) { - fprintf (stderr, "tta: failed to open %s\n", it->fname); + trace ("open_tta_file %s\n", deadbeef->pl_find_meta (it, ":URI")); + if (open_tta_file (deadbeef->pl_find_meta (it, ":URI"), &info->tta, 0) != 0) { + fprintf (stderr, "tta: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } if (player_init (&info->tta) != 0) { - fprintf (stderr, "tta: failed to init player for %s\n", it->fname); + fprintf (stderr, "tta: failed to init player for %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } @@ -90,7 +90,7 @@ tta_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->startsample = 0; info->endsample = (info->tta.DATALENGTH)-1; } - trace ("open_tta_file %s success!\n", it->fname); + trace ("open_tta_file %s success!\n", deadbeef->pl_find_meta (it, ":URI")); return 0; } @@ -193,9 +193,7 @@ tta_insert (DB_playItem_t *after, const char *fname) { int totalsamples = tta.DATALENGTH; double dur = tta.LENGTH; - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "TTA"; deadbeef->pl_set_item_duration (it, dur); @@ -252,7 +250,7 @@ tta_insert (DB_playItem_t *after, const char *fname) { } static int tta_read_metadata (DB_playItem_t *it) { - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c index b450530c..553df92d 100644 --- a/plugins/vorbis/vorbis.c +++ b/plugins/vorbis/vorbis.c @@ -130,16 +130,16 @@ update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc, int refresh_playl deadbeef->pl_add_meta (it, "cuesheet", s + 9); } else if (!strncasecmp (s, "replaygain_album_gain=", 22)) { - it->replaygain_album_gain = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (s+22)); } else if (!strncasecmp (s, "replaygain_album_peak=", 22)) { - it->replaygain_album_peak = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (s+22)); } else if (!strncasecmp (s, "replaygain_track_gain=", 22)) { - it->replaygain_track_gain = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (s+22)); } else if (!strncasecmp (s, "replaygain_track_peak=", 22)) { - it->replaygain_track_peak = atof (s + 22); + deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s+22)); } } } @@ -174,12 +174,13 @@ cvorbis_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->cur_bit_stream = -1; } else { - info->cur_bit_stream = it->tracknum; + int tracknum = deadbeef->pl_find_meta_int (it, ":TRACKNUM", -1); + info->cur_bit_stream = tracknum; } info->ptrack = it; deadbeef->pl_item_ref (it); - info->info.file = deadbeef->fopen (it->fname); + info->info.file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->info.file) { trace ("ogg: failed to open file %s\n", it->fname); return -1; @@ -434,8 +435,7 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) { } int64_t fsize = deadbeef->fgetlength (fp); if (fp->vfs->is_streaming ()) { - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "OggVorbis"; deadbeef->pl_set_item_duration (it, -1); deadbeef->pl_add_meta (it, "title", NULL); @@ -471,11 +471,9 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) { float duration = ov_time_total (&vorbis_file, stream); int totalsamples = ov_pcm_total (&vorbis_file, stream); - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "OggVorbis"; - it->tracknum = stream; + deadbeef->pl_set_meta_int (it, ":TRACKNUM", stream); deadbeef->pl_set_item_duration (it, duration); if (nstreams > 1) { it->startsample = currentsample; @@ -549,7 +547,7 @@ cvorbis_read_metadata (DB_playItem_t *it) { OggVorbis_File vorbis_file; vorbis_info *vi = NULL; - fp = deadbeef->fopen (it->fname); + fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { trace ("cvorbis_read_metadata: failed to fopen %s\n", it->fname); return -1; @@ -569,14 +567,15 @@ cvorbis_read_metadata (DB_playItem_t *it) { trace ("cvorbis_read_metadata: ov_open_callbacks returned %d\n", res); goto error; } - vi = ov_info (&vorbis_file, it->tracknum); + int tracknum = deadbeef->pl_find_meta_int (it, ":TRACKNUM", -1); + vi = ov_info (&vorbis_file, tracknum); if (!vi) { // not a vorbis stream trace ("cvorbis_read_metadata: failed to ov_open %s\n", it->fname); goto error; } // metainfo - vorbis_comment *vc = ov_comment (&vorbis_file, it->tracknum); + vorbis_comment *vc = ov_comment (&vorbis_file, tracknum); if (vc) { update_vorbis_comments (it, vc, 0); } @@ -612,7 +611,7 @@ cvorbis_write_metadata (DB_playItem_t *it) { trace ("cvorbis_write_metadata: vcedit_new_state failed\n"); return -1; } - fp = fopen (it->fname, "rb"); + fp = fopen (deadbeef->pl_find_meta (it, ":URI"), "rb"); if (!fp) { trace ("cvorbis_write_metadata: failed to read metadata from %s\n", it->fname); goto error; @@ -683,7 +682,7 @@ cvorbis_write_metadata (DB_playItem_t *it) { vorbis_comment_add (vc, f->data); } - snprintf (outname, sizeof (outname), "%s.temp.ogg", it->fname); + snprintf (outname, sizeof (outname), "%s.temp.ogg", deadbeef->pl_find_meta (it, ":URI")); out = fopen (outname, "w+b"); if (!out) { @@ -714,7 +713,7 @@ error: } if (!err) { - rename (outname, it->fname); + rename (outname, deadbeef->pl_find_meta (it, ":URI")); } else if (out) { unlink (outname); diff --git a/plugins/vtx/vtx.c b/plugins/vtx/vtx.c index 79eb8cb2..27777981 100644 --- a/plugins/vtx/vtx.c +++ b/plugins/vtx/vtx.c @@ -62,9 +62,9 @@ vtx_init (DB_fileinfo_t *_info, DB_playItem_t *it) { size_t sz = 0; char *buf = NULL; - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { - trace ("vtx: failed to open file %s\n", it->fname); + trace ("vtx: failed to open file %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } @@ -258,10 +258,7 @@ vtx_insert (DB_playItem_t *after, const char *fname) { } trace ("vtx: datasize: %d\n", hdr->regdata_size); - DB_playItem_t *it = deadbeef->pl_item_alloc (); - - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = filetypes[0]; int numframes = hdr->regdata_size / AY_FRAME_SIZE; diff --git a/plugins/wavpack/wavpack.c b/plugins/wavpack/wavpack.c index 44177f05..6646183b 100644 --- a/plugins/wavpack/wavpack.c +++ b/plugins/wavpack/wavpack.c @@ -125,15 +125,15 @@ wv_open (uint32_t hints) { static int wv_init (DB_fileinfo_t *_info, DB_playItem_t *it) { wvctx_t *info = (wvctx_t *)_info; - info->file = deadbeef->fopen (it->fname); + info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->file) { return -1; } #ifndef TINYWV - char *c_fname = alloca (strlen (it->fname) + 2); + char *c_fname = alloca (strlen (deadbeef->pl_find_meta (it, ":URI")) + 2); if (c_fname) { - strcpy (c_fname, it->fname); + strcpy (c_fname, deadbeef->pl_find_meta (it, ":URI")); strcat (c_fname, "c"); info->c_file = deadbeef->fopen (c_fname); } @@ -295,9 +295,7 @@ wv_insert (DB_playItem_t *after, const char *fname) { int samplerate = WavpackGetSampleRate (ctx); float duration = (float)totalsamples / samplerate; - DB_playItem_t *it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id); - it->fname = strdup (fname); + DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); it->filetype = "wv"; deadbeef->pl_set_item_duration (it, duration); trace ("wv: totalsamples=%d, samplerate=%d, duration=%f\n", totalsamples, samplerate, duration); @@ -370,7 +368,7 @@ wv_insert (DB_playItem_t *after, const char *fname) { int wv_read_metadata (DB_playItem_t *it) { - DB_FILE *fp = deadbeef->fopen (it->fname); + DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { return -1; } diff --git a/plugins/wildmidi/wildmidiplug.c b/plugins/wildmidi/wildmidiplug.c index 4136745d..ca26e497 100644 --- a/plugins/wildmidi/wildmidiplug.c +++ b/plugins/wildmidi/wildmidiplug.c @@ -52,9 +52,9 @@ int wmidi_init (DB_fileinfo_t *_info, DB_playItem_t *it) { wmidi_info_t *info = (wmidi_info_t *)_info; - info->m = WildMidi_Open (it->fname); + info->m = WildMidi_Open (deadbeef->pl_find_meta (it, ":URI")); if (!info->m) { - trace ("wmidi: failed to open %s\n", it->fname); + trace ("wmidi: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } @@ -117,9 +117,7 @@ wmidi_insert (DB_playItem_t *after, const char *fname) { } struct _WM_Info *inf = WildMidi_GetInfo (m); - it = deadbeef->pl_item_alloc (); - it->decoder_id = deadbeef->plug_get_decoder_id (wmidi_plugin.plugin.id); - it->fname = strdup (fname); + it = deadbeef->pl_item_alloc_init (fname, wmidi_plugin.plugin.id); deadbeef->pl_add_meta (it, "title", NULL); deadbeef->pl_set_item_duration (it, inf->approx_total_samples / 44100.f); it->filetype = "MID"; diff --git a/replaygain.c b/replaygain.c index 335cd8b0..efe89ba9 100644 --- a/replaygain.c +++ b/replaygain.c @@ -24,6 +24,10 @@ static int conf_replaygain_mode = 0; static int conf_replaygain_scale = 1; +static float rg_albumgain = 1; +static float rg_albumpeak = 1; +static float rg_trackgain = 1; +static float rg_trackpeak = 1; void replaygain_apply (ddb_waveformat_t *fmt, playItem_t *it, char *bytes, int bytesread) { @@ -52,33 +56,50 @@ replaygain_set (int mode, int scale) { } void -apply_replay_gain_int8 (playItem_t *it, char *bytes, int size) { - if (!conf_replaygain_mode) { - return; - } +replaygain_set_values (float albumgain, float albumpeak, float trackgain, float trackpeak) { + rg_albumgain = db_to_amp (albumgain); + rg_trackgain = db_to_amp (trackgain); + rg_albumpeak = albumpeak; + rg_trackpeak = trackpeak; +} + +static inline int +get_int_volume (void) { int vol = 1000; if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { - return; + if (rg_trackgain == 1) { + return -1; } - vol = db_to_amp (it->replaygain_track_gain) * 1000; + vol = rg_trackgain * 1000; if (conf_replaygain_scale) { - if (vol * it->replaygain_track_peak > 1000) { - vol = 1000 / it->replaygain_track_peak; + if (vol * rg_trackpeak > 1000) { + vol = 1000 / rg_trackpeak; } } } else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { - return; + if (rg_albumgain == 1) { + return -1; } - vol = db_to_amp (it->replaygain_album_gain) * 1000; + vol = rg_albumgain * 1000; if (conf_replaygain_scale) { - if (vol * it->replaygain_album_peak > 1000) { - vol = 1000 / it->replaygain_album_peak; + if (vol * rg_albumpeak > 1000) { + vol = 1000 / rg_albumpeak; } } } + return vol; +} + +void +apply_replay_gain_int8 (playItem_t *it, char *bytes, int size) { + if (!conf_replaygain_mode) { + return; + } + int vol = get_int_volume (); + if (vol < 0) { + return; + } int8_t *s = (int8_t*)bytes; for (int j = 0; j < size; j++) { int32_t sample = ((int8_t)(*s)) * vol / 1000; @@ -98,28 +119,9 @@ apply_replay_gain_int16 (playItem_t *it, char *bytes, int size) { if (!conf_replaygain_mode) { return; } - int vol = 1000; - if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_track_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_track_peak > 1000) { - vol = 1000 / it->replaygain_track_peak; - } - } - } - else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_album_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_album_peak > 1000) { - vol = 1000 / it->replaygain_album_peak; - } - } + int vol = get_int_volume (); + if (vol < 0) { + return; } int16_t *s = (int16_t*)bytes; for (int j = 0; j < size/2; j++) { @@ -140,28 +142,9 @@ apply_replay_gain_int24 (playItem_t *it, char *bytes, int size) { if (!conf_replaygain_mode) { return; } - int64_t vol = 1000; - if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_track_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_track_peak > 1000) { - vol = 1000 / it->replaygain_track_peak; - } - } - } - else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_album_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_album_peak > 1000) { - vol = 1000 / it->replaygain_album_peak; - } - } + int64_t vol = get_int_volume (); + if (vol < 0) { + return; } char *s = (char*)bytes; for (int j = 0; j < size/3; j++) { @@ -185,28 +168,9 @@ apply_replay_gain_int32 (playItem_t *it, char *bytes, int size) { if (!conf_replaygain_mode) { return; } - int64_t vol = 1000; - if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_track_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_track_peak > 1000) { - vol = 1000 / it->replaygain_track_peak; - } - } - } - else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { - return; - } - vol = db_to_amp (it->replaygain_album_gain) * 1000; - if (conf_replaygain_scale) { - if (vol * it->replaygain_album_peak > 1000) { - vol = 1000 / it->replaygain_album_peak; - } - } + int64_t vol = get_int_volume (); + if (vol < 0) { + return; } int32_t *s = (int32_t*)bytes; for (int j = 0; j < size/4; j++) { @@ -229,24 +193,24 @@ apply_replay_gain_float32 (playItem_t *it, char *bytes, int size) { } float vol = 1.f; if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { + if (rg_trackgain == 1) { return; } - vol = db_to_amp (it->replaygain_track_gain); + vol = rg_trackgain; if (conf_replaygain_scale) { - if (vol * it->replaygain_track_peak > 1.f) { - vol = 1.f / it->replaygain_track_peak; + if (vol * rg_trackpeak > 1.f) { + vol = 1.f / rg_trackpeak; } } } else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { + if (rg_albumgain == 1) { return; } - vol = db_to_amp (it->replaygain_album_gain); + vol = rg_albumgain; if (conf_replaygain_scale) { - if (vol * it->replaygain_album_peak > 1.f) { - vol = 1.f / it->replaygain_album_peak; + if (vol * rg_albumpeak > 1.f) { + vol = 1.f / rg_albumpeak; } } } diff --git a/replaygain.h b/replaygain.h index 5169c99c..1ebf79fd 100644 --- a/replaygain.h +++ b/replaygain.h @@ -27,6 +27,9 @@ replaygain_apply (ddb_waveformat_t *fmt, playItem_t *it, char *bytes, int bytesr void replaygain_set (int mode, int scale); +void +replaygain_set_values (float albumgain, float albumpeak, float trackgain, float trackpeak); + void apply_replay_gain_int8 (playItem_t *it, char *bytes, int size); diff --git a/streamer.c b/streamer.c index 380cd30c..07740544 100644 --- a/streamer.c +++ b/streamer.c @@ -151,12 +151,20 @@ streamer_start_playback (playItem_t *from, playItem_t *it) { playing_track = it; if (playing_track) { pl_item_ref (playing_track); + + // setup replaygain + float albumgain = pl_get_item_replaygain (playing_track, DDB_REPLAYGAIN_ALBUMGAIN); + float albumpeak = pl_get_item_replaygain (playing_track, DDB_REPLAYGAIN_ALBUMPEAK); + float trackgain = pl_get_item_replaygain (playing_track, DDB_REPLAYGAIN_TRACKGAIN); + float trackpeak = pl_get_item_replaygain (playing_track, DDB_REPLAYGAIN_TRACKPEAK); + replaygain_set_values (albumgain, albumpeak, trackgain, trackpeak); + printf ("played=1 [1]\n"); playing_track->played = 1; playing_track->started_timestamp = time (NULL); trace ("sending songstarted to plugins [2] current playtrack: %s\n", playing_track->fname); plug_trigger_event (DB_EV_SONGSTARTED, 0); - trace ("from=%p (%s), to=%p (%s) [2]\n", from, from ? from->fname : "null", it, it ? it->fname : "null"); + trace ("from=%p (%s), to=%p (%s) [2]\n", from, from ? from->fname : "null", it, it ? pl_find_meta (it, ":URI") : "null"); plug_trigger_event_trackchange (from, it); } if (from) { @@ -246,16 +254,16 @@ streamer_move_to_nextsong (int reason) { return 0; } else { - trace ("%s not found in current streaming playlist\n", it->fname); + trace ("%s not found in current streaming playlist\n", pl_find_meta (it, ":URI")); // find playlist playlist_t *old = streamer_playlist; streamer_playlist = plt_get_list (); int i = 0; while (streamer_playlist) { - trace ("searching for %s in playlist %d\n", it->fname, i); + trace ("searching for %s in playlist %d\n", pl_find_meta (it, ":URI"), i); int r = str_get_idx_of (it); if (r >= 0) { - trace ("%s found in playlist %d\n", it->fname, i); + trace ("%s found in playlist %d\n", pl_find_meta (it, ":URI"), i); pl_item_unref (it); streamer_set_nextsong (r, 3); pl_global_unlock (); @@ -264,7 +272,7 @@ streamer_move_to_nextsong (int reason) { i++; streamer_playlist = streamer_playlist->next; } - trace ("%s not found in any playlists\n", it->fname); + trace ("%s not found in any playlists\n", pl_find_meta (it, ":URI")); streamer_playlist = old; pl_item_unref (it); } @@ -591,11 +599,12 @@ streamer_set_current (playItem_t *it) { if (from) { plug_trigger_event_trackinfochanged (from); } - if (!it->decoder_id && it->filetype && !strcmp (it->filetype, "content")) { + const char *decoder_id = pl_find_meta (it, ":DECODER"); + if (!decoder_id && it->filetype && !strcmp (it->filetype, "content")) { // try to get content-type mutex_lock (decodemutex); - trace ("\033[0;34mopening file %s\033[37;0m\n", it->fname); - DB_FILE *fp = streamer_file = vfs_fopen (it->fname); + trace ("\033[0;34mopening file %s\033[37;0m\n", pl_find_meta (it, ":URI")); + DB_FILE *fp = streamer_file = vfs_fopen (pl_find_meta (it, ":URI")); mutex_unlock (decodemutex); const char *plug = NULL; if (fp && vfs_get_content_type) { @@ -628,22 +637,23 @@ streamer_set_current (playItem_t *it) { // match by decoder for (int i = 0; decoders[i]; i++) { if (!strcmp (decoders[i]->plugin.id, plug)) { - it->decoder_id = decoders[i]->plugin.id; + pl_replace_meta (it, ":DECODER", decoders[i]->plugin.id); + decoder_id = decoders[i]->plugin.id; it->filetype = decoders[i]->filetypes[0]; trace ("\033[0;34mfound plugin %s\033[37;0m\n", plug); } } } else { - trace ("\033[0;34mclosed file %s (bad or interrupted)\033[37;0m\n", it->fname); + trace ("\033[0;34mclosed file %s (bad or interrupted)\033[37;0m\n", pl_find_meta (it, ":URI")); } } playlist_track = it; - if (it->decoder_id) { + if (decoder_id) { DB_decoder_t *dec = NULL; - dec = plug_get_decoder_for_id (it->decoder_id); + dec = plug_get_decoder_for_id (decoder_id); if (dec) { - trace ("\033[0;33minit decoder for %s (%s)\033[37;0m\n", it->fname, it->decoder_id); + trace ("\033[0;33minit decoder for %s (%s)\033[37;0m\n", pl_find_meta (it, ":URI"), decoder_id); new_fileinfo = dec->open (0); if (new_fileinfo && dec->init (new_fileinfo, DB_PLAYITEM (it)) != 0) { trace ("\033[0;31mfailed to init decoder\033[37;0m\n") @@ -1040,7 +1050,8 @@ streamer_thread (void *ctx) { mutex_lock (decodemutex); DB_decoder_t *dec = NULL; - dec = plug_get_decoder_for_id (streaming_track->decoder_id); + const char *decoder_id = pl_find_meta (streaming_track, ":DECODER"); + dec = plug_get_decoder_for_id (decoder_id); if (dec) { fileinfo = dec->open (0); if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (streaming_track)) != 0) { @@ -1067,8 +1078,9 @@ streamer_thread (void *ctx) { if (streaming_track) { plug_trigger_event_trackinfochanged (streaming_track); } - if (fileinfo && playing_track && playing_track->_duration > 0) { - if (pos >= playing_track->_duration) { + float dur = pl_get_item_duration (playing_track); + if (fileinfo && playing_track && dur > 0) { + if (pos >= dur) { output->stop (); streamer_move_to_nextsong (1); continue; -- cgit v1.2.3