diff options
author | Max Kellermann <max@duempel.org> | 2012-08-15 22:44:21 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2012-08-15 23:07:24 +0200 |
commit | 916a02017333ac32b8058d3c397eeb4ec85b742b (patch) | |
tree | d68e24237cf924eb7c077407cb415968010e2cac /src | |
parent | c2e4fe983da690907316dac9cd1838fc713dec1b (diff) | |
download | mpd-916a02017333ac32b8058d3c397eeb4ec85b742b.tar.gz mpd-916a02017333ac32b8058d3c397eeb4ec85b742b.tar.xz mpd-916a02017333ac32b8058d3c397eeb4ec85b742b.zip |
Song: add function song_dup_detached()
Initial support for "detached" songs that come from the database, but
are private copies.
Diffstat (limited to 'src')
-rw-r--r-- | src/Song.cxx | 36 | ||||
-rw-r--r-- | src/mapper.c | 21 | ||||
-rw-r--r-- | src/song.h | 25 |
3 files changed, 81 insertions, 1 deletions
diff --git a/src/Song.cxx b/src/Song.cxx index 3dfdc0c74..2ef690fb0 100644 --- a/src/Song.cxx +++ b/src/Song.cxx @@ -29,6 +29,8 @@ extern "C" { #include <assert.h> +struct directory detached_root; + static struct song * song_alloc(const char *uri, struct directory *parent) { @@ -76,6 +78,27 @@ song_replace_uri(struct song *old_song, const char *uri) return new_song; } +struct song * +song_dup_detached(const struct song *src) +{ + assert(src != nullptr); + + struct song *song; + if (song_in_database(src)) { + char *uri = song_get_uri(src); + song = song_alloc(uri, &detached_root); + g_free(uri); + } else + song = song_alloc(src->uri, nullptr); + + song->tag = tag_dup(src->tag); + song->mtime = src->mtime; + song->start_ms = src->start_ms; + song->end_ms = src->end_ms; + + return song; +} + void song_free(struct song *song) { @@ -107,6 +130,19 @@ song_equals(const struct song *a, const struct song *b) assert(a != nullptr); assert(b != nullptr); + if (a->parent != nullptr && b->parent != nullptr && + !directory_equals(*a->parent, *b->parent) && + (a->parent == &detached_root || b->parent == &detached_root)) { + /* must compare the full URI if one of the objects is + "detached" */ + char *au = song_get_uri(a); + char *bu = song_get_uri(b); + const bool result = strcmp(au, bu) == 0; + g_free(bu); + g_free(au); + return result; + } + return directory_is_same(a->parent, b->parent) && strcmp(a->uri, b->uri) == 0; } diff --git a/src/mapper.c b/src/mapper.c index 7db74b1af..1f8a54b46 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -219,13 +219,32 @@ map_directory_child_fs(const struct directory *directory, const char *name) return path; } +/** + * Map a song object that was created by song_dup_detached(). It does + * not have a real parent directory, only the dummy object + * #detached_root. + */ +static char * +map_detached_song_fs(const char *uri_utf8) +{ + char *uri_fs = utf8_to_fs_charset(uri_utf8); + if (uri_fs == NULL) + return NULL; + + char *path = g_build_filename(music_dir_fs, uri_fs, NULL); + g_free(uri_fs); + return path; +} + char * map_song_fs(const struct song *song) { assert(song_is_file(song)); if (song_in_database(song)) - return map_directory_child_fs(song->parent, song->uri); + return song_is_detached(song) + ? map_detached_song_fs(song->uri) + : map_directory_child_fs(song->parent, song->uri); else return utf8_to_fs_charset(song->uri); } diff --git a/src/song.h b/src/song.h index 366ffc1a1..a09b69df2 100644 --- a/src/song.h +++ b/src/song.h @@ -23,6 +23,7 @@ #include "util/list.h" #include "gcc.h" +#include <assert.h> #include <stddef.h> #include <stdbool.h> #include <sys/time.h> @@ -59,6 +60,12 @@ struct song { char uri[sizeof(int)]; }; +/** + * A dummy #directory instance that is used for "detached" song + * copies. + */ +extern struct directory detached_root; + G_BEGIN_DECLS /** allocate a new song with a remote URL */ @@ -86,6 +93,15 @@ song_file_load(const char *path, struct directory *parent); struct song * song_replace_uri(struct song *song, const char *uri); +/** + * Creates a duplicate of the song object. If the object is in the + * database, it creates a "detached" copy of this song, see + * song_is_detached(). + */ +gcc_malloc +struct song * +song_dup_detached(const struct song *src); + void song_free(struct song *song); @@ -101,6 +117,15 @@ song_is_file(const struct song *song) return song_in_database(song) || song->uri[0] == '/'; } +static inline bool +song_is_detached(const struct song *song) +{ + assert(song != NULL); + assert(song_in_database(song)); + + return song->parent == &detached_root; +} + /** * Returns true if both objects refer to the same physical song. */ |