update master

This commit is contained in:
Chengyi Zhao 2024-06-25 16:53:15 +08:00
commit 7138fa0272
227 changed files with 67492 additions and 3107 deletions

1
.gitignore vendored
View file

@ -37,3 +37,4 @@ stamp-*
.dirstamp
*.orig
*.rej
subprojects/*/

View file

@ -2,7 +2,7 @@
# container and push it to the project's container registry on fd.o GitLab.
# This step is only run when the tag for the container changes, else it is
# effectively a no-op. All of this infrastructure is inherited from the
# wayland/ci-templates repository which is the recommended way to set up CI
# freedesktop/ci-templates repository which is the recommended way to set up CI
# infrastructure on fd.o GitLab.
#
# Once the container stage is done, we move on to the 'build' stage where we
@ -19,22 +19,26 @@ variables:
# CI runs, for example when adding new packages to FDO_DISTRIBUTION_PACKAGES.
# The tag is an arbitrary string that identifies the exact container
# contents.
<<<<<<< HEAD
FDO_DISTRIBUTION_TAG: '2021-03-01-02'
FDO_DISTRIBUTION_VERSION: '18.04'
=======
FDO_DISTRIBUTION_TAG: '2023-08-13-00'
FDO_DISTRIBUTION_VERSION: '20.04'
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
FDO_UPSTREAM_REPO: 'pulseaudio/pulseaudio'
UBUNTU_IMAGE: "$CI_REGISTRY_IMAGE/ubuntu/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
include:
# We pull templates from master to avoid the overhead of periodically
# scanning for changes upstream. This does means builds might occasionally
# break due to upstream changing things, so if you see unexpected build
# failures, this might be one cause.
- project: 'wayland/ci-templates'
- project: 'freedesktop/ci-templates'
ref: 'master'
file: '/templates/ubuntu.yml'
build-container:
extends: .fdo.container-ifnot-exists@ubuntu
extends: .fdo.container-build@ubuntu
stage: container
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
@ -48,6 +52,7 @@ build-container:
check
curl
dbus-x11
doxygen
g++
gcc
gettext
@ -88,17 +93,17 @@ build-container:
wget
build-meson:
extends: .fdo.distribution-image@ubuntu
stage: build
image: $UBUNTU_IMAGE
script:
# Install meson
- wget -q https://github.com/mesonbuild/meson/releases/download/0.50.0/meson-0.50.0.tar.gz
- tar -xf meson-0.50.0.tar.gz
- cd meson-0.50.0
# Install meson (higher than our min version to support our wrap file)
- wget -q https://github.com/mesonbuild/meson/releases/download/0.63.2/meson-0.63.2.tar.gz
- tar -xf meson-0.63.2.tar.gz
- cd meson-0.63.2
- python3 setup.py install
- cd ..
# Do the actual build
- meson build
- meson build -Dwebrtc-aec=enabled
- cd build
- ninja
- ulimit -c 0 # don't dump core files on tests that are supposed to assert

189
NEWS
View file

@ -1,3 +1,192 @@
<<<<<<< HEAD
=======
PulseAudio 17.0
Changes at a glance:
* Notes for end users
* Updates to ALSA UCM-based setups
* Battery level indication to Bluetooth devices
* Support for the Bluetooth FastStream codec
* webrtc-audio-processing dependency updated
* Trigger role groups added to module-role-cork
* XDG base directory spec for profile-set loading
* Notes for application developers
* PA_RATE_MAX increased
* Notes for packagers
* webrtc-audio-processing dependency updated
Contributors
Alistair Leslie-Hughes
Alper Nebi Yasak
Arun Raghavan
Asier Sarasua Garmendia
Ataberk Özen
Balázs Meskó
Biswapriyo Nath
Dylan Van Assche
Eero Nurkkala
Ettore Atalan
Fabrice Fontaine
Fran Diéguez
Georg Chini
Gioele Barabucci
Gogo Gogsi
Hector Martin
Hugo Carvalho
Hui Wang
Igor V. Kovalenko
Jaechul Lee
Jan Kuparinen
Jan Palus
Jaroslav Kysela
Jiri Grönroos
Joachim Philipp
Jordi Mas
Marijn Suijten
Mart Raudsepp
Nicolas Cavallari
Peter Meerwald-Stadler
Philip Goto
Rosen Penev
Rudi Heitbaum
Sabri Ünal
Sean Greenslade
Seong-ho Cho
Shunsuke Shimizu
SimonP
Takashi Sakamoto
Tanu Kaskinen
Temuri Doghonadze
Toni Estevez
Weijia Wang
Wim Taymans
Yureka
acheronfail
flyingOwl
grimst
hashitaku
mooo
peijiankang
redfast00
wael
김인수
PulseAudio 16.1
A bug fix release.
* Fix parsing of percentage volumes with decimal points in pactl
* Fix crash with the "pacmd play-file" command when reads from the disk aren't frame-aligned
* Fix module-rtp-recv sometimes thinking it's receiving an Opus stream when it's not
* Fix frequent crashing in module-combine-sink, regression in 16.0
* Fix crashing on 32-bit architectures when using the GStreamer codecs for LDAC and AptX
Contributors
Georg Chini
Igor V. Kovalenko
Jaechul Lee
Jan Palus
Sean Greenslade
PulseAudio 16.0
Changes at a glance:
* Notes for end users
* Opus support in RTP modules
* Improved hardware support
* EPOS/Sennheiser GSP 670 USB/wireless headset
* SteelSeries GameDAC
* Behringer UMC22 generalized to Texas Instruments PCM2902 to support more products
* NI Komplete Audio 6 MK2 profiles
* Tunnel latency is now configurable
* Bluetooth device battery level reporting added
* Tunnel and combine-sunk latency fixes
* patcl can show information in JSON format
* Channel remixing can be disabled for module-combine-sink
* A lot of fixes to ALSA, bluetooth, and other components.
* Notes for application developers
* Stream latency reports now include resampler delay
* Module installation location changed, remember to upgrade paprefs to the latest version!
* Notes for packagers
* Opus support in the RTP modules requires enabling GStreamer
* Bluetooth battery level reporting via BlueZ requires enabling experimentals features in BlueZ
* New time smoother implementation
* Change Meson option 'daemon-only' to 'client'
* glib and fftw are now common dependencies, not only for the client.
* Enable GStreamer-based RTP by default when available
Detailed change log:
https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/16.0/
Contributors
Alexey Rubtsov
Anders Jonsson
Andika Triwidada
Arun Raghavan
Biswapriyo Nath
BtbN
Chengyi Zhao
Chupligin Sergey
Craig Howard
Daniel Dantur
Daniel Hernandez
Diederik de Haas
Dylan Van Assche
Emilio Herrera
Ettore Atalan
Fran Diéguez
Georg Chini
Gogo Gogsi
Göran Uddeborg
Hela Basa
Hui Wang
Igor V. Kovalenko
Jan Kuparinen
Jaroslav Kysela
Josef Haider
João Paulo Rechi Vita
Juho Hämäläinen
Karl Ove Hufthammer
Laurent Bigonville
Luna Jernberg
Lv Genggeng
Marijn Suijten
Mart Raudsepp
Mathy Vanvoorden
Olivier Gayot
Ovari
Oğuz Ersen
Piotr Drąg
Rafael Fontenelle
Rico Tzschichholz
Sanchayan Maity
Sebastian Reichel
Sergey A
Sibo Dong
Sungjoon Moon
Takashi Sakamoto
Takuro Onoue
Tanu Kaskinen
Temuri Doghonadze
Will Thompson
Yuri Chornoivan
acheronfail
baek inchan
guest271314
liaohanqin
simmon
simple
tensorknower69
김인수
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
PulseAudio 15.0
Changes at a glance:

View file

@ -14,11 +14,33 @@ if get_option('daemon')
]
endif
<<<<<<< HEAD
manpages += [
['pacat', '1', ['paplay', 'parec', 'parecord', 'pamon']],
['pactl', '1'],
['pulse-client.conf', '5'],
]
=======
if get_option('client')
manpages += [
['pacat', '1', ['paplay', 'parec', 'parecord', 'pamon']],
['pactl', '1'],
['pulse-client.conf', '5'],
]
if cdata.has('HAVE_OSS_WRAPPER')
manpages += [
['padsp', '1'],
]
endif
if x11_dep.found()
manpages += [
['pax11publish', '1'],
]
endif
endif
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if cdata.has('HAVE_OSS_WRAPPER')
manpages += [

View file

@ -79,7 +79,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>-d | --device</opt><arg>=SINKORSOURCE</arg></p>
<optdesc><p>Specify the symbolic name of the sink/source to play/record this stream on/from.</p></optdesc>
<optdesc><p>Specify the symbolic name of the sink/source to play/record this stream on/from. The special names @DEFAULT_SINK@, @DEFAULT_SOURCE@ and @DEFAULT_MONITOR@ can be used to specify the default sink, source and monitor respectively.</p></optdesc>
</option>
<option>

View file

@ -174,7 +174,13 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>set-default-sink</opt> <arg>SINK</arg></p>
<<<<<<< HEAD
<optdesc><p>Make the specified sink (identified by its symbolic name or numerical index) the default sink.</p></optdesc>
=======
<optdesc><p>Make the specified sink (identified by its symbolic name or numerical index) the default sink.
Use the special name \@NONE@ to unset the user defined default sink. This will make pulseaudio return to the default
sink selection based on sink priority.</p></optdesc>
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
</option>
<option>
@ -189,7 +195,13 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>set-default-source</opt> <arg>SOURCE</arg></p>
<<<<<<< HEAD
<optdesc><p>Make the specified source (identified by its symbolic name or numerical index) the default source.</p></optdesc>
=======
<optdesc><p>Make the specified source (identified by its symbolic name or numerical index) the default source.
Use the special name \@NONE@ to unset the user defined default source. This will make pulseaudio return to the default
source selection based on source priority.</p></optdesc>
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
</option>
<option>

View file

@ -143,8 +143,10 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<p><opt>set-default-sink|set-default-source</opt> <arg>index|name</arg></p>
<optdesc><p>Make a sink (resp. source) the default. You may specify the
sink (resp. source) by its index in the sink (resp. source) list or by its
name.</p><p>Note that defaults may be overridden by various policy modules
or by specific stream configurations.</p></optdesc>
name. Use the special name \@NONE@ to unset the user defined default sink or
source. In this case, pulseaudio will return to the default sink or source
selection based on priority.</p><p>Note that defaults may be overridden by
various policy modules or by specific stream configurations.</p></optdesc>
</option>
<option>

View file

@ -71,7 +71,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
</option>
<option>
<p><opt>default-server=</opt> The default sever to connect
<p><opt>default-server=</opt> The default server to connect
to. The environment variable <opt>$PULSE_SERVER</opt> takes
precedence.</p>
</option>

View file

@ -1,10 +1,16 @@
project('pulseaudio', 'c', 'cpp',
version : run_command(find_program('git-version-gen'), join_paths(meson.current_source_dir(), '.tarball-version')).stdout().strip(),
project('pulseaudio', 'c',
version : run_command(find_program('git-version-gen'), join_paths(meson.current_source_dir(), '.tarball-version'), check : false).stdout().strip(),
meson_version : '>= 0.50.0',
default_options : [ 'c_std=gnu11', 'cpp_std=c++11' ]
default_options : [ 'c_std=gnu11', 'cpp_std=c++17' ]
)
<<<<<<< HEAD
meson.add_dist_script('scripts/save-tarball-version.sh', meson.project_version())
=======
if not meson.is_subproject()
meson.add_dist_script('scripts/save-tarball-version.sh', meson.project_version())
endif
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_version_str = meson.project_version()
# For tarballs, the first split will do nothing, but for builds in git, we
@ -25,7 +31,11 @@ pa_protocol_version = 35
# The stable ABI for client applications, for the version info x:y:z
# always will hold x=z
<<<<<<< HEAD
libpulse_version_info = [24, 0, 24]
=======
libpulse_version_info = [24, 3, 24]
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
# A simplified, synchronous, ABI-stable interface for client
# applications, for the version info x:y:z always will hold x=z
@ -53,6 +63,8 @@ libpulse_mainloop_glib_version = '@0@.@1@.@2@'.format(
libpulse_mainloop_glib_version_info[1],
)
i18n = import('i18n')
# Paths
prefix = get_option('prefix')
@ -68,6 +80,10 @@ localedir = join_paths(prefix, get_option('localedir'))
localstatedir = join_paths(prefix, get_option('localstatedir'))
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
privlibdir = join_paths(libdir, 'pulseaudio')
<<<<<<< HEAD
=======
po_dir = join_paths(meson.current_source_dir(), 'po')
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if host_machine.system() == 'windows'
# Windows only supports loading libraries from the same dir as the executable
@ -85,7 +101,12 @@ pulsesysconfdir = join_paths(sysconfdir, 'pulse')
modlibexecdir = get_option('modlibexecdir')
if modlibexecdir == ''
modlibexecdir = join_paths(libdir, 'pulse-' + pa_version_major_minor, 'modules')
modlibexecdir = join_paths(libdir, 'pulseaudio', 'modules')
endif
if host_machine.system() == 'windows'
# Windows only supports loading libraries from the same dir as the executable
modlibexecdir = bindir
endif
padsplibdir = get_option('padsplibdir')
@ -140,7 +161,11 @@ cdata.set_quoted('PA_MACHINE_ID', join_paths(sysconfdir, 'machine-id'))
cdata.set_quoted('PA_MACHINE_ID_FALLBACK', join_paths(localstatedir, 'lib', 'dbus', 'machine-id'))
cdata.set_quoted('PA_SRCDIR', join_paths(meson.current_source_dir(), 'src'))
cdata.set_quoted('PA_BUILDDIR', meson.current_build_dir())
cdata.set_quoted('PA_SOEXT', '.so')
if host_machine.system() == 'windows'
cdata.set_quoted('PA_SOEXT', '.dll')
else
cdata.set_quoted('PA_SOEXT', '.so')
endif
cdata.set_quoted('PA_DEFAULT_CONFIG_DIR', pulsesysconfdir)
cdata.set('PA_DEFAULT_CONFIG_DIR_UNQUOTED', pulsesysconfdir)
cdata.set_quoted('PA_BINARY', join_paths(bindir, 'pulseaudio'))
@ -152,8 +177,7 @@ cdata.set_quoted('PA_SYSTEM_USER', get_option('system_user'))
cdata.set_quoted('PA_SYSTEM_GROUP', get_option('system_group'))
cdata.set_quoted('PA_ACCESS_GROUP', get_option('access_group'))
cdata.set_quoted('PA_CFLAGS', 'Not yet supported on meson')
cdata.set_quoted('PA_ALSA_PATHS_DIR', join_paths(alsadatadir, 'paths'))
cdata.set_quoted('PA_ALSA_PROFILE_SETS_DIR', join_paths(alsadatadir, 'profile-sets'))
cdata.set_quoted('PA_ALSA_DATA_DIR', alsadatadir)
cdata.set_quoted('DESKTOPFILEDIR', join_paths(datadir, 'applications'))
cdata.set_quoted('PULSE_LOCALEDIR', localedir)
cdata.set_quoted('GETTEXT_PACKAGE', 'pulseaudio')
@ -177,6 +201,7 @@ endif
# rather than ending up in the config.h file?
if host_machine.system() == 'darwin'
cdata.set('OS_IS_DARWIN', 1)
cdata.set('HAVE_COREAUDIO', 1)
cdata.set('_DARWIN_C_SOURCE', '200112L') # Needed to get NSIG on Mac OS
elif host_machine.system() == 'windows'
cdata.set('OS_IS_WIN32', 1)
@ -416,7 +441,11 @@ cdata.set('MESON_BUILD', 1)
# so we request the nodelete flag to be enabled.
# On other systems, we don't really know how to do that, but it's welcome if somebody can tell.
# Windows doesn't support this flag.
<<<<<<< HEAD
if host_machine.system() != 'windows'
=======
if host_machine.system() != 'windows' and host_machine.system() != 'darwin'
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
nodelete_link_args = ['-Wl,-z,nodelete']
else
nodelete_link_args = []
@ -425,6 +454,7 @@ endif
# Code coverage
if get_option('gcov')
add_languages('cpp')
add_project_arguments('--coverage', language: ['c', 'cpp'])
add_project_link_arguments('--coverage', language: ['c', 'cpp'])
endif
@ -490,22 +520,24 @@ endif
need_libatomic_ops = false
atomictest = '''void func() {
atomictest = '''int main() {
volatile int atomic = 2;
__sync_bool_compare_and_swap (&atomic, 2, 3);
return 0;
}
'''
if cc.compiles(atomictest)
if cc.links(atomictest)
cdata.set('HAVE_ATOMIC_BUILTINS', 1)
newatomictest = '''void func() {
newatomictest = '''int main() {
int c = 0;
__atomic_store_n(&c, 4, __ATOMIC_SEQ_CST);
return 0;
}
'''
if(cc.compiles(newatomictest))
if(cc.links(newatomictest))
cdata.set('HAVE_ATOMIC_BUILTINS_MEMORY_MODEL', 1)
endif
@ -577,6 +609,7 @@ if host_machine.cpu_family() == 'arm'
endif
# NEON checks are automatically done by the unstable-simd module
<<<<<<< HEAD
if get_option('daemon')
# FIXME: make sure it's >= 2.2
ltdl_dep = cc.find_library('ltdl', required : true)
@ -593,39 +626,20 @@ elif get_option('database') == 'gdbm'
else
database_dep = dependency('', required: false)
endif
=======
# Dependencies common to client, daemon and modules
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if get_option('ipv6')
cdata.set('HAVE_IPV6', 1)
endif
if get_option('legacy-database-entry-format')
cdata.set('ENABLE_LEGACY_DATABASE_ENTRY_FORMAT', 1)
endif
if get_option('stream-restore-clear-old-devices')
cdata.set('STREAM_RESTORE_CLEAR_OLD_DEVICES', 1)
endif
if get_option('running-from-build-tree')
cdata.set('HAVE_RUNNING_FROM_BUILD_TREE', 1)
endif
alsa_dep = dependency('alsa', version : '>= 1.0.24', required : get_option('alsa'))
if alsa_dep.found()
cdata.set('HAVE_ALSA', 1)
cdata.set('HAVE_ALSA_UCM', 1)
endif
asyncns_dep = dependency('libasyncns', version : '>= 0.1', required : get_option('asyncns'))
if asyncns_dep.found()
cdata.set('HAVE_LIBASYNCNS', 1)
endif
dbus_dep = dependency('dbus-1', version : '>= 1.4.12', required : get_option('dbus'))
if dbus_dep.found()
cdata.set('HAVE_DBUS', 1)
endif
<<<<<<< HEAD
gio_dep = dependency('gio-2.0', version : '>= 2.26.0')
if get_option('gsettings').enabled()
assert(gio_dep.found(), 'GSettings support needs glib I/O library (GIO)')
@ -634,51 +648,22 @@ else
cdata.set('HAVE_GSETTINGS', 0)
endif
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
glib_dep = dependency('glib-2.0', version : '>= 2.28.0', required: get_option('glib'))
if glib_dep.found()
cdata.set('HAVE_GLIB', 1)
endif
gtk_dep = dependency('gtk+-3.0', required : get_option('gtk'))
if gtk_dep.found()
cdata.set('HAVE_GTK', 1)
endif
have_orcc = false
orcc_args = []
orc_dep = dependency('orc-0.4', version : '>= 0.4.11', required : get_option('orc'))
orcc = find_program('orcc', required : get_option('orc'))
if orc_dep.found() and orcc.found()
have_orcc = true
orcc_args = [orcc]
#orcc_args = [orcc, '--include', 'glib.h']
cdata.set('HAVE_ORC', 1)
else
cdata.set('DISABLE_ORC', 1)
endif
samplerate_dep = dependency('samplerate', version : '>= 0.1.0', required : get_option('samplerate'))
if samplerate_dep.found()
cdata.set('HAVE_LIBSAMPLERATE', 1)
cdata.set('HAVE_GLIB20', 1) # to match the AM_CONDITIONAL for CMake file generation
endif
sndfile_dep = dependency('sndfile', version : '>= 1.0.20')
soxr_dep = dependency('soxr', version : '>= 0.1.1', required : get_option('soxr'))
if soxr_dep.found()
cdata.set('HAVE_SOXR', 1)
endif
libsystemd_dep = dependency('libsystemd', required : get_option('systemd'))
if libsystemd_dep.found()
cdata.set('HAVE_SYSTEMD_DAEMON', 1)
cdata.set('HAVE_SYSTEMD_LOGIN', 1)
cdata.set('HAVE_SYSTEMD_JOURNAL', 1)
endif
systemd_dep = dependency('systemd', required : get_option('systemd'))
if systemd_dep.found() and systemduserunitdir == ''
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir')
endif
libelogind_dep = dependency('libelogind', required : get_option('elogind'))
if libelogind_dep.found()
@ -691,6 +676,7 @@ if cc.has_header('tcpd.h') and cc.has_function('hosts_access', dependencies : tc
endif
x11_dep = dependency('x11-xcb', required : get_option('x11'))
<<<<<<< HEAD
if x11_dep.found()
xcb_dep = dependency('xcb', required : true, version : '>= 1.6')
ice_dep = dependency('ice', required : get_option('daemon'))
@ -704,15 +690,24 @@ endif
# Module dependencies
if cc.has_header('sys/soundcard.h', required: get_option('oss-output'))
=======
# OSS support
if cc.has_header('sys/soundcard.h', required: get_option('oss-output'))
# OSS output via daemon module-detect
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
cdata.set('HAVE_OSS_OUTPUT', 1)
# OSS wrapper
cdata.set('HAVE_OSS_WRAPPER', 1)
cdata.set('PULSEDSP_LOCATION', pulsedsp_location)
endif
if get_option('hal-compat')
cdata.set('HAVE_HAL_COMPAT', 1)
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
if fftw_dep.found()
cdata.set('HAVE_FFTW', 1)
endif
<<<<<<< HEAD
avahi_dep = dependency('avahi-client', version : '>= 0.6.0', required : get_option('avahi'), disabler : true)
if avahi_dep.found()
cdata.set('HAVE_AVAHI', 1)
@ -732,47 +727,179 @@ if bluez_dep.found()
cdata.set('HAVE_BLUEZ_5', 1)
if get_option('bluez5-native-headset')
cdata.set('HAVE_BLUEZ_5_NATIVE_HEADSET', 1)
=======
# Client library dependencies
if get_option('client')
asyncns_dep = dependency('libasyncns', version : '>= 0.1', required : get_option('asyncns'))
if asyncns_dep.found()
cdata.set('HAVE_LIBASYNCNS', 1)
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
endif
if get_option('bluez5-ofono-headset')
cdata.set('HAVE_BLUEZ_5_OFONO_HEADSET', 1)
gtk_dep = dependency('gtk+-3.0', required : get_option('gtk'))
if gtk_dep.found()
cdata.set('HAVE_GTK', 1)
endif
endif
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
if fftw_dep.found()
cdata.set('HAVE_FFTW', 1)
endif
# Daemon and module dependencies
jack_dep = dependency('jack', version : '>= 0.117.0', required : get_option('jack'))
if jack_dep.found()
cdata.set('HAVE_JACK', 1)
endif
if get_option('daemon')
# FIXME: make sure it's >= 2.2
ltdl_dep = cc.find_library('ltdl', required : true)
lirc_dep = dependency('lirc', required : get_option('lirc'))
if lirc_dep.found()
cdata.set('HAVE_LIRC', 1)
endif
# FIXME: can meson support libtool -dlopen/-dlpreopen things?
# and do we still want to support this at all?
cdata.set('DISABLE_LIBTOOL_PRELOAD', 1)
openssl_dep = dependency('openssl', version : '>= 0.9', required : get_option('openssl'))
if openssl_dep.found()
cdata.set('HAVE_OPENSSL', 1)
endif
if get_option('database') == 'tdb'
database_dep = dependency('tdb')
elif get_option('database') == 'gdbm'
database_dep = cc.find_library('gdbm', required : true)
else
database_dep = dependency('', required: false)
endif
speex_dep = dependency('speexdsp', version : '>= 1.2', required : get_option('speex'))
if speex_dep.found()
cdata.set('HAVE_SPEEX', 1)
endif
if get_option('legacy-database-entry-format')
cdata.set('ENABLE_LEGACY_DATABASE_ENTRY_FORMAT', 1)
endif
udev_dep = dependency('libudev', version : '>= 143', required : get_option('udev'))
if udev_dep.found()
cdata.set('HAVE_UDEV', 1)
endif
if get_option('stream-restore-clear-old-devices')
cdata.set('STREAM_RESTORE_CLEAR_OLD_DEVICES', 1)
endif
webrtc_dep = dependency('webrtc-audio-processing', version : '>= 0.2', required : get_option('webrtc-aec'))
if webrtc_dep.found()
cdata.set('HAVE_WEBRTC', 1)
endif
if get_option('running-from-build-tree')
cdata.set('HAVE_RUNNING_FROM_BUILD_TREE', 1)
endif
if get_option('enable-smoother-2')
cdata.set('USE_SMOOTHER_2', 1)
endif
alsa_dep = dependency('alsa', version : '>= 1.0.24', required : get_option('alsa'))
if alsa_dep.found()
cdata.set('HAVE_ALSA', 1)
cdata.set('HAVE_ALSA_UCM', 1)
endif
gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : false)
if get_option('gsettings').enabled()
assert(gio_dep.found(), 'GSettings support needs glib I/O library (GIO)')
cdata.set('HAVE_GSETTINGS', 1)
else
cdata.set('HAVE_GSETTINGS', 0)
endif
have_orcc = false
orcc_args = []
orc_dep = dependency('orc-0.4', version : '>= 0.4.11', required : get_option('orc'))
orcc = find_program('orcc', required : get_option('orc'))
if orc_dep.found() and orcc.found()
have_orcc = true
orcc_args = [orcc]
#orcc_args = [orcc, '--include', 'glib.h']
cdata.set('HAVE_ORC', 1)
else
cdata.set('DISABLE_ORC', 1)
endif
samplerate_dep = dependency('samplerate', version : '>= 0.1.0', required : get_option('samplerate'))
if samplerate_dep.found()
cdata.set('HAVE_LIBSAMPLERATE', 1)
endif
speex_dep = dependency('speexdsp', version : '>= 1.2', required : get_option('speex'))
if speex_dep.found()
cdata.set('HAVE_SPEEX', 1)
endif
soxr_dep = dependency('soxr', version : '>= 0.1.1', required : get_option('soxr'))
if soxr_dep.found()
cdata.set('HAVE_SOXR', 1)
endif
webrtc_dep = dependency('webrtc-audio-processing-1', version : '>= 1.0', required : get_option('webrtc-aec'))
if webrtc_dep.found()
cdata.set('HAVE_WEBRTC', 1)
endif
systemd_dep = dependency('systemd', required : get_option('systemd'))
if systemd_dep.found() and systemduserunitdir == ''
systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir')
endif
libelogind_dep = dependency('libelogind', required : get_option('elogind'))
if libelogind_dep.found()
cdata.set('HAVE_SYSTEMD_LOGIN', 1)
endif
if get_option('consolekit').enabled()
assert(dbus_dep.found(), 'ConsoleKit requires D-Bus support')
endif
tcpwrap_dep = cc.find_library('wrap', required: get_option('tcpwrap'))
if cc.has_header('tcpd.h') and cc.has_function('hosts_access', dependencies : tcpwrap_dep)
cdata.set('HAVE_LIBWRAP', 1)
endif
if x11_dep.found()
xcb_dep = dependency('xcb', required : true, version : '>= 1.6')
ice_dep = dependency('ice', required : true)
sm_dep = dependency('sm', required : true)
xtst_dep = dependency('xtst', required : true)
cdata.set('HAVE_X11', 1)
if cc.has_function('XSetIOErrorExitHandler', dependencies: x11_dep)
cdata.set('HAVE_XSETIOERROREXITHANDLER', 1)
endif
endif
avahi_dep = dependency('avahi-client', version : '>= 0.6.0', required : get_option('avahi'), disabler : true)
if avahi_dep.found()
cdata.set('HAVE_AVAHI', 1)
else
cdata.set('HAVE_AVAHI', 0)
endif
sbc_dep = dependency('sbc', version : '>= 1.0', required : false)
bluez_dep = dependency('bluez', required : get_option('bluez5'))
if bluez_dep.found()
assert(dbus_dep.found(), 'BlueZ requires D-Bus support')
assert(sbc_dep.found(), 'BlueZ requires SBC support')
cdata.set('HAVE_SBC', 1)
cdata.set('HAVE_BLUEZ', 1)
cdata.set('HAVE_BLUEZ_5', 1)
if get_option('bluez5-native-headset')
cdata.set('HAVE_BLUEZ_5_NATIVE_HEADSET', 1)
endif
if get_option('bluez5-ofono-headset')
cdata.set('HAVE_BLUEZ_5_OFONO_HEADSET', 1)
endif
endif
jack_dep = dependency('jack', version : '>= 0.117.0', required : get_option('jack'))
if jack_dep.found()
cdata.set('HAVE_JACK', 1)
endif
lirc_dep = dependency('lirc', required : get_option('lirc'))
if lirc_dep.found()
cdata.set('HAVE_LIRC', 1)
endif
openssl_dep = dependency('openssl', version : '>= 0.9', required : get_option('openssl'))
if openssl_dep.found()
cdata.set('HAVE_OPENSSL', 1)
endif
udev_dep = dependency('libudev', version : '>= 143', required : get_option('udev'))
if udev_dep.found()
cdata.set('HAVE_UDEV', 1)
endif
<<<<<<< HEAD
gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('gstreamer'))
gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('gstreamer'))
gstrtp_dep = dependency('gstreamer-rtp-1.0', required : get_option('gstreamer'))
@ -781,6 +908,30 @@ have_gstreamer = false
if gst_dep.found() and gstapp_dep.found() and gstrtp_dep.found()
assert(gio_dep.found(), 'GStreamer-based RTP needs glib I/O library (GIO)')
have_gstreamer = true
=======
if get_option('hal-compat')
cdata.set('HAVE_HAL_COMPAT', 1)
endif
gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('gstreamer'))
gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('gstreamer'))
gstrtp_dep = dependency('gstreamer-rtp-1.0', required : get_option('gstreamer'))
have_gstreamer = false
if gst_dep.found() and gstapp_dep.found() and gstrtp_dep.found()
assert(gio_dep.found(), 'GStreamer-based RTP needs glib I/O library (GIO)')
have_gstreamer = true
endif
bluez5_gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('bluez5-gstreamer'))
bluez5_gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('bluez5-gstreamer'))
have_bluez5_gstreamer = false
if bluez5_gst_dep.found() and bluez5_gstapp_dep.found()
have_bluez5_gstreamer = true
cdata.set('HAVE_GSTLDAC', 1)
cdata.set('HAVE_GSTAPTX', 1)
endif
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
endif
bluez5_gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('bluez5-gstreamer'))
@ -795,9 +946,6 @@ endif
# These are required for the CMake file generation
cdata.set('PA_LIBDIR', libdir)
cdata.set('PA_INCDIR', includedir)
if glib_dep.found()
cdata.set('HAVE_GLIB20', 1) # to match the AM_CONDITIONAL for CMake file generation
endif
# Test dependencies
@ -808,81 +956,93 @@ check_dep = dependency('check', version : '>= 0.9.10', required : get_option('te
if get_option('doxygen')
subdir('doxygen')
endif
<<<<<<< HEAD
subdir('po')
=======
if get_option('client')
subdir('po')
endif
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if get_option('man')
subdir('man')
endif
subdir('shell-completion/bash')
subdir('shell-completion/zsh')
subdir('src')
subdir('vala')
if get_option('client')
subdir('vala')
endif
# Now generate config.h from everything above
configure_file(output : 'config.h', configuration : cdata)
# pkg-config files
if get_option('client')
pc_cdata = configuration_data()
# pkg-config files
pc_cdata.set('prefix', prefix)
pc_cdata.set('exec_prefix', prefix)
pc_cdata.set('libdir', libdir)
pc_cdata.set('includedir', includedir)
pc_cdata.set('modlibexecdir', modlibexecdir)
pc_cdata.set('PACKAGE_VERSION', pa_version_str)
pc_cdata.set('PA_MAJORMINOR', pa_version_major_minor)
# FIXME: the line below is wrong. Currently the meson thread dep lacks documentation,
# and doesn't allow introspection, ie. none of get_pkgconfig_variable() or
# get_configtool_variable() work with it, so we have no way to get this flag right,
# unless we do all the work ourselves. See current work in glib, also meson #553.
pc_cdata.set('PTHREAD_LIBS', '-pthread')
pc_cdata = configuration_data()
pc_files = [
'libpulse.pc',
'libpulse-simple.pc',
]
pc_cdata.set('prefix', prefix)
pc_cdata.set('exec_prefix', prefix)
pc_cdata.set('libdir', libdir)
pc_cdata.set('includedir', includedir)
pc_cdata.set('modlibexecdir', modlibexecdir)
pc_cdata.set('PACKAGE_VERSION', pa_version_str)
pc_cdata.set('PA_MAJORMINOR', pa_version_major_minor)
# FIXME: the line below is wrong. Currently the meson thread dep lacks documentation,
# and doesn't allow introspection, ie. none of get_pkgconfig_variable() or
# get_configtool_variable() work with it, so we have no way to get this flag right,
# unless we do all the work ourselves. See current work in glib, also meson #553.
pc_cdata.set('PTHREAD_LIBS', '-pthread')
if glib_dep.found()
pc_files += 'libpulse-mainloop-glib.pc'
endif
pc_files = [
'libpulse.pc',
'libpulse-simple.pc',
]
if glib_dep.found()
pc_files += 'libpulse-mainloop-glib.pc'
endif
foreach file : pc_files
configure_file(
input : file + '.in',
output : file,
configuration : pc_cdata,
install_dir : pkgconfigdir)
endforeach
# CMake files
m4 = find_program('m4', required: true)
cmakedir = join_paths(libdir, 'cmake', 'PulseAudio')
cmake_template_file = configure_file(
input : 'PulseAudioConfig.cmake.in',
output : 'PulseAudioConfig.cmake.tmp',
configuration: cdata,
)
custom_target('PulseAudioConfig.cmake',
input : cmake_template_file,
output : 'PulseAudioConfig.cmake',
capture : true,
command : [m4, '@INPUT@'],
build_by_default : true,
install : true,
install_dir : cmakedir,
)
foreach file : pc_files
configure_file(
input : file + '.in',
output : file,
configuration : pc_cdata,
install_dir : pkgconfigdir)
endforeach
input : 'PulseAudioConfigVersion.cmake.in',
output : 'PulseAudioConfigVersion.cmake',
configuration: cdata,
install : true,
install_dir : cmakedir,
)
# CMake files
m4 = find_program('m4', required: true)
cmakedir = join_paths(libdir, 'cmake', 'PulseAudio')
cmake_template_file = configure_file(
input : 'PulseAudioConfig.cmake.in',
output : 'PulseAudioConfig.cmake.tmp',
configuration: cdata,
)
custom_target('PulseAudioConfig.cmake',
input : cmake_template_file,
output : 'PulseAudioConfig.cmake',
capture : true,
command : [m4, '@INPUT@'],
build_by_default : true,
install : true,
install_dir : cmakedir,
)
configure_file(
input : 'PulseAudioConfigVersion.cmake.in',
output : 'PulseAudioConfigVersion.cmake',
configuration: cdata,
install : true,
install_dir : cmakedir,
)
endif # client
############################################################
@ -913,17 +1073,57 @@ summary = [
# 'LIBS: @0@'.format(${LIBS}),
'',
'Enable pulseaudio daemon: @0@'.format(get_option('daemon')),
<<<<<<< HEAD
'',
'Enable memfd shared memory: @0@'.format(cdata.has('HAVE_MEMFD')),
'Enable X11: @0@'.format(x11_dep.found()),
' Safe X11 I/O errors: @0@'.format(cdata.has('HAVE_XSETIOERROREXITHANDLER')),
'Enable OSS Output: @0@'.format(cdata.has('HAVE_OSS_OUTPUT')),
'Enable OSS Wrapper: @0@'.format(cdata.has('HAVE_OSS_WRAPPER')),
=======
'Enable pulseaudio client: @0@'.format(get_option('client')),
'',
'Enable memfd shared memory: @0@'.format(cdata.has('HAVE_MEMFD')),
'Enable X11: @0@'.format(x11_dep.found()),
'Enable D-Bus: @0@'.format(dbus_dep.found()),
'Enable GLib 2: @0@'.format(glib_dep.found()),
'Enable systemd integration: @0@'.format(libsystemd_dep.found()),
'Enable FFTW: @0@'.format(fftw_dep.found()),
'Enable IPv6: @0@'.format(get_option('ipv6')),
'Enable Gcov coverage: @0@'.format(get_option('gcov')),
'Enable Valgrind: @0@'.format(cdata.has('HAVE_VALGRIND_MEMCHECK_H')),
'Enable man pages: @0@'.format(get_option('man')),
'Enable unit tests: @0@'.format(get_option('tests')),
]
if get_option('client')
summary += [
'',
'--- Pulseaudio client features ---',
'',
'Enable Gtk+ 3: @0@'.format(gtk_dep.found()),
'Enable Async DNS: @0@'.format(asyncns_dep.found()),
'Enable OSS Wrapper: @0@'.format(cdata.has('HAVE_OSS_WRAPPER')),
]
endif
if get_option('daemon')
summary += [
'',
'--- Pulseaudio daemon features ---',
'',
'Safe X11 I/O errors: @0@'.format(cdata.has('HAVE_XSETIOERROREXITHANDLER')),
'Enable Avahi: @0@'.format(avahi_dep.found()),
'Enable OSS Output: @0@'.format(cdata.has('HAVE_OSS_OUTPUT')),
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
# 'Enable EsounD: @0@'.format(${ENABLE_ESOUND}),
'Enable Alsa: @0@'.format(alsa_dep.found()),
'Enable Jack: @0@'.format(jack_dep.found()),
'Enable LIRC: @0@'.format(lirc_dep.found()),
# 'Enable CoreAudio: @0@'.format(${ENABLE_COREAUDIO}),
# 'Enable Solaris: @0@'.format(${ENABLE_SOLARIS}),
# 'Enable WaveOut: @0@'.format(${ENABLE_WAVEOUT}),
<<<<<<< HEAD
'Enable GLib 2: @0@'.format(glib_dep.found()),
'Enable GSettings: @0@'.format(gio_dep.found()),
'Enable Gtk+ 3: @0@'.format(gtk_dep.found()),
@ -941,21 +1141,35 @@ summary = [
'Enable systemd: @0@'.format(libsystemd_dep.found()),
'Enable elogind: @0@'.format(libelogind_dep.found()),
'Enable TCP Wrappers: @0@'.format(tcpwrap_dep.found()),
'Enable libsamplerate: @0@'.format(samplerate_dep.found()),
'Enable IPv6: @0@'.format(get_option('ipv6')),
'Enable OpenSSL (for Airtunes): @0@'.format(openssl_dep.found()),
'Enable FFTW: @0@'.format(fftw_dep.found()),
'Enable ORC: @0@'.format(have_orcc),
=======
'Enable GSettings: @0@'.format(gio_dep.found()),
'Enable BlueZ 5: @0@'.format(cdata.has('HAVE_BLUEZ_5')),
' Enable native headsets: @0@'.format(cdata.has('HAVE_BLUEZ_5_NATIVE_HEADSET')),
' Enable ofono headsets: @0@'.format(cdata.has('HAVE_BLUEZ_5_OFONO_HEADSET')),
' Enable GStreamer based codecs: @0@'.format(have_bluez5_gstreamer),
'Enable GStreamer: @0@'.format(have_gstreamer),
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
'Enable libsamplerate: @0@'.format(samplerate_dep.found()),
'Enable ORC: @0@'.format(have_orcc),
'Enable Adrian echo canceller: @0@'.format(get_option('adrian-aec')),
'Enable Speex (resampler, AEC): @0@'.format(speex_dep.found()),
'Enable SoXR (resampler): @0@'.format(soxr_dep.found()),
'Enable WebRTC echo canceller: @0@'.format(webrtc_dep.found()),
<<<<<<< HEAD
'Enable Gcov coverage: @0@'.format(get_option('gcov')),
'Enable Valgrind: @0@'.format(cdata.has('HAVE_VALGRIND_MEMCHECK_H')),
'Enable man pages: @0@'.format(get_option('man')),
'Enable unit tests: @0@'.format(get_option('tests')),
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
'',
'Enable udev: @0@'.format(udev_dep.found()),
' Enable HAL->udev compat: @0@'.format(get_option('hal-compat')),
'Enable systemd units: @0@'.format(systemd_dep.found()),
'Enable elogind: @0@'.format(libelogind_dep.found()),
'Enable ConsoleKit: @0@'.format(not get_option('consolekit').disabled() and dbus_dep.found()),
'Enable TCP Wrappers: @0@'.format(tcpwrap_dep.found()),
'Enable OpenSSL (for Airtunes): @0@'.format(openssl_dep.found()),
'Database: @0@'.format(get_option('database')),
'Legacy Database Entry Support: @0@'.format(get_option('legacy-database-entry-format')),
'module-stream-restore:',
@ -968,19 +1182,21 @@ summary = [
# 'Force preopen: @0@'.format(${FORCE_PREOPEN}),
# 'Preopened modules: @0@'.format(${PREOPEN_MODS}),
]
endif
message('\n '.join(summary))
# Sanity checks
if not speex_dep.found() and not webrtc_dep.found() and not get_option('adrian-aec')
if get_option('daemon') and not speex_dep.found() and not webrtc_dep.found() and not get_option('adrian-aec')
error('At least one echo canceller implementation must be available!')
endif
if samplerate_dep.found()
if get_option('daemon') and samplerate_dep.found()
warning('Support for libsamplerate is DEPRECATED')
endif
<<<<<<< HEAD
if host_machine.system() != 'windows'
if not dbus_dep.found()
message = [
@ -1011,4 +1227,36 @@ if host_machine.system() != 'windows'
]
warning('\n' + '\n'.join(message))
endif
=======
if host_machine.system() != 'windows' and not dbus_dep.found()
message = [
'You do not have D-Bus support enabled. It is strongly recommended',
'that you enable D-Bus support if your platform supports it.',
'Many parts of PulseAudio use D-Bus, from ConsoleKit interaction',
'to the Device Reservation Protocol to speak to JACK, Bluetooth',
'support and even a native control protocol for communicating and',
'controlling the PulseAudio daemon itself.',
]
warning('\n' + '\n'.join(message))
endif
if get_option('daemon') and host_machine.system() == 'linux' and not udev_dep.found()
message = [
'You do not have udev support enabled. It is strongly recommended',
'that you enable udev support if your platform supports it as it is',
'the primary method used to detect hardware audio devices (on Linux)',
'and is thus a critical part of PulseAudio on that platform.',
]
warning('\n' + '\n'.join(message))
endif
if get_option('daemon') and host_machine.system() != 'windows' and not speex_dep.found()
message = [
'You do not have speex support enabled. It is strongly recommended',
'that you enable speex support if your platform supports it as it is',
'the primary method used for audio resampling and is thus a critical',
'part of PulseAudio on that platform.',
]
warning('\n' + '\n'.join(message))
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
endif

View file

@ -1,6 +1,12 @@
option('daemon',
type : 'boolean', value : true,
description : 'Enable building and installation of pulseaudio daemon and supporting configuration files')
<<<<<<< HEAD
=======
option('client',
type : 'boolean', value : true,
description : 'Build and install pulseaudio client libraries and utilities')
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
option('doxygen',
type : 'boolean', value : true,
description : 'Enable building and installation of documentation generated with doxygen')
@ -96,6 +102,9 @@ option('bluez5-native-headset',
option('bluez5-ofono-headset',
type : 'boolean',
description : 'Optional oFono headset backend support (BlueZ 5)')
option('consolekit',
type : 'feature', value : 'auto',
description : 'Optional ConsoleKit support')
option('dbus',
type : 'feature', value : 'auto',
description : 'Optional D-Bus support')
@ -162,6 +171,9 @@ option('valgrind',
option('x11',
type : 'feature', value : 'auto',
description : 'Optional X11 support')
option('enable-smoother-2',
type : 'boolean', value : true,
description : 'Use alternative time smoother implementation')
# Echo cancellation

View file

@ -48,3 +48,8 @@ zh_CN
zh_TW
eo
si
<<<<<<< HEAD
=======
ka
eu
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336

View file

@ -170,6 +170,7 @@ src/pulsecore/thread-mq.c
src/pulsecore/thread-posix.c
src/pulsecore/thread-win32.c
src/pulsecore/time-smoother.c
src/pulsecore/time-smoother_2.c
src/pulsecore/tokenizer.c
src/pulsecore/x11prop.c
src/pulsecore/x11wrap.c

756
po/af.po

File diff suppressed because it is too large Load diff

944
po/as.po

File diff suppressed because it is too large Load diff

778
po/be.po

File diff suppressed because it is too large Load diff

818
po/bg.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1802
po/ca.po

File diff suppressed because it is too large Load diff

769
po/cs.po

File diff suppressed because it is too large Load diff

760
po/da.po

File diff suppressed because it is too large Load diff

858
po/de.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

789
po/el.po

File diff suppressed because it is too large Load diff

767
po/eo.po

File diff suppressed because it is too large Load diff

1721
po/es.po

File diff suppressed because it is too large Load diff

2902
po/eu.po Normal file

File diff suppressed because it is too large Load diff

1811
po/fi.po

File diff suppressed because it is too large Load diff

916
po/fr.po

File diff suppressed because it is too large Load diff

886
po/gl.po

File diff suppressed because it is too large Load diff

955
po/gu.po

File diff suppressed because it is too large Load diff

1223
po/he.po

File diff suppressed because it is too large Load diff

860
po/hi.po

File diff suppressed because it is too large Load diff

913
po/hr.po

File diff suppressed because it is too large Load diff

1073
po/hu.po

File diff suppressed because it is too large Load diff

903
po/id.po

File diff suppressed because it is too large Load diff

770
po/it.po

File diff suppressed because it is too large Load diff

823
po/ja.po

File diff suppressed because it is too large Load diff

2993
po/ka.po Normal file

File diff suppressed because it is too large Load diff

751
po/kk.po

File diff suppressed because it is too large Load diff

982
po/kn.po

File diff suppressed because it is too large Load diff

1862
po/ko.po

File diff suppressed because it is too large Load diff

781
po/lt.po

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,3 @@
i18n = import('i18n')
i18n.gettext(
meson.project_name(),
preset: 'glib',
@ -7,5 +6,3 @@ i18n.gettext(
args: ['--msgid-bugs-address=https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new',
'--width=90'],
)
po_dir = meson.current_source_dir()

1025
po/ml.po

File diff suppressed because it is too large Load diff

1040
po/mr.po

File diff suppressed because it is too large Load diff

2035
po/nl.po

File diff suppressed because it is too large Load diff

828
po/nn.po

File diff suppressed because it is too large Load diff

771
po/oc.po

File diff suppressed because it is too large Load diff

963
po/or.po

File diff suppressed because it is too large Load diff

904
po/pa.po

File diff suppressed because it is too large Load diff

772
po/pl.po

File diff suppressed because it is too large Load diff

2436
po/pt.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1339
po/ru.po

File diff suppressed because it is too large Load diff

779
po/si.po

File diff suppressed because it is too large Load diff

781
po/sk.po

File diff suppressed because it is too large Load diff

952
po/sr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

797
po/sv.po

File diff suppressed because it is too large Load diff

885
po/ta.po

File diff suppressed because it is too large Load diff

1125
po/te.po

File diff suppressed because it is too large Load diff

959
po/tr.po

File diff suppressed because it is too large Load diff

773
po/uk.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,21 @@ print_map_file() {
echo "};"
}
<<<<<<< HEAD
TARGET_FILE=$1
shift
cd "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}" && print_map_file "$@" > ${TARGET_FILE}
=======
print_def_file() {
echo "EXPORTS"
ctags -I ${CTAGS_IDENTIFIER_LIST} -f - --c-kinds=p "$@" | awk '/^pa_/ && !/(^pa_glib_|^pa_simple_)/ { print $1 }' | sort
}
MAP_FILE=$1
DEF_FILE=$2
shift 2
cd "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}" && print_map_file "$@" > ${MAP_FILE}
cd "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}" && print_def_file "$@" > ${DEF_FILE}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336

View file

@ -1,5 +1,6 @@
if bashcompletiondir != 'no'
aliases = []
<<<<<<< HEAD
if get_option('daemon')
aliases += [
@ -16,12 +17,38 @@ if bashcompletiondir != 'no'
'parec',
'parecord',
]
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
install_data('pulseaudio', install_dir : bashcompletiondir)
if get_option('daemon')
aliases += [
'pulseaudio',
'pacmd',
'pasuspender',
]
# Create target directory for symlinks
if meson.version().version_compare('>= 0.60.0')
install_emptydir(bashcompletiondir)
else
meson.add_install_script('sh', '-c', 'mkdir -p $DESTDIR@0@'.format(bashcompletiondir))
endif
endif
if get_option('client')
aliases += [
'pacat',
'padsp',
'paplay',
'parec',
'parecord',
]
install_data('pactl', install_dir : bashcompletiondir)
endif
foreach alias : aliases
dst = join_paths(bashcompletiondir, alias)
cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pulseaudio', dst)
cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pactl', dst)
meson.add_install_script('sh', '-c', cmd)
endforeach
endif

View file

@ -109,19 +109,26 @@ in_array() {
}
_pactl() {
local cur prev words cword preprev command
local cur prev words cword preprev word command
local comps
local flags='-h --help --version -s --server= --client-name='
local list_types='short sinks sources sink-inputs source-outputs cards
modules samples clients message-handlers'
local commands=(stat info list exit upload-sample play-sample remove-sample
load-module unload-module move-sink-input move-source-output
suspend-sink suspend-source set-card-profile set-default-sink
set-sink-port set-default-source set-source-port set-sink-volume
suspend-sink suspend-source set-card-profile get-default-sink
set-default-sink set-sink-port get-default-source set-default-source
set-source-port get-sink-volume set-sink-volume get-source-volume
set-source-volume set-sink-input-volume set-source-output-volume
<<<<<<< HEAD:shell-completion/bash/pulseaudio
set-sink-mute set-source-mute set-sink-input-mute
set-source-output-mute set-sink-formats set-port-latency-offset
subscribe send-message help)
=======
get-sink-mute set-sink-mute get-source-mute set-source-mute
set-sink-input-mute set-source-output-mute set-sink-formats
set-port-latency-offset subscribe send-message help)
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336:shell-completion/bash/pactl
_init_completion -n = || return
preprev=${words[$cword-2]}
@ -186,6 +193,8 @@ _pactl() {
remove-sample) ;; # TODO
get-default*) ;;
load-module)
comps=$(__all_modules)
COMPREPLY=($(compgen -W '${comps[*]}' -- "$cur"))
@ -255,7 +264,7 @@ _pactl() {
complete -F _pactl pactl
_pacmd() {
local cur prev words cword preprev command
local cur prev words cword preprev word command
local comps
local flags='-h --help --version'
local commands=(exit help list-modules list-cards list-sinks list-sources list-clients
@ -500,7 +509,7 @@ _pulseaudio()
--start -k --kill --check --system= -D --daemonize= --fail= --high-priority=
--realtime= --disallow-module-loading= --disallow-exit= --exit-idle-time=
--scache-idle-time= --log-level= -v --log-target= --log-meta= --log-time=
--log-backtrace= -p --dl-search-path= --resample-method= --use-pit-file=
--log-backtrace= -p --dl-search-path= --resample-method= --use-pid-file=
--no-cpu-limit= --disable-shm= --enable-memfd= -L --load= -F --file= -C -n'
_init_completion -n = || return

View file

@ -18,10 +18,12 @@ _devices() {
if [[ $service == pactl || $service == pacmd ]]; then
case $words[$((CURRENT - 1))] in
set-sink-input-*) cmd=('sink-inputs');;
get-sink-*) cmd=('sinks');;
set-sink-*) cmd=('sinks');;
set-default-sink) cmd=('sinks');;
set-default-source) cmd=('sources');;
set-source-output-*) cmd=('source-outputs');;
get-source-*) cmd=('sources');;
set-source-*) cmd=('sources');;
suspend-sink) cmd=('sinks');;
suspend-source) cmd=('sources');;
@ -257,16 +259,22 @@ _pactl_completion() {
'suspend-sink: suspend or resume a sink'
'suspend-source: suspend or resume a source'
'set-card-profile: set a card profile'
'get-default-sink: get the default sink'
'set-default-sink: set the default sink'
'get-default-source: get the default source'
'set-default-source: set the default source'
'set-sink-port: set the sink port of a sink'
'set-source-port: set the source port of a source'
'set-port-latency-offset: set a latency offset on a port'
'get-sink-volume: get the volume of a sink'
'set-sink-volume: set the volume of a sink'
'get-source-volume: get the volume of a source'
'set-source-volume: set the volume of a source'
'set-sink-input-volume: set the volume of a stream'
'set-source-output-volume: set the volume of a recording stream'
'get-sink-mute: get the mute status of a sink'
'set-sink-mute: mute a sink'
'get-source-mute: get the mute status of a source'
'set-source-mute: mute a source'
'set-sink-input-mute: mute a stream'
'set-source-output-mute: mute a recording stream'
@ -492,11 +500,15 @@ _pactl_completion() {
set-default-source) if ((CURRENT == 2)); then _devices; fi;;
set-sink-port) _set_sink_port_parameter;;
set-source-port) _set_source_port_parameter;;
get-sink-volume) if ((CURRENT == 2)); then _devices; fi;;
set-sink-volume) if ((CURRENT == 2)); then _devices; fi;;
get-source-volume) if ((CURRENT == 2)); then _devices; fi;;
set-source-volume) if ((CURRENT == 2)); then _devices; fi;;
set-sink-input-volume) if ((CURRENT == 2)); then _devices; fi;;
set-source-output-volume) if ((CURRENT == 2)); then _devices; fi;;
get-sink-mute) if ((CURRENT == 2)); then _devices; fi;;
set-sink-mute) _set_sink_mute_parameter;;
get-source-mute) if ((CURRENT == 2)); then _devices; fi;;
set-source-mute) _set_source_mute_parameter;;
set-sink-input-mute) _set_sink_input_mute_parameter;;
set-source-output-mute) _set_source_output_mute_parameter;;

View file

@ -1,3 +1,5 @@
if zshcompletiondir != 'no'
install_data('_pulseaudio', install_dir : zshcompletiondir)
if get_option('client')
if zshcompletiondir != 'no'
install_data('_pulseaudio', install_dir : zshcompletiondir)
endif
endif

1
src/.gitignore vendored
View file

@ -71,6 +71,7 @@ proplist-test
queue-test
remix-test
resampler-test
resampler-rewind-test
rtpoll-test
rtstutter
sig2str-test

View file

@ -262,7 +262,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
if (optarg) {
if (pa_daemon_conf_set_log_level(conf, optarg) < 0) {
pa_log(_("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."));
pa_log(_("--log-level expects log level argument (either numeric in range 0..4 or one of error, warn, notice, info, debug)."));
goto fail;
}
} else {

View file

@ -171,5 +171,9 @@ load-module module-filter-apply
### Allow including a default.pa.d directory, which if present, can be used
### for additional configuration snippets.
<<<<<<< HEAD
=======
### Note that those snippet files must have a .pa file extension, not .conf
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.nofail
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/default.pa.d

View file

@ -30,8 +30,13 @@ executable('pulseaudio',
install_rpath : privlibdir,
include_directories : [configinc, topinc],
link_args : ['-ffast-math'],
<<<<<<< HEAD
link_with : [libpulsecore, libpulsecommon, libpulse],
dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep, platform_dep, platform_socket_dep],
=======
link_with : [libpulsecore],
dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep, platform_dep, platform_socket_dep, libpulsecommon_dep, libpulse_dep],
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
c_args : pa_c_args,
)
@ -141,7 +146,7 @@ custom_target('system.pa',
if dbus_dep.found()
install_data('pulseaudio-system.conf',
install_dir : join_paths(sysconfdir, 'dbus-1', 'system.d')
install_dir : join_paths(datadir, 'dbus-1', 'system.d')
)
endif

View file

@ -69,5 +69,9 @@ load-module module-position-event-sounds
### Allow including a system.pa.d directory, which if present, can be used
### for additional configuration snippets.
<<<<<<< HEAD
=======
### Note that those snippet files must have a .pa file extension, not .conf
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.nofail
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/system.pa.d

View file

@ -57,12 +57,12 @@ libpulsecommon_sources = [
'pulsecore/shm.c',
'pulsecore/bitset.c',
'pulsecore/socket-client.c',
'pulsecore/socket-server.c',
'pulsecore/socket-util.c',
'pulsecore/strbuf.c',
'pulsecore/strlist.c',
'pulsecore/tagstruct.c',
'pulsecore/time-smoother.c',
'pulsecore/time-smoother_2.c',
'pulsecore/tokenizer.c',
'pulsecore/usergroup.c',
'pulsecore/sndfile-util.c',
@ -136,13 +136,13 @@ libpulsecommon_headers = [
'pulsecore/shm.h',
'pulsecore/bitset.h',
'pulsecore/socket-client.h',
'pulsecore/socket-server.h',
'pulsecore/socket-util.h',
'pulsecore/strbuf.h',
'pulsecore/strlist.h',
'pulsecore/tagstruct.h',
'pulsecore/thread.h',
'pulsecore/time-smoother.h',
'pulsecore/time-smoother_2.h',
'pulsecore/tokenizer.h',
'pulsecore/usergroup.h',
'pulsecore/sndfile-util.h',
@ -182,6 +182,7 @@ if host_machine.system() == 'windows'
else
libpulsecommon_sources += [
'pulsecore/mutex-posix.c',
<<<<<<< HEAD
'pulsecore/semaphore-posix.c',
'pulsecore/thread-posix.c'
]
@ -203,10 +204,49 @@ libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
platform_dep, tcpwrap_dep, platform_socket_dep, execinfo_dep,
],
implicit_include_directories : false)
=======
'pulsecore/poll-posix.c',
'pulsecore/thread-posix.c',
]
if host_machine.system() == 'darwin'
libpulsecommon_sources += ['pulsecore/semaphore-osx.c']
else
libpulsecommon_sources += ['pulsecore/semaphore-posix.c']
endif
endif
# FIXME: Do SIMD things
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
if not get_option('client')
libpulsecommon_dep = cc.find_library('pulsecommon-' + pa_version_major_minor, dirs : privlibdir, required : true)
libpulse_dep = dependency('libpulse', required : true)
libpulse_simple_dep = dependency('libpulse-simple', required : true)
else
libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
libpulsecommon_sources,
libpulsecommon_headers,
include_directories : [configinc, topinc],
c_args : [pa_c_args],
link_args : [nodelete_link_args],
install : true,
install_dir : privlibdir,
dependencies : [
libm_dep, thread_dep, dl_dep, shm_dep, iconv_dep, sndfile_dep, dbus_dep,
x11_dep, libsystemd_dep, glib_dep.partial_dependency(compile_args: true),
gtk_dep.partial_dependency(compile_args: true), asyncns_dep, libintl_dep,
platform_dep, platform_socket_dep, execinfo_dep, libatomic_ops_dep,
],
implicit_include_directories : false)
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
subdir('pulse')
endif
<<<<<<< HEAD
subdir('pulse')
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if get_option('daemon')
subdir('pulsecore')
subdir('daemon')

View file

@ -107,13 +107,22 @@ ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1011", ENV{PULSE_PROFILE_SET}="nativ
ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1001", ENV{PULSE_PROFILE_SET}="native-instruments-komplete-audio6.conf"
<<<<<<< HEAD
=======
# This entry is for the Komplete Audio 6 MK2, which has a different ID, but is functionally identical to the Komplete Audio 6.
ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1870", ENV{PULSE_PROFILE_SET}="native-instruments-komplete-audio6.conf"
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1021", ENV{PULSE_PROFILE_SET}="native-instruments-traktor-audio10.conf"
ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{PULSE_PROFILE_SET}="maudio-fasttrack-pro.conf"
ATTRS{idVendor}=="045e", ATTRS{idProduct}=="02bb", ENV{PULSE_PROFILE_SET}="kinect-audio.conf"
ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{PULSE_PROFILE_SET}="sb-omni-surround-5.1.conf"
ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{PULSE_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="402e", ENV{PULSE_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
<<<<<<< HEAD
ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{PULSE_PROFILE_SET}="behringer-umc22.conf"
=======
ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{PULSE_PROFILE_SET}="texas-instruments-pcm2902.conf"
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0269", ENV{PULSE_PROFILE_SET}="hp-tbt-dock-120w-g2.conf"
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0567", ENV{PULSE_PROFILE_SET}="hp-tbt-dock-audio-module.conf"
@ -123,6 +132,11 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1260", ENV{PULSE_PROFILE_SET}="usb-g
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12ad", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
<<<<<<< HEAD
=======
# ID 1038:1282 is for SteelSeries GameDAC
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1282", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
# ID 1038:12c4 is for Arctis 9
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12c4", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# Lucidsound LS31
@ -164,6 +178,19 @@ ATTRS{idVendor}=="1395", ATTRS{idProduct}=="00a0", ENV{PULSE_PROFILE_SET}="sennh
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="005f", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="00a1", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
<<<<<<< HEAD
=======
# Sennheiser GSA 70 wireless USB dongle for GSP 670
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="0089", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# EPOS GSA 70 wireless USB dongle for GSP 670 (Sennheiser GSA 70 with updated firmware)
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="0300", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# Sennheiser GSP 670 USB headset
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="008a", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# Asus Xonar SE
ATTRS{idVendor}=="0b05", ATTRS{idProduct}=="189d", ENV{PULSE_PROFILE_SET}="asus-xonar-se.conf"
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
GOTO="pulseaudio_end"
LABEL="pulseaudio_check_pci"

View file

@ -2838,7 +2838,7 @@ static int path_verify(pa_alsa_path *p) {
if (p->device_port_type == PA_DEVICE_PORT_TYPE_UNKNOWN)
p->device_port_type = map->type;
if (!p->description)
p->description = pa_xstrdup(map->description);
p->description = pa_xstrdup(_(map->description));
}
if (!p->description) {
@ -2851,31 +2851,57 @@ static int path_verify(pa_alsa_path *p) {
return 0;
}
<<<<<<< HEAD
static char *get_path_config_path(const char *paths_dir, const char *fname) {
char *path_config_path;
=======
static char *get_data_path(const char *data_dir, const char *data_type, const char *fname) {
char *result;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
char *dir;
char *data_home;
pa_dynarray *data_dirs;
<<<<<<< HEAD
if (paths_dir) {
path_config_path = pa_maybe_prefix_path(fname, paths_dir);
if (access(path_config_path, R_OK) == 0)
return path_config_path;
else
pa_xfree(path_config_path);
=======
if (data_dir) {
result = pa_maybe_prefix_path(fname, data_dir);
if (access(result, R_OK) == 0)
return result;
else
pa_xfree(result);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
if (pa_run_from_build_tree()) {
<<<<<<< HEAD
path_config_path = pa_maybe_prefix_path(fname, PA_SRCDIR "/modules/alsa/mixer/paths/");
if (access(path_config_path, R_OK) == 0)
return path_config_path;
else
pa_xfree(path_config_path);
=======
dir = pa_sprintf_malloc(PA_SRCDIR "/modules/alsa/mixer/%s/", data_type);
result = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
if (access(result, R_OK) == 0)
return result;
else
pa_xfree(result);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
#endif
if (pa_get_data_home_dir(&data_home) == 0) {
<<<<<<< HEAD
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", data_home);
pa_xfree(data_home);
@ -2886,6 +2912,18 @@ static char *get_path_config_path(const char *paths_dir, const char *fname) {
return path_config_path;
else
pa_xfree(path_config_path);
=======
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "%s", data_home, data_type);
pa_xfree(data_home);
result = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
if (access(result, R_OK) == 0)
return result;
else
pa_xfree(result);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
if (pa_get_data_dirs(&data_dirs) == 0) {
@ -2893,6 +2931,7 @@ static char *get_path_config_path(const char *paths_dir, const char *fname) {
const char *n;
PA_DYNARRAY_FOREACH(n, data_dirs, idx) {
<<<<<<< HEAD
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", n);
path_config_path = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
@ -2903,14 +2942,34 @@ static char *get_path_config_path(const char *paths_dir, const char *fname) {
}
else {
pa_xfree(path_config_path);
=======
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "%s", n, data_type);
result = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
if (access(result, R_OK) == 0) {
pa_dynarray_free(data_dirs);
return result;
}
else {
pa_xfree(result);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
}
pa_dynarray_free(data_dirs);
}
<<<<<<< HEAD
path_config_path = pa_maybe_prefix_path(fname, PA_ALSA_PATHS_DIR);
return path_config_path;
=======
dir = pa_sprintf_malloc(PA_ALSA_DATA_DIR PA_PATH_SEP "%s", data_type);
result = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
return result;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) {
@ -2977,7 +3036,11 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
items[2].data = &p->description;
items[3].data = &mute_during_activation;
<<<<<<< HEAD
fn = get_path_config_path(paths_dir, fname);
=======
fn = get_data_path(paths_dir, "paths", fname);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_log_info("Loading path config: %s", fn);
@ -4971,11 +5034,9 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
if (!fname)
fname = "default.conf";
fn = pa_maybe_prefix_path(fname,
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
pa_run_from_build_tree() ? PA_SRCDIR "/modules/alsa/mixer/profile-sets/" :
#endif
PA_ALSA_PROFILE_SETS_DIR);
fn = get_data_path(NULL, "profile-sets", fname);
pa_log_info("Loading profile set: %s", fn);
r = pa_config_parse(fn, NULL, items, NULL, false, ps);
pa_xfree(fn);
@ -5074,7 +5135,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
handle = pa_alsa_open_by_template(
m->device_strings, dev_id, NULL, &try_ss,
&try_map, mode, &try_period_size,
&try_buffer_size, 0, NULL, NULL, exact_channels);
&try_buffer_size, 0, NULL, NULL, NULL, NULL, exact_channels);
if (handle && !exact_channels && m->channel_map.channels != try_map.channels) {
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,

View file

@ -103,8 +103,8 @@ struct pa_alsa_setting {
/* An entry for one ALSA mixer */
struct pa_alsa_mixer {
struct pa_alsa_mixer *alias;
snd_mixer_t *mixer_handle;
int card_index;
pa_alsa_fdlist *fdl;
bool used_for_probe_only:1;
};
@ -318,7 +318,7 @@ struct pa_alsa_mapping {
pa_sink *sink;
pa_source *source;
/* ucm device context*/
/* ucm device context */
pa_alsa_ucm_mapping_context ucm_context;
};
@ -342,6 +342,9 @@ struct pa_alsa_profile {
pa_idxset *input_mappings;
pa_idxset *output_mappings;
/* ucm device context */
pa_alsa_ucm_profile_context ucm_context;
};
struct pa_alsa_decibel_fix {

View file

@ -52,7 +52,12 @@
#include <pulsecore/thread.h>
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#ifdef USE_SMOOTHER_2
#include <pulsecore/time-smoother_2.h>
#else
#include <pulsecore/time-smoother.h>
#endif
#include <modules/reserve-wrap.h>
@ -78,11 +83,15 @@
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/
#ifdef USE_SMOOTHER_2
#define SMOOTHER_WINDOW_USEC (15*PA_USEC_PER_SEC) /* 15s -- smoother windows size */
#else
#define SMOOTHER_WINDOW_USEC (10*PA_USEC_PER_SEC) /* 10s -- smoother windows size */
#define SMOOTHER_ADJUST_USEC (1*PA_USEC_PER_SEC) /* 1s -- smoother adjust time */
#define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC) /* 2ms -- min smoother update interval */
#define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC) /* 200ms -- max smoother update interval */
#endif
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
@ -156,11 +165,18 @@ struct userdata {
pa_rtpoll_item *alsa_rtpoll_item;
#ifdef USE_SMOOTHER_2
pa_smoother_2 *smoother;
#else
pa_smoother *smoother;
#endif
uint64_t write_count;
uint64_t since_start;
#ifndef USE_SMOOTHER_2
pa_usec_t smoother_interval;
pa_usec_t last_smoother_update;
#endif
pa_idxset *formats;
@ -480,9 +496,13 @@ static void hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*p
/* Reset smoother and counters */
static void reset_vars(struct userdata *u) {
#ifdef USE_SMOOTHER_2
pa_smoother_2_reset(u->smoother, pa_rtclock_now());
#else
pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
u->last_smoother_update = 0;
#endif
u->first = true;
u->since_start = 0;
@ -955,7 +975,10 @@ static void update_smoother(struct userdata *u) {
snd_pcm_sframes_t delay = 0;
int64_t position;
int err;
pa_usec_t now1 = 0, now2;
pa_usec_t now1 = 0;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
snd_pcm_status_t *status;
snd_htimestamp_t htstamp = { 0, 0 };
@ -978,13 +1001,16 @@ static void update_smoother(struct userdata *u) {
if (now1 <= 0)
now1 = pa_rtclock_now();
position = (int64_t) u->write_count - ((int64_t) delay * (int64_t) u->frame_size);
#ifdef USE_SMOOTHER_2
pa_smoother_2_put(u->smoother, now1, position);
#else
/* check if the time since the last update is bigger than the interval */
if (u->last_smoother_update > 0)
if (u->last_smoother_update + u->smoother_interval > now1)
return;
position = (int64_t) u->write_count - ((int64_t) delay * (int64_t) u->frame_size);
if (PA_UNLIKELY(position < 0))
position = 0;
@ -995,18 +1021,26 @@ static void update_smoother(struct userdata *u) {
u->last_smoother_update = now1;
/* exponentially increase the update interval up to the MAX limit */
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
#endif
}
static int64_t sink_get_latency(struct userdata *u) {
int64_t delay;
pa_usec_t now1, now2;
pa_usec_t now1;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_assert(u);
now1 = pa_rtclock_now();
#ifdef USE_SMOOTHER_2
delay = pa_smoother_2_get_delay(u->smoother, now1, u->write_count);
#else
now2 = pa_smoother_get(u->smoother, now1);
delay = (int64_t) pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - (int64_t) now2;
#endif
if (u->memchunk.memblock)
delay += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
@ -1036,7 +1070,11 @@ static void suspend(struct userdata *u) {
if (!u->pcm_handle)
return;
#ifdef USE_SMOOTHER_2
pa_smoother_2_pause(u->smoother, pa_rtclock_now());
#else
pa_smoother_pause(u->smoother, pa_rtclock_now());
#endif
/* Close PCM device */
close_pcm(u);
@ -1683,7 +1721,7 @@ static int sink_set_port_ucm_cb(pa_sink *s, pa_device_port *p) {
else
sync_mixer(u, p);
return pa_alsa_ucm_set_port(u->ucm_context, p, true);
return pa_alsa_ucm_set_port(u->ucm_context, p);
}
static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
@ -1784,12 +1822,22 @@ static void sink_reconfigure_cb(pa_sink *s, pa_sample_spec *spec, bool passthrou
int i;
bool format_supported = false;
bool rate_supported = false;
#ifdef USE_SMOOTHER_2
pa_sample_spec effective_spec;
#endif
pa_assert(u);
#ifdef USE_SMOOTHER_2
effective_spec.channels = s->sample_spec.channels;
#endif
for (i = 0; u->supported_formats[i] != PA_SAMPLE_MAX; i++) {
if (u->supported_formats[i] == spec->format) {
pa_sink_set_sample_format(u->sink, spec->format);
#ifdef USE_SMOOTHER_2
effective_spec.format = spec->format;
#endif
format_supported = true;
break;
}
@ -1799,11 +1847,17 @@ static void sink_reconfigure_cb(pa_sink *s, pa_sample_spec *spec, bool passthrou
pa_log_info("Sink does not support sample format of %s, set it to a verified value",
pa_sample_format_to_string(spec->format));
pa_sink_set_sample_format(u->sink, u->verified_sample_spec.format);
#ifdef USE_SMOOTHER_2
effective_spec.format = u->verified_sample_spec.format;
#endif
}
for (i = 0; u->supported_rates[i]; i++) {
if (u->supported_rates[i] == spec->rate) {
pa_sink_set_sample_rate(u->sink, spec->rate);
#ifdef USE_SMOOTHER_2
effective_spec.rate = spec->rate;
#endif
rate_supported = true;
break;
}
@ -1812,8 +1866,15 @@ static void sink_reconfigure_cb(pa_sink *s, pa_sample_spec *spec, bool passthrou
if (!rate_supported) {
pa_log_info("Sink does not support sample rate of %u, set it to a verified value", spec->rate);
pa_sink_set_sample_rate(u->sink, u->verified_sample_spec.rate);
#ifdef USE_SMOOTHER_2
effective_spec.rate = u->verified_sample_spec.rate;
#endif
}
#ifdef USE_SMOOTHER_2
pa_smoother_2_set_sample_spec(u->smoother, pa_rtclock_now(), &effective_spec);
#endif
/* Passthrough status change is handled during unsuspend */
}
@ -1947,7 +2008,11 @@ static void thread_func(void *userdata) {
pa_log_info("Starting playback.");
snd_pcm_start(u->pcm_handle);
#ifdef USE_SMOOTHER_2
pa_smoother_2_resume(u->smoother, pa_rtclock_now());
#else
pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
#endif
u->first = false;
}
@ -1981,7 +2046,11 @@ static void thread_func(void *userdata) {
/* Convert from the sound card time domain to the
* system time domain */
#ifdef USE_SMOOTHER_2
cusec = pa_smoother_2_translate(u->smoother, sleep_usec);
#else
cusec = pa_smoother_translate(u->smoother, pa_rtclock_now(), sleep_usec);
#endif
#ifdef DEBUG_TIMING
pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
@ -2170,7 +2239,7 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) {
* will be NULL, but the UCM device enable sequence will still need to be
* executed. */
if (u->sink->active_port && u->ucm_context) {
if (pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0)
if (pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port) < 0)
return -1;
}
@ -2281,7 +2350,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
bool volume_is_set;
bool mute_is_set;
pa_alsa_profile_set *profile_set = NULL;
<<<<<<< HEAD
void *state;
=======
void *state = NULL;
#ifdef USE_SMOOTHER_2
snd_pcm_info_t* pcm_info;
const char *id;
#endif
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_assert(m);
pa_assert(ma);
@ -2394,6 +2471,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
#ifndef USE_SMOOTHER_2
u->smoother = pa_smoother_new(
SMOOTHER_ADJUST_USEC,
SMOOTHER_WINDOW_USEC,
@ -2403,6 +2481,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_rtclock_now(),
true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
#endif
/* use ucm */
if (mapping && mapping->ucm_context.ucm)
@ -2452,7 +2531,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, mapping)))
&b, &d,
&u->supported_formats, &u->supported_rates,
mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
@ -2466,7 +2547,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, profile_set, &mapping)))
&b, &d,
&u->supported_formats, &u->supported_rates,
profile_set, &mapping)))
goto fail;
} else {
@ -2477,7 +2560,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, false)))
&b, &d,
&u->supported_formats, &u->supported_rates,
false)))
goto fail;
}
@ -2523,13 +2608,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->verified_sample_spec = ss;
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
if (!u->supported_formats) {
pa_log_error("Failed to find any supported sample formats.");
goto fail;
}
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
if (!u->supported_rates) {
pa_log_error("Failed to find any supported sample rates.");
goto fail;
@ -2613,6 +2696,25 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
goto fail;
}
#ifdef USE_SMOOTHER_2
u->smoother = pa_smoother_2_new(SMOOTHER_WINDOW_USEC, pa_rtclock_now(), frame_size, u->sink->sample_spec.rate);
/* Check if this is an USB device, see alsa-util.c
* USB devices unfortunately need some special handling */
snd_pcm_info_alloca(&pcm_info);
if (snd_pcm_info(u->pcm_handle, pcm_info) == 0 &&
(id = snd_pcm_info_get_id(pcm_info))) {
if (pa_streq(id, "USB Audio")) {
uint32_t hack_threshold;
/* USB device, set hack parameter */
hack_threshold = 2000;
if (!u->use_tsched)
hack_threshold = 1000;
pa_smoother_2_usb_hack_enable(u->smoother, true, hack_threshold);
}
}
#endif
if (u->ucm_context) {
pa_device_port *port;
unsigned h_prio = 0;
@ -2816,7 +2918,11 @@ static void userdata_free(struct userdata *u) {
pa_hashmap_free(u->mixers);
if (u->smoother)
#ifdef USE_SMOOTHER_2
pa_smoother_2_free(u->smoother);
#else
pa_smoother_free(u->smoother);
#endif
if (u->formats)
pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);

View file

@ -47,7 +47,12 @@
#include <pulsecore/thread.h>
#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
#ifdef USE_SMOOTHER_2
#include <pulsecore/time-smoother_2.h>
#else
#include <pulsecore/time-smoother.h>
#endif
#include <modules/reserve-wrap.h>
@ -71,11 +76,15 @@
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */
#ifdef USE_SMOOTHER_2
#define SMOOTHER_WINDOW_USEC (15*PA_USEC_PER_SEC) /* 15s */
#else
#define SMOOTHER_WINDOW_USEC (10*PA_USEC_PER_SEC) /* 10s */
#define SMOOTHER_ADJUST_USEC (1*PA_USEC_PER_SEC) /* 1s */
#define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC) /* 2ms */
#define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC) /* 200ms */
#endif
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100)
@ -140,10 +149,17 @@ struct userdata {
pa_rtpoll_item *alsa_rtpoll_item;
#ifdef USE_SMOOTHER_2
pa_smoother_2 *smoother;
#else
pa_smoother *smoother;
#endif
uint64_t read_count;
#ifndef USE_SMOOTHER_2
pa_usec_t smoother_interval;
pa_usec_t last_smoother_update;
#endif
pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot;
@ -452,9 +468,13 @@ static void hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*p
/* Reset smoother and counters */
static void reset_vars(struct userdata *u) {
#ifdef USE_SMOOTHER_2
pa_smoother_2_reset(u->smoother, pa_rtclock_now());
#else
pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
u->last_smoother_update = 0;
#endif
u->read_count = 0;
u->first = true;
@ -462,7 +482,12 @@ static void reset_vars(struct userdata *u) {
/* Called from IO context */
static void close_pcm(struct userdata *u) {
#ifdef USE_SMOOTHER_2
pa_smoother_2_pause(u->smoother, pa_rtclock_now());
#else
pa_smoother_pause(u->smoother, pa_rtclock_now());
#endif
/* Let's suspend */
snd_pcm_close(u->pcm_handle);
@ -877,7 +902,10 @@ static void update_smoother(struct userdata *u) {
snd_pcm_sframes_t delay = 0;
uint64_t position;
int err;
pa_usec_t now1 = 0, now2;
pa_usec_t now1 = 0;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
snd_pcm_status_t *status;
snd_htimestamp_t htstamp = { 0, 0 };
@ -900,12 +928,16 @@ static void update_smoother(struct userdata *u) {
if (now1 <= 0)
now1 = pa_rtclock_now();
position = u->read_count + ((uint64_t) delay * (uint64_t) u->frame_size);
#ifdef USE_SMOOTHER_2
pa_smoother_2_put(u->smoother, now1, position);
#else
/* check if the time since the last update is bigger than the interval */
if (u->last_smoother_update > 0)
if (u->last_smoother_update + u->smoother_interval > now1)
return;
position = u->read_count + ((uint64_t) delay * (uint64_t) u->frame_size);
now2 = pa_bytes_to_usec(position, &u->source->sample_spec);
pa_smoother_put(u->smoother, now1, now2);
@ -913,18 +945,27 @@ static void update_smoother(struct userdata *u) {
u->last_smoother_update = now1;
/* exponentially increase the update interval up to the MAX limit */
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
#endif
}
static int64_t source_get_latency(struct userdata *u) {
int64_t delay;
pa_usec_t now1, now2;
pa_usec_t now1;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_assert(u);
now1 = pa_rtclock_now();
#ifdef USE_SMOOTHER_2
delay = - pa_smoother_2_get_delay(u->smoother, now1, u->read_count);
#else
now2 = pa_smoother_get(u->smoother, now1);
delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec(u->read_count, &u->source->sample_spec);
#endif
return delay;
}
@ -1554,7 +1595,7 @@ static int source_set_port_ucm_cb(pa_source *s, pa_device_port *p) {
else
sync_mixer(u, p);
return pa_alsa_ucm_set_port(u->ucm_context, p, false);
return pa_alsa_ucm_set_port(u->ucm_context, p);
}
static int source_set_port_cb(pa_source *s, pa_device_port *p) {
@ -1596,12 +1637,22 @@ static void source_reconfigure_cb(pa_source *s, pa_sample_spec *spec, bool passt
int i;
bool format_supported = false;
bool rate_supported = false;
#ifdef USE_SMOOTHER_2
pa_sample_spec effective_spec;
#endif
pa_assert(u);
#ifdef USE_SMOOTHER_2
effective_spec.channels = s->sample_spec.channels;
#endif
for (i = 0; u->supported_formats[i] != PA_SAMPLE_MAX; i++) {
if (u->supported_formats[i] == spec->format) {
pa_source_set_sample_format(u->source, spec->format);
#ifdef USE_SMOOTHER_2
effective_spec.format = spec->format;
#endif
format_supported = true;
break;
}
@ -1611,11 +1662,17 @@ static void source_reconfigure_cb(pa_source *s, pa_sample_spec *spec, bool passt
pa_log_info("Source does not support sample format of %s, set it to a verified value",
pa_sample_format_to_string(spec->format));
pa_source_set_sample_format(u->source, u->verified_sample_spec.format);
#ifdef USE_SMOOTHER_2
effective_spec.format = u->verified_sample_spec.format;
#endif
}
for (i = 0; u->supported_rates[i]; i++) {
if (u->supported_rates[i] == spec->rate) {
pa_source_set_sample_rate(u->source, spec->rate);
#ifdef USE_SMOOTHER_2
effective_spec.rate = spec->rate;
#endif
rate_supported = true;
break;
}
@ -1624,7 +1681,15 @@ static void source_reconfigure_cb(pa_source *s, pa_sample_spec *spec, bool passt
if (!rate_supported) {
pa_log_info("Source does not support sample rate of %u, set it to a verfied value", spec->rate);
pa_source_set_sample_rate(u->source, u->verified_sample_spec.rate);
#ifdef USE_SMOOTHER_2
effective_spec.rate = u->verified_sample_spec.rate;
#endif
}
#ifdef USE_SMOOTHER_2
pa_smoother_2_set_sample_spec(u->smoother, pa_rtclock_now(), &effective_spec);
#endif
}
static void thread_func(void *userdata) {
@ -1658,7 +1723,11 @@ static void thread_func(void *userdata) {
pa_log_info("Starting capture.");
snd_pcm_start(u->pcm_handle);
#ifdef USE_SMOOTHER_2
pa_smoother_2_resume(u->smoother, pa_rtclock_now());
#else
pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
#endif
u->first = false;
}
@ -1686,7 +1755,11 @@ static void thread_func(void *userdata) {
/* Convert from the sound card time domain to the
* system time domain */
#ifdef USE_SMOOTHER_2
cusec = pa_smoother_2_translate(u->smoother, sleep_usec);
#else
cusec = pa_smoother_translate(u->smoother, pa_rtclock_now(), sleep_usec);
#endif
/* pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
@ -1870,7 +1943,7 @@ static int setup_mixer(struct userdata *u, bool ignore_dB) {
* will be NULL, but the UCM device enable sequence will still need to be
* executed. */
if (u->source->active_port && u->ucm_context) {
if (pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0)
if (pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port) < 0)
return -1;
}
@ -2085,6 +2158,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
goto fail;
}
#ifndef USE_SMOOTHER_2
u->smoother = pa_smoother_new(
SMOOTHER_ADJUST_USEC,
SMOOTHER_WINDOW_USEC,
@ -2094,6 +2168,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_rtclock_now(),
true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
#endif
/* use ucm */
if (mapping && mapping->ucm_context.ucm)
@ -2143,7 +2218,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, mapping)))
&b, &d, &u->supported_formats, &u->supported_rates, mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
@ -2157,7 +2232,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, profile_set, &mapping)))
&b, &d, &u->supported_formats, &u->supported_rates, profile_set, &mapping)))
goto fail;
} else {
@ -2168,7 +2243,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
&b, &d, false)))
&b, &d, &u->supported_formats, &u->supported_rates, false)))
goto fail;
}
@ -2204,13 +2279,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->verified_sample_spec = ss;
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
if (!u->supported_formats) {
pa_log_error("Failed to find any supported sample formats.");
goto fail;
}
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
if (!u->supported_rates) {
pa_log_error("Failed to find any supported sample rates.");
goto fail;
@ -2293,6 +2366,10 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
goto fail;
}
#ifdef USE_SMOOTHER_2
u->smoother = pa_smoother_2_new(SMOOTHER_WINDOW_USEC, pa_rtclock_now(), frame_size, u->source->sample_spec.rate);
#endif
if (u->ucm_context) {
pa_device_port *port;
unsigned h_prio = 0;
@ -2454,7 +2531,11 @@ static void userdata_free(struct userdata *u) {
pa_hashmap_free(u->mixers);
if (u->smoother)
#ifdef USE_SMOOTHER_2
pa_smoother_2_free(u->smoother);
#else
pa_smoother_free(u->smoother);
#endif
if (u->supported_formats)
pa_xfree(u->supported_formats);

File diff suppressed because it is too large Load diff

View file

@ -140,12 +140,13 @@ typedef struct pa_alsa_ucm_modifier pa_alsa_ucm_modifier;
typedef struct pa_alsa_ucm_device pa_alsa_ucm_device;
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
typedef struct pa_alsa_ucm_mapping_context pa_alsa_ucm_mapping_context;
typedef struct pa_alsa_ucm_profile_context pa_alsa_ucm_profile_context;
typedef struct pa_alsa_ucm_port_data pa_alsa_ucm_port_data;
typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
pa_alsa_profile_set* pa_alsa_ucm_add_profile_set(pa_alsa_ucm_config *ucm, pa_channel_map *default_channel_map);
int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, const char *new_profile, const char *old_profile);
int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, pa_alsa_profile *new_profile, pa_alsa_profile *old_profile);
int pa_alsa_ucm_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb);
@ -157,14 +158,14 @@ void pa_alsa_ucm_add_ports(
pa_card *card,
snd_pcm_t *pcm_handle,
bool ignore_dB);
void pa_alsa_ucm_add_ports_combination(
void pa_alsa_ucm_add_port(
pa_hashmap *hash,
pa_alsa_ucm_mapping_context *context,
bool is_sink,
pa_hashmap *ports,
pa_card_profile *cp,
pa_core *core);
int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, bool is_sink);
int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port);
void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm);
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
@ -221,11 +222,8 @@ struct pa_alsa_ucm_modifier {
pa_proplist *proplist;
int n_confdev;
int n_suppdev;
const char **conflicting_devices;
const char **supported_devices;
pa_idxset *conflicting_devices;
pa_idxset *supported_devices;
pa_direction_t action_direction;
@ -253,6 +251,7 @@ struct pa_alsa_ucm_config {
pa_core *core;
snd_use_case_mgr_t *ucm_mgr;
pa_alsa_ucm_verb *active_verb;
char *alib_prefix;
pa_hashmap *mixers;
PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
@ -263,21 +262,23 @@ struct pa_alsa_ucm_mapping_context {
pa_alsa_ucm_config *ucm;
pa_direction_t direction;
pa_idxset *ucm_devices;
pa_idxset *ucm_modifiers;
pa_alsa_ucm_device *ucm_device;
pa_alsa_ucm_modifier *ucm_modifier;
};
struct pa_alsa_ucm_profile_context {
pa_alsa_ucm_verb *verb;
};
struct pa_alsa_ucm_port_data {
pa_alsa_ucm_config *ucm;
pa_device_port *core_port;
/* A single port will be associated with multiple devices if it represents
* a combination of devices. */
pa_dynarray *devices; /* pa_alsa_ucm_device */
pa_alsa_ucm_device *device;
/* profile name -> pa_alsa_path for volume control */
/* verb name -> pa_alsa_path for volume control */
pa_hashmap *paths;
/* Current path, set when activating profile */
/* Current path, set when activating verb */
pa_alsa_path *path;
/* ELD info */

View file

@ -40,6 +40,7 @@
#include <pulsecore/thread.h>
#include <pulsecore/conf-parser.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/strbuf.h>
#include "alsa-util.h"
#include "alsa-mixer.h"
@ -522,6 +523,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
pa_sample_format_t **query_supported_formats,
unsigned int **query_supported_rates,
pa_alsa_profile_set *ps,
pa_alsa_mapping **mapping) {
@ -560,6 +563,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
query_supported_formats,
query_supported_rates,
m);
if (pcm_handle) {
@ -587,6 +592,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
query_supported_formats,
query_supported_rates,
m);
if (pcm_handle) {
@ -611,6 +618,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
query_supported_formats,
query_supported_rates,
false);
pa_xfree(d);
@ -631,6 +640,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
pa_sample_format_t **query_supported_formats,
unsigned int **query_supported_rates,
pa_alsa_mapping *m) {
snd_pcm_t *pcm_handle;
@ -660,6 +671,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
tsched_size,
use_mmap,
use_tsched,
query_supported_formats,
query_supported_rates,
pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
if (!pcm_handle)
@ -683,6 +696,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
pa_sample_format_t **query_supported_formats,
unsigned int **query_supported_rates,
bool require_exact_channel_number) {
int err;
@ -710,6 +725,12 @@ snd_pcm_t *pa_alsa_open_by_device_string(
pa_log_debug("Managed to open %s", d);
if (query_supported_formats)
*query_supported_formats = pa_alsa_get_supported_formats(pcm_handle, ss->format);
if (query_supported_rates)
*query_supported_rates = pa_alsa_get_supported_rates(pcm_handle, ss->rate);
if ((err = pa_alsa_set_hw_params(
pcm_handle,
ss,
@ -783,6 +804,8 @@ snd_pcm_t *pa_alsa_open_by_template(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
pa_sample_format_t **query_supported_formats,
unsigned int **query_supported_rates,
bool require_exact_channel_number) {
snd_pcm_t *pcm_handle;
@ -804,6 +827,8 @@ snd_pcm_t *pa_alsa_open_by_template(
tsched_size,
use_mmap,
use_tsched,
query_supported_formats,
query_supported_rates,
require_exact_channel_number);
pa_xfree(d);
@ -1406,13 +1431,31 @@ char *pa_alsa_get_reserve_name(const char *device) {
return pa_sprintf_malloc("Audio%i", i);
}
static void dump_supported_rates(unsigned int* values)
{
pa_strbuf *buf;
char *str;
int i;
buf = pa_strbuf_new();
for (i = 0; values[i]; i++) {
pa_strbuf_printf(buf, " %u", values[i]);
}
str = pa_strbuf_to_string_free(buf);
pa_log_debug("Supported rates:%s", str);
pa_xfree(str);
}
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
static unsigned int all_rates[] = { 8000, 11025, 12000,
16000, 22050, 24000,
32000, 44100, 48000,
64000, 88200, 96000,
128000, 176400, 192000,
384000 };
352800, 384000,
705600, 768000 };
bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
snd_pcm_hw_params_t *hwparams;
unsigned int i, j, n, *rates = NULL;
@ -1454,39 +1497,40 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
rates[1] = 0;
}
dump_supported_rates(rates);
return rates;
}
pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
static const snd_pcm_format_t format_trans_to_pa[] = {
[SND_PCM_FORMAT_U8] = PA_SAMPLE_U8,
[SND_PCM_FORMAT_A_LAW] = PA_SAMPLE_ALAW,
[SND_PCM_FORMAT_MU_LAW] = PA_SAMPLE_ULAW,
[SND_PCM_FORMAT_S16_LE] = PA_SAMPLE_S16LE,
[SND_PCM_FORMAT_S16_BE] = PA_SAMPLE_S16BE,
[SND_PCM_FORMAT_FLOAT_LE] = PA_SAMPLE_FLOAT32LE,
[SND_PCM_FORMAT_FLOAT_BE] = PA_SAMPLE_FLOAT32BE,
[SND_PCM_FORMAT_S32_LE] = PA_SAMPLE_S32LE,
[SND_PCM_FORMAT_S32_BE] = PA_SAMPLE_S32BE,
[SND_PCM_FORMAT_S24_3LE] = PA_SAMPLE_S24LE,
[SND_PCM_FORMAT_S24_3BE] = PA_SAMPLE_S24BE,
[SND_PCM_FORMAT_S24_LE] = PA_SAMPLE_S24_32LE,
[SND_PCM_FORMAT_S24_BE] = PA_SAMPLE_S24_32BE,
static const snd_pcm_format_t format_trans_to_pcm[] = {
[PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
[PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
[PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
[PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
[PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
[PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
[PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
[PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
[PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
[PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
[PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
[PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
[PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
};
static const snd_pcm_format_t all_formats[] = {
SND_PCM_FORMAT_U8,
SND_PCM_FORMAT_A_LAW,
SND_PCM_FORMAT_MU_LAW,
SND_PCM_FORMAT_S16_LE,
SND_PCM_FORMAT_S16_BE,
SND_PCM_FORMAT_FLOAT_LE,
SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_S32_LE,
SND_PCM_FORMAT_S32_BE,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE,
static const pa_sample_format_t all_formats[] = {
PA_SAMPLE_U8,
PA_SAMPLE_ALAW,
PA_SAMPLE_ULAW,
PA_SAMPLE_S16LE,
PA_SAMPLE_S16BE,
PA_SAMPLE_FLOAT32LE,
PA_SAMPLE_FLOAT32BE,
PA_SAMPLE_S32LE,
PA_SAMPLE_S32BE,
PA_SAMPLE_S24LE,
PA_SAMPLE_S24BE,
PA_SAMPLE_S24_32LE,
PA_SAMPLE_S24_32BE,
};
bool supported[PA_ELEMENTSOF(all_formats)] = {
false,
@ -1504,7 +1548,7 @@ pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_form
}
for (i = 0, n = 0; i < PA_ELEMENTSOF(all_formats); i++) {
if (snd_pcm_hw_params_test_format(pcm, hwparams, all_formats[i]) == 0) {
if (snd_pcm_hw_params_test_format(pcm, hwparams, format_trans_to_pcm[all_formats[i]]) == 0) {
supported[i] = true;
n++;
}
@ -1515,7 +1559,7 @@ pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_form
for (i = 0, j = 0; i < PA_ELEMENTSOF(all_formats); i++) {
if (supported[i])
formats[j++] = format_trans_to_pa[all_formats[i]];
formats[j++] = all_formats[i];
}
formats[j] = PA_SAMPLE_MAX;
@ -1523,7 +1567,7 @@ pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_form
formats = pa_xnew(pa_sample_format_t, 2);
formats[0] = fallback_format;
if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pa[formats[0]])) < 0) {
if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pcm[formats[0]])) < 0) {
pa_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret));
pa_xfree(formats);
return NULL;
@ -1614,14 +1658,16 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
snd_ctl_elem_iface_t iface,
const char *name,
unsigned int index,
unsigned int device) {
unsigned int device,
unsigned int subdevice) {
snd_mixer_elem_t *elem;
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
snd_hctl_elem_t *helem;
snd_hctl_elem_t **_helem, *helem;
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
continue;
helem = snd_mixer_elem_get_private(elem);
_helem = snd_mixer_elem_get_private(elem);
helem = *_helem;
if (snd_hctl_elem_get_interface(helem) != iface)
continue;
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
@ -1630,17 +1676,23 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
continue;
if (snd_hctl_elem_get_device(helem) != device)
continue;
if (snd_hctl_elem_get_subdevice(helem) != subdevice)
continue;
return elem;
}
return NULL;
}
snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
<<<<<<< HEAD
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
=======
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device, 0);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device);
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device, 0);
}
static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
@ -1649,31 +1701,79 @@ static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_
return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1);
}
static void mixer_melem_free(snd_mixer_elem_t *elem)
{
snd_hctl_elem_t **_helem;
_helem = snd_mixer_elem_get_private(elem);
pa_xfree(_helem);
}
static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
{
int err;
const char *name = snd_hctl_elem_get_name(helem);
if (mask & SND_CTL_EVENT_MASK_ADD) {
snd_hctl_elem_t **_helem;
/* NOTE: The remove event is defined as '~0U`. */
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
/* NOTE: Unless we remove the pointer to melem from the linked-list at
* private_data of helem, an assertion will be hit in alsa-lib since
* the list is not empty. */
_helem = snd_mixer_elem_get_private(melem);
*_helem = NULL;
snd_mixer_elem_detach(melem, helem);
} else if (mask & SND_CTL_EVENT_MASK_ADD) {
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
if (iface == SND_CTL_ELEM_IFACE_CARD || iface == SND_CTL_ELEM_IFACE_PCM) {
snd_mixer_t *mixer = snd_mixer_class_get_mixer(class);
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
const char *name = snd_hctl_elem_get_name(helem);
const int index = snd_hctl_elem_get_index(helem);
const int device = snd_hctl_elem_get_device(helem);
const int subdevice = snd_hctl_elem_get_subdevice(helem);
snd_mixer_elem_t *new_melem;
bool found = true;
/* Put the hctl pointer as our private data - it will be useful for callbacks */
if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) {
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
return 0;
new_melem = pa_alsa_mixer_find(mixer, iface, name, index, device, subdevice);
if (!new_melem) {
_helem = pa_xmalloc(sizeof(snd_hctl_elem_t *));
*_helem = helem;
/* Put the hctl pointer as our private data - it will be useful for callbacks */
if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, _helem, mixer_melem_free)) < 0) {
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
return 0;
}
found = false;
} else {
_helem = snd_mixer_elem_get_private(new_melem);
if (_helem) {
char *s1, *s2;
snd_ctl_elem_id_t *id1, *id2;
snd_ctl_elem_id_alloca(&id1);
snd_ctl_elem_id_alloca(&id2);
snd_hctl_elem_get_id(helem, id1);
snd_hctl_elem_get_id(*_helem, id2);
s1 = snd_ctl_ascii_elem_id_get(id1);
s2 = snd_ctl_ascii_elem_id_get(id2);
pa_log_warn("mixer_class_event - duplicate mixer controls: %s | %s", s1, s2);
free(s2);
free(s1);
return 0;
}
*_helem = helem;
}
if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
snd_mixer_elem_free(melem);
snd_mixer_elem_free(melem);
return 0;
}
if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
return 0;
if (!found) {
if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
return 0;
}
}
}
}
@ -1687,14 +1787,14 @@ static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
return 0;
}
static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t *hctl) {
int err;
snd_mixer_class_t *class;
pa_assert(mixer);
pa_assert(dev);
if ((err = snd_mixer_attach(mixer, dev)) < 0) {
if ((err = snd_mixer_attach_hctl(mixer, hctl)) < 0) {
pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
return -1;
}
@ -1733,17 +1833,30 @@ snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool pr
return m;
}
pa_alsa_mixer *pa_alsa_create_mixer(pa_hashmap *mixers, const char *dev, snd_mixer_t *m, bool probe) {
pa_alsa_mixer *pm;
pm = pa_xnew0(pa_alsa_mixer, 1);
if (pm == NULL)
return NULL;
pm->used_for_probe_only = probe;
pm->mixer_handle = m;
pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
return pm;
}
snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) {
int err;
snd_mixer_t *m;
snd_hctl_t *hctl;
pa_alsa_mixer *pm;
char *dev2;
void *state;
pa_assert(mixers);
pa_assert(dev);
pm = pa_hashmap_get(mixers, dev);
<<<<<<< HEAD
/* The quick card number/index lookup (hw:#)
* We already know the card number/index, thus use the mixer
@ -1764,6 +1877,8 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
}
}
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (pm) {
if (!probe)
pm->used_for_probe_only = false;
@ -1775,27 +1890,55 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
return NULL;
}
if (prepare_mixer(m, dev) >= 0) {
pm = pa_xnew0(pa_alsa_mixer, 1);
if (pm) {
snd_hctl_t *hctl;
pm->card_index = -1;
/* determine the ALSA card number (index) and store it to card_index */
err = snd_mixer_get_hctl(m, dev, &hctl);
if (err >= 0) {
snd_ctl_card_info_t *info;
snd_ctl_card_info_alloca(&info);
err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
if (err >= 0)
pm->card_index = snd_ctl_card_info_get_card(info);
}
pm->used_for_probe_only = probe;
pm->mixer_handle = m;
pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
return m;
}
err = snd_hctl_open(&hctl, dev, 0);
if (err < 0) {
pa_log("Error opening hctl device: %s", pa_alsa_strerror(err));
goto __close;
}
if (prepare_mixer(m, dev, hctl) >= 0) {
/* get the ALSA card number (index) and ID (alias) and create two identical mixers */
char *p, *dev2, *dev_idx, *dev_id;
snd_ctl_card_info_t *info;
snd_ctl_card_info_alloca(&info);
err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
if (err < 0)
goto __std;
dev2 = pa_xstrdup(dev);
if (dev2 == NULL)
goto __close;
p = strchr(dev2, ':');
/* sanity check - only hw: devices */
if (p == NULL || (p - dev2) < 2 || !pa_strneq(p - 2, "hw:", 3)) {
pa_xfree(dev2);
goto __std;
}
*p = '\0';
dev_idx = pa_sprintf_malloc("%s:%u", dev2, snd_ctl_card_info_get_card(info));
dev_id = pa_sprintf_malloc("%s:%s", dev2, snd_ctl_card_info_get_id(info));
pa_log_debug("ALSA alias mixers: %s = %s", dev_idx, dev_id);
if (dev_idx && dev_id && (strcmp(dev, dev_idx) == 0 || strcmp(dev, dev_id) == 0)) {
pm = pa_alsa_create_mixer(mixers, dev_idx, m, probe);
if (pm) {
pa_alsa_mixer *pm2;
pm2 = pa_alsa_create_mixer(mixers, dev_id, m, probe);
if (pm2) {
pm->alias = pm2;
pm2->alias = pm;
}
}
}
pa_xfree(dev_id);
pa_xfree(dev_idx);
pa_xfree(dev2);
__std:
if (pm == NULL)
pm = pa_alsa_create_mixer(mixers, dev, m, probe);
if (pm)
return m;
}
__close:
snd_mixer_close(m);
return NULL;
}
@ -1836,8 +1979,10 @@ void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
{
if (mixer->fdl)
pa_alsa_fdlist_free(mixer->fdl);
if (mixer->mixer_handle)
if (mixer->mixer_handle && mixer->alias == NULL)
snd_mixer_close(mixer->mixer_handle);
if (mixer->alias)
mixer->alias->alias = NULL;
pa_xfree(mixer);
}

View file

@ -67,6 +67,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* modified at return */
bool *use_tsched, /* modified at return */
pa_sample_format_t **query_supported_formats, /* modified at return */
unsigned int **query_supported_rates, /* modified at return */
pa_alsa_profile_set *ps,
pa_alsa_mapping **mapping); /* modified at return */
@ -82,6 +84,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* modified at return */
bool *use_tsched, /* modified at return */
pa_sample_format_t **query_supported_formats, /* modified at return */
unsigned int **query_supported_rates, /* modified at return */
pa_alsa_mapping *mapping);
/* Opens the explicit ALSA device */
@ -96,6 +100,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* modified at return */
bool *use_tsched, /* modified at return */
pa_sample_format_t **query_supported_formats, /* modified at return */
unsigned int **query_supported_rates, /* modified at return */
bool require_exact_channel_number);
/* Opens the explicit ALSA device with a fallback list */
@ -111,6 +117,8 @@ snd_pcm_t *pa_alsa_open_by_template(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* modified at return */
bool *use_tsched, /* modified at return */
pa_sample_format_t **query_supported_formats, /* modified at return */
unsigned int **query_supported_rates, /* modified at return */
bool require_exact_channel_number);
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);

View file

@ -0,0 +1,91 @@
# 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.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, see <http://www.gnu.org/licenses/>.
; ASUS Xonar SE card.
; This card has two devices for each rear and front panel jacks.
;
; See default.conf for an explanation on the directives used here.
[General]
auto-profiles = yes
[Mapping analog-stereo-headset]
device-strings = hw:%f,1
channel-map = left,right
paths-output = analog-output analog-output-headphones
paths-input = analog-input-mic analog-input-headphone-mic analog-input-headset-mic
priority = 15
[Mapping analog-stereo]
device-strings = hw:%f,0
channel-map = left,right
paths-output = analog-output analog-output-speaker
paths-input = analog-input analog-input-mic analog-input-linein
priority = 14
[Mapping analog-surround-21]
device-strings = surround21:%f
channel-map = front-left,front-right,lfe
paths-output = analog-output-speaker
priority = 13
direction = output
[Mapping analog-surround-40]
device-strings = surround40:%f
channel-map = front-left,front-right,rear-left,rear-right
paths-output = analog-output-speaker
priority = 12
direction = output
[Mapping analog-surround-41]
device-strings = surround41:%f
channel-map = front-left,front-right,rear-left,rear-right,lfe
paths-output = analog-output-speaker
priority = 13
direction = output
[Mapping analog-surround-50]
device-strings = surround50:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center
paths-output = analog-output-speaker
priority = 12
direction = output
[Mapping analog-surround-51]
device-strings = surround51:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
paths-output = analog-output-speaker
priority = 13
direction = output
[Mapping iec958-stereo]
device-strings = iec958:%f
channel-map = left,right
paths-output = iec958-stereo-output
priority = 5
[Mapping iec958-ac3-surround-40]
device-strings = a52:%f
channel-map = front-left,front-right,rear-left,rear-right
paths-output = iec958-stereo-output
priority = 2
direction = output
[Mapping iec958-ac3-surround-51]
device-strings = a52:%f
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
paths-output = iec958-stereo-output
priority = 3
direction = output

