DatabasePlugin: add method ReturnSong()
Allow the plugin to allocate the GetSong() return value.
This commit is contained in:
parent
f45616e5f6
commit
3b8532f3fb
@ -132,6 +132,15 @@ db_get_song(const char *file)
|
|||||||
return db->GetSong(file, NULL);
|
return db->GetSong(file, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
db_return_song(struct song *song)
|
||||||
|
{
|
||||||
|
assert(db != nullptr);
|
||||||
|
assert(song != nullptr);
|
||||||
|
|
||||||
|
db->ReturnSong(song);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
db_save(GError **error_r)
|
db_save(GError **error_r)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +85,8 @@ public:
|
|||||||
virtual void Close() {}
|
virtual void Close() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up a song (including tag data) in the database.
|
* Look up a song (including tag data) in the database. When
|
||||||
|
* you don't need this anymore, call ReturnSong().
|
||||||
*
|
*
|
||||||
* @param uri_utf8 the URI of the song within the music
|
* @param uri_utf8 the URI of the song within the music
|
||||||
* directory (UTF-8)
|
* directory (UTF-8)
|
||||||
@ -93,6 +94,12 @@ public:
|
|||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual struct song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const = 0;
|
GError **error_r) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the song object as "unused". Call this on objects
|
||||||
|
* returned by GetSong().
|
||||||
|
*/
|
||||||
|
virtual void ReturnSong(struct song *song) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit the selected entities.
|
* Visit the selected entities.
|
||||||
*/
|
*/
|
||||||
|
@ -1326,6 +1326,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
value = sticker_song_get_value(song, argv[4]);
|
value = sticker_song_get_value(song, argv[4]);
|
||||||
|
db_return_song(song);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
command_error(client, ACK_ERROR_NO_EXIST,
|
command_error(client, ACK_ERROR_NO_EXIST,
|
||||||
"no such sticker");
|
"no such sticker");
|
||||||
@ -1349,6 +1350,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
sticker = sticker_song_get(song);
|
sticker = sticker_song_get(song);
|
||||||
|
db_return_song(song);
|
||||||
if (sticker) {
|
if (sticker) {
|
||||||
sticker_print(client, sticker);
|
sticker_print(client, sticker);
|
||||||
sticker_free(sticker);
|
sticker_free(sticker);
|
||||||
@ -1368,6 +1370,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = sticker_song_set_value(song, argv[4], argv[5]);
|
ret = sticker_song_set_value(song, argv[4], argv[5]);
|
||||||
|
db_return_song(song);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
command_error(client, ACK_ERROR_SYSTEM,
|
command_error(client, ACK_ERROR_SYSTEM,
|
||||||
"failed to set sticker value");
|
"failed to set sticker value");
|
||||||
@ -1391,6 +1394,7 @@ handle_sticker_song(struct client *client, int argc, char *argv[])
|
|||||||
ret = argc == 4
|
ret = argc == 4
|
||||||
? sticker_song_delete(song)
|
? sticker_song_delete(song)
|
||||||
: sticker_song_delete_value(song, argv[4]);
|
: sticker_song_delete_value(song, argv[4]);
|
||||||
|
db_return_song(song);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
command_error(client, ACK_ERROR_SYSTEM,
|
command_error(client, ACK_ERROR_SYSTEM,
|
||||||
"no such sticker");
|
"no such sticker");
|
||||||
|
@ -74,6 +74,10 @@ gcc_pure
|
|||||||
struct song *
|
struct song *
|
||||||
db_get_song(const char *file);
|
db_get_song(const char *file);
|
||||||
|
|
||||||
|
gcc_nonnull(1)
|
||||||
|
void
|
||||||
|
db_return_song(struct song *song);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* May only be used if db_is_simple() returns true.
|
* May only be used if db_is_simple() returns true.
|
||||||
*/
|
*/
|
||||||
|
@ -56,6 +56,8 @@ public:
|
|||||||
virtual void Close() override;
|
virtual void Close() override;
|
||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual struct song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const override;
|
GError **error_r) const override;
|
||||||
|
virtual void ReturnSong(struct song *song) const;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
virtual bool Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
@ -191,6 +193,16 @@ ProxyDatabase::GetSong(const char *uri, GError **error_r) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProxyDatabase::ReturnSong(struct song *song) const
|
||||||
|
{
|
||||||
|
assert(song != nullptr);
|
||||||
|
assert(song_in_database(song));
|
||||||
|
assert(song_is_detached(song));
|
||||||
|
|
||||||
|
song_free(song);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
Visit(struct mpd_connection *connection, const char *uri,
|
Visit(struct mpd_connection *connection, const char *uri,
|
||||||
bool recursive, VisitDirectory visit_directory, VisitSong visit_song,
|
bool recursive, VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
|
@ -184,6 +184,10 @@ SimpleDatabase::Open(GError **error_r)
|
|||||||
root = directory_new_root();
|
root = directory_new_root();
|
||||||
mtime = 0;
|
mtime = 0;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
borrowed_song_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
if (!Load(&error)) {
|
if (!Load(&error)) {
|
||||||
directory_free(root);
|
directory_free(root);
|
||||||
@ -204,6 +208,7 @@ void
|
|||||||
SimpleDatabase::Close()
|
SimpleDatabase::Close()
|
||||||
{
|
{
|
||||||
assert(root != NULL);
|
assert(root != NULL);
|
||||||
|
assert(borrowed_song_count == 0);
|
||||||
|
|
||||||
directory_free(root);
|
directory_free(root);
|
||||||
}
|
}
|
||||||
@ -219,10 +224,25 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const
|
|||||||
if (song == NULL)
|
if (song == NULL)
|
||||||
g_set_error(error_r, db_quark(), DB_NOT_FOUND,
|
g_set_error(error_r, db_quark(), DB_NOT_FOUND,
|
||||||
"No such song: %s", uri);
|
"No such song: %s", uri);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
else
|
||||||
|
++const_cast<unsigned &>(borrowed_song_count);
|
||||||
|
#endif
|
||||||
|
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SimpleDatabase::ReturnSong(gcc_unused struct song *song) const
|
||||||
|
{
|
||||||
|
assert(song != nullptr);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(borrowed_song_count > 0);
|
||||||
|
--const_cast<unsigned &>(borrowed_song_count);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
G_GNUC_PURE
|
G_GNUC_PURE
|
||||||
const struct directory *
|
const struct directory *
|
||||||
SimpleDatabase::LookupDirectory(const char *uri) const
|
SimpleDatabase::LookupDirectory(const char *uri) const
|
||||||
|
@ -38,6 +38,10 @@ class SimpleDatabase : public Database {
|
|||||||
|
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
unsigned borrowed_song_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
gcc_pure
|
gcc_pure
|
||||||
struct directory *GetRoot() {
|
struct directory *GetRoot() {
|
||||||
@ -61,6 +65,8 @@ public:
|
|||||||
|
|
||||||
virtual struct song *GetSong(const char *uri_utf8,
|
virtual struct song *GetSong(const char *uri_utf8,
|
||||||
GError **error_r) const override;
|
GError **error_r) const override;
|
||||||
|
virtual void ReturnSong(struct song *song) const;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
virtual bool Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
|
@ -128,7 +128,12 @@ playlist_append_uri(struct playlist *playlist, struct player_control *pc,
|
|||||||
if (song == NULL)
|
if (song == NULL)
|
||||||
return PLAYLIST_RESULT_NO_SUCH_SONG;
|
return PLAYLIST_RESULT_NO_SUCH_SONG;
|
||||||
|
|
||||||
return playlist_append_song(playlist, pc, song, added_id);
|
enum playlist_result result =
|
||||||
|
playlist_append_song(playlist, pc, song, added_id);
|
||||||
|
if (song_in_database(song))
|
||||||
|
db_return_song(song);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum playlist_result
|
enum playlist_result
|
||||||
|
@ -127,6 +127,7 @@ spl_print(struct client *client, const char *name_utf8, bool detail,
|
|||||||
struct song *song = db_get_song(temp);
|
struct song *song = db_get_song(temp);
|
||||||
if (song) {
|
if (song) {
|
||||||
song_print_info(client, song);
|
song_print_info(client, song);
|
||||||
|
db_return_song(song);
|
||||||
wrote = true;
|
wrote = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +158,6 @@ playlist_provider_print(struct client *client, const char *uri,
|
|||||||
else
|
else
|
||||||
song_print_uri(client, song);
|
song_print_uri(client, song);
|
||||||
|
|
||||||
if (!song_in_database(song) || song_is_detached(song))
|
|
||||||
song_free(song);
|
song_free(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
|||||||
++i) {
|
++i) {
|
||||||
if (i < start_index) {
|
if (i < start_index) {
|
||||||
/* skip songs before the start index */
|
/* skip songs before the start index */
|
||||||
if (!song_in_database(song))
|
|
||||||
song_free(song);
|
song_free(song);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -51,9 +50,8 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
result = playlist_append_song(dest, pc, song, NULL);
|
result = playlist_append_song(dest, pc, song, NULL);
|
||||||
if (result != PLAYLIST_RESULT_SUCCESS) {
|
|
||||||
if (!song_in_database(song))
|
|
||||||
song_free(song);
|
song_free(song);
|
||||||
|
if (result != PLAYLIST_RESULT_SUCCESS) {
|
||||||
g_free(base_uri);
|
g_free(base_uri);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,7 @@ apply_song_metadata(struct song *dest, const struct song *src)
|
|||||||
(e.g. last track on a CUE file); fix it up here */
|
(e.g. last track on a CUE file); fix it up here */
|
||||||
tmp->tag->time = dest->tag->time - src->start_ms / 1000;
|
tmp->tag->time = dest->tag->time - src->start_ms / 1000;
|
||||||
|
|
||||||
if (!song_in_database(dest))
|
|
||||||
song_free(dest);
|
song_free(dest);
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,10 +95,13 @@ playlist_check_load_song(const struct song *song, const char *uri, bool secure)
|
|||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
dest = db_get_song(uri);
|
struct song *tmp = db_get_song(uri);
|
||||||
if (dest == NULL)
|
if (tmp == NULL)
|
||||||
/* not found in database */
|
/* not found in database */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
dest = song_dup_detached(tmp);
|
||||||
|
db_return_song(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return apply_song_metadata(dest, song);
|
return apply_song_metadata(dest, song);
|
||||||
|
@ -103,4 +103,7 @@ queue_load_song(FILE *fp, GString *buffer, const char *line,
|
|||||||
}
|
}
|
||||||
|
|
||||||
queue_append(queue, song);
|
queue_append(queue, song);
|
||||||
|
|
||||||
|
if (song_in_database(song))
|
||||||
|
db_return_song(song);
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,9 @@ spl_append_uri(const char *url, const char *utf8file, GError **error_r)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return spl_append_song(utf8file, song, error_r);
|
bool success = spl_append_song(utf8file, song, error_r);
|
||||||
|
db_return_song(song);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user