Modify player-to-DACP status update communication

Have DACP set a callback (through a sync_command() setter) into the player
instead of setting an fd without any locking. All the code now lies in DACP
instead of being split between DACP and the player.
This commit is contained in:
Julien BLACHE 2010-09-12 14:31:41 +02:00
parent 90b13b1855
commit 942f3e4aad
3 changed files with 52 additions and 35 deletions

View File

@ -342,6 +342,25 @@ playstatusupdate_cb(int fd, short what, void *arg)
DPRINTF(E_LOG, L_DACP, "Couldn't re-add event for playstatusupdate\n");
}
/* Thread: player */
static void
dacp_playstatus_update_handler(void)
{
int ret;
#ifdef USE_EVENTFD
ret = eventfd_write(update_efd, 1);
if (ret < 0)
DPRINTF(E_LOG, L_DACP, "Could not send status update event: %s\n", strerror(errno));
#else
int dummy = 42;
ret = write(update_pipe[1], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_DACP, "Could not write to status update fd: %s\n", strerror(errno));
#endif
}
static void
update_fail_cb(struct evhttp_connection *evcon, void *arg)
{
@ -1794,11 +1813,7 @@ dacp_init(void)
event_base_set(evbase_httpd, &updateev);
event_add(&updateev, NULL);
#ifdef USE_EVENTFD
player_set_updatefd(update_efd);
#else
player_set_updatefd(update_pipe[1]);
#endif
player_set_update_handler(dacp_playstatus_update_handler);
return 0;
@ -1823,6 +1838,8 @@ dacp_deinit(void)
struct dacp_update_request *ur;
int i;
player_set_update_handler(NULL);
for (i = 0; dacp_handlers[i].handler; i++)
regfree(&dacp_handlers[i].preg);
@ -1839,8 +1856,6 @@ dacp_deinit(void)
free(ur);
}
player_set_updatefd(-1);
event_del(&updateev);
avl_free_tree(dacp_props_hash);

View File

@ -129,7 +129,7 @@ static enum repeat_mode repeat;
static char shuffle;
/* Status updates (for DACP) */
static int update_fd;
static player_status_handler update_handler;
/* Playback timer */
static int pb_timer_fd;
@ -181,26 +181,10 @@ static struct evbuffer *audio_buf;
static void
status_update(enum play_status status)
{
#ifndef USE_EVENTFD
int dummy = 42;
#endif
int ret;
player_state = status;
if (update_fd < 0)
return;
#ifdef USE_EVENTFD
ret = eventfd_write(update_fd, 1);
if (ret < 0)
#else
ret = write(update_fd, &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
#endif
{
DPRINTF(E_LOG, L_PLAYER, "Could not send status update: %s\n", strerror(errno));
}
if (update_handler)
update_handler();
}
@ -2467,6 +2451,17 @@ queue_plid(void *arg)
return 0;
}
static int
set_update_handler(void *arg)
{
player_status_handler handler;
handler = (player_status_handler)arg;
update_handler = handler;
return 0;
}
/* Command helpers */
/* Thread: player */
@ -2842,6 +2837,19 @@ player_queue_plid(uint32_t plid)
pthread_mutex_unlock(&cmd_lck);
}
void
player_set_update_handler(player_status_handler handler)
{
pthread_mutex_lock(&cmd_lck);
cmd.func = set_update_handler;
cmd.func_bh = NULL;
cmd.arg = handler;
sync_command();
pthread_mutex_unlock(&cmd_lck);
}
/* Thread: main (mdns) */
static void
@ -3176,13 +3184,6 @@ exit_cb(int fd, short what, void *arg)
player_exit = 1;
}
/* Thread: main at DACP init/deinit */
void
player_set_updatefd(int fd)
{
update_fd = fd;
}
/* Thread: main */
int
player_init(void)
@ -3212,7 +3213,7 @@ player_init(void)
repeat = REPEAT_OFF;
shuffle = 0;
update_fd = -1;
update_handler = NULL;
/* Random RTP time start */
gcry_randomize(&rnd, sizeof(rnd), GCRY_STRONG_RANDOM);

View File

@ -46,6 +46,7 @@ struct player_status {
};
typedef void (*spk_enum_cb)(uint64_t id, const char *name, int selected, int has_password, void *arg);
typedef void (*player_status_handler)(void);
struct player_source;
@ -112,7 +113,7 @@ player_queue_plid(uint32_t plid);
void
player_set_updatefd(int fd);
player_set_update_handler(player_status_handler handler);
int
player_init(void);