Merge pull request #374 from chme/outputsvolume
Set speaker/output volume with mpd sendmessage command
This commit is contained in:
commit
4423cd4ce6
226
src/mpd.c
226
src/mpd.c
|
@ -3636,6 +3636,135 @@ mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
outputvolume_set(uint32_t shortid, int volume, char **errmsg)
|
||||||
|
{
|
||||||
|
struct outputs outputs;
|
||||||
|
struct output *output;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
outputs.count = 0;
|
||||||
|
outputs.active = 0;
|
||||||
|
outputs.outputs = NULL;
|
||||||
|
|
||||||
|
player_speaker_enumerate(outputs_enum_cb, &outputs);
|
||||||
|
|
||||||
|
output = outputs.outputs;
|
||||||
|
while (output)
|
||||||
|
{
|
||||||
|
if (output->shortid == shortid)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output = output->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
|
free_outputs(outputs.outputs);
|
||||||
|
ret = asprintf(errmsg, "No speaker found for short id: %d", shortid);
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = player_volume_setabs_speaker(output->id, volume);
|
||||||
|
|
||||||
|
free_outputs(outputs.outputs);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ret = asprintf(errmsg, "Setting volume to %d for speaker with short-id %d failed", volume, shortid);
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
|
{
|
||||||
|
uint32_t shortid;
|
||||||
|
int volume;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
ret = asprintf(errmsg, "Missing argument for command 'outputvolume'");
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safe_atou32(argv[1], &shortid);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[1]);
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safe_atoi32(argv[2], &volume);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[2]);
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = outputvolume_set(shortid, volume, errmsg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
channel_outputvolume(const char *message)
|
||||||
|
{
|
||||||
|
uint32_t shortid;
|
||||||
|
int volume;
|
||||||
|
char *tmp;
|
||||||
|
char *ptr;
|
||||||
|
char *errmsg = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tmp = strdup(message);
|
||||||
|
ptr = strrchr(tmp, ':');
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
free(tmp);
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Failed to parse output id and volume from message '%s' (expected format: \"output-id:volume\"\n", message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
ret = safe_atou32(tmp, &shortid);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
free(tmp);
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Failed to parse output id from message: '%s'\n", message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safe_atoi32((ptr + 1), &volume);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
free(tmp);
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Failed to parse volume from message: '%s'\n", message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputvolume_set(shortid, volume, &errmsg);
|
||||||
|
if (errmsg)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Failed to set output volume from message: '%s' (error='%s')\n", message, errmsg);
|
||||||
|
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
channel_pairing(const char *message)
|
channel_pairing(const char *message)
|
||||||
{
|
{
|
||||||
|
@ -3657,6 +3786,10 @@ struct mpd_channel
|
||||||
|
|
||||||
static struct mpd_channel mpd_channels[] =
|
static struct mpd_channel mpd_channels[] =
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
.channel = "outputvolume",
|
||||||
|
.handler = channel_outputvolume
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.channel = "pairing",
|
.channel = "pairing",
|
||||||
.handler = channel_pairing
|
.handler = channel_pairing
|
||||||
|
@ -3689,6 +3822,21 @@ mpd_find_channel(const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mpd_command_channels(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; mpd_channels[i].handler; i++)
|
||||||
|
{
|
||||||
|
evbuffer_add_printf(evbuf,
|
||||||
|
"channel: %s\n",
|
||||||
|
mpd_channels[i].channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
|
@ -3720,82 +3868,6 @@ mpd_command_sendmessage(struct evbuffer *evbuf, int argc, char **argv, char **er
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|
||||||
{
|
|
||||||
uint32_t shortid;
|
|
||||||
int volume;
|
|
||||||
struct outputs outputs;
|
|
||||||
struct output *output;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
{
|
|
||||||
ret = asprintf(errmsg, "Missing argument for command 'outputvolume'");
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
|
||||||
return ACK_ERROR_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = safe_atou32(argv[1], &shortid);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[1]);
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
|
||||||
return ACK_ERROR_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = safe_atoi32(argv[2], &volume);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
ret = asprintf(errmsg, "Argument doesn't convert to integer: '%s'", argv[2]);
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
|
||||||
return ACK_ERROR_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs.count = 0;
|
|
||||||
outputs.active = 0;
|
|
||||||
outputs.outputs = NULL;
|
|
||||||
|
|
||||||
player_speaker_enumerate(outputs_enum_cb, &outputs);
|
|
||||||
|
|
||||||
output = outputs.outputs;
|
|
||||||
while (output)
|
|
||||||
{
|
|
||||||
if (output->shortid == shortid)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
output = output->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!output)
|
|
||||||
{
|
|
||||||
free_outputs(outputs.outputs);
|
|
||||||
ret = asprintf(errmsg, "No speaker found for short id: %d", shortid);
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = player_volume_setabs_speaker(output->id, volume);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
free_outputs(outputs.outputs);
|
|
||||||
ret = asprintf(errmsg, "Setting volume to %d for speaker with short-id %d failed", volume, shortid);
|
|
||||||
if (ret < 0)
|
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
|
||||||
return ACK_ERROR_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_outputs(outputs.outputs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dummy function to handle commands that are not supported by forked-daapd and should
|
* Dummy function to handle commands that are not supported by forked-daapd and should
|
||||||
* not raise an error.
|
* not raise an error.
|
||||||
|
@ -4327,7 +4399,7 @@ static struct mpd_command mpd_handlers[] =
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.mpdcommand = "channels",
|
.mpdcommand = "channels",
|
||||||
.handler = mpd_command_ignore
|
.handler = mpd_command_channels
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.mpdcommand = "readmessages",
|
.mpdcommand = "readmessages",
|
||||||
|
|
Loading…
Reference in New Issue