[mpd] Refactor commands to enable/disable/toggle/volume for outputs

This commit is contained in:
chme 2018-02-07 23:06:41 +01:00
parent decf9f1329
commit 43887d160f

309
src/mpd.c
View File

@ -212,31 +212,21 @@ struct output
char *name; char *name;
unsigned selected; unsigned selected;
struct output *next;
}; };
struct outputs struct output_get_param
{ {
unsigned int count; unsigned short shortid;
unsigned int active; struct output *output;
struct output *outputs;
}; };
static void static void
free_outputs(struct output *outputs) free_output(struct output *output)
{ {
struct output *temp; if (output)
struct output *next;
temp = outputs;
next = outputs ? outputs->next : NULL;
while (temp)
{ {
free(temp->name); free(output->name);
free(temp); free(output);
temp = next;
next = next ? next->next : NULL;
} }
} }
@ -3575,28 +3565,23 @@ mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errms
* the shortid of output_get_param matches the given speaker/output spk. * the shortid of output_get_param matches the given speaker/output spk.
*/ */
static void static void
outputs_enum_cb(struct spk_info *spk, void *arg) output_get_cb(struct spk_info *spk, void *arg)
{ {
struct outputs *outputs; struct output_get_param *param = arg;
struct output *output;
outputs = (struct outputs *)arg; if (!param->output
&& param->shortid == (unsigned short) spk->id)
{
param->output = calloc(1, sizeof(struct output));
output = (struct output*)malloc(sizeof(struct output)); param->output->id = spk->id;
param->output->shortid = (unsigned short) spk->id;
param->output->name = strdup(spk->name);
param->output->selected = spk->selected;
output->id = spk->id; DPRINTF(E_DBG, L_MPD, "Output found: shortid %d, id %" PRIu64 ", name '%s', selected %d\n",
output->shortid = (unsigned short) spk->id; param->output->shortid, param->output->id, param->output->name, param->output->selected);
output->name = strdup(spk->name); }
output->selected = spk->selected;
output->next = outputs->outputs;
outputs->outputs = output;
outputs->count++;
if (spk->selected)
outputs->active++;
DPRINTF(E_DBG, L_MPD, "Output enum: shortid %d, id %" PRIu64 ", name '%s', selected %d\n",
output->shortid, output->id, output->name, output->selected);
} }
/* /*
@ -3606,20 +3591,10 @@ outputs_enum_cb(struct spk_info *spk, void *arg)
static int static int
mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
{ {
struct outputs outputs; struct output_get_param param;
struct output *output;
uint32_t num; uint32_t num;
uint64_t *ids;
int nspk;
int i;
int ret; int ret;
if (argc < 2)
{
*errmsg = safe_asprintf("Missing argument for command 'disableoutput'");
return ACK_ERROR_ARG;
}
ret = safe_atou32(argv[1], &num); ret = safe_atou32(argv[1], &num);
if (ret < 0) if (ret < 0)
{ {
@ -3627,58 +3602,22 @@ mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **
return ACK_ERROR_ARG; return ACK_ERROR_ARG;
} }
outputs.count = 0; memset(&param, 0, sizeof(struct output_get_param));
outputs.active = 0; param.shortid = num;
outputs.outputs = NULL;
player_speaker_enumerate(outputs_enum_cb, &outputs); player_speaker_enumerate(output_get_cb, &param);
nspk = outputs.active; if (param.output && param.output->selected)
output = outputs.outputs;
while (output)
{ {
if (output->shortid == num && output->selected) ret = player_speaker_disable(param.output->id);
{ free_output(param.output);
nspk--;
break;
}
output = output->next;
}
if (nspk == outputs.active)
{
DPRINTF(E_LOG, L_MPD, "No speaker to deactivate\n");
free_outputs(outputs.outputs);
return 0;
}
ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t));
ids[0] = nspk;
i = 1;
output = outputs.outputs;
while (output)
{
if (output->shortid != num && output->selected)
{
ids[i] = output->id;
i++;
}
output = output->next;
}
ret = player_speaker_set(ids);
free(ids);
free_outputs(outputs.outputs);
if (ret < 0) if (ret < 0)
{ {
*errmsg = safe_asprintf("Speakers deactivation failed: %d", num); *errmsg = safe_asprintf("Speakers deactivation failed: %d", num);
return ACK_ERROR_UNKNOWN; return ACK_ERROR_UNKNOWN;
} }
}
return 0; return 0;
} }
@ -3690,20 +3629,10 @@ mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **
static int static int
mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
{ {
struct outputs outputs; struct output_get_param param;
struct output *output;
uint32_t num; uint32_t num;
uint64_t *ids;
int nspk;
int i;
int ret; int ret;
if (argc < 2)
{
*errmsg = safe_asprintf("Missing argument for command 'enableoutput'");
return ACK_ERROR_ARG;
}
ret = safe_atou32(argv[1], &num); ret = safe_atou32(argv[1], &num);
if (ret < 0) if (ret < 0)
{ {
@ -3711,59 +3640,22 @@ mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **e
return ACK_ERROR_ARG; return ACK_ERROR_ARG;
} }
outputs.count = 0; memset(&param, 0, sizeof(struct output_get_param));
outputs.active = 0; param.shortid = num;
outputs.outputs = NULL;
player_speaker_enumerate(outputs_enum_cb, &outputs); player_speaker_enumerate(output_get_cb, &param);
nspk = outputs.active; if (param.output && !param.output->selected)
output = outputs.outputs;
while (output)
{ {
if (output->shortid == num && !output->selected) ret = player_speaker_enable(param.output->id);
{ free_output(param.output);
nspk++;
break;
}
output = output->next;
}
if (nspk == outputs.active)
{
DPRINTF(E_LOG, L_MPD, "No speaker to activate\n");
free_outputs(outputs.outputs);
return 0;
}
ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t));
ids[0] = nspk;
i = 1;
output = outputs.outputs;
while (output)
{
if (output->shortid == num || output->selected)
{
ids[i] = output->id;
i++;
}
output = output->next;
}
ret = player_speaker_set(ids);
if (ids)
free(ids);
free_outputs(outputs.outputs);
if (ret < 0) if (ret < 0)
{ {
*errmsg = safe_asprintf("Speakers activation failed: %d", num); *errmsg = safe_asprintf("Speakers deactivation failed: %d", num);
return ACK_ERROR_UNKNOWN; return ACK_ERROR_UNKNOWN;
} }
}
return 0; return 0;
} }
@ -3775,20 +3667,10 @@ mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **e
static int static int
mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx)
{ {
struct outputs outputs; struct output_get_param param;
struct output *output;
uint32_t num; uint32_t num;
uint64_t *ids;
int nspk;
int i;
int ret; int ret;
if (argc < 2)
{
*errmsg = safe_asprintf("Missing argument for command 'toggleoutput'");
return ACK_ERROR_ARG;
}
ret = safe_atou32(argv[1], &num); ret = safe_atou32(argv[1], &num);
if (ret < 0) if (ret < 0)
{ {
@ -3796,65 +3678,26 @@ mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **e
return ACK_ERROR_ARG; return ACK_ERROR_ARG;
} }
outputs.count = 0; memset(&param, 0, sizeof(struct output_get_param));
outputs.active = 0; param.shortid = num;
outputs.outputs = NULL;
player_speaker_enumerate(outputs_enum_cb, &outputs); player_speaker_enumerate(output_get_cb, &param);
nspk = outputs.active; if (param.output)
output = outputs.outputs;
while (output)
{ {
if (output->shortid == num && !output->selected) if (param.output->selected)
{ ret = player_speaker_disable(param.output->id);
nspk++; else
break; ret = player_speaker_enable(param.output->id);
}
else if (output->shortid == num && output->selected)
{
nspk--;
break;
}
output = output->next;
}
if (nspk == outputs.active) free_output(param.output);
{
DPRINTF(E_LOG, L_MPD, "No speaker to de/activate\n");
free_outputs(outputs.outputs);
return 0;
}
ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t));
ids[0] = nspk;
i = 1;
output = outputs.outputs;
while (output)
{
if ((output->shortid == num && !output->selected)
|| (output->shortid != num && output->selected))
{
ids[i] = output->id;
i++;
}
output = output->next;
}
ret = player_speaker_set(ids);
if (ids)
free(ids);
free_outputs(outputs.outputs);
if (ret < 0) if (ret < 0)
{ {
*errmsg = safe_asprintf("Speakers de/activation failed: %d", num); *errmsg = safe_asprintf("Toggle speaker failed: %d", num);
return ACK_ERROR_UNKNOWN; return ACK_ERROR_UNKNOWN;
} }
}
return 0; return 0;
} }
@ -3888,7 +3731,7 @@ speaker_enum_cb(struct spk_info *spk, void *arg)
} }
/* /*
* Command handler function for 'outputs' * Command handler function for 'output'
* Returns a lists with the avaiable speakers. * Returns a lists with the avaiable speakers.
*/ */
static int static int
@ -3902,42 +3745,30 @@ mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
static int static int
outputvolume_set(uint32_t shortid, int volume, char **errmsg) outputvolume_set(uint32_t shortid, int volume, char **errmsg)
{ {
struct outputs outputs; struct output_get_param param;
struct output *output;
int ret; int ret;
outputs.count = 0; memset(&param, 0, sizeof(struct output_get_param));
outputs.active = 0; param.shortid = shortid;
outputs.outputs = NULL;
player_speaker_enumerate(outputs_enum_cb, &outputs); player_speaker_enumerate(output_get_cb, &param);
output = outputs.outputs; if (param.output)
while (output)
{ {
if (output->shortid == shortid) ret = player_volume_setabs_speaker(param.output->id, volume);
{ free_output(param.output);
break;
}
output = output->next;
}
if (!output)
{
free_outputs(outputs.outputs);
*errmsg = safe_asprintf("No speaker found for short id: %d", shortid);
return ACK_ERROR_UNKNOWN;
}
ret = player_volume_setabs_speaker(output->id, volume);
free_outputs(outputs.outputs);
if (ret < 0) if (ret < 0)
{ {
*errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid); *errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid);
return ACK_ERROR_UNKNOWN; return ACK_ERROR_UNKNOWN;
} }
}
else
{
*errmsg = safe_asprintf("No speaker found for short id: %d", shortid);
return ACK_ERROR_UNKNOWN;
}
return 0; return 0;
} }
@ -3949,12 +3780,6 @@ mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **e
int volume; int volume;
int ret; int ret;
if (argc < 3)
{
*errmsg = safe_asprintf("Missing argument for command 'outputvolume'");
return ACK_ERROR_ARG;
}
ret = safe_atou32(argv[1], &shortid); ret = safe_atou32(argv[1], &shortid);
if (ret < 0) if (ret < 0)
{ {
@ -4335,9 +4160,9 @@ static struct mpd_command mpd_handlers[] =
{ "ping", mpd_command_ignore, -1 }, { "ping", mpd_command_ignore, -1 },
// Audio output devices // Audio output devices
{ "disableoutput", mpd_command_disableoutput, -1 }, { "disableoutput", mpd_command_disableoutput, 2 },
{ "enableoutput", mpd_command_enableoutput, -1 }, { "enableoutput", mpd_command_enableoutput, 2 },
{ "toggleoutput", mpd_command_toggleoutput, -1 }, { "toggleoutput", mpd_command_toggleoutput, 2 },
{ "outputs", mpd_command_outputs, -1 }, { "outputs", mpd_command_outputs, -1 },
// Reflection // Reflection
@ -4356,7 +4181,7 @@ static struct mpd_command mpd_handlers[] =
{ "sendmessage", mpd_command_sendmessage, -1 }, { "sendmessage", mpd_command_sendmessage, -1 },
// Forked-daapd commands (not supported by mpd) // Forked-daapd commands (not supported by mpd)
{ "outputvolume", mpd_command_outputvolume, -1 }, { "outputvolume", mpd_command_outputvolume, 3 },
// NULL command to terminate loop // NULL command to terminate loop
{ NULL, NULL, -1 } { NULL, NULL, -1 }