mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
[library] Change implementation of item_add, event cb and drop item_remove.
This commit is contained in:
parent
5cddf0e347
commit
2ee5f6d747
144
src/library.c
144
src/library.c
@ -48,6 +48,14 @@
|
|||||||
#include "listener.h"
|
#include "listener.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|
||||||
|
#define LIBRARY_MAX_CALLBACKS 16
|
||||||
|
|
||||||
|
struct library_callback_register
|
||||||
|
{
|
||||||
|
library_cb cb;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
struct playlist_item_add_param
|
struct playlist_item_add_param
|
||||||
{
|
{
|
||||||
const char *vp_playlist;
|
const char *vp_playlist;
|
||||||
@ -107,6 +115,9 @@ static struct event *updateev;
|
|||||||
static unsigned int deferred_update_notifications;
|
static unsigned int deferred_update_notifications;
|
||||||
static short deferred_update_events;
|
static short deferred_update_events;
|
||||||
|
|
||||||
|
// Stores callbacks that backends may have requested
|
||||||
|
static struct library_callback_register library_cb_register[LIBRARY_MAX_CALLBACKS];
|
||||||
|
|
||||||
|
|
||||||
/* ------------------- CALLED BY LIBRARY SOURCE MODULES -------------------- */
|
/* ------------------- CALLED BY LIBRARY SOURCE MODULES -------------------- */
|
||||||
|
|
||||||
@ -155,6 +166,50 @@ library_playlist_save(struct playlist_info *pli)
|
|||||||
return db_pl_update(pli);
|
return db_pl_update(pli);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scheduled_cb(int fd, short what, void *arg)
|
||||||
|
{
|
||||||
|
struct library_callback_register *cbreg = arg;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_LIB, "Executing library callback to %p\n", cbreg->cb);
|
||||||
|
|
||||||
|
cbreg->cb(cbreg->arg);
|
||||||
|
|
||||||
|
memset(cbreg, 0, sizeof(struct library_callback_register));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait)
|
||||||
|
{
|
||||||
|
struct library_callback_register *cbreg;
|
||||||
|
int callback_id;
|
||||||
|
|
||||||
|
// Find a free slot in the queue
|
||||||
|
for (callback_id = 0; callback_id < ARRAY_SIZE(library_cb_register); callback_id++)
|
||||||
|
{
|
||||||
|
if (library_cb_register[callback_id].cb == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback_id == ARRAY_SIZE(library_cb_register))
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_LIB, "Library callback register is full! (size is %d)\n", LIBRARY_MAX_CALLBACKS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbreg = &library_cb_register[callback_id];
|
||||||
|
|
||||||
|
cbreg->cb = cb;
|
||||||
|
cbreg->arg = arg;
|
||||||
|
|
||||||
|
// One-time event, freed automatically by libevent
|
||||||
|
CHECK_ERR(L_LIB, event_base_once(evbase_lib, -1, EV_TIMEOUT, scheduled_cb, cbreg, wait));
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_LIB, "Added library callback to %p (id %d)\n", cbreg->cb, callback_id);
|
||||||
|
|
||||||
|
return callback_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------- LIBRARY ABSTRACTION --------------------- */
|
/* ---------------------- LIBRARY ABSTRACTION --------------------- */
|
||||||
/* thread: library */
|
/* thread: library */
|
||||||
@ -446,11 +501,11 @@ queue_save(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
item_add(void *arg, int *retval)
|
item_add(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
struct item_add_params *params = arg;
|
const char *path = arg;
|
||||||
int i;
|
int i;
|
||||||
int ret = LIBRARY_ERROR;
|
int ret = LIBRARY_ERROR;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Adding item to library '%s' '%s'\n", params->name, params->path);
|
DPRINTF(E_DBG, L_LIB, "Adding item to library '%s'\n", path);
|
||||||
|
|
||||||
for (i = 0; sources[i]; i++)
|
for (i = 0; sources[i]; i++)
|
||||||
{
|
{
|
||||||
@ -460,11 +515,11 @@ item_add(void *arg, int *retval)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sources[i]->item_add(params->name, params->path, params->limit);
|
ret = sources[i]->item_add(path);
|
||||||
|
|
||||||
if (ret == LIBRARY_OK)
|
if (ret == LIBRARY_OK)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_LIB, "Add item to path '%s' with library source '%s'\n", params->path, sources[i]->name);
|
DPRINTF(E_DBG, L_LIB, "Add item to path '%s' with library source '%s'\n", path, sources[i]->name);
|
||||||
listener_notify(LISTENER_DATABASE);
|
listener_notify(LISTENER_DATABASE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -474,38 +529,6 @@ item_add(void *arg, int *retval)
|
|||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum command_state
|
|
||||||
item_remove(void *arg, int *retval)
|
|
||||||
{
|
|
||||||
const char *path = arg;
|
|
||||||
int i;
|
|
||||||
int ret = LIBRARY_ERROR;
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Removing item from library '%s'\n", path);
|
|
||||||
|
|
||||||
for (i = 0; sources[i]; i++)
|
|
||||||
{
|
|
||||||
if (sources[i]->disabled || !sources[i]->item_remove)
|
|
||||||
{
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Library source '%s' is disabled or does not support add_remove\n", sources[i]->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sources[i]->item_remove(path);
|
|
||||||
|
|
||||||
if (ret == LIBRARY_OK)
|
|
||||||
{
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Removing item from path '%s' with library source '%s'\n", path, sources[i]->name);
|
|
||||||
listener_notify(LISTENER_DATABASE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*retval = ret;
|
|
||||||
return COMMAND_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Callback to notify listeners of database changes
|
// Callback to notify listeners of database changes
|
||||||
static void
|
static void
|
||||||
update_trigger_cb(int fd, short what, void *arg)
|
update_trigger_cb(int fd, short what, void *arg)
|
||||||
@ -709,40 +732,12 @@ library_queue_item_add(const char *path, int position, char reshuffle, uint32_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
library_item_add(const char *name, const char *path, long limit)
|
library_item_add(const char *path)
|
||||||
{
|
|
||||||
struct item_add_params params;
|
|
||||||
|
|
||||||
if (library_is_scanning())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
params.name = name;
|
|
||||||
params.path = path;
|
|
||||||
params.limit = limit;
|
|
||||||
return commands_exec_sync(cmdbase, item_add, NULL, ¶ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
library_item_remove(const char *path)
|
|
||||||
{
|
{
|
||||||
if (library_is_scanning())
|
if (library_is_scanning())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return commands_exec_sync(cmdbase, item_remove, NULL, path);
|
return commands_exec_sync(cmdbase, item_add, NULL, (char *)path);
|
||||||
}
|
|
||||||
|
|
||||||
struct event*
|
|
||||||
library_register_event(void (*ev_cb)(int fd, short what, void *arg), void *ev_cb_arg, const struct timeval* cb_interval)
|
|
||||||
{
|
|
||||||
struct event *ev;
|
|
||||||
ev = evtimer_new(evbase_lib, ev_cb, ev_cb_arg);
|
|
||||||
if (!ev)
|
|
||||||
{
|
|
||||||
DPRINTF(E_FATAL, L_LIB, "Failed to create timer event\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
evtimer_add(ev, cb_interval);
|
|
||||||
return ev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -807,21 +802,18 @@ library_init(void)
|
|||||||
|
|
||||||
for (i = 0; sources[i]; i++)
|
for (i = 0; sources[i]; i++)
|
||||||
{
|
{
|
||||||
if (!sources[i]->init)
|
|
||||||
{
|
|
||||||
DPRINTF(E_FATAL, L_LIB, "BUG: library source '%s' has no init()\n", sources[i]->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sources[i]->initscan || !sources[i]->rescan || !sources[i]->metarescan || !sources[i]->fullrescan)
|
if (!sources[i]->initscan || !sources[i]->rescan || !sources[i]->metarescan || !sources[i]->fullrescan)
|
||||||
{
|
{
|
||||||
DPRINTF(E_FATAL, L_LIB, "BUG: library source '%s' is missing a scanning method\n", sources[i]->name);
|
DPRINTF(E_FATAL, L_LIB, "BUG: library source '%s' is missing a scanning method\n", sources[i]->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sources[i]->init();
|
if (sources[i]->init && !sources[i]->disabled)
|
||||||
if (ret < 0)
|
{
|
||||||
sources[i]->disabled = 1;
|
ret = sources[i]->init();
|
||||||
|
if (ret < 0)
|
||||||
|
sources[i]->disabled = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_NULL(L_LIB, cmdbase = commands_base_new(evbase_lib, NULL));
|
CHECK_NULL(L_LIB, cmdbase = commands_base_new(evbase_lib, NULL));
|
||||||
@ -858,7 +850,7 @@ library_deinit()
|
|||||||
for (i = 0; sources[i]; i++)
|
for (i = 0; sources[i]; i++)
|
||||||
{
|
{
|
||||||
if (sources[i]->deinit && !sources[i]->disabled)
|
if (sources[i]->deinit && !sources[i]->disabled)
|
||||||
sources[i]->deinit();
|
sources[i]->deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
event_free(updateev);
|
event_free(updateev);
|
||||||
|
@ -30,11 +30,7 @@
|
|||||||
#define LIBRARY_ERROR -1
|
#define LIBRARY_ERROR -1
|
||||||
#define LIBRARY_PATH_INVALID -2
|
#define LIBRARY_PATH_INVALID -2
|
||||||
|
|
||||||
struct item_add_params {
|
typedef void (*library_cb)(void *arg);
|
||||||
const char *name;
|
|
||||||
const char *path;
|
|
||||||
int limit;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definition of a library source
|
* Definition of a library source
|
||||||
@ -78,10 +74,9 @@ struct library_source
|
|||||||
int (*fullrescan)(void);
|
int (*fullrescan)(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform an add to library of single item
|
* Add an item to the library
|
||||||
*/
|
*/
|
||||||
int (*item_add)(const char *name, const char *path, int limit);
|
int (*item_add)(const char *path);
|
||||||
int (*item_remove)(const char *path);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add item to playlist
|
* Add item to playlist
|
||||||
@ -106,6 +101,12 @@ struct library_source
|
|||||||
|
|
||||||
/* --------------------- Interface towards source backends ----------------- */
|
/* --------------------- Interface towards source backends ----------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds a mfi if mfi->id == 0, otherwise updates.
|
||||||
|
*
|
||||||
|
* @param mfi Media to save
|
||||||
|
* @return 0 if operation succeeded, -1 on failure.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
library_media_save(struct media_file_info *mfi);
|
library_media_save(struct media_file_info *mfi);
|
||||||
|
|
||||||
@ -113,11 +114,27 @@ library_media_save(struct media_file_info *mfi);
|
|||||||
* Adds a playlist if pli->id == 0, otherwise updates.
|
* Adds a playlist if pli->id == 0, otherwise updates.
|
||||||
*
|
*
|
||||||
* @param pli Playlist to save
|
* @param pli Playlist to save
|
||||||
* @return playlist id if operation succeeded, -1 on failure.
|
* @return Playlist id if operation succeeded, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
library_playlist_save(struct playlist_info *pli);
|
library_playlist_save(struct playlist_info *pli);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param cb Callback to call
|
||||||
|
* @param arg Argument to call back with
|
||||||
|
* @param timeval How long to wait before calling back
|
||||||
|
* @return id of the scheduled event, -1 on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @return true if a running scan should be aborted due to imminent shutdown
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
library_is_exiting();
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------ Library external interface --------------------- */
|
/* ------------------------ Library external interface --------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -141,12 +158,6 @@ library_is_scanning();
|
|||||||
void
|
void
|
||||||
library_set_scanning(bool is_scanning);
|
library_set_scanning(bool is_scanning);
|
||||||
|
|
||||||
/*
|
|
||||||
* @return true if a running scan should be aborted due to imminent shutdown, otherwise false
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
library_is_exiting();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trigger for sending the DATABASE event
|
* Trigger for sending the DATABASE event
|
||||||
*
|
*
|
||||||
@ -169,15 +180,8 @@ int
|
|||||||
library_queue_item_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id);
|
library_queue_item_add(const char *path, int position, char reshuffle, uint32_t item_id, int *count, int *new_item_id);
|
||||||
|
|
||||||
int
|
int
|
||||||
library_item_add(const char *name, const char *url, long limit);
|
library_item_add(const char *path);
|
||||||
|
|
||||||
int
|
|
||||||
library_item_remove(const char *url);
|
|
||||||
|
|
||||||
/* Register any timer events for library modules
|
|
||||||
*/
|
|
||||||
struct event*
|
|
||||||
library_register_event(void (*ev_cb)(int fd, short what, void *arg), void *ev_cb_arg, const struct timeval* cb_interval);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute the function 'func' with the given argument 'arg' in the library thread.
|
* Execute the function 'func' with the given argument 'arg' in the library thread.
|
||||||
|
Loading…
Reference in New Issue
Block a user