diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index a5b08fbb..b4ee691b 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -2294,7 +2294,7 @@ dacp_reply_setproperty(struct evhttp_request *req, struct evbuffer *evbuf, char } static void -speaker_enum_cb(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg) +speaker_enum_cb(uint64_t id, const char *name, int relvol, int absvol, struct spk_flags flags, void *arg) { struct evbuffer *evbuf; int len; diff --git a/src/mpd.c b/src/mpd.c index 20485344..5da1e202 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -3218,7 +3218,7 @@ mpd_command_rescan(struct evbuffer *evbuf, int argc, char **argv, char **errmsg) * Adds a new struct output to the given struct outputs in *arg for the given speaker (id, name, etc.). */ static void -outputs_enum_cb(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg) +outputs_enum_cb(uint64_t id, const char *name, int relvol, int absvol, struct spk_flags flags, void *arg) { struct outputs *outputs; struct output *output; @@ -3528,21 +3528,24 @@ mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **e * outputid: 0 * outputname: Computer * outputenabled: 1 + * outputvolume: 50 */ static void -speaker_enum_cb(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg) +speaker_enum_cb(uint64_t id, const char *name, int relvol, int absvol, struct spk_flags flags, void *arg) { struct evbuffer *evbuf; evbuf = (struct evbuffer *)arg; evbuffer_add_printf(evbuf, - "outputid: %d\n" - "outputname: %s\n" - "outputenabled: %d\n", - (unsigned short) id, - name, - flags.selected); + "outputid: %d\n" + "outputname: %s\n" + "outputenabled: %d\n" + "outputvolume: %d\n", + (unsigned short) id, + name, + flags.selected, + absvol); } /* @@ -3557,6 +3560,82 @@ mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg 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 * not raise an error. @@ -4099,6 +4178,14 @@ static struct mpd_command mpd_handlers[] = .handler = mpd_command_ignore }, + /* + * Forked-daapd commands (not supported by mpd) + */ + { + .mpdcommand = "outputvolume", + .handler = mpd_command_outputvolume + }, + /* * NULL command to terminate loop */ diff --git a/src/player.c b/src/player.c index d2e85a51..d6423b9e 100644 --- a/src/player.c +++ b/src/player.c @@ -2724,7 +2724,7 @@ speaker_enumerate(void *arg, int *retval) flags.has_password = device->has_password; flags.has_video = device->has_video; - spk_enum->cb(device->id, device->name, device->relvol, flags, spk_enum->arg); + spk_enum->cb(device->id, device->name, device->relvol, device->volume, flags, spk_enum->arg); #ifdef DEBUG_RELVOL DPRINTF(E_DBG, L_PLAYER, "*** %s: abs %d rel %d\n", device->name, device->volume, device->relvol); diff --git a/src/player.h b/src/player.h index c69a69fa..d0b4040b 100644 --- a/src/player.h +++ b/src/player.h @@ -69,7 +69,7 @@ struct player_status { int next_pos_pl; }; -typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg); +typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, int absvol, struct spk_flags flags, void *arg); struct player_history {