[mpd] Use generic inter thread commands util

This commit is contained in:
chme 2016-05-07 10:46:31 +02:00
parent 9856536fd7
commit 4aacf487e8
1 changed files with 24 additions and 137 deletions

161
src/mpd.c
View File

@ -62,6 +62,7 @@
#include "player.h" #include "player.h"
#include "queue.h" #include "queue.h"
#include "filescanner.h" #include "filescanner.h"
#include "commands.h"
static pthread_t tid_mpd; static pthread_t tid_mpd;
@ -70,29 +71,12 @@ static struct event_base *evbase_mpd;
static int g_exit_pipe[2]; static int g_exit_pipe[2];
static struct event *g_exitev; static struct event *g_exitev;
static int g_cmd_pipe[2]; static struct commands_base *cmdbase;
static struct event *g_cmdev;
static struct evhttp *evhttpd; static struct evhttp *evhttpd;
struct evconnlistener *listener; struct evconnlistener *listener;
struct mpd_command;
typedef int (*cmd_func)(struct mpd_command *cmd);
struct mpd_command
{
pthread_mutex_t lck;
pthread_cond_t cond;
cmd_func func;
enum listener_event_type arg_evtype;
int nonblock;
int ret;
};
#define COMMAND_ARGV_MAX 37 #define COMMAND_ARGV_MAX 37
@ -207,40 +191,6 @@ struct idle_client
struct idle_client *idle_clients; struct idle_client *idle_clients;
/* ---------------------------- COMMAND EXECUTION -------------------------- */
static int
send_command(struct mpd_command *cmd)
{
int ret;
if (!cmd->func)
{
DPRINTF(E_LOG, L_MPD, "BUG: cmd->func is NULL!\n");
return -1;
}
ret = write(g_cmd_pipe[1], &cmd, sizeof(cmd));
if (ret != sizeof(cmd))
{
DPRINTF(E_LOG, L_MPD, "Could not send command: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int
nonblock_command(struct mpd_command *cmd)
{
int ret;
ret = send_command(cmd);
if (ret < 0)
return -1;
return 0;
}
static void static void
thread_exit(void) thread_exit(void)
@ -3699,7 +3649,7 @@ mpd_command_decoders(struct evbuffer *evbuf, int argc, char **argv, char **errms
return 0; return 0;
} }
struct command struct mpd_command
{ {
/* The command name */ /* The command name */
const char *mpdcommand; const char *mpdcommand;
@ -3716,7 +3666,7 @@ struct command
int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg); int (*handler)(struct evbuffer *evbuf, int argc, char **argv, char **errmsg);
}; };
static struct command mpd_handlers[] = static struct mpd_command mpd_handlers[] =
{ {
/* /*
* Commands for querying status * Commands for querying status
@ -4192,7 +4142,7 @@ static struct command mpd_handlers[] =
* @param name the name of the command * @param name the name of the command
* @return the command or NULL if it is an unknown/unsupported command * @return the command or NULL if it is an unknown/unsupported command
*/ */
static struct command* static struct mpd_command*
mpd_find_command(const char *name) mpd_find_command(const char *name)
{ {
int i; int i;
@ -4240,7 +4190,7 @@ mpd_read_cb(struct bufferevent *bev, void *ctx)
int ncmd; int ncmd;
char *line; char *line;
char *errmsg; char *errmsg;
struct command *command; struct mpd_command *command;
enum command_list_type listtype; enum command_list_type listtype;
int idle_cmd; int idle_cmd;
int close_cmd; int close_cmd;
@ -4525,16 +4475,18 @@ mpd_notify_idle_client(struct idle_client *client, enum listener_event_type type
return 0; return 0;
} }
static int static enum command_state
mpd_notify_idle(struct mpd_command *cmd) mpd_notify_idle(void *arg, int *retval)
{ {
enum listener_event_type type;
struct idle_client *client; struct idle_client *client;
struct idle_client *prev; struct idle_client *prev;
struct idle_client *next; struct idle_client *next;
int i; int i;
int ret; int ret;
DPRINTF(E_DBG, L_MPD, "Notify clients waiting for idle results: %d\n", cmd->arg_evtype); type = *(enum listener_event_type *)arg;
DPRINTF(E_DBG, L_MPD, "Notify clients waiting for idle results: %d\n", type);
prev = NULL; prev = NULL;
next = NULL; next = NULL;
@ -4546,7 +4498,7 @@ mpd_notify_idle(struct mpd_command *cmd)
next = client->next; next = client->next;
ret = mpd_notify_idle_client(client, cmd->arg_evtype); ret = mpd_notify_idle_client(client, type);
if (ret == 0) if (ret == 0)
{ {
@ -4566,63 +4518,20 @@ mpd_notify_idle(struct mpd_command *cmd)
i++; i++;
} }
return 0; *retval = 0;
return COMMAND_END;
} }
static void static void
mpd_listener_cb(enum listener_event_type type) mpd_listener_cb(enum listener_event_type type)
{ {
enum listener_event_type *ptr;
ptr = (enum listener_event_type *)malloc(sizeof(enum listener_event_type));
*ptr = type;
DPRINTF(E_DBG, L_MPD, "Listener callback called with event type %d.\n", type); DPRINTF(E_DBG, L_MPD, "Listener callback called with event type %d.\n", type);
struct mpd_command *cmd; commands_exec_async(cmdbase, mpd_notify_idle, ptr);
cmd = (struct mpd_command *)malloc(sizeof(struct mpd_command));
if (!cmd)
{
DPRINTF(E_LOG, L_MPD, "Could not allocate cache_command\n");
return;
}
memset(cmd, 0, sizeof(struct mpd_command));
cmd->nonblock = 1;
cmd->func = mpd_notify_idle;
cmd->arg_evtype = type;
nonblock_command(cmd);
}
static void
command_cb(int fd, short what, void *arg)
{
struct mpd_command *cmd;
int ret;
ret = read(g_cmd_pipe[0], &cmd, sizeof(cmd));
if (ret != sizeof(cmd))
{
DPRINTF(E_LOG, L_MPD, "Could not read command! (read %d): %s\n", ret, (ret < 0) ? strerror(errno) : "-no error-");
goto readd;
}
if (cmd->nonblock)
{
cmd->func(cmd);
free(cmd);
goto readd;
}
pthread_mutex_lock(&cmd->lck);
ret = cmd->func(cmd);
cmd->ret = ret;
pthread_cond_signal(&cmd->cond);
pthread_mutex_unlock(&cmd->lck);
readd:
event_add(g_cmdev, NULL);
} }
/* /*
@ -4772,17 +4681,6 @@ int mpd_init(void)
goto exit_fail; goto exit_fail;
} }
#ifdef HAVE_PIPE2
ret = pipe2(g_cmd_pipe, O_CLOEXEC);
#else
ret = pipe(g_cmd_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_MPD, "Could not create command pipe: %s\n", strerror(errno));
goto cmd_fail;
}
evbase_mpd = event_base_new(); evbase_mpd = event_base_new();
if (!evbase_mpd) if (!evbase_mpd)
{ {
@ -4799,15 +4697,7 @@ int mpd_init(void)
event_add(g_exitev, NULL); event_add(g_exitev, NULL);
cmdbase = commands_base_new(evbase_mpd);
g_cmdev = event_new(evbase_mpd, g_cmd_pipe[0], EV_READ, command_cb, NULL);
if (!g_cmdev)
{
DPRINTF(E_LOG, L_MPD, "Could not create cmd event\n");
goto evnew_fail;
}
event_add(g_cmdev, NULL);
if (v6enabled) if (v6enabled)
{ {
@ -4917,15 +4807,12 @@ int mpd_init(void)
evhttp_fail: evhttp_fail:
evconnlistener_free(listener); evconnlistener_free(listener);
connew_fail: connew_fail:
commands_base_free(cmdbase);
evnew_fail: evnew_fail:
event_base_free(evbase_mpd); event_base_free(evbase_mpd);
evbase_mpd = NULL; evbase_mpd = NULL;
evbase_fail: evbase_fail:
close(g_cmd_pipe[0]);
close(g_cmd_pipe[1]);
cmd_fail:
close(g_exit_pipe[0]); close(g_exit_pipe[0]);
close(g_exit_pipe[1]); close(g_exit_pipe[1]);
@ -4966,6 +4853,8 @@ void mpd_deinit(void)
free(temp); free(temp);
} }
commands_base_free(cmdbase);
http_port = cfg_getint(cfg_getsec(cfg, "mpd"), "http_port"); http_port = cfg_getint(cfg_getsec(cfg, "mpd"), "http_port");
if (http_port > 0) if (http_port > 0)
evhttp_free(evhttpd); evhttp_free(evhttpd);
@ -4978,6 +4867,4 @@ void mpd_deinit(void)
// Close pipes // Close pipes
close(g_exit_pipe[0]); close(g_exit_pipe[0]);
close(g_exit_pipe[1]); close(g_exit_pipe[1]);
close(g_cmd_pipe[0]);
close(g_cmd_pipe[1]);
} }