Compare commits

..

No commits in common. "master" and "v14.99.2" have entirely different histories.

245 changed files with 22479 additions and 48387 deletions

1
.gitignore vendored
View file

@ -37,4 +37,3 @@ 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
# freedesktop/ci-templates repository which is the recommended way to set up CI
# wayland/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
@ -10,15 +10,6 @@
# there doesn't seem to be significant value to splitting the stages at the
# moment.
# Create merge request pipelines for open merge requests, branch pipelines
# otherwise. This allows MRs for new users to run CI.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
stages:
- container
- build
@ -28,21 +19,22 @@ 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.
FDO_DISTRIBUTION_TAG: '2023-08-13-00'
FDO_DISTRIBUTION_VERSION: '20.04'
FDO_DISTRIBUTION_TAG: '2021-03-01-02'
FDO_DISTRIBUTION_VERSION: '18.04'
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: 'freedesktop/ci-templates'
- project: 'wayland/ci-templates'
ref: 'master'
file: '/templates/ubuntu.yml'
build-container:
extends: .fdo.container-build@ubuntu
extends: .fdo.container-ifnot-exists@ubuntu
stage: container
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
@ -56,7 +48,6 @@ build-container:
check
curl
dbus-x11
doxygen
g++
gcc
gettext
@ -97,19 +88,17 @@ build-container:
wget
build-meson:
extends: .fdo.distribution-image@ubuntu
stage: build
image: $UBUNTU_IMAGE
script:
# 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
# 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
- python3 setup.py install
- cd ..
# needed to generate a version
- git fetch https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git --tags
# Do the actual build
- meson build -Dwebrtc-aec=enabled
- meson build
- cd build
- ninja
- ulimit -c 0 # don't dump core files on tests that are supposed to assert

View file

@ -28,10 +28,10 @@ Please take a look at the [coding style
documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/CodingStyle/)
on our wiki.
## Commit messages
## Commit messagse
We follow the standard git commit message format of a summary on the first line
(<=50 characters for preference, <=72 characters otherwise), followed by a new
(<=50 characterss for preference, <=72 characters otherwise), followed by a new
line, followed by a detailed commit message. An additional line at the end may
link to an issue being fixed by this MR.

300
NEWS
View file

@ -1,303 +1,3 @@
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
김인수
PulseAudio 15.0
Changes at a glance:
* Notes for end users
* Support for LDAC and AptX bluetooth codecs, plus "SBC XQ" (SBC with higher-quality parameters)
* Support for HFP bluetooth profiles
* Support for Bluetooth A2DP AVRCP Absolute Volume
* ALSA path configuration files can now be placed in user home directory
* module-virtual-surround-sink rewritten
* More options for module-jackdbus-detect
* Improved hardware support
* SteelSeries Arctis 9
* HP Thunderbolt Dock 120W G2
* Behringer U-Phoria UMC22
* OnePlus Type-C Bullets
* Sennheiser GSX 1000/1200 PRO
* New udev variable: PULSE_MODARGS
* max_latency_msec argument added to module-null-source
* module-filter-apply can take filter parameters from device properties
* module-match can now be loaded multiple times
* Improvements to FreeBSD support
* Windows support added to Meson
* Additional commands for pactl
* Card profiles can be set to sticky
* Notes for application developers
* New API for sending messages from clients to PulseAudio objects
* New mechanism for applications to disable shared memory on their connection to PulseAudio
* Notes for packagers
* Autotools build system have been dropped
* The startup script can now read additional configuration from the /etc/pulse/default.pa.d/ directory
* Option to build client library and utilities only
* Avoid loading X11 modules on Wayland (GNOME-only for now)
* OSS support is now configurable in Meson
* Valgrind support is now configurable in Meson
Detailed change log:
https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/
Contributors
Alexey Rubtsov
Alper Nebi Yasak
Anders Jonsson
Arun Raghavan
Ben Buchwald
Benjamin Valentin
Carlos Garnacho
Carmen Bianca Bakker
Christopher Arndt
Christopher Snowhill
David
Dusan Kazik
Edward Lee
Emilio Herrera
Evan Miller
Fabian Affolter
Faidon Liambotis
Felipe Sateler
Frédéric Danis
Georg Chini
Greg V
Göran Uddeborg
Hela Basa
Henri Chain
Hui Wang
Igor V. Kovalenko
Ilja van Sprundel
Jaechul Lee
James Bottomley
Jan Alexander Steffens (heftig)
Jan Kuparinen
Jaroslav Kysela
Jason Nader
Johannes Wolf
Julien Humbert
Kai-Heng Feng
Karl Ove Hufthammer
Klaas van Schelven
Laurent Bigonville
Laurențiu Nicola
Lyndon Brown
Marijn Suijten
Martin Wilck
Mattias Jernberg
Milo Casagrande
Nazar Mokrynskyi
Oğuz Ersen
Patrick Gaskin
Patrick McLean
Paul Seyfert
Pierre Ossman
Piotr Drąg
Pjotr Vertaalt
Ricky Tigg
Robin Lahtinen
Samuel Thibault
Sanchayan Maity
Scott Worley
Sebastian Krzyszkowiak
SimonP
Takashi Sakamoto
Tanu Kaskinen
Tobias Weise
Toni Estevez
Yaron Shahrabani
Yuri Chornoivan
morrishoresh
pseyfert
scootergrisen
simmon
PulseAudio 14.2
A bug fix release.

View file

@ -1,8 +1,3 @@
doxygen = find_program('doxygen', required: get_option('doxygen'))
if not doxygen.found()
subdir_done()
endif
cdata.set('DOXYGEN_OUTPUT_DIRECTORY', meson.current_build_dir())
doxygen_conf = configure_file(
@ -12,4 +7,4 @@ doxygen_conf = configure_file(
)
run_target('doxygen',
command : [doxygen, doxygen_conf])
command : ['doxygen', doxygen_conf])

View file

@ -14,24 +14,22 @@ if get_option('daemon')
]
endif
if get_option('client')
manpages += [
['pacat', '1', ['paplay', 'parec', 'parecord', 'pamon']],
['pactl', '1'],
['pulse-client.conf', '5'],
]
if cdata.has('HAVE_OSS_WRAPPER')
manpages += [
['pacat', '1', ['paplay', 'parec', 'parecord', 'pamon']],
['pactl', '1'],
['pulse-client.conf', '5'],
['padsp', '1'],
]
endif
if cdata.has('HAVE_OSS_WRAPPER')
manpages += [
['padsp', '1'],
]
endif
if x11_dep.found()
manpages += [
['pax11publish', '1'],
]
endif
if x11_dep.found()
manpages += [
['pax11publish', '1'],
]
endif
# FIXME: Add esdcompat if HAVE_ESOUND

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. The special names @DEFAULT_SINK@, @DEFAULT_SOURCE@ and @DEFAULT_MONITOR@ can be used to specify the default sink, source and monitor respectively.</p></optdesc>
<optdesc><p>Specify the symbolic name of the sink/source to play/record this stream on/from.</p></optdesc>
</option>
<option>

View file

@ -53,12 +53,6 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<optdesc><p>Choose the server to connect to.</p></optdesc>
</option>
<option>
<p><opt>-f | --format</opt><arg>=FORMAT</arg></p>
<optdesc><p>Choose output format, available options are "text" or "json".</p></optdesc>
</option>
<option>
<p><opt>-n | --client-name</opt><arg>=NAME</arg></p>
@ -69,7 +63,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<section name="Commands">
<p>
When supplied as arguments to the commands below, the special names \@DEFAULT_SINK@, \@DEFAULT_SOURCE@ and \@DEFAULT_MONITOR@
When supplied as arguments to the commands below, the special names \@DEFAULT_SINK@, \@DEFAULT_SOURCE@ and \@DEFAULT_MONITOR@
can be used to specify the default sink, source and monitor respectively.
</p>
@ -174,9 +168,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>set-default-sink</opt> <arg>SINK</arg></p>
<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>
<optdesc><p>Make the specified sink (identified by its symbolic name or numerical index) the default sink.</p></optdesc>
</option>
<option>
@ -191,9 +183,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>set-default-source</opt> <arg>SOURCE</arg></p>
<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>
<optdesc><p>Make the specified source (identified by its symbolic name or numerical index) the default source.</p></optdesc>
</option>
<option>

View file

@ -143,10 +143,8 @@ 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. 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>
name.</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 server to connect
<p><opt>default-server=</opt> The default sever to connect
to. The environment variable <opt>$PULSE_SERVER</opt> takes
precedence.</p>
</option>

View file

@ -1,12 +1,10 @@
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.56.0',
default_options : [ 'c_std=gnu11', 'cpp_std=c++17' ]
project('pulseaudio', 'c', 'cpp',
version : run_command(find_program('git-version-gen'), join_paths(meson.current_source_dir(), '.tarball-version')).stdout().strip(),
meson_version : '>= 0.50.0',
default_options : [ 'c_std=gnu11', 'cpp_std=c++11' ]
)
if not meson.is_subproject()
meson.add_dist_script('scripts/save-tarball-version.sh', meson.project_version())
endif
meson.add_dist_script('scripts/save-tarball-version.sh', meson.project_version())
pa_version_str = meson.project_version()
# For tarballs, the first split will do nothing, but for builds in git, we
@ -27,7 +25,7 @@ pa_protocol_version = 35
# The stable ABI for client applications, for the version info x:y:z
# always will hold x=z
libpulse_version_info = [24, 3, 24]
libpulse_version_info = [24, 0, 24]
# A simplified, synchronous, ABI-stable interface for client
# applications, for the version info x:y:z always will hold x=z
@ -55,8 +53,6 @@ libpulse_mainloop_glib_version = '@0@.@1@.@2@'.format(
libpulse_mainloop_glib_version_info[1],
)
i18n = import('i18n')
# Paths
prefix = get_option('prefix')
@ -72,7 +68,6 @@ 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')
po_dir = join_paths(meson.current_source_dir(), 'po')
if host_machine.system() == 'windows'
# Windows only supports loading libraries from the same dir as the executable
@ -90,12 +85,7 @@ pulsesysconfdir = join_paths(sysconfdir, 'pulse')
modlibexecdir = get_option('modlibexecdir')
if modlibexecdir == ''
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
modlibexecdir = join_paths(libdir, 'pulse-' + pa_version_major_minor, 'modules')
endif
padsplibdir = get_option('padsplibdir')
@ -123,7 +113,7 @@ bashcompletiondir = get_option('bashcompletiondir')
if bashcompletiondir == ''
bash_completion_dep = dependency('bash-completion', required : false)
if bash_completion_dep.found()
bashcompletiondir = bash_completion_dep.get_variable(pkgconfig : 'completionsdir')
bashcompletiondir = bash_completion_dep.get_pkgconfig_variable('completionsdir')
else
bashcompletiondir = join_paths(datadir, 'bash-completion', 'completions')
endif
@ -150,11 +140,7 @@ 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())
if host_machine.system() == 'windows'
cdata.set_quoted('PA_SOEXT', '.dll')
else
cdata.set_quoted('PA_SOEXT', '.so')
endif
cdata.set_quoted('PA_SOEXT', '.so')
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'))
@ -166,12 +152,13 @@ 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_DATA_DIR', alsadatadir)
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('DESKTOPFILEDIR', join_paths(datadir, 'applications'))
cdata.set_quoted('PULSE_LOCALEDIR', localedir)
cdata.set_quoted('GETTEXT_PACKAGE', 'pulseaudio')
cdata.set('ENABLE_NLS', 1)
cdata.set('top_srcdir', meson.project_source_root())
cdata.set('top_srcdir', meson.source_root())
# Platform specifics
# First some defaults to keep config file generation happy
@ -190,7 +177,6 @@ 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)
@ -230,6 +216,7 @@ endif
check_headers = [
'arpa/inet.h',
'byteswap.h',
'cpuid.h',
'dlfcn.h',
'execinfo.h',
'grp.h',
@ -289,19 +276,6 @@ if cc.has_header_symbol('pthread.h', 'PTHREAD_PRIO_INHERIT')
cdata.set('HAVE_PTHREAD_PRIO_INHERIT', 1)
endif
# Headers which are usable
check_usable_headers = [
'cpuid.h',
]
foreach h : check_usable_headers
if cc.check_header(h)
define = 'HAVE_' + h.underscorify().to_upper()
cdata.set(define, 1)
endif
endforeach
# Functions
check_functions = [
@ -430,7 +404,7 @@ 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.
if host_machine.system() != 'windows' and host_machine.system() != 'darwin'
if host_machine.system() != 'windows'
nodelete_link_args = ['-Wl,-z,nodelete']
else
nodelete_link_args = []
@ -439,7 +413,6 @@ endif
# Code coverage
if get_option('gcov')
add_languages('cpp', native: false)
add_project_arguments('--coverage', language: ['c', 'cpp'])
add_project_link_arguments('--coverage', language: ['c', 'cpp'])
endif
@ -505,24 +478,22 @@ endif
need_libatomic_ops = false
atomictest = '''int main() {
atomictest = '''void func() {
volatile int atomic = 2;
__sync_bool_compare_and_swap (&atomic, 2, 3);
return 0;
}
'''
if cc.links(atomictest)
if cc.compiles(atomictest)
cdata.set('HAVE_ATOMIC_BUILTINS', 1)
newatomictest = '''int main() {
newatomictest = '''void func() {
int c = 0;
__atomic_store_n(&c, 4, __ATOMIC_SEQ_CST);
return 0;
}
'''
if(cc.links(newatomictest))
if(cc.compiles(newatomictest))
cdata.set('HAVE_ATOMIC_BUILTINS_MEMORY_MODEL', 1)
endif
@ -594,245 +565,219 @@ if host_machine.cpu_family() == 'arm'
endif
# NEON checks are automatically done by the unstable-simd module
# Dependencies common to client, daemon and modules
if get_option('daemon')
# FIXME: make sure it's >= 2.2
ltdl_dep = cc.find_library('ltdl', required : true)
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)
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
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
gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : get_option('gsettings'))
if gio_dep.found()
cdata.set('HAVE_GSETTINGS', 1)
endif
glib_dep = dependency('glib-2.0', version : '>= 2.28.0', required: get_option('glib'))
if glib_dep.found()
cdata.set('HAVE_GLIB', 1)
cdata.set('HAVE_GLIB20', 1) # to match the AM_CONDITIONAL for CMake file generation
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)
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()
cdata.set('HAVE_SYSTEMD_LOGIN', 1)
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
x11_dep = dependency('x11-xcb', required : get_option('x11'))
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
# OSS support
# Module dependencies
if cc.has_header('sys/soundcard.h', required: get_option('oss-output'))
# OSS output via daemon module-detect
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)
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)
endif
sbc_dep = dependency('sbc', version : '>= 1.0', required : false)
if get_option('bluez5')
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
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
if fftw_dep.found()
cdata.set('HAVE_FFTW', 1)
endif
# 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)
endif
gtk_dep = dependency('gtk+-3.0', required : get_option('gtk'))
if gtk_dep.found()
cdata.set('HAVE_GTK', 1)
endif
jack_dep = dependency('jack', version : '>= 0.117.0', required : get_option('jack'))
if jack_dep.found()
cdata.set('HAVE_JACK', 1)
endif
# Daemon and module dependencies
lirc_dep = dependency('lirc', required : get_option('lirc'))
if lirc_dep.found()
cdata.set('HAVE_LIRC', 1)
endif
if get_option('daemon')
# FIXME: make sure it's >= 2.2
ltdl_dep = cc.find_library('ltdl', required : true)
openssl_dep = dependency('openssl', version : '>= 0.9', required : get_option('openssl'))
if openssl_dep.found()
cdata.set('HAVE_OPENSSL', 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)
speex_dep = dependency('speexdsp', version : '>= 1.2', required : get_option('speex'))
if speex_dep.found()
cdata.set('HAVE_SPEEX', 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
udev_dep = dependency('libudev', version : '>= 143', required : get_option('udev'))
if udev_dep.found()
cdata.set('HAVE_UDEV', 1)
endif
if get_option('legacy-database-entry-format')
cdata.set('ENABLE_LEGACY_DATABASE_ENTRY_FORMAT', 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('stream-restore-clear-old-devices')
cdata.set('STREAM_RESTORE_CLEAR_OLD_DEVICES', 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'))
if get_option('running-from-build-tree')
cdata.set('HAVE_RUNNING_FROM_BUILD_TREE', 1)
endif
have_gstreamer = false
if gst_dep.found() and gstapp_dep.found() and gstrtp_dep.found()
have_gstreamer = true
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_variable(pkgconfig: '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
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
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
# 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
@ -840,90 +785,84 @@ check_dep = dependency('check', version : '>= 0.9.10', required : get_option('te
# Subdirs
subdir('doxygen')
if get_option('client')
subdir('po')
if get_option('doxygen')
subdir('doxygen')
endif
subdir('po')
if get_option('man')
subdir('man')
endif
subdir('shell-completion/bash')
subdir('shell-completion/zsh')
subdir('src')
if get_option('client')
subdir('vala')
endif
subdir('vala')
# Now generate config.h from everything above
configure_file(output : 'config.h', configuration : cdata)
if get_option('client')
# pkg-config files
# pkg-config files
pc_cdata = configuration_data()
pc_cdata = configuration_data()
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.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_files = [
'libpulse.pc',
'libpulse-simple.pc',
]
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,
)
if glib_dep.found()
pc_files += 'libpulse-mainloop-glib.pc'
endif
foreach file : pc_files
configure_file(
input : 'PulseAudioConfigVersion.cmake.in',
output : 'PulseAudioConfigVersion.cmake',
configuration: cdata,
install : true,
install_dir : cmakedir,
)
input : file + '.in',
output : file,
configuration : pc_cdata,
install_dir : pkgconfigdir)
endforeach
endif # client
# 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,
)
############################################################
@ -954,67 +893,49 @@ summary = [
# 'LIBS: @0@'.format(${LIBS}),
'',
'Enable pulseaudio daemon: @0@'.format(get_option('daemon')),
'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()),
' 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 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}),
'Enable GLib 2: @0@'.format(glib_dep.found()),
'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),
'Enable Gtk+ 3: @0@'.format(gtk_dep.found()),
'Enable Avahi: @0@'.format(avahi_dep.found()),
'Enable Jack: @0@'.format(jack_dep.found()),
'Enable Async DNS: @0@'.format(asyncns_dep.found()),
'Enable LIRC: @0@'.format(lirc_dep.found()),
'Enable D-Bus: @0@'.format(dbus_dep.found()),
' Enable BlueZ 5: @0@'.format(get_option('bluez5')),
' Enable native headsets: @0@'.format(get_option('bluez5-native-headset')),
' Enable ofono headsets: @0@'.format(get_option('bluez5-ofono-headset')),
' Enable GStreamer based codecs: @0@'.format(have_bluez5_gstreamer),
'Enable udev: @0@'.format(udev_dep.found()),
' Enable HAL->udev compat: @0@'.format(get_option('hal-compat')),
'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 GStreamer: @0@'.format(have_gstreamer),
'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()),
'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')),
'',
'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:',
@ -1027,48 +948,47 @@ summary += [
# 'Force preopen: @0@'.format(${FORCE_PREOPEN}),
# 'Preopened modules: @0@'.format(${PREOPEN_MODS}),
]
endif
message('\n '.join(summary))
# Sanity checks
if get_option('daemon') and not speex_dep.found() and not webrtc_dep.found() and not get_option('adrian-aec')
if 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 get_option('daemon') and samplerate_dep.found()
if samplerate_dep.found()
warning('Support for libsamplerate is DEPRECATED')
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))
if host_machine.system() != 'windows'
if 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 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 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))
endif
endif

View file

@ -1,11 +1,8 @@
option('daemon',
type : 'boolean', value : true,
description : 'Enable building and installation of pulseaudio daemon and supporting configuration files')
option('client',
type : 'boolean', value : true,
description : 'Build and install pulseaudio client libraries and utilities')
option('doxygen',
type : 'feature',
type : 'boolean', value : true,
description : 'Enable building and installation of documentation generated with doxygen')
option('gcov',
type : 'boolean', value : false,
@ -14,7 +11,7 @@ option('man',
type : 'boolean',
description : 'Enable building and installation of man pages')
option('tests',
type : 'feature',
type : 'boolean',
description : 'Enable unit tests')
option('system_user',
@ -88,7 +85,7 @@ option('avahi',
type : 'feature', value : 'auto',
description : 'Optional Avahi support')
option('bluez5',
type : 'feature', value : 'auto',
type : 'boolean', value : 'true',
description : 'Optional BlueZ 5 support')
option('bluez5-gstreamer',
type : 'feature', value: 'auto',
@ -99,9 +96,6 @@ 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')
@ -118,7 +112,7 @@ option('gsettings',
type : 'feature', value : 'auto',
description : 'Optional GSettings support')
option('gstreamer',
type : 'feature', value : 'auto',
type : 'feature', value : 'disabled',
description : 'Optional GStreamer dependency for media-related functionality')
option('gtk',
type : 'feature', value : 'auto',
@ -168,9 +162,6 @@ 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,8 +48,3 @@ zh_CN
zh_TW
eo
si
ka
eu
ar
sl
ro

View file

@ -170,7 +170,6 @@ 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

612
po/af.po

File diff suppressed because it is too large Load diff

2903
po/ar.po

File diff suppressed because it is too large Load diff

619
po/as.po

File diff suppressed because it is too large Load diff

828
po/be.po

File diff suppressed because it is too large Load diff

2106
po/bg.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

647
po/ca.po

File diff suppressed because it is too large Load diff

667
po/cs.po

File diff suppressed because it is too large Load diff

641
po/da.po

File diff suppressed because it is too large Load diff

727
po/de.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1074
po/el.po

File diff suppressed because it is too large Load diff

612
po/eo.po

File diff suppressed because it is too large Load diff

1668
po/es.po

File diff suppressed because it is too large Load diff

2902
po/eu.po

File diff suppressed because it is too large Load diff

742
po/fi.po

File diff suppressed because it is too large Load diff

673
po/fr.po

File diff suppressed because it is too large Load diff

765
po/gl.po

File diff suppressed because it is too large Load diff

619
po/gu.po

File diff suppressed because it is too large Load diff

616
po/he.po

File diff suppressed because it is too large Load diff

2341
po/hi.po

File diff suppressed because it is too large Load diff

782
po/hr.po

File diff suppressed because it is too large Load diff

930
po/hu.po

File diff suppressed because it is too large Load diff

913
po/id.po

File diff suppressed because it is too large Load diff

638
po/it.po

File diff suppressed because it is too large Load diff

631
po/ja.po

File diff suppressed because it is too large Load diff

3046
po/ka.po

File diff suppressed because it is too large Load diff

614
po/kk.po

File diff suppressed because it is too large Load diff

619
po/kn.po

File diff suppressed because it is too large Load diff

1061
po/ko.po

File diff suppressed because it is too large Load diff

701
po/lt.po

File diff suppressed because it is too large Load diff

View file

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

619
po/ml.po

File diff suppressed because it is too large Load diff

619
po/mr.po

File diff suppressed because it is too large Load diff

665
po/nl.po

File diff suppressed because it is too large Load diff

628
po/nn.po

File diff suppressed because it is too large Load diff

645
po/oc.po

File diff suppressed because it is too large Load diff

619
po/or.po

File diff suppressed because it is too large Load diff

619
po/pa.po

File diff suppressed because it is too large Load diff

627
po/pl.po

File diff suppressed because it is too large Load diff

1091
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

3412
po/ro.po

File diff suppressed because it is too large Load diff

1311
po/ru.po

File diff suppressed because it is too large Load diff

622
po/si.po

File diff suppressed because it is too large Load diff

619
po/sk.po

File diff suppressed because it is too large Load diff

3376
po/sl.po

File diff suppressed because it is too large Load diff

619
po/sr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

648
po/sv.po

File diff suppressed because it is too large Load diff

619
po/ta.po

File diff suppressed because it is too large Load diff

619
po/te.po

File diff suppressed because it is too large Load diff

790
po/tr.po

File diff suppressed because it is too large Load diff

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

View file

@ -3,33 +3,25 @@ if bashcompletiondir != 'no'
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
aliases += [
'pacat',
'pactl',
'padsp',
'paplay',
'parec',
'parecord',
]
install_data('pulseaudio', install_dir : bashcompletiondir)
foreach alias : aliases
dst = join_paths(bashcompletiondir, alias)
cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pactl', dst)
cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pulseaudio', dst)
meson.add_install_script('sh', '-c', cmd)
endforeach
endif

View file

@ -109,20 +109,19 @@ in_array() {
}
_pactl() {
local cur prev words cword preprev word command
local cur prev words cword preprev 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 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
suspend-sink suspend-source set-card-profile set-default-sink
set-sink-port set-default-source set-source-port set-sink-volume
set-source-volume set-sink-input-volume set-source-output-volume
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)
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)
_init_completion -n = || return
preprev=${words[$cword-2]}
@ -187,8 +186,6 @@ _pactl() {
remove-sample) ;; # TODO
get-default*) ;;
load-module)
comps=$(__all_modules)
COMPREPLY=($(compgen -W '${comps[*]}' -- "$cur"))
@ -258,7 +255,7 @@ _pactl() {
complete -F _pactl pactl
_pacmd() {
local cur prev words cword preprev word command
local cur prev words cword preprev command
local comps
local flags='-h --help --version'
local commands=(exit help list-modules list-cards list-sinks list-sources list-clients
@ -503,7 +500,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-pid-file=
--log-backtrace= -p --dl-search-path= --resample-method= --use-pit-file=
--no-cpu-limit= --disable-shm= --enable-memfd= -L --load= -F --file= -C -n'
_init_completion -n = || return

View file

@ -18,12 +18,10 @@ _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');;
@ -259,22 +257,16 @@ _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'
@ -500,15 +492,11 @@ _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,5 +1,3 @@
if get_option('client')
if zshcompletiondir != 'no'
install_data('_pulseaudio', install_dir : zshcompletiondir)
endif
if zshcompletiondir != 'no'
install_data('_pulseaudio', install_dir : zshcompletiondir)
endif

1
src/.gitignore vendored
View file

@ -71,7 +71,6 @@ 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 error, warn, notice, info, debug)."));
pa_log(_("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."));
goto fail;
}
} else {

View file

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

View file

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

View file

@ -69,6 +69,5 @@ load-module module-position-event-sounds
### Allow including a system.pa.d directory, which if present, can be used
### for additional configuration snippets.
### Note that those snippet files must have a .pa file extension, not .conf
.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,47 +182,37 @@ if host_machine.system() == 'windows'
else
libpulsecommon_sources += [
'pulsecore/mutex-posix.c',
'pulsecore/poll-posix.c',
'pulsecore/thread-posix.c',
'pulsecore/semaphore-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
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 = 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, tcpwrap_dep, platform_socket_dep, execinfo_dep,
],
implicit_include_directories : false)
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
subdir('pulse')
endif
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
subdir('pulse')
if get_option('daemon')
subdir('pulsecore')
subdir('daemon')
subdir('modules')
endif
subdir('tests')
if get_option('tests')
subdir('tests')
endif
subdir('utils')

View file

@ -107,15 +107,13 @@ 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"
# 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"
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"
ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{PULSE_PROFILE_SET}="texas-instruments-pcm2902.conf"
ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{PULSE_PROFILE_SET}="behringer-umc22.conf"
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"
@ -125,8 +123,6 @@ 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"
# ID 1038:1282 is for SteelSeries GameDAC
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1282", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# ID 1038:12c4 is for Arctis 9
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12c4", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# Lucidsound LS31
@ -168,16 +164,6 @@ 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"
# 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"
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,44 +2851,41 @@ static int path_verify(pa_alsa_path *p) {
return 0;
}
static char *get_data_path(const char *data_dir, const char *data_type, const char *fname) {
char *result;
static char *get_path_config_path(const char *paths_dir, const char *fname) {
char *path_config_path;
char *dir;
char *data_home;
pa_dynarray *data_dirs;
if (data_dir) {
result = pa_maybe_prefix_path(fname, data_dir);
if (access(result, R_OK) == 0)
return result;
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(result);
pa_xfree(path_config_path);
}
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
if (pa_run_from_build_tree()) {
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;
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(result);
pa_xfree(path_config_path);
}
#endif
if (pa_get_data_home_dir(&data_home) == 0) {
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "%s", data_home, data_type);
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", data_home);
pa_xfree(data_home);
result = pa_maybe_prefix_path(fname, dir);
path_config_path = pa_maybe_prefix_path(fname, dir);
pa_xfree(dir);
if (access(result, R_OK) == 0)
return result;
if (access(path_config_path, R_OK) == 0)
return path_config_path;
else
pa_xfree(result);
pa_xfree(path_config_path);
}
if (pa_get_data_dirs(&data_dirs) == 0) {
@ -2896,27 +2893,24 @@ static char *get_data_path(const char *data_dir, const char *data_type, const ch
const char *n;
PA_DYNARRAY_FOREACH(n, data_dirs, idx) {
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "%s", n, data_type);
result = pa_maybe_prefix_path(fname, dir);
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);
if (access(result, R_OK) == 0) {
if (access(path_config_path, R_OK) == 0) {
pa_dynarray_free(data_dirs);
return result;
return path_config_path;
}
else {
pa_xfree(result);
pa_xfree(path_config_path);
}
}
pa_dynarray_free(data_dirs);
}
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;
path_config_path = pa_maybe_prefix_path(fname, PA_ALSA_PATHS_DIR);
return path_config_path;
}
pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) {
@ -2983,7 +2977,7 @@ 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;
fn = get_data_path(paths_dir, "paths", fname);
fn = get_path_config_path(paths_dir, fname);
pa_log_info("Loading path config: %s", fn);
@ -4977,9 +4971,11 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
if (!fname)
fname = "default.conf";
fn = get_data_path(NULL, "profile-sets", fname);
pa_log_info("Loading profile set: %s", fn);
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);
r = pa_config_parse(fn, NULL, items, NULL, false, ps);
pa_xfree(fn);
@ -5078,7 +5074,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, NULL, NULL, exact_channels);
&try_buffer_size, 0, 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,9 +342,6 @@ 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,12 +52,7 @@
#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>
@ -83,15 +78,11 @@
#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 */
@ -165,18 +156,11 @@ 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;
@ -496,13 +480,9 @@ 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;
@ -975,10 +955,7 @@ static void update_smoother(struct userdata *u) {
snd_pcm_sframes_t delay = 0;
int64_t position;
int err;
pa_usec_t now1 = 0;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_usec_t now1 = 0, now2;
snd_pcm_status_t *status;
snd_htimestamp_t htstamp = { 0, 0 };
@ -1001,16 +978,13 @@ 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;
@ -1021,26 +995,18 @@ 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;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_usec_t now1, now2;
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);
@ -1070,11 +1036,7 @@ 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);
@ -1532,7 +1494,6 @@ static void sink_set_volume_cb(pa_sink *s) {
pa_cvolume r;
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
bool deferred_volume = !!(s->flags & PA_SINK_DEFERRED_VOLUME);
bool write_to_hw = !deferred_volume;
pa_assert(u);
pa_assert(u->mixer_path);
@ -1541,14 +1502,7 @@ static void sink_set_volume_cb(pa_sink *s) {
/* Shift up by the base volume */
pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
/* If the set_volume() is called because of ucm active_port changing, the
* volume should be written to hw immediately, otherwise this volume will be
* overridden by calling get_volume_cb() which is called by
* _disdev/_enadev() -> io_mixer_callback() */
if (u->ucm_context && s->port_changing)
write_to_hw = true;
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, write_to_hw) < 0)
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, !deferred_volume) < 0)
return;
/* Shift down by the base volume, so that 0dB becomes maximum volume */
@ -1721,7 +1675,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);
return pa_alsa_ucm_set_port(u->ucm_context, p, true);
}
static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
@ -1822,22 +1776,12 @@ 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;
}
@ -1847,17 +1791,11 @@ 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;
}
@ -1866,15 +1804,8 @@ 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 */
}
@ -2008,11 +1939,7 @@ 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;
}
@ -2046,11 +1973,7 @@ 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);
@ -2190,7 +2113,8 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
NULL, (pa_free_cb_t) pa_alsa_mixer_free);
mdev = mapping ? pa_proplist_gets(mapping->proplist, "alsa.mixer_device") : NULL;
if (mapping)
mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
if (mdev) {
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, true);
} else {
@ -2239,7 +2163,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) < 0)
if (pa_alsa_ucm_set_port(u->ucm_context, u->sink->active_port, true) < 0)
return -1;
}
@ -2350,11 +2274,7 @@ 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;
void *state = NULL;
#ifdef USE_SMOOTHER_2
snd_pcm_info_t* pcm_info;
const char *id;
#endif
void *state;
pa_assert(m);
pa_assert(ma);
@ -2467,7 +2387,6 @@ 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,
@ -2477,7 +2396,6 @@ 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)
@ -2527,9 +2445,7 @@ 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,
&u->supported_formats, &u->supported_rates,
mapping)))
&b, &d, mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
@ -2543,9 +2459,7 @@ 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,
&u->supported_formats, &u->supported_rates,
profile_set, &mapping)))
&b, &d, profile_set, &mapping)))
goto fail;
} else {
@ -2556,9 +2470,7 @@ 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,
&u->supported_formats, &u->supported_rates,
false)))
&b, &d, false)))
goto fail;
}
@ -2604,11 +2516,13 @@ 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;
@ -2692,25 +2606,6 @@ 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;
@ -2914,11 +2809,7 @@ 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,12 +47,7 @@
#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>
@ -76,15 +71,11 @@
#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)
@ -149,17 +140,10 @@ 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;
@ -468,13 +452,9 @@ 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;
@ -482,12 +462,7 @@ 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);
@ -902,10 +877,7 @@ static void update_smoother(struct userdata *u) {
snd_pcm_sframes_t delay = 0;
uint64_t position;
int err;
pa_usec_t now1 = 0;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_usec_t now1 = 0, now2;
snd_pcm_status_t *status;
snd_htimestamp_t htstamp = { 0, 0 };
@ -928,16 +900,12 @@ 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);
@ -945,27 +913,18 @@ 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;
#ifndef USE_SMOOTHER_2
pa_usec_t now2;
#endif
pa_usec_t now1, now2;
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;
}
@ -1406,7 +1365,6 @@ static void source_set_volume_cb(pa_source *s) {
pa_cvolume r;
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
bool deferred_volume = !!(s->flags & PA_SOURCE_DEFERRED_VOLUME);
bool write_to_hw = !deferred_volume;
pa_assert(u);
pa_assert(u->mixer_path);
@ -1415,14 +1373,7 @@ static void source_set_volume_cb(pa_source *s) {
/* Shift up by the base volume */
pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
/* If the set_volume() is called because of ucm active_port changing, the
* volume should be written to hw immediately, otherwise this volume will be
* overridden by calling get_volume_cb() which is called by
* _disdev/_enadev() -> io_mixer_callback() */
if (u->ucm_context && s->port_changing)
write_to_hw = true;
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, write_to_hw) < 0)
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, !deferred_volume) < 0)
return;
/* Shift down by the base volume, so that 0dB becomes maximum volume */
@ -1595,7 +1546,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);
return pa_alsa_ucm_set_port(u->ucm_context, p, false);
}
static int source_set_port_cb(pa_source *s, pa_device_port *p) {
@ -1637,22 +1588,12 @@ 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;
}
@ -1662,17 +1603,11 @@ 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;
}
@ -1681,15 +1616,7 @@ 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) {
@ -1723,11 +1650,7 @@ 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;
}
@ -1755,11 +1678,7 @@ 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); */
@ -1894,7 +1813,8 @@ static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char
u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
NULL, (pa_free_cb_t) pa_alsa_mixer_free);
mdev = mapping ? pa_proplist_gets(mapping->proplist, "alsa.mixer_device") : NULL;
if (mapping)
mdev = pa_proplist_gets(mapping->proplist, "alsa.mixer_device");
if (mdev) {
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, false);
} else {
@ -1943,7 +1863,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) < 0)
if (pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0)
return -1;
}
@ -2158,7 +2078,6 @@ 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,
@ -2168,7 +2087,6 @@ 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)
@ -2218,7 +2136,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, &u->supported_formats, &u->supported_rates, mapping)))
&b, &d, mapping)))
goto fail;
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
@ -2232,7 +2150,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, &u->supported_formats, &u->supported_rates, profile_set, &mapping)))
&b, &d, profile_set, &mapping)))
goto fail;
} else {
@ -2243,7 +2161,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, &u->supported_formats, &u->supported_rates, false)))
&b, &d, false)))
goto fail;
}
@ -2279,11 +2197,13 @@ 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;
@ -2366,10 +2286,6 @@ 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;
@ -2531,11 +2447,7 @@ 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,13 +140,12 @@ 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, pa_alsa_profile *new_profile, pa_alsa_profile *old_profile);
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_get_verb(snd_use_case_mgr_t *uc_mgr, const char *verb_name, const char *verb_desc, pa_alsa_ucm_verb **p_verb);
@ -158,14 +157,14 @@ void pa_alsa_ucm_add_ports(
pa_card *card,
snd_pcm_t *pcm_handle,
bool ignore_dB);
void pa_alsa_ucm_add_port(
void pa_alsa_ucm_add_ports_combination(
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);
int pa_alsa_ucm_set_port(pa_alsa_ucm_mapping_context *context, pa_device_port *port, bool is_sink);
void pa_alsa_ucm_free(pa_alsa_ucm_config *ucm);
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
@ -222,8 +221,11 @@ struct pa_alsa_ucm_modifier {
pa_proplist *proplist;
pa_idxset *conflicting_devices;
pa_idxset *supported_devices;
int n_confdev;
int n_suppdev;
const char **conflicting_devices;
const char **supported_devices;
pa_direction_t action_direction;
@ -251,7 +253,6 @@ 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);
@ -262,23 +263,21 @@ struct pa_alsa_ucm_mapping_context {
pa_alsa_ucm_config *ucm;
pa_direction_t direction;
pa_alsa_ucm_device *ucm_device;
pa_alsa_ucm_modifier *ucm_modifier;
};
struct pa_alsa_ucm_profile_context {
pa_alsa_ucm_verb *verb;
pa_idxset *ucm_devices;
pa_idxset *ucm_modifiers;
};
struct pa_alsa_ucm_port_data {
pa_alsa_ucm_config *ucm;
pa_device_port *core_port;
pa_alsa_ucm_device *device;
/* A single port will be associated with multiple devices if it represents
* a combination of devices. */
pa_dynarray *devices; /* pa_alsa_ucm_device */
/* verb name -> pa_alsa_path for volume control */
/* profile name -> pa_alsa_path for volume control */
pa_hashmap *paths;
/* Current path, set when activating verb */
/* Current path, set when activating profile */
pa_alsa_path *path;
/* ELD info */

View file

@ -40,7 +40,6 @@
#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"
@ -523,8 +522,6 @@ 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) {
@ -563,8 +560,6 @@ 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) {
@ -592,8 +587,6 @@ 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) {
@ -618,8 +611,6 @@ 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);
@ -640,8 +631,6 @@ 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;
@ -671,8 +660,6 @@ 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)
@ -696,8 +683,6 @@ 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;
@ -725,12 +710,6 @@ 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,
@ -804,8 +783,6 @@ 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;
@ -827,8 +804,6 @@ 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);
@ -1431,31 +1406,13 @@ 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,
352800, 384000,
705600, 768000 };
384000 };
bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
snd_pcm_hw_params_t *hwparams;
unsigned int i, j, n, *rates = NULL;
@ -1497,40 +1454,39 @@ 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_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 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 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,
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,
};
bool supported[PA_ELEMENTSOF(all_formats)] = {
false,
@ -1548,7 +1504,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, format_trans_to_pcm[all_formats[i]]) == 0) {
if (snd_pcm_hw_params_test_format(pcm, hwparams, all_formats[i]) == 0) {
supported[i] = true;
n++;
}
@ -1559,7 +1515,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++] = all_formats[i];
formats[j++] = format_trans_to_pa[all_formats[i]];
}
formats[j] = PA_SAMPLE_MAX;
@ -1567,7 +1523,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_pcm[formats[0]])) < 0) {
if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pa[formats[0]])) < 0) {
pa_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret));
pa_xfree(formats);
return NULL;
@ -1658,16 +1614,14 @@ 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 subdevice) {
unsigned int device) {
snd_mixer_elem_t *elem;
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
snd_hctl_elem_t **_helem, *helem;
snd_hctl_elem_t *helem;
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
continue;
_helem = snd_mixer_elem_get_private(elem);
helem = *_helem;
helem = snd_mixer_elem_get_private(elem);
if (snd_hctl_elem_get_interface(helem) != iface)
continue;
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
@ -1676,19 +1630,17 @@ 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) {
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device, 0);
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
}
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, 0);
return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device);
}
static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
@ -1697,79 +1649,31 @@ 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);
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) {
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;
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;
/* 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;
}
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 (!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;
}
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;
}
}
}
@ -1783,14 +1687,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, snd_hctl_t *hctl) {
static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
int err;
snd_mixer_class_t *class;
pa_assert(mixer);
pa_assert(dev);
if ((err = snd_mixer_attach_hctl(mixer, hctl)) < 0) {
if ((err = snd_mixer_attach(mixer, dev)) < 0) {
pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
return -1;
}
@ -1829,29 +1733,37 @@ 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);
/* The quick card number/index lookup (hw:#)
* We already know the card number/index, thus use the mixer
* from the cache at first.
*/
if (!pm && pa_strneq(dev, "hw:", 3)) {
const char *s = dev + 3;
int card_index;
while (*s && *s >= '0' && *s <= '9') s++;
if (*s == '\0' && pa_atoi(dev + 3, &card_index) >= 0) {
PA_HASHMAP_FOREACH_KV(dev2, pm, mixers, state) {
if (pm->card_index == card_index) {
dev = dev2;
pm = pa_hashmap_get(mixers, dev);
break;
}
}
}
}
if (pm) {
if (!probe)
pm->used_for_probe_only = false;
@ -1863,55 +1775,27 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
return NULL;
}
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;
}
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);
}
}
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)
pm->used_for_probe_only = probe;
pm->mixer_handle = m;
pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
return m;
}
}
__close:
snd_mixer_close(m);
return NULL;
}
@ -1952,10 +1836,8 @@ void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
{
if (mixer->fdl)
pa_alsa_fdlist_free(mixer->fdl);
if (mixer->mixer_handle && mixer->alias == NULL)
if (mixer->mixer_handle)
snd_mixer_close(mixer->mixer_handle);
if (mixer->alias)
mixer->alias->alias = NULL;
pa_xfree(mixer);
}

View file

@ -67,8 +67,6 @@ 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 */
@ -84,8 +82,6 @@ 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 */
@ -100,8 +96,6 @@ 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 */
@ -117,8 +111,6 @@ 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

@ -24,9 +24,6 @@ description-key = analog-input-microphone-rear
[Jack Rear Mic]
required-any = any
[Jack Rear Mic - Input]
required-any = any
[Jack Rear Mic Phantom]
required-any = any
state.plugged = unknown

View file

@ -1,91 +0,0 @@
# 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

@ -13,29 +13,22 @@
# 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
; Behringer U-Phoria UMC22
;
; 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".
; Default mapping only allows to use stereo input and sound card has two
; physical input channels.
;
; Behringer UMC22 has stereo input (representing two physical mono inputs),
; others have mono input.
; However in case of only using a single input channel (like condenser
; microphone) only one channel will have any sound, which is often
; inconvenient for casual use.
;
; 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 includes mono input options which makes it much more
; friendly in single input configuration.
;
; This config also removes default digital input/output mappings that do
; not physically exist on cards that we've seen so far.
; not physically exist on this card.
;
; Originally added by Nazar Mokrynskyi <nazar@mokrynskyi.com> for Behringer
; UMC22.
; Added by Nazar Mokrynskyi <nazar@mokrynskyi.com>
[General]
auto-profiles = yes
@ -43,28 +36,28 @@ auto-profiles = yes
[Mapping analog-stereo-input]
device-strings = hw:%f
channel-map = left,right
paths-input = analog-input-mic analog-input
paths-input = analog-input-mic
direction = input
priority = 4
[Mapping analog-mono]
device-strings = hw:%f
channel-map = mono
paths-input = analog-input-mic analog-input
channel-map = mono,mono
paths-input = analog-input-mic
direction = input
priority = 3
[Mapping analog-mono-left]
device-strings = hw:%f
channel-map = mono,aux1
paths-input = analog-input-mic analog-input
paths-input = analog-input-mic
direction = input
priority = 2
[Mapping analog-mono-right]
device-strings = hw:%f
channel-map = aux1,mono
paths-input = analog-input-mic analog-input
paths-input = analog-input-mic
direction = input
priority = 1

View file

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

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_port(NULL, &m->ucm_context, true, ports, cp, u->core);
pa_alsa_ucm_add_ports_combination(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_port(NULL, &m->ucm_context, false, ports, cp, u->core);
pa_alsa_ucm_add_ports_combination(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,7 +249,8 @@ 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, od->profile) < 0) {
if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile ? nd->profile->name : NULL,
od->profile ? od->profile->name : NULL) < 0) {
ret = -1;
goto finish;
}
@ -301,7 +302,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, NULL) < 0) {
if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile->name, NULL) < 0) {
pa_log("Failed to set ucm profile %s", d->profile->name);
return;
}
@ -370,7 +371,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), *elem;
snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
snd_ctl_elem_value_t *elem_value;
bool plugged_in;
void *state;
@ -380,8 +381,6 @@ 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
@ -564,18 +563,13 @@ 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), *elem;
int device;
snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
int device = snd_hctl_elem_get_device(elem);
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,6 +42,9 @@ 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);

View file

@ -490,7 +490,7 @@ 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;
written = gst_transcode_buffer(codec_info, timestamp, input_buffer, input_size, output_buffer, output_size, processed);
written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed);
if (PA_UNLIKELY(*processed == 0 || *processed != input_size))
pa_log_error("aptX encoding error");
@ -526,7 +526,7 @@ 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;
written = gst_transcode_buffer(codec_info, -1, input_buffer, input_size, output_buffer, output_size, processed);
written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed);
/* 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,6 +556,7 @@ 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 },
.support_backchannel = false,
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities,
.choose_remote_endpoint = choose_remote_endpoint,
@ -579,6 +580,7 @@ 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 },
.support_backchannel = false,
.can_be_supported = can_be_supported,
.can_accept_capabilities = can_accept_capabilities_hd,
.choose_remote_endpoint = choose_remote_endpoint_hd,

View file

@ -22,14 +22,12 @@
#endif
#include <arpa/inet.h>
#include <stdint.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include <pulsecore/once.h>
#include <pulsecore/core-util.h>
#include <pulse/sample.h>
#include <pulse/timeval.h>
#include <pulse/util.h>
#include "a2dp-codecs.h"
@ -41,19 +39,83 @@ static void app_sink_eos(GstAppSink *appsink, gpointer userdata) {
pa_log_debug("Sink got EOS");
}
/* Called from the GStreamer streaming thread */
static GstFlowReturn app_sink_new_sample(GstAppSink *appsink, gpointer userdata) {
struct gst_info *info = (struct gst_info *) userdata;
GstSample *sample = NULL;
GstBuffer *buf;
sample = gst_app_sink_pull_sample(GST_APP_SINK(info->app_sink));
if (!sample)
return GST_FLOW_OK;
buf = gst_sample_get_buffer(sample);
gst_buffer_ref(buf);
gst_adapter_push(info->sink_adapter, buf);
gst_sample_unref(sample);
pa_fdsem_post(info->sample_ready_fdsem);
return GST_FLOW_OK;
}
static void gst_deinit_common(struct gst_info *info) {
if (!info)
return;
if (info->sample_ready_fdsem)
pa_fdsem_free(info->sample_ready_fdsem);
if (info->app_src)
gst_object_unref(info->app_src);
if (info->app_sink)
gst_object_unref(info->app_sink);
if (info->bin)
gst_object_unref(info->bin);
if (info->sink_adapter)
g_object_unref(info->sink_adapter);
if (info->pipeline)
gst_object_unref(info->pipeline);
}
static GstBusSyncReply sync_bus_handler (GstBus *bus, GstMessage *message, struct gst_info *info) {
GstStreamStatusType type;
GstElement *owner;
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_STREAM_STATUS:
gst_message_parse_stream_status (message, &type, &owner);
switch (type) {
case GST_STREAM_STATUS_TYPE_ENTER:
pa_log_debug("GStreamer pipeline thread starting up");
if (info->core->realtime_scheduling)
pa_thread_make_realtime(info->core->realtime_priority);
break;
case GST_STREAM_STATUS_TYPE_LEAVE:
pa_log_debug("GStreamer pipeline thread shutting down");
break;
default:
break;
}
break;
default:
break;
}
/* pass all messages on the async queue */
return GST_BUS_PASS;
}
bool gst_init_common(struct gst_info *info) {
GstElement *bin = NULL;
GstElement *appsink = NULL;
GstElement *pipeline = NULL;
GstElement *appsrc = NULL, *appsink = NULL;
GstAdapter *adapter;
GstAppSinkCallbacks callbacks = { 0, };
GstBus *bus;
appsrc = gst_element_factory_make("appsrc", "app_source");
if (!appsrc) {
pa_log_error("Could not create appsrc element");
goto fail;
}
g_object_set(appsrc, "is-live", FALSE, "format", GST_FORMAT_TIME, "stream-type", 0, "max-bytes", 0, NULL);
appsink = gst_element_factory_make("appsink", "app_sink");
if (!appsink) {
@ -63,27 +125,75 @@ 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;
callbacks.new_sample = app_sink_new_sample;
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &callbacks, info, NULL);
bin = gst_bin_new(NULL);
pa_assert(bin);
adapter = gst_adapter_new();
pa_assert(adapter);
pipeline = gst_pipeline_new(NULL);
pa_assert(pipeline);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) sync_bus_handler, info, NULL);
gst_object_unref (bus);
info->app_src = appsrc;
info->app_sink = appsink;
info->bin = bin;
info->sink_adapter = adapter;
info->pipeline = pipeline;
info->sample_ready_fdsem = pa_fdsem_new();
return true;
fail:
if (appsrc)
gst_object_unref(appsrc);
if (appsink)
gst_object_unref(appsink);
return false;
}
/*
* 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
* source pad. In encode_buffer, we wait on the fdsem. The fdsem gets posted
* when either new_sample or idle probe gets called. We do this, to make the
* appsink behave synchronously.
*
* For buffer probes, see
* https://gstreamer.freedesktop.org/documentation/additional/design/probes.html?gi-language=c
*/
static GstPadProbeReturn gst_sink_buffer_idle_probe(GstPad *pad, GstPadProbeInfo *probe_info, gpointer userdata)
{
struct gst_info *info = (struct gst_info *)userdata;
pa_assert(probe_info->type & GST_PAD_PROBE_TYPE_IDLE);
pa_fdsem_post(info->sample_ready_fdsem);
return GST_PAD_PROBE_REMOVE;
}
static GstPadProbeReturn gst_sink_buffer_probe(GstPad *pad, GstPadProbeInfo *probe_info, gpointer userdata)
{
struct gst_info *info = (struct gst_info *)userdata;
GstPad *peer_pad;
pa_assert(probe_info->type & GST_PAD_PROBE_TYPE_BUFFER);
peer_pad = gst_pad_get_peer(pad);
gst_pad_add_probe(peer_pad, GST_PAD_PROBE_TYPE_IDLE, gst_sink_buffer_idle_probe, info, NULL);
gst_object_unref(peer_pad);
return GST_PAD_PROBE_OK;
}
static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
gchar *sample_format;
GstCaps *caps;
uint64_t channel_mask;
int channel_mask;
switch (ss->format) {
case PA_SAMPLE_S16LE:
@ -130,10 +240,6 @@ 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;
GstEvent *event;
GstSegment segment;
GstEvent *stream_start;
guint group_id;
pa_assert(transcoder);
@ -142,49 +248,30 @@ bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transc
if (!gst_init_common(info))
goto common_fail;
gst_bin_add_many(GST_BIN(info->bin), transcoder, info->app_sink, NULL);
caps = gst_create_caps_from_sample_spec(info->ss);
if (for_encoding)
g_object_set(info->app_src, "caps", caps, NULL);
else
g_object_set(info->app_sink, "caps", caps, NULL);
gst_caps_unref(caps);
if (!gst_element_link_many(transcoder, info->app_sink, NULL)) {
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)) {
pa_log_error("Failed to link codec elements into pipeline");
goto pipeline_fail;
}
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) {
if (gst_element_set_state(info->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
pa_log_error("Could not start pipeline");
goto pipeline_fail;
}
/* 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);
/* 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);
pa_log_info("GStreamer pipeline initialisation succeeded");
@ -208,58 +295,40 @@ common_fail:
return false;
}
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) {
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 transcoded;
gsize available, transcoded;
GstBuffer *in_buf;
GstMapInfo map_info;
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);
in_buf = gst_buffer_new_allocate(NULL, input_size, 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));
pa_assert_se(gst_buffer_map(in_buf, &map_info, GST_MAP_WRITE));
memcpy(map_info.data, input_buffer, input_size);
gst_buffer_unmap(in_buf, &map_info);
ret = gst_app_src_push_buffer(GST_APP_SRC(info->app_src), in_buf);
if (ret != GST_FLOW_OK) {
pa_log_error("failed to push buffer for transcoding %d", ret);
goto fail;
}
while ((sample = gst_app_sink_try_pull_sample(GST_APP_SINK(info->app_sink), 0))) {
in_buf = gst_sample_get_buffer(sample);
pa_fdsem_wait(info->sample_ready_fdsem);
available = gst_adapter_available(info->sink_adapter);
if (available) {
transcoded = PA_MIN(available, output_size);
gst_adapter_copy(info->sink_adapter, output_buffer, 0, transcoded);
gst_adapter_flush(info->sink_adapter, transcoded);
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);
}
} else
pa_log_debug("No transcoded data available in adapter");
*processed = input_size;
@ -274,13 +343,17 @@ fail:
void gst_codec_deinit(void *codec_info) {
struct gst_info *info = (struct gst_info *) codec_info;
if (info->bin) {
gst_element_set_state(info->bin, GST_STATE_NULL);
gst_object_unref(info->bin);
if (info->sample_ready_fdsem)
pa_fdsem_free(info->sample_ready_fdsem);
if (info->pipeline) {
gst_element_set_state(info->pipeline, GST_STATE_NULL);
gst_object_unref(info->pipeline);
}
if (info->pad_sink)
gst_object_unref(GST_OBJECT(info->pad_sink));
if (info->sink_adapter)
g_object_unref(info->sink_adapter);
pa_xfree(info);
}

View file

@ -43,15 +43,15 @@ struct gst_info {
const a2dp_ldac_t *ldac_config;
} a2dp_codec_t;
/* 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;
GstElement *app_src, *app_sink;
GstElement *pipeline;
GstAdapter *sink_adapter;
pa_fdsem *sample_ready_fdsem;
uint16_t seq_num;
};
bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transcoder);
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);
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);
void gst_codec_deinit(void *codec_info);

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