There are two versions in the RAOP protocol; one uses TCP and the other uses UDP. Current raop implementation only supports TCP version. This patch recognizes the transport protocol type announced from the server side. It also introduces a flag representing the protocol type. Protocol parameters are based on Matrin Blanchard's implementation. --- src/modules/raop/module-raop-sink.c | 26 ++++++++++++++++++++++++-- src/modules/raop/raop_client.c | 6 +++++- src/modules/raop/raop_client.h | 7 ++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c index 96c6a82..d94b0e1 100644 --- a/src/modules/raop/module-raop-sink.c +++ b/src/modules/raop/module-raop-sink.c @@ -68,6 +68,9 @@ PA_MODULE_USAGE( "sink_name=<name for the sink> " "sink_properties=<properties for the sink> " "server=<address> " + "protocol=<transport protocol> " + "encryption=<encryption type> " + "codec=<audio codec> " "format=<sample format> " "rate=<sample rate> " "channels=<number of channels>"); @@ -84,6 +87,8 @@ struct userdata { pa_rtpoll_item *rtpoll_item; pa_thread *thread; + pa_raop_protocol_t protocol; + pa_memchunk raw_memchunk; pa_memchunk encoded_memchunk; @@ -115,6 +120,9 @@ static const char* const valid_modargs[] = { "sink_name", "sink_properties", "server", + "protocol", + "encryption", + "codec", "format", "rate", "channels", @@ -506,7 +514,7 @@ int pa__init(pa_module *m) { struct userdata *u = NULL; pa_sample_spec ss; pa_modargs *ma = NULL; - const char *server; + const char *server, *protocol; pa_sink_new_data data; pa_assert(m); @@ -569,6 +577,20 @@ int pa__init(pa_module *m) { goto fail; } + protocol = pa_modargs_get_value(ma, "protocol", NULL); + if (protocol == NULL || pa_streq(protocol, "TCP")) { + /* Assume TCP by default */ + u->protocol = RAOP_TCP; + } + else if (pa_streq(protocol, "UDP")) { + u->protocol = RAOP_UDP; + pa_log("UDP is not supported in this module version."); + goto fail; + } else { + pa_log("Unsupported protocol argument given: %s", protocol); + goto fail; + } + pa_sink_new_data_init(&data); data.driver = __FILE__; data.module = m; @@ -601,7 +623,7 @@ int pa__init(pa_module *m) { pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); - if (!(u->raop = pa_raop_client_new(u->core, server))) { + if (!(u->raop = pa_raop_client_new(u->core, server, u->protocol))) { pa_log("Failed to connect to server."); goto fail; } diff --git a/src/modules/raop/raop_client.c b/src/modules/raop/raop_client.c index f6dcd25..fdc2787 100644 --- a/src/modules/raop/raop_client.c +++ b/src/modules/raop/raop_client.c @@ -76,6 +76,7 @@ struct pa_raop_client { uint16_t port; char *sid; pa_rtsp_client *rtsp; + pa_raop_protocol_t protocol; uint8_t jack_type; uint8_t jack_status; @@ -365,18 +366,21 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist *he } } -pa_raop_client* pa_raop_client_new(pa_core *core, const char *host) { +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host, + pa_raop_protocol_t protocol) { pa_parsed_address a; pa_raop_client *c = pa_xnew0(pa_raop_client, 1); pa_assert(core); pa_assert(host); + pa_assert(protocol == RAOP_TCP); if (pa_parse_address(host, &a) < 0 || a.type == PA_PARSED_ADDRESS_UNIX) return NULL; c->core = core; c->fd = -1; + c->protocol = protocol; c->host = pa_xstrdup(a.path_or_host); if (a.port) diff --git a/src/modules/raop/raop_client.h b/src/modules/raop/raop_client.h index e44b1d7..fe669d1 100644 --- a/src/modules/raop/raop_client.h +++ b/src/modules/raop/raop_client.h @@ -24,9 +24,14 @@ #include <pulsecore/core.h> +typedef enum pa_raop_protocol { + RAOP_TCP, + RAOP_UDP, +} pa_raop_protocol_t; + typedef struct pa_raop_client pa_raop_client; -pa_raop_client* pa_raop_client_new(pa_core *core, const char *host); +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host, pa_raop_protocol_t protocol); void pa_raop_client_free(pa_raop_client *c); int pa_raop_connect(pa_raop_client *c); -- 1.8.1.2