From eef2dde3435d90b61155bf07ea9aaccab8b0bbad Mon Sep 17 00:00:00 2001 From: datasone Date: Tue, 11 Apr 2023 22:43:35 +0800 Subject: [PATCH 1/2] Add `real_uri` property into `mpd_song` CUE virtual playlists is currently implemented by accessing ranges in file referenced by `real_uri`. But the `real_uri` is not included in the song info protocol now, thus `ProxyDatabasePlugin` is not able to retreive this information and access the corresponding file, leads to not working cue tracks in satellite setup. This commit parses the `real_uri` information returned by mpd server with key name `RealUri`, and adds `real_uri` property and `mpd_song_get_real_uri` function for storing and accessing `real_uri`. --- include/mpd/song.h | 9 +++++++++ libmpdclient.ld | 1 + src/song.c | 27 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/include/mpd/song.h b/include/mpd/song.h index 9323f535..c733c290 100644 --- a/include/mpd/song.h +++ b/include/mpd/song.h @@ -100,6 +100,15 @@ const char * mpd_song_get_tag(const struct mpd_song *song, enum mpd_tag_type type, unsigned idx); +/** + * Returns the "real" URI of the song, the one to be used for opening + * the resource. If this attribute is nullptr, then #mpd_song_get_uri + * shall be used. + */ +mpd_pure +const char * +mpd_song_get_real_uri(const struct mpd_song *song); + /** * Returns the duration of this song in seconds. 0 means the duration * is unknown. diff --git a/libmpdclient.ld b/libmpdclient.ld index f3633b4d..af5ba60e 100644 --- a/libmpdclient.ld +++ b/libmpdclient.ld @@ -362,6 +362,7 @@ global: mpd_song_dup; mpd_song_get_uri; mpd_song_get_tag; + mpd_song_get_real_uri; mpd_song_get_duration; mpd_song_get_duration_ms; mpd_song_get_start; diff --git a/src/song.c b/src/song.c index a0d18ecd..a209db91 100644 --- a/src/song.c +++ b/src/song.c @@ -55,6 +55,13 @@ struct mpd_song { struct mpd_tag_value tags[MPD_TAG_COUNT]; + /** + * The "real" URI, the one to be used for opening the + * resource. If this attribute is nullptr, then #uri + * shall be used. + */ + char *real_uri; + /** * Duration of the song in seconds, or 0 for unknown. */ @@ -136,6 +143,7 @@ mpd_song_new(const char *uri) for (unsigned i = 0; i < MPD_TAG_COUNT; ++i) song->tags[i].value = NULL; + song->real_uri = NULL; song->duration = 0; song->duration_ms = 0; song->start = 0; @@ -179,6 +187,8 @@ void mpd_song_free(struct mpd_song *song) { } } + free(song->real_uri); + free(song); } @@ -216,6 +226,7 @@ mpd_song_dup(const struct mpd_song *song) } while (src_tag != NULL); } + ret->real_uri = strdup(song->real_uri); ret->duration = song->duration; ret->duration_ms = song->duration_ms; ret->start = song->start; @@ -331,6 +342,20 @@ mpd_song_get_tag(const struct mpd_song *song, return tag->value; } +static void +mpd_song_set_real_uri(struct mpd_song *song, char *real_uri) +{ + song->real_uri = real_uri; +} + +const char * +mpd_song_get_real_uri(const struct mpd_song *song) +{ + assert(song != NULL); + + return song->real_uri; +} + static void mpd_song_set_duration(struct mpd_song *song, unsigned duration) { @@ -546,6 +571,8 @@ mpd_song_feed(struct mpd_song *song, const struct mpd_pair *pair) mpd_song_set_prio(song, strtoul(pair->value, NULL, 10)); else if (strcmp(pair->name, "Format") == 0) mpd_song_parse_audio_format(song, pair->value); + else if (strcmp(pair->name, "RealUri") == 0) + mpd_song_set_real_uri(song, strdup(pair->value)); return true; } From 86a9321173cb87268c54258e8886af2bf522f66d Mon Sep 17 00:00:00 2001 From: datasone Date: Tue, 11 Apr 2023 22:44:42 +0800 Subject: [PATCH 2/2] Add range start and end properties in milliseconds into `mpd_song` Range `start` and `end` values in `mpd_song` is stored in seconds only, which makes range times in `ProxySong` truncated to seconds and leads to precision loss on satellite cue track range times. This commit adds `start_ms` and `end_ms` properties to store range start and end times in milliseconds, and corresponding functions to access them: `mpd_song_get_start_ms`, `mpd_song_get_end_ms`. The values are parsed from float time values returned by mpd server. --- include/mpd/song.h | 16 ++++++++++++++++ libmpdclient.ld | 2 ++ src/song.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/mpd/song.h b/include/mpd/song.h index c733c290..c4f90639 100644 --- a/include/mpd/song.h +++ b/include/mpd/song.h @@ -137,6 +137,14 @@ mpd_pure unsigned mpd_song_get_start(const struct mpd_song *song); +/** + * Returns the start of the virtual song within the physical file in + * milliseconds. + */ +mpd_pure +unsigned +mpd_song_get_start_ms(const struct mpd_song *song); + /** * Returns the end of the virtual song within the physical file in * seconds. 0 means that the physical song file is played to the end. @@ -147,6 +155,14 @@ mpd_pure unsigned mpd_song_get_end(const struct mpd_song *song); +/** + * Returns the end of the virtual song within the physical file in + * milliseconds. 0 means that the physical song file is played to the end. + */ +mpd_pure +unsigned +mpd_song_get_end_ms(const struct mpd_song *song); + /** * @return the POSIX UTC time stamp of the last modification, or 0 if * that is unknown diff --git a/libmpdclient.ld b/libmpdclient.ld index af5ba60e..98ca371d 100644 --- a/libmpdclient.ld +++ b/libmpdclient.ld @@ -366,7 +366,9 @@ global: mpd_song_get_duration; mpd_song_get_duration_ms; mpd_song_get_start; + mpd_song_get_start_ms; mpd_song_get_end; + mpd_song_get_end_ms; mpd_song_get_last_modified; mpd_song_set_pos; mpd_song_get_pos; diff --git a/src/song.c b/src/song.c index a209db91..2fea65a3 100644 --- a/src/song.c +++ b/src/song.c @@ -78,6 +78,12 @@ struct mpd_song { */ unsigned start; + /** + * Start of the virtual song within the physical file in + * milliseconds. + */ + unsigned start_ms; + /** * End of the virtual song within the physical file in * seconds. Zero means that the physical song file is @@ -85,6 +91,13 @@ struct mpd_song { */ unsigned end; + /** + * End of the virtual song within the physical file in + * milliseconds. Zero means that the physical song + * file is played to the end. + */ + unsigned end_ms; + /** * The POSIX UTC time stamp of the last modification, or 0 if * that is unknown. @@ -147,7 +160,9 @@ mpd_song_new(const char *uri) song->duration = 0; song->duration_ms = 0; song->start = 0; + song->start_ms = 0; song->end = 0; + song->end_ms = 0; song->last_modified = 0; song->pos = 0; song->id = 0; @@ -230,7 +245,9 @@ mpd_song_dup(const struct mpd_song *song) ret->duration = song->duration; ret->duration_ms = song->duration_ms; ret->start = song->start; + ret->start_ms = song->start_ms; ret->end = song->end; + ret->end_ms = song->end_ms; ret->last_modified = song->last_modified; ret->pos = song->pos; ret->id = song->id; @@ -396,6 +413,14 @@ mpd_song_get_start(const struct mpd_song *song) return song->start; } +unsigned +mpd_song_get_start_ms(const struct mpd_song *song) +{ + assert(song != NULL); + + return song->start_ms; +} + unsigned mpd_song_get_end(const struct mpd_song *song) { @@ -404,6 +429,14 @@ mpd_song_get_end(const struct mpd_song *song) return song->end; } +unsigned +mpd_song_get_end_ms(const struct mpd_song *song) +{ + assert(song != NULL); + + return song->end_ms; +} + static void mpd_song_set_last_modified(struct mpd_song *song, time_t mtime) { @@ -508,15 +541,19 @@ mpd_song_parse_range(struct mpd_song *song, const char *value) } song->start = start > 0.0 ? (unsigned)start : 0; + song->start_ms = start > 0.0 ? (unsigned)(start * 1000) : 0; if (end > 0.0) { song->end = (unsigned)end; + song->end_ms = (unsigned)(end * 1000); if (song->end == 0) /* round up, because the caller must sees that there's an upper limit */ song->end = 1; - } else + } else { song->end = 0; + song->end_ms = 0; + } } static void