mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-28 08:05:56 -05:00
Merge pull request #489 from chme/playeroutputs
Refactore output enumeration and support enable/disable of single output
This commit is contained in:
commit
cdaa929078
@ -510,34 +510,34 @@ playqueuecontents_add_queue_item(struct evbuffer *songlist, struct db_queue_item
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg)
|
speaker_enum_cb(struct spk_info *spk, void *arg)
|
||||||
{
|
{
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
evbuf = (struct evbuffer *)arg;
|
evbuf = (struct evbuffer *)arg;
|
||||||
|
|
||||||
len = 8 + strlen(name) + 28;
|
len = 8 + strlen(spk->name) + 28;
|
||||||
if (flags.selected)
|
if (spk->selected)
|
||||||
len += 9;
|
len += 9;
|
||||||
if (flags.has_password)
|
if (spk->has_password)
|
||||||
len += 9;
|
len += 9;
|
||||||
if (flags.has_video)
|
if (spk->has_video)
|
||||||
len += 9;
|
len += 9;
|
||||||
|
|
||||||
CHECK_ERR(L_DACP, evbuffer_expand(evbuf, 71 + len));
|
CHECK_ERR(L_DACP, evbuffer_expand(evbuf, 71 + len));
|
||||||
|
|
||||||
dmap_add_container(evbuf, "mdcl", len); /* 8 + len */
|
dmap_add_container(evbuf, "mdcl", len); /* 8 + len */
|
||||||
if (flags.selected)
|
if (spk->selected)
|
||||||
dmap_add_char(evbuf, "caia", 1); /* 9 */
|
dmap_add_char(evbuf, "caia", 1); /* 9 */
|
||||||
if (flags.has_password)
|
if (spk->has_password)
|
||||||
dmap_add_char(evbuf, "cahp", 1); /* 9 */
|
dmap_add_char(evbuf, "cahp", 1); /* 9 */
|
||||||
if (flags.has_video)
|
if (spk->has_video)
|
||||||
dmap_add_char(evbuf, "caiv", 1); /* 9 */
|
dmap_add_char(evbuf, "caiv", 1); /* 9 */
|
||||||
dmap_add_string(evbuf, "minm", name); /* 8 + len */
|
dmap_add_string(evbuf, "minm", spk->name); /* 8 + len */
|
||||||
dmap_add_long(evbuf, "msma", id); /* 16 */
|
dmap_add_long(evbuf, "msma", spk->id); /* 16 */
|
||||||
|
|
||||||
dmap_add_int(evbuf, "cmvo", relvol); /* 12 */
|
dmap_add_int(evbuf, "cmvo", spk->relvol); /* 12 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -495,7 +495,7 @@ jsonapi_reply_lastfm_logout(struct httpd_request *hreq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg)
|
speaker_enum_cb(struct spk_info *spk, void *arg)
|
||||||
{
|
{
|
||||||
json_object *outputs;
|
json_object *outputs;
|
||||||
json_object *output;
|
json_object *output;
|
||||||
@ -504,15 +504,15 @@ speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relv
|
|||||||
outputs = arg;
|
outputs = arg;
|
||||||
output = json_object_new_object();
|
output = json_object_new_object();
|
||||||
|
|
||||||
snprintf(output_id, sizeof(output_id), "%" PRIu64, id);
|
snprintf(output_id, sizeof(output_id), "%" PRIu64, spk->id);
|
||||||
json_object_object_add(output, "id", json_object_new_string(output_id));
|
json_object_object_add(output, "id", json_object_new_string(output_id));
|
||||||
json_object_object_add(output, "name", json_object_new_string(name));
|
json_object_object_add(output, "name", json_object_new_string(spk->name));
|
||||||
json_object_object_add(output, "type", json_object_new_string(output_type));
|
json_object_object_add(output, "type", json_object_new_string(spk->output_type));
|
||||||
json_object_object_add(output, "selected", json_object_new_boolean(flags.selected));
|
json_object_object_add(output, "selected", json_object_new_boolean(spk->selected));
|
||||||
json_object_object_add(output, "has_password", json_object_new_boolean(flags.has_password));
|
json_object_object_add(output, "has_password", json_object_new_boolean(spk->has_password));
|
||||||
json_object_object_add(output, "requires_auth", json_object_new_boolean(flags.requires_auth));
|
json_object_object_add(output, "requires_auth", json_object_new_boolean(spk->requires_auth));
|
||||||
json_object_object_add(output, "needs_auth_key", json_object_new_boolean(flags.needs_auth_key));
|
json_object_object_add(output, "needs_auth_key", json_object_new_boolean(spk->needs_auth_key));
|
||||||
json_object_object_add(output, "volume", json_object_new_int(absvol));
|
json_object_object_add(output, "volume", json_object_new_int(spk->absvol));
|
||||||
|
|
||||||
json_object_array_add(outputs, output);
|
json_object_array_add(outputs, output);
|
||||||
}
|
}
|
||||||
|
336
src/mpd.c
336
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3571,31 +3561,27 @@ mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback function for the 'player_speaker_enumerate' function.
|
* Callback function for the 'player_speaker_enumerate' function.
|
||||||
* Adds a new struct output to the given struct outputs in *arg for the given speaker (id, name, etc.).
|
* Expect a struct output_get_param as argument and allocates a struct output if
|
||||||
|
* the shortid of output_get_param matches the given speaker/output spk.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
outputs_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, 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 = id;
|
DPRINTF(E_DBG, L_MPD, "Output found: shortid %d, id %" PRIu64 ", name '%s', selected %d\n",
|
||||||
output->shortid = (unsigned short) id;
|
param->output->shortid, param->output->id, param->output->name, param->output->selected);
|
||||||
output->name = strdup(name);
|
}
|
||||||
output->selected = flags.selected;
|
|
||||||
|
|
||||||
output->next = outputs->outputs;
|
|
||||||
outputs->outputs = output;
|
|
||||||
outputs->count++;
|
|
||||||
if (flags.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3605,20 +3591,10 @@ outputs_enum_cb(uint64_t id, const char *name, const char *output_type, int relv
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -3626,57 +3602,21 @@ 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);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nspk--;
|
*errmsg = safe_asprintf("Speakers deactivation failed: %d", num);
|
||||||
break;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
{
|
|
||||||
*errmsg = safe_asprintf("Speakers deactivation failed: %d", num);
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3689,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)
|
||||||
{
|
{
|
||||||
@ -3710,58 +3640,21 @@ 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);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nspk++;
|
*errmsg = safe_asprintf("Speakers deactivation failed: %d", num);
|
||||||
break;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
{
|
|
||||||
*errmsg = safe_asprintf("Speakers activation failed: %d", num);
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3774,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)
|
||||||
{
|
{
|
||||||
@ -3795,64 +3678,25 @@ 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);
|
||||||
|
else
|
||||||
|
ret = player_speaker_enable(param.output->id);
|
||||||
|
|
||||||
|
free_output(param.output);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nspk++;
|
*errmsg = safe_asprintf("Toggle speaker failed: %d", num);
|
||||||
break;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
else if (output->shortid == num && output->selected)
|
|
||||||
{
|
|
||||||
nspk--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
output = output->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nspk == outputs.active)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
*errmsg = safe_asprintf("Speakers de/activation failed: %d", num);
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3869,7 +3713,7 @@ mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||||||
* outputvolume: 50
|
* outputvolume: 50
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg)
|
speaker_enum_cb(struct spk_info *spk, void *arg)
|
||||||
{
|
{
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
|
|
||||||
@ -3880,14 +3724,14 @@ speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relv
|
|||||||
"outputname: %s\n"
|
"outputname: %s\n"
|
||||||
"outputenabled: %d\n"
|
"outputenabled: %d\n"
|
||||||
"outputvolume: %d\n",
|
"outputvolume: %d\n",
|
||||||
(unsigned short) id,
|
(unsigned short) spk->id,
|
||||||
name,
|
spk->name,
|
||||||
flags.selected,
|
spk->selected,
|
||||||
absvol);
|
spk->absvol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@ -3901,43 +3745,31 @@ 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);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
break;
|
*errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid);
|
||||||
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
output = output->next;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!output)
|
|
||||||
{
|
{
|
||||||
free_outputs(outputs.outputs);
|
|
||||||
*errmsg = safe_asprintf("No speaker found for short id: %d", shortid);
|
*errmsg = safe_asprintf("No speaker found for short id: %d", shortid);
|
||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_volume_setabs_speaker(output->id, volume);
|
|
||||||
|
|
||||||
free_outputs(outputs.outputs);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
*errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid);
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3948,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)
|
||||||
{
|
{
|
||||||
@ -4334,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
|
||||||
@ -4355,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 }
|
||||||
|
300
src/player.c
300
src/player.c
@ -155,16 +155,7 @@ struct speaker_auth_param
|
|||||||
|
|
||||||
union player_arg
|
union player_arg
|
||||||
{
|
{
|
||||||
struct volume_param vol_param;
|
|
||||||
void *noarg;
|
|
||||||
struct spk_enum *spk_enum;
|
|
||||||
struct output_device *device;
|
struct output_device *device;
|
||||||
struct player_status *status;
|
|
||||||
struct player_source *ps;
|
|
||||||
struct metadata_param metadata_param;
|
|
||||||
uint32_t *id_ptr;
|
|
||||||
struct speaker_set_param speaker_set_param;
|
|
||||||
enum repeat_mode mode;
|
|
||||||
struct speaker_auth_param auth;
|
struct speaker_auth_param auth;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int intval;
|
int intval;
|
||||||
@ -1375,13 +1366,12 @@ device_auth_kickoff(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
device_metadata_send(void *arg, int *retval)
|
device_metadata_send(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg;
|
struct metadata_param *metadata_param = arg;
|
||||||
struct input_metadata *imd;
|
struct input_metadata *imd;
|
||||||
struct output_metadata *omd;
|
struct output_metadata *omd;
|
||||||
|
|
||||||
cmdarg = arg;
|
imd = metadata_param->input;
|
||||||
imd = cmdarg->metadata_param.input;
|
omd = metadata_param->output;
|
||||||
omd = cmdarg->metadata_param.output;
|
|
||||||
|
|
||||||
outputs_metadata_send(omd, imd->rtptime, imd->offset, imd->startup);
|
outputs_metadata_send(omd, imd->rtptime, imd->offset, imd->startup);
|
||||||
|
|
||||||
@ -1777,15 +1767,12 @@ playback_suspend(void)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
get_status(void *arg, int *retval)
|
get_status(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
struct player_status *status = arg;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
struct player_source *ps;
|
struct player_source *ps;
|
||||||
struct player_status *status;
|
|
||||||
uint64_t pos;
|
uint64_t pos;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
status = cmdarg->status;
|
|
||||||
|
|
||||||
memset(status, 0, sizeof(struct player_status));
|
memset(status, 0, sizeof(struct player_status));
|
||||||
|
|
||||||
status->shuffle = shuffle;
|
status->shuffle = shuffle;
|
||||||
@ -1865,12 +1852,9 @@ get_status(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
now_playing(void *arg, int *retval)
|
now_playing(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
uint32_t *id = arg;
|
||||||
uint32_t *id;
|
|
||||||
struct player_source *ps_playing;
|
struct player_source *ps_playing;
|
||||||
|
|
||||||
id = cmdarg->id_ptr;
|
|
||||||
|
|
||||||
ps_playing = source_now_playing();
|
ps_playing = source_now_playing();
|
||||||
|
|
||||||
if (ps_playing)
|
if (ps_playing)
|
||||||
@ -2398,32 +2382,27 @@ player_speaker_status_trigger(void)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
speaker_enumerate(void *arg, int *retval)
|
speaker_enumerate(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
struct spk_enum *spk_enum = arg;
|
||||||
struct output_device *device;
|
struct output_device *device;
|
||||||
struct spk_enum *spk_enum;
|
struct spk_info spk;
|
||||||
struct spk_flags flags;
|
|
||||||
|
|
||||||
spk_enum = cmdarg->spk_enum;
|
|
||||||
|
|
||||||
#ifdef DEBUG_RELVOL
|
|
||||||
DPRINTF(E_DBG, L_PLAYER, "*** master: %d\n", master_volume);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (device = dev_list; device; device = device->next)
|
for (device = dev_list; device; device = device->next)
|
||||||
{
|
{
|
||||||
if (device->advertised || device->selected)
|
if (device->advertised || device->selected)
|
||||||
{
|
{
|
||||||
flags.selected = device->selected;
|
spk.id = device->id;
|
||||||
flags.has_password = device->has_password;
|
spk.name = device->name;
|
||||||
flags.has_video = device->has_video;
|
spk.output_type = device->type_name;
|
||||||
flags.requires_auth = device->requires_auth;
|
spk.relvol = device->relvol;
|
||||||
flags.needs_auth_key = (device->requires_auth && device->auth_key == NULL);
|
spk.absvol = device->volume;
|
||||||
|
|
||||||
spk_enum->cb(device->id, device->name, device->type_name, device->relvol, device->volume, flags, spk_enum->arg);
|
spk.selected = device->selected;
|
||||||
|
spk.has_password = device->has_password;
|
||||||
|
spk.has_video = device->has_video;
|
||||||
|
spk.requires_auth = device->requires_auth;
|
||||||
|
spk.needs_auth_key = (device->requires_auth && device->auth_key == NULL);
|
||||||
|
|
||||||
#ifdef DEBUG_RELVOL
|
spk_enum->cb(&spk, spk_enum->arg);
|
||||||
DPRINTF(E_DBG, L_PLAYER, "*** %s: abs %d rel %d\n", device->name, device->volume, device->relvol);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2436,12 +2415,21 @@ speaker_activate(struct output_device *device)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!device)
|
if (device->has_password && !device->password)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Bug! speaker_activate called with device\n");
|
DPRINTF(E_INFO, L_PLAYER, "The %s device '%s' is password-protected, but we don't have it\n", device->type_name, device->name);
|
||||||
return -1;
|
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is selected\n", device->type_name, device->name);
|
||||||
|
|
||||||
|
if (!device->selected)
|
||||||
|
speaker_select_output(device);
|
||||||
|
|
||||||
|
if (device->session)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (player_state == PLAY_PLAYING)
|
if (player_state == PLAY_PLAYING)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_PLAYER, "Activating %s device '%s'\n", device->type_name, device->name);
|
DPRINTF(E_DBG, L_PLAYER, "Activating %s device '%s'\n", device->type_name, device->name);
|
||||||
@ -2450,7 +2438,7 @@ speaker_activate(struct output_device *device)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Could not start %s device '%s'\n", device->type_name, device->name);
|
DPRINTF(E_LOG, L_PLAYER, "Could not start %s device '%s'\n", device->type_name, device->name);
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2461,11 +2449,16 @@ speaker_activate(struct output_device *device)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Could not probe %s device '%s'\n", device->type_name, device->name);
|
DPRINTF(E_LOG, L_PLAYER, "Could not probe %s device '%s'\n", device->type_name, device->name);
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
DPRINTF(E_LOG, L_PLAYER, "Could not activate %s device '%s'\n", device->type_name, device->name);
|
||||||
|
speaker_deselect_output(device);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2473,16 +2466,21 @@ speaker_deactivate(struct output_device *device)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_PLAYER, "Deactivating %s device '%s'\n", device->type_name, device->name);
|
DPRINTF(E_DBG, L_PLAYER, "Deactivating %s device '%s'\n", device->type_name, device->name);
|
||||||
|
|
||||||
|
if (device->selected)
|
||||||
|
speaker_deselect_output(device);
|
||||||
|
|
||||||
|
if (!device->session)
|
||||||
|
return 0;
|
||||||
|
|
||||||
outputs_status_cb(device->session, device_shutdown_cb);
|
outputs_status_cb(device->session, device_shutdown_cb);
|
||||||
outputs_device_stop(device->session);
|
outputs_device_stop(device->session);
|
||||||
|
return 1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum command_state
|
static enum command_state
|
||||||
speaker_set(void *arg, int *retval)
|
speaker_set(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
struct speaker_set_param *speaker_set_param = arg;
|
||||||
struct output_device *device;
|
struct output_device *device;
|
||||||
uint64_t *ids;
|
uint64_t *ids;
|
||||||
int nspk;
|
int nspk;
|
||||||
@ -2490,7 +2488,7 @@ speaker_set(void *arg, int *retval)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*retval = 0;
|
*retval = 0;
|
||||||
ids = cmdarg->speaker_set_param.device_ids;
|
ids = speaker_set_param->device_ids;
|
||||||
|
|
||||||
if (ids)
|
if (ids)
|
||||||
nspk = ids[0];
|
nspk = ids[0];
|
||||||
@ -2513,62 +2511,80 @@ speaker_set(void *arg, int *retval)
|
|||||||
|
|
||||||
if (i <= nspk)
|
if (i <= nspk)
|
||||||
{
|
{
|
||||||
if (device->has_password && !device->password)
|
ret = speaker_activate(device);
|
||||||
{
|
|
||||||
DPRINTF(E_INFO, L_PLAYER, "The %s device '%s' is password-protected, but we don't have it\n", device->type_name, device->name);
|
|
||||||
|
|
||||||
cmdarg->speaker_set_param.intval = -2;
|
if (ret > 0)
|
||||||
continue;
|
(*retval)++;
|
||||||
}
|
else if (ret < 0 && speaker_set_param->intval != -2)
|
||||||
|
speaker_set_param->intval = ret;
|
||||||
DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is selected\n", device->type_name, device->name);
|
|
||||||
|
|
||||||
if (!device->selected)
|
|
||||||
speaker_select_output(device);
|
|
||||||
|
|
||||||
if (!device->session)
|
|
||||||
{
|
|
||||||
ret = speaker_activate(device);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Could not activate %s device '%s'\n", device->type_name, device->name);
|
|
||||||
|
|
||||||
speaker_deselect_output(device);
|
|
||||||
|
|
||||||
if (cmdarg->speaker_set_param.intval != -2)
|
|
||||||
cmdarg->speaker_set_param.intval = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
(*retval)++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is NOT selected\n", device->type_name, device->name);
|
ret = speaker_deactivate(device);
|
||||||
|
|
||||||
if (device->selected)
|
if (ret > 0)
|
||||||
speaker_deselect_output(device);
|
(*retval)++;
|
||||||
|
}
|
||||||
if (device->session)
|
}
|
||||||
{
|
|
||||||
ret = speaker_deactivate(device);
|
if (*retval > 0)
|
||||||
if (ret < 0)
|
return COMMAND_PENDING; // async
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Could not deactivate %s device '%s'\n", device->type_name, device->name);
|
*retval = speaker_set_param->intval;
|
||||||
|
return COMMAND_END;
|
||||||
if (cmdarg->speaker_set_param.intval != -2)
|
}
|
||||||
cmdarg->speaker_set_param.intval = -1;
|
|
||||||
}
|
static enum command_state
|
||||||
else
|
speaker_enable(void *arg, int *retval)
|
||||||
(*retval)++;
|
{
|
||||||
}
|
uint64_t *id = arg;
|
||||||
|
struct output_device *device;
|
||||||
|
|
||||||
|
*retval = 0;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "Speaker enable: %" PRIu64 "\n", *id);
|
||||||
|
|
||||||
|
*retval = 0;
|
||||||
|
|
||||||
|
for (device = dev_list; device; device = device->next)
|
||||||
|
{
|
||||||
|
if (*id == device->id)
|
||||||
|
{
|
||||||
|
*retval = speaker_activate(device);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*retval > 0)
|
||||||
|
return COMMAND_PENDING; // async
|
||||||
|
|
||||||
|
return COMMAND_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum command_state
|
||||||
|
speaker_disable(void *arg, int *retval)
|
||||||
|
{
|
||||||
|
uint64_t *id = arg;
|
||||||
|
struct output_device *device;
|
||||||
|
|
||||||
|
*retval = 0;
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "Speaker disable: %" PRIu64 "\n", *id);
|
||||||
|
|
||||||
|
*retval = 0;
|
||||||
|
|
||||||
|
for (device = dev_list; device; device = device->next)
|
||||||
|
{
|
||||||
|
if (*id == device->id)
|
||||||
|
{
|
||||||
|
*retval = speaker_deactivate(device);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*retval > 0)
|
if (*retval > 0)
|
||||||
return COMMAND_PENDING; // async
|
return COMMAND_PENDING; // async
|
||||||
|
|
||||||
*retval = cmdarg->speaker_set_param.intval;
|
|
||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2613,14 +2629,14 @@ volume_set(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
volume_setrel_speaker(void *arg, int *retval)
|
volume_setrel_speaker(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
struct volume_param *vol_param = arg;
|
||||||
struct output_device *device;
|
struct output_device *device;
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
int relvol;
|
int relvol;
|
||||||
|
|
||||||
*retval = 0;
|
*retval = 0;
|
||||||
id = cmdarg->vol_param.spk_id;
|
id = vol_param->spk_id;
|
||||||
relvol = cmdarg->vol_param.volume;
|
relvol = vol_param->volume;
|
||||||
|
|
||||||
for (device = dev_list; device; device = device->next)
|
for (device = dev_list; device; device = device->next)
|
||||||
{
|
{
|
||||||
@ -2657,14 +2673,14 @@ volume_setrel_speaker(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
volume_setabs_speaker(void *arg, int *retval)
|
volume_setabs_speaker(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
struct volume_param *vol_param = arg;
|
||||||
struct output_device *device;
|
struct output_device *device;
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
int volume;
|
int volume;
|
||||||
|
|
||||||
*retval = 0;
|
*retval = 0;
|
||||||
id = cmdarg->vol_param.spk_id;
|
id = vol_param->spk_id;
|
||||||
volume = cmdarg->vol_param.volume;
|
volume = vol_param->volume;
|
||||||
|
|
||||||
master_volume = volume;
|
master_volume = volume;
|
||||||
|
|
||||||
@ -2707,24 +2723,24 @@ volume_setabs_speaker(void *arg, int *retval)
|
|||||||
static enum command_state
|
static enum command_state
|
||||||
repeat_set(void *arg, int *retval)
|
repeat_set(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
union player_arg *cmdarg = arg;
|
enum repeat_mode *mode = arg;
|
||||||
|
|
||||||
if (cmdarg->mode == repeat)
|
if (*mode == repeat)
|
||||||
{
|
{
|
||||||
*retval = 0;
|
*retval = 0;
|
||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmdarg->mode)
|
switch (*mode)
|
||||||
{
|
{
|
||||||
case REPEAT_OFF:
|
case REPEAT_OFF:
|
||||||
case REPEAT_SONG:
|
case REPEAT_SONG:
|
||||||
case REPEAT_ALL:
|
case REPEAT_ALL:
|
||||||
repeat = cmdarg->mode;
|
repeat = *mode;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Invalid repeat mode: %d\n", cmdarg->mode);
|
DPRINTF(E_LOG, L_PLAYER, "Invalid repeat mode: %d\n", *mode);
|
||||||
*retval = -1;
|
*retval = -1;
|
||||||
return COMMAND_END;
|
return COMMAND_END;
|
||||||
}
|
}
|
||||||
@ -2854,12 +2870,9 @@ player_get_current_pos(uint64_t *pos, struct timespec *ts, int commit)
|
|||||||
int
|
int
|
||||||
player_get_status(struct player_status *status)
|
player_get_status(struct player_status *status)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cmdarg.status = status;
|
ret = commands_exec_sync(cmdbase, get_status, NULL, status);
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, get_status, NULL, &cmdarg);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2875,12 +2888,9 @@ player_get_status(struct player_status *status)
|
|||||||
int
|
int
|
||||||
player_now_playing(uint32_t *id)
|
player_now_playing(uint32_t *id)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cmdarg.id_ptr = id;
|
ret = commands_exec_sync(cmdbase, now_playing, NULL, id);
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, now_playing, NULL, &cmdarg);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2985,27 +2995,48 @@ player_playback_prev(void)
|
|||||||
void
|
void
|
||||||
player_speaker_enumerate(spk_enum_cb cb, void *arg)
|
player_speaker_enumerate(spk_enum_cb cb, void *arg)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
|
||||||
struct spk_enum spk_enum;
|
struct spk_enum spk_enum;
|
||||||
|
|
||||||
spk_enum.cb = cb;
|
spk_enum.cb = cb;
|
||||||
spk_enum.arg = arg;
|
spk_enum.arg = arg;
|
||||||
|
|
||||||
cmdarg.spk_enum = &spk_enum;
|
commands_exec_sync(cmdbase, speaker_enumerate, NULL, &spk_enum);
|
||||||
|
|
||||||
commands_exec_sync(cmdbase, speaker_enumerate, NULL, &cmdarg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
player_speaker_set(uint64_t *ids)
|
player_speaker_set(uint64_t *ids)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
struct speaker_set_param speaker_set_param;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cmdarg.speaker_set_param.device_ids = ids;
|
speaker_set_param.device_ids = ids;
|
||||||
cmdarg.speaker_set_param.intval = 0;
|
speaker_set_param.intval = 0;
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, speaker_set, NULL, &cmdarg);
|
ret = commands_exec_sync(cmdbase, speaker_set, NULL, &speaker_set_param);
|
||||||
|
|
||||||
|
listener_notify(LISTENER_SPEAKER);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
player_speaker_enable(uint64_t id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = commands_exec_sync(cmdbase, speaker_enable, NULL, &id);
|
||||||
|
|
||||||
|
listener_notify(LISTENER_SPEAKER);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
player_speaker_disable(uint64_t id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = commands_exec_sync(cmdbase, speaker_disable, NULL, &id);
|
||||||
|
|
||||||
listener_notify(LISTENER_SPEAKER);
|
listener_notify(LISTENER_SPEAKER);
|
||||||
|
|
||||||
@ -3033,7 +3064,7 @@ player_volume_set(int vol)
|
|||||||
int
|
int
|
||||||
player_volume_setrel_speaker(uint64_t id, int relvol)
|
player_volume_setrel_speaker(uint64_t id, int relvol)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
struct volume_param vol_param;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (relvol < 0 || relvol > 100)
|
if (relvol < 0 || relvol > 100)
|
||||||
@ -3042,17 +3073,17 @@ player_volume_setrel_speaker(uint64_t id, int relvol)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdarg.vol_param.spk_id = id;
|
vol_param.spk_id = id;
|
||||||
cmdarg.vol_param.volume = relvol;
|
vol_param.volume = relvol;
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, volume_setrel_speaker, NULL, &cmdarg);
|
ret = commands_exec_sync(cmdbase, volume_setrel_speaker, NULL, &vol_param);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
player_volume_setabs_speaker(uint64_t id, int vol)
|
player_volume_setabs_speaker(uint64_t id, int vol)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
struct volume_param vol_param;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (vol < 0 || vol > 100)
|
if (vol < 0 || vol > 100)
|
||||||
@ -3061,22 +3092,19 @@ player_volume_setabs_speaker(uint64_t id, int vol)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdarg.vol_param.spk_id = id;
|
vol_param.spk_id = id;
|
||||||
cmdarg.vol_param.volume = vol;
|
vol_param.volume = vol;
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, volume_setabs_speaker, NULL, &cmdarg);
|
ret = commands_exec_sync(cmdbase, volume_setabs_speaker, NULL, &vol_param);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
player_repeat_set(enum repeat_mode mode)
|
player_repeat_set(enum repeat_mode mode)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cmdarg.mode = mode;
|
ret = commands_exec_sync(cmdbase, repeat_set, NULL, &mode);
|
||||||
|
|
||||||
ret = commands_exec_sync(cmdbase, repeat_set, NULL, &cmdarg);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3200,12 +3228,12 @@ player_raop_verification_kickoff(char **arglist)
|
|||||||
void
|
void
|
||||||
player_metadata_send(void *imd, void *omd)
|
player_metadata_send(void *imd, void *omd)
|
||||||
{
|
{
|
||||||
union player_arg cmdarg;
|
struct metadata_param metadata_param;
|
||||||
|
|
||||||
cmdarg.metadata_param.input = imd;
|
metadata_param.input = imd;
|
||||||
cmdarg.metadata_param.output = omd;
|
metadata_param.output = omd;
|
||||||
|
|
||||||
commands_exec_sync(cmdbase, device_metadata_send, NULL, &cmdarg);
|
commands_exec_sync(cmdbase, device_metadata_send, NULL, &metadata_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
27
src/player.h
27
src/player.h
@ -2,6 +2,7 @@
|
|||||||
#ifndef __PLAYER_H__
|
#ifndef __PLAYER_H__
|
||||||
#define __PLAYER_H__
|
#define __PLAYER_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
@ -28,13 +29,19 @@ enum repeat_mode {
|
|||||||
REPEAT_ALL = 2,
|
REPEAT_ALL = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spk_flags {
|
struct spk_info {
|
||||||
unsigned selected:1;
|
uint64_t id;
|
||||||
unsigned has_password:1;
|
const char *name;
|
||||||
unsigned requires_auth:1;
|
const char *output_type;
|
||||||
unsigned needs_auth_key:1;
|
int relvol;
|
||||||
|
int absvol;
|
||||||
|
|
||||||
unsigned has_video:1;
|
bool selected;
|
||||||
|
bool has_password;
|
||||||
|
bool requires_auth;
|
||||||
|
bool needs_auth_key;
|
||||||
|
|
||||||
|
bool has_video;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct player_status {
|
struct player_status {
|
||||||
@ -57,7 +64,7 @@ struct player_status {
|
|||||||
uint32_t len_ms;
|
uint32_t len_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*spk_enum_cb)(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg);
|
typedef void (*spk_enum_cb)(struct spk_info *spk, void *arg);
|
||||||
|
|
||||||
struct player_history
|
struct player_history
|
||||||
{
|
{
|
||||||
@ -88,6 +95,12 @@ player_speaker_enumerate(spk_enum_cb cb, void *arg);
|
|||||||
int
|
int
|
||||||
player_speaker_set(uint64_t *ids);
|
player_speaker_set(uint64_t *ids);
|
||||||
|
|
||||||
|
int
|
||||||
|
player_speaker_enable(uint64_t id);
|
||||||
|
|
||||||
|
int
|
||||||
|
player_speaker_disable(uint64_t id);
|
||||||
|
|
||||||
void
|
void
|
||||||
player_speaker_status_trigger(void);
|
player_speaker_status_trigger(void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user