Commit 916a0201 authored by Max Kellermann's avatar Max Kellermann

Song: add function song_dup_detached()

Initial support for "detached" songs that come from the database, but are private copies.
parent c2e4fe98
...@@ -29,6 +29,8 @@ extern "C" { ...@@ -29,6 +29,8 @@ extern "C" {
#include <assert.h> #include <assert.h>
struct directory detached_root;
static struct song * static struct song *
song_alloc(const char *uri, struct directory *parent) song_alloc(const char *uri, struct directory *parent)
{ {
...@@ -76,6 +78,27 @@ song_replace_uri(struct song *old_song, const char *uri) ...@@ -76,6 +78,27 @@ song_replace_uri(struct song *old_song, const char *uri)
return new_song; 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 void
song_free(struct song *song) song_free(struct song *song)
{ {
...@@ -107,6 +130,19 @@ song_equals(const struct song *a, const struct song *b) ...@@ -107,6 +130,19 @@ song_equals(const struct song *a, const struct song *b)
assert(a != nullptr); assert(a != nullptr);
assert(b != 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) && return directory_is_same(a->parent, b->parent) &&
strcmp(a->uri, b->uri) == 0; strcmp(a->uri, b->uri) == 0;
} }
......
...@@ -219,13 +219,32 @@ map_directory_child_fs(const struct directory *directory, const char *name) ...@@ -219,13 +219,32 @@ map_directory_child_fs(const struct directory *directory, const char *name)
return path; 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 * char *
map_song_fs(const struct song *song) map_song_fs(const struct song *song)
{ {
assert(song_is_file(song)); assert(song_is_file(song));
if (song_in_database(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 else
return utf8_to_fs_charset(song->uri); return utf8_to_fs_charset(song->uri);
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "util/list.h" #include "util/list.h"
#include "gcc.h" #include "gcc.h"
#include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/time.h> #include <sys/time.h>
...@@ -59,6 +60,12 @@ struct song { ...@@ -59,6 +60,12 @@ struct song {
char uri[sizeof(int)]; char uri[sizeof(int)];
}; };
/**
* A dummy #directory instance that is used for "detached" song
* copies.
*/
extern struct directory detached_root;
G_BEGIN_DECLS G_BEGIN_DECLS
/** allocate a new song with a remote URL */ /** allocate a new song with a remote URL */
...@@ -86,6 +93,15 @@ song_file_load(const char *path, struct directory *parent); ...@@ -86,6 +93,15 @@ song_file_load(const char *path, struct directory *parent);
struct song * struct song *
song_replace_uri(struct song *song, const char *uri); 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 void
song_free(struct song *song); song_free(struct song *song);
...@@ -101,6 +117,15 @@ song_is_file(const struct song *song) ...@@ -101,6 +117,15 @@ song_is_file(const struct song *song)
return song_in_database(song) || song->uri[0] == '/'; 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. * Returns true if both objects refer to the same physical song.
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment