[httpd] Check speaker settings to determine DAAP/RSP stream format
This commit is contained in:
parent
62b42ce354
commit
ff2d0b4ab1
31
src/httpd.c
31
src/httpd.c
|
@ -1069,7 +1069,7 @@ httpd_stream_file(struct httpd_request *hreq, int id)
|
|||
}
|
||||
|
||||
param = httpd_header_find(hreq->in_headers, "Accept-Codecs");
|
||||
profile = transcode_needed(hreq->user_agent, param, mfi->codectype);
|
||||
profile = httpd_xcode_profile_get(hreq->user_agent, hreq->peer_address, param, mfi->codectype);
|
||||
if (profile == XCODE_UNKNOWN)
|
||||
{
|
||||
DPRINTF(E_LOG, L_HTTPD, "Could not serve '%s' to client, unable to determine output format\n", mfi->path);
|
||||
|
@ -1188,6 +1188,35 @@ httpd_stream_file(struct httpd_request *hreq, int id)
|
|||
free_mfi(mfi, 0);
|
||||
}
|
||||
|
||||
// Returns enum transcode_profile, but is just declared with int so we don't
|
||||
// need to include transcode.h in httpd_internal.h
|
||||
int
|
||||
httpd_xcode_profile_get(const char *user_agent, const char *address, const char *accept_codecs, const char *codec)
|
||||
{
|
||||
enum transcode_profile profile;
|
||||
struct player_speaker_info spk;
|
||||
int ret;
|
||||
|
||||
profile = transcode_needed(user_agent, accept_codecs, codec);
|
||||
if (profile == XCODE_NONE)
|
||||
return profile;
|
||||
|
||||
// A Roku Soundbridge may also be RCP device/speaker for which the user may
|
||||
// have set a prefered streaming format
|
||||
ret = player_speaker_get_byaddress(&spk, address);
|
||||
if (ret < 0)
|
||||
return profile;
|
||||
|
||||
if (spk.format == MEDIA_FORMAT_WAV)
|
||||
return XCODE_WAV;
|
||||
if (spk.format == MEDIA_FORMAT_MP3)
|
||||
return XCODE_MP3;
|
||||
if (spk.format == MEDIA_FORMAT_ALAC)
|
||||
return XCODE_MP4_ALAC;
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
struct evbuffer *
|
||||
httpd_gzip_deflate(struct evbuffer *in)
|
||||
{
|
||||
|
|
|
@ -1146,7 +1146,7 @@ daap_reply_songlist_generic(struct httpd_request *hreq, int playlist)
|
|||
const struct dmap_field **meta = NULL;
|
||||
struct sort_ctx *sctx;
|
||||
const char *param;
|
||||
const char *client_codecs;
|
||||
const char *accept_codecs;
|
||||
const char *tag;
|
||||
size_t len;
|
||||
enum transcode_profile profile;
|
||||
|
@ -1216,10 +1216,10 @@ daap_reply_songlist_generic(struct httpd_request *hreq, int playlist)
|
|||
goto error;
|
||||
}
|
||||
|
||||
client_codecs = NULL;
|
||||
accept_codecs = NULL;
|
||||
if (!s->is_remote && hreq->in_headers)
|
||||
{
|
||||
client_codecs = httpd_header_find(hreq->in_headers, "Accept-Codecs");
|
||||
accept_codecs = httpd_header_find(hreq->in_headers, "Accept-Codecs");
|
||||
}
|
||||
|
||||
nsongs = 0;
|
||||
|
@ -1229,7 +1229,7 @@ daap_reply_songlist_generic(struct httpd_request *hreq, int playlist)
|
|||
|
||||
// Not sure if the is_remote path is really needed. Note that if you
|
||||
// change the below you might need to do the same in rsp_reply_playlist()
|
||||
profile = s->is_remote ? XCODE_WAV : transcode_needed(hreq->user_agent, client_codecs, dbmfi.codectype);
|
||||
profile = s->is_remote ? XCODE_WAV : httpd_xcode_profile_get(hreq->user_agent, hreq->peer_address, accept_codecs, dbmfi.codectype);
|
||||
if (profile == XCODE_UNKNOWN)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Cannot transcode '%s', codec type is unknown\n", dbmfi.fname);
|
||||
|
|
|
@ -206,6 +206,9 @@ struct httpd_request {
|
|||
void
|
||||
httpd_stream_file(struct httpd_request *hreq, int id);
|
||||
|
||||
int
|
||||
httpd_xcode_profile_get(const char *user_agent, const char *address, const char *accept_codecs, const char *codec);
|
||||
|
||||
void
|
||||
httpd_request_handler_set(struct httpd_request *hreq);
|
||||
|
||||
|
|
|
@ -525,6 +525,7 @@ httpd_backend_output_buffer_get(httpd_backend *backend)
|
|||
int
|
||||
httpd_backend_peer_get(const char **addr, uint16_t *port, httpd_backend *backend, httpd_backend_data *backend_data)
|
||||
{
|
||||
#define IPV4_MAPPED_IPV6_PREFIX "::ffff:"
|
||||
httpd_connection *conn = evhttp_request_get_connection(backend);
|
||||
if (!conn)
|
||||
return -1;
|
||||
|
@ -534,6 +535,11 @@ httpd_backend_peer_get(const char **addr, uint16_t *port, httpd_backend *backend
|
|||
#else
|
||||
evhttp_connection_get_peer(conn, (char **)addr, port);
|
||||
#endif
|
||||
|
||||
// Just use the pure ipv4 address if it's mapped
|
||||
if (strncmp(*addr, IPV4_MAPPED_IPV6_PREFIX, strlen(IPV4_MAPPED_IPV6_PREFIX)) == 0)
|
||||
*addr += strlen(IPV4_MAPPED_IPV6_PREFIX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -415,7 +415,7 @@ rsp_reply_db(struct httpd_request *hreq)
|
|||
}
|
||||
|
||||
static int
|
||||
item_add(xml_node *parent, struct query_params *qp, const char *user_agent, const char *client_codecs, int mode)
|
||||
item_add(xml_node *parent, struct query_params *qp, const char *user_agent, const char *address, const char *accept_codecs, int mode)
|
||||
{
|
||||
struct media_quality quality = { 0 };
|
||||
struct db_media_file_info dbmfi;
|
||||
|
@ -432,7 +432,7 @@ item_add(xml_node *parent, struct query_params *qp, const char *user_agent, cons
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
profile = transcode_needed(user_agent, client_codecs, dbmfi.codectype);
|
||||
profile = httpd_xcode_profile_get(user_agent, address, accept_codecs, dbmfi.codectype);
|
||||
if (profile == XCODE_UNKNOWN)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Cannot transcode '%s', codec type is unknown\n", dbmfi.fname);
|
||||
|
@ -484,7 +484,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
|
|||
{
|
||||
struct query_params qp;
|
||||
const char *param;
|
||||
const char *client_codecs;
|
||||
const char *accept_codecs;
|
||||
xml_node *response;
|
||||
xml_node *items;
|
||||
int mode;
|
||||
|
@ -493,7 +493,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
|
|||
|
||||
memset(&qp, 0, sizeof(struct query_params));
|
||||
|
||||
client_codecs = httpd_header_find(hreq->in_headers, "Accept-Codecs");
|
||||
accept_codecs = httpd_header_find(hreq->in_headers, "Accept-Codecs");
|
||||
|
||||
ret = safe_atoi32(hreq->path_parts[2], &qp.id);
|
||||
if (ret < 0)
|
||||
|
@ -555,7 +555,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
|
|||
items = xml_new_node(response, "items", NULL);
|
||||
do
|
||||
{
|
||||
ret = item_add(items, &qp, hreq->user_agent, client_codecs, mode);
|
||||
ret = item_add(items, &qp, hreq->user_agent, hreq->peer_address, accept_codecs, mode);
|
||||
}
|
||||
while (ret == 0);
|
||||
|
||||
|
|
39
src/player.c
39
src/player.c
|
@ -164,6 +164,7 @@ struct speaker_get_param
|
|||
{
|
||||
uint64_t spk_id;
|
||||
uint32_t active_remote;
|
||||
const char *address;
|
||||
struct player_speaker_info *spk_info;
|
||||
};
|
||||
|
||||
|
@ -2606,6 +2607,31 @@ speaker_get_byactiveremote(void *arg, int *retval)
|
|||
return COMMAND_END;
|
||||
}
|
||||
|
||||
static enum command_state
|
||||
speaker_get_byaddress(void *arg, int *retval)
|
||||
{
|
||||
struct speaker_get_param *spk_param = arg;
|
||||
struct output_device *device;
|
||||
bool match_v4;
|
||||
bool match_v6;
|
||||
|
||||
for (device = outputs_list(); device; device = device->next)
|
||||
{
|
||||
match_v4 = device->v4_address && (strcmp(spk_param->address, device->v4_address) == 0);
|
||||
match_v6 = device->v6_address && (strcmp(spk_param->address, device->v6_address) == 0);
|
||||
if (match_v4 || match_v6)
|
||||
{
|
||||
device_to_speaker_info(spk_param->spk_info, device);
|
||||
*retval = 0;
|
||||
return COMMAND_END;
|
||||
}
|
||||
}
|
||||
|
||||
// No output device found with matching id
|
||||
*retval = -1;
|
||||
return COMMAND_END;
|
||||
}
|
||||
|
||||
static enum command_state
|
||||
speaker_set(void *arg, int *retval)
|
||||
{
|
||||
|
@ -3444,6 +3470,19 @@ player_speaker_get_byactiveremote(struct player_speaker_info *spk, uint32_t acti
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
player_speaker_get_byaddress(struct player_speaker_info *spk, const char *address)
|
||||
{
|
||||
struct speaker_get_param param;
|
||||
int ret;
|
||||
|
||||
param.address = address;
|
||||
param.spk_info = spk;
|
||||
|
||||
ret = commands_exec_sync(cmdbase, speaker_get_byaddress, NULL, ¶m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
player_speaker_enable(uint64_t id)
|
||||
{
|
||||
|
|
|
@ -103,6 +103,9 @@ player_speaker_get_byid(struct player_speaker_info *spk, uint64_t id);
|
|||
int
|
||||
player_speaker_get_byactiveremote(struct player_speaker_info *spk, uint32_t active_remote);
|
||||
|
||||
int
|
||||
player_speaker_get_byaddress(struct player_speaker_info *spk, const char *address);
|
||||
|
||||
int
|
||||
player_speaker_enable(uint64_t id);
|
||||
|
||||
|
|
|
@ -2097,7 +2097,7 @@ transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality
|
|||
}
|
||||
|
||||
enum transcode_profile
|
||||
transcode_needed(const char *user_agent, const char *client_codecs, char *file_codectype)
|
||||
transcode_needed(const char *user_agent, const char *client_codecs, const char *file_codectype)
|
||||
{
|
||||
const char *codectype;
|
||||
const char *prefer_format;
|
||||
|
|
|
@ -112,7 +112,7 @@ struct decode_ctx *
|
|||
transcode_decode_setup_raw(enum transcode_profile profile, struct media_quality *quality);
|
||||
|
||||
enum transcode_profile
|
||||
transcode_needed(const char *user_agent, const char *client_codecs, char *file_codectype);
|
||||
transcode_needed(const char *user_agent, const char *client_codecs, const char *file_codectype);
|
||||
|
||||
// Cleaning up
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue