[pulseaudio-discuss] [PATCH v2 5/5] tunnel-manager: Load tunnel sinks and sources

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Mon Dec 1 05:06:07 PST 2014


This makes the tunnel manager load tunnel sinks and sources for all
devices in the remote servers, except for monitor sources.
---
 src/modules/tunnel-manager/tunnel-manager.c | 81 +++++++++++++++++++++++++++++
 src/modules/tunnel-manager/tunnel-manager.h |  4 ++
 2 files changed, 85 insertions(+)

diff --git a/src/modules/tunnel-manager/tunnel-manager.c b/src/modules/tunnel-manager/tunnel-manager.c
index cb8b3a6..0735c66 100644
--- a/src/modules/tunnel-manager/tunnel-manager.c
+++ b/src/modules/tunnel-manager/tunnel-manager.c
@@ -46,6 +46,7 @@ static void remote_server_set_failed(pa_tunnel_manager_remote_server *server, bo
 static void remote_device_new(pa_tunnel_manager_remote_server *server, pa_device_type_t type, const void *info);
 static void remote_device_free(pa_tunnel_manager_remote_device *device);
 static void remote_device_update(pa_tunnel_manager_remote_device *device);
+static void remote_device_apply_tunnel_enabled_policy(pa_tunnel_manager_remote_device *device);
 
 struct device_stub {
     pa_tunnel_manager_remote_server *server;
@@ -67,6 +68,21 @@ static void device_stub_new(pa_tunnel_manager_remote_server *server, pa_device_t
 static void device_stub_unlink(struct device_stub *stub);
 static void device_stub_free(struct device_stub *stub);
 
+static pa_hook_result_t module_unload_cb(void *hook_data, void *call_data, void *userdata) {
+    pa_module *module = call_data;
+    pa_tunnel_manager *manager = userdata;
+    pa_tunnel_manager_remote_device *device;
+
+    pa_assert(module);
+    pa_assert(manager);
+
+    device = pa_hashmap_remove(manager->remote_devices_by_module, module);
+    if (device)
+        device->tunnel_module = NULL;
+
+    return PA_HOOK_OK;
+}
+
 static pa_tunnel_manager *tunnel_manager_new(pa_core *core) {
     pa_tunnel_manager *manager;
     pa_tunnel_manager_config *manager_config;
@@ -77,9 +93,13 @@ static pa_tunnel_manager *tunnel_manager_new(pa_core *core) {
 
     manager = pa_xnew0(pa_tunnel_manager, 1);
     manager->core = core;
+    manager->remote_devices_by_module = pa_hashmap_new(NULL, NULL);
     manager->remote_servers = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
     manager->refcnt = 1;
 
+    manager->module_unload_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_MODULE_UNLOAD], PA_HOOK_NORMAL, module_unload_cb,
+                                                  manager);
+
     manager_config = pa_tunnel_manager_config_new();
 
     PA_HASHMAP_FOREACH(server_config, manager_config->remote_servers, state)
@@ -98,6 +118,9 @@ static void tunnel_manager_free(pa_tunnel_manager *manager) {
 
     pa_shared_remove(manager->core, "tunnel_manager");
 
+    if (manager->module_unload_slot)
+        pa_hook_slot_free(manager->module_unload_slot);
+
     if (manager->remote_servers) {
         pa_tunnel_manager_remote_server *server;
 
@@ -107,6 +130,11 @@ static void tunnel_manager_free(pa_tunnel_manager *manager) {
         pa_hashmap_free(manager->remote_servers);
     }
 
+    if (manager->remote_devices_by_module) {
+        pa_assert(pa_hashmap_isempty(manager->remote_devices_by_module));
+        pa_hashmap_free(manager->remote_devices_by_module);
+    }
+
     pa_xfree(manager);
 }
 
@@ -561,6 +589,36 @@ static void remote_device_new(pa_tunnel_manager_remote_server *server, pa_device
     pa_log_debug("        Sample spec: %s", pa_sample_spec_snprint(sample_spec_str, sizeof(sample_spec_str), sample_spec));
     pa_log_debug("        Channel map: %s", pa_channel_map_snprint(channel_map_str, sizeof(channel_map_str), channel_map));
     pa_log_debug("        Is monitor: %s", pa_boolean_to_string(device->is_monitor));
+    pa_log_debug("        Tunnel enabled: %s", pa_boolean_to_string(device->tunnel_enabled));
+
+    remote_device_apply_tunnel_enabled_policy(device);
+
+    if (device->tunnel_enabled) {
+        const char *module_name;
+        char *args;
+
+        switch (device->type) {
+            case PA_DEVICE_TYPE_SINK:
+                module_name = "module-tunnel-sink-new";
+                break;
+
+            case PA_DEVICE_TYPE_SOURCE:
+                module_name = "module-tunnel-source-new";
+                break;
+        }
+
+        args = pa_sprintf_malloc("server=%s "
+                                 "%s=%s "
+                                 "%s_name=tunnel_manager.%s.%s",
+                                 device->server->address,
+                                 device_type_to_string(device->type), device->name,
+                                 device_type_to_string(device->type), device->server->name, device->name);
+        device->tunnel_module = pa_module_load(device->server->manager->core, module_name, args);
+        pa_xfree(args);
+
+        if (device->tunnel_module)
+            pa_hashmap_put(device->server->manager->remote_devices_by_module, device->tunnel_module, device);
+    }
 }
 
 static void remote_device_free(pa_tunnel_manager_remote_device *device) {
@@ -570,6 +628,11 @@ static void remote_device_free(pa_tunnel_manager_remote_device *device) {
 
     pa_log_debug("[%s] Freeing remote device %s.", device->server->name, device->name);
 
+    if (device->tunnel_module) {
+        pa_hashmap_remove(device->server->manager->remote_devices_by_module, device->tunnel_module);
+        pa_module_unload(device->server->manager->core, device->tunnel_module, true);
+    }
+
     pa_hashmap_remove(device->server->devices, device->name);
     pa_hook_fire(&device->hooks[PA_TUNNEL_MANAGER_REMOTE_DEVICE_HOOK_UNLINKED], NULL);
 
@@ -602,6 +665,18 @@ static void remote_device_set_proplist(pa_tunnel_manager_remote_device *device,
     pa_hook_fire(&device->hooks[PA_TUNNEL_MANAGER_REMOTE_DEVICE_HOOK_PROPLIST_CHANGED], NULL);
 }
 
+static void remote_device_set_tunnel_enabled(pa_tunnel_manager_remote_device *device, bool enabled) {
+    pa_assert(device);
+
+    if (enabled == device->tunnel_enabled)
+        return;
+
+    device->tunnel_enabled = enabled;
+
+    pa_log_debug("[%s %s] Tunnel enabled changed from %s to %s.", device->server->name, device->name,
+                 pa_boolean_to_string(!enabled), pa_boolean_to_string(enabled));
+}
+
 static void remote_device_get_info_cb(pa_context *context, const void *info, int is_last, void *userdata) {
     pa_tunnel_manager_remote_device *device = userdata;
     pa_proplist *proplist = NULL;
@@ -674,6 +749,12 @@ static void remote_device_update(pa_tunnel_manager_remote_device *device) {
     }
 }
 
+static void remote_device_apply_tunnel_enabled_policy(pa_tunnel_manager_remote_device *device) {
+    pa_assert(device);
+
+    remote_device_set_tunnel_enabled(device, !device->is_monitor);
+}
+
 static void device_stub_get_info_cb(pa_context *context, const void *info, int is_last, void *userdata) {
     struct device_stub *stub = userdata;
     uint32_t idx = PA_INVALID_INDEX;
diff --git a/src/modules/tunnel-manager/tunnel-manager.h b/src/modules/tunnel-manager/tunnel-manager.h
index 9775fd1..cd790b5 100644
--- a/src/modules/tunnel-manager/tunnel-manager.h
+++ b/src/modules/tunnel-manager/tunnel-manager.h
@@ -32,9 +32,11 @@ typedef struct pa_tunnel_manager_remote_device pa_tunnel_manager_remote_device;
 
 struct pa_tunnel_manager {
     pa_core *core;
+    pa_hashmap *remote_devices_by_module; /* pa_module -> pa_tunnel_manager_remote_device */
     pa_hashmap *remote_servers; /* name -> pa_tunnel_manager_remote_server */
 
     unsigned refcnt;
+    pa_hook_slot *module_unload_slot;
 };
 
 /* If ref is true, the reference count of the manager is incremented, and also
@@ -73,9 +75,11 @@ struct pa_tunnel_manager_remote_device {
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
     bool is_monitor;
+    bool tunnel_enabled;
     pa_hook hooks[PA_TUNNEL_MANAGER_REMOTE_DEVICE_HOOK_MAX];
 
     pa_operation *get_info_operation;
+    pa_module *tunnel_module;
 
     /* These are a workaround for the problem that the introspection API's info
      * callbacks are called multiple times, which means that if the userdata
-- 
1.9.3



More information about the pulseaudio-discuss mailing list