diff options
Diffstat (limited to '')
-rw-r--r-- | src/Song.cxx (renamed from src/song.c) | 102 |
1 files changed, 88 insertions, 14 deletions
diff --git a/src/song.c b/src/Song.cxx index f5cc7c35a..c845384ae 100644 --- a/src/song.c +++ b/src/Song.cxx @@ -19,26 +19,31 @@ #include "config.h" #include "song.h" -#include "uri.h" -#include "directory.h" +#include "Directory.hxx" + +extern "C" { #include "tag.h" +} #include <glib.h> #include <assert.h> +Directory detached_root; + static struct song * -song_alloc(const char *uri, struct directory *parent) +song_alloc(const char *uri, Directory *parent) { size_t uri_length; - struct song *song; assert(uri); uri_length = strlen(uri); assert(uri_length); - song = g_malloc(sizeof(*song) - sizeof(song->uri) + uri_length + 1); - song->tag = NULL; + struct song *song = (struct song *) + g_malloc(sizeof(*song) - sizeof(song->uri) + uri_length + 1); + + song->tag = nullptr; memcpy(song->uri, uri, uri_length + 1); song->parent = parent; song->mtime = 0; @@ -50,13 +55,13 @@ song_alloc(const char *uri, struct directory *parent) struct song * song_remote_new(const char *uri) { - return song_alloc(uri, NULL); + return song_alloc(uri, nullptr); } struct song * -song_file_new(const char *path, struct directory *parent) +song_file_new(const char *path, Directory *parent) { - assert((parent == NULL) == (*path == '/')); + assert((parent == nullptr) == (*path == '/')); return song_alloc(path, parent); } @@ -73,6 +78,35 @@ song_replace_uri(struct song *old_song, const char *uri) return new_song; } +struct song * +song_detached_new(const char *uri) +{ + assert(uri != nullptr); + + return song_alloc(uri, &detached_root); +} + +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_detached_new(uri); + 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) { @@ -81,17 +115,57 @@ song_free(struct song *song) g_free(song); } +gcc_pure +static inline bool +directory_equals(const Directory &a, const Directory &b) +{ + return strcmp(a.path, b.path) == 0; +} + +gcc_pure +static inline bool +directory_is_same(const Directory *a, const Directory *b) +{ + return a == b || + (a != nullptr && b != nullptr && + directory_equals(*a, *b)); + +} + +bool +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; +} + char * song_get_uri(const struct song *song) { - assert(song != NULL); + assert(song != nullptr); assert(*song->uri); - if (!song_in_database(song) || directory_is_root(song->parent)) + if (!song_in_database(song) || song->parent->IsRoot()) return g_strdup(song->uri); else - return g_strconcat(directory_get_path(song->parent), - "/", song->uri, NULL); + return g_strconcat(song->parent->GetPath(), + "/", song->uri, nullptr); } double @@ -100,7 +174,7 @@ song_get_duration(const struct song *song) if (song->end_ms > 0) return (song->end_ms - song->start_ms) / 1000.0; - if (song->tag == NULL) + if (song->tag == nullptr) return 0; return song->tag->time - song->start_ms / 1000.0; |