View file

@ -39,7 +39,11 @@ channel-map = aux0,aux1,left,right,aux2,aux3
direction = output
[Mapping stereo-out-ef]
<<<<<<< HEAD
description = Analog Stereo 5/6
=======
description = Stereo 5/6 (S/PDIF)
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
device-strings = hw:%f,0,0
channel-map = aux0,aux1,aux2,aux3,left,right
direction = output
@ -51,7 +55,11 @@ channel-map = mono,aux0,aux1,aux2,aux3,aux4
direction = input
[Mapping analog-mono-in-b]
<<<<<<< HEAD
description = Anlog Mono Input 2
=======
description = Analog Mono Input 2
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
device-strings = hw:%f,0,0
channel-map = aux0,mono,aux1,aux2,aux3,aux4
direction = input
@ -69,7 +77,11 @@ channel-map = aux0,aux1,left,right,aux2,aux3
direction = input
[Mapping stereo-in-ef]
<<<<<<< HEAD
description = Stereo Input 5/6
=======
description = Stereo Input 5/6 (S/PDIF)
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
device-strings = hw:%f,0,0
channel-map = aux0,aux1,aux2,aux3,left,right
direction = input

View file

@ -0,0 +1,75 @@
# 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.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, see <http://www.gnu.org/licenses/>.
; Texas Instruments PCM2902
;
; This is a generic chip used in multiple products, including at least
; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and
; some unbranded "usb mini microphone".
;
; Behringer UMC22 has stereo input (representing two physical mono inputs),
; others have mono input.
;
; Some devices have a mic input path, but at least Behringer Xenyx 302USB
; doesn't have any input mixer controls.
;
; Since the UMC22 card has only stereo input PCM device but is commonly used
; with mono mics, we define special mono mappings using "mono,aux1" and
; "aux1,mono" channel maps. If we had only had the standard stereo input
; mapping, the user would have to record stereo tracks with one channel silent,
; which would be inconvenient.
;
; This config also removes default digital input/output mappings that do
; not physically exist on cards that we've seen so far.
;
; Originally added by Nazar Mokrynskyi <nazar@mokrynskyi.com> for Behringer
; UMC22.
[General]
auto-profiles = yes
[Mapping analog-stereo-input]
device-strings = hw:%f
channel-map = left,right
paths-input = analog-input-mic analog-input
direction = input
priority = 4
[Mapping analog-mono]
device-strings = hw:%f
channel-map = mono
paths-input = analog-input-mic analog-input
direction = input
priority = 3
[Mapping analog-mono-left]
device-strings = hw:%f
channel-map = mono,aux1
paths-input = analog-input-mic analog-input
direction = input
priority = 2
[Mapping analog-mono-right]
device-strings = hw:%f
channel-map = aux1,mono
paths-input = analog-input-mic analog-input
direction = input
priority = 1
[Mapping analog-stereo-output]
device-strings = front:%f
channel-map = left,right
paths-output = analog-output
direction = output

