mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-29 00:23:23 -05:00
[raop] Use GET_PARAMETER of volume to keep connection alive and get speaker volume
This commit is contained in:
parent
fe05f80822
commit
d9a67b6dce
@ -327,7 +327,7 @@ static struct event *flush_timer;
|
|||||||
|
|
||||||
/* Keep-alive timer - hack for ATV's with tvOS 10 */
|
/* Keep-alive timer - hack for ATV's with tvOS 10 */
|
||||||
static struct event *keep_alive_timer;
|
static struct event *keep_alive_timer;
|
||||||
static struct timeval keep_alive_tv = { 60, 0 };
|
static struct timeval keep_alive_tv = { 30, 0 };
|
||||||
|
|
||||||
/* Sessions */
|
/* Sessions */
|
||||||
static struct raop_session *sessions;
|
static struct raop_session *sessions;
|
||||||
@ -1443,6 +1443,56 @@ raop_send_req_set_parameter(struct raop_session *rs, struct evbuffer *evbuf, cha
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
raop_send_req_get_parameter(struct raop_session *rs, struct evbuffer *evbuf, char *ctype, char *rtpinfo, evrtsp_req_cb cb)
|
||||||
|
{
|
||||||
|
struct evrtsp_request *req;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
req = evrtsp_request_new(cb, rs);
|
||||||
|
if (!req)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Could not create RTSP request for GET_PARAMETER\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = evbuffer_add_buffer(req->output_buffer, evbuf);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Out of memory for GET_PARAMETER payload\n");
|
||||||
|
|
||||||
|
evrtsp_request_free(req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = raop_add_headers(rs, req, EVRTSP_REQ_GET_PARAMETER);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
evrtsp_request_free(req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
evrtsp_add_header(req->output_headers, "Content-Type", ctype);
|
||||||
|
|
||||||
|
if (rtpinfo)
|
||||||
|
evrtsp_add_header(req->output_headers, "RTP-Info", rtpinfo);
|
||||||
|
|
||||||
|
ret = evrtsp_make_request(rs->ctrl, req, EVRTSP_REQ_GET_PARAMETER, rs->session_url);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Could not make GET_PARAMETER request\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs->reqs_in_flight++;
|
||||||
|
|
||||||
|
evrtsp_connection_set_closecb(rs->ctrl, NULL, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
raop_send_req_record(struct raop_session *rs, evrtsp_req_cb cb)
|
raop_send_req_record(struct raop_session *rs, evrtsp_req_cb cb)
|
||||||
{
|
{
|
||||||
@ -2376,8 +2426,25 @@ raop_metadata_send(void *metadata, uint64_t rtptime, uint64_t offset, int startu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Volume handling */
|
/* Volume handling */
|
||||||
|
static int
|
||||||
|
raop_volume_to_pct(float raop_volume)
|
||||||
|
{
|
||||||
|
int volume;
|
||||||
|
|
||||||
|
/* RAOP volume
|
||||||
|
* -144.0 is off
|
||||||
|
* -30.0 - 0 maps to 0 - 100
|
||||||
|
*/
|
||||||
|
if (raop_volume > -30.0 && raop_volume <= 0.0)
|
||||||
|
volume = (int)(100.0 * raop_volume / 30.0 + 100.0);
|
||||||
|
else
|
||||||
|
volume = 0;
|
||||||
|
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
static float
|
static float
|
||||||
raop_volume_convert(int volume, char *name)
|
raop_volume_from_pct(int volume, char *name)
|
||||||
{
|
{
|
||||||
float raop_volume;
|
float raop_volume;
|
||||||
cfg_t *airplay;
|
cfg_t *airplay;
|
||||||
@ -2391,7 +2458,7 @@ raop_volume_convert(int volume, char *name)
|
|||||||
|
|
||||||
if ((max_volume < 1) || (max_volume > RAOP_CONFIG_MAX_VOLUME))
|
if ((max_volume < 1) || (max_volume > RAOP_CONFIG_MAX_VOLUME))
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_RAOP, "Config has bad max_volume (%d) for device %s, using default instead\n", max_volume, name);
|
DPRINTF(E_LOG, L_RAOP, "Config has bad max_volume (%d) for device '%s', using default instead\n", max_volume, name);
|
||||||
|
|
||||||
max_volume = RAOP_CONFIG_MAX_VOLUME;
|
max_volume = RAOP_CONFIG_MAX_VOLUME;
|
||||||
}
|
}
|
||||||
@ -2423,7 +2490,7 @@ raop_set_volume_internal(struct raop_session *rs, int volume, evrtsp_req_cb cb)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
raop_volume = raop_volume_convert(volume, rs->devname);
|
raop_volume = raop_volume_from_pct(volume, rs->devname);
|
||||||
|
|
||||||
/* Don't let locales get in the way here */
|
/* Don't let locales get in the way here */
|
||||||
/* We use -%d and -(int)raop_volume so -0.3 won't become 0.3 */
|
/* We use -%d and -(int)raop_volume so -0.3 won't become 0.3 */
|
||||||
@ -2447,6 +2514,36 @@ raop_set_volume_internal(struct raop_session *rs, int volume, evrtsp_req_cb cb)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
raop_get_volume_internal(struct raop_session *rs, evrtsp_req_cb cb)
|
||||||
|
{
|
||||||
|
struct evbuffer *evbuf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
evbuf = evbuffer_new();
|
||||||
|
if (!evbuf)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Could not allocate evbuffer for volume payload\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = evbuffer_add_printf(evbuf, "volume\n");
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Out of memory for GET_PARAMETER payload (volume)\n");
|
||||||
|
evbuffer_free(evbuf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = raop_send_req_get_parameter(rs, evbuf, "text/parameters", NULL, cb);
|
||||||
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Could not send GET_PARAMETER request for volume\n");
|
||||||
|
|
||||||
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
raop_cb_set_volume(struct evrtsp_request *req, void *arg)
|
raop_cb_set_volume(struct evrtsp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
@ -2549,25 +2646,45 @@ static void
|
|||||||
raop_cb_keep_alive(struct evrtsp_request *req, void *arg)
|
raop_cb_keep_alive(struct evrtsp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
struct raop_session *rs = arg;
|
struct raop_session *rs = arg;
|
||||||
|
char *body;
|
||||||
|
float raop_volume;
|
||||||
|
|
||||||
rs->reqs_in_flight--;
|
rs->reqs_in_flight--;
|
||||||
|
|
||||||
if (!req)
|
if (!req)
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (req->response_code != RTSP_OK)
|
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_RAOP, "SET_PARAMETER request failed for keep alive: %d %s\n", req->response_code, req->response_code_line);
|
DPRINTF(E_LOG, L_RAOP, "No reply from '%s' to our keep alive request, hanging up\n", rs->devname);
|
||||||
goto error;
|
raop_session_failure(rs);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rs->reqs_in_flight)
|
if (!rs->reqs_in_flight)
|
||||||
evrtsp_connection_set_closecb(rs->ctrl, raop_rtsp_close_cb, rs);
|
evrtsp_connection_set_closecb(rs->ctrl, raop_rtsp_close_cb, rs);
|
||||||
|
|
||||||
|
if (req->response_code != RTSP_OK)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Keep alive GET_PARAMETER request to '%s' failed: %d %s\n", rs->devname, req->response_code, req->response_code_line);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
evbuffer_add(req->input_buffer, "", 1); // NULL-terminate
|
||||||
raop_session_failure(rs);
|
|
||||||
|
body = (char *)evbuffer_pullup(req->input_buffer, -1);
|
||||||
|
if (!body || strncmp(body, "volume: ", strlen("volume: ")) != 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_RAOP, "Invalid response from '%s' to keep alive request: '%s'\n", rs->devname, body);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
raop_volume = atof(strchr(body, ':') + 2);
|
||||||
|
|
||||||
|
rs->volume = raop_volume_to_pct(raop_volume);
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_RAOP, "GET_PARAMETER request to '%s' returned volume %f (%d)\n", rs->devname, raop_volume, rs->volume);
|
||||||
|
|
||||||
|
evtimer_add(keep_alive_timer, &keep_alive_tv);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2632,16 +2749,14 @@ raop_keep_alive_timer_cb(int fd, short what, void *arg)
|
|||||||
|
|
||||||
for (rs = sessions; rs; rs = rs->next)
|
for (rs = sessions; rs; rs = rs->next)
|
||||||
{
|
{
|
||||||
if (!rs->keep_alive)
|
// if (!rs->keep_alive)
|
||||||
continue;
|
// continue;
|
||||||
|
|
||||||
if (!(rs->state & RAOP_STATE_F_CONNECTED))
|
if (!(rs->state & RAOP_STATE_F_CONNECTED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
raop_set_volume_internal(rs, rs->volume, raop_cb_keep_alive);
|
raop_get_volume_internal(rs, raop_cb_keep_alive);
|
||||||
}
|
}
|
||||||
|
|
||||||
evtimer_add(keep_alive_timer, &keep_alive_tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
Reference in New Issue
Block a user