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/remote-device.c | 93 ++++++++++++++++++++++++++++++ src/modules/tunnel-manager/remote-device.h | 3 + 2 files changed, 96 insertions(+) diff --git a/src/modules/tunnel-manager/remote-device.c b/src/modules/tunnel-manager/remote-device.c index a6c9cb1..859800b 100644 --- a/src/modules/tunnel-manager/remote-device.c +++ b/src/modules/tunnel-manager/remote-device.c @@ -32,6 +32,9 @@ #include <pulsecore/device-type.h> #include <pulsecore/namereg.h> +static void tear_down_tunnel_module(pa_tunnel_manager_remote_device *device); +static void apply_tunnel_enabled_policy(pa_tunnel_manager_remote_device *device); + void pa_tunnel_manager_remote_device_new(pa_tunnel_manager_remote_server *server, pa_device_type_t type, const void *info) { const char *name = NULL; uint32_t idx = PA_INVALID_INDEX; @@ -129,6 +132,68 @@ void pa_tunnel_manager_remote_device_new(pa_tunnel_manager_remote_server *server 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)); + + apply_tunnel_enabled_policy(device); +} + +static pa_hook_result_t module_unload_cb(void *hook_data, void *call_data, void *userdata) { + pa_module *module = call_data; + pa_tunnel_manager_remote_device *device = userdata; + + pa_assert(module); + pa_assert(device); + + if (module == device->tunnel_module) + tear_down_tunnel_module(device); + + return PA_HOOK_OK; +} + +static void set_up_tunnel_module(pa_tunnel_manager_remote_device *device) { + const char *module_name = NULL; + char *args; + + pa_assert(device); + pa_assert(!device->tunnel_module); + + 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, + pa_device_type_to_string(device->type), device->name, + pa_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) + return; + + device->module_unload_slot = pa_hook_connect(&device->server->manager->core->hooks[PA_CORE_HOOK_MODULE_UNLOAD], + PA_HOOK_NORMAL, module_unload_cb, device); +} + +static void tear_down_tunnel_module(pa_tunnel_manager_remote_device *device) { + pa_assert(device); + + if (device->module_unload_slot) { + pa_hook_slot_free(device->module_unload_slot); + device->module_unload_slot = NULL; + } + + if (device->tunnel_module) { + pa_module_unload(device->tunnel_module->core, device->tunnel_module, true); + device->tunnel_module = NULL; + } } void pa_tunnel_manager_remote_device_free(pa_tunnel_manager_remote_device *device) { @@ -149,6 +214,8 @@ void pa_tunnel_manager_remote_device_free(pa_tunnel_manager_remote_device *devic pa_hashmap_remove(device->server->devices, device->name); pa_hook_fire(&device->hooks[PA_TUNNEL_MANAGER_REMOTE_DEVICE_HOOK_UNLINKED], NULL); + tear_down_tunnel_module(device); + if (device->get_info_operation) { pa_operation_cancel(device->get_info_operation); pa_operation_unref(device->get_info_operation); @@ -184,6 +251,23 @@ static void set_proplist(pa_tunnel_manager_remote_device *device, pa_proplist *p pa_hook_fire(&device->hooks[PA_TUNNEL_MANAGER_REMOTE_DEVICE_HOOK_PROPLIST_CHANGED], NULL); } +static void 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)); + + if (enabled) + set_up_tunnel_module(device); + else + tear_down_tunnel_module(device); +} + static void 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; @@ -253,3 +337,12 @@ void pa_tunnel_manager_remote_device_update(pa_tunnel_manager_remote_device *dev pa_tunnel_manager_remote_server_set_failed(device->server, true); } } + +static void apply_tunnel_enabled_policy(pa_tunnel_manager_remote_device *device) { + bool enabled; + + pa_assert(device); + + enabled = !device->is_monitor; + set_tunnel_enabled(device, enabled); +} diff --git a/src/modules/tunnel-manager/remote-device.h b/src/modules/tunnel-manager/remote-device.h index a766763..b08424c 100644 --- a/src/modules/tunnel-manager/remote-device.h +++ b/src/modules/tunnel-manager/remote-device.h @@ -41,9 +41,12 @@ 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; + pa_hook_slot *module_unload_slot; /* 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