View file

@ -162,7 +162,7 @@ static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
if (u->use_ucm)
pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, true, ports, cp, u->core);
pa_alsa_ucm_add_port(NULL, &m->ucm_context, true, ports, cp, u->core);
else
pa_alsa_path_set_add_ports(m->output_path_set, cp, ports, NULL, u->core);
if (m->channel_map.channels > cp->max_sink_channels)
@ -175,7 +175,7 @@ static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
if (u->use_ucm)
pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, false, ports, cp, u->core);
pa_alsa_ucm_add_port(NULL, &m->ucm_context, false, ports, cp, u->core);
else
pa_alsa_path_set_add_ports(m->input_path_set, cp, ports, NULL, u->core);
if (m->channel_map.channels > cp->max_source_channels)
@ -249,8 +249,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
/* if UCM is available for this card then update the verb */
if (u->use_ucm) {
if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile ? nd->profile->name : NULL,
od->profile ? od->profile->name : NULL) < 0) {
if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile, od->profile) < 0) {
ret = -1;
goto finish;
}
@ -302,7 +301,7 @@ static void init_profile(struct userdata *u) {
if (d->profile && u->use_ucm) {
/* Set initial verb */
if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile->name, NULL) < 0) {
if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile, NULL) < 0) {
pa_log("Failed to set ucm profile %s", d->profile->name);
return;
}
@ -371,7 +370,7 @@ struct temp_port_avail {
static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
snd_ctl_elem_value_t *elem_value;
bool plugged_in;
void *state;
@ -381,6 +380,8 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
pa_available_t active_available = PA_AVAILABLE_UNKNOWN;
pa_assert(u);
pa_assert(_elem);
elem = *_elem;
/* Changing the jack state may cause a port change, and a port change will
* make the sink or source change the mixer settings. If there are multiple
@ -563,13 +564,18 @@ static pa_device_port* find_port_with_eld_device(struct userdata *u, int device)
static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
int device = snd_hctl_elem_get_device(elem);
snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
int device;
const char *old_monitor_name;
pa_device_port *p;
pa_hdmi_eld eld;
bool changed = false;
pa_assert(u);
pa_assert(_elem);
elem = *_elem;
device = snd_hctl_elem_get_device(elem);
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return 0;

View file

@ -42,8 +42,8 @@ typedef struct pa_a2dp_endpoint_conf {
/* A2DP codec id */
pa_a2dp_codec_id id;
/* True if codec is bi-directional and supports backchannel */
bool support_backchannel;
/* Returns true if the codec can be supported on the system */
bool (*can_be_supported)(bool for_encoding);
/* Returns true if the codec can be supported on the system */
bool (*can_be_supported)(bool for_encoding);

View file

@ -490,7 +490,11 @@ static size_t reduce_encoder_bitrate(void *codec_info, size_t write_link_mtu) {
static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
size_t written;
<<<<<<< HEAD
written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed);
=======
written = gst_transcode_buffer(codec_info, timestamp, input_buffer, input_size, output_buffer, output_size, processed);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (PA_UNLIKELY(*processed == 0 || *processed != input_size))
pa_log_error("aptX encoding error");
@ -526,7 +530,11 @@ static size_t encode_buffer_hd(void *codec_info, uint32_t timestamp, const uint8
static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
size_t written;
<<<<<<< HEAD
written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed);
=======
written = gst_transcode_buffer(codec_info, -1, input_buffer, input_size, output_buffer, output_size, processed);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* Due to aptX latency, aptx_decode starts filling output buffer after 90 input samples.
* If input buffer contains less than 90 samples, aptx_decode returns zero (=no output)
@ -556,7 +564,10 @@ static size_t decode_buffer_hd(void *codec_info, const uint8_t *input_buffer, si
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx = {
.id = { A2DP_CODEC_VENDOR, APTX_VENDOR_ID, APTX_CODEC_ID },
<<<<<<< HEAD
.support_backchannel = false,
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities,
.choose_remote_endpoint = choose_remote_endpoint,
@ -580,7 +591,10 @@ const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx = {
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx_hd = {
.id = { A2DP_CODEC_VENDOR, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID },
<<<<<<< HEAD
.support_backchannel = false,
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities_hd,
.choose_remote_endpoint = choose_remote_endpoint_hd,

View file

@ -22,12 +22,20 @@
#endif
#include <arpa/inet.h>
<<<<<<< HEAD
=======
#include <stdint.h>
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include <pulsecore/once.h>
#include <pulsecore/core-util.h>
#include <pulse/sample.h>
<<<<<<< HEAD
=======
#include <pulse/timeval.h>
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
#include <pulse/util.h>
#include "a2dp-codecs.h"
@ -39,6 +47,7 @@ static void app_sink_eos(GstAppSink *appsink, gpointer userdata) {
pa_log_debug("Sink got EOS");
}
<<<<<<< HEAD
/* Called from the GStreamer streaming thread */
static GstFlowReturn app_sink_new_sample(GstAppSink *appsink, gpointer userdata) {
struct gst_info *info = (struct gst_info *) userdata;
@ -116,6 +125,21 @@ bool gst_init_common(struct gst_info *info) {
goto fail;
}
g_object_set(appsrc, "is-live", FALSE, "format", GST_FORMAT_TIME, "stream-type", 0, "max-bytes", 0, NULL);
=======
static void gst_deinit_common(struct gst_info *info) {
if (!info)
return;
if (info->app_sink)
gst_object_unref(info->app_sink);
if (info->bin)
gst_object_unref(info->bin);
}
bool gst_init_common(struct gst_info *info) {
GstElement *bin = NULL;
GstElement *appsink = NULL;
GstAppSinkCallbacks callbacks = { 0, };
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
appsink = gst_element_factory_make("appsink", "app_sink");
if (!appsink) {
@ -125,6 +149,7 @@ bool gst_init_common(struct gst_info *info) {
g_object_set(appsink, "sync", FALSE, "async", FALSE, "enable-last-sample", FALSE, NULL);
callbacks.eos = app_sink_eos;
<<<<<<< HEAD
callbacks.new_sample = app_sink_new_sample;
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &callbacks, info, NULL);
@ -143,18 +168,31 @@ bool gst_init_common(struct gst_info *info) {
info->sink_adapter = adapter;
info->pipeline = pipeline;
info->sample_ready_fdsem = pa_fdsem_new();
=======
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &callbacks, info, NULL);
bin = gst_bin_new(NULL);
pa_assert(bin);
info->app_sink = appsink;
info->bin = bin;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
return true;
fail:
<<<<<<< HEAD
if (appsrc)
gst_object_unref(appsrc);
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (appsink)
gst_object_unref(appsink);
return false;
}
<<<<<<< HEAD
/*
* The idea of using buffer probes is as follows. We set a buffer probe on the
* encoder sink pad. In the buffer probe, we set an idle probe on the upstream
@ -194,6 +232,12 @@ static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
gchar *sample_format;
GstCaps *caps;
int channel_mask;
=======
static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
gchar *sample_format;
GstCaps *caps;
uint64_t channel_mask;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
switch (ss->format) {
case PA_SAMPLE_S16LE:
@ -240,6 +284,13 @@ static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transcoder) {
GstPad *pad;
GstCaps *caps;
<<<<<<< HEAD
=======
GstEvent *event;
GstSegment segment;
GstEvent *stream_start;
guint group_id;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_assert(transcoder);
@ -248,6 +299,7 @@ bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transc
if (!gst_init_common(info))
goto common_fail;
<<<<<<< HEAD
caps = gst_create_caps_from_sample_spec(info->ss);
if (for_encoding)
g_object_set(info->app_src, "caps", caps, NULL);
@ -259,19 +311,62 @@ bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transc
gst_bin_add_many(GST_BIN(info->pipeline), info->app_src, transcoder, info->app_sink, NULL);
if (!gst_element_link_many(info->app_src, transcoder, info->app_sink, NULL)) {
=======
gst_bin_add_many(GST_BIN(info->bin), transcoder, info->app_sink, NULL);
if (!gst_element_link_many(transcoder, info->app_sink, NULL)) {
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_log_error("Failed to link codec elements into pipeline");
goto pipeline_fail;
}
<<<<<<< HEAD
if (gst_element_set_state(info->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
=======
pad = gst_element_get_static_pad(transcoder, "sink");
pa_assert_se(gst_element_add_pad(info->bin, gst_ghost_pad_new("sink", pad)));
/**
* Only the sink pad is needed to push buffers. Cache it since
* gst_element_get_static_pad is relatively expensive and verbose
* on higher log levels.
*/
info->pad_sink = pad;
if (gst_element_set_state(info->bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_log_error("Could not start pipeline");
goto pipeline_fail;
}
<<<<<<< HEAD
/* See the comment on buffer probe functions */
pad = gst_element_get_static_pad(transcoder, "sink");
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, gst_sink_buffer_probe, info, NULL);
gst_object_unref(pad);
=======
/* First, send stream-start sticky event */
group_id = gst_util_group_id_next();
stream_start = gst_event_new_stream_start("gst-codec-pa");
gst_event_set_group_id(stream_start, group_id);
gst_pad_send_event(info->pad_sink, stream_start);
/* Retrieve the pad that handles the PCM format between PA and GStreamer */
if (for_encoding)
pad = gst_element_get_static_pad(transcoder, "sink");
else
pad = gst_element_get_static_pad(transcoder, "src");
/* Second, send caps sticky event */
caps = gst_create_caps_from_sample_spec(info->ss);
pa_assert_se(gst_pad_set_caps(pad, caps));
gst_caps_unref(caps);
gst_object_unref(GST_OBJECT(pad));
/* Third, send segment sticky event */
gst_segment_init(&segment, GST_FORMAT_TIME);
event = gst_event_new_segment(&segment);
gst_pad_send_event(info->pad_sink, event);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_log_info("GStreamer pipeline initialisation succeeded");
@ -295,6 +390,7 @@ common_fail:
return false;
}
<<<<<<< HEAD
size_t gst_transcode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
struct gst_info *info = (struct gst_info *) codec_info;
gsize available, transcoded;
@ -311,11 +407,48 @@ size_t gst_transcode_buffer(void *codec_info, const uint8_t *input_buffer, size_
gst_buffer_unmap(in_buf, &map_info);
ret = gst_app_src_push_buffer(GST_APP_SRC(info->app_src), in_buf);
=======
size_t gst_transcode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
struct gst_info *info = (struct gst_info *) codec_info;
gsize transcoded;
GstBuffer *in_buf;
GstFlowReturn ret;
size_t written = 0;
GstSample *sample;
pa_assert(info->pad_sink);
in_buf = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY,
(gpointer)input_buffer, input_size, 0, input_size, NULL, NULL);
pa_assert(in_buf);
/* Acquire an extra reference to validate refcount afterwards */
gst_mini_object_ref(GST_MINI_OBJECT_CAST(in_buf));
pa_assert(GST_MINI_OBJECT_REFCOUNT_VALUE(in_buf) == 2);
if (timestamp == -1)
GST_BUFFER_TIMESTAMP(in_buf) = GST_CLOCK_TIME_NONE;
else {
// Timestamp is monotonically increasing with samplerate/packets-per-second;
// convert it to a timestamp in nanoseconds:
GST_BUFFER_TIMESTAMP(in_buf) = timestamp * PA_USEC_PER_SEC / info->ss->rate;
}
ret = gst_pad_chain(info->pad_sink, in_buf);
/**
* Ensure we're the only one holding a reference to this buffer after gst_pad_chain,
* which internally holds a pointer reference to input_buffer. The caller provides
* no guarantee to the validity of this pointer after returning from this function.
*/
pa_assert(GST_MINI_OBJECT_REFCOUNT_VALUE(in_buf) == 1);
gst_mini_object_unref(GST_MINI_OBJECT_CAST(in_buf));
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (ret != GST_FLOW_OK) {
pa_log_error("failed to push buffer for transcoding %d", ret);
goto fail;
}
<<<<<<< HEAD
pa_fdsem_wait(info->sample_ready_fdsem);
available = gst_adapter_available(info->sink_adapter);
@ -329,6 +462,21 @@ size_t gst_transcode_buffer(void *codec_info, const uint8_t *input_buffer, size_
written += transcoded;
} else
pa_log_debug("No transcoded data available in adapter");
=======
while ((sample = gst_app_sink_try_pull_sample(GST_APP_SINK(info->app_sink), 0))) {
in_buf = gst_sample_get_buffer(sample);
transcoded = gst_buffer_get_size(in_buf);
written += transcoded;
pa_assert(written <= output_size);
GstMapInfo map_info;
pa_assert_se(gst_buffer_map(in_buf, &map_info, GST_MAP_READ));
memcpy(output_buffer, map_info.data, transcoded);
gst_buffer_unmap(in_buf, &map_info);
gst_sample_unref(sample);
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
*processed = input_size;
@ -343,6 +491,7 @@ fail:
void gst_codec_deinit(void *codec_info) {
struct gst_info *info = (struct gst_info *) codec_info;
<<<<<<< HEAD
if (info->sample_ready_fdsem)
pa_fdsem_free(info->sample_ready_fdsem);
@ -354,6 +503,15 @@ void gst_codec_deinit(void *codec_info) {
if (info->sink_adapter)
g_object_unref(info->sink_adapter);
=======
if (info->bin) {
gst_element_set_state(info->bin, GST_STATE_NULL);
gst_object_unref(info->bin);
}
if (info->pad_sink)
gst_object_unref(GST_OBJECT(info->pad_sink));
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_xfree(info);
}

View file

@ -43,15 +43,27 @@ struct gst_info {
const a2dp_ldac_t *ldac_config;
} a2dp_codec_t;
<<<<<<< HEAD
GstElement *app_src, *app_sink;
GstElement *pipeline;
GstAdapter *sink_adapter;
pa_fdsem *sample_ready_fdsem;
=======
/* The appsink element that accumulates encoded/decoded buffers */
GstElement *app_sink;
GstElement *bin;
/* The sink pad to push to-be-encoded/decoded buffers into */
GstPad *pad_sink;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
uint16_t seq_num;
};
bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transcoder);
<<<<<<< HEAD
size_t gst_transcode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed);
=======
size_t gst_transcode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
void gst_codec_deinit(void *codec_info);

View file

@ -46,6 +46,7 @@ static bool can_be_supported(bool for_encoding) {
}
gst_object_unref(element_factory);
<<<<<<< HEAD
element_factory = gst_element_factory_find("rtpldacpay");
if (element_factory == NULL) {
pa_log_info("LDAC RTP payloader element `rtpldacpay` not found");
@ -53,6 +54,8 @@ static bool can_be_supported(bool for_encoding) {
}
gst_object_unref(element_factory);
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
return true;
}
@ -206,7 +209,10 @@ static uint8_t fill_preferred_configuration(const pa_sample_spec *default_sample
GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) {
GstElement *bin;
<<<<<<< HEAD
GstElement *rtpldacpay;
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
GstElement *enc;
GstPad *pad;
@ -270,6 +276,7 @@ GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_en
goto fail;
}
<<<<<<< HEAD
rtpldacpay = gst_element_factory_make("rtpldacpay", "rtp_ldac_pay");
if (!rtpldacpay) {
pa_log_error("Could not create RTP LDAC payloader element");
@ -286,12 +293,22 @@ GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_en
gst_object_unref(bin);
return NULL;
}
=======
bin = gst_bin_new("ldac_enc_bin");
pa_assert(bin);
gst_bin_add_many(GST_BIN(bin), enc, NULL);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pad = gst_element_get_static_pad(enc, "sink");
pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad)));
gst_object_unref(GST_OBJECT(pad));
<<<<<<< HEAD
pad = gst_element_get_static_pad(rtpldacpay, "src");
=======
pad = gst_element_get_static_pad(enc, "src");
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("src", pad)));
gst_object_unref(GST_OBJECT(pad));
@ -421,18 +438,51 @@ static size_t reduce_encoder_bitrate(void *codec_info, size_t write_link_mtu) {
}
static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) {
<<<<<<< HEAD
size_t written;
written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed);
if (PA_UNLIKELY(*processed != input_size))
pa_log_error("LDAC encoding error");
=======
struct gst_info *info = (struct gst_info *) codec_info;
struct rtp_header *header;
struct rtp_payload *payload;
size_t written;
if (PA_UNLIKELY(output_size < sizeof(*header) + sizeof(*payload))) {
*processed = 0;
return 0;
}
written = gst_transcode_buffer(codec_info, timestamp, input_buffer, input_size, output_buffer + sizeof(*header) + sizeof(*payload), output_size - sizeof(*header) - sizeof(*payload), processed);
if (PA_UNLIKELY(*processed != input_size))
pa_log_error("LDAC encoding error");
if (PA_LIKELY(written > 0)) {
header = (struct rtp_header *) output_buffer;
pa_zero(*header);
header->v = 2;
header->pt = 96;
header->sequence_number = htons(info->seq_num++);
header->timestamp = htonl(timestamp);
header->ssrc = htonl(1);
payload = (struct rtp_payload*) (output_buffer + sizeof(*header));
payload->frame_count = get_ldac_num_frames(codec_info, info->codec_type);
written += sizeof(*header) + sizeof(*payload);
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
return written;
}
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_hq = {
.id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID },
<<<<<<< HEAD
.support_backchannel = false,
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities,
.choose_remote_endpoint = choose_remote_endpoint,
@ -455,7 +505,10 @@ const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_hq = {
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_sq = {
.id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID },
<<<<<<< HEAD
.support_backchannel = false,
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities,
.choose_remote_endpoint = choose_remote_endpoint,
@ -478,7 +531,10 @@ const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_sq = {
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_mq = {
.id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID },
<<<<<<< HEAD
.support_backchannel = false,
=======
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities,
.choose_remote_endpoint = choose_remote_endpoint,

File diff suppressed because it is too large Load diff

View file

@ -52,6 +52,10 @@ extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_hq;
extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_sq;
extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_mq;
#endif
<<<<<<< HEAD
=======
extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_faststream;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* This is list of supported codecs. Their order is important.
* Codec with lower index has higher priority. */
@ -69,6 +73,10 @@ static const pa_a2dp_endpoint_conf *pa_a2dp_endpoint_configurations[] = {
&pa_a2dp_endpoint_conf_sbc_xq_453,
&pa_a2dp_endpoint_conf_sbc_xq_512,
&pa_a2dp_endpoint_conf_sbc_xq_552,
<<<<<<< HEAD
=======
&pa_a2dp_endpoint_conf_faststream,
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
};
unsigned int pa_bluetooth_a2dp_endpoint_conf_count(void) {

View file

@ -21,6 +21,8 @@
#include <config.h>
#endif
#include <pulse/util.h>
#include <pulsecore/shared.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-util.h>
@ -36,15 +38,34 @@
#include "bluez5-util.h"
#include "bt-codec-msbc.h"
<<<<<<< HEAD
=======
#include "upower.h"
#define MANDATORY_CALL_INDICATORS \
"(\"call\",(0-1))," \
"(\"callsetup\",(0-3))," \
"(\"callheld\",(0-2))" \
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
struct pa_bluetooth_backend {
pa_core *core;
pa_dbus_connection *connection;
pa_bluetooth_discovery *discovery;
pa_hook_slot *adapter_uuids_changed_slot;
<<<<<<< HEAD
bool enable_shared_profiles;
bool enable_hsp_hs;
bool enable_hfp_hf;
=======
pa_hook_slot *host_battery_level_changed_slot;
pa_upower_backend *upower;
bool enable_shared_profiles;
bool enable_hsp_hs;
bool enable_hfp_hf;
bool cmer_indicator_reporting_enabled;
uint32_t cind_enabled_indicators;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
PA_LLIST_HEAD(pa_dbus_pending, pending);
};
@ -55,6 +76,7 @@ struct transport_data {
int sco_fd;
pa_io_event *sco_io;
pa_mainloop_api *mainloop;
pa_bluetooth_backend *backend;
};
struct hfp_config {
@ -65,6 +87,37 @@ struct hfp_config {
bool supports_indicators;
int selected_codec;
};
<<<<<<< HEAD
/*
* the separate hansfree headset (HF) and Audio Gateway (AG) features
*/
enum hfp_hf_features {
HFP_HF_EC_NR = 0,
HFP_HF_CALL_WAITING = 1,
HFP_HF_CLI = 2,
HFP_HF_VR = 3,
HFP_HF_RVOL = 4,
HFP_HF_ESTATUS = 5,
HFP_HF_ECALL = 6,
HFP_HF_CODECS = 7,
HFP_HF_INDICATORS = 8,
};
enum hfp_ag_features {
HFP_AG_THREE_WAY = 0,
HFP_AG_EC_NR = 1,
HFP_AG_VR = 2,
HFP_AG_RING = 3,
HFP_AG_NUM_TAG = 4,
HFP_AG_REJECT = 5,
HFP_AG_ESTATUS = 6,
HFP_AG_ECALL = 7,
HFP_AG_EERR = 8,
HFP_AG_CODECS = 9,
HFP_AG_INDICATORS = 10,
};
=======
/*
* the separate hansfree headset (HF) and Audio Gateway (AG) features
@ -95,6 +148,21 @@ enum hfp_ag_features {
HFP_AG_INDICATORS = 10,
};
/*
* Always keep this struct in sync with indicator discovery of AT+CIND=?
* These indicators are used in bitflags and intentionally start at 1
* since AT+CIND indicators start at index 1.
*/
typedef enum pa_bluetooth_ag_to_hf_indicators {
CIND_CALL_INDICATOR = 1,
CIND_CALL_SETUP_INDICATOR = 2,
CIND_CALL_HELD_INDICATOR = 3,
CIND_SERVICE_INDICATOR = 4,
CIND_BATT_CHG_INDICATOR = 5,
CIND_INDICATOR_MAX = 6
} pa_bluetooth_ag_to_hf_indicators_t;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* gateway features we support, which is as little as we can get away with */
static uint32_t hfp_features =
/* HFP 1.6 requires this */
@ -108,6 +176,9 @@ static uint32_t hfp_features =
* The choice seems to be a bit arbitrary -- it looks like at least channels 2, 4 and 5 also work*/
#define HSP_HS_DEFAULT_CHANNEL 3
/* Total number of trying to reconnect */
#define SCO_RECONNECTION_COUNT 3
#define PROFILE_INTROSPECT_XML \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
"<node>" \
@ -320,17 +391,43 @@ fail:
static int sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) {
int sock;
socklen_t len;
int i;
if (optional)
sock = sco_do_accept(t);
else
sock = sco_do_connect(t);
else {
for (i = 0; i < SCO_RECONNECTION_COUNT; i++) {
sock = sco_do_connect(t);
if (sock < 0) {
pa_log_debug("err is %s and reconnection count is %d", pa_cstrerror(errno), i);
pa_msleep(300);
continue;
} else
break;
}
}
if (sock < 0)
goto fail;
<<<<<<< HEAD
if (imtu) *imtu = 60;
if (omtu) *omtu = 60;
=======
/* The correct block size should take into account the SCO MTU from
* the Bluetooth adapter and (for adapters in the USB bus) the MxPS
* value from the Isoc USB endpoint in use by btusb and should be
* made available to userspace by the Bluetooth kernel subsystem.
*
* Set initial MTU to max known payload length of HCI packet
* in USB Alternate Setting 5 (144 bytes)
* See also pa_bluetooth_transport::last_read_size handling
* and comment about MTU size in bt_prepare_encoder_buffer()
*/
if (imtu) *imtu = 144;
if (omtu) *omtu = 144;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (t->device->autodetect_mtu) {
struct sco_options sco_opt;
@ -568,11 +665,21 @@ static pa_volume_t set_source_volume(pa_bluetooth_transport *t, pa_volume_t volu
static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf)
{
struct hfp_config *c = t->config;
<<<<<<< HEAD
int indicator, val;
char str[5];
const char *r;
size_t len;
const char *state;
=======
struct transport_data *trd = t->userdata;
pa_bluetooth_backend *b = trd->backend;
int indicator, mode, val;
char *str;
const char *r;
size_t len;
const char *state = NULL;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* first-time initialize selected codec to CVSD */
if (c->selected_codec == 0)
@ -587,6 +694,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
c->state = 1;
return true;
<<<<<<< HEAD
} else if (sscanf(buf, "AT+BAC=%3s", str) == 1) {
c->support_msbc = false;
@ -594,11 +702,52 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
/* check if codec id 2 (mSBC) is in the list of supported codecs */
while ((r = pa_split_in_place(str, ",", &len, &state))) {
=======
} else if (pa_startswith(buf, "AT+BIA=")) {
/* Indicators start with index 1 and follow the order of the AT+CIND=? response */
str = pa_xstrdup(buf + 7);
for (indicator = 1; (r = pa_split_in_place(str, ",\r\n", &len, &state)); indicator++) {
/* Ignore updates to mandatory indicators which are always ON */
if (indicator == CIND_CALL_INDICATOR
|| indicator == CIND_CALL_SETUP_INDICATOR
|| indicator == CIND_CALL_HELD_INDICATOR)
continue;
/* Indicators may have no value and should be skipped */
if (len == 0)
continue;
if (len == 1 && r[0] == '1')
b->cind_enabled_indicators |= (1 << indicator);
else if (len == 1 && r[0] == '0')
b->cind_enabled_indicators &= ~(1 << indicator);
else {
pa_log_error("Unable to parse indicator of AT+BIA command: %s", buf);
rfcomm_write_response(fd, "ERROR");
pa_xfree(str);
return false;
}
}
pa_xfree(str);
return true;
} else if (pa_startswith(buf, "AT+BAC=")) {
c->support_msbc = false;
/* check if codec id 2 (mSBC) is in the list of supported codecs */
str = pa_xstrdup(buf + 7);
while ((r = pa_split_in_place(str, ",\r\n", &len, &state))) {
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (len == 1 && r[0] == '2') {
c->support_msbc = true;
break;
}
}
<<<<<<< HEAD
=======
pa_xfree(str);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
c->support_codec_negotiation = true;
@ -612,6 +761,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
return true;
} else if (c->state == 1 && pa_startswith(buf, "AT+CIND=?")) {
<<<<<<< HEAD
/* we declare minimal no indicators */
rfcomm_write_response(fd, "+CIND: "
/* many indicators can be supported, only call and
@ -620,16 +770,58 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
"(\"call\",(0-1)),"
"(\"callsetup\",(0-3)),"
"(\"callheld\",(0-2))");
=======
/* UPower backend available, declare support for more indicators */
if (b->upower) {
rfcomm_write_response(fd, "+CIND: "
MANDATORY_CALL_INDICATORS ","
"(\"service\",(0-1)),"
"(\"battchg\",(0-5))");
/* Minimal indicators supported without any additional backend */
} else {
rfcomm_write_response(fd, "+CIND: "
MANDATORY_CALL_INDICATORS ","
"(\"service\",(0-1))");
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
c->state = 2;
return true;
} else if (c->state == 2 && pa_startswith(buf, "AT+CIND?")) {
<<<<<<< HEAD
rfcomm_write_response(fd, "+CIND: 0,0,0,0");
=======
if (b->upower)
rfcomm_write_response(fd, "+CIND: 0,0,0,0,%u", pa_upower_get_battery_level(b->upower));
else
rfcomm_write_response(fd, "+CIND: 0,0,0,0");
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
c->state = 3;
return true;
} else if ((c->state == 2 || c->state == 3) && pa_startswith(buf, "AT+CMER=")) {
<<<<<<< HEAD
rfcomm_write_response(fd, "OK");
=======
if (sscanf(buf, "AT+CMER=%d,%*d,%*d,%d", &mode, &val) == 2) {
/* Bluetooth HFP spec only defines mode == 3 */
if (mode != 3)
pa_log_warn("Unexpected mode for AT+CMER: %d", mode);
/* Configure CMER event reporting */
b->cmer_indicator_reporting_enabled = !!val;
pa_log_debug("Event indications enabled? %s", pa_yes_no(val));
rfcomm_write_response(fd, "OK");
}
else {
pa_log_error("Unable to parse AT+CMER command: %s", buf);
rfcomm_write_response(fd, "ERROR");
return false;
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (c->support_codec_negotiation) {
if (c->support_msbc && pa_bluetooth_discovery_get_enable_msbc(t->device->discovery)) {
@ -715,10 +907,67 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
* update, but we process only the ones we care about
*/
return true;
<<<<<<< HEAD
=======
}
static int get_rfcomm_fd(pa_bluetooth_discovery *discovery) {
struct pa_bluetooth_transport *t;
struct transport_data *trd = NULL;
void *state = NULL;
/* Find RFCOMM transport by checking if a HSP or HFP profile transport is available */
while ((t = pa_hashmap_iterate(pa_bluetooth_discovery_get_transports(discovery), &state, NULL))) {
/* Skip non-connected transports */
if (!t || t->state == PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED) {
continue;
}
/* Break when an RFCOMM capable transport profile is available */
if (t->profile == PA_BLUETOOTH_PROFILE_HFP_HF) {
trd = t->userdata;
break;
}
}
/* Skip if RFCOMM channel is not available yet */
if (!trd) {
pa_log_info("RFCOMM not available yet, skipping notification");
return -1;
}
return trd->rfcomm_fd;
}
static pa_hook_result_t host_battery_level_changed_cb(pa_bluetooth_discovery *y, const pa_upower_backend *u, pa_bluetooth_backend *b) {
int rfcomm_fd;
pa_assert(y);
pa_assert(u);
pa_assert(b);
/* Get RFCOMM channel if available */
rfcomm_fd = get_rfcomm_fd(y);
if (rfcomm_fd < 0)
return PA_HOOK_OK;
/* Notify HF about AG battery level change over RFCOMM */
if (b->cmer_indicator_reporting_enabled && (b->cind_enabled_indicators & (1 << CIND_BATT_CHG_INDICATOR))) {
rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_BATT_CHG_INDICATOR, u->battery_level);
pa_log_debug("HG notified of AG's battery level change");
/* Skip notification if indicator is disabled or event reporting is completely disabled */
} else
pa_log_debug("Battery level change indicator disabled, skipping notification");
return PA_HOOK_OK;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
pa_bluetooth_transport *t = userdata;
struct transport_data *trd = t->userdata;
pa_bluetooth_backend *b = trd->backend;
int i;
pa_assert(io);
pa_assert(t);
@ -734,18 +983,23 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
}
if (events & PA_IO_EVENT_INPUT) {
char buf[512];
char rbuf[512];
ssize_t len;
int gain, dummy;
bool do_reply = false;
int vendor, product, version, features;
<<<<<<< HEAD
=======
char *buf = rbuf;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
int num;
len = pa_read(fd, buf, 511, NULL);
len = pa_read(fd, rbuf, 511, NULL);
if (len < 0) {
pa_log_error("RFCOMM read error: %s", pa_cstrerror(errno));
goto fail;
}
<<<<<<< HEAD
buf[len] = 0;
pa_log_debug("RFCOMM << %s", buf);
@ -834,11 +1088,119 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
if (do_reply)
rfcomm_write_response(fd, "OK");
=======
rbuf[len] = 0;
pa_log_debug("RFCOMM << %s", rbuf);
while (buf[0]) {
/* There are only four HSP AT commands:
* AT+VGS=value: value between 0 and 15, sent by the HS to AG to set the speaker gain.
* +VGS=value is sent by AG to HS as a response to an AT+VGS command or when the gain
* is changed on the AG side.
* AT+VGM=value: value between 0 and 15, sent by the HS to AG to set the microphone gain.
* +VGM=value is sent by AG to HS as a response to an AT+VGM command or when the gain
* is changed on the AG side.
* AT+CKPD=200: Sent by HS when headset button is pressed.
* RING: Sent by AG to HS to notify of an incoming call. It can safely be ignored because
* it does not expect a reply. */
if (sscanf(buf, "AT+VGS=%d", &gain) == 1 || sscanf(buf, "\r\n+VGM%*[=:]%d\r\n", &gain) == 1) {
if (!t->set_sink_volume) {
pa_log_debug("HS/HF peer supports speaker gain control");
t->set_sink_volume = set_sink_volume;
}
t->sink_volume = hsp_gain_to_volume(gain);
pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SINK_VOLUME_CHANGED), t);
do_reply = true;
} else if (sscanf(buf, "AT+VGM=%d", &gain) == 1 || sscanf(buf, "\r\n+VGS%*[=:]%d\r\n", &gain) == 1) {
if (!t->set_source_volume) {
pa_log_debug("HS/HF peer supports microphone gain control");
t->set_source_volume = set_source_volume;
}
t->source_volume = hsp_gain_to_volume(gain);
pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED), t);
do_reply = true;
} else if (sscanf(buf, "AT+CKPD=%d", &dummy) == 1) {
do_reply = true;
} else if (sscanf(buf, "AT+XAPL=%04x-%04x-%04x,%d", &vendor, &product, &version, &features) == 4) {
if (features & 0x2)
/* claim, that we support battery status reports */
rfcomm_write_response(fd, "+XAPL=iPhone,6");
do_reply = true;
} else if (sscanf(buf, "AT+IPHONEACCEV=%d", &num) == 1) {
char *substr = buf, *keystr;
int key, val, i;
do_reply = true;
for (i = 0; i < num; ++i) {
keystr = strchr(substr, ',');
if (!keystr) {
pa_log_warn("%s misses key for argument #%d", buf, i);
do_reply = false;
break;
}
keystr++;
substr = strchr(keystr, ',');
if (!substr) {
pa_log_warn("%s misses value for argument #%d", buf, i);
do_reply = false;
break;
}
substr++;
key = atoi(keystr);
val = atoi(substr);
switch (key) {
case 1:
pa_log_debug("Battery Level: %d0%%", val + 1);
pa_bluetooth_device_report_battery_level(t->device, (val + 1) * 10, "Apple accessory indication");
break;
case 2:
pa_log_debug("Dock Status: %s", val ? "docked" : "undocked");
break;
default:
pa_log_debug("Unexpected IPHONEACCEV key %#x", key);
break;
}
}
if (!do_reply)
rfcomm_write_response(fd, "ERROR");
} else if (t->config) { /* t->config is only non-null for hfp profile */
do_reply = hfp_rfcomm_handle(fd, t, buf);
} else {
rfcomm_write_response(fd, "ERROR");
do_reply = false;
}
if (do_reply)
rfcomm_write_response(fd, "OK");
if (buf[0] == '\r') /* in case it is the command with format \r\nCOMMAND\r\n, skip the starting \r */
buf = buf + 1;
buf = strstr(buf, "\r"); /* try to find the next AT command in the buf */
if (!buf)
break;
else if (buf[1] == '\n')
buf = buf + 2; /* skip \r\n */
else
buf = buf + 1; /* skip \r */
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
}
return;
fail:
/* Service Connection lost, reset indicators and event reporting to default values */
b->cmer_indicator_reporting_enabled = false;
for (i = 1; i < CIND_INDICATOR_MAX; i++)
b->cind_enabled_indicators |= (1 << i);
pa_bluetooth_transport_unlink(t);
pa_bluetooth_transport_free(t);
}
@ -862,6 +1224,7 @@ static void transport_destroy(pa_bluetooth_transport *t) {
static pa_volume_t set_sink_volume(pa_bluetooth_transport *t, pa_volume_t volume) {
struct transport_data *trd = t->userdata;
uint16_t gain = volume_to_hsp_gain(volume);
<<<<<<< HEAD
/* Propagate rounding and bound checks */
volume = hsp_gain_to_volume(gain);
@ -871,6 +1234,17 @@ static pa_volume_t set_sink_volume(pa_bluetooth_transport *t, pa_volume_t volume
t->sink_volume = volume;
=======
/* Propagate rounding and bound checks */
volume = hsp_gain_to_volume(gain);
if (t->sink_volume == volume)
return volume;
t->sink_volume = volume;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* If we are in the AG role, we send an unsolicited result-code to the headset
* to change the speaker gain. In the HS role, source and sink are swapped,
* so in this case we notify the AG that the microphone gain has changed
@ -887,6 +1261,7 @@ static pa_volume_t set_sink_volume(pa_bluetooth_transport *t, pa_volume_t volume
static pa_volume_t set_source_volume(pa_bluetooth_transport *t, pa_volume_t volume) {
struct transport_data *trd = t->userdata;
uint16_t gain = volume_to_hsp_gain(volume);
<<<<<<< HEAD
/* Propagate rounding and bound checks */
volume = hsp_gain_to_volume(gain);
@ -896,6 +1271,17 @@ static pa_volume_t set_source_volume(pa_bluetooth_transport *t, pa_volume_t volu
t->source_volume = volume;
=======
/* Propagate rounding and bound checks */
volume = hsp_gain_to_volume(gain);
if (t->source_volume == volume)
return volume;
t->source_volume = volume;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
/* If we are in the AG role, we send an unsolicited result-code to the headset
* to change the microphone gain. In the HS role, source and sink are swapped,
* so in this case we notify the AG that the speaker gain has changed
@ -1001,6 +1387,7 @@ static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m,
trd = pa_xnew0(struct transport_data, 1);
trd->rfcomm_fd = fd;
trd->mainloop = b->core->mainloop;
trd->backend = b;
trd->rfcomm_io = trd->mainloop->io_new(b->core->mainloop, fd, PA_IO_EVENT_INPUT,
rfcomm_io_callback, t);
t->userdata = trd;
@ -1153,9 +1540,15 @@ static void native_backend_apply_profile_registration_change(pa_bluetooth_backen
profile_done(native_backend, PA_BLUETOOTH_PROFILE_HFP_HF);
}
}
<<<<<<< HEAD
void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *native_backend, bool enable) {
=======
void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *native_backend, bool enable) {
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (enable == native_backend->enable_shared_profiles)
return;
@ -1167,6 +1560,7 @@ void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *na
pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles) {
pa_bluetooth_backend *backend;
DBusError err;
int i;
pa_log_debug("Bluetooth Headset Backend API support using the native backend");
@ -1189,6 +1583,7 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
backend->adapter_uuids_changed_slot =
pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_ADAPTER_UUIDS_CHANGED), PA_HOOK_NORMAL,
(pa_hook_cb_t) adapter_uuids_changed_cb, backend);
<<<<<<< HEAD
if (!backend->enable_hsp_hs && !backend->enable_hfp_hf)
pa_log_warn("Both HSP HS and HFP HF bluetooth profiles disabled in native backend. Native backend will not register for headset connections.");
@ -1198,6 +1593,31 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
if (backend->enable_shared_profiles)
native_backend_apply_profile_registration_change(backend, true);
=======
backend->host_battery_level_changed_slot =
pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED), PA_HOOK_NORMAL,
(pa_hook_cb_t) host_battery_level_changed_cb, backend);
if (!backend->enable_hsp_hs && !backend->enable_hfp_hf)
pa_log_warn("Both HSP HS and HFP HF bluetooth profiles disabled in native backend. Native backend will not register for headset connections.");
if (backend->enable_hsp_hs)
profile_init(backend, PA_BLUETOOTH_PROFILE_HSP_HS);
if (backend->enable_shared_profiles)
native_backend_apply_profile_registration_change(backend, true);
backend->upower = pa_upower_backend_new(c, y);
/* All CIND indicators are enabled by default until overriden by AT+BIA */
for (i = 1; i < CIND_INDICATOR_MAX; i++)
backend->cind_enabled_indicators |= (1 << i);
/* While all CIND indicators are enabled, event reporting is not enabled by default */
backend->cmer_indicator_reporting_enabled = false;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
return backend;
}
@ -1210,11 +1630,23 @@ void pa_bluetooth_native_backend_free(pa_bluetooth_backend *backend) {
if (backend->adapter_uuids_changed_slot)
pa_hook_slot_free(backend->adapter_uuids_changed_slot);
<<<<<<< HEAD
=======
if (backend->host_battery_level_changed_slot)
pa_hook_slot_free(backend->host_battery_level_changed_slot);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (backend->enable_shared_profiles)
native_backend_apply_profile_registration_change(backend, false);
if (backend->enable_hsp_hs)
profile_done(backend, PA_BLUETOOTH_PROFILE_HSP_HS);
<<<<<<< HEAD
=======
if (backend->upower)
pa_upower_backend_free(backend->upower);
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_dbus_connection_unref(backend->connection);

View file

@ -250,6 +250,9 @@ static pa_hook_result_t device_unlink_cb(pa_bluetooth_discovery *y, const pa_blu
pa_assert(d);
pa_assert(card);
if (d != card->transport->device)
return PA_HOOK_OK;
hf_audio_agent_card_removed(card->backend, card->path);
return PA_HOOK_OK;
@ -330,6 +333,7 @@ static int hf_audio_agent_transport_acquire(pa_bluetooth_transport *t, bool opti
* value from the Isoc USB endpoint in use by btusb and should be
* made available to userspace by the Bluetooth kernel subsystem.
*
<<<<<<< HEAD
* Set initial MTU to max size which is reported to be working (60 bytes)
* See also pa_bluetooth_transport::last_read_size handling.
*/
@ -337,6 +341,17 @@ static int hf_audio_agent_transport_acquire(pa_bluetooth_transport *t, bool opti
*imtu = 60;
if (omtu)
*omtu = 60;
=======
* Set initial MTU to max known payload length of HCI packet
* in USB Alternate Setting 5 (144 bytes)
* See also pa_bluetooth_transport::last_read_size handling
* and comment about MTU size in bt_prepare_encoder_buffer()
*/
if (imtu)
*imtu = 144;
if (omtu)
*omtu = 144;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
err = socket_accept(card->fd);
if (err < 0) {

View file

@ -254,8 +254,24 @@ static const char *transport_state_to_string(pa_bluetooth_transport_state_t stat
return "invalid";
}
<<<<<<< HEAD
static bool device_supports_profile(pa_bluetooth_device *device, pa_bluetooth_profile_t profile) {
bool show_hfp, show_hsp;
=======
bool pa_bluetooth_device_supports_profile(const pa_bluetooth_device *device, pa_bluetooth_profile_t profile) {
bool show_hfp, show_hsp, r;
pa_assert(device);
/* While discovery is being released adapters will be removed from devices,
* and there are no profiles to support without adapter.
*/
if (!device->adapter) {
pa_log_debug("Device %s (%s) has no adapter to support profile %s",
device->alias, device->address, pa_bluetooth_profile_to_string(profile));
return false;
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
if (device->enable_hfp_hf) {
show_hfp = pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_HF);
@ -267,8 +283,11 @@ static bool device_supports_profile(pa_bluetooth_device *device, pa_bluetooth_pr
switch (profile) {
case PA_BLUETOOTH_PROFILE_A2DP_SINK:
return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_A2DP_SINK);
r = !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_A2DP_SINK) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_A2DP_SOURCE));
break;
case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
<<<<<<< HEAD
return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_A2DP_SOURCE);
case PA_BLUETOOTH_PROFILE_HSP_HS:
return show_hsp
@ -280,11 +299,43 @@ static bool device_supports_profile(pa_bluetooth_device *device, pa_bluetooth_pr
return show_hfp && !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_HF);
case PA_BLUETOOTH_PROFILE_HFP_AG:
return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_AG);
=======
r = !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_A2DP_SOURCE) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_A2DP_SINK));
break;
case PA_BLUETOOTH_PROFILE_HSP_HS:
r = show_hsp
&& ( !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_HS) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HSP_AG)) ||
!!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_HS_ALT) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HSP_AG)) );
break;
case PA_BLUETOOTH_PROFILE_HSP_AG:
r = !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_AG) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HSP_HS)) ||
!!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_AG) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HSP_HS_ALT));
break;
case PA_BLUETOOTH_PROFILE_HFP_HF:
r = show_hfp
&& !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_HF) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HFP_AG));
break;
case PA_BLUETOOTH_PROFILE_HFP_AG:
r = !!(pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_AG) &&
pa_hashmap_get(device->adapter->uuids, PA_BLUETOOTH_UUID_HFP_HF));
break;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
case PA_BLUETOOTH_PROFILE_OFF:
default:
pa_assert_not_reached();
break;
}
pa_assert_not_reached();
pa_log_debug("Checking if device %s (%s) supports profile %s: %s",
device->alias, device->address, pa_bluetooth_profile_to_string(profile), r ? "true" : "false");
return r;
}
static bool device_is_profile_connected(pa_bluetooth_device *device, pa_bluetooth_profile_t profile) {
@ -299,7 +350,7 @@ static unsigned device_count_disconnected_profiles(pa_bluetooth_device *device)
unsigned count = 0;
for (profile = 0; profile < PA_BLUETOOTH_PROFILE_COUNT; profile++) {
if (!device_supports_profile(device, profile))
if (!pa_bluetooth_device_supports_profile(device, profile))
continue;
if (!device_is_profile_connected(device, profile))
@ -332,7 +383,7 @@ static void wait_for_profiles_cb(pa_mainloop_api *api, pa_time_event* event, con
if (device_is_profile_connected(device, profile))
continue;
if (!device_supports_profile(device, profile))
if (!pa_bluetooth_device_supports_profile(device, profile))
continue;
if (first)
@ -756,6 +807,10 @@ static void get_volume_reply(DBusPendingCall *pending, void *userdata) {
pa_bluetooth_transport *t;
uint16_t gain;
pa_volume_t volume;
<<<<<<< HEAD
=======
const char *error_name, *error_message;
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_assert(pending);
pa_assert_se(p = userdata);
@ -764,10 +819,25 @@ static void get_volume_reply(DBusPendingCall *pending, void *userdata) {
pa_assert_se(r = dbus_pending_call_steal_reply(pending));
if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
<<<<<<< HEAD
pa_log_error(DBUS_INTERFACE_PROPERTIES ".Get %s Volume failed: %s: %s",
dbus_message_get_path(p->message),
dbus_message_get_error_name(r),
pa_dbus_get_error_message(r));
=======
error_name = dbus_message_get_error_name(r);
error_message = pa_dbus_get_error_message(r);
if (pa_streq(error_name, DBUS_ERROR_INVALID_ARGS) && pa_streq(error_message, "No such property 'Volume'")) {
pa_log_warn(DBUS_INTERFACE_PROPERTIES ".Get %s Volume property not (yet) available",
dbus_message_get_path(p->message));
} else {
pa_log_error(DBUS_INTERFACE_PROPERTIES ".Get %s Volume failed: %s: %s",
dbus_message_get_path(p->message),
error_name,
error_message);
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
goto finish;
}
dbus_message_iter_init(r, &iter);
@ -1161,6 +1231,16 @@ bool pa_bluetooth_discovery_get_enable_msbc(pa_bluetooth_discovery *y)
return y->enable_msbc;
}
<<<<<<< HEAD
=======
pa_hashmap* pa_bluetooth_discovery_get_transports(pa_bluetooth_discovery *y) {
pa_assert(y);
pa_assert(PA_REFCNT_VALUE(y) > 0);
return y->transports;
}
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_address(pa_bluetooth_discovery *y, const char *remote, const char *local) {
pa_bluetooth_device *d;
void *state = NULL;
@ -1470,6 +1550,7 @@ static void adapter_free(pa_bluetooth_adapter *a) {
if (d->adapter == a)
device_set_adapter(d, NULL);
pa_hashmap_free(a->uuids);
pa_xfree(a->path);
pa_xfree(a->address);
pa_xfree(a);
@ -2081,7 +2162,11 @@ void pa_bluetooth_discovery_set_ofono_running(pa_bluetooth_discovery *y, bool is
pa_bluetooth_device *d;
PA_HASHMAP_FOREACH(d, y->devices, state) {
<<<<<<< HEAD
if (device_supports_profile(d, PA_BLUETOOTH_PROFILE_HFP_AG) || device_supports_profile(d, PA_BLUETOOTH_PROFILE_HFP_HF)) {
=======
if (pa_bluetooth_device_supports_profile(d, PA_BLUETOOTH_PROFILE_HFP_AG) || pa_bluetooth_device_supports_profile(d, PA_BLUETOOTH_PROFILE_HFP_HF)) {
>>>>>>> c1990dd02647405b0c13aab59f75d05cbb202336
DBusMessage *m;
pa_assert_se(m = dbus_message_new_method_call(BLUEZ_SERVICE, d->path, BLUEZ_DEVICE_INTERFACE, "Disconnect"));

Some files were not shown because too many files have changed in this diff Show more