static int publish_main_service(struct userdata *u) { DNSServiceErrorType err; TXTRecordRef txt; pa_assert(u); if (u->main_service) { DNSServiceRefDeallocate(u->main_service); u->main_service = NULL; } TXTRecordCreate(&txt, 0, NULL); txt_record_server_data(u->core, &txt); err = DNSServiceRegister(&u->main_service, 0, /* flags */ kDNSServiceInterfaceIndexAny, u->service_name, SERVICE_TYPE_SERVER, NULL, /* domain */ NULL, /* host */ compute_port(u), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), NULL, NULL); if (err != kDNSServiceErr_NoError) { pa_log("%s(): DNSServiceRegister() returned err %d", __func__, err); return err; } TXTRecordDeallocate(&txt); return 0; }
static int publish_main_service(struct userdata *u) { AvahiStringList *txt = NULL; int r = -1; pa_assert(u); if (!u->main_entry_group) { if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) { pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } } else avahi_entry_group_reset(u->main_entry_group); txt = txt_record_server_data(u->core, txt); if (avahi_entry_group_add_service_strlst( u->main_entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, u->service_name, SERVICE_TYPE_SERVER, NULL, NULL, compute_port(u), txt) < 0) { pa_log("avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } if (avahi_entry_group_commit(u->main_entry_group) < 0) { pa_log("avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } r = 0; fail: avahi_string_list_free(txt); return r; }
static int publish_service(struct service *s) { int r = -1; TXTRecordRef txt; DNSServiceErrorType err; const char *name = NULL, *t; pa_proplist *proplist = NULL; pa_sample_spec ss; pa_channel_map map; char cm[PA_CHANNEL_MAP_SNPRINT_MAX], tmp[64]; enum service_subtype subtype; const char * const subtype_text[] = { [SUBTYPE_HARDWARE] = "hardware", [SUBTYPE_VIRTUAL] = "virtual", [SUBTYPE_MONITOR] = "monitor" }; pa_assert(s); if (s->service) { DNSServiceRefDeallocate(s->service); s->service = NULL; } TXTRecordCreate(&txt, 0, NULL); txt_record_server_data(s->userdata->core, &txt); get_service_data(s, &ss, &map, &name, &proplist, &subtype); TXTRecordSetValue(&txt, "device", strlen(name), name); snprintf(tmp, sizeof(tmp), "%u", ss.rate); TXTRecordSetValue(&txt, "rate", strlen(tmp), tmp); snprintf(tmp, sizeof(tmp), "%u", ss.channels); TXTRecordSetValue(&txt, "channels", strlen(tmp), tmp); t = pa_sample_format_to_string(ss.format); TXTRecordSetValue(&txt, "format", strlen(t), t); t = pa_channel_map_snprint(cm, sizeof(cm), &map); TXTRecordSetValue(&txt, "channel_map", strlen(t), t); t = subtype_text[subtype]; TXTRecordSetValue(&txt, "subtype", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION))) TXTRecordSetValue(&txt, "description", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME))) TXTRecordSetValue(&txt, "icon-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME))) TXTRecordSetValue(&txt, "vendor-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME))) TXTRecordSetValue(&txt, "product-name", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS))) TXTRecordSetValue(&txt, "class", strlen(t), t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR))) TXTRecordSetValue(&txt, "form-factor", strlen(t), t); err = DNSServiceRegister(&s->service, 0, /* flags */ kDNSServiceInterfaceIndexAny, s->service_name, pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, NULL, /* domain */ NULL, /* host */ compute_port(s->userdata), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), dns_service_register_reply, s); if (err != kDNSServiceErr_NoError) { pa_log("DNSServiceRegister() returned err %d", err); goto finish; } pa_log_debug("Successfully registered Bonjour services for >%s<.", s->service_name); return 0; finish: /* Remove this service */ if (r < 0) service_free(s); TXTRecordDeallocate(&txt); return r; }
static int publish_service(struct service *s) { int r = -1; AvahiStringList *txt = NULL; const char *name = NULL, *t; pa_proplist *proplist = NULL; pa_sample_spec ss; pa_channel_map map; char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; enum service_subtype subtype; const char * const subtype_text[] = { [SUBTYPE_HARDWARE] = "hardware", [SUBTYPE_VIRTUAL] = "virtual", [SUBTYPE_MONITOR] = "monitor" }; pa_assert(s); if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING) return 0; if (!s->entry_group) { if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) { pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; } } else avahi_entry_group_reset(s->entry_group); txt = txt_record_server_data(s->userdata->core, txt); get_service_data(s, &ss, &map, &name, &proplist, &subtype); txt = avahi_string_list_add_pair(txt, "device", name); txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map)); txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_DESCRIPTION))) txt = avahi_string_list_add_pair(txt, "description", t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_ICON_NAME))) txt = avahi_string_list_add_pair(txt, "icon-name", t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_VENDOR_NAME))) txt = avahi_string_list_add_pair(txt, "vendor-name", t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME))) txt = avahi_string_list_add_pair(txt, "product-name", t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS))) txt = avahi_string_list_add_pair(txt, "class", t); if ((t = pa_proplist_gets(proplist, PA_PROP_DEVICE_FORM_FACTOR))) txt = avahi_string_list_add_pair(txt, "form-factor", t); if (avahi_entry_group_add_service_strlst( s->entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, s->service_name, pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, NULL, NULL, compute_port(s->userdata), txt) < 0) { pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; } if (avahi_entry_group_add_service_subtype( s->entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, s->service_name, pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, NULL, pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) : (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) { pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; } if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) { if (avahi_entry_group_add_service_subtype( s->entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, s->service_name, SERVICE_TYPE_SOURCE, NULL, SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) { pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; } } if (avahi_entry_group_commit(s->entry_group) < 0) { pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; } r = 0; pa_log_debug("Successfully created entry group for %s.", s->service_name); finish: /* Remove this service */ if (r < 0) service_free(s); avahi_string_list_free(txt); return r; }