From: Martin Blanchard <tinram@xxxxxx> During the discovery phase, raop servers send their capabilities (supported encryption, audio codec...). These should be passed to the raop sink via module's arguments. Original patch written by Martin Blanchard, then modified by Hajime Fujita <crisp.fujita at nifty.com> based on review comments by Anton Lundin <glance at acc.umu.se>. Now resolver_cb always dtrdup()s string blocks given by Avahi, to make the code easier to maintain. --- src/modules/raop/module-raop-discover.c | 89 ++++++++++++++++++++++++++++++++- src/modules/raop/module-raop-sink.c | 2 +- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/modules/raop/module-raop-discover.c b/src/modules/raop/module-raop-discover.c index 1ced777..6e2542a 100644 --- a/src/modules/raop/module-raop-discover.c +++ b/src/modules/raop/module-raop-discover.c @@ -139,6 +139,9 @@ static void resolver_cb( struct userdata *u = userdata; struct tunnel *tnl; char *device = NULL, *nicename, *dname, *vname, *args; + char *tp = NULL, *et = NULL, *cn = NULL; + char *ch = NULL, *ss = NULL, *sr = NULL; + char *t = NULL; char at[AVAHI_ADDRESS_STR_MAX]; AvahiStringList *l; pa_module *m; @@ -169,6 +172,51 @@ static void resolver_cb( if (pa_streq(key, "device")) { device = value; value = NULL; + } else if (pa_streq(key, "tp")) { + /* Transport protocol: + * - TCP = only TCP, + * - UDP = only UDP, + * - TCP,UDP = both supported (UDP should be prefered) */ + if (pa_str_in_list(value, ",", "UDP")) + tp = pa_xstrdup("UDP"); + else if (pa_str_in_list(value, ",", "TCP")) + tp = pa_xstrdup("TCP"); + else + tp = pa_xstrdup(value); + } else if (pa_streq(key, "et")) { + /* Supported encryption types: + * - 0 = none, + * - 1 = RSA, + * - 2 = FairPlay, + * - 3 = MFiSAP, + * - 4 = FairPlay SAPv2.5. */ + if (pa_str_in_list(value, ",", "1")) + et = pa_xstrdup("RSA"); + else + et = pa_xstrdup("none"); + } else if (pa_streq(key, "cn")) { + /* Suported audio codecs: + * - 0 = PCM, + * - 1 = ALAC, + * - 2 = AAC, + * - 3 = AAC ELD. */ + cn = pa_xstrdup("PCM"); + } else if (pa_streq(key, "md")) { + /* Supported metadata types: + * - 0 = text, + * - 1 = artwork, + * - 2 = progress. */ + } else if (pa_streq(key, "pw")) { + /* Requires password ? (true/false) */ + } else if (pa_streq(key, "ch")) { + /* Number of channels */ + ch = pa_xstrdup(value); + } else if (pa_streq(key, "ss")) { + /* Sample size */ + ss = pa_xstrdup(value); + } else if (pa_streq(key, "sr")) { + /* Sample rate */ + sr = pa_xstrdup(value); } avahi_free(key); @@ -176,9 +224,9 @@ static void resolver_cb( } if (device) - dname = pa_sprintf_malloc("raop.%s.%s", host_name, device); + dname = pa_sprintf_malloc("raop_output.%s.%s", host_name, device); else - dname = pa_sprintf_malloc("raop.%s", host_name); + dname = pa_sprintf_malloc("raop_output.%s", host_name); if (!(vname = pa_namereg_make_valid_name(dname))) { pa_log("Cannot construct valid device name from '%s'.", dname); @@ -205,6 +253,43 @@ static void resolver_cb( vname); } + if (tp != NULL) { + t = args; + args = pa_sprintf_malloc("%s protocol=%s", args, tp); + pa_xfree(tp); + pa_xfree(t); + } + if (et != NULL) { + t = args; + args = pa_sprintf_malloc("%s encryption=%s", args, et); + pa_xfree(et); + pa_xfree(t); + } + if (cn != NULL) { + t = args; + args = pa_sprintf_malloc("%s codec=%s", args, cn); + pa_xfree(cn); + pa_xfree(t); + } + if (ch != NULL) { + t = args; + args = pa_sprintf_malloc("%s channels=%s", args, ch); + pa_xfree(ch); + pa_xfree(t); + } + if (ss != NULL) { + t = args; + args = pa_sprintf_malloc("%s format=%s", args, ss); + pa_xfree(ss); + pa_xfree(t); + } + if (sr != NULL) { + t = args; + args = pa_sprintf_malloc("%s rate=%s", args, sr); + pa_xfree(sr); + pa_xfree(t); + } + pa_log_debug("Loading module-raop-sink with arguments '%s'", args); if ((m = pa_module_load(u->core, "module-raop-sink", args))) { diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c index 1eadde2..c1afedd 100644 --- a/src/modules/raop/module-raop-sink.c +++ b/src/modules/raop/module-raop-sink.c @@ -721,7 +721,7 @@ static void udp_thread_func(struct userdata *u) { } /* Polling (audio data + control socket + timing socket). */ - if ((rv = pa_rtpoll_run(u->rtpoll, true)) < 0) + if ((rv = pa_rtpoll_run(u->rtpoll)) < 0) goto fail; else if (rv == 0) goto finish; -- 2.9.3