mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 08:15:02 -05:00
[library] Add action to library_schedule_callback()
Makes it possible for the caller to request that a previous callback is replaced, so we don't end up with more and more callbacks. Also add other options for future use.
This commit is contained in:
parent
2af7296723
commit
2d8521139c
@ -54,6 +54,7 @@ struct library_callback_register
|
|||||||
{
|
{
|
||||||
library_cb cb;
|
library_cb cb;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
struct event *ev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct playlist_item_add_param
|
struct playlist_item_add_param
|
||||||
@ -170,44 +171,71 @@ static void
|
|||||||
scheduled_cb(int fd, short what, void *arg)
|
scheduled_cb(int fd, short what, void *arg)
|
||||||
{
|
{
|
||||||
struct library_callback_register *cbreg = arg;
|
struct library_callback_register *cbreg = arg;
|
||||||
|
library_cb cb = cbreg->cb;
|
||||||
|
void *cb_arg = cbreg->arg;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Executing library callback to %p\n", cbreg->cb);
|
// Must reset the register before calling back, otherwise it won't work if the
|
||||||
|
// callback reschedules by calling library_callback_schedule()
|
||||||
cbreg->cb(cbreg->arg);
|
event_free(cbreg->ev);
|
||||||
|
|
||||||
memset(cbreg, 0, sizeof(struct library_callback_register));
|
memset(cbreg, 0, sizeof(struct library_callback_register));
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_LIB, "Executing library callback to %p\n", cb);
|
||||||
|
cb(cb_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait)
|
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait, enum library_cb_action action)
|
||||||
{
|
{
|
||||||
struct library_callback_register *cbreg;
|
struct library_callback_register *cbreg;
|
||||||
int callback_id;
|
bool replace_done;
|
||||||
|
int idx_available;
|
||||||
|
int i;
|
||||||
|
|
||||||
// Find a free slot in the queue
|
for (i = 0, idx_available = -1, replace_done = false; i < ARRAY_SIZE(library_cb_register); i++)
|
||||||
for (callback_id = 0; callback_id < ARRAY_SIZE(library_cb_register); callback_id++)
|
|
||||||
{
|
{
|
||||||
if (library_cb_register[callback_id].cb == NULL)
|
if (idx_available == -1 && library_cb_register[i].cb == NULL)
|
||||||
break;
|
idx_available = i;
|
||||||
|
|
||||||
|
if (library_cb_register[i].cb != cb)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (action == LIBRARY_CB_REPLACE || action == LIBRARY_CB_ADD_OR_REPLACE)
|
||||||
|
{
|
||||||
|
event_add(library_cb_register[i].ev, wait);
|
||||||
|
library_cb_register[i].arg = arg;
|
||||||
|
replace_done = true;
|
||||||
|
}
|
||||||
|
else if (action == LIBRARY_CB_DELETE)
|
||||||
|
{
|
||||||
|
event_free(library_cb_register[i].ev);
|
||||||
|
memset(&library_cb_register[i], 0, sizeof(struct library_callback_register));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback_id == ARRAY_SIZE(library_cb_register))
|
if (action == LIBRARY_CB_REPLACE || action == LIBRARY_CB_DELETE || (action == LIBRARY_CB_ADD_OR_REPLACE && replace_done))
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_LIB, "Library callback register is full! (size is %d)\n", LIBRARY_MAX_CALLBACKS);
|
return 0; // All done
|
||||||
|
}
|
||||||
|
else if (idx_available == -1)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_LIB, "Error scheduling callback, register full (size=%d, action=%d)\n", LIBRARY_MAX_CALLBACKS, action);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cbreg = &library_cb_register[callback_id];
|
cbreg = &library_cb_register[idx_available];
|
||||||
|
|
||||||
cbreg->cb = cb;
|
cbreg->cb = cb;
|
||||||
cbreg->arg = arg;
|
cbreg->arg = arg;
|
||||||
|
|
||||||
// One-time event, freed automatically by libevent
|
if (!cbreg->ev)
|
||||||
CHECK_ERR(L_LIB, event_base_once(evbase_lib, -1, EV_TIMEOUT, scheduled_cb, cbreg, wait));
|
cbreg->ev = evtimer_new(evbase_lib, scheduled_cb, cbreg);
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_LIB, "Added library callback to %p (id %d)\n", cbreg->cb, callback_id);
|
CHECK_NULL(L_LIB, cbreg->ev);
|
||||||
|
|
||||||
return callback_id;
|
event_add(cbreg->ev, wait);
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_LIB, "Added library callback to %p (id %d), wait %ld.%06ld\n", cbreg->cb, idx_available, wait->tv_sec, wait->tv_usec);
|
||||||
|
|
||||||
|
return idx_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -853,6 +881,12 @@ library_deinit()
|
|||||||
sources[i]->deinit();
|
sources[i]->deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(library_cb_register); i++)
|
||||||
|
{
|
||||||
|
if (library_cb_register[i].ev)
|
||||||
|
event_free(library_cb_register[i].ev);
|
||||||
|
}
|
||||||
|
|
||||||
event_free(updateev);
|
event_free(updateev);
|
||||||
event_base_free(evbase_lib);
|
event_base_free(evbase_lib);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,21 @@
|
|||||||
|
|
||||||
typedef void (*library_cb)(void *arg);
|
typedef void (*library_cb)(void *arg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argument to library_callback_schedule()
|
||||||
|
*/
|
||||||
|
enum library_cb_action
|
||||||
|
{
|
||||||
|
// Add as new callback
|
||||||
|
LIBRARY_CB_ADD,
|
||||||
|
// Replace callback if it already exists
|
||||||
|
LIBRARY_CB_REPLACE,
|
||||||
|
// Replace callback if it already exists, otherwise add as new
|
||||||
|
LIBRARY_CB_ADD_OR_REPLACE,
|
||||||
|
// Delete a callback
|
||||||
|
LIBRARY_CB_DELETE,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definition of a library source
|
* Definition of a library source
|
||||||
*
|
*
|
||||||
@ -123,10 +138,11 @@ library_playlist_save(struct playlist_info *pli);
|
|||||||
* @param cb Callback to call
|
* @param cb Callback to call
|
||||||
* @param arg Argument to call back with
|
* @param arg Argument to call back with
|
||||||
* @param timeval How long to wait before calling back
|
* @param timeval How long to wait before calling back
|
||||||
|
* @param action (see enum)
|
||||||
* @return id of the scheduled event, -1 on failure
|
* @return id of the scheduled event, -1 on failure
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait);
|
library_callback_schedule(library_cb cb, void *arg, struct timeval *wait, enum library_cb_action action);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @return true if a running scan should be aborted due to imminent shutdown
|
* @return true if a running scan should be aborted due to imminent shutdown
|
||||||
|
@ -549,7 +549,7 @@ rss_scan_all(enum rss_scan_type scan_type)
|
|||||||
if (count == 0)
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
library_callback_schedule(rss_refresh, NULL, &rss_refresh_interval);
|
library_callback_schedule(rss_refresh, NULL, &rss_refresh_interval, LIBRARY_CB_ADD_OR_REPLACE);
|
||||||
|
|
||||||
DPRINTF(E_INFO, L_LIB, "Refreshed %d RSS feeds in %.f sec (scan type %d)\n", count, difftime(end, start), scan_type);
|
DPRINTF(E_INFO, L_LIB, "Refreshed %d RSS feeds in %.f sec (scan type %d)\n", count, difftime(end, start), scan_type);
|
||||||
}
|
}
|
||||||
@ -601,7 +601,7 @@ rss_add(const char *path)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return LIBRARY_PATH_INVALID;
|
return LIBRARY_PATH_INVALID;
|
||||||
|
|
||||||
library_callback_schedule(rss_refresh, NULL, &rss_refresh_interval);
|
library_callback_schedule(rss_refresh, NULL, &rss_refresh_interval, LIBRARY_CB_ADD_OR_REPLACE);
|
||||||
|
|
||||||
return LIBRARY_OK;
|
return LIBRARY_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user