[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid.spec
^
|
|
[-]
[+]
|
Deleted |
_service:tar_git:pulseaudio-modules-droid-11.1.68.tar.bz2/src/common/droid-util.h
^
|
@@ -1,456 +0,0 @@
-#ifndef foodroidutilfoo
-#define foodroidutilfoo
-
-/*
- * Copyright (C) 2013 Jolla Ltd.
- *
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
- *
- * These PulseAudio Modules are 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
- * version 2.1 of the License.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <pulsecore/core-util.h>
-#include <pulsecore/macro.h>
-#include <pulsecore/mutex.h>
-#include <pulsecore/strlist.h>
-#include <pulsecore/atomic.h>
-
-#include <android-config.h>
-
-#if !defined(ANDROID_VERSION_MAJOR) || !defined(ANDROID_VERSION_MINOR) || !defined(ANDROID_VERSION_PATCH)
-#error "ANDROID_VERSION_* not defined. Did you get your headers via extract-headers.sh?"
-#endif
-
-#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 1
-#include "droid-util-41qc.h"
-#else
-#include "droid-util-audio.h"
-#endif
-
-/* We currently support API version up-to 3.0 */
-#define DROID_API_VERSION_SUPPORT HARDWARE_DEVICE_API_VERSION(3, 0)
-
-#if AUDIO_DEVICE_API_VERSION_CURRENT > DROID_API_VERSION_SUPPORT
-#warning Compiling against higher audio device API version than currently supported!
-#warning Compile likely fails or module may malfunction.
-#endif
-
-#define AUDIO_API_VERSION_MAJ ((AUDIO_DEVICE_API_VERSION_CURRENT >> 8) & 0xff)
-#define AUDIO_API_VERSION_MIN (AUDIO_DEVICE_API_VERSION_CURRENT & 0xff)
-
-#define AUDIO_API_VERSION_GET_MAJ(x) ((x >> 8) & 0xff)
-#define AUDIO_API_VERSION_GET_MIN(x) (x & 0xff)
-
-#if defined(QCOM_BSP) && (AUDIO_API_VERSION_MAJ >= 3)
-#define DROID_AUDIO_HAL_USE_VSID
-#endif
-
-#define PROP_DROID_DEVICES "droid.devices"
-#define PROP_DROID_FLAGS "droid.flags"
-#define PROP_DROID_HW_MODULE "droid.hw_module"
-#define PROP_DROID_API_STRING "droid-hal"
-
-#define PROP_DROID_OUTPUT_PRIMARY "droid.output.primary"
-#define PROP_DROID_OUTPUT_LOW_LATENCY "droid.output.low_latency"
-#define PROP_DROID_OUTPUT_MEDIA_LATENCY "droid.output.media_latency"
-#define PROP_DROID_OUTPUT_OFFLOAD "droid.output.offload"
-#define PROP_DROID_INPUT_BUILTIN "droid.input.builtin"
-#define PROP_DROID_INPUT_EXTERNAL "droid.input.external"
-
-#define PA_DROID_PRIMARY_DEVICE "primary"
-
-typedef struct pa_droid_hw_module pa_droid_hw_module;
-typedef struct pa_droid_stream pa_droid_stream;
-typedef struct pa_droid_output_stream pa_droid_output_stream;
-typedef struct pa_droid_input_stream pa_droid_input_stream;
-typedef struct pa_droid_card_data pa_droid_card_data;
-typedef int (*common_set_parameters_cb_t)(pa_droid_card_data *card_data, const char *str);
-
-typedef struct pa_droid_config_audio pa_droid_config_audio;
-typedef struct pa_droid_config_hw_module pa_droid_config_hw_module;
-
-typedef struct pa_droid_quirks pa_droid_quirks;
-
-typedef enum pa_droid_hook {
- PA_DROID_HOOK_INPUT_CHANNEL_MAP_CHANGED, /* Call data: pa_droid_stream */
- PA_DROID_HOOK_INPUT_BUFFER_SIZE_CHANGED, /* Call data: pa_droid_stream */
- PA_DROID_HOOK_MAX
-} pa_droid_hook_t;
-
-
-struct pa_droid_hw_module {
- PA_REFCNT_DECLARE;
-
- pa_core *core;
- char *shared_name;
-
- pa_droid_config_audio *config;
- const pa_droid_config_hw_module *enabled_module;
- pa_mutex *hw_mutex;
- pa_mutex *output_mutex;
- pa_mutex *input_mutex;
-
- struct hw_module_t *hwmod;
- audio_hw_device_t *device;
-
- const char *module_id;
-
- uint32_t stream_out_id;
- uint32_t stream_in_id;
-
- pa_idxset *outputs;
- pa_idxset *inputs;
- pa_hook_slot *sink_put_hook_slot;
- pa_hook_slot *sink_unlink_hook_slot;
- pa_hook_slot *source_put_hook_slot;
- pa_hook_slot *source_unlink_hook_slot;
-
- pa_atomic_t active_outputs;
-
- pa_droid_quirks *quirks;
- pa_hook hooks[PA_DROID_HOOK_MAX];
-};
-
-struct pa_droid_output_stream {
- struct audio_stream_out *stream;
- pa_sample_spec sample_spec;
- pa_channel_map channel_map;
- uint32_t flags;
- uint32_t device;
-};
-
-struct pa_droid_input_stream {
- struct audio_stream_in *stream;
- pa_sample_spec sample_spec;
- pa_channel_map channel_map;
- pa_sample_spec input_sample_spec;
- pa_channel_map input_channel_map;
- uint32_t flags;
- uint32_t device;
- audio_devices_t all_devices;
- bool merged;
-};
-
-struct pa_droid_stream {
- PA_REFCNT_DECLARE;
-
- pa_droid_hw_module *module;
- size_t buffer_size;
- void *data;
-
- pa_droid_output_stream *output;
- pa_droid_input_stream *input;
-};
-
-struct pa_droid_card_data {
- void *userdata;
- /* General functions */
- char *module_id;
- common_set_parameters_cb_t set_parameters;
-};
-
-#define AUDIO_MAX_SAMPLING_RATES (32)
-
-typedef struct pa_droid_config_global {
- uint32_t audio_hal_version;
- audio_devices_t attached_output_devices;
- audio_devices_t default_output_device;
- audio_devices_t attached_input_devices;
-} pa_droid_config_global;
-
-typedef struct pa_droid_config_output {
- const pa_droid_config_hw_module *module;
-
- char *name;
- uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]; /* (uint32_t) -1 -> dynamic */
- audio_channel_mask_t channel_masks; /* 0 -> dynamic */
- audio_format_t formats; /* 0 -> dynamic */
- audio_devices_t devices;
- audio_output_flags_t flags;
-
- struct pa_droid_config_output *next;
-} pa_droid_config_output;
-
-typedef struct pa_droid_config_input {
- const pa_droid_config_hw_module *module;
-
- char *name;
- uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]; /* (uint32_t) -1 -> dynamic */
- audio_channel_mask_t channel_masks; /* 0 -> dynamic */
- audio_format_t formats; /* 0 -> dynamic */
- audio_devices_t devices;
-#if AUDIO_API_VERSION_MAJ >= 3
- audio_input_flags_t flags;
-#endif
-
- struct pa_droid_config_input *next;
-} pa_droid_config_input;
-
-struct pa_droid_config_hw_module {
- const pa_droid_config_audio *config;
-
- char *name;
- /* If global config is not defined for module, use root global config. */
- pa_droid_config_global *global_config;
- pa_droid_config_output *outputs;
- pa_droid_config_input *inputs;
-
- struct pa_droid_config_hw_module *next;
-};
-
-struct pa_droid_config_audio {
- pa_droid_config_global *global_config;
- pa_droid_config_hw_module *hw_modules;
-};
-
-
-/* Profiles */
-
-typedef struct pa_droid_profile_set pa_droid_profile_set;
-typedef struct pa_droid_mapping pa_droid_mapping;
-
-typedef struct pa_droid_port_data {
- audio_devices_t device;
-} pa_droid_port_data;
-
-typedef struct pa_droid_port {
- pa_droid_mapping *mapping;
-
- audio_devices_t device;
- char *name;
- char *description;
- unsigned priority;
-} pa_droid_port;
-
-struct pa_droid_mapping {
- pa_droid_profile_set *profile_set;
-
- const pa_droid_config_output *output;
- const pa_droid_config_input *input;
- const pa_droid_config_input *input2;
-
- char *name;
- char *description;
- unsigned priority;
- pa_proplist *proplist;
-
- /* Mapping doesn't own the ports */
- pa_idxset *ports;
-
- pa_direction_t direction;
-
- pa_sink *sink;
- pa_source *source;
-};
-
-typedef struct pa_droid_profile {
- pa_droid_profile_set *profile_set;
-
- const pa_droid_config_hw_module *module;
-
- char *name;
- char *description;
- unsigned priority;
-
- /* Idxsets contain pa_droid_mapping objects.
- * Profile doesn't own the mappings. */
- pa_idxset *output_mappings;
- pa_idxset *input_mappings;
-
-} pa_droid_profile;
-
-struct pa_droid_profile_set {
- const pa_droid_config_audio *config;
-
- pa_hashmap *all_ports;
- pa_hashmap *output_mappings;
- pa_hashmap *input_mappings;
- pa_hashmap *profiles;
-};
-
-#define PA_DROID_OUTPUT_PARKING "output-parking"
-#define PA_DROID_INPUT_PARKING "input-parking"
-
-enum pa_droid_quirk_type {
- QUIRK_INPUT_ATOI,
- QUIRK_SET_PARAMETERS,
- QUIRK_CLOSE_INPUT,
- QUIRK_UNLOAD_NO_CLOSE,
- QUIRK_NO_HW_VOLUME,
- QUIRK_OUTPUT_MAKE_WRITABLE,
- QUIRK_REALCALL,
- QUIRK_COUNT
-};
-
-struct pa_droid_quirks {
- bool enabled[QUIRK_COUNT];
-};
-
-/* Open hardware module */
-/* 'config' can be NULL if it is assumed that hw module with module_id already is open. */
-/* if opening of hw_module succeeds, config ownership is transferred to hw_module and config
- * shouldn't be freed. */
-pa_droid_hw_module *pa_droid_hw_module_get(pa_core *core, pa_droid_config_audio *config, const char *module_id);
-pa_droid_hw_module *pa_droid_hw_module_ref(pa_droid_hw_module *hw);
-void pa_droid_hw_module_unref(pa_droid_hw_module *hw);
-
-void pa_droid_hw_module_lock(pa_droid_hw_module *hw);
-bool pa_droid_hw_module_try_lock(pa_droid_hw_module *hw);
-void pa_droid_hw_module_unlock(pa_droid_hw_module *hw);
-
-bool pa_droid_quirk_parse(pa_droid_hw_module *hw, const char *quirks);
-void pa_droid_quirk_log(pa_droid_hw_module *hw);
-
-static inline bool pa_droid_quirk(pa_droid_hw_module *hw, enum pa_droid_quirk_type quirk) {
- return hw->quirks && hw->quirks->enabled[quirk];
-}
-
-/* Conversion helpers */
-typedef enum {
- CONV_FROM_PA,
- CONV_FROM_HAL
-} pa_conversion_field_t;
-
-bool pa_convert_output_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
-bool pa_convert_input_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
-bool pa_convert_format(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
-
-bool pa_string_convert_output_device_num_to_str(audio_devices_t value, const char **to_str);
-bool pa_string_convert_output_device_str_to_num(const char *str, audio_devices_t *to_value);
-bool pa_string_convert_input_device_num_to_str(audio_devices_t value, const char **to_str);
-bool pa_string_convert_input_device_str_to_num(const char *str, audio_devices_t *to_value);
-
-bool pa_string_convert_flag_num_to_str(audio_output_flags_t value, const char **to_str);
-bool pa_string_convert_flag_str_to_num(const char *str, audio_output_flags_t *to_value);
-
-char *pa_list_string_output_device(audio_devices_t devices);
-char *pa_list_string_input_device(audio_devices_t devices);
-char *pa_list_string_flags(audio_output_flags_t flags);
-
-/* Get default audio source associated with input device.
- * Return true if default source was found, false if not. */
-bool pa_input_device_default_audio_source(audio_devices_t input_device, audio_source_t *default_source);
-
-/* Config parser */
-bool pa_parse_droid_audio_config(const char *filename, pa_droid_config_audio *config);
-pa_droid_config_audio *pa_droid_config_load(pa_modargs *ma);
-
-const pa_droid_config_output *pa_droid_config_find_output(const pa_droid_config_hw_module *module, const char *name);
-const pa_droid_config_input *pa_droid_config_find_input(const pa_droid_config_hw_module *module, const char *name);
-const pa_droid_config_hw_module *pa_droid_config_find_module(const pa_droid_config_audio *config, const char* module_id);
-
-
-/* Profiles */
-pa_droid_profile_set *pa_droid_profile_set_new(const pa_droid_config_hw_module *module);
-pa_droid_profile_set *pa_droid_profile_set_default_new(const pa_droid_config_hw_module *module,
- bool merge_inputs);
-void pa_droid_profile_set_free(pa_droid_profile_set *ps);
-
-void pa_droid_profile_add_mapping(pa_droid_profile *p, pa_droid_mapping *am);
-void pa_droid_profile_free(pa_droid_profile *p);
-
-pa_droid_mapping *pa_droid_mapping_get(pa_droid_profile_set *ps, pa_direction_t direction, const void *data);
-pa_droid_mapping *pa_droid_mapping_merged_get(pa_droid_profile_set *ps,
- const pa_droid_config_input *input1,
- const pa_droid_config_input *input2);
-bool pa_droid_mapping_is_primary(pa_droid_mapping *am);
-/* Go through idxset containing pa_droid_mapping objects and if primary output or input
- * mapping is found, return pointer to that mapping. */
-pa_droid_mapping *pa_droid_idxset_get_primary(pa_idxset *i);
-pa_droid_mapping *pa_droid_idxset_mapping_with_device(pa_idxset *i, uint32_t flag);
-void pa_droid_mapping_free(pa_droid_mapping *am);
-
-/* Add ports from sinks/sources.
- * May be called multiple times for one sink/source. */
-void pa_droid_add_ports(pa_hashmap *ports, pa_droid_mapping *am, pa_card *card);
-/* Add ports from card.
- * May be called multiple times for one card profile. */
-void pa_droid_add_card_ports(pa_card_profile *cp, pa_hashmap *ports, pa_droid_mapping *am, pa_core *core);
-
-/* Pretty port names */
-bool pa_droid_output_port_name(audio_devices_t value, const char **to_str);
-bool pa_droid_input_port_name(audio_devices_t value, const char **to_str);
-
-/* Pretty audio source names */
-bool pa_droid_audio_source_name(audio_source_t value, const char **to_str);
-
-pa_hook *pa_droid_hooks(pa_droid_hw_module *hw);
-
-/* Module operations */
-int pa_droid_set_parameters(pa_droid_hw_module *hw, const char *parameters);
-
-/* Stream operations */
-pa_droid_stream *pa_droid_stream_ref(pa_droid_stream *s);
-void pa_droid_stream_unref(pa_droid_stream *s);
-
-int pa_droid_stream_set_parameters(pa_droid_stream *s, const char *parameters);
-
-/* Output stream operations */
-pa_droid_stream *pa_droid_open_output_stream(pa_droid_hw_module *module,
- const pa_sample_spec *spec,
- const pa_channel_map *map,
- audio_output_flags_t flags,
- audio_devices_t devices);
-
-/* Set routing to the input or output stream, with following side-effects:
- * Output:
- * - if routing is set to primary output stream, set routing to all other
- * open streams as well
- * - if routing is set to non-primary stream and primary stream exists, do nothing
- * - if routing is set to non-primary stream and primary stream doesn't exist, set routing
- * Input:
- * - buffer size or channel count may change
- */
-int pa_droid_stream_set_route(pa_droid_stream *s, audio_devices_t device);
-
-/* Input stream operations */
-pa_droid_stream *pa_droid_open_input_stream(pa_droid_hw_module *module,
- const pa_sample_spec *spec,
- const pa_channel_map *map,
- audio_devices_t devices,
- pa_droid_mapping *am);
-
-bool pa_droid_stream_is_primary(pa_droid_stream *s);
-
-int pa_droid_stream_suspend(pa_droid_stream *s, bool suspend);
-
-size_t pa_droid_stream_buffer_size(pa_droid_stream *s);
-pa_usec_t pa_droid_stream_get_latency(pa_droid_stream *s);
-
-static inline int pa_droid_output_stream_any_active(pa_droid_stream *s) {
- return pa_atomic_load(&s->module->active_outputs);
-}
-
-static inline ssize_t pa_droid_stream_write(pa_droid_stream *stream, const void *buffer, size_t bytes) {
- return stream->output->stream->write(stream->output->stream, buffer, bytes);
-}
-
-static inline ssize_t pa_droid_stream_read(pa_droid_stream *stream, void *buffer, size_t bytes) {
- return stream->input->stream->read(stream->input->stream, buffer, bytes);
-}
-
-void pa_droid_stream_set_data(pa_droid_stream *s, void *data);
-void *pa_droid_stream_get_data(pa_droid_stream *s);
-bool pa_sink_is_droid_sink(pa_sink *sink);
-bool pa_source_is_droid_source(pa_source *source);
-
-/* Misc */
-size_t pa_droid_buffer_size_round_up(size_t buffer_size, size_t block_size);
-
-#endif
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/README
^
|
@@ -14,6 +14,7 @@
* 5.x
* 6.0.x
* 7.x
+ * 8.x
Headers for defining devices and strings for different droid versions are in
src/common/droid-util-audio.h (legacy headers for Jolla 1 in droid-util-41qc.h).
@@ -49,6 +50,35 @@
Components
==========
+common
+------
+
+The common part of PulseAudio Droid modules contains library for handling
+most operations towards audio HAL.
+
+### Audio policy configuration parsing
+
+To populate our configuration structs there exists two parsers, legacy parser
+for old .conf format present in Android versions 7.0 and older and new xml
+format present from version 7.0 upwards. The legacy format is obsoleted in
+version 7.0 but by default still in use and most 7.0 adaptations probably
+contain the legacy format. But 8.0 adaptations and up start to include only
+the new style xml format configuration files.
+
+### Configuration files
+
+By default new style xml format is tried first and if it is not found old
+config is read next. If the configuration is in non-default location for
+some reason "config" module argument (available for all modules, card, sink,
+and source) can be used to point to the configuration file location.
+
+By default files are tried in following order,
+
+ /vendor/etc/audio_policy_configuration.xml (new xml format)
+ /vendor/etc/audio_policy.conf (legacy format)
+ /system/etc/audio_policy_configuration.xml (new xml format)
+ /system/etc/audio_policy.conf (legacy format)
+
module-droid-card
-----------------
@@ -56,11 +86,6 @@
configuration, creates profiles and loads sinks and sources based on the
selected profile.
-Droid-card reads configuration from /vendor/etc/audio_policy.conf or
-/system/etc/audio_policy.conf, depending on which is found first. If vendor
-config is found, configuration is read from there, otherwise from system
-configuration.
-
default profile
---------------
@@ -301,6 +326,11 @@
doing voicecall routing. If there is no voicecall audio you can
try enabling this quirk so that the realcall parameter is applied
when switching to voicecall profile.
+ * unload_call_exit
+ * Disabled by default.
+ * Some HAL module implementations get stuck in mutex or segfault when
+ trying to unload the module. To avoid confusing segfaults call
+ exit(0) instead of calling unload for the module.
For example, to disable input_atoi and enable close_input quirks, use module
argument
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/configure.ac
^
|
@@ -187,6 +187,25 @@
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
+#### expat (for xml config format parsing) (optional) ####
+
+AC_ARG_ENABLE([xml],
+ AS_HELP_STRING([--disable-xml],[Disable optional xml config support]))
+
+AS_IF([test "x$enable_xml" != "xno"],
+ [PKG_CHECK_MODULES(EXPAT, [ expat >= 2.1 ], HAVE_EXPAT=1, HAVE_EXPAT=0)],
+ HAVE_EXPAT=0)
+
+AS_IF([test "x$enable_xml" = "xyes" && test "x$HAVE_EXPAT" = "x0"],
+ [AC_MSG_ERROR([*** expat not found])])
+
+AC_SUBST(HAVE_EXPAT)
+AC_SUBST(EXPAT_CFLAGS)
+AC_SUBST(EXPAT_LIBS)
+AM_CONDITIONAL([HAVE_EXPAT], [test "x$HAVE_EXPAT" = x1])
+AS_IF([test "x$HAVE_EXPAT" = "x1"], AC_DEFINE([HAVE_EXPAT], 1, [Have expat?]))
+AS_IF([test "x$HAVE_EXPAT" = "x1"], ENABLE_XML="yes (expat)", ENABLE_XML=no)
+
# Output devices
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_OUT_HDMI])
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_OUT_HDMI_ARC])
@@ -277,6 +296,12 @@
AC_SUBST([DROID_DEVICE_CFLAGS])
fi
+# Workaround for SBJ HAL headers
+if test "x$droiddevice" = xsbj ; then
+ SBJ_DEVICE_LDFLAGS="-Wl,--allow-multiple-definition"
+ AC_SUBST([SBJ_DEVICE_LDFLAGS])
+fi
+
AC_MSG_CHECKING([If we are using hardfp tool chain])
case `echo | gcc -v -xc -o - - 2>&1 | grep COLLECT_GCC_OPTIONS | tail -1` in
*float-abi=hard*) hardfp=yes; AC_MSG_RESULT([yes]) ;;
@@ -309,5 +334,6 @@
prefix: ${prefix}
modules directory: ${modlibexecdir}
- Droid device ${droiddevice}
+ Droid device: ${droiddevice}
+ XML config support: ${ENABLE_XML}
"
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/Makefile.am
^
|
@@ -1,18 +1,35 @@
AM_LIBADD = \
$(PULSEAUDIO_LIBS) \
- $(HYBRIS_LIBS)
+ $(HYBRIS_LIBS) \
+ $(EXPAT_LIBS)
AM_CFLAGS = \
$(DROID_DEVICE_CFLAGS) \
$(PULSEAUDIO_CFLAGS) \
$(DROIDHEADERS_CFLAGS) \
$(HYBRIS_CFLAGS) \
+ $(EXPAT_CFLAGS) \
-DPULSEAUDIO_VERSION=@PA_MAJOR@ \
- -I$(top_srcdir)/src/common
+ -I$(top_srcdir)/src/common \
+ -I$(top_srcdir)/src/common/include
modlibexec_LTLIBRARIES = libdroid-util.la
+includedir = @includedir@/pulsecore/modules/droid
+include_HEADERS = include/droid/version.h \
+ include/droid/conversion.h \
+ include/droid/droid-config.h \
+ include/droid/droid-util.h
-libdroid_util_la_SOURCES = droid-util.c droid-util.h
-libdroid_util_la_LDFLAGS = -avoid-version -Wl,-z,noexecstack -lhybris-common
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libdroid-util.pc
+
+libdroid_util_la_SOURCES = droid-util.c \
+ droid-config.c \
+ conversion.c \
+ config-parser-legacy.c \
+ config-parser-xml.c \
+ droid-util-audio.h \
+ droid-util-41qc.h
+libdroid_util_la_LDFLAGS = -avoid-version -Wl,-z,noexecstack -lhybris-common $(SBJ_DEVICE_LDFLAGS)
libdroid_util_la_LIBADD = $(AM_LIBADD)
libdroid_util_la_CFLAGS = $(AM_CFLAGS)
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/config-parser-legacy.c
^
|
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdbool.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/log.h>
+#include <pulse/xmalloc.h>
+
+#include <hardware_legacy/audio_policy_conf.h>
+
+#include "droid/version.h"
+#include "droid/droid-config.h"
+#include "droid/conversion.h"
+#include "droid/sllist.h"
+
+/* Section defining custom global configuration variables. */
+#define GLOBAL_CONFIG_EXT_TAG "custom_properties"
+
+#define GAIN_TAG_PREFIX "gain_"
+
+#define MAX_LINE_LENGTH (1024)
+#define WHITESPACE "\n\r \t"
+
+static void log_parse_error(const char *fn, const unsigned ln, const char *section, const char *v) {
+ pa_log("[%s:%u] failed to parse line in section %s: unknown section (%s)", fn, ln, section, v);
+}
+
+pa_droid_config_audio *pa_parse_droid_audio_config_legacy(const char *filename) {
+ pa_droid_config_audio *config = NULL;
+ FILE *f;
+ unsigned n = 0;
+ bool ret = true;
+ char *full_line = NULL;
+ uint32_t hw_module_count = 0;
+
+ enum config_loc {
+ IN_ROOT = 0,
+ IN_GLOBAL = 1,
+ IN_GLOBAL_EXT = 2,
+ IN_HW_MODULES = 3,
+ IN_MODULE = 4,
+ IN_OUTPUT_INPUT = 5,
+ IN_CONFIG = 6,
+ IN_MODULE_GLOBAL = 10,
+ IN_DEVICES = 20,
+ IN_DEVICES_DEVICE = 21,
+ IN_GAINS = 22,
+ IN_GAIN_N = 23
+ } loc = IN_ROOT;
+
+ bool in_output = true;
+
+ pa_droid_config_hw_module *module = NULL;
+ pa_droid_config_device *output = NULL;
+ pa_droid_config_device *input = NULL;
+
+ pa_assert(filename);
+
+ f = fopen(filename, "r");
+
+ if (!f) {
+ pa_log_info("Failed to open config file (%s): %s", filename, pa_cstrerror(errno));
+ ret = false;
+ goto finish;
+ }
+
+ config = pa_xnew0(pa_droid_config_audio, 1);
+ config->global_config = pa_xnew0(pa_droid_config_global, 1);
+
+ pa_lock_fd(fileno(f), 1);
+
+ full_line = pa_xmalloc0(sizeof(char) * MAX_LINE_LENGTH);
+
+ while (!feof(f)) {
+ char *ln, *d, *v, *value;
+
+ if (!fgets(full_line, MAX_LINE_LENGTH, f))
+ break;
+
+ n++;
+
+ pa_strip_nl(full_line);
+
+ if (!*full_line)
+ continue;
+
+ ln = full_line + strspn(full_line, WHITESPACE);
+
+ if (ln[0] == '#')
+ continue;
+
+ v = ln;
+ d = v + strcspn(v, WHITESPACE);
+
+ value = d + strspn(d, WHITESPACE);
+ d[0] = '\0';
+ d = value + strcspn(value, WHITESPACE);
+ d[0] = '\0';
+
+ /* Enter section */
+ if (pa_streq(value, "{")) {
+
+ if (!*v) {
+ pa_log("[%s:%u] failed to parse line - too few words", filename, n);
+ goto finish;
+ }
+
+ switch (loc) {
+ case IN_ROOT:
+ if (pa_streq(v, GLOBAL_CONFIG_TAG)) {
+ loc = IN_GLOBAL;
+ }
+ else if (pa_streq(v, AUDIO_HW_MODULE_TAG))
+ loc = IN_HW_MODULES;
+ else {
+ log_parse_error(filename, n, "<root>", v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ case IN_GLOBAL:
+ if (pa_streq(v, GLOBAL_CONFIG_EXT_TAG))
+ loc = IN_GLOBAL_EXT;
+ else {
+ log_parse_error(filename, n, GLOBAL_CONFIG_TAG, v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ case IN_HW_MODULES:
+ pa_assert(!module);
+
+ module = pa_droid_config_hw_module_new(config, v);
+ SLLIST_APPEND(pa_droid_config_hw_module, config->hw_modules, module);
+ hw_module_count++;
+ loc = IN_MODULE;
+ pa_log_debug("config: New module: %s", module->name);
+ break;
+
+ case IN_MODULE:
+ pa_assert(module);
+
+ if (pa_streq(v, OUTPUTS_TAG)) {
+ loc = IN_OUTPUT_INPUT;
+ in_output = true;
+ } else if (pa_streq(v, INPUTS_TAG)) {
+ loc = IN_OUTPUT_INPUT;
+ in_output = false;
+ } else if (pa_streq(v, GLOBAL_CONFIG_TAG)) {
+ loc = IN_MODULE_GLOBAL;
+ } else if (pa_streq(v, DEVICES_TAG)) {
+ loc = IN_DEVICES;
+ } else {
+ log_parse_error(filename, n, module->name, v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ case IN_OUTPUT_INPUT:
+ pa_assert(module);
+
+ if (in_output) {
+ output = pa_droid_config_device_new(module, PA_DIRECTION_OUTPUT, v);
+ SLLIST_APPEND(pa_droid_config_device, module->outputs, output);
+ loc = IN_CONFIG;
+ pa_log_debug("config: %s: New output: %s", module->name, output->name);
+ } else {
+ input = pa_droid_config_device_new(module, PA_DIRECTION_INPUT, v);
+ SLLIST_APPEND(pa_droid_config_device, module->inputs, input);
+ loc = IN_CONFIG;
+ pa_log_debug("config: %s: New input: %s", module->name, input->name);
+ }
+ break;
+
+ case IN_DEVICES:
+ /* TODO Missing implementation of parsing the module/devices section.
+ * As of now there is no need for the information, fix this when that
+ * changes. */
+ loc = IN_DEVICES_DEVICE;
+ break;
+
+ case IN_DEVICES_DEVICE:
+ if (pa_streq(v, GAINS_TAG))
+ loc = IN_GAINS;
+ else {
+ log_parse_error(filename, n, DEVICES_TAG, v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ case IN_GAINS:
+ /* TODO Missing implementation of parsing the gain_n section.
+ * As of now there is no need for the information, fix this when that
+ * changes. */
+ if (pa_startswith(v, GAIN_TAG_PREFIX))
+ loc = IN_GAIN_N;
+ else {
+ log_parse_error(filename, n, GAINS_TAG, v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ case IN_CONFIG:
+ if (pa_streq(v, GAINS_TAG)) {
+ loc = IN_GAINS;
+ } else {
+ log_parse_error(filename, n, in_output ? output->name : input->name, v);
+ ret = false;
+ goto finish;
+ }
+ break;
+
+ default:
+ pa_log("[%s:%u] failed to parse line: unknown section (%s)", filename, n, v);
+ ret = false;
+ goto finish;
+ }
+
+ continue;
+ }
+
+ /* Exit section */
+ if (pa_streq(v, "}")) {
+ switch (loc) {
+ case IN_ROOT:
+ pa_log("[%s:%u] failed to parse line - extra closing bracket", filename, n);
+ ret = false;
+ goto finish;
+
+ case IN_HW_MODULES:
+ /* fall through */
+ case IN_GLOBAL:
+ loc = IN_ROOT;
+ break;
+
+ case IN_MODULE:
+ module = NULL;
+ loc = IN_HW_MODULES;
+ break;
+
+ case IN_DEVICES:
+ /* fall through */
+ case IN_MODULE_GLOBAL:
+ loc = IN_MODULE;
+ break;
+
+ case IN_GAINS:
+ if (output || input)
+ loc = IN_CONFIG;
+ else
+ loc = IN_DEVICES_DEVICE;
+ break;
+
+ case IN_OUTPUT_INPUT:
+ if (in_output)
+ output = NULL;
+ else
+ input = NULL;
+ /* fall through */
+ case IN_GAIN_N:
+ /* fall through */
+ case IN_DEVICES_DEVICE:
+ /* fall through */
+ case IN_CONFIG:
+ /* fall through */
+ case IN_GLOBAL_EXT:
+ loc--;
+ break;
+ }
+
+ continue;
+ }
+
+ /* Parsing of values */
+ if (loc == IN_GLOBAL ||
+ loc == IN_GLOBAL_EXT ||
+ loc == IN_MODULE_GLOBAL ||
+ loc == IN_CONFIG ||
+ loc == IN_DEVICES_DEVICE ||
+ loc == IN_GAIN_N) {
+
+ bool success = false;
+
+ if (loc == IN_GLOBAL || loc == IN_MODULE_GLOBAL) {
+ pa_droid_config_global *global_config = NULL;
+
+ if (loc == IN_MODULE_GLOBAL) {
+ pa_assert(module);
+ if (!module->global_config)
+ module->global_config = pa_xnew0(pa_droid_config_global, 1);
+ global_config = module->global_config;
+ } else
+ global_config = config->global_config;
+
+ pa_assert(global_config);
+
+ /* Parse global configuration */
+
+ if (pa_streq(v, ATTACHED_OUTPUT_DEVICES_TAG))
+ success = pa_conversion_parse_output_devices(filename, n, value, true, true,
+ &global_config->attached_output_devices);
+ else if (pa_streq(v, DEFAULT_OUTPUT_DEVICE_TAG))
+ success = pa_conversion_parse_output_devices(filename, n, value, true, true,
+ &global_config->default_output_device);
+ else if (pa_streq(v, ATTACHED_INPUT_DEVICES_TAG))
+ success = pa_conversion_parse_input_devices(filename, n, value, true, false,
+ &global_config->attached_input_devices);
+ else if (pa_streq(v, AUDIO_HAL_VERSION_TAG))
+ success = pa_conversion_parse_version(filename, n, value,
+ &global_config->audio_hal_version);
+#ifdef SPEAKER_DRC_ENABLED_TAG
+ // SPEAKER_DRC_ENABLED_TAG is only from Android v4.4
+ else if (pa_streq(v, SPEAKER_DRC_ENABLED_TAG))
+ /* TODO - Add support for dynamic range control */
+ success = true; /* Do not fail while parsing speaker_drc_enabled entry */
+#endif
+ else {
+ pa_log("[%s:%u] failed to parse line - unknown config entry %s", filename, n, v);
+ success = false;
+ }
+
+ } else if (loc == IN_GLOBAL_EXT) {
+
+ /* Parse custom global configuration
+ * For now just log all custom variables, don't do
+ * anything with the values.
+ * TODO: Store custom values somehow */
+
+ pa_log_debug("[%s:%u] TODO custom variable: %s = %s", filename, n, v, value);
+ success = true;
+
+ } else if (loc == IN_CONFIG) {
+
+ /* Parse per-output or per-input configuration */
+
+ if ((in_output && !output) || (!in_output && !input)) {
+ pa_log("[%s:%u] failed to parse line", filename, n);
+ ret = false;
+ goto finish;
+ }
+
+ if (pa_streq(v, SAMPLING_RATES_TAG))
+ success = pa_conversion_parse_sampling_rates(filename, n, value, true,
+ in_output ? output->sampling_rates : input->sampling_rates);
+ else if (pa_streq(v, FORMATS_TAG))
+ success = pa_conversion_parse_formats(filename, n, value, true,
+ in_output ? &output->formats : &input->formats);
+ else if (pa_streq(v, CHANNELS_TAG)) {
+ if (in_output)
+ success = pa_conversion_parse_output_channels(filename, n, value, true, &output->channel_masks);
+ else
+ success = pa_conversion_parse_input_channels(filename, n, value, true, &input->channel_masks);
+ } else if (pa_streq(v, DEVICES_TAG)) {
+ if (in_output)
+ success = pa_conversion_parse_output_devices(filename, n, value, true, false, &output->devices);
+ else
+ success = pa_conversion_parse_input_devices(filename, n, value, true, false, &input->devices);
+ } else if (pa_streq(v, FLAGS_TAG)) {
+ if (in_output)
+ success = pa_conversion_parse_output_flags(filename, n, value, &output->flags);
+ else {
+#if AUDIO_API_VERSION_MAJ >= 3
+ success = pa_conversion_parse_input_flags(filename, n, value, &input->flags);
+#else
+ pa_log("[%s:%u] failed to parse line - output flags inside input definition", filename, n);
+ success = false;
+#endif
+ }
+ } else {
+ pa_log("[%s:%u] failed to parse line - unknown config entry %s", filename, n, v);
+ success = false;
+ }
+
+ } else if (loc == IN_DEVICES_DEVICE) {
+ /* TODO Missing implementation of parsing the module/devices section.
+ * As of now there is no need for the information, fix this when that
+ * changes. */
+ success = true;
+ } else if (loc == IN_GAIN_N) {
+ /* TODO Missing implementation of parsing the gain_n section.
+ * As of now there is no need for the information, fix this when that
+ * changes. */
+ success = true;
+ } else
+ pa_assert_not_reached();
+
+ if (!success) {
+ ret = false;
+ goto finish;
+ }
+ }
+ }
+
+ pa_log_info("Parsed config file (%s): %u modules.", filename, hw_module_count);
+
+finish:
+ if (f) {
+ pa_lock_fd(fileno(f), 0);
+ fclose(f);
+ }
+
+ pa_xfree(full_line);
+
+ if (!ret)
+ pa_droid_config_free(config), config = NULL;
+
+ return config;
+}
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/config-parser-xml.c
^
|
@@ -0,0 +1,1064 @@
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pulsecore/log.h>
+
+#include "droid/droid-config.h"
+
+#ifndef HAVE_EXPAT
+#include <unistd.h>
+pa_droid_config_audio *pa_parse_droid_audio_config_xml(const char *filename) {
+ if (access(filename, F_OK) == 0)
+ pa_log_warn("Could not parse %s, xml configuration parsing support not compiled in", filename);
+ return NULL;
+}
+#else
+
+#include <stdarg.h>
+#include <string.h>
+#include <expat.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
+
+#include "droid/conversion.h"
+#include "droid/sllist.h"
+
+#ifdef XML_UNICODE_WCHAR_T
+# include <wchar.h>
+# define XML_FMT_STR "ls"
+#else
+# define XML_FMT_STR "s"
+#endif
+
+#define POLICY_SUPPORTED_VERSION "1.0"
+
+#define ELEMENT_audioPolicyConfiguration "audioPolicyConfiguration"
+#define ELEMENT_globalConfiguration "globalConfiguration"
+#define ELEMENT_modules "modules"
+#define ELEMENT_module "module"
+#define ELEMENT_attachedDevices "attachedDevices"
+#define ELEMENT_item "item"
+#define ELEMENT_defaultOutputDevice "defaultOutputDevice"
+#define ELEMENT_mixPorts "mixPorts"
+#define ELEMENT_mixPort "mixPort"
+#define ELEMENT_profile "profile"
+#define ELEMENT_devicePorts "devicePorts"
+#define ELEMENT_devicePort "devicePort"
+/* ELEMENT_profile */
+#define ELEMENT_routes "routes"
+#define ELEMENT_route "route"
+
+#define ATTRIBUTE_version "version"
+#define ATTRIBUTE_name "name"
+#define ATTRIBUTE_halVersion "halVersion"
+#define ATTRIBUTE_format "format"
+#define ATTRIBUTE_samplingRates "samplingRates"
+#define ATTRIBUTE_channelMasks "channelMasks"
+#define ATTRIBUTE_tagName "tagName"
+#define ATTRIBUTE_role "role"
+#define ATTRIBUTE_flags "flags"
+#define ATTRIBUTE_sink "sink"
+#define ATTRIBUTE_sources "sources"
+#define ATTRIBUTE_type "type"
+
+#define PORT_TYPE_sink "sink"
+#define PORT_TYPE_source "source"
+
+
+struct parser_data;
+
+struct element_parser {
+ const char *name;
+ bool (*attributes)(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+ void (*char_data)(struct parser_data *data, const char *str);
+ const struct element_parser *next;
+ const struct element_parser *child;
+};
+
+struct element_parser_stack {
+ const struct element_parser *data;
+ struct element_parser_stack *next;
+};
+
+#define ELEMENT_STACK_PUSH(_stack, _item) \
+ do { \
+ struct element_parser_stack *_i; \
+ _i = pa_xmalloc0(sizeof(*_i)); \
+ _i->data = _item; \
+ _i->next = _stack; \
+ _stack = _i; \
+ } while(0)
+
+#define ELEMENT_STACK_POP(_stack, _item) \
+ do { \
+ if (_stack) { \
+ struct element_parser_stack *_t; \
+ _t = _stack; \
+ _item = _stack->data; \
+ _stack = _stack->next; \
+ pa_xfree(_t); \
+ } else \
+ _item = NULL; \
+ } while(0)
+
+static bool parse_audio_policy_configuration(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_route(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_profile(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_device_port(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_mix_port(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static void parse_default_output_device(struct parser_data *data, const char *str);
+static void parse_item(struct parser_data *data, const char *str);
+static bool parse_module(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+static bool parse_global_configuration(struct parser_data *data, const char *element_name, const XML_Char **attributes);
+
+static const struct element_parser element_parse_route = {
+ ELEMENT_route,
+ parse_route,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const struct element_parser element_parse_routes = {
+ ELEMENT_routes,
+ NULL,
+ NULL,
+ NULL,
+ &element_parse_route
+};
+
+static const struct element_parser element_parse_profile = {
+ ELEMENT_profile,
+ parse_profile,
+ NULL,
+ NULL,
+ NULL
+};
+
+static const struct element_parser element_parse_device_port = {
+ ELEMENT_devicePort,
+ parse_device_port,
+ NULL,
+ NULL,
+ &element_parse_profile
+};
+
+static const struct element_parser element_parse_device_ports = {
+ ELEMENT_devicePorts,
+ NULL,
+ NULL,
+ &element_parse_routes,
+ &element_parse_device_port
+};
+
+static const struct element_parser element_parse_mix_port = {
+ ELEMENT_mixPort,
+ parse_mix_port,
+ NULL,
+ NULL,
+ &element_parse_profile
+};
+
+static const struct element_parser element_parse_mix_ports = {
+ ELEMENT_mixPorts,
+ NULL,
+ NULL,
+ &element_parse_device_ports,
+ &element_parse_mix_port
+};
+
+static const struct element_parser element_parse_default_output_device = {
+ ELEMENT_defaultOutputDevice,
+ NULL,
+ parse_default_output_device,
+ &element_parse_mix_ports,
+ NULL
+};
+
+static const struct element_parser element_parse_item = {
+ ELEMENT_item,
+ NULL,
+ parse_item,
+ NULL,
+ NULL
+};
+
+static const struct element_parser element_parse_attached_devices = {
+ ELEMENT_attachedDevices,
+ NULL,
+ NULL,
+ &element_parse_default_output_device,
+ &element_parse_item
+};
+
+static const struct element_parser element_parse_module = {
+ ELEMENT_module,
+ parse_module,
+ NULL,
+ NULL,
+ &element_parse_attached_devices
+};
+
+static const struct element_parser element_parse_modules = {
+ ELEMENT_modules,
+ NULL,
+ NULL,
+ NULL,
+ &element_parse_module
+};
+
+static const struct element_parser element_parse_global_configuration = {
+ ELEMENT_globalConfiguration,
+ parse_global_configuration,
+ NULL,
+ &element_parse_modules,
+ NULL
+};
+
+static const struct element_parser element_parse_audio_policy_configuration = {
+ ELEMENT_audioPolicyConfiguration,
+ parse_audio_policy_configuration,
+ NULL,
+ NULL,
+ &element_parse_global_configuration
+};
+
+static const struct element_parser element_parse_root = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &element_parse_audio_policy_configuration
+};
+
+
+struct global_configuration {
+ char *key;
+ char *value;
+ struct global_configuration *next;
+};
+
+struct device {
+ char *name;
+ struct device *next;
+};
+
+struct profile {
+ char *name;
+ audio_format_t format;
+ uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES];
+ audio_channel_mask_t channel_masks;
+ struct profile *next;
+};
+
+struct mix_port {
+ char *name;
+ char *role;
+ uint32_t flags;
+ struct profile *profiles;
+ struct mix_port *next;
+};
+
+struct device_port {
+ char *tag_name;
+ audio_devices_t type;
+ char *role;
+ struct profile *profiles;
+ struct device_port *next;
+};
+
+struct route {
+ char *type;
+ char *sink;
+ struct device *sources;
+ struct route *next;
+};
+
+struct module {
+ char *name;
+ uint32_t version;
+ struct device *attached_devices;
+ struct device *default_output;
+ struct mix_port *mix_ports;
+ struct device_port *device_ports;
+ struct route *routes;
+
+ struct module *next;
+};
+
+struct audio_policy_configuration {
+ struct global_configuration *global;
+ struct module *modules;
+};
+
+struct parser_data {
+ XML_Parser parser;
+ const char *fn;
+ unsigned lineno;
+
+ const struct element_parser *root;
+ const struct element_parser *current;
+ struct element_parser_stack *stack;
+
+ struct audio_policy_configuration *conf;
+ struct module *current_module;
+ struct mix_port *current_mix_port;
+ struct device_port *current_device_port;
+};
+
+
+static char *xml_string_dup(const XML_Char *xml_str, int len)
+{
+ char *str;
+
+ if (len > 0) {
+ str = pa_xmalloc0(len + 1);
+ snprintf(str, len + 1, "%" XML_FMT_STR, xml_str);
+ } else
+ str = pa_sprintf_malloc("%" XML_FMT_STR, xml_str);
+
+ return str;
+}
+
+static void device_free(struct device *d) {
+ pa_assert(d);
+ pa_xfree(d->name);
+ pa_xfree(d);
+}
+
+static void profile_free(struct profile *p) {
+ pa_assert(p);
+ pa_xfree(p->name);
+ pa_xfree(p);
+}
+
+static void mix_port_free(struct mix_port *p) {
+ struct profile *profile;
+
+ pa_assert(p);
+
+ while (p->profiles) {
+ SLLIST_STEAL_FIRST(profile, p->profiles);
+ profile_free(profile);
+ };
+
+ pa_xfree(p->name);
+ pa_xfree(p->role);
+ pa_xfree(p);
+}
+
+static void device_port_free(struct device_port *p) {
+ pa_assert(p);
+ pa_xfree(p->tag_name);
+ pa_xfree(p->role);
+ pa_xfree(p);
+}
+
+static void route_free(struct route *r) {
+ struct device *d;
+
+ pa_assert(r);
+
+ while (r->sources) {
+ SLLIST_STEAL_FIRST(d, r->sources);
+ device_free(d);
+ }
+ pa_xfree(r->type);
+ pa_xfree(r->sink);
+ pa_xfree(r);
+}
+
+static void module_free(struct module *m) {
+ struct device *dev;
+ struct mix_port *mix_port;
+ struct device_port *device_port;
+ struct route *route;
+
+ pa_assert(m);
+
+ while (m->attached_devices) {
+ SLLIST_STEAL_FIRST(dev, m->attached_devices);
+ device_free(dev);
+ };
+
+ while (m->default_output) {
+ SLLIST_STEAL_FIRST(dev, m->default_output);
+ device_free(dev);
+ };
+
+ while (m->mix_ports) {
+ SLLIST_STEAL_FIRST(mix_port, m->mix_ports);
+ mix_port_free(mix_port);
+ };
+
+ while (m->device_ports) {
+ SLLIST_STEAL_FIRST(device_port, m->device_ports);
+ device_port_free(device_port);
+ };
+
+ while (m->routes) {
+ SLLIST_STEAL_FIRST(route, m->routes);
+ route_free(route);
+ };
+
+ pa_xfree(m->name);
+ pa_xfree(m);
+}
+
+static void audio_policy_configuration_free(struct audio_policy_configuration *xml_config) {
+ struct global_configuration *global;
+ struct module *m;
+
+ pa_assert(xml_config);
+
+ while (xml_config->global) {
+ SLLIST_STEAL_FIRST(global, xml_config->global);
+ pa_xfree(global->key);
+ pa_xfree(global->value);
+ pa_xfree(global);
+ }
+
+ while (xml_config->modules) {
+ SLLIST_STEAL_FIRST(m, xml_config->modules);
+ module_free(m);
+ };
+
+ pa_xfree(xml_config);
+}
+
+static bool get_element_attr(struct parser_data *data, const XML_Char **attr, bool required,
+ const char *key, char **ret_value) {
+ int i;
+ bool found = false;
+
+ pa_assert(attr);
+ pa_assert(key);
+ pa_assert(ret_value);
+
+ for (i = 0; attr[i]; i += 2) {
+ if (pa_streq(attr[i], key)) {
+ *ret_value = xml_string_dup(attr[i + 1], -1);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found && required)
+ pa_log_warn("[%s:%u] Could not find element attribute \"%s\"", data->fn, data->lineno, key);
+
+ return found;
+}
+
+static bool get_element_attrs(struct parser_data *data, const XML_Char **attr, ...) {
+ const char *key;
+ char **ret_value;
+ va_list ap;
+ uint32_t keys = 0;
+ uint32_t found = 0;
+
+ va_start(ap, attr);
+ for (;;) {
+ key = va_arg(ap, const char *);
+ if (!key)
+ break;
+ keys++;
+
+ ret_value = va_arg(ap, char **);
+ if (get_element_attr(data, attr, true, key, ret_value))
+ found++;
+ }
+ va_end(ap);
+
+ return keys == found;
+}
+
+static void XMLCALL xml_start_element(void *userdata, const XML_Char *element_name, const XML_Char **attributes) {
+ struct parser_data *data = userdata;
+ char *element = NULL;
+ const struct element_parser *node;
+
+ element = xml_string_dup(element_name, -1);
+ data->lineno = (unsigned) XML_GetCurrentLineNumber(data->parser);
+
+ SLLIST_FOREACH(node, data->current->child) {
+ if (pa_streq(node->name, element)) {
+ if (node->attributes) {
+ if (!node->attributes(data, element, attributes))
+ goto fail;
+ }
+
+ ELEMENT_STACK_PUSH(data->stack, data->current);
+ data->current = node;
+ break;
+ }
+ }
+
+ pa_xfree(element);
+
+ return;
+
+fail:
+ while (data->stack)
+ ELEMENT_STACK_POP(data->stack, node);
+
+ pa_xfree(element);
+
+ XML_StopParser(data->parser, 0);
+}
+
+static void XMLCALL xml_end_element(void *userdata, const XML_Char *element_name) {
+ struct parser_data *data = userdata;
+ char *element = NULL;
+
+ element = xml_string_dup(element_name, -1);
+
+ if (pa_streq(data->current->name, element)) {
+ ELEMENT_STACK_POP(data->stack, data->current);
+
+ if (pa_streq(element, ELEMENT_mixPort))
+ data->current_mix_port = NULL;
+ else if (pa_streq(element, ELEMENT_devicePort))
+ data->current_device_port = NULL;
+ else if (pa_streq(element, ELEMENT_module))
+ data->current_module = NULL;
+ }
+
+ pa_xfree(element);
+}
+
+static void XMLCALL xml_character_data_handler(void *userdata, const XML_Char *s, int len) {
+ struct parser_data *data = userdata;
+ int whitespace = 0;
+ char *str = NULL;
+
+ if (len <= 0)
+ goto done;
+
+ str = xml_string_dup(s, len);
+ whitespace = strspn(str, "\r\n\t ");
+
+ if (whitespace == len)
+ goto done;
+
+ if (data->current->char_data)
+ data->current->char_data(data, str);
+
+done:
+ pa_xfree(str);
+}
+
+static bool parse_audio_policy_configuration(struct parser_data *data,
+ const char *element_name,
+ const XML_Char **attributes) {
+ char *version = NULL;
+
+ if (!get_element_attr(data, attributes, true, ATTRIBUTE_version, &version))
+ return false;
+
+ if (!pa_streq(version, POLICY_SUPPORTED_VERSION)) {
+ pa_log_warn("[%s:%u] We only support " ELEMENT_audioPolicyConfiguration
+ " version " POLICY_SUPPORTED_VERSION ". Expect problems.",
+ data->fn, data->lineno);
+ }
+
+ pa_xfree(version);
+
+ return true;
+}
+
+static bool parse_module(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct module *m;
+ char *halVersion = NULL;
+
+ m = pa_xmalloc0(sizeof(*m));
+
+ get_element_attr(data, attributes, false, ATTRIBUTE_name, &m->name);
+
+ if (get_element_attr(data, attributes, false, ATTRIBUTE_halVersion, &halVersion))
+ pa_conversion_parse_version(data->fn, data->lineno, halVersion, &m->version);
+ else if (get_element_attr(data, attributes, false, ATTRIBUTE_version, &halVersion))
+ pa_conversion_parse_version(data->fn, data->lineno, halVersion, &m->version);
+
+ if (!m->version) {
+ pa_log_debug("[%s:%u] Could not find valid <" ELEMENT_module "> attribute " ATTRIBUTE_halVersion " or "
+ ATTRIBUTE_version ". Guessing version is 2.0.", data->fn, data->lineno);
+ m->version = HARDWARE_DEVICE_API_VERSION(2, 0);
+ }
+
+ if (!m->name)
+ m->name = pa_sprintf_malloc("module_at_line_%u", data->lineno);
+
+ SLLIST_APPEND(struct module, data->conf->modules, m);
+ data->current_module = m;
+ pa_log_debug("New " ELEMENT_module ": \"%s\"", m->name);
+
+ pa_xfree(halVersion);
+
+ return true;
+}
+
+static bool parse_global_configuration(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ int i;
+
+ for (i = 0; attributes[i]; i += 2) {
+ struct global_configuration *c;
+ c = pa_xmalloc0(sizeof(*c));
+ c->key = xml_string_dup(attributes[i], -1);
+ c->value = xml_string_dup(attributes[i + 1], -1);
+ SLLIST_APPEND(struct global_configuration, data->conf->global, c);
+ }
+
+ return true;
+}
+
+static void parse_item(struct parser_data *data, const char *str) {
+ struct device *d;
+
+ d = pa_xmalloc0(sizeof(*d));
+ d->name = pa_xstrdup(str);
+ SLLIST_APPEND(struct device, data->current_module->attached_devices, d);
+}
+
+static void parse_default_output_device(struct parser_data *data, const char *str) {
+ struct device *d;
+
+ d = pa_xmalloc0(sizeof(*d));
+ d->name = pa_xstrdup(str);
+ SLLIST_APPEND(struct device, data->current_module->default_output, d);
+}
+
+static bool parse_mix_port(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct mix_port *p;
+ bool parsed = false;
+ char *flags = NULL;
+
+ p = pa_xmalloc0(sizeof(*p));
+
+ if (!get_element_attrs(data, attributes,
+ ATTRIBUTE_name, &p->name,
+ ATTRIBUTE_role, &p->role,
+ NULL))
+ goto done;
+
+ /* flags is not mandatory element attribute */
+ if (get_element_attr(data, attributes, false, ATTRIBUTE_flags, &flags)) {
+ if (!(pa_streq(p->role, PORT_TYPE_source) ?
+ pa_conversion_parse_output_flags(data->fn, data->lineno, flags, &p->flags)
+ : pa_conversion_parse_input_flags(data->fn, data->lineno, flags, &p->flags)))
+ goto done;
+ }
+
+ parsed = true;
+done:
+ pa_xfree(flags);
+
+ if (parsed) {
+ SLLIST_APPEND(struct mix_port, data->current_module->mix_ports, p);
+ data->current_mix_port = p;
+ } else {
+ pa_log("[%s:%u] Failed to parse element <" ELEMENT_mixPort ">", data->fn, data->lineno);
+ mix_port_free(p);
+ }
+
+ return parsed;
+}
+
+static void replace_in_place(char **string, const char *a, const char *b) {
+ char *tmp;
+
+ pa_assert(*string);
+ pa_assert(a);
+ pa_assert(b);
+
+ tmp = pa_replace(*string, a, b);
+ pa_xfree(*string);
+ *string = tmp;
+}
+
+static bool parse_profile(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct profile *p;
+ bool parsed = false, unknown_format = false, output = true;
+ char *samplingRates = NULL, *channelMasks = NULL, *format = NULL;
+
+ /* if the parsing of parent devicePort or mixPort failed
+ * we skip child profiles as well. */
+ if (!data->current_mix_port && !data->current_device_port)
+ return true;
+
+ p = pa_xmalloc0(sizeof(*p));
+
+ if (!get_element_attrs(data, attributes,
+ ATTRIBUTE_name, &p->name,
+ ATTRIBUTE_format, &format,
+ ATTRIBUTE_samplingRates, &samplingRates,
+ NULL))
+ goto done;
+
+ if (data->current_mix_port)
+ output = pa_streq(data->current_mix_port->role, PORT_TYPE_source);
+ else if (data->current_device_port)
+ output = pa_streq(data->current_device_port->role, PORT_TYPE_sink);
+ else
+ pa_assert_not_reached();
+
+ /* some devicePorts do not have channel masks */
+ get_element_attr(data, attributes, false, ATTRIBUTE_channelMasks, &channelMasks);
+
+ /* Hard-coded workaround for incorrect audio policy configuration. */
+ if (channelMasks && data->current_device_port) {
+ if (output && pa_startswith(channelMasks, "AUDIO_CHANNEL_IN_")) {
+ pa_log_info("[%s:%u] Output has wrong direction channel mask (%s), reversing.",
+ data->fn, data->lineno, channelMasks);
+ replace_in_place(&channelMasks, "AUDIO_CHANNEL_IN_", "AUDIO_CHANNEL_OUT_");
+ }
+ else if (!output && pa_startswith(channelMasks, "AUDIO_CHANNEL_OUT_")) {
+ pa_log_info("[%s:%u] Input has wrong direction channel mask (%s), reversing.",
+ data->fn, data->lineno, channelMasks);
+ replace_in_place(&channelMasks, "AUDIO_CHANNEL_OUT_", "AUDIO_CHANNEL_IN_");
+ }
+ }
+
+ if (!pa_conversion_parse_sampling_rates(data->fn, data->lineno, samplingRates, false, p->sampling_rates))
+ goto done;
+
+ if (!pa_conversion_parse_formats(data->fn, data->lineno, format, false, &p->format))
+ unknown_format = true;
+
+ if (!unknown_format && channelMasks && !(output ?
+ pa_conversion_parse_output_channels(data->fn, data->lineno, channelMasks, false, &p->channel_masks)
+ : pa_conversion_parse_input_channels(data->fn, data->lineno, channelMasks, false, &p->channel_masks)))
+ goto done;
+
+ parsed = true;
+done:
+ pa_xfree(samplingRates);
+ pa_xfree(channelMasks);
+ pa_xfree(format);
+
+ if (!parsed) {
+ pa_log_error("[%s:%u] Failed to parse element <" ELEMENT_profile ">", data->fn, data->lineno);
+ profile_free(p);
+ } else if (unknown_format) {
+ pa_log_info("[%s:%u] Ignore profile with unknown format.", data->fn, data->lineno);
+ profile_free(p);
+ } else {
+ if (data->current_mix_port)
+ SLLIST_APPEND(struct profile, data->current_module->mix_ports->profiles, p);
+ else if (data->current_device_port)
+ SLLIST_APPEND(struct profile, data->current_module->device_ports->profiles, p);
+ else
+ pa_assert_not_reached();
+ }
+
+ return parsed;
+}
+
+static bool parse_device_port(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct device_port *d;
+ bool parsed = false, unknown_device = false;
+ char *type = NULL;
+
+ d = pa_xmalloc0(sizeof(*d));
+
+ if (!get_element_attrs(data, attributes,
+ ATTRIBUTE_tagName, &d->tag_name,
+ ATTRIBUTE_role, &d->role,
+ NULL))
+ goto done;
+
+ if (!get_element_attr(data, attributes, true, ATTRIBUTE_type, &type))
+ goto done;
+
+ if (!(pa_streq(d->role, ATTRIBUTE_sink) ?
+ pa_conversion_parse_output_devices(data->fn, data->lineno, type, false, false, &d->type)
+ : pa_conversion_parse_input_devices(data->fn, data->lineno, type, false, false, &d->type)))
+ unknown_device = true;
+
+ parsed = true;
+done:
+ pa_xfree(type);
+
+ if (!parsed) {
+ pa_log("[%s:%u] Failed to parse element <" ELEMENT_devicePort ">", data->fn, data->lineno);
+ device_port_free(d);
+ } else if (unknown_device) {
+ pa_log_info("[%s:%u] Ignore <" ELEMENT_devicePort "> with unknown device.", data->fn, data->lineno);
+ device_port_free(d);
+ } else {
+ SLLIST_APPEND(struct device_port, data->current_module->device_ports, d);
+ data->current_device_port = d;
+ }
+
+ return parsed;
+}
+
+static bool parse_route(struct parser_data *data, const char *element_name, const XML_Char **attributes) {
+ struct route *r;
+ bool parsed = false;
+ char *sources = NULL;
+ const char *state = NULL;
+ char *source;
+
+ r = pa_xmalloc0(sizeof(*r));
+
+ if (!get_element_attrs(data, attributes,
+ ATTRIBUTE_type, &r->type,
+ ATTRIBUTE_sink, &r->sink,
+ ATTRIBUTE_sources, &sources,
+ NULL))
+ goto done;
+
+ while ((source = pa_split(sources, ",", &state))) {
+ struct device *d = pa_xmalloc0(sizeof(*d));
+ d->name = source;
+ SLLIST_APPEND(struct device, r->sources, d);
+ }
+
+ parsed = true;
+done:
+ pa_xfree(sources);
+
+ if (parsed) {
+ SLLIST_APPEND(struct route, data->current_module->routes, r);
+ } else {
+ pa_log("[%s:%u] Failed to parse element <" ELEMENT_route ">", data->fn, data->lineno);
+ route_free(r);
+ }
+
+ return parsed;
+}
+
+static bool parse_file(struct parser_data *data, const char *filename) {
+ char buf[BUFSIZ];
+ FILE *f = NULL;
+ XML_Parser parser = NULL;
+ bool done;
+ bool ret = true;
+
+ pa_assert(data);
+ pa_assert(filename);
+
+ f = fopen(filename, "r");
+
+ if (!f) {
+ pa_log_info("Failed to open file (%s): %s", filename, pa_cstrerror(errno));
+ ret = false;
+ goto done;
+ }
+
+ parser = XML_ParserCreate(NULL);
+ data->parser = parser;
+ data->fn = filename;
+ if (!data->conf)
+ data->conf = pa_xnew0(struct audio_policy_configuration, 1);
+
+ XML_SetUserData(parser, data);
+ XML_SetElementHandler(parser, xml_start_element, xml_end_element);
+ XML_SetCharacterDataHandler(parser, xml_character_data_handler);
+
+ pa_log_debug("Read %s ...", data->fn);
+
+ do {
+ size_t len = fread(buf, 1, sizeof(buf), f);
+ done = len < sizeof(buf);
+ if (XML_Parse(parser, buf, (int) len, done) == XML_STATUS_ERROR) {
+ unsigned long lineno = XML_GetCurrentLineNumber(parser);
+ pa_log("%" XML_FMT_STR " at line %lu\n",
+ XML_ErrorString(XML_GetErrorCode(parser)),
+ lineno);
+ ret = false;
+ goto done;
+ }
+ } while (!done);
+
+done:
+ if (parser)
+ XML_ParserFree(parser);
+
+ if (f)
+ fclose(f);
+
+ return ret;
+}
+
+static struct device_port *find_device_port(struct module *module, const char *name) {
+ struct device_port *port;
+
+ SLLIST_FOREACH(port, module->device_ports) {
+ if (pa_streq(port->tag_name, name))
+ return port;
+ }
+
+ return NULL;
+}
+
+static bool device_in_list(struct device *list, const char *name) {
+ struct device *dev;
+
+ pa_assert(name);
+
+ SLLIST_FOREACH(dev, list) {
+ if (pa_streq(name, dev->name))
+ return true;
+ }
+
+ return false;
+}
+
+static void add_output(struct module *module, struct mix_port *mix_port, pa_droid_config_hw_module *hw_module) {
+ pa_droid_config_device *output;
+ struct profile *profile;
+ struct route *route;
+ struct device_port *device_port;
+
+ output = pa_droid_config_device_new(hw_module, PA_DIRECTION_OUTPUT, mix_port->name);
+ output->flags = mix_port->flags;
+ SLLIST_FOREACH(profile, mix_port->profiles) {
+ memcpy(output->sampling_rates, profile->sampling_rates, sizeof(output->sampling_rates));
+ output->channel_masks |= profile->channel_masks;
+ output->formats |= profile->format;
+ }
+
+ SLLIST_FOREACH(route, module->routes) {
+ struct device *source;
+ SLLIST_FOREACH(source, route->sources) {
+ if (pa_streq(source->name, mix_port->name)) {
+ if ((device_port = find_device_port(module, route->sink))) {
+ output->devices |= device_port->type;
+ if (device_in_list(module->attached_devices, device_port->tag_name))
+ hw_module->global_config->attached_output_devices |= device_port->type;
+ if (device_in_list(module->default_output, device_port->tag_name))
+ hw_module->global_config->default_output_device |= device_port->type;
+ break;
+ } else
+ pa_log_info("Couldn't find matching <" ELEMENT_devicePort " tagName=%s> for <" ELEMENT_mixPort " name=%s>",
+ route->sink, source->name);
+ }
+ }
+ }
+
+ pa_log_debug("config: %s: New output: %s", hw_module->name, output->name);
+ SLLIST_APPEND(pa_droid_config_device, hw_module->outputs, output);
+}
+
+static void add_input(struct module *module, struct mix_port *mix_port, pa_droid_config_hw_module *hw_module) {
+ pa_droid_config_device *input;
+ struct profile *profile;
+ struct route *route;
+ struct device_port *device_port;
+
+ input = pa_droid_config_device_new(hw_module, PA_DIRECTION_INPUT, mix_port->name);
+ input->flags = mix_port->flags;
+ SLLIST_FOREACH(profile, mix_port->profiles) {
+ memcpy(input->sampling_rates, profile->sampling_rates, sizeof(input->sampling_rates));
+ input->channel_masks |= profile->channel_masks;
+ input->formats |= profile->format;
+ }
+
+ SLLIST_FOREACH(route, module->routes) {
+ if (pa_streq(route->sink, mix_port->name)) {
+ struct device *source;
+ SLLIST_FOREACH(source, route->sources) {
+ if ((device_port = find_device_port(module, source->name))) {
+ input->devices |= device_port->type;
+ if (device_in_list(module->attached_devices, device_port->tag_name))
+ hw_module->global_config->attached_input_devices |= device_port->type;
+ } else
+ pa_log_info("Couldn't find matching <" ELEMENT_mixPort " name=%s> for <" ELEMENT_devicePort " tagName=%s>",
+ source->name, route->sink);
+
+ }
+ }
+ }
+
+ pa_log_debug("config: %s: New input: %s", hw_module->name, input->name);
+ SLLIST_APPEND(pa_droid_config_device, hw_module->inputs, input);
+}
+
+static void generate_config_for_module(struct module *module, pa_droid_config_audio *config) {
+ pa_droid_config_hw_module *hw_module;
+ struct mix_port *mix_port;
+
+ pa_assert(module);
+ pa_assert(config);
+ pa_assert(config->global_config);
+
+ hw_module = pa_droid_config_hw_module_new(config, module->name);
+ if (module->attached_devices || module->default_output)
+ hw_module->global_config = pa_xnew0(pa_droid_config_global, 1);
+ SLLIST_APPEND(pa_droid_config_hw_module, config->hw_modules, hw_module);
+
+ SLLIST_FOREACH(mix_port, module->mix_ports) {
+ if (pa_streq(mix_port->role, PORT_TYPE_source))
+ add_output(module, mix_port, hw_module);
+ else if (pa_streq(mix_port->role, ATTRIBUTE_sink))
+ add_input(module, mix_port, hw_module);
+ else
+ pa_log_warn("Unknown <" ELEMENT_mixPort "> role \"%s\"", mix_port->role);
+ }
+}
+
+static pa_droid_config_audio *convert_config(struct audio_policy_configuration *source) {
+ pa_droid_config_audio *config = NULL;
+ struct module *module;
+
+ pa_assert(source);
+
+ config = pa_xnew0(pa_droid_config_audio, 1);
+ config->global_config = pa_xnew0(pa_droid_config_global, 1);
+
+ pa_log_debug("Convert configuration ...");
+ SLLIST_FOREACH(module, source->modules)
+ generate_config_for_module(module, config);
+
+ return config;
+}
+
+pa_droid_config_audio *pa_parse_droid_audio_config_xml(const char *filename) {
+ pa_droid_config_audio *config = NULL;
+ struct parser_data data;
+ bool ret = true;
+
+ pa_assert(filename);
+
+ memset(&data, 0, sizeof(data));
+
+ data.root = &element_parse_root;
+ data.current = data.root;
+
+ if (!(ret = parse_file(&data, filename)))
+ goto done;
+
+ config = convert_config(data.conf);
+
+done:
+ if (data.conf)
+ audio_policy_configuration_free(data.conf);
+
+ return config;
+}
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/conversion.c
^
|
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2013-2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "droid/version.h"
+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 1
+#include "droid-util-41qc.h"
+#else
+#include "droid-util-audio.h"
+#endif
+
+#include <pulsecore/core-util.h>
+
+#include <hardware/audio.h>
+
+#include "droid/conversion.h"
+#include "droid/droid-config.h"
+
+#define CONVERT_FUNC(TABL) \
+bool pa_convert_ ## TABL (uint32_t value, pa_conversion_field_t field, uint32_t *to_value) { \
+ for (unsigned int i = 0; i < sizeof( conversion_table_ ## TABL )/(sizeof(uint32_t)*2); i++) { \
+ if ( conversion_table_ ## TABL [i][field] == value) { \
+ *to_value = conversion_table_ ## TABL [i][!field]; \
+ return true; \
+ } \
+ } \
+ return false; \
+} struct __funny_extra_to_allow_semicolon
+
+/* Creates convert_format convert_channel etc.
+ * bool pa_convert_func(uint32_t value, pa_conversion_field_t field, uint32_t *to_value);
+ * return true if conversion succesful */
+CONVERT_FUNC(format);
+CONVERT_FUNC(output_channel);
+CONVERT_FUNC(input_channel);
+
+#define value_separator(legacy) (legacy ? "|" : ",")
+
+static bool string_convert_num_to_str(const struct string_conversion *list, const uint32_t value, const char **to_str) {
+ pa_assert(list);
+ pa_assert(to_str);
+
+ for (unsigned int i = 0; list[i].str; i++) {
+ if (list[i].value == value) {
+ *to_str = list[i].str;
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool string_convert_str_to_num(const struct string_conversion *list, const char *str, uint32_t *to_value) {
+ pa_assert(list);
+ pa_assert(str);
+ pa_assert(to_value);
+
+ for (unsigned int i = 0; list[i].str; i++) {
+ if (pa_streq(list[i].str, str)) {
+ *to_value = list[i].value;
+ return true;
+ }
+ }
+ return false;
+}
+
+static char *list_string(struct string_conversion *list, uint32_t flags) {
+ char *str = NULL;
+ char *tmp;
+
+#if AUDIO_API_VERSION_MAJ >= 2
+ if (flags & AUDIO_DEVICE_BIT_IN)
+ flags &= ~AUDIO_DEVICE_BIT_IN;
+#endif
+
+ for (unsigned int i = 0; list[i].str; i++) {
+#if AUDIO_API_VERSION_MAJ >= 2
+ if (list[i].value & AUDIO_DEVICE_BIT_IN) {
+ if (popcount(list[i].value & ~AUDIO_DEVICE_BIT_IN) != 1)
+ continue;
+ } else
+#endif
+ if (popcount(list[i].value) != 1)
+ continue;
+
+ if (flags & list[i].value) {
+ if (str) {
+ tmp = pa_sprintf_malloc("%s|%s", str, list[i].str);
+ pa_xfree(str);
+ str = tmp;
+ } else {
+ str = pa_sprintf_malloc("%s", list[i].str);
+ }
+ }
+ }
+
+ return str;
+}
+
+
+/* Output device */
+bool pa_string_convert_output_device_num_to_str(audio_devices_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_output_device, (uint32_t) value, to_str);
+}
+
+bool pa_string_convert_output_device_str_to_num(const char *str, audio_devices_t *to_value) {
+ return string_convert_str_to_num(string_conversion_table_output_device, str, (uint32_t*) to_value);
+}
+
+char *pa_list_string_output_device(audio_devices_t devices) {
+ return list_string(string_conversion_table_output_device, devices);
+}
+
+/* Input device */
+bool pa_string_convert_input_device_num_to_str(audio_devices_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_input_device, (uint32_t) value, to_str);
+}
+
+bool pa_string_convert_input_device_str_to_num(const char *str, audio_devices_t *to_value) {
+ return string_convert_str_to_num(string_conversion_table_input_device, str, (uint32_t*) to_value);
+}
+
+char *pa_list_string_input_device(audio_devices_t devices) {
+ return list_string(string_conversion_table_input_device, devices);
+}
+
+/* Flags */
+bool pa_string_convert_flag_num_to_str(audio_output_flags_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_output_flag, (uint32_t) value, to_str);
+}
+
+bool pa_string_convert_flag_str_to_num(const char *str, audio_output_flags_t *to_value) {
+ return string_convert_str_to_num(string_conversion_table_output_flag, str, (uint32_t*) to_value);
+}
+
+char *pa_list_string_flags(audio_output_flags_t flags) {
+ return list_string(string_conversion_table_output_flag, flags);
+}
+
+bool pa_input_device_default_audio_source(audio_devices_t input_device, audio_source_t *default_source)
+{
+#if AUDIO_API_VERSION_MAJ >= 2
+ input_device &= ~AUDIO_DEVICE_BIT_IN;
+#endif
+
+ /* Note converting HAL values to different HAL values! */
+ for (unsigned int i = 0; i < sizeof(conversion_table_default_audio_source) / (sizeof(uint32_t) * 2); i++) {
+ if (conversion_table_default_audio_source[i][0] & input_device) {
+ *default_source = conversion_table_default_audio_source[i][1];
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool pa_droid_output_port_name(audio_devices_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_output_device_fancy, (uint32_t) value, to_str);
+}
+
+bool pa_droid_input_port_name(audio_devices_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_input_device_fancy, (uint32_t) value, to_str);
+}
+
+bool pa_droid_audio_source_name(audio_source_t value, const char **to_str) {
+ return string_convert_num_to_str(string_conversion_table_audio_source_fancy, (uint32_t) value, to_str);
+}
+
+static int parse_list(const struct string_conversion *table,
+ const char *separator,
+ const char *str,
+ uint32_t *dst,
+ char **unknown_entries) {
+ int count = 0;
+ char *entry;
+ char *unknown = NULL;
+ const char *state = NULL;
+
+ pa_assert(table);
+ pa_assert(separator);
+ pa_assert(str);
+ pa_assert(dst);
+ pa_assert(unknown_entries);
+
+ *dst = 0;
+ *unknown_entries = NULL;
+
+ while ((entry = pa_split(str, separator, &state))) {
+ uint32_t d = 0;
+
+ if (!string_convert_str_to_num(table, entry, &d)) {
+ if (*unknown_entries) {
+ unknown = pa_sprintf_malloc("%s|%s", *unknown_entries, entry);
+ pa_xfree(*unknown_entries);
+ pa_xfree(entry);
+ } else
+ unknown = entry;
+
+ *unknown_entries = unknown;
+ continue;
+ }
+
+ *dst |= d;
+ count++;
+
+ pa_xfree(entry);
+ }
+
+ return count;
+}
+
+int pa_conversion_parse_list(pa_conversion_string_t type, const char *separator,
+ const char *str, uint32_t *dst, char **unknown_entries) {
+ switch (type) {
+ case CONV_STRING_FORMAT:
+ return parse_list(string_conversion_table_format, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_OUTPUT_CHANNELS:
+ return parse_list(string_conversion_table_output_channels, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_INPUT_CHANNELS:
+ return parse_list(string_conversion_table_input_channels, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_OUTPUT_DEVICE:
+ return parse_list(string_conversion_table_output_device, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_INPUT_DEVICE:
+ return parse_list(string_conversion_table_input_device, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_OUTPUT_FLAG:
+ return parse_list(string_conversion_table_output_flag, separator, str, dst, unknown_entries);
+
+ case CONV_STRING_INPUT_FLAG:
+ return parse_list(string_conversion_table_input_flag, separator, str, dst, unknown_entries);
+ }
+
+ pa_assert_not_reached();
+ return 0;
+}
+
+bool pa_conversion_parse_sampling_rates(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]) {
+ pa_assert(fn);
+ pa_assert(str);
+
+ char *entry;
+ const char *state = NULL;
+
+ uint32_t pos = 0;
+ while ((entry = pa_split(str, value_separator(legacy), &state))) {
+ int32_t val;
+
+#if AUDIO_API_VERSION_MAJ >= 3
+ if (pos == 0 && pa_streq(entry, "dynamic")) {
+ sampling_rates[pos++] = (uint32_t) -1;
+ pa_xfree(entry);
+ break;
+ }
+#endif
+
+ if (pos == AUDIO_MAX_SAMPLING_RATES) {
+ pa_log("[%s:%u] Too many sample rate entries (> %d)", fn, ln, AUDIO_MAX_SAMPLING_RATES);
+ pa_xfree(entry);
+ return false;
+ }
+
+ if (pa_atoi(entry, &val) < 0) {
+ pa_log("[%s:%u] Bad sample rate value %s", fn, ln, entry);
+ pa_xfree(entry);
+ return false;
+ }
+
+ sampling_rates[pos++] = val;
+
+ pa_xfree(entry);
+
+ }
+
+ sampling_rates[pos] = 0;
+
+ return true;
+}
+
+static bool check_and_log(const char *fn, const unsigned ln, const char *field,
+ const int count, const char *str, char *unknown,
+ const bool must_recognize_all) {
+ bool fail;
+
+ pa_assert(fn);
+ pa_assert(field);
+ pa_assert(str);
+
+ fail = must_recognize_all && unknown;
+
+ if (unknown) {
+ pa_log_info("[%s:%u] Unknown %s entries: %s", fn, ln, field, unknown);
+ pa_xfree(unknown);
+ }
+
+ if (count == 0 || fail) {
+ pa_log("[%s:%u] Failed to parse %s (%s).", fn, ln, field, str);
+ return false;
+ }
+
+ return true;
+}
+
+bool pa_conversion_parse_formats(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_format_t *formats) {
+ int count;
+ char *unknown = NULL;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(formats);
+
+#if AUDIO_API_VERSION_MAJ >= 3
+ /* Needs to be probed later */
+ if (pa_streq(str, "dynamic")) {
+ *formats = 0;
+ return true;
+ }
+#endif
+
+ count = pa_conversion_parse_list(CONV_STRING_FORMAT, value_separator(legacy), str, formats, &unknown);
+
+ if (legacy)
+ return check_and_log(fn, ln, "formats", count, str, unknown, false);
+
+ /* As the new XML configuration lists formats as one per profile, unknown
+ * formats will cause the parser to quit. As a workaround for non-legacy
+ * conversions with no recognized formats log only info level and return false. */
+ check_and_log(fn, ln, "format", count == 0 ? 1 : count, str, unknown, false);
+ return count > 0;
+}
+
+static bool parse_channels(const char *fn, const unsigned ln,
+ const char *str, bool in_output,
+ bool legacy, audio_channel_mask_t *channels) {
+ int count;
+ char *unknown = NULL;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(channels);
+
+ /* Needs to be probed later */
+ if (pa_streq(str, "dynamic")) {
+ *channels = 0;
+ return true;
+ }
+
+ count = pa_conversion_parse_list(in_output ? CONV_STRING_OUTPUT_CHANNELS : CONV_STRING_INPUT_CHANNELS,
+ value_separator(legacy), str, channels, &unknown);
+
+ return check_and_log(fn, ln, in_output ? "output channel_masks" : "input channel_masks",
+ count, str, unknown, false);
+}
+
+bool pa_conversion_parse_output_channels(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_channel_mask_t *channels) {
+ return parse_channels(fn, ln, str, true, legacy, channels);
+}
+
+bool pa_conversion_parse_input_channels(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_channel_mask_t *channels) {
+ return parse_channels(fn, ln, str, false, legacy, channels);
+}
+
+static bool parse_devices(const char *fn, const unsigned ln,
+ const char *str, bool in_output,
+ bool legacy, bool must_recognize_all,
+ audio_devices_t *devices) {
+ int count;
+ char *unknown = NULL;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(devices);
+
+ count = pa_conversion_parse_list(in_output ? CONV_STRING_OUTPUT_DEVICE : CONV_STRING_INPUT_DEVICE,
+ value_separator(legacy), str, devices, &unknown);
+
+ if (legacy)
+ return check_and_log(fn, ln, in_output ? "output devices" : "input devices",
+ count, str, unknown, must_recognize_all);
+
+ /* As the new XML configuration lists devices as one per devicePort, unknown
+ * devices will cause the parser to quit. As a workaround for non-legacy
+ * conversions with no recognized devices log only info level and return false. */
+ check_and_log(fn, ln, in_output ? "output device" : "input device",
+ count == 0 ? 1 : count, str, unknown, must_recognize_all);
+ return count > 0;
+}
+
+bool pa_conversion_parse_output_devices(const char *fn, const unsigned ln,
+ char *str, bool legacy, bool must_recognize_all,
+ audio_devices_t *devices) {
+ return parse_devices(fn, ln, str, true, legacy, must_recognize_all, devices);
+}
+
+bool pa_conversion_parse_input_devices(const char *fn, const unsigned ln,
+ char *str, bool legacy, bool must_recognize_all,
+ audio_devices_t *devices) {
+ return parse_devices(fn, ln, str, false, legacy, must_recognize_all, devices);
+}
+
+bool pa_conversion_parse_output_flags(const char *fn, const unsigned ln,
+ const char *str, audio_output_flags_t *flags) {
+ int count;
+ char *unknown = NULL;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(flags);
+
+ count = pa_conversion_parse_list(CONV_STRING_OUTPUT_FLAG, "|", str, flags, &unknown);
+
+ return check_and_log(fn, ln, "flags", count, str, unknown, false);
+}
+
+bool pa_conversion_parse_input_flags(const char *fn, const unsigned ln,
+ const char *str, uint32_t *flags) {
+ int count;
+ char *unknown = NULL;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(flags);
+
+ count = pa_conversion_parse_list(CONV_STRING_INPUT_FLAG, "|", str, flags, &unknown);
+
+ return check_and_log(fn, ln, "flags", count, str, unknown, false);
+}
+
+bool pa_conversion_parse_version(const char *fn, const unsigned ln, const char *str, uint32_t *version) {
+ uint32_t version_maj;
+ uint32_t version_min;
+
+ pa_assert(fn);
+ pa_assert(str);
+ pa_assert(version);
+
+ if ((sscanf(str, "%u.%u", &version_maj, &version_min)) != 2) {
+ pa_log("[%s:%u] Failed to parse %s (%s).", fn, ln, AUDIO_HAL_VERSION_TAG, str);
+ return false;
+ } else {
+ *version = HARDWARE_DEVICE_API_VERSION(version_maj, version_min);
+ return true;
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/droid-config.c
^
|
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2013-2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "droid/version.h"
+#include "droid/droid-config.h"
+#include "droid/sllist.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
+#include <pulse/rtclock.h>
+#include <pulse/timeval.h>
+#include <pulse/volume.h>
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/core.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/i18n.h>
+#include <pulsecore/module.h>
+#include <pulsecore/memchunk.h>
+#include <pulsecore/sink.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/core-rtclock.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/sample-util.h>
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/time-smoother.h>
+#include <pulsecore/refcnt.h>
+#include <pulsecore/shared.h>
+#include <pulsecore/mutex.h>
+#include <pulsecore/strlist.h>
+#include <pulsecore/atomic.h>
+
+#include <hardware/audio.h>
+#include <hardware_legacy/audio_policy_conf.h>
+
+#define VENDOR_AUDIO_POLICY_CONFIG_XML_FILE "/vendor/etc/audio_policy_configuration.xml"
+#define SYSTEM_AUDIO_POLICY_CONFIG_XML_FILE "/system/etc/audio_policy_configuration.xml"
+
+
+pa_droid_config_audio *pa_droid_config_load(pa_modargs *ma) {
+ pa_droid_config_audio *config = NULL;
+ const char *manual_config;
+ const char *config_location[] = {
+ VENDOR_AUDIO_POLICY_CONFIG_XML_FILE,
+ AUDIO_POLICY_VENDOR_CONFIG_FILE,
+ SYSTEM_AUDIO_POLICY_CONFIG_XML_FILE,
+ AUDIO_POLICY_CONFIG_FILE,
+ NULL};
+
+ pa_assert(ma);
+
+ if ((manual_config = pa_modargs_get_value(ma, "config", NULL))) {
+ if (!(config = pa_parse_droid_audio_config(manual_config)))
+ pa_log("Failed to parse configuration from %s", manual_config);
+ } else {
+ int i;
+ for (i = 0; config_location[i]; i++) {
+ if ((config = pa_parse_droid_audio_config(config_location[i])))
+ break;
+ else
+ pa_log_debug("Failed to parse configuration from %s", config_location[i]);
+ }
+
+ }
+
+ if (!config)
+ pa_log("Failed to parse any configuration.");
+
+ return config;
+}
+
+pa_droid_config_audio *pa_droid_config_dup(const pa_droid_config_audio *config) {
+ pa_droid_config_audio *config_copy;
+ pa_droid_config_hw_module *module, *module_copy;
+ pa_droid_config_device *device, *device_copy;
+
+ pa_assert(config);
+
+ config_copy = pa_xnew0(pa_droid_config_audio, 1);
+
+ if (config->global_config)
+ config_copy->global_config = pa_xmemdup(config->global_config, sizeof(*config->global_config));
+
+ SLLIST_FOREACH(module, config->hw_modules) {
+ module_copy = pa_droid_config_hw_module_new(config_copy, module->name);
+ if (module->global_config)
+ module_copy->global_config = pa_xmemdup(module->global_config, sizeof(*module->global_config));
+
+ SLLIST_FOREACH(device, module->outputs) {
+ device_copy = pa_xmemdup(device, sizeof(*device));
+ device_copy->module = module_copy;
+ device_copy->name = pa_xstrdup(device->name);
+ SLLIST_APPEND(pa_droid_config_device, module_copy->outputs, device_copy);
+ }
+
+ SLLIST_FOREACH(device, module->inputs) {
+ device_copy = pa_xmemdup(device, sizeof(*device));
+ device_copy->module = module_copy;
+ device_copy->name = pa_xstrdup(device->name);
+ SLLIST_APPEND(pa_droid_config_device, module_copy->inputs, device_copy);
+ }
+
+ SLLIST_APPEND(pa_droid_config_hw_module, config_copy->hw_modules, module_copy);
+ }
+
+ return config_copy;
+}
+
+pa_droid_config_audio *pa_parse_droid_audio_config(const char *filename) {
+ const char *suffix;
+
+ pa_assert(filename);
+
+ if ((suffix = rindex(filename, '.'))) {
+ if (strlen(suffix) == 4 && pa_streq(suffix, ".xml"))
+ return pa_parse_droid_audio_config_xml(filename);
+ else if (strlen(suffix) == 5 && pa_streq(suffix, ".conf"))
+ return pa_parse_droid_audio_config_legacy(filename);
+ }
+
+ return NULL;
+}
+
+void pa_droid_config_free(pa_droid_config_audio *config) {
+ pa_droid_config_hw_module *module;
+ pa_droid_config_device *device;
+
+ if (!config)
+ return;
+
+ while (config->hw_modules) {
+ SLLIST_STEAL_FIRST(module, config->hw_modules);
+
+ while (module->outputs) {
+ SLLIST_STEAL_FIRST(device, module->outputs);
+ pa_droid_config_device_free(device);
+ }
+
+ while (module->inputs) {
+ SLLIST_STEAL_FIRST(device, module->inputs);
+ pa_droid_config_device_free(device);
+ }
+
+ pa_droid_config_hw_module_free(module);
+ }
+
+ pa_xfree(config->global_config);
+ pa_xfree(config);
+}
+
+const pa_droid_config_hw_module *pa_droid_config_find_module(const pa_droid_config_audio *config, const char* module_id) {
+ pa_droid_config_hw_module *module;
+
+ pa_assert(config);
+ pa_assert(module_id);
+
+ SLLIST_FOREACH(module, config->hw_modules) {
+ if (pa_streq(module_id, module->name))
+ return module;
+ }
+
+ return NULL;
+}
+
+pa_droid_config_hw_module *pa_droid_config_hw_module_new(const pa_droid_config_audio *config, const char *name) {
+ pa_droid_config_hw_module *hw_module;
+
+ pa_assert(config);
+ pa_assert(name);
+
+ hw_module = pa_xnew0(pa_droid_config_hw_module, 1);
+ hw_module->config = config;
+ hw_module->name = pa_xstrndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN);
+
+ return hw_module;
+}
+
+void pa_droid_config_hw_module_free(pa_droid_config_hw_module *hw_module) {
+ if (!hw_module)
+ return;
+
+ pa_xfree(hw_module->name);
+ pa_xfree(hw_module->global_config);
+ pa_xfree(hw_module);
+}
+
+pa_droid_config_device *pa_droid_config_device_new(const pa_droid_config_hw_module *module,
+ pa_direction_t direction,
+ const char *name) {
+ pa_droid_config_device *device;
+
+ pa_assert(module);
+ pa_assert(direction == PA_DIRECTION_OUTPUT || direction == PA_DIRECTION_INPUT);
+ pa_assert(name);
+
+ device = pa_xnew0(pa_droid_config_device, 1);
+ device->module = module;
+ device->direction = direction;
+ device->name = pa_replace(name, " ", "_");
+
+ return device;
+}
+
+void pa_droid_config_device_free(pa_droid_config_device *device) {
+ if (!device)
+ return;
+
+ pa_xfree(device->name);
+ pa_xfree(device);
+}
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/droid-util-41qc.h
^
|
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2013 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -29,6 +29,8 @@
#include <hardware/audio.h>
#include <hardware_legacy/audio_policy_conf.h>
+#include <pulse/channelmap.h>
+
// PulseAudio value - Android value
uint32_t conversion_table_output_channel[][2] = {
@@ -214,6 +216,10 @@
{ 0, NULL }
};
+struct string_conversion string_conversion_table_input_flag[] = {
+ { 0, NULL }
+};
+
/* Channels */
struct string_conversion string_conversion_table_output_channels[] = {
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/droid-util-audio.h
^
|
@@ -22,6 +22,7 @@
#ifndef _DROID_UTIL_AUDIO_H_
#define _DROID_UTIL_AUDIO_H_
+#include <android-config.h>
#ifdef QCOM_BSP
#define QCOM_HARDWARE
#endif
@@ -29,9 +30,7 @@
#include <hardware/audio.h>
#include <hardware_legacy/audio_policy_conf.h>
-#ifdef SPEAKER_DRC_ENABLED_TAG
-#define DROID_HAVE_DRC
-#endif
+#include <pulse/channelmap.h>
#ifdef STRING_ENTRY
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/droid-util.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include <config.h>
#endif
+#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
@@ -35,6 +36,7 @@
#include <pulse/timeval.h>
#include <pulse/volume.h>
#include <pulse/xmalloc.h>
+#include <pulse/direction.h>
#include <pulsecore/core.h>
#include <pulsecore/core-error.h>
@@ -58,7 +60,11 @@
#include <pulsecore/strlist.h>
#include <pulsecore/atomic.h>
-#include "droid-util.h"
+#include "droid/version.h"
+#include "droid/droid-util.h"
+#include "droid/droid-config.h"
+#include "droid/conversion.h"
+#include "droid/sllist.h"
struct droid_quirk {
const char *name;
@@ -73,851 +79,21 @@
{ "no_hw_volume", QUIRK_NO_HW_VOLUME },
{ "output_make_writable", QUIRK_OUTPUT_MAKE_WRITABLE },
{ "realcall", QUIRK_REALCALL },
+ { "unload_call_exit", QUIRK_UNLOAD_CALL_EXIT },
};
-#define SLLIST_APPEND(t, head, item) \
- do { \
- item->next = NULL; \
- if (!head) { \
- head = item; \
- } else { \
- t *_list; \
- for (_list = head; _list->next; _list = _list->next); \
- _list->next = item; \
- } \
- } while (0)
-
-#define SLLIST_FOREACH(i, head) \
- for (i = (head); i; i = i->next)
-
-#define SLLIST_STEAL_FIRST(i, head) \
- do { \
- if (head) { \
- i = head; \
- head = head->next; \
- } else \
- i = NULL; \
- } while (0)
-
-
-#define CONVERT_FUNC(TABL) \
-bool pa_convert_ ## TABL (uint32_t value, pa_conversion_field_t field, uint32_t *to_value) { \
- for (unsigned int i = 0; i < sizeof( conversion_table_ ## TABL )/(sizeof(uint32_t)*2); i++) { \
- if ( conversion_table_ ## TABL [i][field] == value) { \
- *to_value = conversion_table_ ## TABL [i][!field]; \
- return true; \
- } \
- } \
- return false; \
-} struct __funny_extra_to_allow_semicolon
-
-/* Creates convert_format convert_channel etc.
- * bool pa_convert_func(uint32_t value, pa_conversion_field_t field, uint32_t *to_value);
- * return true if conversion succesful */
-CONVERT_FUNC(format);
-CONVERT_FUNC(output_channel);
-CONVERT_FUNC(input_channel);
#define DEFAULT_PRIORITY (100)
-/* Section defining custom global configuration variables. */
-#define GLOBAL_CONFIG_EXT_TAG "custom_properties"
-
-/* From recent audio_policy_conf.h */
-#ifndef AUDIO_HAL_VERSION_TAG
-#define AUDIO_HAL_VERSION_TAG "audio_hal_version"
-#endif
-#ifndef GAINS_TAG
-#define GAINS_TAG "gains"
-#endif
-
-#define GAIN_TAG_PREFIX "gain_"
-
static const char * const droid_combined_auto_outputs[3] = { "primary", "low_latency", NULL };
static const char * const droid_combined_auto_inputs[2] = { "primary", NULL };
-static void droid_config_free(pa_droid_config_audio *config);
static void droid_port_free(pa_droid_port *p);
static pa_droid_stream *get_primary_output(pa_droid_hw_module *hw);
static int input_stream_set_route(pa_droid_stream *s, audio_devices_t device);
-static bool string_convert_num_to_str(const struct string_conversion *list, const uint32_t value, const char **to_str) {
- pa_assert(list);
- pa_assert(to_str);
-
- for (unsigned int i = 0; list[i].str; i++) {
- if (list[i].value == value) {
- *to_str = list[i].str;
- return true;
- }
- }
- return false;
-}
-
-static bool string_convert_str_to_num(const struct string_conversion *list, const char *str, uint32_t *to_value) {
- pa_assert(list);
- pa_assert(str);
- pa_assert(to_value);
-
- for (unsigned int i = 0; list[i].str; i++) {
- if (pa_streq(list[i].str, str)) {
- *to_value = list[i].value;
- return true;
- }
- }
- return false;
-}
-
-static char *list_string(struct string_conversion *list, uint32_t flags) {
- char *str = NULL;
- char *tmp;
-
-#if AUDIO_API_VERSION_MAJ >= 2
- if (flags & AUDIO_DEVICE_BIT_IN)
- flags &= ~AUDIO_DEVICE_BIT_IN;
-#endif
-
- for (unsigned int i = 0; list[i].str; i++) {
-#if AUDIO_API_VERSION_MAJ >= 2
- if (list[i].value & AUDIO_DEVICE_BIT_IN) {
- if (popcount(list[i].value & ~AUDIO_DEVICE_BIT_IN) != 1)
- continue;
- } else
-#endif
- if (popcount(list[i].value) != 1)
- continue;
-
- if (flags & list[i].value) {
- if (str) {
- tmp = pa_sprintf_malloc("%s|%s", str, list[i].str);
- pa_xfree(str);
- str = tmp;
- } else {
- str = pa_sprintf_malloc("%s", list[i].str);
- }
- }
- }
-
- return str;
-}
-
-
-/* Output device */
-bool pa_string_convert_output_device_num_to_str(audio_devices_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_output_device, (uint32_t) value, to_str);
-}
-
-bool pa_string_convert_output_device_str_to_num(const char *str, audio_devices_t *to_value) {
- return string_convert_str_to_num(string_conversion_table_output_device, str, (uint32_t*) to_value);
-}
-
-char *pa_list_string_output_device(audio_devices_t devices) {
- return list_string(string_conversion_table_output_device, devices);
-}
-
-/* Input device */
-bool pa_string_convert_input_device_num_to_str(audio_devices_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_input_device, (uint32_t) value, to_str);
-}
-
-bool pa_string_convert_input_device_str_to_num(const char *str, audio_devices_t *to_value) {
- return string_convert_str_to_num(string_conversion_table_input_device, str, (uint32_t*) to_value);
-}
-
-char *pa_list_string_input_device(audio_devices_t devices) {
- return list_string(string_conversion_table_input_device, devices);
-}
-
-/* Flags */
-bool pa_string_convert_flag_num_to_str(audio_output_flags_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_output_flag, (uint32_t) value, to_str);
-}
-
-bool pa_string_convert_flag_str_to_num(const char *str, audio_output_flags_t *to_value) {
- return string_convert_str_to_num(string_conversion_table_output_flag, str, (uint32_t*) to_value);
-}
-
-char *pa_list_string_flags(audio_output_flags_t flags) {
- return list_string(string_conversion_table_output_flag, flags);
-}
-
-bool pa_input_device_default_audio_source(audio_devices_t input_device, audio_source_t *default_source)
-{
-#if AUDIO_API_VERSION_MAJ >= 2
- input_device &= ~AUDIO_DEVICE_BIT_IN;
-#endif
-
- /* Note converting HAL values to different HAL values! */
- for (unsigned int i = 0; i < sizeof(conversion_table_default_audio_source) / (sizeof(uint32_t) * 2); i++) {
- if (conversion_table_default_audio_source[i][0] & input_device) {
- *default_source = conversion_table_default_audio_source[i][1];
- return true;
- }
- }
- return false;
-}
-
-/* Config parser */
-
-#define WHITESPACE "\n\r \t"
-
-static int parse_list(const struct string_conversion *table,
- const char *str,
- uint32_t *dst,
- char **unknown_entries) {
- int count = 0;
- char *entry;
- char *unknown = NULL;
- const char *state = NULL;
-
- pa_assert(table);
- pa_assert(str);
- pa_assert(dst);
- pa_assert(unknown_entries);
-
- *dst = 0;
- *unknown_entries = NULL;
-
- while ((entry = pa_split(str, "|", &state))) {
- uint32_t d = 0;
-
- if (!string_convert_str_to_num(table, entry, &d)) {
- if (*unknown_entries) {
- unknown = pa_sprintf_malloc("%s|%s", *unknown_entries, entry);
- pa_xfree(*unknown_entries);
- pa_xfree(entry);
- } else
- unknown = entry;
-
- *unknown_entries = unknown;
- continue;
- }
-
- *dst |= d;
- count++;
-
- pa_xfree(entry);
- }
-
- return count;
-}
-
-static bool parse_sampling_rates(const char *fn, const unsigned ln,
- const char *str, uint32_t sampling_rates[32]) {
- pa_assert(fn);
- pa_assert(str);
-
- char *entry;
- const char *state = NULL;
-
- uint32_t pos = 0;
- while ((entry = pa_split(str, "|", &state))) {
- int32_t val;
-
-#if AUDIO_API_VERSION_MAJ >= 3
- if (pos == 0 && pa_streq(entry, "dynamic")) {
- sampling_rates[pos++] = (uint32_t) -1;
- pa_xfree(entry);
- break;
- }
-#endif
-
- if (pos == AUDIO_MAX_SAMPLING_RATES) {
- pa_log("[%s:%u] Too many sample rate entries (> %d)", fn, ln, AUDIO_MAX_SAMPLING_RATES);
- pa_xfree(entry);
- return false;
- }
-
- if (pa_atoi(entry, &val) < 0) {
- pa_log("[%s:%u] Bad sample rate value %s", fn, ln, entry);
- pa_xfree(entry);
- return false;
- }
-
- sampling_rates[pos++] = val;
-
- pa_xfree(entry);
-
- }
-
- sampling_rates[pos] = 0;
-
- return true;
-}
-
-static bool check_and_log(const char *fn, const unsigned ln, const char *field,
- const int count, const char *str, char *unknown,
- const bool must_have_all) {
- bool fail;
-
- pa_assert(fn);
- pa_assert(field);
- pa_assert(str);
-
- fail = must_have_all && unknown;
-
- if (unknown) {
- pa_log_info("[%s:%u] Unknown %s entries: %s", fn, ln, field, unknown);
- pa_xfree(unknown);
- }
-
- if (count == 0 || fail) {
- pa_log("[%s:%u] Failed to parse %s (%s).", fn, ln, field, str);
- return false;
- }
-
- return true;
-}
-
-static bool parse_formats(const char *fn, const unsigned ln,
- const char *str, audio_format_t *formats) {
- int count;
- char *unknown = NULL;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(formats);
-
-#if AUDIO_API_VERSION_MAJ >= 3
- /* Needs to be probed later */
- if (pa_streq(str, "dynamic")) {
- *formats = 0;
- return true;
- }
-#endif
-
- count = parse_list(string_conversion_table_format, str, formats, &unknown);
-
- return check_and_log(fn, ln, "formats", count, str, unknown, false);
-}
-
-static bool parse_channels(const char *fn, const unsigned ln,
- const char *str, bool in_output, audio_channel_mask_t *channels) {
- int count;
- char *unknown = NULL;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(channels);
-
- /* Needs to be probed later */
- if (pa_streq(str, "dynamic")) {
- *channels = 0;
- return true;
- }
-
- count = parse_list(in_output ? string_conversion_table_output_channels
- : string_conversion_table_input_channels,
- str, channels, &unknown);
-
- return check_and_log(fn, ln, in_output ? "output channel_masks" : "input channel_masks",
- count, str, unknown, false);
-}
-
-static bool parse_devices(const char *fn, const unsigned ln,
- const char *str, bool in_output, audio_devices_t *devices, bool must_have_all) {
- int count;
- char *unknown = NULL;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(devices);
-
- count = parse_list(in_output ? string_conversion_table_output_device
- : string_conversion_table_input_device,
- str, devices, &unknown);
-
- return check_and_log(fn, ln, in_output ? "output devices" : "input devices",
- count, str, unknown, must_have_all);
-}
-
-static bool parse_output_flags(const char *fn, const unsigned ln,
- const char *str, audio_output_flags_t *flags) {
- int count;
- char *unknown = NULL;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(flags);
-
- count = parse_list(string_conversion_table_output_flag, str, flags, &unknown);
-
- return check_and_log(fn, ln, "flags", count, str, unknown, false);
-}
-
-#if AUDIO_API_VERSION_MAJ >= 3
-static bool parse_input_flags(const char *fn, const unsigned ln,
- const char *str, audio_input_flags_t *flags) {
- int count;
- char *unknown = NULL;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(flags);
-
- count = parse_list(string_conversion_table_input_flag, str, flags, &unknown);
-
- return check_and_log(fn, ln, "flags", count, str, unknown, false);
-}
-#endif
-
-static bool parse_version(const char *fn, const unsigned ln, const char *str, uint32_t *version) {
- uint32_t version_maj;
- uint32_t version_min;
-
- pa_assert(fn);
- pa_assert(str);
- pa_assert(version);
-
- if ((sscanf(str, "%u.%u", &version_maj, &version_min)) != 2) {
- pa_log("[%s:%u] Failed to parse %s (%s).", fn, ln, AUDIO_HAL_VERSION_TAG, str);
- return false;
- } else {
- *version = HARDWARE_DEVICE_API_VERSION(version_maj, version_min);
- return true;
- }
-}
-
-static void log_parse_error(const char *fn, const unsigned ln, const char *section, const char *v) {
- pa_log("[%s:%u] failed to parse line in section %s: unknown section (%s)", fn, ln, section, v);
-}
-
-#define MAX_LINE_LENGTH (1024)
-
-bool pa_parse_droid_audio_config(const char *filename, pa_droid_config_audio *config) {
- FILE *f;
- unsigned n = 0;
- bool ret = true;
- char *full_line = NULL;
- uint32_t hw_module_count = 0;
-
- enum config_loc {
- IN_ROOT = 0,
- IN_GLOBAL = 1,
- IN_GLOBAL_EXT = 2,
- IN_HW_MODULES = 3,
- IN_MODULE = 4,
- IN_OUTPUT_INPUT = 5,
- IN_CONFIG = 6,
- IN_MODULE_GLOBAL = 10,
- IN_DEVICES = 20,
- IN_DEVICES_DEVICE = 21,
- IN_GAINS = 22,
- IN_GAIN_N = 23
- } loc = IN_ROOT;
-
- bool in_output = true;
-
- pa_droid_config_hw_module *module = NULL;
- pa_droid_config_output *output = NULL;
- pa_droid_config_input *input = NULL;
-
- pa_assert(filename);
- pa_assert(config);
-
- memset(config, 0, sizeof(pa_droid_config_audio));
- config->global_config = pa_xnew0(pa_droid_config_global, 1);
-
- f = fopen(filename, "r");
-
- if (!f) {
- pa_log_info("Failed to open config file (%s): %s", filename, pa_cstrerror(errno));
- ret = false;
- goto finish;
- }
-
- pa_lock_fd(fileno(f), 1);
-
- full_line = pa_xmalloc0(sizeof(char) * MAX_LINE_LENGTH);
-
- while (!feof(f)) {
- char *ln, *d, *v, *value;
-
- if (!fgets(full_line, MAX_LINE_LENGTH, f))
- break;
-
- n++;
-
- pa_strip_nl(full_line);
-
- if (!*full_line)
- continue;
-
- ln = full_line + strspn(full_line, WHITESPACE);
-
- if (ln[0] == '#')
- continue;
-
- v = ln;
- d = v + strcspn(v, WHITESPACE);
-
- value = d + strspn(d, WHITESPACE);
- d[0] = '\0';
- d = value + strcspn(value, WHITESPACE);
- d[0] = '\0';
-
- /* Enter section */
- if (pa_streq(value, "{")) {
-
- if (!*v) {
- pa_log("[%s:%u] failed to parse line - too few words", filename, n);
- goto finish;
- }
-
- switch (loc) {
- case IN_ROOT:
- if (pa_streq(v, GLOBAL_CONFIG_TAG)) {
- loc = IN_GLOBAL;
- }
- else if (pa_streq(v, AUDIO_HW_MODULE_TAG))
- loc = IN_HW_MODULES;
- else {
- log_parse_error(filename, n, "<root>", v);
- ret = false;
- goto finish;
- }
- break;
-
- case IN_GLOBAL:
- if (pa_streq(v, GLOBAL_CONFIG_EXT_TAG))
- loc = IN_GLOBAL_EXT;
- else {
- log_parse_error(filename, n, GLOBAL_CONFIG_TAG, v);
- ret = false;
- goto finish;
- }
- break;
-
- case IN_HW_MODULES:
- pa_assert(!module);
-
- module = pa_xnew0(pa_droid_config_hw_module, 1);
- SLLIST_APPEND(pa_droid_config_hw_module, config->hw_modules, module);
- hw_module_count++;
- module->name = pa_xstrndup(v, AUDIO_HARDWARE_MODULE_ID_MAX_LEN);
- module->config = config;
- loc = IN_MODULE;
- pa_log_debug("config: New module: %s", module->name);
- break;
-
- case IN_MODULE:
- pa_assert(module);
-
- if (pa_streq(v, OUTPUTS_TAG)) {
- loc = IN_OUTPUT_INPUT;
- in_output = true;
- } else if (pa_streq(v, INPUTS_TAG)) {
- loc = IN_OUTPUT_INPUT;
- in_output = false;
- } else if (pa_streq(v, GLOBAL_CONFIG_TAG)) {
- loc = IN_MODULE_GLOBAL;
- } else if (pa_streq(v, DEVICES_TAG)) {
- loc = IN_DEVICES;
- } else {
- log_parse_error(filename, n, module->name, v);
- ret = false;
- goto finish;
- }
- break;
-
- case IN_OUTPUT_INPUT:
- pa_assert(module);
-
- if (in_output) {
- output = pa_xnew0(pa_droid_config_output, 1);
- SLLIST_APPEND(pa_droid_config_output, module->outputs, output);
- output->name = pa_xstrndup(v, AUDIO_HARDWARE_MODULE_ID_MAX_LEN);
- output->module = module;
- loc = IN_CONFIG;
- pa_log_debug("config: %s: New output: %s", module->name, output->name);
- } else {
- input = pa_xnew0(pa_droid_config_input, 1);
- SLLIST_APPEND(pa_droid_config_input, module->inputs, input);
- input->name = pa_xstrndup(v, AUDIO_HARDWARE_MODULE_ID_MAX_LEN);
- input->module = module;
- loc = IN_CONFIG;
- pa_log_debug("config: %s: New input: %s", module->name, input->name);
- }
- break;
-
- case IN_DEVICES:
- /* TODO Missing implementation of parsing the module/devices section.
- * As of now there is no need for the information, fix this when that
- * changes. */
- loc = IN_DEVICES_DEVICE;
- break;
-
- case IN_DEVICES_DEVICE:
- if (pa_streq(v, GAINS_TAG))
- loc = IN_GAINS;
- else {
- log_parse_error(filename, n, DEVICES_TAG, v);
- ret = false;
- goto finish;
- }
- break;
-
- case IN_GAINS:
- /* TODO Missing implementation of parsing the gain_n section.
- * As of now there is no need for the information, fix this when that
- * changes. */
- if (pa_startswith(v, GAIN_TAG_PREFIX))
- loc = IN_GAIN_N;
- else {
- log_parse_error(filename, n, GAINS_TAG, v);
- ret = false;
- goto finish;
- }
- break;
-
- case IN_CONFIG:
- if (pa_streq(v, GAINS_TAG)) {
- loc = IN_GAINS;
- } else {
- log_parse_error(filename, n, in_output ? output->name : input->name, v);
- ret = false;
- goto finish;
- }
- break;
-
- default:
- pa_log("[%s:%u] failed to parse line: unknown section (%s)", filename, n, v);
- ret = false;
- goto finish;
- }
-
- continue;
- }
-
- /* Exit section */
- if (pa_streq(v, "}")) {
- switch (loc) {
- case IN_ROOT:
- pa_log("[%s:%u] failed to parse line - extra closing bracket", filename, n);
- ret = false;
- goto finish;
-
- case IN_HW_MODULES:
- /* fall through */
- case IN_GLOBAL:
- loc = IN_ROOT;
- break;
-
- case IN_MODULE:
- module = NULL;
- loc = IN_HW_MODULES;
- break;
-
- case IN_DEVICES:
- /* fall through */
- case IN_MODULE_GLOBAL:
- loc = IN_MODULE;
- break;
-
- case IN_GAINS:
- if (output || input)
- loc = IN_CONFIG;
- else
- loc = IN_DEVICES_DEVICE;
- break;
-
- case IN_OUTPUT_INPUT:
- if (in_output)
- output = NULL;
- else
- input = NULL;
- /* fall through */
- case IN_GAIN_N:
- /* fall through */
- case IN_DEVICES_DEVICE:
- /* fall through */
- case IN_CONFIG:
- /* fall through */
- case IN_GLOBAL_EXT:
- loc--;
- break;
- }
-
- continue;
- }
-
- /* Parsing of values */
- if (loc == IN_GLOBAL ||
- loc == IN_GLOBAL_EXT ||
- loc == IN_MODULE_GLOBAL ||
- loc == IN_CONFIG ||
- loc == IN_DEVICES_DEVICE ||
- loc == IN_GAIN_N) {
-
- bool success = false;
-
- if (loc == IN_GLOBAL || loc == IN_MODULE_GLOBAL) {
- pa_droid_config_global *global_config = NULL;
-
- if (loc == IN_MODULE_GLOBAL) {
- pa_assert(module);
- if (!module->global_config)
- module->global_config = pa_xnew0(pa_droid_config_global, 1);
- global_config = module->global_config;
- } else
- global_config = config->global_config;
-
- pa_assert(global_config);
-
- /* Parse global configuration */
-
- if (pa_streq(v, ATTACHED_OUTPUT_DEVICES_TAG))
- success = parse_devices(filename, n, value, true,
- &global_config->attached_output_devices, false);
- else if (pa_streq(v, DEFAULT_OUTPUT_DEVICE_TAG))
- success = parse_devices(filename, n, value, true,
- &global_config->default_output_device, true);
- else if (pa_streq(v, ATTACHED_INPUT_DEVICES_TAG))
- success = parse_devices(filename, n, value, false,
- &global_config->attached_input_devices, false);
- else if (pa_streq(v, AUDIO_HAL_VERSION_TAG))
- success = parse_version(filename, n, value,
- &global_config->audio_hal_version);
-#ifdef DROID_HAVE_DRC
- // SPEAKER_DRC_ENABLED_TAG is only from Android v4.4
- else if (pa_streq(v, SPEAKER_DRC_ENABLED_TAG))
- /* TODO - Add support for dynamic range control */
- success = true; /* Do not fail while parsing speaker_drc_enabled entry */
-#endif
- else {
- pa_log("[%s:%u] failed to parse line - unknown config entry %s", filename, n, v);
- success = false;
- }
-
- } else if (loc == IN_GLOBAL_EXT) {
-
- /* Parse custom global configuration
- * For now just log all custom variables, don't do
- * anything with the values.
- * TODO: Store custom values somehow */
-
- pa_log_debug("[%s:%u] TODO custom variable: %s = %s", filename, n, v, value);
- success = true;
-
- } else if (loc == IN_CONFIG) {
-
- /* Parse per-output or per-input configuration */
-
- if ((in_output && !output) || (!in_output && !input)) {
- pa_log("[%s:%u] failed to parse line", filename, n);
- ret = false;
- goto finish;
- }
-
- if (pa_streq(v, SAMPLING_RATES_TAG))
- success = parse_sampling_rates(filename, n, value,
- in_output ? output->sampling_rates : input->sampling_rates);
- else if (pa_streq(v, FORMATS_TAG))
- success = parse_formats(filename, n, value, in_output ? &output->formats : &input->formats);
- else if (pa_streq(v, CHANNELS_TAG)) {
- if (in_output)
- success = parse_channels(filename, n, value, true, &output->channel_masks);
- else
- success = parse_channels(filename, n, value, false, &input->channel_masks);
- } else if (pa_streq(v, DEVICES_TAG)) {
- if (in_output)
- success = parse_devices(filename, n, value, true, &output->devices, false);
- else
- success = parse_devices(filename, n, value, false, &input->devices, false);
- } else if (pa_streq(v, FLAGS_TAG)) {
- if (in_output)
- success = parse_output_flags(filename, n, value, &output->flags);
- else {
-#if AUDIO_API_VERSION_MAJ >= 3
- success = parse_input_flags(filename, n, value, &input->flags);
-#else
- pa_log("[%s:%u] failed to parse line - output flags inside input definition", filename, n);
- success = false;
-#endif
- }
- } else {
- pa_log("[%s:%u] failed to parse line - unknown config entry %s", filename, n, v);
- success = false;
- }
-
- } else if (loc == IN_DEVICES_DEVICE) {
- /* TODO Missing implementation of parsing the module/devices section.
- * As of now there is no need for the information, fix this when that
- * changes. */
- success = true;
- } else if (loc == IN_GAIN_N) {
- /* TODO Missing implementation of parsing the gain_n section.
- * As of now there is no need for the information, fix this when that
- * changes. */
- success = true;
- } else
- pa_assert_not_reached();
-
- if (!success) {
- ret = false;
- goto finish;
- }
- }
- }
-
- pa_log_info("Parsed config file (%s): %u modules.", filename, hw_module_count);
-
-finish:
- if (f) {
- pa_lock_fd(fileno(f), 0);
- fclose(f);
- }
-
- pa_xfree(full_line);
-
- return ret;
-}
-
-
-const pa_droid_config_output *pa_droid_config_find_output(const pa_droid_config_hw_module *module, const char *name) {
- pa_droid_config_output *output;
-
- pa_assert(module);
- pa_assert(name);
-
- SLLIST_FOREACH(output, module->outputs) {
- if (pa_streq(name, output->name))
- return output;
- }
-
- return NULL;
-}
-
-const pa_droid_config_input *pa_droid_config_find_input(const pa_droid_config_hw_module *module, const char *name) {
- pa_droid_config_input *input;
-
- pa_assert(module);
- pa_assert(name);
-
- SLLIST_FOREACH(input, module->inputs) {
- if (pa_streq(name, input->name))
- return input;
- }
-
- return NULL;
-}
-
-const pa_droid_config_hw_module *pa_droid_config_find_module(const pa_droid_config_audio *config, const char* module_id) {
- pa_droid_config_hw_module *module;
-
- pa_assert(config);
- pa_assert(module_id);
-
- SLLIST_FOREACH(module, config->hw_modules) {
- if (pa_streq(module_id, module->name))
- return module;
- }
-
- return NULL;
-}
-
static pa_droid_profile *profile_new(pa_droid_profile_set *ps,
const pa_droid_config_hw_module *module,
const char *name,
@@ -945,15 +121,17 @@
}
static pa_droid_profile *droid_profile_new(pa_droid_profile_set *ps,
- const pa_droid_config_output *primary_output,
- const pa_droid_config_output *output,
- const pa_droid_config_input *input) {
+ const pa_droid_config_device *primary_output,
+ const pa_droid_config_device *output,
+ const pa_droid_config_device *input) {
pa_droid_profile *p;
char *name;
char *description;
pa_assert(ps);
pa_assert(output);
+ pa_assert(!primary_output || primary_output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(!input || input->direction == PA_DIRECTION_INPUT);
name = pa_sprintf_malloc("%s%s%s", output->name, input ? "-" : "", input ? input->name : "");
description = pa_sprintf_malloc("%s output%s%s%s", output->name,
@@ -973,11 +151,11 @@
}
if (primary_output && primary_output != output)
- pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, primary_output), NULL);
+ pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, primary_output), NULL);
if (output)
- pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, output), NULL);
+ pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, output), NULL);
if (input)
- pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_INPUT, input), NULL);
+ pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, input), NULL);
return p;
}
@@ -993,11 +171,15 @@
}
static pa_droid_profile *add_profile(pa_droid_profile_set *ps,
- const pa_droid_config_output *primary_output,
- const pa_droid_config_output *output,
- const pa_droid_config_input *input) {
+ const pa_droid_config_device *primary_output,
+ const pa_droid_config_device *output,
+ const pa_droid_config_device *input) {
pa_droid_profile *ap;
+ pa_assert(primary_output && primary_output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(output && output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(!input || input->direction == PA_DIRECTION_INPUT);
+
pa_log_debug("New profile: %s-%s", output->name, input ? input->name : "no input");
ap = droid_profile_new(ps, primary_output, output, input);
@@ -1028,12 +210,13 @@
static void add_all_profiles(pa_droid_profile_set *ps,
const pa_droid_config_hw_module *module,
- const pa_droid_config_output *primary_output) {
- pa_droid_config_output *output;
- pa_droid_config_input *input;
+ const pa_droid_config_device *primary_output) {
+ pa_droid_config_device *output;
+ pa_droid_config_device *input;
pa_assert(ps);
pa_assert(module);
+ pa_assert(primary_output && primary_output->direction == PA_DIRECTION_OUTPUT);
/* Each distinct hw module output matches one profile. If there are multiple inputs
* combinations are made so that all possible outputs and inputs can be selected.
@@ -1061,36 +244,41 @@
static void add_default_profile(pa_droid_profile_set *ps,
const pa_droid_config_hw_module *module,
- const pa_droid_config_output *primary_output,
- const pa_droid_config_output *low_latency_output,
- const pa_droid_config_output *media_latency_output,
- const pa_droid_config_input *builtin_input,
- const pa_droid_config_input *external_input,
+ const pa_droid_config_device *primary_output,
+ const pa_droid_config_device *low_latency_output,
+ const pa_droid_config_device *media_latency_output,
+ const pa_droid_config_device *builtin_input,
+ const pa_droid_config_device *external_input,
bool merge_inputs) {
pa_droid_profile *p;
pa_assert(ps);
pa_assert(module);
+ pa_assert(!primary_output || primary_output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(!low_latency_output || primary_output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(!media_latency_output || primary_output->direction == PA_DIRECTION_OUTPUT);
+ pa_assert(!builtin_input || builtin_input->direction == PA_DIRECTION_INPUT);
+ pa_assert(!external_input || external_input->direction == PA_DIRECTION_INPUT);
pa_log_debug("New default profile");
p = profile_new(ps, module, "default", "Default profile");
if (primary_output)
- pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, primary_output), NULL);
+ pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, primary_output), NULL);
if (low_latency_output && primary_output != low_latency_output)
- pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, low_latency_output), NULL);
+ pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, low_latency_output), NULL);
if (media_latency_output && primary_output != media_latency_output && low_latency_output != media_latency_output)
- pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, media_latency_output), NULL);
+ pa_idxset_put(p->output_mappings, pa_droid_mapping_get(ps, media_latency_output), NULL);
if (builtin_input && external_input && builtin_input != external_input && merge_inputs) {
pa_idxset_put(p->input_mappings, pa_droid_mapping_merged_get(ps, builtin_input, external_input), NULL);
} else {
if (builtin_input)
- pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_INPUT, builtin_input), NULL);
+ pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, builtin_input), NULL);
if (external_input && builtin_input != external_input)
- pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, PA_DIRECTION_INPUT, external_input), NULL);
+ pa_idxset_put(p->input_mappings, pa_droid_mapping_get(ps, external_input), NULL);
}
p->priority += DEFAULT_PRIORITY * (pa_idxset_size(p->output_mappings) + pa_idxset_size(p->input_mappings));
@@ -1101,15 +289,15 @@
static void auto_add_profiles(pa_droid_profile_set *ps,
const pa_droid_config_hw_module *module,
bool merge_inputs) {
- const pa_droid_config_output *output;
- const pa_droid_config_input *input;
+ const pa_droid_config_device *output;
+ const pa_droid_config_device *input;
- const pa_droid_config_output *primary_output = NULL;
- const pa_droid_config_output *low_latency_output = NULL;
- const pa_droid_config_output *media_latency_output = NULL;
+ const pa_droid_config_device *primary_output = NULL;
+ const pa_droid_config_device *low_latency_output = NULL;
+ const pa_droid_config_device *media_latency_output = NULL;
- const pa_droid_config_input *builtin_input = NULL;
- const pa_droid_config_input *external_input = NULL;
+ const pa_droid_config_device *builtin_input = NULL;
+ const pa_droid_config_device *external_input = NULL;
uint32_t input_devices;
@@ -1388,42 +576,35 @@
pa_idxset_put(am->ports, p, NULL);
}
-pa_droid_mapping *pa_droid_mapping_get(pa_droid_profile_set *ps, pa_direction_t direction, const void *data) {
+pa_droid_mapping *pa_droid_mapping_get(pa_droid_profile_set *ps, const pa_droid_config_device *device) {
pa_droid_mapping *am;
pa_hashmap *map;
- const char *name;
- const pa_droid_config_output *output = NULL;
- const pa_droid_config_input *input = NULL;
- if (direction == PA_DIRECTION_OUTPUT) {
- output = (pa_droid_config_output *) data;
- map = ps->output_mappings;
- name = output->name;
- } else {
- input = (pa_droid_config_input *) data;
- map = ps->input_mappings;
- name = input->name;
- }
+ pa_assert(ps);
+ pa_assert(device);
- if ((am = pa_hashmap_get(map, name))) {
- pa_log_debug(" %s mapping %s from cache", input ? "Input" : "Output", name);
+ map = device->direction == PA_DIRECTION_OUTPUT ? ps->output_mappings : ps->input_mappings;
+
+ if ((am = pa_hashmap_get(map, device->name))) {
+ pa_log_debug(" %s mapping %s from cache", pa_direction_to_string(device->direction), device->name);
return am;
}
- pa_log_debug(" New %s mapping %s", input ? "input" : "output", name);
+ pa_log_debug(" New %s mapping %s", pa_direction_to_string(device->direction), device->name);
am = pa_xnew0(pa_droid_mapping, 1);
am->profile_set = ps;
- am->name = pa_xstrdup(name);
+ am->name = pa_xstrdup(device->name);
am->proplist = pa_proplist_new();
- am->direction = direction;
- am->output = output;
- am->input = input;
+ am->direction = device->direction;
am->ports = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);;
- if (am->direction == PA_DIRECTION_OUTPUT)
+ if (am->direction == PA_DIRECTION_OUTPUT) {
+ am->output = device;
add_o_ports(am);
- else
+ } else {
+ am->input = device;
add_i_ports(am);
+ }
pa_hashmap_put(map, am->name, am);
@@ -1431,16 +612,20 @@
}
pa_droid_mapping *pa_droid_mapping_merged_get(pa_droid_profile_set *ps,
- const pa_droid_config_input *input1,
- const pa_droid_config_input *input2) {
+ const pa_droid_config_device *input1,
+ const pa_droid_config_device *input2) {
pa_droid_mapping *am;
pa_hashmap *map = ps->input_mappings;
char *name;
+ pa_assert(ps);
+ pa_assert(input1 && input1->direction == PA_DIRECTION_INPUT);
+ pa_assert(input2 && input2->direction == PA_DIRECTION_INPUT);
+
name = pa_sprintf_malloc("%s+%s", input1->name, input2->name);
if ((am = pa_hashmap_get(map, name))) {
- pa_log_debug(" Input mapping %s from cache", name);
+ pa_log_debug(" input mapping %s from cache", name);
pa_xfree(name);
return am;
}
@@ -1468,13 +653,13 @@
if (am->direction == PA_DIRECTION_OUTPUT) {
pa_assert(am->output);
- return pa_streq(am->output->name, PA_DROID_PRIMARY_DEVICE);
+ return am->output->flags & AUDIO_OUTPUT_FLAG_PRIMARY;
} else {
pa_assert(am->input);
/* merged input mapping is always primary */
if (am->input && am->input2)
return true;
- return pa_streq(am->input->name, PA_DROID_PRIMARY_DEVICE);
+ return pa_startswith(am->input->name, PA_DROID_PRIMARY_DEVICE);
}
}
@@ -1519,18 +704,6 @@
return NULL;
}
-bool pa_droid_output_port_name(audio_devices_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_output_device_fancy, (uint32_t) value, to_str);
-}
-
-bool pa_droid_input_port_name(audio_devices_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_input_device_fancy, (uint32_t) value, to_str);
-}
-
-bool pa_droid_audio_source_name(audio_source_t value, const char **to_str) {
- return string_convert_num_to_str(string_conversion_table_audio_source_fancy, (uint32_t) value, to_str);
-}
-
static int add_ports(pa_core *core, pa_card_profile *cp, pa_hashmap *ports, pa_droid_mapping *am, pa_hashmap *extra) {
pa_droid_port *p;
pa_device_port_new_data dp_data;
@@ -1837,7 +1010,7 @@
return pa_sprintf_malloc("droid-hardware-module-%s", module_id);
}
-static pa_droid_hw_module *droid_hw_module_open(pa_core *core, pa_droid_config_audio *config, const char *module_id) {
+static pa_droid_hw_module *droid_hw_module_open(pa_core *core, const pa_droid_config_audio *config, const char *module_id) {
const pa_droid_config_hw_module *module;
pa_droid_hw_module *hw = NULL;
struct hw_module_t *hwmod = NULL;
@@ -1848,13 +1021,13 @@
pa_assert(core);
pa_assert(module_id);
- pa_log_info("Droid hw module %s", VERSION);
-
if (!config) {
- pa_log("No configuration provided for opening module with id %s", module_id);
+ pa_log_debug("No configuration provided for opening module with id %s", module_id);
goto fail;
}
+ pa_log_info("Droid hw module %s", VERSION);
+
if (!(module = pa_droid_config_find_module(config, module_id))) {
pa_log("Couldn't find module with id %s", module_id);
goto fail;
@@ -1893,7 +1066,7 @@
hw->output_mutex = pa_mutex_new(true, false);
hw->input_mutex = pa_mutex_new(true, false);
hw->device = device;
- hw->config = config; /* We take ownership of config struct. */
+ hw->config = pa_droid_config_dup(config);
hw->enabled_module = pa_droid_config_find_module(hw->config, module_id);
hw->module_id = hw->enabled_module->name;
hw->shared_name = shared_name_get(hw->module_id);
@@ -1927,7 +1100,7 @@
return NULL;
}
-pa_droid_hw_module *pa_droid_hw_module_get(pa_core *core, pa_droid_config_audio *config, const char *module_id) {
+pa_droid_hw_module *pa_droid_hw_module_get(pa_core *core, const pa_droid_config_audio *config, const char *module_id) {
pa_droid_hw_module *hw;
char *shared_name;
@@ -1973,10 +1146,14 @@
pa_hook_done(&hw->hooks[h]);
if (hw->config)
- droid_config_free(hw->config);
+ pa_droid_config_free(hw->config);
- if (hw->device && !pa_droid_quirk(hw, QUIRK_UNLOAD_NO_CLOSE))
- audio_hw_device_close(hw->device);
+ if (hw->device) {
+ if (pa_droid_quirk(hw, QUIRK_UNLOAD_CALL_EXIT))
+ exit(EXIT_SUCCESS);
+ else if (!pa_droid_quirk(hw, QUIRK_UNLOAD_NO_CLOSE))
+ audio_hw_device_close(hw->device);
+ }
if (hw->hw_mutex)
pa_mutex_free(hw->hw_mutex);
@@ -2017,72 +1194,6 @@
droid_hw_module_close(hw);
}
-static void droid_config_free(pa_droid_config_audio *config) {
- pa_droid_config_hw_module *module;
- pa_droid_config_output *output;
- pa_droid_config_input *input;
-
- pa_assert(config);
-
- while (config->hw_modules) {
- SLLIST_STEAL_FIRST(module, config->hw_modules);
-
- while (module->outputs) {
- SLLIST_STEAL_FIRST(output, module->outputs);
- pa_xfree(output->name);
- pa_xfree(output);
- }
-
- while (module->inputs) {
- SLLIST_STEAL_FIRST(input, module->inputs);
- pa_xfree(input->name);
- pa_xfree(input);
- }
-
- pa_xfree(module->global_config);
- pa_xfree(module->name);
- pa_xfree(module);
- }
-
- pa_xfree(config->global_config);
- pa_xfree(config);
-}
-
-pa_droid_config_audio *pa_droid_config_load(pa_modargs *ma) {
- pa_droid_config_audio *config;
- const char *config_location;
-
- pa_assert(ma);
-
- config = pa_xnew0(pa_droid_config_audio, 1);
-
- if ((config_location = pa_modargs_get_value(ma, "config", NULL))) {
- if (!pa_parse_droid_audio_config(config_location, config)) {
- pa_log("Failed to parse configuration from %s", config_location);
- goto fail;
- }
- } else {
- config_location = AUDIO_POLICY_VENDOR_CONFIG_FILE;
-
- if (!pa_parse_droid_audio_config(config_location, config)) {
- pa_log_debug("Failed to parse configuration from vendor %s", config_location);
-
- config_location = AUDIO_POLICY_CONFIG_FILE;
-
- if (!pa_parse_droid_audio_config(config_location, config)) {
- pa_log("Failed to parse configuration from %s", config_location);
- goto fail;
- }
- }
- }
-
- return config;
-
-fail:
- droid_config_free(config);
- return NULL;
-}
-
void pa_droid_hw_module_lock(pa_droid_hw_module *hw) {
pa_assert(hw);
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/include/droid/conversion.h
^
|
@@ -0,0 +1,112 @@
+#ifndef foodroidconversionfoo
+#define foodroidconversionfoo
+
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pulsecore/modargs.h>
+
+#include <hardware/audio.h>
+
+/* From recent audio_policy_conf.h */
+#ifndef AUDIO_HAL_VERSION_TAG
+#define AUDIO_HAL_VERSION_TAG "audio_hal_version"
+#endif
+#ifndef GAINS_TAG
+#define GAINS_TAG "gains"
+#endif
+
+#include <droid/version.h>
+#include <droid/droid-config.h>
+
+typedef enum {
+ CONV_FROM_PA,
+ CONV_FROM_HAL
+} pa_conversion_field_t;
+
+typedef enum {
+ CONV_STRING_FORMAT,
+ CONV_STRING_OUTPUT_CHANNELS,
+ CONV_STRING_INPUT_CHANNELS,
+ CONV_STRING_OUTPUT_DEVICE,
+ CONV_STRING_INPUT_DEVICE,
+ CONV_STRING_OUTPUT_FLAG,
+ CONV_STRING_INPUT_FLAG
+} pa_conversion_string_t;
+
+bool pa_convert_output_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
+bool pa_convert_input_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
+bool pa_convert_format(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
+
+bool pa_string_convert_output_device_num_to_str(audio_devices_t value, const char **to_str);
+bool pa_string_convert_output_device_str_to_num(const char *str, audio_devices_t *to_value);
+bool pa_string_convert_input_device_num_to_str(audio_devices_t value, const char **to_str);
+bool pa_string_convert_input_device_str_to_num(const char *str, audio_devices_t *to_value);
+
+bool pa_string_convert_flag_num_to_str(audio_output_flags_t value, const char **to_str);
+bool pa_string_convert_flag_str_to_num(const char *str, audio_output_flags_t *to_value);
+
+char *pa_list_string_output_device(audio_devices_t devices);
+char *pa_list_string_input_device(audio_devices_t devices);
+char *pa_list_string_flags(audio_output_flags_t flags);
+
+/* Get default audio source associated with input device.
+ * Return true if default source was found. */
+bool pa_input_device_default_audio_source(audio_devices_t input_device, audio_source_t *default_source);
+
+/* Pretty port names */
+bool pa_droid_output_port_name(audio_devices_t value, const char **to_str);
+bool pa_droid_input_port_name(audio_devices_t value, const char **to_str);
+
+/* Pretty audio source names */
+bool pa_droid_audio_source_name(audio_source_t value, const char **to_str);
+
+int pa_conversion_parse_list(pa_conversion_string_t type, const char *separator,
+ const char *str, uint32_t *dst, char **unknown_entries);
+
+bool pa_conversion_parse_sampling_rates(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]);
+bool pa_conversion_parse_formats(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_format_t *formats);
+bool pa_conversion_parse_output_channels(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_channel_mask_t *channels);
+bool pa_conversion_parse_input_channels(const char *fn, const unsigned ln,
+ const char *str, bool legacy,
+ audio_channel_mask_t *channels);
+bool pa_conversion_parse_output_devices(const char *fn, const unsigned ln,
+ char *str, bool legacy, bool must_recognize_all,
+ audio_devices_t *devices);
+bool pa_conversion_parse_input_devices(const char *fn, const unsigned ln,
+ char *str, bool legacy, bool must_recognize_all,
+ audio_devices_t *devices);
+bool pa_conversion_parse_output_flags(const char *fn, const unsigned ln,
+ const char *str, audio_output_flags_t *flags);
+bool pa_conversion_parse_input_flags(const char *fn, const unsigned ln,
+ const char *str, uint32_t *flags);
+bool pa_conversion_parse_version(const char *fn, const unsigned ln, const char *str, uint32_t *version);
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/include/droid/droid-config.h
^
|
@@ -0,0 +1,102 @@
+#ifndef foodroidconfigfoo
+#define foodroidconfigfoo
+
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pulsecore/modargs.h>
+
+#include <android-config.h>
+#include <hardware/audio.h>
+
+#include <droid/version.h>
+
+typedef struct pa_droid_config_audio pa_droid_config_audio;
+typedef struct pa_droid_config_hw_module pa_droid_config_hw_module;
+
+#define AUDIO_MAX_SAMPLING_RATES (32)
+
+typedef struct pa_droid_config_global {
+ uint32_t audio_hal_version;
+ audio_devices_t attached_output_devices;
+ audio_devices_t default_output_device;
+ audio_devices_t attached_input_devices;
+} pa_droid_config_global;
+
+typedef struct pa_droid_config_device {
+ const pa_droid_config_hw_module *module;
+
+ char *name;
+ uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]; /* (uint32_t) -1 -> dynamic */
+ audio_channel_mask_t channel_masks; /* 0 -> dynamic */
+ audio_format_t formats; /* 0 -> dynamic */
+ audio_devices_t devices;
+ /* Instead of using audio_output_flags_t and audio_input_flags_t
+ * unify the flags as uint32_t so that we can have single struct for both
+ * output and input configurations.
+ * audio_input_flags_t was introduced in APIs 2 & 3, depending on adaptation,
+ * so having input flags as uint32_t is simpler from input implementation
+ * point of view as well. */
+ uint32_t flags;
+ pa_direction_t direction;
+
+ struct pa_droid_config_device *next;
+} pa_droid_config_device;
+
+struct pa_droid_config_hw_module {
+ const pa_droid_config_audio *config;
+
+ char *name;
+ /* If global config is not defined for module, use root global config. */
+ pa_droid_config_global *global_config;
+ pa_droid_config_device *outputs;
+ pa_droid_config_device *inputs;
+
+ struct pa_droid_config_hw_module *next;
+};
+
+struct pa_droid_config_audio {
+ pa_droid_config_global *global_config;
+ pa_droid_config_hw_module *hw_modules;
+};
+
+/* Config parser */
+pa_droid_config_audio *pa_droid_config_load(pa_modargs *ma);
+pa_droid_config_audio *pa_droid_config_dup(const pa_droid_config_audio *config);
+void pa_droid_config_free(pa_droid_config_audio *config);
+pa_droid_config_audio *pa_parse_droid_audio_config_legacy(const char *filename);
+pa_droid_config_audio *pa_parse_droid_audio_config_xml(const char *filename);
+/* autodetect config type from filename and parse */
+pa_droid_config_audio *pa_parse_droid_audio_config(const char *filename);
+
+const pa_droid_config_hw_module *pa_droid_config_find_module(const pa_droid_config_audio *config, const char* module_id);
+
+pa_droid_config_hw_module *pa_droid_config_hw_module_new(const pa_droid_config_audio *config, const char *name);
+void pa_droid_config_hw_module_free(pa_droid_config_hw_module *hw_module);
+pa_droid_config_device *pa_droid_config_device_new(const pa_droid_config_hw_module *module,
+ pa_direction_t direction,
+ const char *name);
+void pa_droid_config_device_free(pa_droid_config_device *device);
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/include/droid/droid-util.h
^
|
@@ -0,0 +1,333 @@
+#ifndef foodroidutilfoo
+#define foodroidutilfoo
+
+/*
+ * Copyright (C) 2013-2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/mutex.h>
+#include <pulsecore/strlist.h>
+#include <pulsecore/atomic.h>
+
+#include <droid/version.h>
+#include <droid/droid-config.h>
+
+#if defined(QCOM_BSP) && (AUDIO_API_VERSION_MAJ >= 3)
+#define DROID_AUDIO_HAL_USE_VSID
+#endif
+
+#define PROP_DROID_DEVICES "droid.devices"
+#define PROP_DROID_FLAGS "droid.flags"
+#define PROP_DROID_HW_MODULE "droid.hw_module"
+#define PROP_DROID_API_STRING "droid-hal"
+
+#define PROP_DROID_OUTPUT_PRIMARY "droid.output.primary"
+#define PROP_DROID_OUTPUT_LOW_LATENCY "droid.output.low_latency"
+#define PROP_DROID_OUTPUT_MEDIA_LATENCY "droid.output.media_latency"
+#define PROP_DROID_OUTPUT_OFFLOAD "droid.output.offload"
+#define PROP_DROID_INPUT_BUILTIN "droid.input.builtin"
+#define PROP_DROID_INPUT_EXTERNAL "droid.input.external"
+
+#define PA_DROID_PRIMARY_DEVICE "primary"
+
+typedef struct pa_droid_hw_module pa_droid_hw_module;
+typedef struct pa_droid_stream pa_droid_stream;
+typedef struct pa_droid_output_stream pa_droid_output_stream;
+typedef struct pa_droid_input_stream pa_droid_input_stream;
+typedef struct pa_droid_card_data pa_droid_card_data;
+typedef int (*common_set_parameters_cb_t)(pa_droid_card_data *card_data, const char *str);
+
+typedef struct pa_droid_quirks pa_droid_quirks;
+
+typedef enum pa_droid_hook {
+ PA_DROID_HOOK_INPUT_CHANNEL_MAP_CHANGED, /* Call data: pa_droid_stream */
+ PA_DROID_HOOK_INPUT_BUFFER_SIZE_CHANGED, /* Call data: pa_droid_stream */
+ PA_DROID_HOOK_MAX
+} pa_droid_hook_t;
+
+
+struct pa_droid_hw_module {
+ PA_REFCNT_DECLARE;
+
+ pa_core *core;
+ char *shared_name;
+
+ pa_droid_config_audio *config;
+ const pa_droid_config_hw_module *enabled_module;
+ pa_mutex *hw_mutex;
+ pa_mutex *output_mutex;
+ pa_mutex *input_mutex;
+
+ struct hw_module_t *hwmod;
+ audio_hw_device_t *device;
+
+ const char *module_id;
+
+ uint32_t stream_out_id;
+ uint32_t stream_in_id;
+
+ pa_idxset *outputs;
+ pa_idxset *inputs;
+ pa_hook_slot *sink_put_hook_slot;
+ pa_hook_slot *sink_unlink_hook_slot;
+ pa_hook_slot *source_put_hook_slot;
+ pa_hook_slot *source_unlink_hook_slot;
+
+ pa_atomic_t active_outputs;
+
+ pa_droid_quirks *quirks;
+ pa_hook hooks[PA_DROID_HOOK_MAX];
+};
+
+struct pa_droid_output_stream {
+ struct audio_stream_out *stream;
+ pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
+ uint32_t flags;
+ uint32_t device;
+};
+
+struct pa_droid_input_stream {
+ struct audio_stream_in *stream;
+ pa_sample_spec sample_spec;
+ pa_channel_map channel_map;
+ pa_sample_spec input_sample_spec;
+ pa_channel_map input_channel_map;
+ uint32_t flags;
+ uint32_t device;
+ audio_devices_t all_devices;
+ bool merged;
+};
+
+struct pa_droid_stream {
+ PA_REFCNT_DECLARE;
+
+ pa_droid_hw_module *module;
+ size_t buffer_size;
+ void *data;
+
+ pa_droid_output_stream *output;
+ pa_droid_input_stream *input;
+};
+
+struct pa_droid_card_data {
+ void *userdata;
+ /* General functions */
+ char *module_id;
+ common_set_parameters_cb_t set_parameters;
+};
+
+
+/* Profiles */
+
+typedef struct pa_droid_profile_set pa_droid_profile_set;
+typedef struct pa_droid_mapping pa_droid_mapping;
+
+typedef struct pa_droid_port_data {
+ audio_devices_t device;
+} pa_droid_port_data;
+
+typedef struct pa_droid_port {
+ pa_droid_mapping *mapping;
+
+ audio_devices_t device;
+ char *name;
+ char *description;
+ unsigned priority;
+} pa_droid_port;
+
+struct pa_droid_mapping {
+ pa_droid_profile_set *profile_set;
+
+ const pa_droid_config_device *output;
+ const pa_droid_config_device *input;
+ const pa_droid_config_device *input2;
+
+ char *name;
+ char *description;
+ unsigned priority;
+ pa_proplist *proplist;
+
+ /* Mapping doesn't own the ports */
+ pa_idxset *ports;
+
+ pa_direction_t direction;
+
+ pa_sink *sink;
+ pa_source *source;
+};
+
+typedef struct pa_droid_profile {
+ pa_droid_profile_set *profile_set;
+
+ const pa_droid_config_hw_module *module;
+
+ char *name;
+ char *description;
+ unsigned priority;
+
+ /* Idxsets contain pa_droid_mapping objects.
+ * Profile doesn't own the mappings. */
+ pa_idxset *output_mappings;
+ pa_idxset *input_mappings;
+
+} pa_droid_profile;
+
+struct pa_droid_profile_set {
+ const pa_droid_config_audio *config;
+
+ pa_hashmap *all_ports;
+ pa_hashmap *output_mappings;
+ pa_hashmap *input_mappings;
+ pa_hashmap *profiles;
+};
+
+#define PA_DROID_OUTPUT_PARKING "output-parking"
+#define PA_DROID_INPUT_PARKING "input-parking"
+
+enum pa_droid_quirk_type {
+ QUIRK_INPUT_ATOI,
+ QUIRK_SET_PARAMETERS,
+ QUIRK_CLOSE_INPUT,
+ QUIRK_UNLOAD_NO_CLOSE,
+ QUIRK_NO_HW_VOLUME,
+ QUIRK_OUTPUT_MAKE_WRITABLE,
+ QUIRK_REALCALL,
+ QUIRK_UNLOAD_CALL_EXIT,
+ QUIRK_COUNT
+};
+
+struct pa_droid_quirks {
+ bool enabled[QUIRK_COUNT];
+};
+
+/* Open hardware module */
+/* 'config' can be NULL if it is assumed that hw module with module_id already is open. */
+pa_droid_hw_module *pa_droid_hw_module_get(pa_core *core, const pa_droid_config_audio *config, const char *module_id);
+pa_droid_hw_module *pa_droid_hw_module_ref(pa_droid_hw_module *hw);
+void pa_droid_hw_module_unref(pa_droid_hw_module *hw);
+
+void pa_droid_hw_module_lock(pa_droid_hw_module *hw);
+bool pa_droid_hw_module_try_lock(pa_droid_hw_module *hw);
+void pa_droid_hw_module_unlock(pa_droid_hw_module *hw);
+
+bool pa_droid_quirk_parse(pa_droid_hw_module *hw, const char *quirks);
+void pa_droid_quirk_log(pa_droid_hw_module *hw);
+
+static inline bool pa_droid_quirk(pa_droid_hw_module *hw, enum pa_droid_quirk_type quirk) {
+ return hw->quirks && hw->quirks->enabled[quirk];
+}
+
+/* Profiles */
+pa_droid_profile_set *pa_droid_profile_set_new(const pa_droid_config_hw_module *module);
+pa_droid_profile_set *pa_droid_profile_set_default_new(const pa_droid_config_hw_module *module,
+ bool merge_inputs);
+void pa_droid_profile_set_free(pa_droid_profile_set *ps);
+
+void pa_droid_profile_add_mapping(pa_droid_profile *p, pa_droid_mapping *am);
+void pa_droid_profile_free(pa_droid_profile *p);
+
+pa_droid_mapping *pa_droid_mapping_get(pa_droid_profile_set *ps, const pa_droid_config_device *device);
+pa_droid_mapping *pa_droid_mapping_merged_get(pa_droid_profile_set *ps,
+ const pa_droid_config_device *input1,
+ const pa_droid_config_device *input2);
+bool pa_droid_mapping_is_primary(pa_droid_mapping *am);
+/* Go through idxset containing pa_droid_mapping objects and if primary output or input
+ * mapping is found, return pointer to that mapping. */
+pa_droid_mapping *pa_droid_idxset_get_primary(pa_idxset *i);
+pa_droid_mapping *pa_droid_idxset_mapping_with_device(pa_idxset *i, uint32_t flag);
+void pa_droid_mapping_free(pa_droid_mapping *am);
+
+/* Add ports from sinks/sources.
+ * May be called multiple times for one sink/source. */
+void pa_droid_add_ports(pa_hashmap *ports, pa_droid_mapping *am, pa_card *card);
+/* Add ports from card.
+ * May be called multiple times for one card profile. */
+void pa_droid_add_card_ports(pa_card_profile *cp, pa_hashmap *ports, pa_droid_mapping *am, pa_core *core);
+
+pa_hook *pa_droid_hooks(pa_droid_hw_module *hw);
+
+/* Module operations */
+int pa_droid_set_parameters(pa_droid_hw_module *hw, const char *parameters);
+
+/* Stream operations */
+pa_droid_stream *pa_droid_stream_ref(pa_droid_stream *s);
+void pa_droid_stream_unref(pa_droid_stream *s);
+
+int pa_droid_stream_set_parameters(pa_droid_stream *s, const char *parameters);
+
+/* Output stream operations */
+pa_droid_stream *pa_droid_open_output_stream(pa_droid_hw_module *module,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ audio_output_flags_t flags,
+ audio_devices_t devices);
+
+/* Set routing to the input or output stream, with following side-effects:
+ * Output:
+ * - if routing is set to primary output stream, set routing to all other
+ * open streams as well
+ * - if routing is set to non-primary stream and primary stream exists, do nothing
+ * - if routing is set to non-primary stream and primary stream doesn't exist, set routing
+ * Input:
+ * - buffer size or channel count may change
+ */
+int pa_droid_stream_set_route(pa_droid_stream *s, audio_devices_t device);
+
+/* Input stream operations */
+pa_droid_stream *pa_droid_open_input_stream(pa_droid_hw_module *module,
+ const pa_sample_spec *spec,
+ const pa_channel_map *map,
+ audio_devices_t devices,
+ pa_droid_mapping *am);
+
+bool pa_droid_stream_is_primary(pa_droid_stream *s);
+
+int pa_droid_stream_suspend(pa_droid_stream *s, bool suspend);
+
+size_t pa_droid_stream_buffer_size(pa_droid_stream *s);
+pa_usec_t pa_droid_stream_get_latency(pa_droid_stream *s);
+
+static inline int pa_droid_output_stream_any_active(pa_droid_stream *s) {
+ return pa_atomic_load(&s->module->active_outputs);
+}
+
+static inline ssize_t pa_droid_stream_write(pa_droid_stream *stream, const void *buffer, size_t bytes) {
+ return stream->output->stream->write(stream->output->stream, buffer, bytes);
+}
+
+static inline ssize_t pa_droid_stream_read(pa_droid_stream *stream, void *buffer, size_t bytes) {
+ return stream->input->stream->read(stream->input->stream, buffer, bytes);
+}
+
+void pa_droid_stream_set_data(pa_droid_stream *s, void *data);
+void *pa_droid_stream_get_data(pa_droid_stream *s);
+bool pa_sink_is_droid_sink(pa_sink *sink);
+bool pa_source_is_droid_source(pa_source *source);
+
+/* Misc */
+size_t pa_droid_buffer_size_round_up(size_t buffer_size, size_t block_size);
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/include/droid/sllist.h
^
|
@@ -0,0 +1,49 @@
+#ifndef foosllistfoo
+#define foosllistfoo
+
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#define SLLIST_APPEND(t, head, item) \
+ do { \
+ item->next = NULL; \
+ if (!head) { \
+ head = item; \
+ } else { \
+ t *_list; \
+ for (_list = head; _list->next; _list = _list->next); \
+ _list->next = item; \
+ } \
+ } while (0)
+
+#define SLLIST_FOREACH(i, head) \
+ for (i = (head); i; i = i->next)
+
+#define SLLIST_STEAL_FIRST(i, head) \
+ do { \
+ if (head) { \
+ i = head; \
+ head = head->next; \
+ } else \
+ i = NULL; \
+ } while (0)
+
+#endif
|
[-]
[+]
|
Added |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/common/include/droid/version.h
^
|
@@ -0,0 +1,51 @@
+#ifndef foodroidversionfoo
+#define foodroidversionfoo
+
+/*
+ * Copyright (C) 2018 Jolla Ltd.
+ *
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
+ *
+ * These PulseAudio Modules are 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
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+
+#include <android-config.h>
+#ifdef QCOM_BSP
+#define QCOM_HARDWARE
+#endif
+
+#include <hardware/audio.h>
+
+#if !defined(ANDROID_VERSION_MAJOR) || !defined(ANDROID_VERSION_MINOR) || !defined(ANDROID_VERSION_PATCH)
+#error "ANDROID_VERSION_* not defined. Did you get your headers via extract-headers.sh?"
+#endif
+
+/* We currently support API version up-to 3.0 */
+#define DROID_API_VERSION_SUPPORT HARDWARE_DEVICE_API_VERSION(3, 0)
+
+#if AUDIO_DEVICE_API_VERSION_CURRENT > DROID_API_VERSION_SUPPORT
+#warning Compiling against higher audio device API version than currently supported!
+#warning Compile likely fails or module may malfunction.
+#endif
+
+#define AUDIO_API_VERSION_MAJ ((AUDIO_DEVICE_API_VERSION_CURRENT >> 8) & 0xff)
+#define AUDIO_API_VERSION_MIN (AUDIO_DEVICE_API_VERSION_CURRENT & 0xff)
+
+#define AUDIO_API_VERSION_GET_MAJ(x) ((x >> 8) & 0xff)
+#define AUDIO_API_VERSION_GET_MIN(x) (x & 0xff)
+
+#endif
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/Makefile.am
^
|
@@ -9,7 +9,7 @@
$(HYBRIS_CFLAGS) \
-DPULSEAUDIO_VERSION=@PA_MAJOR@ \
-I$(top_srcdir)/src/droid \
- -I$(top_srcdir)/src/common
+ -I$(top_srcdir)/src/common/include
modlibexec_LTLIBRARIES = \
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/droid-sink.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -56,7 +56,8 @@
#include <pulsecore/core-subscribe.h>
#include "droid-sink.h"
-#include "droid-util.h"
+#include <droid/droid-util.h>
+#include <droid/conversion.h>
struct userdata {
pa_core *core;
@@ -1138,18 +1139,17 @@
* hw module ourself.
*
* First let's find out if hw module has already been opened, or if we need to
- * do it ourself.
- */
+ * do it ourself. */
if (!(u->hw_module = pa_droid_hw_module_get(u->core, NULL, module_id))) {
-
/* No hw module object in shared object db, let's open the module now. */
-
if (!(config = pa_droid_config_load(ma)))
goto fail;
- /* Ownership of config transfers to hw_module if opening of hw module succeeds. */
if (!(u->hw_module = pa_droid_hw_module_get(u->core, config, module_id)))
goto fail;
+
+ pa_droid_config_free(config);
+ config = NULL;
}
}
@@ -1308,6 +1308,7 @@
return u->sink;
fail:
+ pa_droid_config_free(config);
pa_xfree(thread_name);
if (config)
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/droid-sink.h
^
|
@@ -2,9 +2,9 @@
#define foodroidsinkfoo
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -41,7 +41,7 @@
#include <pulsecore/macro.h>
#include <pulsecore/card.h>
-#include "droid-util.h"
+#include <droid/droid-util.h>
pa_sink *pa_droid_sink_new(pa_module *m,
pa_modargs *ma,
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/droid-source.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -53,7 +53,8 @@
#include <pulsecore/resampler.h>
#include "droid-source.h"
-#include "droid-util.h"
+#include <droid/droid-util.h>
+#include <droid/conversion.h>
struct userdata {
pa_core *core;
@@ -595,15 +596,20 @@
u->card_data = card_data;
pa_assert_se((u->hw_module = pa_droid_hw_module_get(u->core, NULL, card_data->module_id)));
} else {
- /* Stand-alone source */
-
+ /* Source wasn't created from inside card module, so we'll need to open
+ * hw module ourself.
+ *
+ * First let's find out if hw module has already been opened, or if we need to
+ * do it ourself. */
if (!(u->hw_module = pa_droid_hw_module_get(u->core, NULL, module_id))) {
if (!(config = pa_droid_config_load(ma)))
goto fail;
- /* Ownership of config transfers to hw_module if opening of hw module succeeds. */
if (!(u->hw_module = pa_droid_hw_module_get(u->core, config, module_id)))
goto fail;
+
+ pa_droid_config_free(config);
+ config = NULL;
}
}
@@ -719,11 +725,9 @@
return u->source;
fail:
+ pa_droid_config_free(config);
pa_xfree(thread_name);
- if (config)
- pa_xfree(config);
-
if (u)
userdata_free(u);
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/droid-source.h
^
|
@@ -2,9 +2,9 @@
#define foodroidsourcefoo
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -41,7 +41,7 @@
#include <pulsecore/macro.h>
#include <pulsecore/card.h>
-#include "droid-util.h"
+#include <droid/droid-util.h>
/* If device is non-zero, it will override whatever is set in modargs for input device. */
pa_source *pa_droid_source_new(pa_module *m,
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/keepalive.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/keepalive.h
^
|
@@ -2,9 +2,9 @@
#define foodroidkeepalivefoo
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-card-symdef.h
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-card.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -59,7 +59,7 @@
//#include <droid/hardware/audio_policy.h>
//#include <droid/system/audio_policy.h>
-#include "droid-util.h"
+#include <droid/droid-util.h>
#include "droid-sink.h"
#include "droid-source.h"
@@ -720,14 +720,21 @@
u->core = m->core;
m->userdata = u;
- if (!(config = pa_droid_config_load(ma)))
- goto fail;
-
module_id = pa_modargs_get_value(ma, "module_id", DEFAULT_MODULE_ID);
- /* Ownership of config transfers to hw_module if opening of hw module succeeds. */
- if (!(u->hw_module = pa_droid_hw_module_get(u->core, config, module_id)))
- goto fail;
+ /* First let's find out if hw module has already been opened, or if we need to
+ * do it ourself. */
+ if (!(u->hw_module = pa_droid_hw_module_get(u->core, NULL, module_id))) {
+ /* No hw module object in shared object db, let's open the module now. */
+ if (!(config = pa_droid_config_load(ma)))
+ goto fail;
+
+ if (!(u->hw_module = pa_droid_hw_module_get(u->core, config, module_id)))
+ goto fail;
+
+ pa_droid_config_free(config);
+ config = NULL;
+ }
if ((quirks = pa_modargs_get_value(ma, "quirks", NULL))) {
if (!pa_droid_quirk_parse(u->hw_module, quirks)) {
@@ -835,6 +842,8 @@
return 0;
fail:
+ pa_droid_config_free(config);
+
if (ma)
pa_modargs_free(ma);
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-keepalive-symdef.h
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-keepalive.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -103,42 +103,52 @@
u->active = false;
}
-static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
- pa_assert(c);
- pa_object_assert_ref(o);
+static void update_sink(pa_sink *sink, struct userdata *u) {
+ pa_assert(sink);
pa_assert(u);
- if (pa_source_isinstance(o)) {
- pa_source *s = PA_SOURCE(o);
+ if (pa_sink_get_state(sink) != PA_SINK_SUSPENDED)
+ start(u);
+ else
+ stop(u);
+}
- /* Don't react on monitor state changes. */
- if (!s->monitor_of) {
- pa_source_state_t state = pa_source_get_state(s);
-
- if (state != PA_SOURCE_SUSPENDED)
- start(u);
- else
- stop(u);
- }
- } else if (pa_sink_isinstance(o)) {
- pa_sink *s = PA_SINK(o);
- pa_sink_state_t state = pa_sink_get_state(s);
+static void update_source(pa_source *source, struct userdata *u) {
+ pa_assert(source);
+ pa_assert(u);
- if (state != PA_SINK_SUSPENDED)
+ /* Don't react on monitor state changes. */
+ if (!source->monitor_of) {
+ if (pa_source_get_state(source) != PA_SOURCE_SUSPENDED)
start(u);
else
stop(u);
}
+}
+
+static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
+ pa_assert(c);
+ pa_object_assert_ref(o);
+ pa_assert(u);
+
+ if (pa_source_isinstance(o))
+ update_source(PA_SOURCE(o), u);
+ else if (pa_sink_isinstance(o))
+ update_sink(PA_SINK(o), u);
return PA_HOOK_OK;
}
int pa__init(pa_module *m) {
+ uint32_t idx = 0;
+ pa_sink *sink;
+ pa_source *source;
+ struct userdata *u;
pa_assert(m);
- struct userdata *u = pa_xnew0(struct userdata, 1);
+ u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->active = false;
u->module = m;
@@ -152,6 +162,12 @@
u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) device_state_changed_hook_cb, u);
u->source_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) device_state_changed_hook_cb, u);
+ PA_IDXSET_FOREACH(source, u->core->sources, idx)
+ update_source(source, u);
+
+ PA_IDXSET_FOREACH(sink, u->core->sinks, idx)
+ update_sink(sink, u);
+
return 0;
fail:
@@ -173,7 +189,7 @@
pa_hook_slot_free(u->source_state_changed_slot);
if (u->keepalive) {
- stop(u);
+ pa_droid_keepalive_stop(u->keepalive);
pa_droid_keepalive_free(u->keepalive);
}
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-sink-symdef.h
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-sink.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,8 @@
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
-#include "droid-util.h"
+#include <droid/droid-util.h>
+#include <droid/conversion.h>
#include "droid-sink.h"
#include "module-droid-sink-symdef.h"
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-source-symdef.h
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
|
[-]
[+]
|
Changed |
_service:tar_git:pulseaudio-modules-droid-11.1.75.tar.bz2/src/droid/module-droid-source.c
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (C) 2013-2018 Jolla Ltd.
*
- * Contact: Juho Hämäläinen <juho.hamalainen@tieto.com>
+ * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,7 @@
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
-#include "droid-util.h"
+#include <droid/droid-util.h>
#include "droid-source.h"
#include "module-droid-source-symdef.h"
|