mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-02 21:38:58 -04:00
module-raop: Add transient HomeKit pairing
This commit is contained in:
parent
75eb403d15
commit
45a0460722
2 changed files with 432 additions and 37 deletions
|
|
@ -64,7 +64,7 @@
|
|||
* #raop.domain = ""
|
||||
* #raop.device = ""
|
||||
* #raop.transport = "udp" | "tcp"
|
||||
* #raop.encryption.type = "RSA" | "auth_setup" | "none"
|
||||
* #raop.encryption.type = "RSA" | "auth_setup" | "pair_setup" | "none"
|
||||
* #raop.audio.codec = "PCM" | "ALAC" | "AAC" | "AAC-ELD"
|
||||
* #audio.channels = 2
|
||||
* #audio.format = "S16" | "S24" | "S32"
|
||||
|
|
@ -105,12 +105,14 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
|||
|
||||
static const struct spa_dict_item module_props[] = {
|
||||
{ PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ PW_KEY_MODULE_DESCRIPTION, "Discover remote streams" },
|
||||
{ PW_KEY_MODULE_DESCRIPTION, "Discover remote speakers" },
|
||||
{ PW_KEY_MODULE_USAGE, MODULE_USAGE },
|
||||
{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
|
||||
};
|
||||
|
||||
#define SERVICE_TYPE_SINK "_raop._tcp"
|
||||
#define SERVICE_TYPE_RAOP "_raop._tcp"
|
||||
#define SERVICE_TYPE_AP "_airplay._tcp"
|
||||
|
||||
|
||||
struct impl {
|
||||
struct pw_context *context;
|
||||
|
|
@ -122,7 +124,8 @@ struct impl {
|
|||
|
||||
AvahiPoll *avahi_poll;
|
||||
AvahiClient *client;
|
||||
AvahiServiceBrowser *sink_browser;
|
||||
AvahiServiceBrowser *sink_browser_raop;
|
||||
AvahiServiceBrowser *sink_browser_ap;
|
||||
|
||||
struct spa_list tunnel_list;
|
||||
};
|
||||
|
|
@ -182,8 +185,10 @@ static void impl_free(struct impl *impl)
|
|||
spa_list_consume(t, &impl->tunnel_list, link)
|
||||
free_tunnel(t);
|
||||
|
||||
if (impl->sink_browser)
|
||||
avahi_service_browser_free(impl->sink_browser);
|
||||
if (impl->sink_browser_raop)
|
||||
avahi_service_browser_free(impl->sink_browser_raop);
|
||||
if (impl->sink_browser_ap)
|
||||
avahi_service_browser_free(impl->sink_browser_ap);
|
||||
if (impl->client)
|
||||
avahi_client_free(impl->client);
|
||||
if (impl->avahi_poll)
|
||||
|
|
@ -215,7 +220,30 @@ static bool str_in_list(const char *haystack, const char *delimiters, const char
|
|||
return false;
|
||||
}
|
||||
|
||||
static void pw_properties_from_avahi_string(const char *key, const char *value,
|
||||
static void pw_properties_from_ap_txt(const char *key, const char *value,
|
||||
struct pw_properties *props)
|
||||
{
|
||||
if (spa_streq(key, "deviceid")) {
|
||||
pw_properties_set(props, "raop.device", value);
|
||||
}
|
||||
else if (spa_streq(key, "features")) {
|
||||
pw_properties_set(props, "raop.features", value);
|
||||
}
|
||||
else if (spa_streq(key, "flags")) {
|
||||
pw_properties_set(props, "raop.flags", value);
|
||||
}
|
||||
else if (spa_streq(key, "pk")) {
|
||||
pw_properties_set(props, "raop.pk", value);
|
||||
}
|
||||
else if (spa_streq(key, "pi")) {
|
||||
pw_properties_set(props, "raop.pi", value);
|
||||
}
|
||||
else if (spa_streq(key, "psi")) {
|
||||
pw_properties_set(props, "raop.psi", value);
|
||||
}
|
||||
}
|
||||
|
||||
static void pw_properties_from_raop_txt(const char *key, const char *value,
|
||||
struct pw_properties *props)
|
||||
{
|
||||
if (spa_streq(key, "device")) {
|
||||
|
|
@ -393,6 +421,37 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr
|
|||
goto done;
|
||||
}
|
||||
|
||||
pw_log_info("mdns service type: %s", type);
|
||||
if (strcmp(type, SERVICE_TYPE_AP) == 0) {
|
||||
for (l = txt; l; l = l->next) {
|
||||
char *key, *value;
|
||||
|
||||
if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0)
|
||||
break;
|
||||
|
||||
pw_properties_from_ap_txt(key, value, props);
|
||||
avahi_free(key);
|
||||
avahi_free(value);
|
||||
}
|
||||
|
||||
// TODO lorbus
|
||||
// if !feature audio goto done
|
||||
pw_properties_set(props, "raop.encryption.type", "pair_setup");
|
||||
pw_properties_set(props, "raop.transport", "udp");
|
||||
|
||||
} else {
|
||||
for (l = txt; l; l = l->next) {
|
||||
char *key, *value;
|
||||
|
||||
if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0)
|
||||
break;
|
||||
|
||||
pw_properties_from_raop_txt(key, value, props);
|
||||
avahi_free(key);
|
||||
avahi_free(value);
|
||||
}
|
||||
}
|
||||
|
||||
avahi_address_snprint(at, sizeof(at), a);
|
||||
ipv = protocol == AVAHI_PROTO_INET ? 4 : 6;
|
||||
pw_properties_setf(props, "raop.ip", "%s", at);
|
||||
|
|
@ -402,17 +461,6 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr
|
|||
pw_properties_setf(props, "raop.hostname", "%s", host_name);
|
||||
pw_properties_setf(props, "raop.domain", "%s", domain);
|
||||
|
||||
for (l = txt; l; l = l->next) {
|
||||
char *key, *value;
|
||||
|
||||
if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0)
|
||||
break;
|
||||
|
||||
pw_properties_from_avahi_string(key, value, props);
|
||||
avahi_free(key);
|
||||
avahi_free(value);
|
||||
}
|
||||
|
||||
if ((str = pw_properties_get(impl->properties, "raop.latency.ms")) != NULL)
|
||||
pw_properties_set(props, "raop.latency.ms", str);
|
||||
|
||||
|
|
@ -502,9 +550,13 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
case AVAHI_CLIENT_S_REGISTERING:
|
||||
case AVAHI_CLIENT_S_RUNNING:
|
||||
case AVAHI_CLIENT_S_COLLISION:
|
||||
if (impl->sink_browser == NULL)
|
||||
impl->sink_browser = make_browser(impl, SERVICE_TYPE_SINK);
|
||||
if (impl->sink_browser == NULL)
|
||||
if (impl->sink_browser_raop == NULL)
|
||||
impl->sink_browser_raop = make_browser(impl, SERVICE_TYPE_RAOP);
|
||||
if (impl->sink_browser_raop == NULL)
|
||||
goto error;
|
||||
if (impl->sink_browser_ap == NULL)
|
||||
impl->sink_browser_ap = make_browser(impl, SERVICE_TYPE_AP);
|
||||
if (impl->sink_browser_ap == NULL)
|
||||
goto error;
|
||||
break;
|
||||
case AVAHI_CLIENT_FAILURE:
|
||||
|
|
@ -513,9 +565,13 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
|
|||
|
||||
SPA_FALLTHROUGH;
|
||||
case AVAHI_CLIENT_CONNECTING:
|
||||
if (impl->sink_browser) {
|
||||
avahi_service_browser_free(impl->sink_browser);
|
||||
impl->sink_browser = NULL;
|
||||
if (impl->sink_browser_raop) {
|
||||
avahi_service_browser_free(impl->sink_browser_raop);
|
||||
impl->sink_browser_raop = NULL;
|
||||
}
|
||||
if (impl->sink_browser_ap) {
|
||||
avahi_service_browser_free(impl->sink_browser_ap);
|
||||
impl->sink_browser_ap = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue