[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