[jsonapi] Support changing volume by the given step (increase/decrease

volume)
This commit is contained in:
chme 2019-01-20 13:13:01 +01:00
parent db7b9c689b
commit 343c583229

View File

@ -30,6 +30,7 @@
# include <config.h> # include <config.h>
#endif #endif
#include <limits.h>
#include <regex.h> #include <regex.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -1066,6 +1067,7 @@ struct outputs_param
{ {
json_object *output; json_object *output;
uint64_t output_id; uint64_t output_id;
int output_volume;
}; };
static json_object * static json_object *
@ -1101,25 +1103,15 @@ speaker_enum_cb(struct spk_info *spk, void *arg)
json_object_array_add(outputs, output); json_object_array_add(outputs, output);
} }
static void
speaker_get_cb(struct spk_info *spk, void *arg)
{
struct outputs_param *outputs_param = arg;
if (outputs_param->output_id == spk->id)
{
outputs_param->output = speaker_to_json(spk);
}
}
/* /*
* GET /api/outputs/[output_id] * GET /api/outputs/[output_id]
*/ */
static int static int
jsonapi_reply_outputs_get_byid(struct httpd_request *hreq) jsonapi_reply_outputs_get_byid(struct httpd_request *hreq)
{ {
struct outputs_param outputs_param; struct spk_info speaker_info;
uint64_t output_id; uint64_t output_id;
json_object *jreply;
int ret; int ret;
ret = safe_atou64(hreq->uri_parsed->path_parts[2], &output_id); ret = safe_atou64(hreq->uri_parsed->path_parts[2], &output_id);
@ -1130,21 +1122,19 @@ jsonapi_reply_outputs_get_byid(struct httpd_request *hreq)
return HTTP_BADREQUEST; return HTTP_BADREQUEST;
} }
outputs_param.output_id = output_id; ret = player_speaker_get_byid(output_id, &speaker_info);
outputs_param.output = NULL;
player_speaker_enumerate(speaker_get_cb, &outputs_param); if (ret < 0)
if (!outputs_param.output)
{ {
DPRINTF(E_LOG, L_WEB, "No output found for '%s'\n", hreq->uri_parsed->path); DPRINTF(E_LOG, L_WEB, "No output found for '%s'\n", hreq->uri_parsed->path);
return HTTP_BADREQUEST; return HTTP_BADREQUEST;
} }
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(outputs_param.output))); jreply = speaker_to_json(&speaker_info);
CHECK_ERRNO(L_WEB, evbuffer_add_printf(hreq->reply, "%s", json_object_to_json_string(jreply)));
jparse_free(outputs_param.output); jparse_free(jreply);
return HTTP_OK; return HTTP_OK;
} }
@ -2202,37 +2192,114 @@ jsonapi_reply_player_consume(struct httpd_request *hreq)
return HTTP_NOCONTENT; return HTTP_NOCONTENT;
} }
static int
volume_set(int volume, int step)
{
int new_volume;
struct player_status status;
int ret;
new_volume = volume;
if (step != 0)
{
// Calculate new volume from given step value
player_get_status(&status);
new_volume = status.volume + step;
}
// Make sure we are setting a correct value
new_volume = new_volume > 100 ? 100 : new_volume;
new_volume = new_volume < 0 ? 0 : new_volume;
ret = player_volume_set(new_volume);
return ret;
}
static int
output_volume_set(int volume, int step, uint64_t output_id)
{
int new_volume;
struct spk_info speaker_info;
int ret;
new_volume = volume;
if (step != 0)
{
// Calculate new output volume from the given step value
ret = player_speaker_get_byid(output_id, &speaker_info);
if (ret < 0)
{
DPRINTF(E_LOG, L_WEB, "No output found for the given output id .\n");
return -1;
}
new_volume = speaker_info.absvol + step;
}
// Make sure we are setting a correct value
new_volume = new_volume > 100 ? 100 : new_volume;
new_volume = new_volume < 0 ? 0 : new_volume;
ret = player_volume_setabs_speaker(output_id, new_volume);
return ret;
}
static int static int
jsonapi_reply_player_volume(struct httpd_request *hreq) jsonapi_reply_player_volume(struct httpd_request *hreq)
{ {
const char *param_volume;
const char *param_step;
const char *param; const char *param;
uint64_t output_id; uint64_t output_id;
int volume; int volume;
int step;
int ret; int ret;
param = evhttp_find_header(hreq->query, "volume"); volume = 0;
if (!param) step = 0;
return HTTP_BADREQUEST;
ret = safe_atoi32(param, &volume); // Parse and validate parameters
if (ret < 0) param_volume = evhttp_find_header(hreq->query, "volume");
return HTTP_BADREQUEST; if (param_volume)
{
ret = safe_atoi32(param_volume, &volume);
if (ret < 0)
return HTTP_BADREQUEST;
}
if (volume < 0 || volume > 100) param_step = evhttp_find_header(hreq->query, "step");
return HTTP_BADREQUEST; if (param_step)
{
ret = safe_atoi32(param_step, &step);
if (ret < 0)
return HTTP_BADREQUEST;
}
if ((!param_volume && !param_step)
|| (param_volume && param_step))
{
DPRINTF(E_LOG, L_WEB, "Invalid parameters for player/volume request. Either 'volume' or 'step' parameter required.\n");
return HTTP_BADREQUEST;
}
param = evhttp_find_header(hreq->query, "output_id"); param = evhttp_find_header(hreq->query, "output_id");
if (param) if (param)
{ {
// Update volume for individual output
ret = safe_atou64(param, &output_id); ret = safe_atou64(param, &output_id);
if (ret < 0) if (ret < 0)
return HTTP_BADREQUEST; {
DPRINTF(E_LOG, L_WEB, "Invalid value for parameter 'output_id'. Output id must be an integer (output_id='%s').\n", param);
ret = player_volume_setabs_speaker(output_id, volume); return HTTP_BADREQUEST;
}
ret = output_volume_set(volume, step, output_id);
} }
else else
{ {
ret = player_volume_set(volume); // Update master volume
ret = volume_set(volume, step);
} }
if (ret < 0) if (ret < 0)