Commit 21851c06 authored by Steven Blackburn's avatar Steven Blackburn Committed by Max Kellermann

Add support for streaming to a DLNA client

The Naim Uniti does not appear to support icecast-style streaming of FLAC music but does support the codec from a DLNA server. This change looks for "transferMode.dlna.org: Streaming" in the HTTP request header and responds with something the Uniti (and hopefully other DLNA clients) accepts. The only difference in the DLNA streaming mode is the reponse header and that icecast metadata is disabled. If a client request indicates both modes are supported, the DLNA mode is preferred (as the Uniti says it supports both but then rejects a FLAC ICY stream). Note: This change may be specific to Naim equipment (the only device it was tested on). E.g. the hardcoding of Content-Length which works but is not a logically correct value. The change should be backwards-compatible, so only those clients requesting a DLNA stream will see any difference.
parent 7e219c36
...@@ -14,6 +14,7 @@ ver 0.17 (2011/??/??) ...@@ -14,6 +14,7 @@ ver 0.17 (2011/??/??)
- ffmpeg: support libavformat 0.7 - ffmpeg: support libavformat 0.7
- oggflac: delete this obsolete plugin - oggflac: delete this obsolete plugin
* output: * output:
- httpd: support for streaming to a DLNA client
- osx: allow user to specify other audio devices - osx: allow user to specify other audio devices
- raop: new output plugin - raop: new output plugin
- shout: add possibility to set url - shout: add possibility to set url
......
...@@ -93,6 +93,11 @@ struct httpd_client { ...@@ -93,6 +93,11 @@ struct httpd_client {
*/ */
size_t current_position; size_t current_position;
/**
* If DLNA streaming was an option.
*/
bool dlna_streaming_requested;
/* ICY */ /* ICY */
/** /**
...@@ -234,6 +239,15 @@ httpd_client_handle_line(struct httpd_client *client, const char *line) ...@@ -234,6 +239,15 @@ httpd_client_handle_line(struct httpd_client *client, const char *line)
return true; return true;
} }
if (g_ascii_strncasecmp(line, "transferMode.dlna.org: Streaming", 32) == 0) {
/* Send as dlna */
client->dlna_streaming_requested = true;
/* metadata is not supported by dlna streaming, so disable it */
client->metadata_supported = false;
client->metadata_requested = false;
return true;
}
/* expect more request headers */ /* expect more request headers */
return true; return true;
} }
...@@ -285,16 +299,21 @@ httpd_client_send_response(struct httpd_client *client) ...@@ -285,16 +299,21 @@ httpd_client_send_response(struct httpd_client *client)
assert(client != NULL); assert(client != NULL);
assert(client->state == RESPONSE); assert(client->state == RESPONSE);
if (!client->metadata_requested) { if (client->dlna_streaming_requested) {
g_snprintf(buffer, sizeof(buffer), g_snprintf(buffer, sizeof(buffer),
"HTTP/1.1 200 OK\r\n" "HTTP/1.1 206 OK\r\n"
"Content-Type: %s\r\n" "Content-Type: %s\r\n"
"Content-Length: 10000\r\n"
"Content-RangeX: 0-1000000/1000000\r\n"
"transferMode.dlna.org: Streaming\r\n"
"Accept-Ranges: bytes\r\n"
"Connection: close\r\n" "Connection: close\r\n"
"Pragma: no-cache\r\n" "realTimeInfo.dlna.org: DLNA.ORG_TLAG=*\r\n"
"Cache-Control: no-cache, no-store\r\n" "contentFeatures.dlna.org: DLNA.ORG_OP=01;DLNA.ORG_CI=0\r\n"
"\r\n", "\r\n",
client->httpd->content_type); client->httpd->content_type);
} else {
} else if (client->metadata_requested) {
gchar *metadata_header; gchar *metadata_header;
metadata_header = icy_server_metadata_header( metadata_header = icy_server_metadata_header(
...@@ -307,6 +326,16 @@ httpd_client_send_response(struct httpd_client *client) ...@@ -307,6 +326,16 @@ httpd_client_send_response(struct httpd_client *client)
g_strlcpy(buffer, metadata_header, sizeof(buffer)); g_strlcpy(buffer, metadata_header, sizeof(buffer));
g_free(metadata_header); g_free(metadata_header);
} else { /* revert to a normal HTTP request */
g_snprintf(buffer, sizeof(buffer),
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Connection: close\r\n"
"Pragma: no-cache\r\n"
"Cache-Control: no-cache, no-store\r\n"
"\r\n",
client->httpd->content_type);
} }
status = g_io_channel_write_chars(client->channel, status = g_io_channel_write_chars(client->channel,
...@@ -476,6 +505,7 @@ httpd_client_new(struct httpd_output *httpd, int fd, bool metadata_supported) ...@@ -476,6 +505,7 @@ httpd_client_new(struct httpd_output *httpd, int fd, bool metadata_supported)
client->input = fifo_buffer_new(4096); client->input = fifo_buffer_new(4096);
client->state = REQUEST; client->state = REQUEST;
client->dlna_streaming_requested = false;
client->metadata_supported = metadata_supported; client->metadata_supported = metadata_supported;
client->metadata_requested = false; client->metadata_requested = false;
client->metadata_sent = true; client->metadata_sent = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment