Compare commits
4 commits
bookworm-m
...
i9305-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dccef3aef6 | ||
|
|
7183df5788 | ||
|
|
7f5649c442 | ||
|
|
0fad8598a6 |
64 changed files with 3677 additions and 9333 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -19,6 +19,3 @@ config.status
|
|||
libtool
|
||||
*.pc
|
||||
stamp-*
|
||||
|
||||
# Added by Droidian
|
||||
!.circleci/
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
SUBDIRS = src
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
$(top_srcdir)/.version:
|
||||
echo $(VERSION) > $@-t && mv $@-t $@
|
||||
|
||||
dist-hook:
|
||||
echo $(VERSION) > $(distdir)/.tarball-version
|
||||
echo $(VERSION) > $(distdir)/.version
|
||||
|
|
|
|||
3
README
Normal file
3
README
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
PulseAudio Droid modules
|
||||
========================
|
||||
|
||||
356
README.md
356
README.md
|
|
@ -1,356 +0,0 @@
|
|||
PulseAudio Droid modules
|
||||
========================
|
||||
|
||||
For adapdations for Android versions 4 to 10,
|
||||
see [pulseaudio-modules-droid-jb2q](https://github.com/mer-hybris/pulseaudio-modules-droid-jb2q)
|
||||
|
||||
Building of droid modules is split to two packages
|
||||
* **common** (and **common-devel**) which contains shared library code for use in
|
||||
PulseAudio modules in this package and for inclusion in other projects
|
||||
* **droid** with actual PulseAudio modules
|
||||
|
||||
Linking to libdroid is **not encouraged**, usually only HAL functions are needed
|
||||
which can be accessed using the pulsecore shared API (see below).
|
||||
|
||||
Supported Android versions:
|
||||
|
||||
* 11.x
|
||||
|
||||
Headers for defining devices and strings for different droid versions are in
|
||||
src/common/droid-util-audio.h.
|
||||
|
||||
When new devices with relevant new enums appear, add enum check to configure.ac.
|
||||
CC_CHECK_DROID_ENUM macro will create macros HAVE_ENUM_FOO, STRING_ENTRY_IF_FOO
|
||||
and FANCY_ENTRY_IF_FOO if enum FOO exists in HAL audio.h.
|
||||
|
||||
For example:
|
||||
|
||||
# configure.ac:
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_OUT_IP])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_OUT_OTHER_NEW])
|
||||
|
||||
# and then in droid-util-audio.h add macros to proper tables:
|
||||
/* string_conversion_table_output_device[] */
|
||||
STRING_ENTRY_IF_OUT_IP
|
||||
STRING_ENTRY_IF_OUT_OTHER_NEW
|
||||
|
||||
/* string_conversion_table_output_device_fancy[] */
|
||||
FANCY_ENTRY_IF_OUT_IP("output-ip")
|
||||
FANCY_ENTRY_IF_OUT_OTHER_NEW("output-other_new")
|
||||
|
||||
In addition to the above macros there are also now defines
|
||||
HAVE_ENUM_AUDIO_DEVICE_OUT_IP and HAVE_ENUM_AUDIO_DEVICE_OUT_OTHER_NEW.
|
||||
|
||||
The purpose of droid-modules is to "replace AudioFlinger". Many hardware
|
||||
adaptations use ALSA as the kernel interface, but there is no saying that
|
||||
someday vendor would create and use something proprietary or otherwise
|
||||
different from ALSA. Also the ALSA implementation in droid devices may contain
|
||||
funny ways to achieve things (notable example is voicecall) which might be
|
||||
difficult to do if interfacing directly with ALSA to replace AudioFlinger.
|
||||
Also using ALSA directly would mean that the whole HAL adaptation would need to
|
||||
be ported for each new device adaptation. With droid-modules this is much more
|
||||
simpler, with somewhat stable HAL (HALv3 as of now, also different vendors add
|
||||
their own incompatible extensions) API. In best scenarios using droid-modules
|
||||
with new device is just compiling against target.
|
||||
|
||||
Components
|
||||
==========
|
||||
|
||||
common
|
||||
------
|
||||
|
||||
The common part of PulseAudio Droid modules contains library for handling
|
||||
most operations towards audio HAL.
|
||||
|
||||
### Audio policy configuration parsing
|
||||
|
||||
Configuration parser reads audio policy xml files.
|
||||
|
||||
### Configuration files
|
||||
|
||||
If the configuration is in non-default location for some reason "config"
|
||||
module argument can be used to point to the configuration file location.
|
||||
|
||||
By default files are tried in following order,
|
||||
|
||||
/odm/etc/audio_policy_configuration.xml
|
||||
/vendor/etc/audio/audio_policy_configuration.xml
|
||||
/vendor/etc/audio_policy_configuration.xml
|
||||
/system/etc/audio_policy_configuration.xml
|
||||
|
||||
module-droid-card
|
||||
-----------------
|
||||
|
||||
Ideally only module-droid-card is loaded and then droid-card loads
|
||||
configuration, creates profiles and loads sinks and sources based on the
|
||||
selected profile.
|
||||
|
||||
default profile
|
||||
---------------
|
||||
|
||||
When module-droid-card is loaded with default arguments, droid-card will
|
||||
create a default profile (called unsurprisingly "default"). The default
|
||||
profile will merge supported output and input streams to one profile,
|
||||
to allow use of possible low latency or deep buffer outputs.
|
||||
|
||||
virtual profiles
|
||||
----------------
|
||||
|
||||
In addition to aforementioned card profile, droid-card creates some additional
|
||||
virtual profiles. These virtual profiles are used when enabling voicecall
|
||||
routings etc. When virtual profile is enabled, possible sinks and sources
|
||||
previously active profile had are not removed.
|
||||
|
||||
As an illustration, following command line sequence enables voicecall mode and
|
||||
routes audio to internal handsfree (ihf - "handsfree speaker"):
|
||||
|
||||
pactl set-card-profile droid_card.primary voicecall
|
||||
pactl set-sink-port sink.primary output-parking
|
||||
pactl set-sink-port sink.primary output-speaker
|
||||
|
||||
After this, when there is an active voicecall (created by ofono for example),
|
||||
voice audio starts to flow between modem and audio chip.
|
||||
|
||||
To disable voicecall and return to media audio:
|
||||
|
||||
pactl set-card-profile droid_card.primary default
|
||||
pactl set-sink-port sink.primary output-parking
|
||||
pactl set-sink-port sink.primary output-speaker
|
||||
|
||||
With this example sequence sinks and sources are the ones from default
|
||||
card profile, and they are maintained for the whole duration of the voicecall
|
||||
and after.
|
||||
|
||||
This sequence follows the droid HAL idea that when changing audio mode the mode
|
||||
change is done when next routing change happens. output-parking and
|
||||
input-parking ports are just convenience for PulseAudio, where setting already
|
||||
active port is a no-op (output/input-parking doesn't do any real routing
|
||||
changes).
|
||||
|
||||
Current virtual profiles are:
|
||||
* voicecall
|
||||
* voicecall-record
|
||||
* communication
|
||||
* ringtone
|
||||
|
||||
Communication profile is used for VoIP-like applications, to enable some
|
||||
voicecall related algorithms without being in voicecall. Ringtone profile
|
||||
should be used when ringtone is playing, to again enable possible loudness
|
||||
related optimizations etc. Voicecall-record profile can be enabled when
|
||||
voicecall profile is active.
|
||||
|
||||
If mix port with flag AUDIO_OUTPUT_FLAG_VOIP_RX exists when communication
|
||||
virtual profile is enabled additional droid-sink is created with the config
|
||||
defined in the mix port. Voip audio should then be played to this new sink.
|
||||
|
||||
module-droid-sink and module-droid-source
|
||||
-----------------------------------------
|
||||
|
||||
Normally user should not need to load droid-sink or droid-source modules by
|
||||
hand, but droid-card loads appropriate modules based on the active card
|
||||
profile.
|
||||
|
||||
Changing output routing is as simple as
|
||||
|
||||
pactl set-sink-port sink.primary output-wired_headphone
|
||||
|
||||
Sinks or sources do not track possible headphone/other wired accessory
|
||||
plugging, but this needs to be handled elsewhere and then that other entity
|
||||
needs to control sinks and sources. (For example in SailfishOS this entity is
|
||||
OHM with accessory-plugin and pulseaudio-policy-enforcement module for
|
||||
actually making the port switching)
|
||||
|
||||
Droid source automatic reconfiguration
|
||||
--------------------------------------
|
||||
|
||||
As droid HAL makes assumptions on (input) routing based on what the parameters
|
||||
for the stream are (device, sample rate, channels, format, etc.) normal
|
||||
PulseAudio sources are a bit inflexible as only sample rate can change after
|
||||
source creation and even then there are restrictions based on alternative
|
||||
sample rate value.
|
||||
|
||||
To overcome this and to allow some more variables affecting the stream being
|
||||
passed to the input stream droid source is modified to reconfigure itself
|
||||
with the source-output that connects to it. This means, that just looking at
|
||||
inactive source from "pactl list" listing doesn't tell the whole story.
|
||||
|
||||
Droid source is always reconfigured with the *last* source-output that
|
||||
connects to it, possibly already connected source-outputs will continue
|
||||
to read from the source but through resampler.
|
||||
|
||||
For example,
|
||||
|
||||
1) source-output 44100Hz, stereo connects (so1)
|
||||
1) source is configured with 44100Hz, stereo
|
||||
2) so1 connects to the source without resampler
|
||||
2) source-output 16000Hz, mono connects (so2)
|
||||
1) so1 is detached from the source
|
||||
2) source is configured with 16000Hz, mono
|
||||
3) so2 connects to the source without resampler
|
||||
4) resampler is created for so1, 16000Hz, mono -> 44100Hz stereo
|
||||
5) so1 is re-attached to the source through resampler
|
||||
3) source-output 16000Hz, mono connects (so3)
|
||||
1) so1 and so2 are detached from the source
|
||||
2) so3 connects to the source without resampler
|
||||
3) so1 is re-attached to the source through resampler
|
||||
4) so2 is attached to the source
|
||||
|
||||
Classifying sinks and sources
|
||||
-----------------------------
|
||||
|
||||
Certain property values are set to all active sinks and sources based on their
|
||||
functionality to ease device classification.
|
||||
|
||||
Currently following properties are set:
|
||||
|
||||
* For droid sinks
|
||||
* droid.output.primary
|
||||
* droid.output.low_latency
|
||||
* droid.output.media_latency
|
||||
* droid.output.offload
|
||||
* droid.output.voip
|
||||
* For droid sources
|
||||
* droid.input.builtin
|
||||
* droid.input.external
|
||||
|
||||
If the property is set and with value "true", the sink or source should be
|
||||
used for the property type. If the property is not defined or contains
|
||||
value "false" it shouldn't be used for the property type.
|
||||
|
||||
For example, we might have sink.primary and sink.low_latency with following
|
||||
properties:
|
||||
|
||||
* sink.primary
|
||||
* droid.output.primary "true"
|
||||
* droid.output.media_latency "true"
|
||||
* sink.low_latency
|
||||
* droid.output.low_latency "true"
|
||||
|
||||
There also may be just one sink, with all the properties defined as "true"
|
||||
and so on.
|
||||
|
||||
Right now there exists only one source (input device) which will always have
|
||||
both properties as true.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
There are some adaptations that require hacks to get things working. These
|
||||
hacks can be enabled or disabled with module argument "options". Some options
|
||||
are enabled by default with some adaptations etc. There are also some more
|
||||
generic options.
|
||||
|
||||
Currently there are following options:
|
||||
|
||||
* input_atoi
|
||||
* Enabled by default with Android versions 5 and up.
|
||||
* Due to how atoi works in bionic vs libc we need to pass the input
|
||||
route a bit funny. If input routing doesn't work switch this on or off.
|
||||
* close_input
|
||||
* Enabled by default.
|
||||
* Close input stream when not in use instead of suspending the stream.
|
||||
Cannot be changed when multiple inputs are merged to single source.
|
||||
* unload_no_close
|
||||
* Disabled by default.
|
||||
* Don't call audio_hw_device_close() for the hw module when unloading.
|
||||
Mostly useful for tracking module unload issues.
|
||||
* hw_volume
|
||||
* Enabled by default.
|
||||
* Some broken implementations are incorrectly probed for supporting hw
|
||||
volume control. This is manifested by always full volume with volume
|
||||
control not affecting volume level. To fix this disable this option.
|
||||
* realcall
|
||||
* Disabled by default.
|
||||
* Some vendors apply custom realcall parameter to HAL device when
|
||||
doing voicecall routing. If there is no voicecall audio you can
|
||||
try enabling this option 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.
|
||||
* output_fast
|
||||
* Enabled by default.
|
||||
* Create separate sink if AUDIO_OUTPUT_FLAG_FAST is found. If this sink
|
||||
is misbehaving try disabling this option.
|
||||
* output_deep_buffer
|
||||
* Enabled by default.
|
||||
* Create separate sink if AUDIO_OUTPUT_FLAG_DEEP_BUFFER is found. If
|
||||
this sink is misbehaving try disabling this option.
|
||||
* audio_cal_wait
|
||||
* Disabled by default.
|
||||
* Certain devices do audio calibration during hw module open and
|
||||
writing audio too early will break the calibration. In these cases
|
||||
this option can be enabled and 10 seconds of sleep is added after
|
||||
opening hw module.
|
||||
* speaker_before_voice
|
||||
* Disabled by default.
|
||||
* Set route to speaker before changing audio mode to AUDIO_MODE_IN_CALL.
|
||||
Some devices don't get routing right if the route is something else
|
||||
(like AUDIO_DEVICE_OUT_WIRED_HEADSET) before calling set_mode().
|
||||
If routing is wrong when call starts with wired accessory connected
|
||||
try enabling this option.
|
||||
* output_voip_rx
|
||||
* Enabled by default.
|
||||
* When audio configuration has AUDIO_OUTPUT_FLAG_VOIP_RX special voip
|
||||
sink is created when AUDIO_MODE_IN_COMMUNICATION is active and the
|
||||
sink is classified as droid.output.voip. If this is not desired then
|
||||
by disabling this option the voip sink is not classified but is still
|
||||
created normally.
|
||||
* record_voice_16k
|
||||
* Disabled by default.
|
||||
* When enabled voice call recording source is forced to sample rate
|
||||
of 16kHz.
|
||||
|
||||
Options can be enabled or disabled normally as module arguments, for example:
|
||||
|
||||
load-module module-droid-card hw_volume=false record_voice_16k=true
|
||||
|
||||
Volume control during voicecall
|
||||
-------------------------------
|
||||
|
||||
When voicecall virtual profile is enabled, active droid-sink is internally
|
||||
switched to voicecall volume control mode. What this means is changing the sink
|
||||
volume or volume of normal streams connected to the sink do not change active
|
||||
voicecall volume. Special stream is needed to control the voicecall volume
|
||||
level. By default this stream is identified by stream property media.role,
|
||||
with value "phone". This can be changed by providing module arguments
|
||||
voice_property_key and voice_property_value to module-droid-card.
|
||||
|
||||
Usually droid HAL has 6 volume levels for voicecall.
|
||||
|
||||
Temporary sink audio routing
|
||||
----------------------------
|
||||
|
||||
It is possible to add temporary route to sink audio routing with specific
|
||||
stream property. When stream with property key
|
||||
droid.device.additional-route connects to droid-sink, this extra route is set
|
||||
(if possible) as the enabled route for the duration of the stream.
|
||||
|
||||
For example, if droid-sink has active port output-wired_headphone:
|
||||
|
||||
paplay --property=droid.device.additional-route=AUDIO_DEVICE_OUT_SPEAKER a.wav
|
||||
|
||||
As long as the new stream is connected to droid-sink, output routing is
|
||||
SPEAKER.
|
||||
|
||||
HAL API
|
||||
-------
|
||||
|
||||
If there is need to call HAL directly from other modules it can be done with
|
||||
function pointer API stored in PulseAudio shared map.
|
||||
|
||||
Once the function pointers are acquired when called they will work the same
|
||||
way as defined in Android audio.h. For example:
|
||||
|
||||
void *handle;
|
||||
int (*set_parameters)(void *handle, const char *key_value_pairs);
|
||||
char* (*get_parameters)(void *handle, const char *keys);
|
||||
|
||||
handle = pa_shared_get(core, "droid.handle.v1");
|
||||
set_parameters = pa_shared_get(core, "droid.set_parameters.v1");
|
||||
get_parameters = pa_shared_get(core, "droid.get_parameters.v1");
|
||||
|
||||
set_parameters(handle, "route=2;");
|
||||
char *value = get_parameters(handle, "connected");
|
||||
84
configure.ac
84
configure.ac
|
|
@ -1,15 +1,15 @@
|
|||
AC_PREREQ(2.60)
|
||||
|
||||
AC_INIT([pulseaudio-modules-droid-modern], [m4_esyscmd(./git-version-gen .tarball-version)], [mer-general@lists.merproject.org])
|
||||
m4_define(PA_MAJOR, [4])
|
||||
m4_define(PA_MINOR, [0])
|
||||
m4_define(NEMO_MICRO, [1])
|
||||
|
||||
AC_INIT([pulseaudio-modules-droid], [PA_MAJOR.PA_MINOR.NEMO_MICRO], [mer-general@lists.merproject.org])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AM_INIT_AUTOMAKE([foreign -Wall silent-rules])
|
||||
AC_CONFIG_MACRO_DIR(m4)
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AS_IF([! test -n "$VERSION"], [
|
||||
AC_MSG_ERROR([git-version-gen failed])
|
||||
])
|
||||
|
||||
if type -p stow > /dev/null && test -d /usr/local/stow ; then
|
||||
AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***])
|
||||
ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
|
||||
|
|
@ -20,15 +20,9 @@ AC_PROG_CC_C99
|
|||
AM_PROG_CC_C_O
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
|
||||
m4_define(pa_major, `pkg-config --modversion libpulse | cut -d. -f1 | cut -d- -f1`)
|
||||
m4_define(pa_minor, `pkg-config --modversion libpulse | cut -d. -f2 | cut -d- -f1`)
|
||||
m4_define(pa_module_version, `echo $VERSION | cut -d. -f3 | cut -d- -f1`)
|
||||
AC_SUBST(PA_MAJORMINOR, PA_MAJOR.PA_MINOR)
|
||||
|
||||
AC_SUBST(PA_MAJOR, pa_major)
|
||||
AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
|
||||
AC_SUBST(PA_MODULE_VERSION, pa_module_version)
|
||||
|
||||
DESIRED_FLAGS="-std=gnu11 -Wall -W -Wextra -pipe -Wno-long-long -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing -Wwrite-strings -Wno-unused-parameter -fno-common -fdiagnostics-show-option -fdiagnostics-color=auto"
|
||||
DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wno-long-long -Winline -Wvla -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wpacked -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wstrict-aliasing=2 -Wwrite-strings -Wno-unused-parameter -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common -fdiagnostics-show-option" # PulseAudio 0.9.15 usess same + -Wcast-align -Wdeclaration-after-statement
|
||||
|
||||
for flag in $DESIRED_FLAGS ; do
|
||||
CC_CHECK_CFLAGS([$flag], [CFLAGS="$CFLAGS $flag"])
|
||||
|
|
@ -170,10 +164,12 @@ AS_IF([test "$pulseaudio_cv__Bool" = "yes"], [
|
|||
#LT_INIT([dlopen win32-dll disable-static])
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
PKG_CHECK_MODULES([PULSEAUDIO], [libpulse >= 14.2 pulsecore >= 14.2])
|
||||
PKG_CHECK_MODULES([PULSEAUDIO], [libpulse >= 2.1 pulsecore >= 2.1 ])
|
||||
AC_SUBST(PULSEAUDIO_CFLAGS)
|
||||
AC_SUBST(PULSEAUDIO_LIBS)
|
||||
|
||||
pulseaudiodir=`pkg-config --variable=prefix pulsecore`
|
||||
|
||||
#PKG_CHECK_MODULES([DROIDHEADERS], [android-headers >= 0.0.6])
|
||||
# android-headers.pc has broken version field
|
||||
PKG_CHECK_MODULES([DROIDHEADERS], [android-headers])
|
||||
|
|
@ -183,43 +179,13 @@ PKG_CHECK_MODULES([HYBRIS], [libhardware >= 0.1.0])
|
|||
AC_SUBST(HYBRIS_CFLAGS)
|
||||
AC_SUBST(HYBRIS_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES([EVDEV], [libevdev >= 1.0])
|
||||
AC_SUBST(EVDEV_CFLAGS)
|
||||
AC_SUBST(EVDEV_LIBS)
|
||||
PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2])
|
||||
AC_SUBST(DBUS_CFLAGS)
|
||||
AC_SUBST(DBUS_LIBS)
|
||||
|
||||
#### expat (for xml config format parsing) ####
|
||||
|
||||
PKG_CHECK_MODULES([EXPAT], [expat >= 2.1])
|
||||
AC_SUBST(EXPAT_CFLAGS)
|
||||
AC_SUBST(EXPAT_LIBS)
|
||||
|
||||
# Input devices
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_IN_FM_RX])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_DEVICE_IN_FM_RX_A2DP])
|
||||
|
||||
# Audio sources
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_SOURCE_ECHO_REFERENCE])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_SOURCE_FM_TUNER])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_SOURCE_FM_RX])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_SOURCE_FM_RX_A2DP])
|
||||
|
||||
# Output flags
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH])
|
||||
|
||||
# Channels
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_CHANNEL_IN_VOICE_CALL_MONO])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO])
|
||||
|
||||
# Formats
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_FORMAT_PCM_OFFLOAD])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_FORMAT_FLAC])
|
||||
CC_CHECK_DROID_ENUM([${DROIDHEADERS_CFLAGS}], [AUDIO_FORMAT_OPUS])
|
||||
|
||||
AC_ARG_WITH(
|
||||
[module-dir],
|
||||
AS_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINOR}/modules]),
|
||||
[modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINOR}/modules"])
|
||||
AC_ARG_WITH([module-dir],
|
||||
AS_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${pulseaudiodir}/lib/pulse-${PA_MAJORMINOR}/modules/]),
|
||||
[modlibexecdir=$withval], [modlibexecdir="${pulseaudiodir}/lib/pulse-${PA_MAJORMINOR}/modules"])
|
||||
|
||||
AC_SUBST(modlibexecdir)
|
||||
|
||||
|
|
@ -230,15 +196,10 @@ AC_ARG_WITH([droid-device],
|
|||
AS_HELP_STRING([--with-droid-device], [Droid device type for possible specific quirks (defaults to generic).]),
|
||||
[droiddevice=$withval], [droiddevice="generic"]
|
||||
)
|
||||
if test "x$droiddevice" != x ; then
|
||||
DROID_DEVICE_CFLAGS="-DDROID_DEVICE_`echo $droiddevice | tr '[a-z]' '[A-Z]'`=1 -DDROID_DEVICE_STRING=\"\\\"$droiddevice\\\"\""
|
||||
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])
|
||||
if test "x$droiddevice" = xmako ; then
|
||||
AC_DEFINE([DROID_DEVICE_MAKO], [1], [Using droid device mako.])
|
||||
else
|
||||
AC_DEFINE([DROID_DEVICE_GENERIC], [1], [Using droid device generic.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([If we are using hardfp tool chain])
|
||||
|
|
@ -256,8 +217,6 @@ fi
|
|||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
src/common/Makefile
|
||||
src/common/libdroid-util.pc
|
||||
src/droid/Makefile
|
||||
])
|
||||
|
||||
|
|
@ -271,7 +230,8 @@ echo "
|
|||
CFLAGS: ${CFLAGS}
|
||||
|
||||
prefix: ${prefix}
|
||||
PulseAudio prefix: ${pulseaudiodir}
|
||||
modules directory: ${modlibexecdir}
|
||||
|
||||
Droid device: ${droiddevice}
|
||||
Droid device ${droiddevice}
|
||||
"
|
||||
|
|
|
|||
98
debian/changelog
vendored
98
debian/changelog
vendored
|
|
@ -1,98 +0,0 @@
|
|||
pulseaudio-modules-droid-modern (16.1.101+gemian11+nmu1) bookworm; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* add config files
|
||||
|
||||
-- Penelope Gwen <support@pogmom.me> Sun, 29 Mar 2026 14:04:19 -0700
|
||||
|
||||
pulseaudio-modules-droid-modern (16.1.101+gemian1) unstable; urgency=medium
|
||||
|
||||
* New upstream nabbed from droidian
|
||||
|
||||
-- Adam Boardman <adamboardman@gmail.com> Tue, 04 Apr 2023 16:02:47 +0100
|
||||
|
||||
pulseaudio-modules-droid (12.2.84+gemian) buster; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- TheKit <thekit@disroot.org> Wed, 03 Jun 2020 01:55:10 +0100
|
||||
|
||||
pulseaudio-modules-droid (12.2.79+gemian) buster; urgency=medium
|
||||
|
||||
* Branch packaging for Gemian
|
||||
|
||||
-- TheKit <thekit@disroot.org> Wed, 13 Nov 2019 13:39:31 +0100
|
||||
|
||||
pulseaudio-modules-droid (12.2.79-3) unstable; urgency=medium
|
||||
|
||||
* Fix pulseaudio droid module version
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Tue, 12 Nov 2019 12:35:51 +0100
|
||||
|
||||
pulseaudio-modules-droid (12.2.79-2) unstable; urgency=medium
|
||||
|
||||
* Fix generating the pkgconfig files with proper pathes
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Tue, 12 Nov 2019 12:06:47 +0100
|
||||
|
||||
pulseaudio-modules-droid (12.2.79-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Sun, 06 Oct 2019 15:23:45 +0200
|
||||
|
||||
pulseaudio-modules-droid (12.2.78-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Thu, 25 Apr 2019 22:37:38 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.75-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Tue, 13 Nov 2018 21:17:39 +0100
|
||||
|
||||
pulseaudio-modules-droid (11.1.74-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Sat, 13 Oct 2018 20:43:53 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.73-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Sat, 13 Oct 2018 20:43:29 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.72-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Sun, 26 Aug 2018 12:27:09 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.71-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Wed, 22 Aug 2018 14:04:55 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.68-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Wed, 06 Jun 2018 14:03:22 +0200
|
||||
|
||||
pulseaudio-modules-droid (11.1.67-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
* Move to mer-hybris upstream
|
||||
* Split packaging from source
|
||||
|
||||
-- Jonah Brüchert <jbb@kaidan.im> Sat, 26 May 2018 20:06:24 +0200
|
||||
|
||||
pulseaudio-modules-droid (0.1) xenial; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Marius Gripsgard <marius@ubports.com> Fri, 19 Jan 2018 07:39:13 +0100
|
||||
1
debian/compat
vendored
1
debian/compat
vendored
|
|
@ -1 +0,0 @@
|
|||
11
|
||||
43
debian/control
vendored
43
debian/control
vendored
|
|
@ -1,43 +0,0 @@
|
|||
Source: pulseaudio-modules-droid-modern
|
||||
Section: sound
|
||||
Priority: optional
|
||||
Build-Depends: android-headers,
|
||||
check,
|
||||
debhelper (>= 11),
|
||||
dh-exec,
|
||||
intltool,
|
||||
pulseaudio-pulsecore-dev,
|
||||
libdbus-1-dev,
|
||||
libhardware-dev,
|
||||
libhybris-common-dev,
|
||||
libltdl-dev,
|
||||
libpulse-dev,
|
||||
libexpat1-dev,
|
||||
libevdev-dev,
|
||||
libudev-dev
|
||||
Maintainer: Adam Boardman <adamboardman@gmail.com>
|
||||
Standards-Version: 4.3.0
|
||||
Homepage: https://github.com/mer-hybris/pulseaudio-modules-droid
|
||||
Vcs-Git: https://github.com/gemian/pulseaudio-modules-droid-modern.git
|
||||
Vcs-Browser: https://github.com/gemian/pulseaudio-modules-droid-modern
|
||||
|
||||
Package: pulseaudio-modules-droid-modern
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Provides: pulseaudio-modules-droid-apispecific
|
||||
Conflicts: pulseaudio-modules-droid-apispecific
|
||||
Description: PulseAudio Droid HAL module
|
||||
Pulseaudio modules to interact with the Android HAL.
|
||||
.
|
||||
This package contains the actual modules, for Android 11+.
|
||||
|
||||
Package: pulseaudio-modules-droid-modern-dev
|
||||
Architecture: any
|
||||
Depends: pulseaudio-modules-droid-modern (= ${binary:Version}),
|
||||
${misc:Depends},
|
||||
Provides: pulseaudio-modules-droid-apispecific-dev
|
||||
Conflicts: pulseaudio-modules-droid-apispecific-dev
|
||||
Description: PulseAudio Droid HAL module - development headers
|
||||
Pulseaudio modules to interact with the Android HAL.
|
||||
.
|
||||
This package contains the development headers.
|
||||
44
debian/copyright
vendored
44
debian/copyright
vendored
|
|
@ -1,44 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: pulseaudio-modules-droid-modern
|
||||
Source: https://github.com/mer-hybris/pulseaudio-modules-droid-modern
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2022, Jolla Ltd.
|
||||
License: LGPL-2.1
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2018, Jonah Brüchert
|
||||
2017, 2018, Marius Gripsgard
|
||||
License: LGPL-2.1
|
||||
|
||||
Files: m4/*
|
||||
Copyright: 2006, 2007, xine project
|
||||
2006, 2007, Diego Pettenò <flameeyes@gmail.com>
|
||||
License: GPL-2+
|
||||
|
||||
License: GPL-2+
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or (at
|
||||
your option) any later version.
|
||||
.
|
||||
On Debian systems, the complete text of version 2 of the GNU General
|
||||
Public License can be found in '/usr/share/common-licenses/GPL-2'.
|
||||
|
||||
License: LGPL-2.1
|
||||
This package is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation, version 2.1 of
|
||||
the License.
|
||||
.
|
||||
This package 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 package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
.
|
||||
On Debian systems, the complete text of the GNU Lesser General
|
||||
Public License can be found in `/usr/share/common-licenses/LGPL-2.1'.
|
||||
4
debian/preinst
vendored
4
debian/preinst
vendored
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
rm /etc/pulse/default.pa.gemian || true
|
||||
rm /etc/pulse/arm_droid_card_custom.pa || true
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
usr/include/pulsecore/modules/droid/*.h
|
||||
usr/lib/*/pkgconfig/*
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
usr/lib/pulse-*/modules/libdroid-sink*.so
|
||||
usr/lib/pulse-*/modules/libdroid-source*.so
|
||||
usr/lib/pulse-*/modules/libdroid-util*.so
|
||||
usr/lib/pulse-*/modules/module-droid-card*.so
|
||||
usr/lib/pulse-*/modules/module-droid-sink*.so
|
||||
usr/lib/pulse-*/modules/module-droid-source*.so
|
||||
etc/*
|
||||
33
debian/rules
vendored
33
debian/rules
vendored
|
|
@ -1,33 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
include /usr/share/dpkg/default.mk
|
||||
|
||||
PA_MODULE_DIR := $$(readlink -f /usr/lib/pulse-*/modules)
|
||||
|
||||
%:
|
||||
dh $@ --with=autoreconf
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- --disable-static --with-module-dir=${PA_MODULE_DIR}
|
||||
|
||||
override_dh_autoreconf:
|
||||
echo ${DEB_VERSION_UPSTREAM} > .tarball-version
|
||||
dh_autoreconf
|
||||
|
||||
override_dh_auto_clean:
|
||||
if [ -f .tarball-version ]; then rm .tarball-version; fi
|
||||
dh_auto_clean
|
||||
|
||||
override_dh_shlibdeps:
|
||||
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info -l/usr/lib/${DEB_HOST_MULTIARCH}/pulseaudio:/usr/lib/pulse-*/modules
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install
|
||||
|
||||
rm debian/tmp/usr/lib/pulse-*/modules/*.la
|
||||
|
||||
install -d debian/tmp/usr/include/pulsecore/modules/droid
|
||||
install -m 644 src/common/*.h debian/tmp/usr/include/pulsecore/modules/droid
|
||||
install -d debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig
|
||||
install -m 644 src/common/*.pc debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig
|
||||
1
debian/source/format
vendored
1
debian/source/format
vendored
|
|
@ -1 +0,0 @@
|
|||
3.0 (native)
|
||||
|
|
@ -1 +0,0 @@
|
|||
load-module module-droid-card
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
#!/usr/bin/pulseaudio -nF
|
||||
#
|
||||
# This file is part of PulseAudio.
|
||||
#
|
||||
# PulseAudio is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PulseAudio is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This startup script is used only if PulseAudio is started per-user
|
||||
# (i.e. not in system mode)
|
||||
|
||||
.nofail
|
||||
|
||||
.fail
|
||||
|
||||
load-module module-droid-keepalive
|
||||
|
||||
|
||||
### Automatically augment property information from .desktop files
|
||||
### stored in /usr/share/application
|
||||
load-module module-augment-properties
|
||||
|
||||
load-module module-null-sink sink_name=sink.null rate=48000
|
||||
|
||||
load-module module-stream-restore
|
||||
|
||||
### Switch when connected by default (ubports)
|
||||
load-module module-switch-on-connect ignore_virtual=yes
|
||||
### Should be after module-*-restore but before module-*-detect (sfos)
|
||||
load-module module-switch-on-port-available
|
||||
|
||||
|
||||
### If droid-card needs other arguments than the default, have the new
|
||||
### load-module line in /etc/pulse/arm_droid_card_custom.pa
|
||||
.ifexists /etc/pulse/arm_droid_card_custom.pa
|
||||
.include /etc/pulse/arm_droid_card_custom.pa
|
||||
.else
|
||||
load-module module-droid-card rate=48000
|
||||
.endif
|
||||
|
||||
### Needed on many new devices. HADK guide explains how to implement this fully
|
||||
.ifexists module-droid-glue.so
|
||||
.nofail
|
||||
load-module module-droid-glue
|
||||
.fail
|
||||
.endif
|
||||
|
||||
.ifexists module-droid-hidl-28.so
|
||||
.nofail
|
||||
load-module module-droid-hidl-28
|
||||
.fail
|
||||
.endif
|
||||
|
||||
load-module module-null-sink sink_name=sink.fake.sco rate=8000 channels=1
|
||||
load-module module-null-source source_name=source.fake.sco rate=8000 channels=1
|
||||
#load-module module-bluetooth-discover bluez4_args="sco_sink=sink.fake.sco sco_source=source.fake.sco" bluez5_args="headset=droid"
|
||||
load-module module-bluetooth-discover
|
||||
load-module module-bluetooth-policy
|
||||
|
||||
#load-module module-policy-enforcement
|
||||
|
||||
load-module module-role-ducking trigger_roles=alarm,notification,warning ducking_roles=x-maemo volume=-200dB
|
||||
|
||||
### Load several protocols
|
||||
.ifexists module-esound-protocol-unix.so
|
||||
load-module module-esound-protocol-unix
|
||||
.endif
|
||||
load-module module-native-protocol-unix
|
||||
|
||||
### Network access (may be configured with paprefs, so leave this commented
|
||||
### here if you plan to use paprefs)
|
||||
#load-module module-esound-protocol-tcp
|
||||
#load-module module-native-protocol-tcp
|
||||
#load-module module-zeroconf-publish
|
||||
|
||||
### Load the RTP receiver module (also configured via paprefs, see above)
|
||||
#load-module module-rtp-recv
|
||||
|
||||
### Load the RTP sender module (also configured via paprefs, see above)
|
||||
#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
|
||||
#load-module module-rtp-send source=rtp.monitor
|
||||
|
||||
### Load additional modules from GSettings. This can be configured with the paprefs tool.
|
||||
### Please keep in mind that the modules configured by paprefs might conflict with manually
|
||||
### loaded modules.
|
||||
.ifexists module-gsettings.so
|
||||
.nofail
|
||||
load-module module-gsettings
|
||||
.fail
|
||||
.endif
|
||||
|
||||
|
||||
### Make sure we always have a sink around, even if it is a null sink.
|
||||
load-module module-always-sink
|
||||
|
||||
### Honour intended role device property
|
||||
load-module module-intended-roles
|
||||
|
||||
### Automatically suspend sinks/sources that become idle for too long
|
||||
load-module module-suspend-on-idle timeout=1
|
||||
|
||||
### If autoexit on idle is enabled we want to make sure we only quit
|
||||
### when no local session needs us anymore.
|
||||
.ifexists module-console-kit.so
|
||||
load-module module-console-kit
|
||||
.endif
|
||||
.ifexists module-systemd-login.so
|
||||
load-module module-systemd-login
|
||||
.endif
|
||||
|
||||
### Load DBus protocol
|
||||
.ifexists module-dbus-protocol.so
|
||||
load-module module-dbus-protocol
|
||||
.endif
|
||||
|
||||
### Move orphan streams to placeholder sinks or sources so that playback doesn't get
|
||||
### interrupted. Policy enforcement module then moves the streams to new appropriate
|
||||
### sinks or sources.
|
||||
#load-module module-rescue-streams sink_name=sink.null source_name=sink.null.monitor
|
||||
|
||||
### Enable positioned event sounds
|
||||
load-module module-position-event-sounds
|
||||
|
||||
### Modules to allow auto-loading of filters (such as echo cancellation)
|
||||
### on demand. module-filter-heuristics tries to determine what filters
|
||||
### make sense, and module-filter-apply does the heavy-lifting of
|
||||
### loading modules and rerouting streams.
|
||||
load-module module-filter-heuristics
|
||||
load-module module-filter-apply
|
||||
|
||||
### Make some devices default
|
||||
set-default-sink sink.primary_output
|
||||
set-default-source source.droid
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if test $# -lt 1
|
||||
then
|
||||
echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VF=$1
|
||||
|
||||
# First see if there is a version file,
|
||||
# then try git-describe, otherwise fail.
|
||||
if test -f $VF
|
||||
then
|
||||
VN=$(cat $VF)
|
||||
elif test -d ${GIT_DIR:-.git} -o -f .git &&
|
||||
V=$(git describe --match "[0-9]*" --abbrev=7 --tags 2>/dev/null)
|
||||
then
|
||||
VN=$V
|
||||
else
|
||||
echo 1>&2 "$0: Failed to determine revision"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
echo "$VN" | tr -d '\012'
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
AC_DEFUN([CC_CHECK_DROID_ENUM],
|
||||
[AC_MSG_CHECKING([if droid headers have enum $2])
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_C
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $1"
|
||||
AC_TRY_COMPILE(
|
||||
[ #include <android-config.h>
|
||||
#ifdef QCOM_BSP
|
||||
#define QCOM_HARDWARE
|
||||
#endif
|
||||
#include <system/audio.h> ],
|
||||
[ unsigned int e = $2; ],
|
||||
cc_check_droid_enum=yes, cc_check_droid_enum=no)
|
||||
CFLAGS="$SAVE_CFLAGS"
|
||||
AC_LANG_RESTORE
|
||||
AC_MSG_RESULT([$cc_check_droid_enum])
|
||||
if test x"$cc_check_droid_enum" = x"yes"; then
|
||||
AC_DEFINE(HAVE_ENUM_$2,,[define if enum $2 is found in headers])
|
||||
AC_DEFINE(STRING_ENTRY_IF_$2,[STRING_ENTRY($2),],[string entry for enum $2])
|
||||
AC_DEFINE(FANCY_ENTRY_IF_$2(n),[{$2, n},],[fancy entry for enum $2])
|
||||
else
|
||||
AC_DEFINE(STRING_ENTRY_IF_$2,,[string entry for enum $2])
|
||||
AC_DEFINE(FANCY_ENTRY_IF_$2(n),,[fancy entry for enum $2])
|
||||
fi
|
||||
])
|
||||
7
rpm/precheckin.sh
Executable file
7
rpm/precheckin.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
DEVICES="boston mako sbj i9305"
|
||||
|
||||
for dev in $DEVICES; do
|
||||
sed -e "s/@DEVICE@/$dev/g" pulseaudio-modules-droid.spec.in > pulseaudio-modules-droid-$dev.spec
|
||||
done
|
||||
42
rpm/pulseaudio-modules-droid-boston.spec
Normal file
42
rpm/pulseaudio-modules-droid-boston.spec
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
%define device boston
|
||||
%define pulseversion 4.0
|
||||
|
||||
Name: pulseaudio-modules-droid-%{device}
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulseversion}.1
|
||||
Release: 1
|
||||
Group: Multimedia/PulseAudio
|
||||
License: LGPLv2.1+
|
||||
URL: https://github.com/mer-hybris/multimedia-pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: pulseaudio-modules-droid.spec.in
|
||||
Source2: precheckin.sh
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulseversion}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
Provides: pulseaudio-modules-droid
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
%reconfigure --disable-static --with-droid-device=%{device}
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulseversion}/modules/*.so
|
||||
42
rpm/pulseaudio-modules-droid-i9305.spec
Normal file
42
rpm/pulseaudio-modules-droid-i9305.spec
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
%define device i9305
|
||||
%define pulseversion 4.0
|
||||
|
||||
Name: pulseaudio-modules-droid-%{device}
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulseversion}.1
|
||||
Release: 1
|
||||
Group: Multimedia/PulseAudio
|
||||
License: LGPLv2.1+
|
||||
URL: https://github.com/mer-hybris/multimedia-pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: pulseaudio-modules-droid.spec.in
|
||||
Source2: precheckin.sh
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulseversion}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
Provides: pulseaudio-modules-droid
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
%reconfigure --disable-static --with-droid-device=%{device}
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulseversion}/modules/*.so
|
||||
42
rpm/pulseaudio-modules-droid-mako.spec
Normal file
42
rpm/pulseaudio-modules-droid-mako.spec
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
%define device mako
|
||||
%define pulseversion 4.0
|
||||
|
||||
Name: pulseaudio-modules-droid-%{device}
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulseversion}.1
|
||||
Release: 1
|
||||
Group: Multimedia/PulseAudio
|
||||
License: LGPLv2.1+
|
||||
URL: https://github.com/mer-hybris/multimedia-pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: pulseaudio-modules-droid.spec.in
|
||||
Source2: precheckin.sh
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulseversion}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
Provides: pulseaudio-modules-droid
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
%reconfigure --disable-static --with-droid-device=%{device}
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulseversion}/modules/*.so
|
||||
42
rpm/pulseaudio-modules-droid-sbj.spec
Normal file
42
rpm/pulseaudio-modules-droid-sbj.spec
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
%define device sbj
|
||||
%define pulseversion 4.0
|
||||
|
||||
Name: pulseaudio-modules-droid-%{device}
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulseversion}.1
|
||||
Release: 1
|
||||
Group: Multimedia/PulseAudio
|
||||
License: LGPLv2.1+
|
||||
URL: https://github.com/mer-hybris/multimedia-pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: pulseaudio-modules-droid.spec.in
|
||||
Source2: precheckin.sh
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulseversion}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
Provides: pulseaudio-modules-droid
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
%reconfigure --disable-static --with-droid-device=%{device}
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulseversion}/modules/*.so
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
%define pulseversion %{expand:%(rpm -q --qf '[%%{version}]' pulseaudio)}
|
||||
%define pulsemajorminor %{expand:%(echo '%{pulseversion}' | cut -d+ -f1)}
|
||||
%define moduleversion %{pulsemajorminor}.%{expand:%(echo '%{version}' | cut -d. -f3)}
|
||||
|
||||
Name: pulseaudio-modules-droid
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulsemajorminor}.101
|
||||
Release: 1
|
||||
License: LGPLv2+
|
||||
URL: https://github.com/mer-hybris/pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
Requires: %{name}-common = %{version}-%{release}
|
||||
Requires: pulseaudio-module-keepalive >= 1.0.0
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulsemajorminor}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(expat)
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
%package common
|
||||
Summary: Common libs for the PulseAudio droid modules
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
|
||||
%description common
|
||||
This contains common libs for the PulseAudio droid modules.
|
||||
|
||||
%package devel
|
||||
Summary: Development files for PulseAudio droid modules
|
||||
Requires: %{name}-common = %{version}-%{release}
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
|
||||
%description devel
|
||||
This contains development files for PulseAudio droid modules.
|
||||
|
||||
%prep
|
||||
%autosetup -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
echo "%{moduleversion}" > .tarball-version
|
||||
# Obtain the DEVICE from the same source as used in /etc/os-release
|
||||
if [ -e "%{_includedir}/droid-devel/hw-release.vars" ]; then
|
||||
. %{_includedir}/droid-devel/hw-release.vars
|
||||
else
|
||||
. %{_libdir}/droid-devel/hw-release.vars
|
||||
fi
|
||||
%reconfigure --disable-static --with-droid-device=$MER_HA_DEVICE
|
||||
%make_build
|
||||
|
||||
%install
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/libdroid-sink.so
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/libdroid-source.so
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/module-droid-sink.so
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/module-droid-source.so
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/module-droid-card.so
|
||||
%license COPYING
|
||||
|
||||
%files common
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulsemajorminor}/modules/libdroid-util.so
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{_includedir}/pulsecore/modules/droid
|
||||
%{_includedir}/pulsecore/modules/droid/conversion.h
|
||||
%{_includedir}/pulsecore/modules/droid/droid-config.h
|
||||
%{_includedir}/pulsecore/modules/droid/droid-util.h
|
||||
%{_includedir}/pulsecore/modules/droid/sllist.h
|
||||
%{_includedir}/pulsecore/modules/droid/utils.h
|
||||
%{_includedir}/pulsecore/modules/droid/version.h
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
42
rpm/pulseaudio-modules-droid.spec.in
Normal file
42
rpm/pulseaudio-modules-droid.spec.in
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
%define device @DEVICE@
|
||||
%define pulseversion 4.0
|
||||
|
||||
Name: pulseaudio-modules-droid-%{device}
|
||||
|
||||
Summary: PulseAudio Droid HAL modules
|
||||
Version: %{pulseversion}.1
|
||||
Release: 1
|
||||
Group: Multimedia/PulseAudio
|
||||
License: LGPLv2.1+
|
||||
URL: https://github.com/mer-hybris/multimedia-pulseaudio-modules-droid
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: pulseaudio-modules-droid.spec.in
|
||||
Source2: precheckin.sh
|
||||
Requires: pulseaudio >= %{pulseversion}
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: libtool-ltdl-devel
|
||||
BuildRequires: pkgconfig(pulsecore) >= %{pulseversion}
|
||||
BuildRequires: pkgconfig(android-headers)
|
||||
BuildRequires: pkgconfig(libhardware)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
Provides: pulseaudio-modules-droid
|
||||
|
||||
%description
|
||||
PulseAudio Droid HAL modules.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
%reconfigure --disable-static --with-droid-device=%{device}
|
||||
make %{?jobs:-j%jobs}
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
%make_install
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/pulse-%{pulseversion}/modules/*.so
|
||||
|
|
@ -1 +1 @@
|
|||
SUBDIRS = common droid
|
||||
SUBDIRS = droid
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
AM_LIBADD = \
|
||||
$(PULSEAUDIO_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/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 \
|
||||
include/droid/sllist.h \
|
||||
include/droid/utils.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libdroid-util.pc
|
||||
|
||||
libdroid_util_la_SOURCES = droid-util.c \
|
||||
droid-config.c \
|
||||
conversion.c \
|
||||
config-parser-xml.c \
|
||||
config-parser-xml.h \
|
||||
sllist.c \
|
||||
utils.c \
|
||||
droid-util-audio.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)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,529 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2022 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 ","
|
||||
|
||||
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;
|
||||
|
||||
for (unsigned int i = 0; list[i].str; i++) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Generic conversion */
|
||||
bool pa_string_convert_num_to_str(pa_conversion_string_t type, uint32_t value, const char **to_str) {
|
||||
switch (type) {
|
||||
case CONV_STRING_FORMAT:
|
||||
return string_convert_num_to_str(string_conversion_table_format, value, to_str);
|
||||
|
||||
case CONV_STRING_OUTPUT_CHANNELS:
|
||||
return string_convert_num_to_str(string_conversion_table_output_channels, value, to_str);
|
||||
|
||||
case CONV_STRING_INPUT_CHANNELS:
|
||||
return string_convert_num_to_str(string_conversion_table_input_channels, value, to_str);
|
||||
|
||||
case CONV_STRING_OUTPUT_DEVICE:
|
||||
return string_convert_num_to_str(string_conversion_table_output_device, value, to_str);
|
||||
|
||||
case CONV_STRING_INPUT_DEVICE:
|
||||
return string_convert_num_to_str(string_conversion_table_input_device, value, to_str);
|
||||
|
||||
case CONV_STRING_OUTPUT_FLAG:
|
||||
return string_convert_num_to_str(string_conversion_table_output_flag, value, to_str);
|
||||
|
||||
case CONV_STRING_INPUT_FLAG:
|
||||
return string_convert_num_to_str(string_conversion_table_input_flag, value, to_str);
|
||||
|
||||
case CONV_STRING_AUDIO_SOURCE_FANCY:
|
||||
return string_convert_num_to_str(string_conversion_table_audio_source_fancy, value, to_str);
|
||||
}
|
||||
|
||||
pa_assert_not_reached();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pa_string_convert_str_to_num(pa_conversion_string_t type, const char *str, uint32_t *to_value) {
|
||||
switch (type) {
|
||||
case CONV_STRING_FORMAT:
|
||||
return string_convert_str_to_num(string_conversion_table_format, str, to_value);
|
||||
|
||||
case CONV_STRING_OUTPUT_CHANNELS:
|
||||
return string_convert_str_to_num(string_conversion_table_output_channels, str, to_value);
|
||||
|
||||
case CONV_STRING_INPUT_CHANNELS:
|
||||
return string_convert_str_to_num(string_conversion_table_input_channels, str, to_value);
|
||||
|
||||
case CONV_STRING_OUTPUT_DEVICE:
|
||||
return string_convert_str_to_num(string_conversion_table_output_device, str, to_value);
|
||||
|
||||
case CONV_STRING_INPUT_DEVICE:
|
||||
return string_convert_str_to_num(string_conversion_table_input_device, str, to_value);
|
||||
|
||||
case CONV_STRING_OUTPUT_FLAG:
|
||||
return string_convert_str_to_num(string_conversion_table_output_flag, str, to_value);
|
||||
|
||||
case CONV_STRING_INPUT_FLAG:
|
||||
return string_convert_str_to_num(string_conversion_table_input_flag, str, to_value);
|
||||
|
||||
case CONV_STRING_AUDIO_SOURCE_FANCY:
|
||||
return string_convert_str_to_num(string_conversion_table_audio_source_fancy, str, to_value);
|
||||
}
|
||||
|
||||
pa_assert_not_reached();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Not handled in this context */
|
||||
case CONV_STRING_AUDIO_SOURCE_FANCY:
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pa_conversion_parse_sampling_rates(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
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, &state))) {
|
||||
int32_t val;
|
||||
|
||||
if (pos == 0 && pa_streq(entry, "dynamic")) {
|
||||
sampling_rates[pos++] = (uint32_t) -1;
|
||||
pa_xfree(entry);
|
||||
break;
|
||||
}
|
||||
|
||||
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,
|
||||
audio_format_t *formats) {
|
||||
int count;
|
||||
char *unknown = NULL;
|
||||
|
||||
pa_assert(fn);
|
||||
pa_assert(str);
|
||||
pa_assert(formats);
|
||||
|
||||
/* Needs to be probed later */
|
||||
if (pa_streq(str, "dynamic")) {
|
||||
*formats = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
count = pa_conversion_parse_list(CONV_STRING_FORMAT, VALUE_SEPARATOR, str, formats, &unknown);
|
||||
|
||||
/* 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 int parse_channels(const char *fn, const unsigned ln,
|
||||
const char *str, bool in_output,
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]) {
|
||||
bool success;
|
||||
int count = 0;
|
||||
char *unknown = NULL;
|
||||
char *entry;
|
||||
const char *state = NULL;
|
||||
|
||||
pa_assert(fn);
|
||||
pa_assert(str);
|
||||
|
||||
/* Needs to be probed later */
|
||||
if (pa_streq(str, "dynamic")) {
|
||||
channel_masks[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((entry = pa_split(str, VALUE_SEPARATOR, &state))) {
|
||||
uint32_t val;
|
||||
|
||||
if (count == AUDIO_MAX_CHANNEL_MASKS) {
|
||||
pa_log("[%s:%u] Too many channel mask entries (> %d)", fn, ln, AUDIO_MAX_CHANNEL_MASKS);
|
||||
pa_xfree(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string_convert_str_to_num(in_output ? string_conversion_table_output_channels
|
||||
: string_conversion_table_input_channels,
|
||||
entry,
|
||||
&val)) {
|
||||
pa_log_debug("[%s:%u] Ignore unknown channel mask value %s", fn, ln, entry);
|
||||
pa_xfree(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
channel_masks[count++] = val;
|
||||
|
||||
pa_xfree(entry);
|
||||
}
|
||||
|
||||
channel_masks[count] = 0;
|
||||
|
||||
/* Avoid aborting parsing when no supported channel is found */
|
||||
success = check_and_log(fn, ln, in_output ? "output channel_masks" : "input channel_masks",
|
||||
count == 0 ? 1 : count, str, unknown, false);
|
||||
return success ? count : -1;
|
||||
}
|
||||
|
||||
int pa_conversion_parse_output_channels(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]) {
|
||||
return parse_channels(fn, ln, str, true, channel_masks);
|
||||
}
|
||||
|
||||
int pa_conversion_parse_input_channels(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]) {
|
||||
return parse_channels(fn, ln, str, false, channel_masks);
|
||||
}
|
||||
|
||||
static bool parse_devices(const char *fn, const unsigned ln,
|
||||
const char *str, bool in_output,
|
||||
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, str, devices, &unknown);
|
||||
|
||||
/* 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 must_recognize_all,
|
||||
audio_devices_t *devices) {
|
||||
return parse_devices(fn, ln, str, true, must_recognize_all, devices);
|
||||
}
|
||||
|
||||
bool pa_conversion_parse_input_devices(const char *fn, const unsigned ln,
|
||||
char *str, bool must_recognize_all,
|
||||
audio_devices_t *devices) {
|
||||
return parse_devices(fn, ln, str, false, 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,366 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2022 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 "config-parser-xml.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/xmalloc.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
|
||||
#include <hardware/audio.h>
|
||||
|
||||
#define ODM_AUDIO_POLICY_CONFIG_XML_FILE "/odm/etc/audio_policy_configuration.xml"
|
||||
#define VENDOR_AUDIO_AUDIO_POLICY_CONFIG_XML_FILE "/vendor/etc/audio/audio_policy_configuration.xml"
|
||||
#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"
|
||||
|
||||
|
||||
dm_config_device *dm_config_load(pa_modargs *ma) {
|
||||
dm_config_device *config = NULL;
|
||||
const char *manual_config;
|
||||
const char *config_location[] = {
|
||||
ODM_AUDIO_POLICY_CONFIG_XML_FILE,
|
||||
VENDOR_AUDIO_AUDIO_POLICY_CONFIG_XML_FILE,
|
||||
VENDOR_AUDIO_POLICY_CONFIG_XML_FILE,
|
||||
SYSTEM_AUDIO_POLICY_CONFIG_XML_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;
|
||||
}
|
||||
|
||||
static dm_config_profile *config_profile_dup(const dm_config_profile *profile) {
|
||||
dm_config_profile *copy = pa_xnew0(dm_config_profile, 1);
|
||||
|
||||
copy->name = pa_xstrdup(profile->name);
|
||||
copy->format = profile->format;
|
||||
memcpy(copy->sampling_rates,
|
||||
profile->sampling_rates,
|
||||
sizeof(profile->sampling_rates));
|
||||
memcpy(copy->channel_masks,
|
||||
profile->channel_masks,
|
||||
sizeof(profile->channel_masks));
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static dm_config_port *config_port_dup(const dm_config_port *port, dm_config_module *module) {
|
||||
dm_config_port *copy = pa_xnew0(dm_config_port, 1);
|
||||
const dm_list_entry *i;
|
||||
|
||||
copy->module = module;
|
||||
copy->port_type = port->port_type;
|
||||
copy->name = pa_xstrdup(port->name);
|
||||
copy->role = port->role;
|
||||
copy->profiles = dm_list_new();
|
||||
|
||||
DM_LIST_FOREACH(i, port->profiles)
|
||||
dm_list_push_back(copy->profiles, config_profile_dup(i->data));
|
||||
|
||||
if (port->port_type == DM_CONFIG_TYPE_DEVICE_PORT) {
|
||||
copy->type = port->type;
|
||||
copy->address = pa_xstrdup(port->address);
|
||||
}
|
||||
|
||||
if (port->port_type == DM_CONFIG_TYPE_MIX_PORT) {
|
||||
copy->flags = port->flags;
|
||||
copy->max_open_count = port->max_open_count;
|
||||
copy->max_active_count = port->max_active_count;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static dm_config_route *config_route_dup(const dm_config_route *route, dm_list *ports) {
|
||||
dm_config_route *copy = pa_xnew0(dm_config_route, 1);
|
||||
dm_config_port *port_copy, *port;
|
||||
void *state, *state2;
|
||||
|
||||
copy->type = route->type;
|
||||
copy->sources = dm_list_new();
|
||||
|
||||
DM_LIST_FOREACH_DATA(port, route->sources, state) {
|
||||
DM_LIST_FOREACH_DATA(port_copy, ports, state2) {
|
||||
if (dm_config_port_equal(port, port_copy)) {
|
||||
dm_list_push_back(copy->sources, port_copy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DM_LIST_FOREACH_DATA(port_copy, ports, state) {
|
||||
if (dm_config_port_equal(port_copy, route->sink)) {
|
||||
copy->sink = port_copy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static dm_config_module *config_module_dup(const dm_config_module *module) {
|
||||
dm_config_module *copy = pa_xnew0(dm_config_module, 1);
|
||||
dm_config_port *device_port, *attached_device, *mix_port;
|
||||
dm_config_route *route;
|
||||
void *state, *state2;
|
||||
|
||||
copy = pa_xnew0(dm_config_module, 1);
|
||||
copy->name = pa_xstrdup(module->name);
|
||||
copy->version_major = module->version_major;
|
||||
copy->version_minor = module->version_minor;
|
||||
copy->attached_devices = dm_list_new();
|
||||
copy->default_output_device = NULL;
|
||||
copy->mix_ports = dm_list_new();
|
||||
copy->device_ports = dm_list_new();
|
||||
copy->ports = dm_list_new();
|
||||
copy->routes = dm_list_new();
|
||||
|
||||
DM_LIST_FOREACH_DATA(device_port, module->device_ports, state) {
|
||||
dm_config_port *device_port_copy = config_port_dup(device_port, copy);
|
||||
dm_list_push_back(copy->device_ports, device_port_copy);
|
||||
dm_list_push_back(copy->ports, device_port_copy);
|
||||
if (module->default_output_device == device_port)
|
||||
copy->default_output_device = device_port_copy;
|
||||
DM_LIST_FOREACH_DATA(attached_device, module->attached_devices, state2) {
|
||||
if (attached_device == device_port) {
|
||||
dm_list_push_back(copy->attached_devices, device_port_copy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DM_LIST_FOREACH_DATA(mix_port, module->mix_ports, state) {
|
||||
dm_config_port *mix_port_copy = config_port_dup(mix_port, copy);
|
||||
dm_list_push_back(copy->mix_ports, mix_port_copy);
|
||||
dm_list_push_back(copy->ports, mix_port_copy);
|
||||
}
|
||||
|
||||
DM_LIST_FOREACH_DATA(route, module->routes, state)
|
||||
dm_list_push_back(copy->routes, config_route_dup(route, copy->ports));
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
dm_config_device *dm_config_dup(const dm_config_device *config) {
|
||||
dm_config_device *copy;
|
||||
dm_config_module *module;
|
||||
void *state;
|
||||
|
||||
pa_assert(config);
|
||||
|
||||
copy = pa_xnew0(dm_config_device, 1);
|
||||
copy->global_config = dm_list_new();
|
||||
copy->modules = dm_list_new();
|
||||
|
||||
if (config->global_config) {
|
||||
dm_config_global *global, *global_copy;
|
||||
|
||||
DM_LIST_FOREACH_DATA(global, config->global_config, state) {
|
||||
global_copy = pa_xnew0(dm_config_global, 1);
|
||||
global_copy->key = pa_xstrdup(global->key);
|
||||
global_copy->value = pa_xstrdup(global->value);
|
||||
dm_list_push_back(copy->global_config, global_copy);
|
||||
}
|
||||
}
|
||||
|
||||
DM_LIST_FOREACH_DATA(module, config->modules, state)
|
||||
dm_list_push_back(copy->modules, config_module_dup(module));
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
dm_config_device *pa_parse_droid_audio_config(const char *filename) {
|
||||
return pa_parse_droid_audio_config_xml(filename);
|
||||
}
|
||||
|
||||
static void config_global_free(void *data) {
|
||||
dm_config_global *global = data;
|
||||
|
||||
pa_xfree(global->key);
|
||||
pa_xfree(global->value);
|
||||
pa_xfree(global);
|
||||
}
|
||||
|
||||
static void config_profile_free(void *data) {
|
||||
dm_config_profile *profile = data;
|
||||
|
||||
pa_xfree(profile->name);
|
||||
pa_xfree(profile);
|
||||
}
|
||||
|
||||
static void config_port_free(void *data) {
|
||||
dm_config_port *port = data;
|
||||
|
||||
pa_xfree(port->name);
|
||||
pa_xfree(port->address);
|
||||
dm_list_free(port->profiles, config_profile_free);
|
||||
pa_xfree(port);
|
||||
}
|
||||
|
||||
static void config_route_free(void *data) {
|
||||
dm_config_route *route = data;
|
||||
|
||||
dm_list_free(route->sources, NULL);
|
||||
pa_xfree(route);
|
||||
}
|
||||
|
||||
static void config_module_free(void *data) {
|
||||
dm_config_module *module = data;
|
||||
|
||||
pa_xfree(module->name);
|
||||
dm_list_free(module->attached_devices, NULL);
|
||||
dm_list_free(module->ports, config_port_free);
|
||||
dm_list_free(module->device_ports, NULL);
|
||||
dm_list_free(module->mix_ports, NULL);
|
||||
dm_list_free(module->routes, config_route_free);
|
||||
pa_xfree(module);
|
||||
}
|
||||
|
||||
void dm_config_free(dm_config_device *config) {
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
dm_list_free(config->global_config, config_global_free);
|
||||
dm_list_free(config->modules, config_module_free);
|
||||
pa_xfree(config);
|
||||
}
|
||||
|
||||
dm_config_module *dm_config_find_module(dm_config_device *config, const char* module_id) {
|
||||
dm_config_module *module;
|
||||
void *state;
|
||||
|
||||
pa_assert(config);
|
||||
pa_assert(module_id);
|
||||
|
||||
DM_LIST_FOREACH_DATA(module, config->modules, state) {
|
||||
if (pa_streq(module_id, module->name))
|
||||
return module;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dm_config_port *dm_config_find_port(dm_config_module *module, const char* name) {
|
||||
dm_config_port *port;
|
||||
void *state;
|
||||
|
||||
pa_assert(module);
|
||||
pa_assert(name);
|
||||
|
||||
DM_LIST_FOREACH_DATA(port, module->ports, state) {
|
||||
if (pa_streq(name, port->name))
|
||||
return port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dm_config_port *dm_config_default_output_device(dm_config_module *module) {
|
||||
pa_assert(module);
|
||||
|
||||
if (module->default_output_device)
|
||||
return module->default_output_device;
|
||||
else {
|
||||
pa_log("Module %s doesn't have default output device.", module->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *dm_config_escape_string(const char *string) {
|
||||
if (!string)
|
||||
return NULL;
|
||||
|
||||
/* Just replace whitespace with underscores for now. */
|
||||
|
||||
return pa_replace(string, " ", "_");
|
||||
}
|
||||
|
||||
dm_config_port *dm_config_find_device_port(dm_config_port *port, audio_devices_t device) {
|
||||
dm_config_port *device_port;
|
||||
void *state;
|
||||
|
||||
pa_assert(port);
|
||||
|
||||
DM_LIST_FOREACH_DATA(device_port, port->module->device_ports, state) {
|
||||
if (device_port->type == device)
|
||||
return device_port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool dm_config_port_equal(const dm_config_port *a, const dm_config_port *b) {
|
||||
if ((!a && b) || (a && !b))
|
||||
return false;
|
||||
|
||||
else if (!a && !b)
|
||||
return true;
|
||||
|
||||
return (pa_streq(a->name, b->name) && a->type == b->type);
|
||||
}
|
||||
|
||||
dm_config_port *dm_config_find_mix_port(dm_config_module *module, const char *name) {
|
||||
dm_config_port *mix_port = NULL;
|
||||
void *state;
|
||||
|
||||
DM_LIST_FOREACH_DATA(mix_port, module->mix_ports, state) {
|
||||
if (pa_streq(mix_port->name, name))
|
||||
return mix_port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1,433 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017-2022 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.
|
||||
*/
|
||||
|
||||
#ifndef _DROID_UTIL_AUDIO_H_
|
||||
#define _DROID_UTIL_AUDIO_H_
|
||||
|
||||
#include <android-config.h>
|
||||
#ifdef QCOM_BSP
|
||||
#define QCOM_HARDWARE
|
||||
#endif
|
||||
|
||||
#include <hardware/audio.h>
|
||||
|
||||
#include <pulse/channelmap.h>
|
||||
|
||||
|
||||
#ifdef STRING_ENTRY
|
||||
#error Macro clashing with our helper macro already defined somewhere, fix this droid lib.
|
||||
#endif
|
||||
|
||||
struct string_conversion {
|
||||
uint32_t value;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
#define STRING_ENTRY(str) { str, #str }
|
||||
|
||||
// PulseAudio value - Android value
|
||||
|
||||
uint32_t conversion_table_output_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_OUT_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_OUT_FRONT_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_OUT_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SUBWOOFER, AUDIO_CHANNEL_OUT_LOW_FREQUENCY },
|
||||
{ PA_CHANNEL_POSITION_REAR_LEFT, AUDIO_CHANNEL_OUT_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_REAR_RIGHT, AUDIO_CHANNEL_OUT_BACK_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_OUT_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_LEFT },
|
||||
{ PA_CHANNEL_POSITION_SIDE_RIGHT, AUDIO_CHANNEL_OUT_SIDE_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_CENTER, AUDIO_CHANNEL_OUT_TOP_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_CENTER, AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_CENTER, AUDIO_CHANNEL_OUT_TOP_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_RIGHT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT }
|
||||
};
|
||||
|
||||
uint32_t conversion_table_input_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_IN_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_IN_FRONT },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_IN_BACK },
|
||||
/* Following are missing suitable counterparts on PulseAudio side. */
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT_PROCESSED },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT_PROCESSED },
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_IN_FRONT_PROCESSED },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_IN_BACK_PROCESSED },
|
||||
{ PA_CHANNEL_POSITION_SUBWOOFER, AUDIO_CHANNEL_IN_PRESSURE },
|
||||
{ PA_CHANNEL_POSITION_AUX0, AUDIO_CHANNEL_IN_X_AXIS },
|
||||
{ PA_CHANNEL_POSITION_AUX1, AUDIO_CHANNEL_IN_Y_AXIS },
|
||||
{ PA_CHANNEL_POSITION_AUX2, AUDIO_CHANNEL_IN_Z_AXIS },
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_IN_VOICE_UPLINK },
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_IN_VOICE_DNLINK }
|
||||
};
|
||||
|
||||
uint32_t conversion_table_format[][2] = {
|
||||
{ PA_SAMPLE_U8, AUDIO_FORMAT_PCM_8_BIT },
|
||||
{ PA_SAMPLE_S16LE, AUDIO_FORMAT_PCM_16_BIT },
|
||||
{ PA_SAMPLE_S24_32LE, AUDIO_FORMAT_PCM_8_24_BIT },
|
||||
{ PA_SAMPLE_S24LE, AUDIO_FORMAT_PCM_24_BIT_PACKED },
|
||||
{ PA_SAMPLE_S32LE, AUDIO_FORMAT_PCM_32_BIT }
|
||||
};
|
||||
|
||||
uint32_t conversion_table_default_audio_source[][2] = {
|
||||
{ AUDIO_DEVICE_IN_COMMUNICATION, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_AMBIENT, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_AUX_DIGITAL, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_VOICE_CALL, AUDIO_SOURCE_VOICE_CALL },
|
||||
{ AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_SOURCE_VOICE_CALL },
|
||||
{ AUDIO_DEVICE_IN_BACK_MIC, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_SOURCE_REMOTE_SUBMIX },
|
||||
{ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_FM_TUNER, AUDIO_SOURCE_FM_TUNER },
|
||||
{ AUDIO_DEVICE_IN_TV_TUNER, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_LINE, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_SPDIF, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_LOOPBACK, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_IP, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_BUS, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_PROXY, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_SOURCE_MIC },
|
||||
{ AUDIO_DEVICE_IN_ECHO_REFERENCE, AUDIO_SOURCE_MIC },
|
||||
|
||||
#if defined(HAVE_ENUM_AUDIO_DEVICE_IN_FM_RX) && defined(HAVE_ENUM_AUDIO_SOURCE_FM_RX)
|
||||
{ AUDIO_DEVICE_IN_FM_RX, AUDIO_SOURCE_FM_RX },
|
||||
#endif
|
||||
#if defined(HAVE_ENUM_AUDIO_DEVICE_IN_FM_RX_A2DP) && defined(HAVE_ENUM_AUDIO_SOURCE_FM_RX_A2DP)
|
||||
{ AUDIO_DEVICE_IN_FM_RX_A2DP, AUDIO_SOURCE_FM_RX_A2DP },
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Output devices */
|
||||
struct string_conversion string_conversion_table_output_device[] = {
|
||||
/* Each device listed here needs fancy name counterpart
|
||||
* in string_conversion_table_output_device_fancy. */
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_EARPIECE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_SPEAKER ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_WIRED_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_WIRED_HEADPHONE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_SCO ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_A2DP ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_AUX_DIGITAL ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_USB_ACCESSORY ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_USB_DEVICE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_REMOTE_SUBMIX ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_TELEPHONY_TX ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_LINE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_HDMI_ARC ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_SPDIF ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_FM ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_AUX_LINE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_SPEAKER_SAFE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_IP ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_BUS ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_PROXY ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_USB_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_HEARING_AID ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_ECHO_CANCELLER ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_OUT_DEFAULT ),
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct string_conversion string_conversion_table_audio_mode_fancy[] = {
|
||||
{ AUDIO_MODE_NORMAL, "normal" },
|
||||
{ AUDIO_MODE_RINGTONE, "ringtone" },
|
||||
{ AUDIO_MODE_IN_CALL, "in call" },
|
||||
{ AUDIO_MODE_IN_COMMUNICATION, "in communication" },
|
||||
{ AUDIO_MODE_CALL_SCREEN, "call screen" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct string_conversion string_conversion_table_output_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_OUT_EARPIECE, "output-earpiece" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER, "output-speaker" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADSET, "output-wired_headset" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "output-wired_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "output-bluetooth_sco" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, "output-sco_headset" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, "output-sco_carkit" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "output-a2dp" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, "output-a2dp_headphones" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "output-a2dp_speaker" },
|
||||
{ AUDIO_DEVICE_OUT_AUX_DIGITAL, "output-aux_digital" },
|
||||
{ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "output-analog_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "output-digital_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_USB_ACCESSORY, "output-usb_accessory" },
|
||||
{ AUDIO_DEVICE_OUT_USB_DEVICE, "output-usb_device" },
|
||||
{ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "output-remote_submix" },
|
||||
{ AUDIO_DEVICE_OUT_TELEPHONY_TX, "output-telephony_tx" },
|
||||
{ AUDIO_DEVICE_OUT_LINE, "output-line" },
|
||||
{ AUDIO_DEVICE_OUT_HDMI_ARC, "output-hdmi_arc" },
|
||||
{ AUDIO_DEVICE_OUT_SPDIF, "output-spdif" },
|
||||
{ AUDIO_DEVICE_OUT_FM, "output-fm" },
|
||||
{ AUDIO_DEVICE_OUT_AUX_LINE, "output-aux_line" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER_SAFE, "output-speaker_safe" },
|
||||
{ AUDIO_DEVICE_OUT_IP, "output-ip" },
|
||||
{ AUDIO_DEVICE_OUT_BUS, "output-bus" },
|
||||
{ AUDIO_DEVICE_OUT_PROXY, "output-proxy" },
|
||||
{ AUDIO_DEVICE_OUT_USB_HEADSET, "output-usb_headset" },
|
||||
{ AUDIO_DEVICE_OUT_HEARING_AID, "output-hearing_aid" },
|
||||
{ AUDIO_DEVICE_OUT_ECHO_CANCELLER, "output-echo_canceller" },
|
||||
{ AUDIO_DEVICE_OUT_DEFAULT, "output-default" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Input devices */
|
||||
struct string_conversion string_conversion_table_input_device[] = {
|
||||
/* Each device listed here needs fancy name counterpart
|
||||
* in string_conversion_table_input_device_fancy. */
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_COMMUNICATION ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_AMBIENT ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BUILTIN_MIC ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_WIRED_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_AUX_DIGITAL ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_HDMI ), /* Same as AUDIO_DEVICE_IN_AUX_DIGITAL */
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_VOICE_CALL ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_TELEPHONY_RX ), /* Same as AUDIO_DEVICE_IN_VOICE_CALL */
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BACK_MIC ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_REMOTE_SUBMIX ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_USB_ACCESSORY ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_USB_DEVICE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_FM_TUNER ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_TV_TUNER ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_LINE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_SPDIF ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BLUETOOTH_A2DP ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_LOOPBACK ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_IP ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BUS ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_PROXY ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_USB_HEADSET ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_BLUETOOTH_BLE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_HDMI_ARC ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_ECHO_REFERENCE ),
|
||||
STRING_ENTRY( AUDIO_DEVICE_IN_DEFAULT ),
|
||||
|
||||
/* Devices which may or may not be defined for all devices. */
|
||||
STRING_ENTRY_IF_AUDIO_DEVICE_IN_FM_RX
|
||||
STRING_ENTRY_IF_AUDIO_DEVICE_IN_FM_RX_A2DP
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct string_conversion string_conversion_table_input_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_IN_COMMUNICATION, "input-communication" },
|
||||
{ AUDIO_DEVICE_IN_AMBIENT, "input-ambient" },
|
||||
{ AUDIO_DEVICE_IN_BUILTIN_MIC, "input-builtin_mic" },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "input-bluetooth_sco_headset" },
|
||||
{ AUDIO_DEVICE_IN_WIRED_HEADSET, "input-wired_headset" },
|
||||
{ AUDIO_DEVICE_IN_AUX_DIGITAL, "input-aux_digital" },
|
||||
{ AUDIO_DEVICE_IN_VOICE_CALL, "input-voice_call" },
|
||||
{ AUDIO_DEVICE_IN_TELEPHONY_RX, "input-telephony_rx", },
|
||||
{ AUDIO_DEVICE_IN_BACK_MIC, "input-back_mic" },
|
||||
{ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "input-remote_submix" },
|
||||
{ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, "input-analog_dock_headset" },
|
||||
{ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, "input-digital_dock_headset" },
|
||||
{ AUDIO_DEVICE_IN_USB_ACCESSORY, "input-usb_accessory" },
|
||||
{ AUDIO_DEVICE_IN_USB_DEVICE, "input-usb_device" },
|
||||
{ AUDIO_DEVICE_IN_FM_TUNER, "input-fm_tuner" },
|
||||
{ AUDIO_DEVICE_IN_TV_TUNER, "input-tv_tuner" },
|
||||
{ AUDIO_DEVICE_IN_LINE, "input-line" },
|
||||
{ AUDIO_DEVICE_IN_SPDIF, "input-spdif" },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "input-bluetooth_a2dp" },
|
||||
{ AUDIO_DEVICE_IN_LOOPBACK, "input-loopback" },
|
||||
{ AUDIO_DEVICE_IN_IP, "input-ip" },
|
||||
{ AUDIO_DEVICE_IN_BUS, "input-bus" },
|
||||
{ AUDIO_DEVICE_IN_PROXY, "input-proxy" },
|
||||
{ AUDIO_DEVICE_IN_USB_HEADSET, "input-usb_headset" },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_BLE, "input-bluetooth_ble" },
|
||||
{ AUDIO_DEVICE_IN_HDMI_ARC, "input-hdmi_arc" },
|
||||
{ AUDIO_DEVICE_IN_ECHO_REFERENCE, "input-echo_reference" },
|
||||
{ AUDIO_DEVICE_IN_DEFAULT, "input-default" },
|
||||
|
||||
/* Devices which may or may not be defined for all devices. */
|
||||
FANCY_ENTRY_IF_AUDIO_DEVICE_IN_FM_RX ( "input-fm_rx" )
|
||||
FANCY_ENTRY_IF_AUDIO_DEVICE_IN_FM_RX_A2DP ( "input-fm_rx_a2dp" )
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Audio source fancy names */
|
||||
struct string_conversion string_conversion_table_audio_source_fancy[] = {
|
||||
{ AUDIO_SOURCE_DEFAULT, "default" },
|
||||
{ AUDIO_SOURCE_MIC, "mic" },
|
||||
{ AUDIO_SOURCE_VOICE_UPLINK, "voice uplink" },
|
||||
{ AUDIO_SOURCE_VOICE_DOWNLINK, "voice downlink" },
|
||||
{ AUDIO_SOURCE_VOICE_CALL, "voice call" },
|
||||
{ AUDIO_SOURCE_CAMCORDER, "camcorder" },
|
||||
{ AUDIO_SOURCE_VOICE_RECOGNITION, "voice recognition" },
|
||||
{ AUDIO_SOURCE_VOICE_COMMUNICATION, "voice communication" },
|
||||
{ AUDIO_SOURCE_REMOTE_SUBMIX, "remote submix" },
|
||||
{ AUDIO_SOURCE_UNPROCESSED, "unprocessed" },
|
||||
{ AUDIO_SOURCE_VOICE_PERFORMANCE, "voice performance" },
|
||||
|
||||
/* Audio sources which may or may not be defined for all devices. */
|
||||
FANCY_ENTRY_IF_AUDIO_SOURCE_ECHO_REFERENCE ( "echo reference" )
|
||||
FANCY_ENTRY_IF_AUDIO_SOURCE_FM_TUNER ( "fm tuner" )
|
||||
FANCY_ENTRY_IF_AUDIO_SOURCE_FM_RX ( "fm rx" )
|
||||
FANCY_ENTRY_IF_AUDIO_SOURCE_FM_RX_A2DP ( "fm rx a2dp" )
|
||||
|
||||
{ (uint32_t)-1, NULL }
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
struct string_conversion string_conversion_table_output_flag[] = {
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_NONE ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_DIRECT ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_PRIMARY ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_FAST ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_DEEP_BUFFER ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_NON_BLOCKING ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_HW_AV_SYNC ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_TTS ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_RAW ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_SYNC ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_DIRECT_PCM ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_MMAP_NOIRQ ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_VOIP_RX ),
|
||||
STRING_ENTRY( AUDIO_OUTPUT_FLAG_INCALL_MUSIC ),
|
||||
|
||||
/* Audio output flags which may or may not be defined for all devices. */
|
||||
STRING_ENTRY_IF_AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct string_conversion string_conversion_table_input_flag[] = {
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_NONE ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_FAST ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_HW_HOTWORD ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_RAW ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_SYNC ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_MMAP_NOIRQ ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_VOIP_TX ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_HW_AV_SYNC ),
|
||||
STRING_ENTRY( AUDIO_INPUT_FLAG_DIRECT ),
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Channels */
|
||||
struct string_conversion string_conversion_table_output_channels[] = {
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_FRONT_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_FRONT_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_FRONT_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_LOW_FREQUENCY ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_BACK_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_BACK_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_BACK_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_SIDE_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_SIDE_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_BACK_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_BACK_CENTER ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_MONO ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_STEREO ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_OUT_QUAD ),
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
struct string_conversion string_conversion_table_input_channels[] = {
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_LEFT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_RIGHT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_FRONT ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_BACK ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_LEFT_PROCESSED ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_RIGHT_PROCESSED ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_FRONT_PROCESSED ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_BACK_PROCESSED ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_PRESSURE ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_X_AXIS ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_Y_AXIS ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_Z_AXIS ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_VOICE_UPLINK ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_VOICE_DNLINK ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_MONO ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_STEREO ),
|
||||
STRING_ENTRY( AUDIO_CHANNEL_IN_FRONT_BACK ),
|
||||
STRING_ENTRY_IF_AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO
|
||||
STRING_ENTRY_IF_AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO
|
||||
STRING_ENTRY_IF_AUDIO_CHANNEL_IN_VOICE_CALL_MONO
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Formats */
|
||||
struct string_conversion string_conversion_table_format[] = {
|
||||
/* Omit most formats as we aren't usually interested in
|
||||
* other than the pcm formats anyway. */
|
||||
STRING_ENTRY( AUDIO_FORMAT_INVALID ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_DEFAULT ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_PCM ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_AMR_NB ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_AMR_WB ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_FLAC ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_MP3 ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_OPUS ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_SBC ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_VORBIS ),
|
||||
|
||||
STRING_ENTRY( AUDIO_FORMAT_PCM_16_BIT ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_PCM_8_BIT ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_PCM_32_BIT ),
|
||||
STRING_ENTRY( AUDIO_FORMAT_PCM_8_24_BIT ),
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#undef STRING_ENTRY
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,111 +0,0 @@
|
|||
#ifndef foodroidconversionfoo
|
||||
#define foodroidconversionfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018-2022 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,
|
||||
CONV_STRING_AUDIO_SOURCE_FANCY,
|
||||
} pa_conversion_string_t;
|
||||
|
||||
bool pa_string_convert_num_to_str(pa_conversion_string_t type, uint32_t value, const char **to_str);
|
||||
bool pa_string_convert_str_to_num(pa_conversion_string_t type, const char *str, uint32_t *to_value);
|
||||
|
||||
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_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);
|
||||
|
||||
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,
|
||||
uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]);
|
||||
bool pa_conversion_parse_formats(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
audio_format_t *formats);
|
||||
int pa_conversion_parse_output_channels(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]);
|
||||
int pa_conversion_parse_input_channels(const char *fn, const unsigned ln,
|
||||
const char *str,
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]);
|
||||
bool pa_conversion_parse_output_devices(const char *fn, const unsigned ln,
|
||||
char *str, bool must_recognize_all,
|
||||
audio_devices_t *devices);
|
||||
bool pa_conversion_parse_input_devices(const char *fn, const unsigned ln,
|
||||
char *str, 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
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#ifndef foodroidconfigfoo
|
||||
#define foodroidconfigfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018-2022 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/sllist.h>
|
||||
#include <droid/version.h>
|
||||
|
||||
#define AUDIO_MAX_SAMPLING_RATES (32)
|
||||
#define AUDIO_MAX_CHANNEL_MASKS (32)
|
||||
|
||||
typedef struct dm_config_global dm_config_global;
|
||||
typedef struct dm_config_port dm_config_port;
|
||||
typedef struct dm_config_route dm_config_route;
|
||||
typedef struct dm_config_module dm_config_module;
|
||||
typedef struct dm_config_device dm_config_device;
|
||||
typedef struct dm_config_profile dm_config_profile;
|
||||
|
||||
struct dm_config_global {
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct dm_config_profile {
|
||||
char *name;
|
||||
audio_format_t format; /* 0 -> dynamic TODO check that this is still true */
|
||||
uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES]; /* sampling_rates[0] == 0 -> dynamic, otherwise 0 terminates list */
|
||||
audio_channel_mask_t channel_masks[AUDIO_MAX_CHANNEL_MASKS]; /* channel_masks[0] == 0 -> dynamic */
|
||||
};
|
||||
|
||||
typedef enum dm_config_role {
|
||||
DM_CONFIG_ROLE_SINK,
|
||||
DM_CONFIG_ROLE_SOURCE,
|
||||
} dm_config_role_t;
|
||||
|
||||
typedef enum dm_config_type {
|
||||
DM_CONFIG_TYPE_MIX,
|
||||
DM_CONFIG_TYPE_DEVICE_PORT,
|
||||
DM_CONFIG_TYPE_MIX_PORT,
|
||||
} dm_config_type_t;
|
||||
|
||||
struct dm_config_port {
|
||||
dm_config_module *module;
|
||||
|
||||
/* common values */
|
||||
|
||||
dm_config_type_t port_type; /* either mixPort or devicePort */
|
||||
char *name;
|
||||
dm_config_role_t role;
|
||||
dm_list *profiles; /* dm_config_profile* */
|
||||
|
||||
/* devicePort specific values */
|
||||
|
||||
audio_devices_t type;
|
||||
char *address;
|
||||
|
||||
/* mixPort specific values */
|
||||
|
||||
uint32_t flags; /* audio_output_flag_t or audio_input_flag_t */
|
||||
int max_open_count; /* 0 == not defined */
|
||||
int max_active_count; /* 0 == not defined */
|
||||
};
|
||||
|
||||
struct dm_config_route {
|
||||
dm_config_type_t type;
|
||||
dm_config_port *sink;
|
||||
dm_list *sources; /* dm_config_port* */
|
||||
};
|
||||
|
||||
struct dm_config_module {
|
||||
dm_config_device *config;
|
||||
|
||||
char *name;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
|
||||
dm_list *attached_devices; /* dm_config_port* owned by device_ports list below */
|
||||
dm_config_port *default_output_device; /* owned by device_ports list below */
|
||||
dm_list *ports; /* dm_config_port* - for convenience port types are filtered to two lists below: */
|
||||
dm_list *mix_ports; /* dm_config_port* */
|
||||
dm_list *device_ports; /* dm_config_port* */
|
||||
dm_list *routes; /* dm_config_route* */
|
||||
};
|
||||
|
||||
struct dm_config_device {
|
||||
dm_list *global_config; /* dm_config_global* */
|
||||
dm_list *modules; /* dm_config_module* */
|
||||
};
|
||||
|
||||
|
||||
/* Config parser */
|
||||
dm_config_device *dm_config_load(pa_modargs *ma);
|
||||
dm_config_device *dm_config_dup(const dm_config_device *config);
|
||||
void dm_config_free(dm_config_device *config);
|
||||
/* autodetect config type from filename and parse */
|
||||
dm_config_device *pa_parse_droid_audio_config(const char *filename);
|
||||
|
||||
dm_config_module *dm_config_find_module(dm_config_device *config, const char* module_id);
|
||||
dm_config_port *dm_config_find_port(dm_config_module *module, const char* name);
|
||||
dm_config_port *dm_config_default_output_device(dm_config_module *module);
|
||||
dm_config_port *dm_config_find_device_port(dm_config_port *port, audio_devices_t device);
|
||||
char *dm_config_escape_string(const char *string);
|
||||
|
||||
bool dm_config_port_equal(const dm_config_port *a, const dm_config_port *b);
|
||||
|
||||
dm_config_port *dm_config_find_mix_port(dm_config_module *module, const char *name);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
#ifndef foodroidutilfoo
|
||||
#define foodroidutilfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2022 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 <pulsecore/modargs.h>
|
||||
|
||||
#include <droid/version.h>
|
||||
#include <droid/droid-config.h>
|
||||
|
||||
#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_OUTPUT_VOIP "droid.output.voip"
|
||||
#define PROP_DROID_INPUT_BUILTIN "droid.input.builtin"
|
||||
#define PROP_DROID_INPUT_EXTERNAL "droid.input.external"
|
||||
#define PROP_DROID_INPUT_VOIP "droid.input.voip"
|
||||
|
||||
#define EXT_PROP_AUDIO_SOURCE "audio.source"
|
||||
|
||||
#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 struct pa_droid_options pa_droid_options;
|
||||
|
||||
enum pa_droid_option_type {
|
||||
DM_OPTION_INPUT_ATOI,
|
||||
DM_OPTION_CLOSE_INPUT,
|
||||
DM_OPTION_UNLOAD_NO_CLOSE,
|
||||
DM_OPTION_HW_VOLUME,
|
||||
DM_OPTION_REALCALL,
|
||||
DM_OPTION_UNLOAD_CALL_EXIT,
|
||||
DM_OPTION_OUTPUT_FAST,
|
||||
DM_OPTION_OUTPUT_DEEP_BUFFER,
|
||||
DM_OPTION_AUDIO_CAL_WAIT,
|
||||
DM_OPTION_SPEAKER_BEFORE_VOICE,
|
||||
DM_OPTION_OUTPUT_VOIP_RX,
|
||||
DM_OPTION_RECORD_VOICE_16K,
|
||||
DM_OPTION_COUNT
|
||||
};
|
||||
|
||||
struct pa_droid_options {
|
||||
bool enabled[DM_OPTION_COUNT];
|
||||
};
|
||||
|
||||
struct pa_droid_hw_module {
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_core *core;
|
||||
char *shared_name;
|
||||
|
||||
dm_config_device *config;
|
||||
dm_config_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_id;
|
||||
bool bt_sco_enabled;
|
||||
|
||||
pa_idxset *outputs;
|
||||
pa_idxset *inputs;
|
||||
pa_hook_slot *sink_put_hook_slot;
|
||||
pa_hook_slot *sink_unlink_hook_slot;
|
||||
|
||||
pa_atomic_t active_outputs;
|
||||
|
||||
pa_droid_options options;
|
||||
|
||||
/* Mode and input control */
|
||||
struct _state {
|
||||
audio_mode_t mode;
|
||||
} state;
|
||||
};
|
||||
|
||||
struct pa_droid_output_stream {
|
||||
struct audio_stream_out *stream;
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
};
|
||||
|
||||
struct pa_droid_input_stream {
|
||||
struct audio_stream_in *stream;
|
||||
pa_sample_spec default_sample_spec;
|
||||
pa_channel_map default_channel_map;
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
pa_sample_spec req_sample_spec;
|
||||
pa_channel_map req_channel_map;
|
||||
|
||||
audio_source_t audio_source;
|
||||
dm_config_port *default_mix_port;
|
||||
dm_config_port *input_port;
|
||||
pa_droid_stream *active_input;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t device;
|
||||
bool first;
|
||||
};
|
||||
|
||||
struct pa_droid_stream {
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_droid_hw_module *module;
|
||||
dm_config_port *mix_port;
|
||||
size_t buffer_size;
|
||||
void *data;
|
||||
|
||||
audio_io_handle_t io_handle;
|
||||
audio_patch_handle_t audio_patch;
|
||||
const dm_config_port *active_device_port;
|
||||
|
||||
pa_droid_output_stream *output;
|
||||
pa_droid_input_stream *input;
|
||||
};
|
||||
|
||||
struct pa_droid_card_data {
|
||||
void *userdata;
|
||||
char *module_id;
|
||||
};
|
||||
|
||||
|
||||
/* 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 {
|
||||
dm_config_port *device_port;
|
||||
} pa_droid_port_data;
|
||||
|
||||
typedef struct pa_droid_port {
|
||||
pa_droid_mapping *mapping;
|
||||
|
||||
dm_config_port *device_port;
|
||||
char *name;
|
||||
char *description;
|
||||
unsigned priority;
|
||||
} pa_droid_port;
|
||||
|
||||
struct pa_droid_mapping {
|
||||
pa_droid_profile_set *profile_set;
|
||||
|
||||
dm_config_module *module;
|
||||
dm_config_port *mix_port;
|
||||
dm_list *device_ports;
|
||||
|
||||
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;
|
||||
|
||||
dm_config_module *module;
|
||||
|
||||
char *name;
|
||||
char *description;
|
||||
unsigned priority;
|
||||
|
||||
/* Idxsets contain pa_droid_mapping objects.
|
||||
* Profile doesn't own the mappings, these
|
||||
* are references to structs in profile set
|
||||
* hashmaps. */
|
||||
pa_idxset *output_mappings;
|
||||
/* Only one input */
|
||||
pa_idxset *input_mappings;
|
||||
pa_droid_mapping *input_mapping;
|
||||
|
||||
} pa_droid_profile;
|
||||
|
||||
struct pa_droid_profile_set {
|
||||
dm_config_device *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"
|
||||
|
||||
/* 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, dm_config_device *config, const char *module_id);
|
||||
/* First try to get already open hw module and if none found parse config and options from modargs
|
||||
* and do initial open. */
|
||||
pa_droid_hw_module *pa_droid_hw_module_get2(pa_core *core, pa_modargs *ma, 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);
|
||||
|
||||
void pa_droid_options_log(pa_droid_hw_module *hw);
|
||||
|
||||
static inline bool pa_droid_option(pa_droid_hw_module *hw, enum pa_droid_option_type option) {
|
||||
return hw && hw->options.enabled[option];
|
||||
}
|
||||
|
||||
bool pa_droid_hw_set_mode(pa_droid_hw_module *hw_module, audio_mode_t mode);
|
||||
bool pa_droid_hw_has_mic_control(pa_droid_hw_module *hw);
|
||||
int pa_droid_hw_mic_get_mute(pa_droid_hw_module *hw_module, bool *muted);
|
||||
void pa_droid_hw_mic_set_mute(pa_droid_hw_module *hw_module, bool muted);
|
||||
|
||||
/* Profiles */
|
||||
pa_droid_profile_set *pa_droid_profile_set_default_new(dm_config_module *module);
|
||||
void pa_droid_profile_set_free(pa_droid_profile_set *ps);
|
||||
|
||||
void pa_droid_profile_free(pa_droid_profile *p);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/* Module operations */
|
||||
int pa_droid_set_parameters(pa_droid_hw_module *hw, const char *parameters);
|
||||
pa_droid_stream *pa_droid_hw_primary_output_stream(pa_droid_hw_module *hw);
|
||||
|
||||
/* 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,
|
||||
dm_config_port *mix_port,
|
||||
dm_config_port *device_port);
|
||||
|
||||
/* 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, dm_config_port *device_port);
|
||||
|
||||
/* Open input stream with currently active routing, sample_spec and channel_map
|
||||
* are requests and may change when opening the stream. */
|
||||
pa_droid_stream *pa_droid_open_input_stream(pa_droid_hw_module *hw_module,
|
||||
const pa_sample_spec *default_sample_spec,
|
||||
const pa_channel_map *default_channel_map,
|
||||
const char *mix_port_name);
|
||||
/* Test if reconfiguring of input stream is needed */
|
||||
bool pa_droid_stream_reconfigure_input_needed(pa_droid_stream *s,
|
||||
const pa_sample_spec *requested_sample_spec,
|
||||
const pa_channel_map *requested_channel_map,
|
||||
const pa_proplist *proplist);
|
||||
bool pa_droid_stream_reconfigure_input(pa_droid_stream *s,
|
||||
const pa_sample_spec *requested_sample_spec,
|
||||
const pa_channel_map *requested_channel_map,
|
||||
const pa_proplist *proplist);
|
||||
bool pa_droid_hw_set_input_device(pa_droid_stream *s,
|
||||
dm_config_port *device_port);
|
||||
|
||||
const pa_sample_spec *pa_droid_stream_sample_spec(pa_droid_stream *stream);
|
||||
const pa_channel_map *pa_droid_stream_channel_map(pa_droid_stream *stream);
|
||||
|
||||
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);
|
||||
|
||||
pa_modargs *pa_droid_modargs_new(const char *args, const char* const keys[]);
|
||||
|
||||
/* Misc */
|
||||
size_t pa_droid_buffer_size_round_up(size_t buffer_size, size_t block_size);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#ifndef foosllistfoo
|
||||
#define foosllistfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018-2022 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 <pulse/def.h>
|
||||
|
||||
#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)
|
||||
|
||||
typedef struct dm_list_entry dm_list_entry;
|
||||
typedef struct dm_list dm_list;
|
||||
|
||||
struct dm_list_entry {
|
||||
struct dm_list_entry *next;
|
||||
struct dm_list_entry *prev;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct dm_list {
|
||||
struct dm_list_entry *head;
|
||||
struct dm_list_entry *tail;
|
||||
ssize_t size;
|
||||
};
|
||||
|
||||
dm_list *dm_list_new(void);
|
||||
void dm_list_free(dm_list *list, pa_free_cb_t free_cb);
|
||||
bool dm_list_remove(dm_list *list, dm_list_entry *entry);
|
||||
void dm_list_prepend(dm_list *list, void *data);
|
||||
void dm_list_push_back(dm_list *list, void *data);
|
||||
dm_list_entry *dm_list_last(dm_list *list);
|
||||
void *dm_list_steal_first(dm_list *list);
|
||||
ssize_t dm_list_size(dm_list *list);
|
||||
void *dm_list_first_data(dm_list *list, void **state);
|
||||
void *dm_list_next_data(dm_list *list, void **state);
|
||||
/* For example
|
||||
* dm_list *list;
|
||||
* void *state;
|
||||
* my_data *data;
|
||||
* DM_LIST_FOREACH_DATA(data, list, state) {
|
||||
* do_something_with_my(data);
|
||||
* }
|
||||
*/
|
||||
#define DM_LIST_FOREACH_DATA(i, list, state) \
|
||||
for (i = dm_list_first_data(list, &(state)); state; i = dm_list_next_data(list, &(state)))
|
||||
/* Access i->data */
|
||||
#define DM_LIST_FOREACH(i, list) \
|
||||
for (i = list->head; i; i = i->next)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef foodroidcommonutilsfoo
|
||||
#define foodroidcommonutilsfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
|
||||
void dm_replace_in_place(char **string, const char *a, const char *b);
|
||||
bool dm_strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef foodroidversionfoo
|
||||
#define foodroidversionfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018-2022 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>
|
||||
#if defined(QCOM_BSP) || defined(DROID_DEVICE_SBJ)
|
||||
#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.1 */
|
||||
#define DROID_API_VERSION_SUPPORT HARDWARE_DEVICE_API_VERSION(3, 1)
|
||||
|
||||
#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 AUDIO_API_VERSION_MAJ < 3
|
||||
#error This module only supports audio API version 3 and upwards.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=${prefix}
|
||||
libdir=@libdir@
|
||||
includedir=${prefix}/include
|
||||
libexecdir=@libexecdir@
|
||||
|
||||
Name: libdroid-util
|
||||
Description: Common droid module building interface.
|
||||
Version: @PA_MODULE_VERSION@
|
||||
Libs: -L${prefix}/lib/pulse-@PA_MAJORMINOR@/modules -ldroid-util
|
||||
Cflags: -D_REENTRANT -I${includedir}/pulsecore/modules
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 <pulse/xmalloc.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "droid/sllist.h"
|
||||
|
||||
dm_list *dm_list_new(void) {
|
||||
return pa_xnew0(dm_list, 1);
|
||||
}
|
||||
|
||||
void dm_list_free(dm_list *list, pa_free_cb_t free_cb) {
|
||||
pa_assert(list);
|
||||
|
||||
while (list->head) {
|
||||
void *data = dm_list_steal_first(list);
|
||||
|
||||
if (free_cb)
|
||||
free_cb(data);
|
||||
}
|
||||
|
||||
pa_xfree(list);
|
||||
}
|
||||
|
||||
bool dm_list_remove(dm_list *list, dm_list_entry *entry) {
|
||||
dm_list_entry *i;
|
||||
bool removed = false;
|
||||
|
||||
for (i = list->head; i; i = i->next) {
|
||||
if (i == entry) {
|
||||
removed = true;
|
||||
if (list->head == entry)
|
||||
list->head = entry->next;
|
||||
if (list->tail == entry)
|
||||
list->tail = entry->prev;
|
||||
if (entry->next)
|
||||
entry->next->prev = entry->prev;
|
||||
if (entry->prev)
|
||||
entry->prev->next = entry->next;
|
||||
pa_xfree(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
void dm_list_prepend(dm_list *list, void *data) {
|
||||
dm_list_entry *entry;
|
||||
|
||||
pa_assert(list);
|
||||
|
||||
entry = pa_xnew0(dm_list_entry, 1);
|
||||
entry->data = data;
|
||||
|
||||
if (!list->tail)
|
||||
list->tail = entry;
|
||||
|
||||
if (list->head) {
|
||||
entry->next = list->head;
|
||||
list->head->prev = entry;
|
||||
}
|
||||
|
||||
list->head = entry;
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void dm_list_push_back(dm_list *list, void *data) {
|
||||
dm_list_entry *entry;
|
||||
|
||||
pa_assert(list);
|
||||
|
||||
entry = pa_xnew0(dm_list_entry, 1);
|
||||
entry->data = data;
|
||||
|
||||
if (!list->head)
|
||||
list->head = entry;
|
||||
|
||||
if (list->tail) {
|
||||
list->tail->next = entry;
|
||||
entry->prev = list->tail;
|
||||
}
|
||||
|
||||
list->tail = entry;
|
||||
list->size++;
|
||||
}
|
||||
|
||||
dm_list_entry *dm_list_last(dm_list *list) {
|
||||
pa_assert(list);
|
||||
|
||||
return list->tail;
|
||||
}
|
||||
|
||||
void *dm_list_steal_first(dm_list *list) {
|
||||
dm_list_entry *entry;
|
||||
void *data = NULL;
|
||||
|
||||
pa_assert(list);
|
||||
|
||||
if (list->head) {
|
||||
data = list->head->data;
|
||||
entry = list->head;
|
||||
if (list->head == list->tail) {
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
} else {
|
||||
list->head->next->prev = NULL;
|
||||
list->head = list->head->next;
|
||||
}
|
||||
pa_xfree(entry);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
ssize_t dm_list_size(dm_list *list) {
|
||||
pa_assert(list);
|
||||
|
||||
return list->size;
|
||||
}
|
||||
|
||||
/* For iteration */
|
||||
|
||||
void *dm_list_first_data(dm_list *list, void **state) {
|
||||
pa_assert(list);
|
||||
pa_assert(state);
|
||||
|
||||
*state = list->head;
|
||||
|
||||
if (list->head)
|
||||
return list->head->data;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *dm_list_next_data(dm_list *list, void **state) {
|
||||
dm_list_entry *entry;
|
||||
|
||||
pa_assert(list);
|
||||
pa_assert(state);
|
||||
|
||||
entry = *state;
|
||||
*state = entry->next;
|
||||
|
||||
if (entry->next)
|
||||
return entry->next->data;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 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 <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include "droid/utils.h"
|
||||
|
||||
void dm_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;
|
||||
}
|
||||
|
||||
/* Simple strcasestr replacement. */
|
||||
bool dm_strcasestr(const char *haystack, const char *needle) {
|
||||
size_t len_haystack, len_needle;
|
||||
|
||||
len_haystack = strlen(haystack);
|
||||
len_needle = strlen(needle);
|
||||
|
||||
if (len_needle > len_haystack)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < len_haystack; i++) {
|
||||
if (len_needle > len_haystack - i)
|
||||
return false;
|
||||
|
||||
if (strncasecmp(haystack + i, needle, len_needle) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,45 +1,55 @@
|
|||
AM_LIBADD = \
|
||||
$(PULSEAUDIO_LIBS) \
|
||||
$(HYBRIS_LIBS)
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(DROID_DEVICE_CFLAGS) \
|
||||
$(PULSEAUDIO_CFLAGS) \
|
||||
$(DROIDHEADERS_CFLAGS) \
|
||||
$(HYBRIS_CFLAGS) \
|
||||
-DPULSEAUDIO_VERSION=@PA_MAJOR@ \
|
||||
-I$(top_srcdir)/src/droid \
|
||||
-I$(top_srcdir)/src/common/include
|
||||
-I$(top_srcdir)/src/droid
|
||||
|
||||
|
||||
modlibexec_LTLIBRARIES = \
|
||||
libdroid-util.la \
|
||||
libdroid-sink.la \
|
||||
libdroid-source.la \
|
||||
module-droid-keepalive.la \
|
||||
module-droid-sink.la \
|
||||
module-droid-source.la \
|
||||
module-droid-card.la
|
||||
|
||||
noinst_HEADERS = module-droid-sink-symdef.h module-droid-source-symdef.h module-droid-card-symdef.h module-droid-keepalive-symdef.h
|
||||
|
||||
module_droid_keepalive_la_SOURCES = keepalive.c keepalive.h module-droid-keepalive.c
|
||||
module_droid_keepalive_la_LDFLAGS = -module -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack
|
||||
module_droid_keepalive_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS)
|
||||
module_droid_keepalive_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
|
||||
|
||||
libdroid_util_la_SOURCES = droid-util.c droid-util.h
|
||||
libdroid_util_la_LDFLAGS = -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
libdroid_util_la_LIBADD = $(AM_LIBADD)
|
||||
libdroid_util_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
libdroid_sink_la_SOURCES = droid-sink.c droid-sink.h
|
||||
libdroid_sink_la_LDFLAGS = -avoid-version -Wl,-z,noexecstack -lhybris-common
|
||||
libdroid_sink_la_LIBADD = $(top_builddir)/src/common/libdroid-util.la $(AM_LIBADD)
|
||||
libdroid_sink_la_LDFLAGS = -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
libdroid_sink_la_LIBADD = $(AM_LIBADD) libdroid-util.la
|
||||
libdroid_sink_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
libdroid_source_la_SOURCES = droid-source.c droid-source.h
|
||||
libdroid_source_la_LDFLAGS = -avoid-version -Wl,-z,noexecstack -lhybris-common
|
||||
libdroid_source_la_LIBADD = $(top_builddir)/src/common/libdroid-util.la $(AM_LIBADD)
|
||||
libdroid_source_la_LDFLAGS = -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
libdroid_source_la_LIBADD = $(AM_LIBADD) libdroid-util.la
|
||||
libdroid_source_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
module_droid_sink_la_SOURCES = module-droid-sink.c
|
||||
module_droid_sink_la_LDFLAGS = -module -avoid-version -Wl,-z,noexecstack -lhybris-common
|
||||
module_droid_sink_la_LIBADD = -lm libdroid-sink.la $(AM_LIBADD)
|
||||
module_droid_sink_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_droid_sink
|
||||
module_droid_sink_la_LDFLAGS = -module -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
module_droid_sink_la_LIBADD = $(AM_LIBADD) -lm libdroid-util.la libdroid-sink.la
|
||||
module_droid_sink_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
module_droid_source_la_SOURCES = module-droid-source.c
|
||||
module_droid_source_la_LDFLAGS = -module -avoid-version -Wl,-z,noexecstack -lhybris-common
|
||||
module_droid_source_la_LIBADD = -lm libdroid-source.la $(AM_LIBADD)
|
||||
module_droid_source_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_droid_source
|
||||
module_droid_source_la_LDFLAGS = -module -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
module_droid_source_la_LIBADD = $(AM_LIBADD) -lm libdroid-util.la libdroid-source.la
|
||||
module_droid_source_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
module_droid_card_la_SOURCES = module-droid-card.c droid-extcon.c droid-extevdev.c
|
||||
module_droid_card_la_LDFLAGS = -module -avoid-version -Wl,-z,noexecstack -lhybris-common -ludev
|
||||
module_droid_card_la_LIBADD = -lm libdroid-sink.la libdroid-source.la $(top_builddir)/src/common/libdroid-util.la $(AM_LIBADD) $(EVDEV_LIBS)
|
||||
module_droid_card_la_CFLAGS = $(AM_CFLAGS) $(EVDEV_CFLAGS) -DPA_MODULE_NAME=module_droid_card
|
||||
module_droid_card_la_SOURCES = module-droid-card.c
|
||||
module_droid_card_la_LDFLAGS = -module -avoid-version -Wl,-no-undefined -Wl,-z,noexecstack -lhybris-common
|
||||
module_droid_card_la_LIBADD = $(AM_LIBADD) -lm libdroid-util.la libdroid-sink.la libdroid-source.la
|
||||
module_droid_card_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
|
|
|||
|
|
@ -1,269 +0,0 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright (C) 2013 Canonical Ltd.
|
||||
Contact: David Henningsson
|
||||
Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/device-port.h>
|
||||
#include <pulsecore/i18n.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include "droid-extcon.h"
|
||||
|
||||
/* For android */
|
||||
#define EXTCON_NAME "switch"
|
||||
|
||||
/* TODO: Backport stuff to 4.0, remove before upstreaming */
|
||||
#ifndef PA_PORT_AVAILABLE_YES
|
||||
#define PA_PORT_AVAILABLE_YES PA_AVAILABLE_YES
|
||||
#define PA_PORT_AVAILABLE_NO PA_AVAILABLE_NO
|
||||
#define PA_PORT_AVAILABLE_UNKNOWN PA_AVAILABLE_UNKNOWN
|
||||
#define pa_port_available_t pa_available_t
|
||||
#endif
|
||||
|
||||
static pa_port_available_t hponly_avail(int state)
|
||||
{
|
||||
return (state & 2) ? PA_PORT_AVAILABLE_YES : PA_PORT_AVAILABLE_NO;
|
||||
}
|
||||
|
||||
static pa_port_available_t hsmic_avail(int state)
|
||||
{
|
||||
return (state & 1) ? PA_PORT_AVAILABLE_YES : PA_PORT_AVAILABLE_NO;
|
||||
}
|
||||
|
||||
struct droid_switch {
|
||||
char *name;
|
||||
uint32_t current_value;
|
||||
};
|
||||
|
||||
static void droid_switch_free(struct droid_switch *as) {
|
||||
if (!as)
|
||||
return;
|
||||
pa_xfree(as->name);
|
||||
pa_xfree(as);
|
||||
}
|
||||
|
||||
static struct droid_switch *droid_switch_new(const char *name) {
|
||||
|
||||
struct droid_switch *as = NULL;
|
||||
char *filename = pa_sprintf_malloc("/sys/class/%s/%s/state", EXTCON_NAME, name);
|
||||
char *state = pa_read_line_from_file(filename);
|
||||
|
||||
if (state == NULL) {
|
||||
pa_log_debug("Cannot open '%s'. Skipping.", filename);
|
||||
pa_xfree(filename);
|
||||
return NULL;
|
||||
}
|
||||
pa_xfree(filename);
|
||||
|
||||
as = pa_xnew0(struct droid_switch, 1);
|
||||
as->name = pa_xstrdup(name);
|
||||
|
||||
if (pa_atou(state, &as->current_value) < 0) {
|
||||
pa_log_warn("Switch '%s' has invalid value '%s'", name, state);
|
||||
pa_xfree(state);
|
||||
droid_switch_free(as);
|
||||
return NULL;
|
||||
}
|
||||
pa_log_debug("Switch '%s' opened with value '%s'", name, state);
|
||||
|
||||
return as;
|
||||
}
|
||||
|
||||
struct udev_data {
|
||||
struct udev *udev;
|
||||
struct udev_monitor *monitor;
|
||||
pa_io_event *event;
|
||||
};
|
||||
|
||||
struct pa_droid_extcon {
|
||||
pa_card *card;
|
||||
struct droid_switch *h2w;
|
||||
struct udev_data udev;
|
||||
};
|
||||
|
||||
static struct droid_switch *find_matching_switch(pa_droid_extcon *u,
|
||||
const char *devpath) {
|
||||
|
||||
if (pa_streq(devpath, "/devices/virtual/" EXTCON_NAME "/h2w"))
|
||||
return u->h2w; /* To be extended if we ever support more switches */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void notify_ports(pa_droid_extcon *u, struct droid_switch *as) {
|
||||
|
||||
pa_device_port *p;
|
||||
void *state;
|
||||
|
||||
pa_assert(as == u->h2w); /* To be extended if we ever support more switches */
|
||||
|
||||
pa_log_debug("Value of switch %s is now %d.", as->name, as->current_value);
|
||||
|
||||
PA_HASHMAP_FOREACH(p, u->card->ports, state) {
|
||||
if (p->direction == PA_DIRECTION_OUTPUT) {
|
||||
if (!strcmp(p->name, "output-wired_headset"))
|
||||
pa_device_port_set_available(p, hsmic_avail(as->current_value));
|
||||
if (!strcmp(p->name, "output-wired_headphone"))
|
||||
pa_device_port_set_available(p, hponly_avail(as->current_value));
|
||||
}
|
||||
if (p->direction == PA_DIRECTION_INPUT) {
|
||||
if (!strcmp(p->name, "input-wired_headset"))
|
||||
pa_device_port_set_available(p, hsmic_avail(as->current_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void udev_cb(pa_mainloop_api *a, pa_io_event *e, int fd,
|
||||
pa_io_event_flags_t events, void *userdata) {
|
||||
|
||||
pa_droid_extcon *u = userdata;
|
||||
struct udev_device *d = udev_monitor_receive_device(u->udev.monitor);
|
||||
struct udev_list_entry *entry;
|
||||
struct droid_switch *as;
|
||||
const char *devpath, *state;
|
||||
|
||||
if (!d) {
|
||||
pa_log("udev_monitor_receive_device failed.");
|
||||
pa_assert(a);
|
||||
a->io_free(u->udev.event);
|
||||
u->udev.event = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
devpath = udev_device_get_devpath(d);
|
||||
if (!devpath) {
|
||||
pa_log("udev_device_get_devpath failed.");
|
||||
goto out;
|
||||
}
|
||||
pa_log_debug("Got uevent with devpath=%s", devpath);
|
||||
|
||||
as = find_matching_switch(u, devpath);
|
||||
if (!as)
|
||||
goto out;
|
||||
|
||||
entry = udev_list_entry_get_by_name(
|
||||
udev_device_get_properties_list_entry(d), "SWITCH_STATE");
|
||||
if (!entry) {
|
||||
pa_log("udev_list_entry_get_by_name failed to find 'SWITCH_STATE' entry.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
state = udev_list_entry_get_value(entry);
|
||||
if (!state) {
|
||||
pa_log("udev_list_entry_get_by_name failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pa_atou(state, &as->current_value) < 0) {
|
||||
pa_log_warn("Switch '%s' has invalid value '%s'", as->name, state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
notify_ports(u, as);
|
||||
|
||||
out:
|
||||
udev_device_unref(d);
|
||||
}
|
||||
|
||||
static bool init_udev(pa_droid_extcon *u, pa_core *core) {
|
||||
|
||||
int fd;
|
||||
|
||||
u->udev.udev = udev_new();
|
||||
if (!u->udev.udev) {
|
||||
pa_log("udev_new failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
u->udev.monitor = udev_monitor_new_from_netlink(u->udev.udev, "udev");
|
||||
if (!u->udev.monitor) {
|
||||
pa_log("udev_monitor_new_from_netlink failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udev_monitor_filter_add_match_subsystem_devtype(u->udev.monitor, EXTCON_NAME, NULL) < 0) {
|
||||
pa_log("udev_monitor_filter_add_match_subsystem_devtype failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (udev_monitor_enable_receiving(u->udev.monitor) < 0) {
|
||||
pa_log("udev_monitor_enable_receiving failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
fd = udev_monitor_get_fd(u->udev.monitor);
|
||||
if (fd < 0) {
|
||||
pa_log("udev_monitor_get_fd failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
pa_assert_se(u->udev.event = core->mainloop->io_new(core->mainloop, fd,
|
||||
PA_IO_EVENT_INPUT, udev_cb, u));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pa_droid_extcon *pa_droid_extcon_new(pa_core *core, pa_card *card) {
|
||||
|
||||
pa_droid_extcon *u = pa_xnew0(pa_droid_extcon, 1);
|
||||
|
||||
pa_assert(core);
|
||||
pa_assert(card);
|
||||
|
||||
u->card = card;
|
||||
u->h2w = droid_switch_new("h2w");
|
||||
if (!u->h2w)
|
||||
goto fail;
|
||||
|
||||
if (!init_udev(u, core))
|
||||
goto fail;
|
||||
|
||||
notify_ports(u, u->h2w);
|
||||
|
||||
return u;
|
||||
|
||||
fail:
|
||||
pa_droid_extcon_free(u);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pa_droid_extcon_free(pa_droid_extcon *u) {
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
if (u->udev.event)
|
||||
u->card->core->mainloop->io_free(u->udev.event);
|
||||
|
||||
if (u->udev.monitor)
|
||||
udev_monitor_unref(u->udev.monitor);
|
||||
|
||||
if (u->udev.udev)
|
||||
udev_unref(u->udev.udev);
|
||||
|
||||
if (u->h2w)
|
||||
droid_switch_free(u->h2w);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef foodroidextconhfoo
|
||||
#define foodroidextconhfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright (C) 2013 Canonical Ltd.
|
||||
Contact: David Henningsson
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
typedef struct pa_droid_extcon pa_droid_extcon;
|
||||
|
||||
pa_droid_extcon *pa_droid_extcon_new(pa_core *, pa_card *);
|
||||
|
||||
void pa_droid_extcon_free(pa_droid_extcon *);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright (C) 2019 UBports foundation.
|
||||
Author(s): Ratchanan Srirattanamet <ratchanan@ubports.com>
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#define _GNU_SOURCE // For scandir and versionsort
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libevdev/libevdev.h>
|
||||
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/device-port.h>
|
||||
|
||||
#include "droid-extevdev.h"
|
||||
|
||||
#define DEV_INPUT_EVENT "/dev/input"
|
||||
#define EVENT_DEV_NAME "event"
|
||||
|
||||
#define N_ELEMENTS(X) (sizeof(X)/sizeof(*(X)))
|
||||
|
||||
struct pa_droid_extevdev {
|
||||
pa_card *card;
|
||||
struct libevdev *evdev_dev;
|
||||
pa_io_event *event;
|
||||
|
||||
/* Switch values */
|
||||
bool sw_headphone_insert : 1;
|
||||
bool sw_microphone_insert : 1;
|
||||
bool sw_lineout_insert : 1;
|
||||
};
|
||||
|
||||
static int is_event_device(const struct dirent *dir) {
|
||||
return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
|
||||
}
|
||||
|
||||
static struct libevdev *find_switch_evdev(void) {
|
||||
struct dirent **namelist;
|
||||
int ndev, i;
|
||||
struct libevdev *ret = NULL;
|
||||
|
||||
ndev = scandir(DEV_INPUT_EVENT, &namelist, is_event_device, versionsort);
|
||||
|
||||
for (i=0; i<ndev; i++) {
|
||||
char fname[PATH_MAX];
|
||||
int fd;
|
||||
struct libevdev *dev;
|
||||
int err;
|
||||
|
||||
snprintf(fname, sizeof(fname),
|
||||
"%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
|
||||
|
||||
pa_log_debug("Checking %s for headphone switch.", fname);
|
||||
|
||||
fd = open(fname, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
err = errno;
|
||||
pa_log_warn("Unable to open device %s, ignored: %s",
|
||||
fname, strerror(err));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((err = libevdev_new_from_fd(fd, &dev)) < 0) {
|
||||
err = -err;
|
||||
pa_log_warn("Unable to create libevdev device for %s, ignored: %s",
|
||||
fname, strerror(err));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(dev, EV_SW, SW_HEADPHONE_INSERT)) {
|
||||
ret = dev;
|
||||
break;
|
||||
}
|
||||
|
||||
libevdev_free(dev);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
for (i=0; i<ndev; i++)
|
||||
free(namelist[i]);
|
||||
free(namelist);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Put the port we want to be active (for each direction) later in the list.
|
||||
* module-switch-on-port-available will switch to the available port as it
|
||||
* become available, so the last port available will stay active. */
|
||||
|
||||
static const char *headphone_ports[] = {
|
||||
"output-speaker+wired_headphone",
|
||||
"output-wired_headphone",
|
||||
};
|
||||
|
||||
static const char *headset_ports[] = {
|
||||
"output-wired_headset",
|
||||
"input-wired_headset",
|
||||
};
|
||||
|
||||
static void notify_ports(pa_droid_extevdev *u) {
|
||||
unsigned int i;
|
||||
|
||||
pa_log_debug("headphone: %d, microphone: %d, lineout: %d, yes: %d, no: %d", u->sw_headphone_insert,
|
||||
u->sw_microphone_insert, u->sw_lineout_insert, PA_AVAILABLE_YES, PA_AVAILABLE_NO);
|
||||
|
||||
pa_available_t has_headphone =
|
||||
((u->sw_headphone_insert || u->sw_lineout_insert)
|
||||
&& !u->sw_microphone_insert) ? PA_AVAILABLE_YES : PA_AVAILABLE_NO;
|
||||
|
||||
pa_log_debug("has_headphone: %d", has_headphone);
|
||||
|
||||
for (i=0; i < N_ELEMENTS(headphone_ports); i++) {
|
||||
pa_device_port *p = pa_hashmap_get(u->card->ports, headphone_ports[i]);
|
||||
pa_log_debug("headphone device port %d, %p", i, p);
|
||||
if (p)
|
||||
pa_device_port_set_available(p, has_headphone);
|
||||
}
|
||||
|
||||
pa_available_t has_headset =
|
||||
((u->sw_headphone_insert || u->sw_lineout_insert)
|
||||
&& u->sw_microphone_insert) ? PA_AVAILABLE_YES : PA_AVAILABLE_NO;
|
||||
|
||||
pa_log_debug("has_headset: %d", has_headset);
|
||||
|
||||
for (i=0; i < N_ELEMENTS(headset_ports); i++) {
|
||||
pa_device_port *p = pa_hashmap_get(u->card->ports, headset_ports[i]);
|
||||
if (p)
|
||||
pa_device_port_set_available(p, has_headset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from IO context */
|
||||
static void evdev_cb(pa_mainloop_api *a, pa_io_event *e, int fd,
|
||||
pa_io_event_flags_t events, void *userdata) {
|
||||
pa_droid_extevdev *u = userdata;
|
||||
|
||||
unsigned int flags = LIBEVDEV_READ_FLAG_NORMAL;
|
||||
int err;
|
||||
struct input_event ev;
|
||||
|
||||
pa_log_debug("EV callback start...");
|
||||
|
||||
while (1) {
|
||||
err = libevdev_next_event(u->evdev_dev, flags, &ev);
|
||||
|
||||
if (err == -EAGAIN) {
|
||||
if (flags == LIBEVDEV_READ_FLAG_SYNC) {
|
||||
/* Switch the flag back to read next normal events. */
|
||||
flags = LIBEVDEV_READ_FLAG_NORMAL;
|
||||
continue;
|
||||
} else {
|
||||
/* We run out of event. */
|
||||
break;
|
||||
}
|
||||
} else if (err == LIBEVDEV_READ_STATUS_SYNC) {
|
||||
if (flags == LIBEVDEV_READ_FLAG_NORMAL) {
|
||||
/* Handle dropped events by switching to SYNC mode. */
|
||||
flags = LIBEVDEV_READ_FLAG_SYNC;
|
||||
continue;
|
||||
} /* Otherwise we're in the middle of handling it. */
|
||||
} else if (err < 0) {
|
||||
pa_log_error("Error in reading the event from evdev: %s",
|
||||
strerror(-err));
|
||||
/* TODO: Should we just remove the event source? */
|
||||
break;
|
||||
}
|
||||
|
||||
/* ev now contains the current event. */
|
||||
if (ev.type == EV_SW) {
|
||||
switch (ev.code) {
|
||||
case SW_HEADPHONE_INSERT:
|
||||
pa_log_debug("Headphone Insert %d", ev.value);
|
||||
u->sw_headphone_insert = ev.value;
|
||||
break;
|
||||
case SW_MICROPHONE_INSERT:
|
||||
pa_log_debug("Microphone Insert %d", ev.value);
|
||||
u->sw_microphone_insert = ev.value;
|
||||
break;
|
||||
case SW_LINEOUT_INSERT:
|
||||
pa_log_debug("Lineout Insert %d", ev.value);
|
||||
u->sw_lineout_insert = ev.value;
|
||||
break;
|
||||
default:
|
||||
pa_log_debug("Unknown switch %d", ev.code);
|
||||
|
||||
/* Ignore unknown switch. */
|
||||
break;
|
||||
}
|
||||
} else if (ev.type == EV_SYN && ev.code == SYN_REPORT) {
|
||||
pa_log_debug("SYN Report");
|
||||
notify_ports(u);
|
||||
}
|
||||
}
|
||||
|
||||
pa_log_debug("EV callback end.");
|
||||
|
||||
}
|
||||
|
||||
static void read_initial_switch_values(pa_droid_extevdev *u) {
|
||||
/* A local variable is needed because sw_* are bitfields. */
|
||||
int value;
|
||||
|
||||
#define INIT_SW(code, sw_var) \
|
||||
if (libevdev_fetch_event_value(u->evdev_dev, EV_SW, code, &value)) \
|
||||
u->sw_var = value; \
|
||||
else \
|
||||
u->sw_var = false;
|
||||
|
||||
INIT_SW(SW_HEADPHONE_INSERT, sw_headphone_insert)
|
||||
INIT_SW(SW_MICROPHONE_INSERT, sw_microphone_insert)
|
||||
INIT_SW(SW_LINEOUT_INSERT, sw_lineout_insert)
|
||||
|
||||
#undef INIT_SW
|
||||
|
||||
notify_ports(u);
|
||||
}
|
||||
|
||||
pa_droid_extevdev *pa_droid_extevdev_new(pa_core *core, pa_card *card) {
|
||||
pa_droid_extevdev *u = pa_xnew0(pa_droid_extevdev, 1);
|
||||
|
||||
pa_assert(core);
|
||||
pa_assert(card);
|
||||
|
||||
u->card = card;
|
||||
u->evdev_dev = find_switch_evdev();
|
||||
|
||||
if (!u->evdev_dev)
|
||||
goto fail;
|
||||
|
||||
pa_assert_se(u->event = core->mainloop->io_new(core->mainloop,
|
||||
libevdev_get_fd(u->evdev_dev), PA_IO_EVENT_INPUT, evdev_cb, u));
|
||||
|
||||
read_initial_switch_values(u);
|
||||
|
||||
return u;
|
||||
|
||||
fail:
|
||||
pa_droid_extevdev_free(u);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pa_droid_extevdev_free(pa_droid_extevdev *u) {
|
||||
if (u->event)
|
||||
u->card->core->mainloop->io_free(u->event);
|
||||
|
||||
if (u->evdev_dev) {
|
||||
int fd = libevdev_get_fd(u->evdev_dev);
|
||||
libevdev_free(u->evdev_dev);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef foodroidextevdevhfoo
|
||||
#define foodroidextevdevhfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright (C) 2019 UBports foundation.
|
||||
Author(s): Ratchanan Srirattanamet <ratchanan@ubports.com>
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
typedef struct pa_droid_extevdev pa_droid_extevdev;
|
||||
|
||||
pa_droid_extevdev *pa_droid_extevdev_new(pa_core *, pa_card *);
|
||||
|
||||
void pa_droid_extevdev_free(pa_droid_extevdev *);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,9 +2,9 @@
|
|||
#define foodroidsinkfoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2018 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/card.h>
|
||||
|
||||
#include <droid/droid-util.h>
|
||||
#include "droid-util.h"
|
||||
|
||||
pa_sink *pa_droid_sink_new(pa_module *m,
|
||||
pa_modargs *ma,
|
||||
|
|
@ -52,6 +52,6 @@ pa_sink *pa_droid_sink_new(pa_module *m,
|
|||
pa_card *card);
|
||||
void pa_droid_sink_free(pa_sink *s);
|
||||
|
||||
void pa_droid_sink_set_voice_control(pa_sink* sink, bool enable);
|
||||
void pa_droid_sink_set_voice_control(pa_sink* sink, pa_bool_t enable);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2022 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -50,13 +50,9 @@
|
|||
#include <pulsecore/thread-mq.h>
|
||||
#include <pulsecore/rtpoll.h>
|
||||
#include <pulsecore/time-smoother.h>
|
||||
#include <pulsecore/resampler.h>
|
||||
#include <pulse/util.h>
|
||||
#include <pulse/version.h>
|
||||
|
||||
#include "droid-source.h"
|
||||
#include <droid/droid-util.h>
|
||||
#include <droid/conversion.h>
|
||||
#include "droid-util.h"
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
|
|
@ -69,85 +65,103 @@ struct userdata {
|
|||
pa_rtpoll *rtpoll;
|
||||
|
||||
pa_memchunk memchunk;
|
||||
audio_devices_t primary_devices;
|
||||
audio_devices_t enabled_devices;
|
||||
pa_bool_t routing_changes_enabled;
|
||||
|
||||
size_t source_buffer_size;
|
||||
size_t buffer_size;
|
||||
pa_usec_t timestamp;
|
||||
|
||||
pa_resampler *resampler;
|
||||
|
||||
pa_droid_card_data *card_data;
|
||||
pa_droid_hw_module *hw_module;
|
||||
pa_droid_stream *stream;
|
||||
bool stream_valid;
|
||||
audio_stream_in_t *stream;
|
||||
};
|
||||
|
||||
#define DEFAULT_MODULE_ID "primary"
|
||||
|
||||
#define DROID_AUDIO_SOURCE "droid.audio_source"
|
||||
#define DROID_AUDIO_SOURCE_UNDEFINED "undefined"
|
||||
|
||||
static void userdata_free(struct userdata *u);
|
||||
static int suspend(struct userdata *u);
|
||||
static void unsuspend(struct userdata *u);
|
||||
static void source_reconfigure(struct userdata *u,
|
||||
const pa_sample_spec *reconfigure_sample_spec,
|
||||
const pa_channel_map *reconfigure_channel_map,
|
||||
const pa_proplist *proplist,
|
||||
dm_config_port *update_device_port);
|
||||
|
||||
/* Our droid source may be left in a state of not having an input stream
|
||||
* if reconfiguration fails and fallback to previously active values fails
|
||||
* as well. In this case just avoid using the stream but don't die. */
|
||||
#define assert_stream(x, action) if (!x) do { pa_log_warn("Assert " #x " failed."); action; } while(0)
|
||||
static pa_bool_t do_routing(struct userdata *u, audio_devices_t devices) {
|
||||
char tmp[32];
|
||||
char *devlist;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->stream);
|
||||
|
||||
if (!u->routing_changes_enabled) {
|
||||
pa_log_debug("Skipping routing change.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (u->primary_devices == devices)
|
||||
pa_log_debug("Refresh active device routing.");
|
||||
|
||||
u->enabled_devices &= ~u->primary_devices;
|
||||
u->primary_devices = devices;
|
||||
u->enabled_devices |= u->primary_devices;
|
||||
|
||||
devlist = pa_list_string_input_device(devices);
|
||||
pa_assert(devlist);
|
||||
pa_snprintf(tmp, sizeof(tmp), "routing=%u", devices);
|
||||
pa_log_debug("set_parameters(): %s (%s)", tmp, devlist);
|
||||
pa_xfree(devlist);
|
||||
#ifdef DROID_DEVICE_MAKO
|
||||
#warning Using mako set_parameters hack.
|
||||
u->card_data->set_parameters(u->card_data, tmp);
|
||||
#else
|
||||
u->stream->common.set_parameters(&u->stream->common, tmp);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pa_bool_t parse_device_list(const char *str, audio_devices_t *dst) {
|
||||
pa_assert(str);
|
||||
pa_assert(dst);
|
||||
|
||||
char *dev;
|
||||
const char *state = NULL;
|
||||
|
||||
*dst = 0;
|
||||
|
||||
while ((dev = pa_split(str, "|", &state))) {
|
||||
audio_devices_t d;
|
||||
|
||||
if (!pa_string_convert_input_device_str_to_num(dev, &d)) {
|
||||
pa_log_warn("Unknown device %s", dev);
|
||||
pa_xfree(dev);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*dst |= d;
|
||||
|
||||
pa_xfree(dev);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int thread_read(struct userdata *u) {
|
||||
void *p;
|
||||
ssize_t readd;
|
||||
pa_memchunk chunk;
|
||||
|
||||
chunk.index = 0;
|
||||
chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) u->buffer_size);
|
||||
|
||||
if (!u->stream_valid) {
|
||||
/* try to resume or post silence */
|
||||
unsuspend(u);
|
||||
if (!u->stream_valid) {
|
||||
p = pa_memblock_acquire(chunk.memblock);
|
||||
chunk.length = pa_memblock_get_length(chunk.memblock);
|
||||
pa_silence_memory(p, chunk.length, &u->source->sample_spec);
|
||||
pa_source_post(u->source, &chunk);
|
||||
pa_memblock_release(chunk.memblock);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
p = pa_memblock_acquire(chunk.memblock);
|
||||
readd = pa_droid_stream_read(u->stream, p, pa_memblock_get_length(chunk.memblock));
|
||||
readd = u->stream->read(u->stream, (uint8_t*) p, pa_memblock_get_length(chunk.memblock));
|
||||
pa_memblock_release(chunk.memblock);
|
||||
|
||||
if (readd < 0) {
|
||||
pa_log("Failed to read from stream. (err %zd)", readd);
|
||||
pa_log("Failed to read from stream. (err %i)", readd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
u->timestamp += pa_bytes_to_usec(readd, &u->source->sample_spec);
|
||||
|
||||
chunk.index = 0;
|
||||
chunk.length = readd;
|
||||
|
||||
if (u->resampler) {
|
||||
pa_memchunk rchunk;
|
||||
|
||||
pa_resampler_run(u->resampler, &chunk, &rchunk);
|
||||
|
||||
if (rchunk.length > 0)
|
||||
pa_source_post(u->source, &rchunk);
|
||||
if (rchunk.memblock)
|
||||
pa_memblock_unref(rchunk.memblock);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (chunk.length > 0)
|
||||
pa_source_post(u->source, &chunk);
|
||||
|
||||
|
|
@ -161,16 +175,11 @@ static void thread_func(void *userdata) {
|
|||
struct userdata *u = userdata;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->stream);
|
||||
|
||||
pa_log_debug("Thread starting up.");
|
||||
|
||||
if (u->core->realtime_scheduling)
|
||||
#if PA_CHECK_VERSION(13,0,0)
|
||||
pa_thread_make_realtime(u->core->realtime_priority);
|
||||
#else
|
||||
pa_make_realtime(u->core->realtime_priority);
|
||||
#endif
|
||||
|
||||
pa_thread_mq_install(&u->thread_mq);
|
||||
|
||||
|
|
@ -187,7 +196,7 @@ static void thread_func(void *userdata) {
|
|||
pa_rtpoll_set_timer_disabled(u->rtpoll);
|
||||
|
||||
/* Sleep */
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
|
||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (ret == 0)
|
||||
|
|
@ -210,9 +219,9 @@ static int suspend(struct userdata *u) {
|
|||
int ret;
|
||||
|
||||
pa_assert(u);
|
||||
assert_stream(u->stream, return 0);
|
||||
pa_assert(u->stream);
|
||||
|
||||
ret = pa_droid_stream_suspend(u->stream, true);
|
||||
ret = u->stream->common.standby(&u->stream->common);
|
||||
|
||||
if (ret == 0)
|
||||
pa_log_info("Device suspended.");
|
||||
|
|
@ -221,61 +230,42 @@ static int suspend(struct userdata *u) {
|
|||
}
|
||||
|
||||
/* Called from IO context */
|
||||
static void unsuspend(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
struct userdata *u = PA_SOURCE(o)->userdata;
|
||||
|
||||
if (!u->stream) {
|
||||
assert_stream(u->stream, u->stream_valid = false);
|
||||
} else if (pa_droid_stream_suspend(u->stream, false) >= 0) {
|
||||
u->stream_valid = true;
|
||||
pa_log_info("Resuming...");
|
||||
} else
|
||||
u->stream_valid = false;
|
||||
}
|
||||
switch (code) {
|
||||
case PA_SOURCE_MESSAGE_SET_STATE: {
|
||||
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
|
||||
case PA_SOURCE_SUSPENDED: {
|
||||
int r;
|
||||
|
||||
/* Called from IO context */
|
||||
static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
|
||||
struct userdata *u;
|
||||
int r;
|
||||
pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
|
||||
|
||||
pa_assert(s);
|
||||
pa_assert_se(u = s->userdata);
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
|
||||
/* It may be that only the suspend cause is changing, in which case there's
|
||||
* nothing more to do. */
|
||||
if (new_state == s->thread_info.state)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (new_state) {
|
||||
case PA_SOURCE_SUSPENDED:
|
||||
if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
}
|
||||
case PA_SOURCE_IDLE:
|
||||
break;
|
||||
case PA_SOURCE_RUNNING: {
|
||||
pa_log_info("Resuming...");
|
||||
u->timestamp = pa_rtclock_now();
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PA_SOURCE_IDLE:
|
||||
/* Fall through */
|
||||
case PA_SOURCE_RUNNING:
|
||||
if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
|
||||
unsuspend(u);
|
||||
u->timestamp = pa_rtclock_now();
|
||||
/* not needed */
|
||||
case PA_SOURCE_UNLINKED:
|
||||
case PA_SOURCE_INIT:
|
||||
case PA_SOURCE_INVALID_STATE:
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
case PA_SOURCE_UNLINKED:
|
||||
/* Suspending since some implementations do not want to free running stream. */
|
||||
suspend(u);
|
||||
break;
|
||||
|
||||
/* not needed */
|
||||
case PA_SOURCE_INIT:
|
||||
case PA_SOURCE_INVALID_STATE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pa_source_process_msg(o, code, data, offset, chunk);
|
||||
}
|
||||
|
||||
static int source_set_port_cb(pa_source *s, pa_device_port *p) {
|
||||
|
|
@ -287,7 +277,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
|
|||
|
||||
data = PA_DEVICE_PORT_DATA(p);
|
||||
|
||||
if (!data->device_port) {
|
||||
if (!data->device) {
|
||||
/* If there is no device defined, just return 0 to say everything is ok.
|
||||
* Then next port change can be whatever source port, even the one enabled
|
||||
* before parking. */
|
||||
|
|
@ -295,16 +285,14 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
pa_log_debug("Source set port %#010x (%s)", data->device_port->type, data->device_port->name);
|
||||
pa_log_debug("Source set port %u", data->device);
|
||||
|
||||
if (!PA_SOURCE_IS_OPENED(u->source->state))
|
||||
pa_droid_stream_set_route(u->stream, data->device_port);
|
||||
else
|
||||
source_reconfigure(u, NULL, NULL, NULL, data->device_port);
|
||||
do_routing(u, data->device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void source_set_name(pa_modargs *ma, pa_source_new_data *data, const char *module_id) {
|
||||
const char *tmp;
|
||||
|
||||
|
|
@ -313,7 +301,7 @@ static void source_set_name(pa_modargs *ma, pa_source_new_data *data, const char
|
|||
|
||||
if ((tmp = pa_modargs_get_value(ma, "source_name", NULL))) {
|
||||
pa_source_new_data_set_name(data, tmp);
|
||||
data->namereg_fail = true;
|
||||
data->namereg_fail = TRUE;
|
||||
pa_proplist_sets(data->proplist, PA_PROP_DEVICE_DESCRIPTION, "Droid source");
|
||||
} else {
|
||||
char *tt;
|
||||
|
|
@ -321,179 +309,65 @@ static void source_set_name(pa_modargs *ma, pa_source_new_data *data, const char
|
|||
tt = pa_sprintf_malloc("source.%s", module_id);
|
||||
pa_source_new_data_set_name(data, tt);
|
||||
pa_xfree(tt);
|
||||
data->namereg_fail = false;
|
||||
data->namereg_fail = FALSE;
|
||||
pa_proplist_setf(data->proplist, PA_PROP_DEVICE_DESCRIPTION, "Droid source %s", module_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int source_get_mute_cb(pa_source *s, bool *muted) {
|
||||
static void source_get_mute_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
pa_bool_t b;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->hw_module);
|
||||
pa_assert(u->hw_module && u->hw_module->device);
|
||||
|
||||
return pa_droid_hw_mic_get_mute(u->hw_module, muted);
|
||||
pa_droid_hw_module_lock(u->hw_module);
|
||||
if (u->hw_module->device->get_mic_mute(u->hw_module->device, &b) < 0) {
|
||||
pa_log("Failed to get mute state.");
|
||||
pa_droid_hw_module_unlock(u->hw_module);
|
||||
return;
|
||||
}
|
||||
pa_droid_hw_module_unlock(u->hw_module);
|
||||
|
||||
s->muted = b;
|
||||
}
|
||||
|
||||
static void source_set_mute_cb(pa_source *s) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(u->hw_module && u->hw_module->device);
|
||||
|
||||
pa_droid_hw_mic_set_mute(u->hw_module, s->muted);
|
||||
pa_droid_hw_module_lock(u->hw_module);
|
||||
if (u->hw_module->device->set_mic_mute(u->hw_module->device, s->muted) < 0)
|
||||
pa_log("Failed to set mute state to %smuted.", s->muted ? "" : "un");
|
||||
pa_droid_hw_module_unlock(u->hw_module);
|
||||
}
|
||||
|
||||
static void source_set_mute_control(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
pa_assert(u->hw_module && u->hw_module->device);
|
||||
|
||||
if (pa_droid_hw_has_mic_control(u->hw_module)) {
|
||||
if (u->hw_module->device->set_mic_mute) {
|
||||
pa_log_info("Using hardware mute control for %s", u->source->name);
|
||||
pa_source_set_get_mute_callback(u->source, source_get_mute_cb);
|
||||
pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
|
||||
} else {
|
||||
pa_log_info("Using software mute control for %s", u->source->name);
|
||||
pa_source_set_get_mute_callback(u->source, NULL);
|
||||
pa_source_set_set_mute_callback(u->source, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from main and IO context */
|
||||
static void update_latency(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
pa_assert(u->source);
|
||||
void pa_droid_source_set_routing(pa_source *s, pa_bool_t enabled) {
|
||||
struct userdata *u = s->userdata;
|
||||
|
||||
if (u->stream)
|
||||
u->buffer_size = pa_droid_stream_buffer_size(u->stream);
|
||||
else
|
||||
u->buffer_size = 1024; /* Random valid value */
|
||||
pa_assert(s);
|
||||
pa_assert(s->userdata);
|
||||
|
||||
assert_stream(u->stream, return);
|
||||
|
||||
if (u->source_buffer_size) {
|
||||
u->buffer_size = pa_droid_buffer_size_round_up(u->source_buffer_size, u->buffer_size);
|
||||
pa_log_info("Using buffer size %zu (requested %zu).", u->buffer_size, u->source_buffer_size);
|
||||
} else
|
||||
pa_log_info("Using buffer size %zu.", u->buffer_size);
|
||||
|
||||
if (pa_thread_mq_get())
|
||||
pa_source_set_fixed_latency_within_thread(u->source, pa_bytes_to_usec(u->buffer_size, pa_droid_stream_sample_spec(u->stream)));
|
||||
else
|
||||
pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, pa_droid_stream_sample_spec(u->stream)));
|
||||
|
||||
pa_log_debug("Set fixed latency %" PRIu64 " usec", pa_bytes_to_usec(u->buffer_size, pa_droid_stream_sample_spec(u->stream)));
|
||||
}
|
||||
|
||||
static void source_reconfigure(struct userdata *u,
|
||||
const pa_sample_spec *reconfigure_sample_spec,
|
||||
const pa_channel_map *reconfigure_channel_map,
|
||||
const pa_proplist *proplist,
|
||||
dm_config_port *update_device_port) {
|
||||
pa_channel_map old_channel_map;
|
||||
pa_sample_spec old_sample_spec;
|
||||
pa_channel_map new_channel_map;
|
||||
pa_sample_spec new_sample_spec;
|
||||
pa_queue *source_outputs = NULL;
|
||||
|
||||
if (pa_source_used_by(u->source)) {
|
||||
/* If we already have connected source outputs detach those
|
||||
* so that when re-attaching them to our source resampling etc.
|
||||
* is renegotiated correctly. */
|
||||
source_outputs = pa_source_move_all_start(u->source, NULL);
|
||||
}
|
||||
|
||||
pa_source_suspend(u->source, true, PA_SUSPEND_UNAVAILABLE);
|
||||
|
||||
old_channel_map = *pa_droid_stream_channel_map(u->stream);
|
||||
old_sample_spec = *pa_droid_stream_sample_spec(u->stream);
|
||||
new_channel_map = reconfigure_channel_map ? *reconfigure_channel_map : old_channel_map;
|
||||
new_sample_spec = reconfigure_sample_spec ? *reconfigure_sample_spec : old_sample_spec;
|
||||
|
||||
if (update_device_port)
|
||||
pa_droid_stream_set_route(u->stream, update_device_port);
|
||||
|
||||
if (pa_droid_stream_reconfigure_input(u->stream, &new_sample_spec, &new_channel_map, proplist))
|
||||
pa_log_info("Source reconfigured.");
|
||||
else
|
||||
pa_log_info("Failed to reconfigure input stream, no worries, using defaults.");
|
||||
|
||||
/* We need to be really careful here as we are modifying
|
||||
* quite profound internal structures. */
|
||||
new_sample_spec = *pa_droid_stream_sample_spec(u->stream);
|
||||
new_channel_map = *pa_droid_stream_channel_map(u->stream);
|
||||
u->source->channel_map = new_channel_map;
|
||||
u->source->sample_spec = new_sample_spec;
|
||||
pa_assert_se(pa_cvolume_remap(&u->source->reference_volume, &old_channel_map, &new_channel_map));
|
||||
pa_assert_se(pa_cvolume_remap(&u->source->real_volume, &old_channel_map, &new_channel_map));
|
||||
pa_assert_se(pa_cvolume_remap(&u->source->soft_volume, &old_channel_map, &new_channel_map));
|
||||
|
||||
update_latency(u);
|
||||
pa_source_suspend(u->source, false, PA_SUSPEND_UNAVAILABLE);
|
||||
|
||||
if (source_outputs && u->source) {
|
||||
pa_source_move_all_finish(u->source, source_outputs, false);
|
||||
}
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_new_hook_callback(void *hook_data,
|
||||
void *call_data,
|
||||
void *slot_data) {
|
||||
pa_source_output_new_data *new_data = call_data;
|
||||
struct userdata *u = slot_data;
|
||||
pa_droid_stream *primary_output;
|
||||
|
||||
/* Not meant for us */
|
||||
if (new_data->source != u->source)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!pa_droid_stream_reconfigure_input_needed(u->stream,
|
||||
&new_data->sample_spec,
|
||||
&new_data->channel_map,
|
||||
new_data->proplist))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
pa_log_info("New source-output connecting and our source needs to be reconfigured.");
|
||||
|
||||
/* Workaround for fm-radio loopback */
|
||||
if (pa_safe_streq(pa_proplist_gets(new_data->proplist, "media.name"), "fmradio-loopback-source") &&
|
||||
(primary_output = pa_droid_hw_primary_output_stream(u->hw_module))) {
|
||||
pa_log_debug("Workaround for fm-radio loopback.");
|
||||
source_reconfigure(u,
|
||||
pa_droid_stream_sample_spec(primary_output),
|
||||
pa_droid_stream_channel_map(primary_output),
|
||||
new_data->proplist,
|
||||
NULL);
|
||||
|
||||
} else
|
||||
source_reconfigure(u, &new_data->sample_spec, &new_data->channel_map, new_data->proplist, NULL);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
static void source_reconfigure_after_changes(struct userdata *u) {
|
||||
pa_source_output *so = NULL;
|
||||
pa_source_output *so_i;
|
||||
void *state = NULL;
|
||||
|
||||
if (!pa_source_used_by(u->source))
|
||||
return;
|
||||
|
||||
/* Find last inserted source-output */
|
||||
so = pa_idxset_iterate(u->source->outputs, &state, NULL);
|
||||
if (so) {
|
||||
while ((so_i = pa_idxset_iterate(u->source->outputs, &state, NULL)))
|
||||
so = so_i;
|
||||
}
|
||||
|
||||
if (so && pa_droid_stream_reconfigure_input_needed(u->stream,
|
||||
&so->sample_spec,
|
||||
&so->channel_map,
|
||||
so->proplist)) {
|
||||
pa_log_info("Source-output disconnected and our source needs to be reconfigured.");
|
||||
source_reconfigure(u, &so->sample_spec, &so->channel_map, so->proplist, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static pa_hook_result_t source_output_unlink_post_hook_callback(void *hook_data,
|
||||
void *call_data,
|
||||
void *slot_data) {
|
||||
source_reconfigure_after_changes(slot_data);
|
||||
return PA_HOOK_OK;
|
||||
if (u->routing_changes_enabled != enabled)
|
||||
pa_log_debug("%s source routing changes.", enabled ? "Enabling" : "Disabling");
|
||||
u->routing_changes_enabled = enabled;
|
||||
}
|
||||
|
||||
pa_source *pa_droid_source_new(pa_module *m,
|
||||
|
|
@ -507,58 +381,35 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
char *thread_name = NULL;
|
||||
pa_source_new_data data;
|
||||
const char *module_id = NULL;
|
||||
const char *tmp;
|
||||
uint32_t sample_rate;
|
||||
uint32_t alternate_sample_rate;
|
||||
audio_devices_t dev_in;
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
const char *format;
|
||||
bool namereg_fail = false;
|
||||
pa_bool_t namereg_fail = FALSE;
|
||||
pa_droid_config_audio *config = NULL; /* Only used when source is created without card */
|
||||
uint32_t source_buffer = 0;
|
||||
int ret;
|
||||
|
||||
audio_format_t hal_audio_format = 0;
|
||||
audio_channel_mask_t hal_channel_mask = 0;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(ma);
|
||||
pa_assert(driver);
|
||||
|
||||
pa_log_info("Create new droid-source");
|
||||
|
||||
/* When running under card use hw module name for source by default. */
|
||||
if (am)
|
||||
module_id = am->mix_port->name;
|
||||
if (card && ma)
|
||||
module_id = am->input->module->name;
|
||||
else
|
||||
module_id = pa_modargs_get_value(ma, "module_id", DEFAULT_MODULE_ID);
|
||||
|
||||
sample_spec = m->core->default_sample_spec;
|
||||
channel_map = m->core->default_channel_map;
|
||||
|
||||
/* First parse both sample spec and channel map, then see if source_* override some
|
||||
* of the values. */
|
||||
if (pa_modargs_get_sample_spec_and_channel_map(ma, &sample_spec, &channel_map, PA_CHANNEL_MAP_AIFF) < 0) {
|
||||
pa_log("Failed to parse source sample specification and channel map.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value(ma, "source_channel_map", NULL)) {
|
||||
if (pa_modargs_get_channel_map(ma, "source_channel_map", &channel_map) < 0) {
|
||||
pa_log("Failed to parse source channel map.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sample_spec.channels = channel_map.channels;
|
||||
}
|
||||
|
||||
if ((format = pa_modargs_get_value(ma, "source_format", NULL))) {
|
||||
if ((sample_spec.format = pa_parse_sample_format(format)) < 0) {
|
||||
pa_log("Failed to parse source format.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_modargs_get_value_u32(ma, "source_rate", &sample_spec.rate) < 0) {
|
||||
pa_log("Failed to parse source_rate.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!pa_sample_spec_valid(&sample_spec)) {
|
||||
pa_log("Sample spec is not valid.");
|
||||
pa_log("Failed to parse sample specification and channel map.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -574,48 +425,116 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
}
|
||||
|
||||
u = pa_xnew0(struct userdata, 1);
|
||||
u->stream_valid = true;
|
||||
u->core = m->core;
|
||||
u->module = m;
|
||||
u->card = card;
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
|
||||
|
||||
/* Enabled routing changes by default. */
|
||||
u->routing_changes_enabled = TRUE;
|
||||
|
||||
if (card_data) {
|
||||
pa_assert(card);
|
||||
u->card_data = card_data;
|
||||
pa_assert_se((u->hw_module = pa_droid_hw_module_get(u->core, NULL, card_data->module_id)));
|
||||
} else {
|
||||
/* Source wasn't created from inside card module, so we'll need to open
|
||||
* hw module ourself. */
|
||||
/* Stand-alone source */
|
||||
|
||||
if (!(u->hw_module = pa_droid_hw_module_get2(u->core, ma, 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;
|
||||
}
|
||||
|
||||
u->stream = pa_droid_open_input_stream(u->hw_module, &sample_spec, &channel_map, am->mix_port->name);
|
||||
if (!pa_convert_format(sample_spec.format, CONV_FROM_PA, &hal_audio_format)) {
|
||||
pa_log("Sample spec format %u not supported.", sample_spec.format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!u->stream) {
|
||||
for (int i = 0; i < channel_map.channels; i++) {
|
||||
audio_channel_mask_t c;
|
||||
if (!pa_convert_input_channel(channel_map.map[i], CONV_FROM_PA, &c)) {
|
||||
pa_log("Failed to convert channel map.");
|
||||
goto fail;
|
||||
}
|
||||
hal_channel_mask |= c;
|
||||
}
|
||||
|
||||
struct audio_config config_in = {
|
||||
.sample_rate = sample_spec.rate,
|
||||
.channel_mask = hal_channel_mask,
|
||||
.format = hal_audio_format
|
||||
};
|
||||
|
||||
/* Default routing */
|
||||
/* FIXME So while setting routing through stream with HALv2 API fails, creation of stream
|
||||
* requires HALv2 style device to work properly. So until that oddity is resolved we always
|
||||
* set AUDIO_DEVICE_IN_BUILTIN_MIC as initial device here. */
|
||||
#if 0
|
||||
pa_assert_se(pa_string_convert_input_device_str_to_num("AUDIO_DEVICE_IN_BUILTIN_MIC", &dev_in));
|
||||
|
||||
if ((tmp = pa_modargs_get_value(ma, "input_devices", NULL))) {
|
||||
audio_devices_t tmp_dev;
|
||||
|
||||
if (parse_device_list(tmp, &tmp_dev) && tmp_dev)
|
||||
dev_in = tmp_dev;
|
||||
|
||||
pa_log_debug("Set initial devices %s", tmp);
|
||||
}
|
||||
#else
|
||||
pa_log_info("FIXME: Setting AUDIO_DEVICE_IN_BUILTIN_MIC as initial device.");
|
||||
dev_in = AUDIO_DEVICE_IN_BUILTIN_MIC;
|
||||
#endif
|
||||
dev_in = AUDIO_DEVICE_IN_DEFAULT;
|
||||
pa_droid_hw_module_lock(u->hw_module);
|
||||
ret = u->hw_module->device->open_input_stream(u->hw_module->device,
|
||||
u->hw_module->stream_in_id++,
|
||||
dev_in,
|
||||
&config_in,
|
||||
&u->stream);
|
||||
pa_droid_hw_module_unlock(u->hw_module);
|
||||
|
||||
if (ret < 0) {
|
||||
pa_log("Failed to open input stream.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((sample_rate = u->stream->common.get_sample_rate(&u->stream->common)) != sample_spec.rate) {
|
||||
pa_log_warn("Requested sample rate %u but got %u instead.", sample_spec.rate, sample_rate);
|
||||
sample_spec.rate = sample_rate;
|
||||
}
|
||||
|
||||
u->buffer_size = u->stream->common.get_buffer_size(&u->stream->common);
|
||||
if (source_buffer) {
|
||||
if (source_buffer < u->buffer_size)
|
||||
pa_log_warn("Requested buffer size %u less than HAL reported buffer size (%u).", source_buffer, u->buffer_size);
|
||||
else if (source_buffer % u->buffer_size) {
|
||||
uint32_t trunc = (source_buffer / u->buffer_size) * u->buffer_size;
|
||||
pa_log_warn("Requested buffer size %u not multiple of HAL buffer size (%u). Using buffer size %u", source_buffer, u->buffer_size, trunc);
|
||||
u->buffer_size = trunc;
|
||||
} else {
|
||||
pa_log_info("Using requested buffer size %u.", source_buffer);
|
||||
u->buffer_size = source_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
pa_log_info("Created Android stream with device: %u sample rate: %u channel mask: %u format: %u buffer size: %u",
|
||||
dev_in,
|
||||
sample_rate,
|
||||
config_in.channel_mask,
|
||||
config_in.format,
|
||||
u->buffer_size);
|
||||
|
||||
|
||||
pa_source_new_data_init(&data);
|
||||
data.driver = driver;
|
||||
data.module = m;
|
||||
data.card = card;
|
||||
/* Start suspended */
|
||||
data.suspend_cause = PA_SUSPEND_IDLE;
|
||||
|
||||
if (am)
|
||||
source_set_name(ma, &data, am->name);
|
||||
else
|
||||
source_set_name(ma, &data, module_id);
|
||||
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, PROP_DROID_API_STRING);
|
||||
pa_proplist_sets(data.proplist, PROP_DROID_INPUT_EXTERNAL, "true");
|
||||
pa_proplist_sets(data.proplist, PROP_DROID_INPUT_BUILTIN, "true");
|
||||
source_set_name(ma, &data, module_id);
|
||||
|
||||
/* We need to give pa_modargs_get_value_boolean() a pointer to a local
|
||||
* variable instead of using &data.namereg_fail directly, because
|
||||
|
|
@ -629,11 +548,11 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
}
|
||||
data.namereg_fail = namereg_fail;
|
||||
|
||||
pa_source_new_data_set_sample_spec(&data, pa_droid_stream_sample_spec(u->stream));
|
||||
pa_source_new_data_set_channel_map(&data, pa_droid_stream_channel_map(u->stream));
|
||||
pa_source_new_data_set_sample_spec(&data, &sample_spec);
|
||||
pa_source_new_data_set_channel_map(&data, &channel_map);
|
||||
pa_source_new_data_set_alternate_sample_rate(&data, alternate_sample_rate);
|
||||
|
||||
if (am && card)
|
||||
if (am)
|
||||
pa_droid_add_ports(data.ports, am, card);
|
||||
|
||||
u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE);
|
||||
|
|
@ -646,8 +565,7 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
|
||||
u->source->userdata = u;
|
||||
|
||||
u->source->parent.process_msg = pa_source_process_msg;
|
||||
u->source->set_state_in_io_thread = source_set_state_in_io_thread_cb;
|
||||
u->source->parent.process_msg = source_process_msg;
|
||||
|
||||
source_set_mute_control(u);
|
||||
|
||||
|
|
@ -667,33 +585,22 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
pa_xfree(thread_name);
|
||||
thread_name = NULL;
|
||||
|
||||
update_latency(u);
|
||||
pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &sample_spec));
|
||||
pa_log_debug("Set fixed latency %" PRIu64 " usec", pa_bytes_to_usec(u->buffer_size, &sample_spec));
|
||||
|
||||
if (u->source->active_port)
|
||||
source_set_port_cb(u->source, u->source->active_port);
|
||||
|
||||
/* Since we started in suspended mode suspend our stream immediately as well. */
|
||||
pa_droid_stream_suspend(u->stream, true);
|
||||
|
||||
pa_droid_stream_set_data(u->stream, u->source);
|
||||
pa_source_put(u->source);
|
||||
|
||||
/* As late as possible */
|
||||
pa_module_hook_connect(u->module,
|
||||
&u->module->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW],
|
||||
PA_HOOK_LATE * 2,
|
||||
source_output_new_hook_callback, u);
|
||||
|
||||
pa_module_hook_connect(u->module,
|
||||
&u->module->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST],
|
||||
PA_HOOK_LATE * 2,
|
||||
source_output_unlink_post_hook_callback, u);
|
||||
|
||||
return u->source;
|
||||
|
||||
fail:
|
||||
pa_xfree(thread_name);
|
||||
|
||||
if (config)
|
||||
pa_xfree(config);
|
||||
|
||||
if (u)
|
||||
userdata_free(u);
|
||||
|
||||
|
|
@ -710,7 +617,6 @@ void pa_droid_source_free(pa_source *s) {
|
|||
}
|
||||
|
||||
static void userdata_free(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
|
||||
if (u->source)
|
||||
pa_source_unlink(u->source);
|
||||
|
|
@ -728,9 +634,13 @@ static void userdata_free(struct userdata *u) {
|
|||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
|
||||
if (u->stream)
|
||||
pa_droid_stream_unref(u->stream);
|
||||
if (u->hw_module && u->stream) {
|
||||
pa_droid_hw_module_lock(u->hw_module);
|
||||
u->hw_module->device->close_input_stream(u->hw_module->device, u->stream);
|
||||
pa_droid_hw_module_unlock(u->hw_module);
|
||||
}
|
||||
|
||||
// Stand alone source
|
||||
if (u->hw_module)
|
||||
pa_droid_hw_module_unref(u->hw_module);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
#define foodroidsourcefoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2022 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/card.h>
|
||||
|
||||
#include <droid/droid-util.h>
|
||||
#include "droid-util.h"
|
||||
|
||||
pa_source *pa_droid_source_new(pa_module *m,
|
||||
pa_modargs *ma,
|
||||
|
|
@ -51,4 +51,6 @@ pa_source *pa_droid_source_new(pa_module *m,
|
|||
pa_card *card);
|
||||
void pa_droid_source_free(pa_source *s);
|
||||
|
||||
void pa_droid_source_set_routing(pa_source *s, pa_bool_t enabled);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
274
src/droid/droid-util-41qc.h
Normal file
274
src/droid/droid-util-41qc.h
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_UTIL_V412_H_
|
||||
#define _ANDROID_UTIL_V412_H_
|
||||
|
||||
// PulseAudio value - Android value
|
||||
|
||||
static uint32_t conversion_table_output_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_OUT_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_OUT_FRONT_RIGHT},
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_OUT_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SUBWOOFER, AUDIO_CHANNEL_OUT_LOW_FREQUENCY },
|
||||
{ PA_CHANNEL_POSITION_REAR_LEFT, AUDIO_CHANNEL_OUT_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_REAR_RIGHT, AUDIO_CHANNEL_OUT_BACK_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_OUT_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_LEFT },
|
||||
{ PA_CHANNEL_POSITION_SIDE_RIGHT, AUDIO_CHANNEL_OUT_SIDE_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_CENTER, AUDIO_CHANNEL_OUT_TOP_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_CENTER, AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_CENTER, AUDIO_CHANNEL_OUT_TOP_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_RIGHT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT }
|
||||
};
|
||||
|
||||
static uint32_t conversion_table_input_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_IN_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT},
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_IN_FRONT },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_IN_BACK },
|
||||
/* Following are missing suitable counterparts on PulseAudio side. */
|
||||
{ AUDIO_CHANNEL_IN_LEFT_PROCESSED, AUDIO_CHANNEL_IN_LEFT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_RIGHT_PROCESSED, AUDIO_CHANNEL_IN_RIGHT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_FRONT_PROCESSED, AUDIO_CHANNEL_IN_FRONT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_BACK_PROCESSED, AUDIO_CHANNEL_IN_BACK_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_PRESSURE, AUDIO_CHANNEL_IN_PRESSURE },
|
||||
{ AUDIO_CHANNEL_IN_X_AXIS, AUDIO_CHANNEL_IN_X_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_Y_AXIS, AUDIO_CHANNEL_IN_Y_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_Z_AXIS, AUDIO_CHANNEL_IN_Z_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_VOICE_UPLINK, AUDIO_CHANNEL_IN_VOICE_UPLINK },
|
||||
{ AUDIO_CHANNEL_IN_VOICE_DNLINK, AUDIO_CHANNEL_IN_VOICE_DNLINK }
|
||||
};
|
||||
|
||||
static uint32_t conversion_table_format[][2] = {
|
||||
{ PA_SAMPLE_U8, AUDIO_FORMAT_PCM_8_BIT },
|
||||
{ PA_SAMPLE_S16LE, AUDIO_FORMAT_PCM_16_BIT },
|
||||
{ PA_SAMPLE_S32LE, AUDIO_FORMAT_PCM_32_BIT },
|
||||
{ PA_SAMPLE_S24LE, AUDIO_FORMAT_PCM_8_24_BIT }
|
||||
};
|
||||
|
||||
struct string_conversion {
|
||||
uint32_t value;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
#if defined(STRING_ENTRY) || defined(STRING_ENTRY)
|
||||
#error STRING_ENTRY already defined somewhere, fix this lib.
|
||||
#endif
|
||||
#define STRING_ENTRY(str) { str, #str }
|
||||
/* Output devices */
|
||||
static struct string_conversion string_conversion_table_output_device[] = {
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_EARPIECE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_SPEAKER),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_WIRED_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_AUX_DIGITAL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_USB_ACCESSORY),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_USB_DEVICE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_FM),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_FM_TX),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ANC_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ANC_HEADPHONE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_PROXY),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_A2DP),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_SCO),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_USB),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct string_conversion string_conversion_table_output_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_OUT_EARPIECE, "output-earpiece" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER, "output-speaker" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER
|
||||
| AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "output-speaker+wired_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADSET, "output-wired_headset" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "output-wired_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "output-bluetooth_sco" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, "output-sco_headset" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, "output-sco_carkit" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "output-a2dp" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, "output-a2dp_headphones" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "output-a2dp_speaker" },
|
||||
{ AUDIO_DEVICE_OUT_AUX_DIGITAL, "output-aux_digital" },
|
||||
{ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "output-analog_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "output-digital_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_USB_ACCESSORY, "output-usb_accessory" },
|
||||
{ AUDIO_DEVICE_OUT_USB_DEVICE, "output-usb_device" },
|
||||
{ AUDIO_DEVICE_OUT_FM, "output-fm" },
|
||||
{ AUDIO_DEVICE_OUT_FM_TX, "output-fm_tx" },
|
||||
{ AUDIO_DEVICE_OUT_ANC_HEADSET, "output-anc_headset" },
|
||||
{ AUDIO_DEVICE_OUT_ANC_HEADPHONE, "output-anc_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_PROXY, "output-proxy" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Input devices */
|
||||
static struct string_conversion string_conversion_table_input_device[] = {
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_COMMUNICATION),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_AMBIENT),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BUILTIN_MIC),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_WIRED_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_AUX_DIGITAL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_VOICE_CALL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BACK_MIC),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_ANC_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_FM_RX),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_FM_RX_A2DP),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_PROXY),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct string_conversion string_conversion_table_input_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_IN_COMMUNICATION, "input-in_communication" },
|
||||
{ AUDIO_DEVICE_IN_AMBIENT, "input-ambient" },
|
||||
{ AUDIO_DEVICE_IN_BUILTIN_MIC, "input-builtin_mic" },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "input-bluetooth_sco_headset" },
|
||||
{ AUDIO_DEVICE_IN_WIRED_HEADSET, "input-wired_headset" },
|
||||
{ AUDIO_DEVICE_IN_AUX_DIGITAL, "input-aux_digital" },
|
||||
{ AUDIO_DEVICE_IN_VOICE_CALL, "input-voice_call" },
|
||||
{ AUDIO_DEVICE_IN_BACK_MIC, "input-back_mic" },
|
||||
{ AUDIO_DEVICE_IN_ANC_HEADSET, "input-anc_headset" },
|
||||
{ AUDIO_DEVICE_IN_FM_RX, "input-fm_rx" },
|
||||
{ AUDIO_DEVICE_IN_FM_RX_A2DP, "input-fm_rx_a2dp" },
|
||||
{ AUDIO_DEVICE_IN_PROXY, "input-in_proxy" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
static struct string_conversion string_conversion_table_flag[] = {
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_NONE),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_DIRECT),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_PRIMARY),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_FAST),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
|
||||
/* Qualcomm flags */
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_LPA),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_TUNNEL),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_VOIP_RX),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Channels */
|
||||
static struct string_conversion string_conversion_table_output_channels[] = {
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_LOW_FREQUENCY),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SIDE_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SIDE_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_STEREO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_QUAD),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SURROUND),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_5POINT1),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_7POINT1),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_ALL),
|
||||
{ 0, NULL }
|
||||
};
|
||||
static struct string_conversion string_conversion_table_input_channels[] = {
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_FRONT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_BACK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_LEFT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_RIGHT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_FRONT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_BACK_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_PRESSURE),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_X_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_Y_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_Z_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_UPLINK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_DNLINK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_STEREO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_5POINT1),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_ALL),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Formats */
|
||||
static struct string_conversion string_conversion_table_format[] = {
|
||||
STRING_ENTRY(AUDIO_FORMAT_DEFAULT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM),
|
||||
STRING_ENTRY(AUDIO_FORMAT_MP3),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AMR_NB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AMR_WB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AAC),
|
||||
STRING_ENTRY(AUDIO_FORMAT_HE_AAC_V1),
|
||||
STRING_ENTRY(AUDIO_FORMAT_HE_AAC_V2),
|
||||
STRING_ENTRY(AUDIO_FORMAT_VORBIS),
|
||||
STRING_ENTRY(AUDIO_FORMAT_EVRC),
|
||||
STRING_ENTRY(AUDIO_FORMAT_QCELP),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AC3),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AC3_PLUS),
|
||||
STRING_ENTRY(AUDIO_FORMAT_DTS),
|
||||
STRING_ENTRY(AUDIO_FORMAT_WMA),
|
||||
STRING_ENTRY(AUDIO_FORMAT_WMA_PRO),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AAC_ADIF),
|
||||
STRING_ENTRY(AUDIO_FORMAT_EVRCB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_EVRCWB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_EAC3),
|
||||
STRING_ENTRY(AUDIO_FORMAT_DTS_LBR),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AMR_WB_PLUS),
|
||||
/* Currently we support only PCM formats, but keep all formats
|
||||
* here so audio_policy.conf can be parsed. */
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_16_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_8_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_32_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_8_24_BIT),
|
||||
{ 0, NULL }
|
||||
};
|
||||
#undef STRING_ENTRY
|
||||
|
||||
#endif
|
||||
275
src/droid/droid-util-42.h
Normal file
275
src/droid/droid-util-42.h
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_UTIL_V42_H_
|
||||
#define _ANDROID_UTIL_V42_H_
|
||||
|
||||
#define HAL_V2
|
||||
|
||||
// PulseAudio value - Android value
|
||||
|
||||
static uint32_t conversion_table_output_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_OUT_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_OUT_FRONT_RIGHT},
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_OUT_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SUBWOOFER, AUDIO_CHANNEL_OUT_LOW_FREQUENCY },
|
||||
{ PA_CHANNEL_POSITION_REAR_LEFT, AUDIO_CHANNEL_OUT_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_REAR_RIGHT, AUDIO_CHANNEL_OUT_BACK_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_OUT_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_LEFT },
|
||||
{ PA_CHANNEL_POSITION_SIDE_RIGHT, AUDIO_CHANNEL_OUT_SIDE_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_CENTER, AUDIO_CHANNEL_OUT_TOP_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_CENTER, AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_LEFT },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_CENTER, AUDIO_CHANNEL_OUT_TOP_BACK_CENTER },
|
||||
{ PA_CHANNEL_POSITION_TOP_REAR_RIGHT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT }
|
||||
};
|
||||
|
||||
static uint32_t conversion_table_input_channel[][2] = {
|
||||
{ PA_CHANNEL_POSITION_MONO, AUDIO_CHANNEL_IN_MONO },
|
||||
{ PA_CHANNEL_POSITION_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT },
|
||||
{ PA_CHANNEL_POSITION_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT},
|
||||
{ PA_CHANNEL_POSITION_FRONT_CENTER, AUDIO_CHANNEL_IN_FRONT },
|
||||
{ PA_CHANNEL_POSITION_REAR_CENTER, AUDIO_CHANNEL_IN_BACK },
|
||||
/* Following are missing suitable counterparts on PulseAudio side. */
|
||||
{ AUDIO_CHANNEL_IN_LEFT_PROCESSED, AUDIO_CHANNEL_IN_LEFT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_RIGHT_PROCESSED, AUDIO_CHANNEL_IN_RIGHT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_FRONT_PROCESSED, AUDIO_CHANNEL_IN_FRONT_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_BACK_PROCESSED, AUDIO_CHANNEL_IN_BACK_PROCESSED },
|
||||
{ AUDIO_CHANNEL_IN_PRESSURE, AUDIO_CHANNEL_IN_PRESSURE },
|
||||
{ AUDIO_CHANNEL_IN_X_AXIS, AUDIO_CHANNEL_IN_X_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_Y_AXIS, AUDIO_CHANNEL_IN_Y_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_Z_AXIS, AUDIO_CHANNEL_IN_Z_AXIS },
|
||||
{ AUDIO_CHANNEL_IN_VOICE_UPLINK, AUDIO_CHANNEL_IN_VOICE_UPLINK },
|
||||
{ AUDIO_CHANNEL_IN_VOICE_DNLINK, AUDIO_CHANNEL_IN_VOICE_DNLINK }
|
||||
};
|
||||
|
||||
static uint32_t conversion_table_format[][2] = {
|
||||
{ PA_SAMPLE_U8, AUDIO_FORMAT_PCM_8_BIT },
|
||||
{ PA_SAMPLE_S16LE, AUDIO_FORMAT_PCM_16_BIT },
|
||||
{ PA_SAMPLE_S32LE, AUDIO_FORMAT_PCM_32_BIT },
|
||||
{ PA_SAMPLE_S24LE, AUDIO_FORMAT_PCM_8_24_BIT }
|
||||
};
|
||||
|
||||
struct string_conversion {
|
||||
uint32_t value;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
#if defined(STRING_ENTRY)
|
||||
#error STRING_ENTRY already defined somewhere, fix this lib.
|
||||
#endif
|
||||
#define STRING_ENTRY(str) { str, #str }
|
||||
/* Output devices */
|
||||
static struct string_conversion string_conversion_table_output_device[] = {
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_EARPIECE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_SPEAKER),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_WIRED_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_AUX_DIGITAL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_USB_ACCESSORY),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_USB_DEVICE),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_DEFAULT),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_A2DP),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_SCO),
|
||||
STRING_ENTRY(AUDIO_DEVICE_OUT_ALL_USB),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct string_conversion string_conversion_table_output_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_OUT_EARPIECE, "output-earpiece" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER, "output-speaker" },
|
||||
{ AUDIO_DEVICE_OUT_SPEAKER
|
||||
| AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "output-speaker+wired_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADSET, "output-wired_headset" },
|
||||
{ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "output-wired_headphone" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "output-bluetooth_sco" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, "output-sco_headset" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, "output-sco_carkit" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "output-a2dp" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, "output-a2dp_headphones" },
|
||||
{ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "output-a2dp_speaker" },
|
||||
{ AUDIO_DEVICE_OUT_AUX_DIGITAL, "output-aux_digital" },
|
||||
{ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "output-analog_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "output-digital_dock_headset" },
|
||||
{ AUDIO_DEVICE_OUT_USB_ACCESSORY, "output-usb_accessory" },
|
||||
{ AUDIO_DEVICE_OUT_USB_DEVICE, "output-usb_device" },
|
||||
{ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "output-remote_submix" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Input devices */
|
||||
#ifdef DROID_DEVICE_MAKO
|
||||
static struct string_conversion string_conversion_table_input_device[] = {
|
||||
{ 0x10000, "AUDIO_DEVICE_IN_COMMUNICATION" },
|
||||
{ 0x20000, "AUDIO_DEVICE_IN_AMBIENT" },
|
||||
{ 0x40000, "AUDIO_DEVICE_IN_BUILTIN_MIC" },
|
||||
{ 0x80000, "AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" },
|
||||
{ 0x100000, "AUDIO_DEVICE_IN_WIRED_HEADSET" },
|
||||
{ 0x200000, "AUDIO_DEVICE_IN_AUX_DIGITAL" },
|
||||
{ 0x400000, "AUDIO_DEVICE_IN_VOICE_CALL" },
|
||||
{ 0x800000, "AUDIO_DEVICE_IN_BACK_MIC" },
|
||||
{ 0x80000000, "AUDIO_DEVICE_IN_DEFAULT" },
|
||||
{ 0x80000000, "AUDIO_DEVICE_IN_REMOTE_SUBMIX" }, // What's this really??
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct string_conversion string_conversion_table_input_device_fancy[] = {
|
||||
{ 0x10000, "input-communication" },
|
||||
{ 0x20000, "input-ambient" },
|
||||
{ 0x40000, "input-builtin_mic" },
|
||||
{ 0x80000, "input-bluetooth_sco_headset" },
|
||||
{ 0x100000, "input-wired_headset" },
|
||||
{ 0x200000, "input-aux_digital" },
|
||||
{ 0x400000, "input-voice_call" },
|
||||
{ 0x800000, "input-back_mic" },
|
||||
{ 0x80000000, "input-remote_submix" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
#else
|
||||
static struct string_conversion string_conversion_table_input_device[] = {
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_COMMUNICATION),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_AMBIENT),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BUILTIN_MIC),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_WIRED_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_AUX_DIGITAL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_VOICE_CALL),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_BACK_MIC),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_USB_ACCESSORY),
|
||||
STRING_ENTRY(AUDIO_DEVICE_IN_USB_DEVICE),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct string_conversion string_conversion_table_input_device_fancy[] = {
|
||||
{ AUDIO_DEVICE_IN_COMMUNICATION, "input-communication" },
|
||||
{ AUDIO_DEVICE_IN_AMBIENT, "input-ambient" },
|
||||
{ AUDIO_DEVICE_IN_BUILTIN_MIC, "input-builtin_mic" },
|
||||
{ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "input-bluetooth_sco_headset" },
|
||||
{ AUDIO_DEVICE_IN_WIRED_HEADSET, "input-wired_headset" },
|
||||
{ AUDIO_DEVICE_IN_AUX_DIGITAL, "input-aux_digital" },
|
||||
{ AUDIO_DEVICE_IN_VOICE_CALL, "input-voice_call" },
|
||||
{ AUDIO_DEVICE_IN_BACK_MIC, "input-back_mic" },
|
||||
{ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "input-remote_submix" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Flags */
|
||||
static struct string_conversion string_conversion_table_flag[] = {
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_NONE),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_DIRECT),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_PRIMARY),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_FAST),
|
||||
STRING_ENTRY(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Channels */
|
||||
static struct string_conversion string_conversion_table_output_channels[] = {
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_LOW_FREQUENCY),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_BACK_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SIDE_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SIDE_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_CENTER),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_STEREO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_QUAD),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_SURROUND),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_5POINT1),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_7POINT1),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_OUT_ALL),
|
||||
{ 0, NULL }
|
||||
};
|
||||
static struct string_conversion string_conversion_table_input_channels[] = {
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_LEFT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_RIGHT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_FRONT),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_BACK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_LEFT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_RIGHT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_FRONT_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_BACK_PROCESSED),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_PRESSURE),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_X_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_Y_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_Z_AXIS),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_UPLINK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_VOICE_DNLINK),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_MONO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_STEREO),
|
||||
STRING_ENTRY(AUDIO_CHANNEL_IN_ALL),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Formats */
|
||||
static struct string_conversion string_conversion_table_format[] = {
|
||||
STRING_ENTRY(AUDIO_FORMAT_DEFAULT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM),
|
||||
STRING_ENTRY(AUDIO_FORMAT_MP3),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AMR_NB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AMR_WB),
|
||||
STRING_ENTRY(AUDIO_FORMAT_AAC),
|
||||
STRING_ENTRY(AUDIO_FORMAT_HE_AAC_V1),
|
||||
STRING_ENTRY(AUDIO_FORMAT_HE_AAC_V2),
|
||||
STRING_ENTRY(AUDIO_FORMAT_VORBIS),
|
||||
STRING_ENTRY(AUDIO_FORMAT_MAIN_MASK),
|
||||
STRING_ENTRY(AUDIO_FORMAT_SUB_MASK),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_16_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_8_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_32_BIT),
|
||||
STRING_ENTRY(AUDIO_FORMAT_PCM_8_24_BIT),
|
||||
{ 0, NULL }
|
||||
};
|
||||
#undef STRING_ENTRY
|
||||
|
||||
#endif
|
||||
1145
src/droid/droid-util.c
Normal file
1145
src/droid/droid-util.c
Normal file
File diff suppressed because it is too large
Load diff
248
src/droid/droid-util.h
Normal file
248
src/droid/droid-util.h
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
#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 <hardware/audio.h>
|
||||
#include <hardware_legacy/audio_policy_conf.h>
|
||||
|
||||
#define PROP_DROID_DEVICES "droid.devices"
|
||||
#define PROP_DROID_FLAGS "droid.flags"
|
||||
#define PROP_DROID_HW_MODULE "droid.hw_module"
|
||||
|
||||
typedef struct pa_droid_hw_module pa_droid_hw_module;
|
||||
typedef struct pa_droid_card_data pa_droid_card_data;
|
||||
typedef void (*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;
|
||||
|
||||
struct pa_droid_hw_module {
|
||||
PA_REFCNT_DECLARE;
|
||||
|
||||
pa_core *core;
|
||||
|
||||
pa_droid_config_audio *config;
|
||||
const pa_droid_config_hw_module *enabled_module;
|
||||
pa_mutex *hw_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;
|
||||
|
||||
};
|
||||
|
||||
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)
|
||||
#define AUDIO_MAX_HW_MODULES (8)
|
||||
#define AUDIO_MAX_INPUTS (8)
|
||||
#define AUDIO_MAX_OUTPUTS (8)
|
||||
|
||||
typedef struct pa_droid_config_global {
|
||||
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[AUDIO_HARDWARE_MODULE_ID_MAX_LEN];
|
||||
uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES];
|
||||
audio_channel_mask_t channel_masks; /* 0 -> dynamic */
|
||||
audio_format_t formats;
|
||||
audio_devices_t devices;
|
||||
audio_output_flags_t flags;
|
||||
} pa_droid_config_output;
|
||||
|
||||
typedef struct pa_droid_config_input {
|
||||
const pa_droid_config_hw_module *module;
|
||||
|
||||
char name[AUDIO_HARDWARE_MODULE_ID_MAX_LEN];
|
||||
uint32_t sampling_rates[AUDIO_MAX_SAMPLING_RATES];
|
||||
audio_channel_mask_t channel_masks; /* 0 -> dynamic */
|
||||
audio_format_t formats;
|
||||
audio_devices_t devices;
|
||||
} pa_droid_config_input;
|
||||
|
||||
struct pa_droid_config_hw_module {
|
||||
const pa_droid_config_audio *config;
|
||||
|
||||
char name[AUDIO_HARDWARE_MODULE_ID_MAX_LEN];
|
||||
pa_droid_config_output outputs[AUDIO_MAX_OUTPUTS];
|
||||
uint32_t outputs_size;
|
||||
pa_droid_config_input inputs[AUDIO_MAX_INPUTS];
|
||||
uint32_t inputs_size;
|
||||
};
|
||||
|
||||
struct pa_droid_config_audio {
|
||||
pa_droid_config_global global_config;
|
||||
pa_droid_config_hw_module hw_modules[AUDIO_MAX_HW_MODULES];
|
||||
uint32_t hw_modules_size;
|
||||
};
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
/* Profile doesn't own the mappings */
|
||||
pa_droid_mapping *output;
|
||||
pa_droid_mapping *input;
|
||||
|
||||
} 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"
|
||||
|
||||
/* 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);
|
||||
pa_bool_t pa_droid_hw_module_try_lock(pa_droid_hw_module *hw);
|
||||
void pa_droid_hw_module_unlock(pa_droid_hw_module *hw);
|
||||
|
||||
/* Conversion helpers */
|
||||
typedef enum {
|
||||
CONV_FROM_PA,
|
||||
CONV_FROM_HAL
|
||||
} pa_conversion_field_t;
|
||||
|
||||
pa_bool_t pa_convert_output_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
|
||||
pa_bool_t pa_convert_input_channel(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
|
||||
pa_bool_t pa_convert_format(uint32_t value, pa_conversion_field_t from, uint32_t *to_value);
|
||||
|
||||
pa_bool_t pa_string_convert_output_device_num_to_str(audio_devices_t value, const char **to_str);
|
||||
pa_bool_t pa_string_convert_output_device_str_to_num(const char *str, audio_devices_t *to_value);
|
||||
pa_bool_t pa_string_convert_input_device_num_to_str(audio_devices_t value, const char **to_str);
|
||||
pa_bool_t pa_string_convert_input_device_str_to_num(const char *str, audio_devices_t *to_value);
|
||||
|
||||
pa_bool_t pa_string_convert_flag_num_to_str(audio_output_flags_t value, const char **to_str);
|
||||
pa_bool_t 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);
|
||||
|
||||
/* Config parser */
|
||||
pa_bool_t 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);
|
||||
void pa_droid_profile_set_free(pa_droid_profile_set *ps);
|
||||
|
||||
pa_droid_profile *pa_droid_profile_new(pa_droid_profile_set *ps, const pa_droid_config_output *output, const pa_droid_config_input *input);
|
||||
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);
|
||||
void pa_droid_mapping_free(pa_droid_mapping *am);
|
||||
|
||||
/* Add ports from sinks/sources */
|
||||
void pa_droid_add_ports(pa_hashmap *ports, pa_droid_mapping *am, pa_card *card);
|
||||
/* Add ports from card */
|
||||
void pa_droid_add_card_ports(pa_card_profile *cp, pa_hashmap *ports, pa_droid_mapping *am, pa_core *core);
|
||||
|
||||
/* Pretty port names */
|
||||
pa_bool_t pa_droid_output_port_name(audio_devices_t value, const char **to_str);
|
||||
pa_bool_t pa_droid_input_port_name(audio_devices_t value, const char **to_str);
|
||||
|
||||
#endif
|
||||
223
src/droid/keepalive.c
Normal file
223
src/droid/keepalive.c
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* 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 <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/rtclock.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/dbus-shared.h>
|
||||
#include <pulsecore/dbus-util.h>
|
||||
#include <pulsecore/atomic.h>
|
||||
|
||||
#include "keepalive.h"
|
||||
|
||||
#define MCE_BUS (DBUS_BUS_SYSTEM)
|
||||
#define MCE_DBUS_NAME "com.nokia.mce"
|
||||
#define MCE_DBUS_PATH "/com/nokia/mce/request"
|
||||
#define MCE_DBUS_IFACE "com.nokia.mce.request"
|
||||
#define MCE_DBUS_KEEPALIVE_PERIOD_REQ "req_cpu_keepalive_period"
|
||||
#define MCE_DBUS_KEEPALIVE_START_REQ "req_cpu_keepalive_start"
|
||||
#define MCE_DBUS_KEEPALIVE_STOP_REQ "req_cpu_keepalive_stop"
|
||||
|
||||
struct pa_droid_keepalive {
|
||||
pa_core *core;
|
||||
pa_dbus_connection *dbus_connection;
|
||||
|
||||
pa_atomic_t started;
|
||||
pa_usec_t timeout;
|
||||
pa_time_event *timer_event;
|
||||
|
||||
};
|
||||
|
||||
pa_droid_keepalive* pa_droid_keepalive_new(pa_core *c) {
|
||||
pa_droid_keepalive *k;
|
||||
pa_dbus_connection *dbus;
|
||||
DBusError error;
|
||||
|
||||
pa_assert(c);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
dbus = pa_dbus_bus_get(c, MCE_BUS, &error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
pa_log("Failed to get %s bus: %s", MCE_BUS == DBUS_BUS_SESSION ? "session" : "system", error.message);
|
||||
dbus_error_free(&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
k = pa_xnew0(pa_droid_keepalive, 1);
|
||||
k->core = c;
|
||||
k->dbus_connection = dbus;
|
||||
k->timeout = 0;
|
||||
pa_atomic_store(&k->started, 0);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
static void send_dbus_signal(pa_dbus_connection *dbus) {
|
||||
DBusMessage *msg;
|
||||
|
||||
pa_assert(dbus);
|
||||
|
||||
/* pa_log_debug("Send keepalive heartbeat."); */
|
||||
|
||||
pa_assert_se((msg = dbus_message_new_method_call(MCE_DBUS_NAME,
|
||||
MCE_DBUS_PATH,
|
||||
MCE_DBUS_IFACE,
|
||||
MCE_DBUS_KEEPALIVE_START_REQ)));
|
||||
|
||||
dbus_connection_send(pa_dbus_connection_get(dbus), msg, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
static void keepalive_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
|
||||
pa_droid_keepalive *k = userdata;
|
||||
|
||||
pa_assert(k);
|
||||
pa_assert(k->timer_event == e);
|
||||
|
||||
send_dbus_signal(k->dbus_connection);
|
||||
pa_core_rttime_restart(k->core, k->timer_event, pa_rtclock_now() + k->timeout);
|
||||
}
|
||||
|
||||
static void keepalive_start(pa_droid_keepalive *k) {
|
||||
pa_assert(k);
|
||||
pa_assert(k->timeout);
|
||||
pa_assert(!k->timer_event);
|
||||
|
||||
pa_log_info("Start keepalive heartbeat with interval %lu seconds.", (unsigned long) (k->timeout / PA_USEC_PER_SEC));
|
||||
|
||||
/* Send first keepalive heartbeat immediately. */
|
||||
send_dbus_signal(k->dbus_connection);
|
||||
|
||||
k->timer_event = pa_core_rttime_new(k->core, pa_rtclock_now() + k->timeout, keepalive_cb, k);
|
||||
}
|
||||
|
||||
static void pending_req_reply_cb(DBusPendingCall *pending, void *userdata) {
|
||||
pa_droid_keepalive *k = userdata;
|
||||
DBusMessage *msg;
|
||||
uint32_t period;
|
||||
|
||||
pa_assert(pending);
|
||||
pa_assert(k);
|
||||
|
||||
pa_assert_se(msg = dbus_pending_call_steal_reply(pending));
|
||||
|
||||
if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR) {
|
||||
pa_log("Failed to get %s", MCE_DBUS_KEEPALIVE_PERIOD_REQ);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pa_assert_se(dbus_message_get_args(msg, NULL,
|
||||
DBUS_TYPE_INT32, &period,
|
||||
DBUS_TYPE_INVALID));
|
||||
|
||||
k->timeout = PA_USEC_PER_SEC * (period - 5);
|
||||
|
||||
keepalive_start(k);
|
||||
|
||||
finish:
|
||||
dbus_message_unref(msg);
|
||||
dbus_pending_call_unref(pending);
|
||||
}
|
||||
|
||||
void pa_droid_keepalive_start(pa_droid_keepalive *k) {
|
||||
DBusPendingCall *pending = NULL;
|
||||
DBusMessage *msg = NULL;
|
||||
|
||||
pa_assert(k);
|
||||
|
||||
/* Only allow first call go through. pa_atomic_inc() returns previous value before incrementing. */
|
||||
if (pa_atomic_inc(&k->started) > 0)
|
||||
return;
|
||||
|
||||
pa_assert(!k->timer_event);
|
||||
|
||||
/* Period time already requested, just start hearbeat. */
|
||||
if (k->timeout > 0) {
|
||||
keepalive_start(k);
|
||||
return;
|
||||
}
|
||||
|
||||
pa_log_debug("Starting keepalive - Request keepalive period.");
|
||||
/* Send first keepalive heartbeat immediately. */
|
||||
send_dbus_signal(k->dbus_connection);
|
||||
|
||||
pa_assert_se((msg = dbus_message_new_method_call(MCE_DBUS_NAME,
|
||||
MCE_DBUS_PATH,
|
||||
MCE_DBUS_IFACE,
|
||||
MCE_DBUS_KEEPALIVE_PERIOD_REQ)));
|
||||
|
||||
dbus_connection_send_with_reply(pa_dbus_connection_get(k->dbus_connection), msg, &pending, -1);
|
||||
dbus_message_unref(msg);
|
||||
|
||||
dbus_pending_call_set_notify(pending, pending_req_reply_cb, k, NULL);
|
||||
}
|
||||
|
||||
void pa_droid_keepalive_stop(pa_droid_keepalive *k) {
|
||||
DBusMessage *msg;
|
||||
|
||||
pa_assert(k);
|
||||
|
||||
/* Only allow last call go through. pa_atomic_dec() returns previous value before decrementing. */
|
||||
if (pa_atomic_dec(&k->started) != 1)
|
||||
return;
|
||||
|
||||
pa_assert(pa_atomic_load(&k->started) == 0);
|
||||
|
||||
if (!k->timer_event)
|
||||
return;
|
||||
|
||||
pa_log_debug("Stopping keepalive.");
|
||||
k->core->mainloop->time_free(k->timer_event);
|
||||
k->timer_event = NULL;
|
||||
|
||||
pa_assert_se((msg = dbus_message_new_method_call(MCE_DBUS_NAME,
|
||||
MCE_DBUS_PATH,
|
||||
MCE_DBUS_IFACE,
|
||||
MCE_DBUS_KEEPALIVE_STOP_REQ)));
|
||||
|
||||
dbus_connection_send(pa_dbus_connection_get(k->dbus_connection), msg, NULL);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
void pa_droid_keepalive_free(pa_droid_keepalive *k) {
|
||||
pa_assert(k);
|
||||
pa_assert(k->dbus_connection);
|
||||
|
||||
pa_assert(pa_atomic_load(&k->started) == 0);
|
||||
|
||||
pa_dbus_connection_unref(k->dbus_connection);
|
||||
pa_xfree(k);
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef foodroidconfigparserxmlfoo
|
||||
#define foodroidconfigparserxmlfoo
|
||||
#ifndef foodroidkeepalivefoo
|
||||
#define foodroidkeepalivefoo
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -26,8 +26,19 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <droid/droid-config.h>
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/dbus-shared.h>
|
||||
#include <pulsecore/atomic.h>
|
||||
|
||||
typedef struct pa_droid_keepalive pa_droid_keepalive;
|
||||
|
||||
pa_droid_keepalive* pa_droid_keepalive_new(pa_core *c);
|
||||
void pa_droid_keepalive_free(pa_droid_keepalive *k);
|
||||
|
||||
void pa_droid_keepalive_start(pa_droid_keepalive *k);
|
||||
void pa_droid_keepalive_stop(pa_droid_keepalive *k);
|
||||
|
||||
dm_config_device *pa_parse_droid_audio_config_xml(const char *filename);
|
||||
|
||||
#endif
|
||||
42
src/droid/module-droid-card-symdef.h
Normal file
42
src/droid/module-droid-card-symdef.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef foomoduledroidcardsymdeffoo
|
||||
#define foomoduledroidcardsymdeffoo
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
||||
#define pa__init module_droid_card_LTX_pa__init
|
||||
#define pa__done module_droid_card_LTX_pa__done
|
||||
#define pa__get_author module_droid_card_LTX_pa__get_author
|
||||
#define pa__get_description module_droid_card_LTX_pa__get_description
|
||||
#define pa__get_usage module_droid_card_LTX_pa__get_usage
|
||||
#define pa__get_version module_droid_card_LTX_pa__get_version
|
||||
|
||||
int pa__init(struct pa_module*m);
|
||||
void pa__done(struct pa_module*m);
|
||||
|
||||
const char* pa__get_author(void);
|
||||
const char* pa__get_description(void);
|
||||
const char* pa__get_usage(void);
|
||||
const char* pa__get_version(void);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
42
src/droid/module-droid-keepalive-symdef.h
Normal file
42
src/droid/module-droid-keepalive-symdef.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef foomoduledroidkeepalivesymdeffoo
|
||||
#define foomoduledroidkeepalivesymdeffoo
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
||||
#define pa__init module_droid_keepalive_LTX_pa__init
|
||||
#define pa__done module_droid_keepalive_LTX_pa__done
|
||||
#define pa__get_author module_droid_keepalive_LTX_pa__get_author
|
||||
#define pa__get_description module_droid_keepalive_LTX_pa__get_description
|
||||
#define pa__get_usage module_droid_keepalive_LTX_pa__get_usage
|
||||
#define pa__get_version module_droid_keepalive_LTX_pa__get_version
|
||||
|
||||
int pa__init(struct pa_module*m);
|
||||
void pa__done(struct pa_module*m);
|
||||
|
||||
const char* pa__get_author(void);
|
||||
const char* pa__get_description(void);
|
||||
const char* pa__get_usage(void);
|
||||
const char* pa__get_version(void);
|
||||
|
||||
#endif
|
||||
182
src/droid/module-droid-keepalive.c
Normal file
182
src/droid/module-droid-keepalive.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* 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 <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/i18n.h>
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/sink.h>
|
||||
#include <pulsecore/source.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/idxset.h>
|
||||
|
||||
#include "keepalive.h"
|
||||
|
||||
#include "module-droid-keepalive-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Juho Hämäläinen");
|
||||
PA_MODULE_DESCRIPTION("Droid keepalive. Send cpu wakeup heartbeat while streams are active.");
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_USAGE(
|
||||
"-"
|
||||
);
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
pa_core *core;
|
||||
pa_module *module;
|
||||
|
||||
pa_droid_keepalive *keepalive;
|
||||
pa_bool_t active;
|
||||
pa_hook_slot *sink_state_changed_slot;
|
||||
pa_hook_slot *source_state_changed_slot;
|
||||
};
|
||||
|
||||
static void start(struct userdata *u) {
|
||||
if (u->active)
|
||||
return;
|
||||
|
||||
u->active = TRUE;
|
||||
|
||||
pa_droid_keepalive_start(u->keepalive);
|
||||
}
|
||||
|
||||
static void stop(struct userdata *u) {
|
||||
void *state = NULL;
|
||||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
|
||||
if (!u->active)
|
||||
return;
|
||||
|
||||
while ((sink = pa_idxset_iterate(u->core->sinks, &state, NULL))) {
|
||||
if (pa_sink_get_state(sink) != PA_SINK_SUSPENDED)
|
||||
return;
|
||||
}
|
||||
|
||||
state = NULL;
|
||||
while ((source = pa_idxset_iterate(u->core->sources, &state, NULL))) {
|
||||
if (source->monitor_of)
|
||||
continue;
|
||||
if (pa_source_get_state(source) != PA_SOURCE_SUSPENDED)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We get here if all sinks and sources are in suspended state. */
|
||||
pa_droid_keepalive_stop(u->keepalive);
|
||||
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);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_source_isinstance(o)) {
|
||||
pa_source *s = PA_SOURCE(o);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (state != PA_SINK_SUSPENDED)
|
||||
start(u);
|
||||
else
|
||||
stop(u);
|
||||
}
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
|
||||
int pa__init(pa_module *m) {
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
struct userdata *u = pa_xnew0(struct userdata, 1);
|
||||
u->core = m->core;
|
||||
u->active = FALSE;
|
||||
u->module = m;
|
||||
m->userdata = u;
|
||||
|
||||
if (!(u->keepalive = pa_droid_keepalive_new(u->core))) {
|
||||
pa_log("Failed to create keepalive handler.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
pa__done(m);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pa__done(pa_module *m) {
|
||||
struct userdata *u;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if ((u = m->userdata)) {
|
||||
|
||||
if (u->sink_state_changed_slot)
|
||||
pa_hook_slot_free(u->sink_state_changed_slot);
|
||||
if (u->source_state_changed_slot)
|
||||
pa_hook_slot_free(u->source_state_changed_slot);
|
||||
|
||||
if (u->keepalive) {
|
||||
stop(u);
|
||||
pa_droid_keepalive_free(u->keepalive);
|
||||
}
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
}
|
||||
42
src/droid/module-droid-sink-symdef.h
Normal file
42
src/droid/module-droid-sink-symdef.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef foomoduledroidsinksymdeffoo
|
||||
#define foomoduledroidsinksymdeffoo
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
||||
#define pa__init module_droid_sink_LTX_pa__init
|
||||
#define pa__done module_droid_sink_LTX_pa__done
|
||||
#define pa__get_author module_droid_sink_LTX_pa__get_author
|
||||
#define pa__get_description module_droid_sink_LTX_pa__get_description
|
||||
#define pa__get_usage module_droid_sink_LTX_pa__get_usage
|
||||
#define pa__get_version module_droid_sink_LTX_pa__get_version
|
||||
|
||||
int pa__init(struct pa_module*m);
|
||||
void pa__done(struct pa_module*m);
|
||||
|
||||
const char* pa__get_author(void);
|
||||
const char* pa__get_description(void);
|
||||
const char* pa__get_usage(void);
|
||||
const char* pa__get_version(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2018 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -37,10 +37,11 @@
|
|||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include <droid/droid-util.h>
|
||||
#include <droid/conversion.h>
|
||||
#include "droid-util.h"
|
||||
#include "droid-sink.h"
|
||||
|
||||
#include "module-droid-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Juho Hämäläinen");
|
||||
PA_MODULE_DESCRIPTION("Droid sink");
|
||||
PA_MODULE_USAGE("master_sink=<sink to connect to> "
|
||||
|
|
@ -48,28 +49,15 @@ PA_MODULE_USAGE("master_sink=<sink to connect to> "
|
|||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"config",
|
||||
"rate",
|
||||
"format",
|
||||
"channels",
|
||||
"channel_map",
|
||||
"sink_rate",
|
||||
"sink_format",
|
||||
"sink_channel_map",
|
||||
"sink_mix_route",
|
||||
"flags",
|
||||
"output",
|
||||
"output_devices",
|
||||
"devices",
|
||||
"sink_name",
|
||||
"module_id",
|
||||
"mute_routing_before",
|
||||
"mute_routing_after",
|
||||
"prewrite_on_resume",
|
||||
"sink_buffer",
|
||||
"deferred_volume",
|
||||
"voice_property_key",
|
||||
"voice_property_value",
|
||||
"voice_virtual_stream",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -84,24 +72,15 @@ void pa__done(pa_module *m) {
|
|||
|
||||
int pa__init(pa_module *m) {
|
||||
pa_modargs *ma = NULL;
|
||||
const char *flags_str;
|
||||
audio_output_flags_t flags = 0;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
pa_log("Failed to parse module argumets.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((flags_str = pa_modargs_get_value(ma, "flags", NULL))) {
|
||||
if (!pa_string_convert_flag_str_to_num(flags_str, &flags)) {
|
||||
pa_log("Failed to parse flags");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(m->userdata = pa_droid_sink_new(m, ma, __FILE__, NULL, flags, NULL, NULL)))
|
||||
if (!(m->userdata = pa_droid_sink_new(m, ma, __FILE__, NULL, 0, NULL, NULL)))
|
||||
goto fail;
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
|
|
|||
42
src/droid/module-droid-source-symdef.h
Normal file
42
src/droid/module-droid-source-symdef.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef foomoduledroidsourcesymdeffoo
|
||||
#define foomoduledroidsourcesymdeffoo
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/module.h>
|
||||
|
||||
#define pa__init module_droid_source_LTX_pa__init
|
||||
#define pa__done module_droid_source_LTX_pa__done
|
||||
#define pa__get_author module_droid_source_LTX_pa__get_author
|
||||
#define pa__get_description module_droid_source_LTX_pa__get_description
|
||||
#define pa__get_usage module_droid_source_LTX_pa__get_usage
|
||||
#define pa__get_version module_droid_source_LTX_pa__get_version
|
||||
|
||||
int pa__init(struct pa_module*m);
|
||||
void pa__done(struct pa_module*m);
|
||||
|
||||
const char* pa__get_author(void);
|
||||
const char* pa__get_description(void);
|
||||
const char* pa__get_usage(void);
|
||||
const char* pa__get_version(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2022 Jolla Ltd.
|
||||
* Copyright (C) 2013 Jolla Ltd.
|
||||
*
|
||||
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
|
||||
* 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
|
||||
|
|
@ -37,9 +37,11 @@
|
|||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include <droid/droid-util.h>
|
||||
#include "droid-util.h"
|
||||
#include "droid-source.h"
|
||||
|
||||
#include "module-droid-source-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Juho Hämäläinen");
|
||||
PA_MODULE_DESCRIPTION("Droid source");
|
||||
PA_MODULE_USAGE("master_source=<source to connect to> "
|
||||
|
|
@ -47,16 +49,9 @@ PA_MODULE_USAGE("master_source=<source to connect to> "
|
|||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
"config",
|
||||
"rate",
|
||||
"format",
|
||||
"channels",
|
||||
"channel_map",
|
||||
"source_rate",
|
||||
"source_format",
|
||||
"source_channel_map",
|
||||
"flags",
|
||||
"input_devices",
|
||||
"devices",
|
||||
"source_name",
|
||||
"module_id",
|
||||
"source_buffer",
|
||||
|
|
@ -79,7 +74,7 @@ int pa__init(pa_module *m) {
|
|||
pa_assert(m);
|
||||
|
||||
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||
pa_log("Failed to parse module arguments.");
|
||||
pa_log("Failed to parse module argumets.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue