Hey,

I have written a small patch that allows the module-zeroconf-publish module
to export the service for both cards, even though they originally had the
same name. In the get_service() I have extracted the content that dealt with
naming the service to a separate function, get_service_name(). Then, if the
registration of the service fails, a loop is entered, trying to add ".%d" to
the name until it succeeds (or a limit of 100 is reached), basically the
same strategy used in pa_namereg_register().

Without this patch, PA refuses to export the second card over the network.
Would be nice if this patch (or something similar) is added to the PA
system.

Thanks,
-Ivar!
diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index d72d264..ecca4cc 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -66,6 +66,7 @@ PA_MODULE_LOAD_ONCE(TRUE);
 #define SERVICE_SUBTYPE_SOURCE_VIRTUAL "_virtual._sub."SERVICE_TYPE_SOURCE
 #define SERVICE_SUBTYPE_SOURCE_MONITOR "_monitor._sub."SERVICE_TYPE_SOURCE
 #define SERVICE_SUBTYPE_SOURCE_NON_MONITOR "_non-monitor._sub."SERVICE_TYPE_SOURCE
+#define MAX_NUM_LEN 16
 
 static const char* const valid_modargs[] = {
     NULL
@@ -222,6 +223,46 @@ static uint16_t compute_port(struct userdata *u) {
     return PA_NATIVE_DEFAULT_PORT;
 }
 
+static char *get_service_name(pa_object *device, int service_number) {
+    char *service_name, *hn, *un;
+    const char *n;
+
+    pa_object_assert_ref(device);
+
+    if (pa_sink_isinstance(device)) {
+        if (!(n = pa_proplist_gets(PA_SINK(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
+            n = PA_SINK(device)->name;
+    } else {
+        if (!(n = pa_proplist_gets(PA_SOURCE(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
+            n = PA_SOURCE(device)->name;
+    }
+
+    hn = pa_get_host_name_malloc();
+    un = pa_get_user_name_malloc();
+
+    if (service_number) {
+        char label[AVAHI_LABEL_MAX];
+        char number_label[MAX_NUM_LEN];
+        char * number_label_write_to;
+        pa_snprintf(label, AVAHI_LABEL_MAX, "%...@%s: %s", un, hn, n);
+        pa_snprintf(number_label, MAX_NUM_LEN, ".%d", service_number);
+        if(strlen(label) + strlen(number_label) > AVAHI_LABEL_MAX-1) {
+            number_label_write_to = label + AVAHI_LABEL_MAX-1 - strlen(number_label);
+        } else {
+            number_label_write_to = label + strlen(label);
+        }
+        pa_snprintf(number_label_write_to, MAX_NUM_LEN, "%s", number_label);
+        service_name = pa_truncate_utf8(pa_sprintf_malloc("%s", label), AVAHI_LABEL_MAX);
+    } else {
+        service_name = pa_truncate_utf8(pa_sprintf_malloc("%...@%s: %s", un, hn, n), AVAHI_LABEL_MAX);
+    }
+
+    pa_xfree(un);
+    pa_xfree(hn);
+
+    return service_name;
+}
+
 static int publish_service(struct service *s) {
     int r = -1;
     AvahiStringList *txt = NULL;
@@ -231,6 +272,7 @@ static int publish_service(struct service *s) {
     pa_channel_map map;
     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
     enum service_subtype subtype;
+    pa_bool_t found_service_name = TRUE;
 
     const char * const subtype_text[] = {
         [SUBTYPE_HARDWARE] = "hardware",
@@ -284,9 +326,31 @@ static int publish_service(struct service *s) {
                 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;
+        found_service_name = FALSE;
+    }
+    if(!found_service_name) {
+        int i;
+        for(i=2; i<100; ++i) {
+            pa_xfree(s->service_name);
+            s->service_name = get_service_name(s->device, i);
+            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) {
+                found_service_name = TRUE;
+                break;
+            }
+        }
+        if(!found_service_name) {
+            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(
@@ -339,8 +403,6 @@ finish:
 
 static struct service *get_service(struct userdata *u, pa_object *device) {
     struct service *s;
-    char *hn, *un;
-    const char *n;
 
     pa_assert(u);
     pa_object_assert_ref(device);
@@ -353,21 +415,7 @@ static struct service *get_service(struct userdata *u, pa_object *device) {
     s->entry_group = NULL;
     s->device = device;
 
-    if (pa_sink_isinstance(device)) {
-        if (!(n = pa_proplist_gets(PA_SINK(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
-            n = PA_SINK(device)->name;
-    } else {
-        if (!(n = pa_proplist_gets(PA_SOURCE(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
-            n = PA_SOURCE(device)->name;
-    }
-
-    hn = pa_get_host_name_malloc();
-    un = pa_get_user_name_malloc();
-
-    s->service_name = pa_truncate_utf8(pa_sprintf_malloc("%...@%s: %s", un, hn, n), AVAHI_LABEL_MAX-1);
-
-    pa_xfree(un);
-    pa_xfree(hn);
+    s->service_name = get_service_name(device, 0);
 
     pa_hashmap_put(u->services, s->device, s);
 
_______________________________________________
pulseaudio-discuss mailing list
pulseaudio-discuss@mail.0pointer.de
https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss

Reply via email to