mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-26 12:59:19 -05:00
[mpd] Refactor commands to enable/disable/toggle/volume for outputs
This commit is contained in:
parent
decf9f1329
commit
43887d160f
309
src/mpd.c
309
src/mpd.c
@ -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(¶m, 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, ¶m);
|
||||||
|
|
||||||
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(¶m, 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, ¶m);
|
||||||
|
|
||||||
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(¶m, 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, ¶m);
|
||||||
|
|
||||||
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(¶m, 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, ¶m);
|
||||||
|
|
||||||
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 }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user