From 4464b68290669f133c17e7135dc86be9c4019326 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Fri, 20 Jul 2018 14:32:51 +0300 Subject: pulseaudio: remove unused .patch files from the repository No recipe uses those. Change-Id: Iec368fcf6e6340866c6d346a438e21c8cb7960ef Signed-off-by: George Kiagiadakis --- .../0031-Add-module-main-volume-policy.patch | 1418 -------------------- 1 file changed, 1418 deletions(-) delete mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch (limited to 'meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch') diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch deleted file mode 100644 index 216ed21e9..000000000 --- a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch +++ /dev/null @@ -1,1418 +0,0 @@ -From cfb39f18569679f59c9b6283c47e8d90ddd9763d Mon Sep 17 00:00:00 2001 -From: Tanu Kaskinen -Date: Wed, 21 May 2014 14:13:41 +0300 -Subject: [PATCH] Add module-main-volume-policy - -Change-Id: I787141b43cafb652aa752c64ae28b6b7aa052d8e -Signed-off-by: Jaska Uimonen ---- - Makefile.am | 3 + - src/Makefile.am | 15 + - src/daemon/default.pa.in | 4 + - .../main-volume-policy/main-volume-context.c | 325 ++++++++++++ - .../main-volume-policy/main-volume-context.h | 75 +++ - .../main-volume-policy/main-volume-policy.c | 213 ++++++++ - .../main-volume-policy.conf.example | 20 + - .../main-volume-policy/main-volume-policy.h | 72 +++ - .../main-volume-policy/module-main-volume-policy.c | 556 +++++++++++++++++++++ - 9 files changed, 1283 insertions(+) - create mode 100644 src/modules/main-volume-policy/main-volume-context.c - create mode 100644 src/modules/main-volume-policy/main-volume-context.h - create mode 100644 src/modules/main-volume-policy/main-volume-policy.c - create mode 100644 src/modules/main-volume-policy/main-volume-policy.conf.example - create mode 100644 src/modules/main-volume-policy/main-volume-policy.h - create mode 100644 src/modules/main-volume-policy/module-main-volume-policy.c - -diff --git a/Makefile.am b/Makefile.am -index cf4a648..646b7fc 100644 ---- a/Makefile.am 2016-04-13 15:14:28.942023245 +0200 -+++ b/Makefile.am 2016-04-13 15:16:32.691023039 +0200 -@@ -60,6 +60,9 @@ - moduledevvolumeapi_DATA = src/modules/volume-api/*.h - moduledevvolumeapidir = $(includedir)/pulsemodule/modules/volume-api - -+moduledevmainvolumepolicy_DATA = $(top_srcdir)/src/modules/main-volume-policy/*.h -+moduledevmainvolumepolicydir = $(includedir)/pulsemodule/modules/main-volume-policy -+ - if HAVE_GLIB20 - pkgconfig_DATA += \ - libpulse-mainloop-glib.pc - libpulse-mainloop-glib.pc -diff --git a/src/Makefile.am b/src/Makefile.am -index a6bb319..8fa60ec 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -1050,7 +1050,8 @@ - libprotocol-simple.la \ - libprotocol-http.la \ - libprotocol-native.la \ -- libvolume-api.la -+ libvolume-api.la \ -+ libmain-volume-policy.la - - if HAVE_WEBRTC - modlibexec_LTLIBRARIES += libwebrtc-util.la -@@ -1051,6 +1052,12 @@ libcli_la_SOURCES = pulsecore/cli.c pulsecore/cli.h - libcli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version - libcli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la - -+libmain_volume_policy_la_SOURCES = \ -+ modules/main-volume-policy/main-volume-context.c modules/main-volume-policy/main-volume-context.h \ -+ modules/main-volume-policy/main-volume-policy.c modules/main-volume-policy/main-volume-policy.h -+libmain_volume_policy_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -+libmain_volume_policy_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libvolume-api.la -+ - libprotocol_cli_la_SOURCES = pulsecore/protocol-cli.c pulsecore/protocol-cli.h - libprotocol_cli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version - libprotocol_cli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libcli.la -@@ -1136,6 +1136,7 @@ endif - modlibexec_LTLIBRARIES += \ - module-cli.la \ - module-cli-protocol-tcp.la \ -+ module-main-volume-policy.la \ - module-simple-protocol-tcp.la \ - module-null-sink.la \ - module-null-source.la \ -@@ -1426,6 +1434,7 @@ SYMDEF_FILES = \ - module-cli-symdef.h \ - module-cli-protocol-tcp-symdef.h \ - module-cli-protocol-unix-symdef.h \ -+ module-main-volume-policy-symdef.h \ - module-pipe-sink-symdef.h \ - module-pipe-source-symdef.h \ - module-simple-protocol-tcp-symdef.h \ -@@ -1575,6 +1584,12 @@ module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_ - module_cli_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) - module_cli_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-cli.la - -+# Main volume and mute policy -+ -+module_main_volume_policy_la_SOURCES = modules/main-volume-policy/module-main-volume-policy.c -+module_main_volume_policy_la_LDFLAGS = $(MODULE_LDFLAGS) -+module_main_volume_policy_la_LIBADD = $(MODULE_LIBADD) libmain-volume-policy.la libvolume-api.la -+ - # HTTP protocol - - module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in -index 7cf52a4..f70804c 100755 ---- a/src/daemon/default.pa.in -+++ b/src/daemon/default.pa.in -@@ -188,6 +188,10 @@ - #.endif - ])dnl - -+.ifexists module-main-volume-policy -+load-module module-main-volume-policy -+.endif -+ - ### Make some devices default - #set-default-sink output - #set-default-source input -diff --git a/src/modules/main-volume-policy/main-volume-context.c b/src/modules/main-volume-policy/main-volume-context.c -new file mode 100644 -index 0000000..7ac35c6 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-context.c -@@ -0,0 +1,325 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "main-volume-context.h" -+ -+#include -+#include -+ -+int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, -+ pa_main_volume_context **context) { -+ pa_main_volume_context *context_local; -+ int r; -+ -+ pa_assert(policy); -+ pa_assert(name); -+ pa_assert(description); -+ pa_assert(context); -+ -+ context_local = pa_xnew0(struct pa_main_volume_context, 1); -+ context_local->main_volume_policy = policy; -+ context_local->index = pa_main_volume_policy_allocate_main_volume_context_index(policy); -+ -+ r = pa_main_volume_policy_register_name(policy, name, true, &context_local->name); -+ if (r < 0) -+ goto fail; -+ -+ context_local->description = pa_xstrdup(description); -+ -+ *context = context_local; -+ -+ return 0; -+ -+fail: -+ pa_main_volume_context_free(context_local); -+ -+ return r; -+} -+ -+void pa_main_volume_context_put(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ pa_main_volume_policy_add_main_volume_context(context->main_volume_policy, context); -+ -+ context->linked = true; -+ -+ pa_log_debug("Created main volume context #%u.", context->index); -+ pa_log_debug(" Name: %s", context->name); -+ pa_log_debug(" Description: %s", context->description); -+ pa_log_debug(" Main output volume control: %s", -+ context->main_output_volume_control ? context->main_output_volume_control->name : "(unset)"); -+ pa_log_debug(" Main input volume control: %s", -+ context->main_input_volume_control ? context->main_input_volume_control->name : "(unset)"); -+ pa_log_debug(" Main output mute control: %s", -+ context->main_output_mute_control ? context->main_output_mute_control->name : "(unset)"); -+ pa_log_debug(" Main input mute control: %s", -+ context->main_input_mute_control ? context->main_input_mute_control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], context); -+} -+ -+void pa_main_volume_context_unlink(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ if (context->unlinked) { -+ pa_log_debug("Unlinking main volume context %s (already unlinked, this is a no-op).", context->name); -+ return; -+ } -+ -+ context->unlinked = true; -+ -+ pa_log_debug("Unlinking main volume context %s.", context->name); -+ -+ if (context->linked) -+ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], context); -+ -+ if (context->main_input_mute_control_binding) { -+ pa_binding_free(context->main_input_mute_control_binding); -+ context->main_input_mute_control_binding = NULL; -+ } -+ -+ if (context->main_output_mute_control_binding) { -+ pa_binding_free(context->main_output_mute_control_binding); -+ context->main_output_mute_control_binding = NULL; -+ } -+ -+ if (context->main_input_volume_control_binding) { -+ pa_binding_free(context->main_input_volume_control_binding); -+ context->main_input_volume_control_binding = NULL; -+ } -+ -+ if (context->main_output_volume_control_binding) { -+ pa_binding_free(context->main_output_volume_control_binding); -+ context->main_output_volume_control_binding = NULL; -+ } -+ -+ context->main_input_mute_control = NULL; -+ context->main_output_mute_control = NULL; -+ context->main_input_volume_control = NULL; -+ context->main_output_volume_control = NULL; -+ -+ pa_main_volume_policy_remove_main_volume_context(context->main_volume_policy, context); -+} -+ -+void pa_main_volume_context_free(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ if (!context->unlinked) -+ pa_main_volume_context_unlink(context); -+ -+ pa_xfree(context->description); -+ -+ if (context->name) -+ pa_main_volume_policy_unregister_name(context->main_volume_policy, context->name); -+ -+ pa_xfree(context); -+} -+ -+const char *pa_main_volume_context_get_name(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ return context->name; -+} -+ -+static void set_main_output_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_output_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_output_volume_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main output volume control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_volume_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_output_volume_control_binding) -+ pa_binding_free(context->main_output_volume_control_binding); -+ -+ context->main_output_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_input_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_input_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_input_volume_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main input volume control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_volume_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_input_volume_control_binding) -+ pa_binding_free(context->main_input_volume_control_binding); -+ -+ context->main_input_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_output_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_output_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_output_mute_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main output mute control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_mute_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_output_mute_control_binding) -+ pa_binding_free(context->main_output_mute_control_binding); -+ -+ context->main_output_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_input_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_input_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_input_mute_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main input mute control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_mute_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_input_mute_control_binding) -+ pa_binding_free(context->main_input_mute_control_binding); -+ -+ context->main_input_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy) { -+ pa_binding_target_type *type; -+ -+ pa_assert(policy); -+ -+ type = pa_binding_target_type_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, policy->main_volume_contexts, -+ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], -+ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], -+ (pa_binding_target_type_get_name_cb_t) pa_main_volume_context_get_name); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_volume_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_volume_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_mute_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_mute_control)); -+ -+ return type; -+} -diff --git a/src/modules/main-volume-policy/main-volume-context.h b/src/modules/main-volume-policy/main-volume-context.h -new file mode 100644 -index 0000000..4a0a6f7 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-context.h -@@ -0,0 +1,75 @@ -+#ifndef foomainvolumecontexthfoo -+#define foomainvolumecontexthfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+#include -+ -+typedef struct pa_main_volume_context pa_main_volume_context; -+ -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE "MainVolumeContext" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL "main_output_volume_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL "main_input_volume_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL "main_output_mute_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL "main_input_mute_control" -+ -+struct pa_main_volume_context { -+ pa_main_volume_policy *main_volume_policy; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_volume_control *main_output_volume_control; -+ pa_volume_control *main_input_volume_control; -+ pa_mute_control *main_output_mute_control; -+ pa_mute_control *main_input_mute_control; -+ -+ pa_binding *main_output_volume_control_binding; -+ pa_binding *main_input_volume_control_binding; -+ pa_binding *main_output_mute_control_binding; -+ pa_binding *main_input_mute_control_binding; -+ -+ bool linked; -+ bool unlinked; -+}; -+ -+int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, -+ pa_main_volume_context **context); -+void pa_main_volume_context_put(pa_main_volume_context *context); -+void pa_main_volume_context_unlink(pa_main_volume_context *context); -+void pa_main_volume_context_free(pa_main_volume_context *context); -+ -+const char *pa_main_volume_context_get_name(pa_main_volume_context *context); -+ -+void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, pa_binding_target_info *target_info); -+ -+/* Called from main-volume-policy.c only. */ -+pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy); -+ -+#endif -diff --git a/src/modules/main-volume-policy/main-volume-policy.c b/src/modules/main-volume-policy/main-volume-policy.c -new file mode 100644 -index 0000000..b0b4ede ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.c -@@ -0,0 +1,213 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "main-volume-policy.h" -+ -+#include -+ -+#include -+#include -+ -+static pa_main_volume_policy *main_volume_policy_new(pa_core *core); -+static void main_volume_policy_free(pa_main_volume_policy *policy); -+ -+pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core) { -+ pa_main_volume_policy *policy; -+ -+ pa_assert(core); -+ -+ policy = pa_shared_get(core, "main-volume-policy"); -+ -+ if (policy) -+ pa_main_volume_policy_ref(policy); -+ else { -+ policy = main_volume_policy_new(core); -+ pa_assert_se(pa_shared_set(core, "main-volume-policy", policy) >= 0); -+ } -+ -+ return policy; -+} -+ -+pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy) { -+ pa_assert(policy); -+ -+ policy->refcnt++; -+ -+ return policy; -+} -+ -+void pa_main_volume_policy_unref(pa_main_volume_policy *policy) { -+ pa_assert(policy); -+ pa_assert(policy->refcnt > 0); -+ -+ policy->refcnt--; -+ -+ if (policy->refcnt == 0) { -+ pa_assert_se(pa_shared_remove(policy->core, "main-volume-policy") >= 0); -+ main_volume_policy_free(policy); -+ } -+} -+ -+static pa_main_volume_policy *main_volume_policy_new(pa_core *core) { -+ pa_main_volume_policy *policy; -+ unsigned i; -+ -+ pa_assert(core); -+ -+ policy = pa_xnew0(pa_main_volume_policy, 1); -+ policy->core = core; -+ policy->refcnt = 1; -+ policy->volume_api = pa_volume_api_get(core); -+ policy->names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); -+ policy->main_volume_contexts = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ -+ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) -+ pa_hook_init(&policy->hooks[i], policy); -+ -+ policy->main_volume_context_binding_target_type = pa_main_volume_context_create_binding_target_type(policy); -+ pa_volume_api_add_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); -+ -+ pa_log_debug("Created a pa_main_volume_policy object."); -+ -+ return policy; -+} -+ -+static void main_volume_policy_free(pa_main_volume_policy *policy) { -+ unsigned i; -+ -+ pa_assert(policy); -+ pa_assert(policy->refcnt == 0); -+ -+ pa_log_debug("Freeing the pa_main_volume_policy object."); -+ -+ if (policy->main_volume_context_binding_target_type) { -+ pa_volume_api_remove_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); -+ pa_binding_target_type_free(policy->main_volume_context_binding_target_type); -+ } -+ -+ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) -+ pa_hook_done(&policy->hooks[i]); -+ -+ if (policy->main_volume_contexts) { -+ pa_assert(pa_hashmap_isempty(policy->main_volume_contexts)); -+ pa_hashmap_free(policy->main_volume_contexts); -+ } -+ -+ if (policy->names) { -+ pa_assert(pa_hashmap_isempty(policy->names)); -+ pa_hashmap_free(policy->names); -+ } -+ -+ if (policy->volume_api) -+ pa_volume_api_unref(policy->volume_api); -+ -+ pa_xfree(policy); -+} -+ -+int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, -+ bool fail_if_already_registered, const char **registered_name) { -+ char *n; -+ -+ pa_assert(policy); -+ pa_assert(requested_name); -+ pa_assert(registered_name); -+ -+ n = pa_xstrdup(requested_name); -+ -+ if (pa_hashmap_put(policy->names, n, n) < 0) { -+ unsigned i = 1; -+ -+ pa_xfree(n); -+ -+ if (fail_if_already_registered) { -+ pa_log("Name %s already registered.", requested_name); -+ return -PA_ERR_EXIST; -+ } -+ -+ do { -+ i++; -+ n = pa_sprintf_malloc("%s.%u", requested_name, i); -+ } while (pa_hashmap_put(policy->names, n, n) < 0); -+ } -+ -+ *registered_name = n; -+ -+ return 0; -+} -+ -+void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name) { -+ pa_assert(policy); -+ pa_assert(name); -+ -+ pa_assert_se(pa_hashmap_remove_and_free(policy->names, name) >= 0); -+} -+ -+uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy) { -+ uint32_t idx; -+ -+ pa_assert(policy); -+ -+ idx = policy->next_main_volume_context_index++; -+ -+ return idx; -+} -+ -+void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_assert(policy); -+ pa_assert(context); -+ -+ pa_assert_se(pa_hashmap_put(policy->main_volume_contexts, (void *) context->name, context) >= 0); -+} -+ -+int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_assert(policy); -+ pa_assert(context); -+ -+ if (!pa_hashmap_remove(policy->main_volume_contexts, context->name)) -+ return -1; -+ -+ if (context == policy->active_main_volume_context) -+ pa_main_volume_policy_set_active_main_volume_context(policy, NULL); -+ -+ return 0; -+} -+ -+void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_main_volume_context *old_context; -+ -+ pa_assert(policy); -+ -+ old_context = policy->active_main_volume_context; -+ -+ if (context == old_context) -+ return; -+ -+ policy->active_main_volume_context = context; -+ -+ pa_log_debug("The active main volume context changed from %s to %s.", old_context ? old_context->name : "(unset)", -+ context ? context->name : "(unset)"); -+ -+ pa_hook_fire(&policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], NULL); -+} -diff --git a/src/modules/main-volume-policy/main-volume-policy.conf.example b/src/modules/main-volume-policy/main-volume-policy.conf.example -new file mode 100644 -index 0000000..a4a35d3 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.conf.example -@@ -0,0 +1,20 @@ -+[General] -+output-volume-model = by-active-main-volume-context -+input-volume-model = by-active-main-volume-context -+output-mute-model = none -+input-mute-model = none -+main-volume-contexts = x-example-call-main-volume-context x-example-default-main-volume-context -+ -+[MainVolumeContext x-example-call-main-volume-context] -+description = Call main volume context -+main-output-volume-control = bind:AudioGroup:x-example-call-downlink-audio-group -+main-input-volume-control = bind:AudioGroup:x-example-call-uplink-audio-group -+main-output-mute-control = none -+main-input-mute-control = none -+ -+[MainVolumeContext x-example-default-main-volume-context] -+description = Default main volume context -+main-output-volume-control = bind:AudioGroup:x-example-default-output-audio-group -+main-input-volume-control = bind:AudioGroup:x-example-default-input-audio-group -+main-output-mute-control = none -+main-input-mute-control = none -diff --git a/src/modules/main-volume-policy/main-volume-policy.h b/src/modules/main-volume-policy/main-volume-policy.h -new file mode 100644 -index 0000000..5cd669e ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.h -@@ -0,0 +1,72 @@ -+#ifndef foomainvolumepolicyhfoo -+#define foomainvolumepolicyhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+#include -+ -+#include -+ -+typedef struct pa_main_volume_policy pa_main_volume_policy; -+ -+/* Avoid circular dependencies... */ -+typedef struct pa_main_volume_context pa_main_volume_context; -+ -+enum { -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAX, -+}; -+ -+struct pa_main_volume_policy { -+ pa_core *core; -+ unsigned refcnt; -+ pa_volume_api *volume_api; -+ pa_hashmap *names; /* object name -> object name (hashmap-as-a-set) */ -+ pa_hashmap *main_volume_contexts; /* name -> pa_main_volume_context */ -+ pa_main_volume_context *active_main_volume_context; -+ -+ uint32_t next_main_volume_context_index; -+ pa_hook hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAX]; -+ pa_binding_target_type *main_volume_context_binding_target_type; -+}; -+ -+pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core); -+pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy); -+void pa_main_volume_policy_unref(pa_main_volume_policy *policy); -+ -+int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, -+ bool fail_if_already_registered, const char **registered_name); -+void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name); -+ -+uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy); -+void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+ -+#endif -diff --git a/src/modules/main-volume-policy/module-main-volume-policy.c b/src/modules/main-volume-policy/module-main-volume-policy.c -new file mode 100644 -index 0000000..a14699d ---- /dev/null -+++ b/src/modules/main-volume-policy/module-main-volume-policy.c -@@ -0,0 +1,556 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "module-main-volume-policy-symdef.h" -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+PA_MODULE_AUTHOR("Tanu Kaskinen"); -+PA_MODULE_DESCRIPTION(_("Main volume and mute policy")); -+PA_MODULE_VERSION(PACKAGE_VERSION); -+PA_MODULE_LOAD_ONCE(true); -+ -+enum control_type { -+ CONTROL_TYPE_VOLUME, -+ CONTROL_TYPE_MUTE, -+}; -+ -+enum model { -+ MODEL_NONE, -+ MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT, -+}; -+ -+struct userdata { -+ pa_main_volume_policy *main_volume_policy; -+ enum model output_volume_model; -+ enum model input_volume_model; -+ enum model output_mute_model; -+ enum model input_mute_model; -+ pa_hashmap *contexts; /* name -> struct context */ -+ -+ pa_hook_slot *active_main_volume_context_changed_slot; -+ -+ /* The following fields are only used during initialization. */ -+ pa_hashmap *context_names; /* name -> name (hashmap-as-a-set) */ -+ pa_hashmap *unused_contexts; /* name -> struct context */ -+}; -+ -+struct context { -+ struct userdata *userdata; -+ char *name; -+ char *description; -+ pa_binding_target_info *main_output_volume_control_target_info; -+ pa_binding_target_info *main_input_volume_control_target_info; -+ pa_binding_target_info *main_output_mute_control_target_info; -+ pa_binding_target_info *main_input_mute_control_target_info; -+ pa_main_volume_context *main_volume_context; -+ -+ bool unlinked; -+}; -+ -+static void context_unlink(struct context *context); -+ -+static const char *model_to_string(enum model model) { -+ switch (model) { -+ case MODEL_NONE: -+ return "none"; -+ -+ case MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT: -+ return "by-active-main-volume-context"; -+ } -+ -+ pa_assert_not_reached(); -+} -+ -+static int model_from_string(const char *str, enum model *model) { -+ pa_assert(str); -+ pa_assert(model); -+ -+ if (pa_streq(str, "none")) -+ *model = MODEL_NONE; -+ else if (pa_streq(str, "by-active-main-volume-context")) -+ *model = MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT; -+ else -+ return -PA_ERR_INVALID; -+ -+ return 0; -+} -+ -+static struct context *context_new(struct userdata *u, const char *name) { -+ struct context *context; -+ -+ pa_assert(u); -+ pa_assert(name); -+ -+ context = pa_xnew0(struct context, 1); -+ context->userdata = u; -+ context->name = pa_xstrdup(name); -+ context->description = pa_xstrdup(name); -+ -+ return context; -+} -+ -+static int context_put(struct context *context) { -+ int r; -+ -+ pa_assert(context); -+ -+ r = pa_main_volume_context_new(context->userdata->main_volume_policy, context->name, context->description, -+ &context->main_volume_context); -+ if (r < 0) -+ goto fail; -+ -+ if (context->main_output_volume_control_target_info) -+ pa_main_volume_context_bind_main_output_volume_control(context->main_volume_context, -+ context->main_output_volume_control_target_info); -+ -+ if (context->main_input_volume_control_target_info) -+ pa_main_volume_context_bind_main_input_volume_control(context->main_volume_context, -+ context->main_input_volume_control_target_info); -+ -+ if (context->main_output_mute_control_target_info) -+ pa_main_volume_context_bind_main_output_mute_control(context->main_volume_context, -+ context->main_output_mute_control_target_info); -+ -+ if (context->main_input_mute_control_target_info) -+ pa_main_volume_context_bind_main_input_mute_control(context->main_volume_context, -+ context->main_input_mute_control_target_info); -+ -+ pa_main_volume_context_put(context->main_volume_context); -+ -+ return 0; -+ -+fail: -+ context_unlink(context); -+ -+ return r; -+} -+ -+static void context_unlink(struct context *context) { -+ pa_assert(context); -+ -+ if (context->unlinked) -+ return; -+ -+ context->unlinked = true; -+ -+ if (context->main_volume_context) { -+ pa_main_volume_context_free(context->main_volume_context); -+ context->main_volume_context = NULL; -+ } -+} -+ -+static void context_free(struct context *context) { -+ pa_assert(context); -+ -+ if (!context->unlinked) -+ context_unlink(context); -+ -+ if (context->main_input_mute_control_target_info) -+ pa_binding_target_info_free(context->main_input_mute_control_target_info); -+ -+ if (context->main_output_mute_control_target_info) -+ pa_binding_target_info_free(context->main_output_mute_control_target_info); -+ -+ if (context->main_input_volume_control_target_info) -+ pa_binding_target_info_free(context->main_input_volume_control_target_info); -+ -+ if (context->main_output_volume_control_target_info) -+ pa_binding_target_info_free(context->main_output_volume_control_target_info); -+ -+ pa_xfree(context->description); -+ pa_xfree(context->name); -+ pa_xfree(context); -+} -+ -+static void context_set_description(struct context *context, const char *description) { -+ pa_assert(context); -+ pa_assert(description); -+ -+ pa_xfree(context->description); -+ context->description = pa_xstrdup(description); -+} -+ -+static void context_set_main_control_target_info(struct context *context, enum control_type type, pa_direction_t direction, -+ pa_binding_target_info *info) { -+ pa_assert(context); -+ -+ switch (type) { -+ case CONTROL_TYPE_VOLUME: -+ if (direction == PA_DIRECTION_OUTPUT) { -+ if (context->main_output_volume_control_target_info) -+ pa_binding_target_info_free(context->main_output_volume_control_target_info); -+ -+ if (info) -+ context->main_output_volume_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_output_volume_control_target_info = NULL; -+ } else { -+ if (context->main_input_volume_control_target_info) -+ pa_binding_target_info_free(context->main_input_volume_control_target_info); -+ -+ if (info) -+ context->main_input_volume_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_input_volume_control_target_info = NULL; -+ } -+ break; -+ -+ case CONTROL_TYPE_MUTE: -+ if (direction == PA_DIRECTION_OUTPUT) { -+ if (context->main_output_mute_control_target_info) -+ pa_binding_target_info_free(context->main_output_mute_control_target_info); -+ -+ if (info) -+ context->main_output_mute_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_output_mute_control_target_info = NULL; -+ } else { -+ if (context->main_input_mute_control_target_info) -+ pa_binding_target_info_free(context->main_input_mute_control_target_info); -+ -+ if (info) -+ context->main_input_mute_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_input_mute_control_target_info = NULL; -+ } -+ break; -+ } -+} -+ -+static pa_hook_result_t active_main_volume_context_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct userdata *u = userdata; -+ pa_main_volume_context *context; -+ pa_volume_api *api; -+ pa_binding_target_info *info = NULL; -+ -+ pa_assert(u); -+ -+ context = u->main_volume_policy->active_main_volume_context; -+ api = u->main_volume_policy->volume_api; -+ -+ if (u->output_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL); -+ pa_volume_api_bind_main_output_volume_control(api, info); -+ } else -+ pa_volume_api_set_main_output_volume_control(api, NULL); -+ } -+ -+ if (u->input_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL); -+ pa_volume_api_bind_main_input_volume_control(api, info); -+ } else -+ pa_volume_api_set_main_input_volume_control(api, NULL); -+ } -+ -+ if (u->output_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL); -+ pa_volume_api_bind_main_output_mute_control(api, info); -+ } else -+ pa_volume_api_set_main_output_mute_control(api, NULL); -+ } -+ -+ if (u->input_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL); -+ pa_volume_api_bind_main_input_mute_control(api, info); -+ } else -+ pa_volume_api_set_main_input_mute_control(api, NULL); -+ } -+ -+ if (info) -+ pa_binding_target_info_free(info); -+ -+ return PA_HOOK_OK; -+} -+ -+static int parse_model(pa_config_parser_state *state) { -+ int r; -+ -+ pa_assert(state); -+ -+ r = model_from_string(state->rvalue, state->data); -+ if (r < 0) -+ pa_log("[%s:%u] Failed to parse model: %s", state->filename, state->lineno, state->rvalue); -+ -+ return r; -+} -+ -+static int parse_main_volume_contexts(pa_config_parser_state *state) { -+ struct userdata *u; -+ char *name; -+ const char *split_state = NULL; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ while ((name = pa_split_spaces(state->rvalue, &split_state))) -+ pa_hashmap_put(u->context_names, name, name); -+ -+ return 0; -+} -+ -+static struct context *get_context(struct userdata *u, const char *section) { -+ const char *name; -+ struct context *context; -+ -+ pa_assert(u); -+ -+ if (!section) -+ return NULL; -+ -+ if (!pa_startswith(section, "MainVolumeContext ")) -+ return NULL; -+ -+ name = section + 18; -+ -+ context = pa_hashmap_get(u->unused_contexts, name); -+ if (!context) { -+ context = context_new(u, name); -+ pa_hashmap_put(u->unused_contexts, context->name, context); -+ } -+ -+ return context; -+} -+ -+static int parse_description(pa_config_parser_state *state) { -+ struct userdata *u; -+ struct context *context; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ context = get_context(u, state->section); -+ if (!context) { -+ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, -+ pa_strnull(state->section)); -+ return -PA_ERR_INVALID; -+ } -+ -+ context_set_description(context, state->rvalue); -+ -+ return 0; -+} -+ -+static const char *get_target_field_name(enum control_type type) { -+ switch (type) { -+ case CONTROL_TYPE_VOLUME: -+ return "volume_control"; -+ -+ case CONTROL_TYPE_MUTE: -+ return "mute_control"; -+ } -+ -+ pa_assert_not_reached(); -+} -+ -+static int parse_main_control(pa_config_parser_state *state, enum control_type type, pa_direction_t direction) { -+ struct userdata *u; -+ struct context *context; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ context = get_context(u, state->section); -+ if (!context) { -+ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, -+ pa_strnull(state->section)); -+ return -PA_ERR_INVALID; -+ } -+ -+ if (pa_streq(state->rvalue, "none")) -+ context_set_main_control_target_info(context, type, direction, NULL); -+ else if (pa_startswith(state->rvalue, "bind:")) { -+ int r; -+ pa_binding_target_info *info; -+ -+ r = pa_binding_target_info_new_from_string(state->rvalue, get_target_field_name(type), &info); -+ if (r < 0) { -+ pa_log("[%s:%u] Failed to parse binding target \"%s\".", state->filename, state->lineno, state->rvalue); -+ return r; -+ } -+ -+ context_set_main_control_target_info(context, type, direction, info); -+ pa_binding_target_info_free(info); -+ } else { -+ pa_log("[%s:%u] Failed to parse value \"%s\".", state->filename, state->lineno, state->rvalue); -+ return -PA_ERR_INVALID; -+ } -+ -+ return 0; -+} -+ -+static int parse_main_output_volume_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_OUTPUT); -+} -+ -+static int parse_main_input_volume_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_INPUT); -+} -+ -+static int parse_main_output_mute_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_OUTPUT); -+} -+ -+static int parse_main_input_mute_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_INPUT); -+} -+ -+static void finalize_config(struct userdata *u) { -+ const char *context_name; -+ void *state; -+ struct context *context; -+ -+ pa_assert(u); -+ -+ PA_HASHMAP_FOREACH(context_name, u->context_names, state) { -+ int r; -+ -+ context = pa_hashmap_remove(u->unused_contexts, context_name); -+ if (!context) -+ context = context_new(u, context_name); -+ -+ r = context_put(context); -+ if (r < 0) { -+ pa_log_warn("Failed to create main volume context %s.", context_name); -+ context_free(context); -+ continue; -+ } -+ -+ pa_assert_se(pa_hashmap_put(u->contexts, context->name, context) >= 0); -+ } -+ -+ PA_HASHMAP_FOREACH(context, u->unused_contexts, state) -+ pa_log_debug("Main volume context %s is not used.", context->name); -+ -+ pa_hashmap_free(u->unused_contexts); -+ u->unused_contexts = NULL; -+ -+ pa_hashmap_free(u->context_names); -+ u->context_names = NULL; -+} -+ -+int pa__init(pa_module *module) { -+ struct userdata *u; -+ FILE *f; -+ char *fn = NULL; -+ -+ pa_assert(module); -+ -+ u = module->userdata = pa_xnew0(struct userdata, 1); -+ u->main_volume_policy = pa_main_volume_policy_get(module->core); -+ u->output_volume_model = MODEL_NONE; -+ u->input_volume_model = MODEL_NONE; -+ u->output_mute_model = MODEL_NONE; -+ u->input_mute_model = MODEL_NONE; -+ u->contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, -+ (pa_free_cb_t) context_free); -+ u->active_main_volume_context_changed_slot = -+ pa_hook_connect(&u->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], -+ PA_HOOK_NORMAL, active_main_volume_context_changed_cb, u); -+ u->context_names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); -+ u->unused_contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, -+ (pa_free_cb_t) context_free); -+ -+ f = pa_open_config_file(PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "main-volume-policy.conf", "main-volume-policy.conf", NULL, &fn); -+ if (f) { -+ pa_config_item config_items[] = { -+ { "output-volume-model", parse_model, &u->output_volume_model, "General" }, -+ { "input-volume-model", parse_model, &u->input_volume_model, "General" }, -+ { "output-mute-model", parse_model, &u->output_mute_model, "General" }, -+ { "input-mute-model", parse_model, &u->input_mute_model, "General" }, -+ { "main-volume-contexts", parse_main_volume_contexts, NULL, "General" }, -+ { "description", parse_description, NULL, NULL }, -+ { "main-output-volume-control", parse_main_output_volume_control, NULL, NULL }, -+ { "main-input-volume-control", parse_main_input_volume_control, NULL, NULL }, -+ { "main-output-mute-control", parse_main_output_mute_control, NULL, NULL }, -+ { "main-input-mute-control", parse_main_input_mute_control, NULL, NULL }, -+ { NULL }, -+ }; -+ -+ pa_config_parse(fn, f, config_items, NULL, u); -+ pa_xfree(fn); -+ fn = NULL; -+ fclose(f); -+ f = NULL; -+ } -+ -+ finalize_config(u); -+ -+ pa_log_debug("Output volume model: %s", model_to_string(u->output_volume_model)); -+ pa_log_debug("Input volume model: %s", model_to_string(u->input_volume_model)); -+ pa_log_debug("Output mute model: %s", model_to_string(u->output_mute_model)); -+ pa_log_debug("Input mute model: %s", model_to_string(u->input_mute_model)); -+ -+ return 0; -+} -+ -+void pa__done(pa_module *module) { -+ struct userdata *u; -+ -+ pa_assert(module); -+ -+ u = module->userdata; -+ if (!u) -+ return; -+ -+ if (u->active_main_volume_context_changed_slot) -+ pa_hook_slot_free(u->active_main_volume_context_changed_slot); -+ -+ if (u->contexts) -+ pa_hashmap_free(u->contexts); -+ -+ if (u->main_volume_policy) -+ pa_main_volume_policy_unref(u->main_volume_policy); -+ -+ pa_xfree(u); -+} --- -2.1.4 - ---- a/po/POTFILES.in 2016-04-14 13:03:50.715006116 +0200 -+++ b/po/POTFILES.in 2016-04-14 13:04:23.097006062 +0200 -@@ -200,3 +200,4 @@ - src/utils/pax11publish.c - src/modules/volume-api/device-creator.c - src/pulse/ext-volume-api.c -+src/modules/main-volume-policy/module-main-volume-policy.c -- cgit 1.2.3-korg