mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-29 08:33:23 -05:00
[chromecast] Volume support and fix double free
This commit is contained in:
parent
153ed98dba
commit
5e239cfbb2
@ -89,7 +89,7 @@ struct cast_session
|
|||||||
char *address;
|
char *address;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
|
||||||
int volume;
|
float volume;
|
||||||
|
|
||||||
// Outgoing request which have the USE_REQUEST_ID flag get a new id, and a
|
// Outgoing request which have the USE_REQUEST_ID flag get a new id, and a
|
||||||
// callback is registered. The callback is called when an incoming message
|
// callback is registered. The callback is called when an incoming message
|
||||||
@ -125,6 +125,7 @@ enum cast_msg_types
|
|||||||
MEDIA_LOAD,
|
MEDIA_LOAD,
|
||||||
MEDIA_STOP,
|
MEDIA_STOP,
|
||||||
MEDIA_LOAD_FAILED,
|
MEDIA_LOAD_FAILED,
|
||||||
|
SET_VOLUME,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cast_msg_basic
|
struct cast_msg_basic
|
||||||
@ -225,6 +226,12 @@ struct cast_msg_basic cast_msg[] =
|
|||||||
.type = MEDIA_LOAD_FAILED,
|
.type = MEDIA_LOAD_FAILED,
|
||||||
.tag = "LOAD_FAILED",
|
.tag = "LOAD_FAILED",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.type = SET_VOLUME,
|
||||||
|
.namespace = NS_RECEIVER,
|
||||||
|
.payload = "{'type':'SET_VOLUME','volume':{'level':%.2f,'muted':0},'requestId':%d}",
|
||||||
|
.flags = USE_REQUEST_ID,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.type = 0,
|
.type = 0,
|
||||||
},
|
},
|
||||||
@ -392,13 +399,15 @@ cast_msg_send(struct cast_session *cs, enum cast_msg_types type, cast_reply_cb r
|
|||||||
cs->callback_register[cs->request_id % CALLBACK_REGISTER_SIZE] = reply_cb;
|
cs->callback_register[cs->request_id % CALLBACK_REGISTER_SIZE] = reply_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special handling of MEDIA_LOAD and MEDIA_STOP for now
|
// Special handling of some message types
|
||||||
if (cast_msg[type].flags & USE_REQUEST_ID_ONLY)
|
if (cast_msg[type].flags & USE_REQUEST_ID_ONLY)
|
||||||
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, cs->request_id);
|
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, cs->request_id);
|
||||||
else if (type == MEDIA_LOAD)
|
else if (type == MEDIA_LOAD)
|
||||||
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, TEST_STREAM_URL, cs->session_id, cs->request_id);
|
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, TEST_STREAM_URL, cs->session_id, cs->request_id);
|
||||||
else if (type == MEDIA_STOP)
|
else if (type == MEDIA_STOP)
|
||||||
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, cs->session_id, cs->request_id);
|
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, cs->session_id, cs->request_id);
|
||||||
|
else if (type == SET_VOLUME)
|
||||||
|
snprintf(msg_buf, sizeof(msg_buf), cast_msg[type].payload, cs->volume, cs->request_id);
|
||||||
else
|
else
|
||||||
snprintf(msg_buf, sizeof(msg_buf), "%s", cast_msg[type].payload);
|
snprintf(msg_buf, sizeof(msg_buf), "%s", cast_msg[type].payload);
|
||||||
|
|
||||||
@ -623,7 +632,7 @@ cast_cb_startup_volume(struct cast_session *cs, struct cast_msg_payload *payload
|
|||||||
static void
|
static void
|
||||||
cast_cb_startup_media(struct cast_session *cs, struct cast_msg_payload *payload)
|
cast_cb_startup_media(struct cast_session *cs, struct cast_msg_payload *payload)
|
||||||
{
|
{
|
||||||
cs->state = OUTPUT_STATE_RECORD;
|
int ret;
|
||||||
|
|
||||||
if (payload->type != MEDIA_STATUS)
|
if (payload->type != MEDIA_STATUS)
|
||||||
{
|
{
|
||||||
@ -634,7 +643,12 @@ cast_cb_startup_media(struct cast_session *cs, struct cast_msg_payload *payload)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Send a volume message with the cb
|
// TODO Send a volume message with the cb
|
||||||
cast_cb_startup_volume(cs, payload);
|
ret = cast_msg_send(cs, SET_VOLUME, cast_cb_startup_volume);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
cast_msg_send(cs, CLOSE, NULL);
|
||||||
|
cast_session_failure(cs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -654,7 +668,6 @@ cast_cb_startup_launch(struct cast_session *cs, struct cast_msg_payload *payload
|
|||||||
DPRINTF(E_LOG, L_CAST, "Ooops, memleaking...\n");
|
DPRINTF(E_LOG, L_CAST, "Ooops, memleaking...\n");
|
||||||
|
|
||||||
cs->transport_id = strdup(payload->transport_id);
|
cs->transport_id = strdup(payload->transport_id);
|
||||||
cs->state = OUTPUT_STATE_ANNOUNCE;
|
|
||||||
|
|
||||||
ret = cast_msg_send(cs, MEDIA_CONNECT, NULL);
|
ret = cast_msg_send(cs, MEDIA_CONNECT, NULL);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@ -684,7 +697,6 @@ cast_cb_startup_connect(struct cast_session *cs, struct cast_msg_payload *payloa
|
|||||||
DPRINTF(E_LOG, L_CAST, "Ooops, memleaking...\n");
|
DPRINTF(E_LOG, L_CAST, "Ooops, memleaking...\n");
|
||||||
|
|
||||||
cs->session_id = strdup(payload->session_id);
|
cs->session_id = strdup(payload->session_id);
|
||||||
cs->state = OUTPUT_STATE_OPTIONS;
|
|
||||||
|
|
||||||
ret = cast_msg_send(cs, LAUNCH, cast_cb_startup_launch);
|
ret = cast_msg_send(cs, LAUNCH, cast_cb_startup_launch);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -717,6 +729,18 @@ cast_cb_load(struct cast_session *cs, struct cast_msg_payload *payload)
|
|||||||
cs->status_cb(cs->device, cs->output_session, cs->state);
|
cs->status_cb(cs->device, cs->output_session, cs->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cast_cb_volume(struct cast_session *cs, struct cast_msg_payload *payload)
|
||||||
|
{
|
||||||
|
output_status_cb status_cb;
|
||||||
|
|
||||||
|
status_cb = cs->status_cb;
|
||||||
|
cs->status_cb = NULL;
|
||||||
|
status_cb(cs->device, cs->output_session, cs->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cast_listen_cb(int fd, short what, void *arg)
|
cast_listen_cb(int fd, short what, void *arg)
|
||||||
{
|
{
|
||||||
@ -724,13 +748,15 @@ cast_listen_cb(int fd, short what, void *arg)
|
|||||||
uint8_t buffer[MAX_BUF + 1]; // Not sure about the +1, but is copied from gnutls examples
|
uint8_t buffer[MAX_BUF + 1]; // Not sure about the +1, but is copied from gnutls examples
|
||||||
uint32_t be;
|
uint32_t be;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
int processed;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cs = (struct cast_session *)arg;
|
cs = (struct cast_session *)arg;
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_CAST, "New data from %s\n", cs->devname);
|
DPRINTF(E_DBG, L_CAST, "New data from %s\n", cs->devname);
|
||||||
|
|
||||||
while ((ret = gnutls_record_recv(cs->tls_session, buffer, MAX_BUF)) > 0)
|
processed = 0;
|
||||||
|
while ((ret = gnutls_record_recv(cs->tls_session, buffer + processed, MAX_BUF - processed)) > 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_CAST, "Received %d bytes\n", ret);
|
DPRINTF(E_DBG, L_CAST, "Received %d bytes\n", ret);
|
||||||
|
|
||||||
@ -742,7 +768,14 @@ cast_listen_cb(int fd, short what, void *arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cast_msg_process(cs, buffer, ret);
|
processed += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed >= MAX_BUF)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_CAST, "Receive buffer exhausted!\n");
|
||||||
|
cast_session_failure(cs);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,7 +783,11 @@ cast_listen_cb(int fd, short what, void *arg)
|
|||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_CAST, "Session error: %s\n", gnutls_strerror(ret));
|
DPRINTF(E_LOG, L_CAST, "Session error: %s\n", gnutls_strerror(ret));
|
||||||
cast_session_failure(cs);
|
cast_session_failure(cs);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (processed)
|
||||||
|
cast_msg_process(cs, buffer, processed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cast_session *
|
static struct cast_session *
|
||||||
@ -841,7 +878,7 @@ cast_session_make(struct output_device *device, int family, output_status_cb cb)
|
|||||||
cs->devname = strdup(device->name);
|
cs->devname = strdup(device->name);
|
||||||
cs->address = strdup(address);
|
cs->address = strdup(address);
|
||||||
|
|
||||||
cs->volume = device->volume;
|
cs->volume = 0.01 * device->volume;
|
||||||
|
|
||||||
cs->next = sessions;
|
cs->next = sessions;
|
||||||
sessions = cs;
|
sessions = cs;
|
||||||
@ -996,6 +1033,34 @@ cast_device_stop(struct output_session *session)
|
|||||||
cast_msg_send(cs, CLOSE, cast_cb_close);
|
cast_msg_send(cs, CLOSE, cast_cb_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cast_volume_set(struct output_device *device, output_status_cb cb)
|
||||||
|
{
|
||||||
|
struct cast_session *cs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!device->session || !device->session->session)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cs = device->session->session;
|
||||||
|
|
||||||
|
if (!(cs->state & OUTPUT_STATE_F_CONNECTED))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cs->volume = 0.01 * device->volume;
|
||||||
|
|
||||||
|
ret = cast_msg_send(cs, SET_VOLUME, cast_cb_volume);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
cast_session_failure(cs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs->status_cb = cb;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cast_playback_start(uint64_t next_pkt, struct timespec *ts)
|
cast_playback_start(uint64_t next_pkt, struct timespec *ts)
|
||||||
{
|
{
|
||||||
@ -1087,8 +1152,8 @@ struct output_definition output_cast =
|
|||||||
.device_start = cast_device_start,
|
.device_start = cast_device_start,
|
||||||
.device_stop = cast_device_stop,
|
.device_stop = cast_device_stop,
|
||||||
/* .device_probe = cast_device_probe,
|
/* .device_probe = cast_device_probe,
|
||||||
.device_free_extra = cast_device_free_extra,
|
.device_free_extra = cast_device_free_extra,*/
|
||||||
.device_volume_set = cast_set_volume_one,*/
|
.device_volume_set = cast_volume_set,
|
||||||
.playback_start = cast_playback_start,
|
.playback_start = cast_playback_start,
|
||||||
/* .playback_stop = cast_playback_stop,
|
/* .playback_stop = cast_playback_stop,
|
||||||
.write = cast_write,
|
.write = cast_write,
|
||||||
|
Loading…
Reference in New Issue
Block a user