mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2026-05-05 18:07:59 +02:00
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
1
.gitignore
vendored
|
|
@ -37,4 +37,3 @@ stamp-*
|
||||||
.dirstamp
|
.dirstamp
|
||||||
*.orig
|
*.orig
|
||||||
*.rej
|
*.rej
|
||||||
subprojects/*/
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# container and push it to the project's container registry on fd.o GitLab.
|
# 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
|
# 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
|
# 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.
|
# infrastructure on fd.o GitLab.
|
||||||
#
|
#
|
||||||
# Once the container stage is done, we move on to the 'build' stage where we
|
# 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
|
# there doesn't seem to be significant value to splitting the stages at the
|
||||||
# moment.
|
# 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:
|
stages:
|
||||||
- container
|
- container
|
||||||
- build
|
- build
|
||||||
|
|
@ -28,21 +19,22 @@ variables:
|
||||||
# CI runs, for example when adding new packages to FDO_DISTRIBUTION_PACKAGES.
|
# CI runs, for example when adding new packages to FDO_DISTRIBUTION_PACKAGES.
|
||||||
# The tag is an arbitrary string that identifies the exact container
|
# The tag is an arbitrary string that identifies the exact container
|
||||||
# contents.
|
# contents.
|
||||||
FDO_DISTRIBUTION_TAG: '2023-08-13-00'
|
FDO_DISTRIBUTION_TAG: '2021-03-01-02'
|
||||||
FDO_DISTRIBUTION_VERSION: '20.04'
|
FDO_DISTRIBUTION_VERSION: '18.04'
|
||||||
FDO_UPSTREAM_REPO: 'pulseaudio/pulseaudio'
|
FDO_UPSTREAM_REPO: 'pulseaudio/pulseaudio'
|
||||||
|
UBUNTU_IMAGE: "$CI_REGISTRY_IMAGE/ubuntu/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||||
|
|
||||||
include:
|
include:
|
||||||
# We pull templates from master to avoid the overhead of periodically
|
# We pull templates from master to avoid the overhead of periodically
|
||||||
# scanning for changes upstream. This does means builds might occasionally
|
# scanning for changes upstream. This does means builds might occasionally
|
||||||
# break due to upstream changing things, so if you see unexpected build
|
# break due to upstream changing things, so if you see unexpected build
|
||||||
# failures, this might be one cause.
|
# failures, this might be one cause.
|
||||||
- project: 'freedesktop/ci-templates'
|
- project: 'wayland/ci-templates'
|
||||||
ref: 'master'
|
ref: 'master'
|
||||||
file: '/templates/ubuntu.yml'
|
file: '/templates/ubuntu.yml'
|
||||||
|
|
||||||
build-container:
|
build-container:
|
||||||
extends: .fdo.container-build@ubuntu
|
extends: .fdo.container-ifnot-exists@ubuntu
|
||||||
stage: container
|
stage: container
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||||
|
|
@ -56,7 +48,6 @@ build-container:
|
||||||
check
|
check
|
||||||
curl
|
curl
|
||||||
dbus-x11
|
dbus-x11
|
||||||
doxygen
|
|
||||||
g++
|
g++
|
||||||
gcc
|
gcc
|
||||||
gettext
|
gettext
|
||||||
|
|
@ -97,19 +88,17 @@ build-container:
|
||||||
wget
|
wget
|
||||||
|
|
||||||
build-meson:
|
build-meson:
|
||||||
extends: .fdo.distribution-image@ubuntu
|
|
||||||
stage: build
|
stage: build
|
||||||
|
image: $UBUNTU_IMAGE
|
||||||
script:
|
script:
|
||||||
# Install meson (higher than our min version to support our wrap file)
|
# Install meson
|
||||||
- wget -q https://github.com/mesonbuild/meson/releases/download/0.63.2/meson-0.63.2.tar.gz
|
- wget -q https://github.com/mesonbuild/meson/releases/download/0.50.0/meson-0.50.0.tar.gz
|
||||||
- tar -xf meson-0.63.2.tar.gz
|
- tar -xf meson-0.50.0.tar.gz
|
||||||
- cd meson-0.63.2
|
- cd meson-0.50.0
|
||||||
- python3 setup.py install
|
- python3 setup.py install
|
||||||
- cd ..
|
- cd ..
|
||||||
# needed to generate a version
|
|
||||||
- git fetch https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git --tags
|
|
||||||
# Do the actual build
|
# Do the actual build
|
||||||
- meson build -Dwebrtc-aec=enabled
|
- meson build
|
||||||
- cd build
|
- cd build
|
||||||
- ninja
|
- ninja
|
||||||
- ulimit -c 0 # don't dump core files on tests that are supposed to assert
|
- ulimit -c 0 # don't dump core files on tests that are supposed to assert
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@ Please take a look at the [coding style
|
||||||
documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/CodingStyle/)
|
documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/CodingStyle/)
|
||||||
on our wiki.
|
on our wiki.
|
||||||
|
|
||||||
## Commit messages
|
## Commit messagse
|
||||||
|
|
||||||
We follow the standard git commit message format of a summary on the first line
|
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
|
line, followed by a detailed commit message. An additional line at the end may
|
||||||
link to an issue being fixed by this MR.
|
link to an issue being fixed by this MR.
|
||||||
|
|
||||||
|
|
|
||||||
300
NEWS
300
NEWS
|
|
@ -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
|
PulseAudio 14.2
|
||||||
|
|
||||||
A bug fix release.
|
A bug fix release.
|
||||||
|
|
|
||||||
|
|
@ -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())
|
cdata.set('DOXYGEN_OUTPUT_DIRECTORY', meson.current_build_dir())
|
||||||
|
|
||||||
doxygen_conf = configure_file(
|
doxygen_conf = configure_file(
|
||||||
|
|
@ -12,4 +7,4 @@ doxygen_conf = configure_file(
|
||||||
)
|
)
|
||||||
|
|
||||||
run_target('doxygen',
|
run_target('doxygen',
|
||||||
command : [doxygen, doxygen_conf])
|
command : ['doxygen', doxygen_conf])
|
||||||
|
|
|
||||||
|
|
@ -14,24 +14,22 @@ if get_option('daemon')
|
||||||
]
|
]
|
||||||
endif
|
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 += [
|
manpages += [
|
||||||
['pacat', '1', ['paplay', 'parec', 'parecord', 'pamon']],
|
['padsp', '1'],
|
||||||
['pactl', '1'],
|
|
||||||
['pulse-client.conf', '5'],
|
|
||||||
]
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
if cdata.has('HAVE_OSS_WRAPPER')
|
if x11_dep.found()
|
||||||
manpages += [
|
manpages += [
|
||||||
['padsp', '1'],
|
['pax11publish', '1'],
|
||||||
]
|
]
|
||||||
endif
|
|
||||||
|
|
||||||
if x11_dep.found()
|
|
||||||
manpages += [
|
|
||||||
['pax11publish', '1'],
|
|
||||||
]
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# FIXME: Add esdcompat if HAVE_ESOUND
|
# FIXME: Add esdcompat if HAVE_ESOUND
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
<option>
|
<option>
|
||||||
<p><opt>-d | --device</opt><arg>=SINKORSOURCE</arg></p>
|
<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>
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
<optdesc><p>Choose the server to connect to.</p></optdesc>
|
||||||
</option>
|
</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>
|
<option>
|
||||||
<p><opt>-n | --client-name</opt><arg>=NAME</arg></p>
|
<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">
|
<section name="Commands">
|
||||||
<p>
|
<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.
|
can be used to specify the default sink, source and monitor respectively.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -174,9 +168,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
<p><opt>set-default-sink</opt> <arg>SINK</arg></p>
|
<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.
|
<optdesc><p>Make the specified sink (identified by its symbolic name or numerical index) the default sink.</p></optdesc>
|
||||||
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>
|
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
|
|
@ -191,9 +183,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
<p><opt>set-default-source</opt> <arg>SOURCE</arg></p>
|
<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.
|
<optdesc><p>Make the specified source (identified by its symbolic name or numerical index) the default source.</p></optdesc>
|
||||||
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>
|
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
<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
|
<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
|
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
|
name.</p><p>Note that defaults may be overridden by various policy modules
|
||||||
source. In this case, pulseaudio will return to the default sink or source
|
or by specific stream configurations.</p></optdesc>
|
||||||
selection based on priority.</p><p>Note that defaults may be overridden by
|
|
||||||
various policy modules or by specific stream configurations.</p></optdesc>
|
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option>
|
<option>
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<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
|
to. The environment variable <opt>$PULSE_SERVER</opt> takes
|
||||||
precedence.</p>
|
precedence.</p>
|
||||||
</option>
|
</option>
|
||||||
|
|
|
||||||
676
meson.build
676
meson.build
|
|
@ -1,12 +1,10 @@
|
||||||
project('pulseaudio', 'c',
|
project('pulseaudio', 'c', 'cpp',
|
||||||
version : run_command(find_program('git-version-gen'), join_paths(meson.current_source_dir(), '.tarball-version'), check : false).stdout().strip(),
|
version : run_command(find_program('git-version-gen'), join_paths(meson.current_source_dir(), '.tarball-version')).stdout().strip(),
|
||||||
meson_version : '>= 0.56.0',
|
meson_version : '>= 0.50.0',
|
||||||
default_options : [ 'c_std=gnu11', 'cpp_std=c++17' ]
|
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())
|
||||||
meson.add_dist_script('scripts/save-tarball-version.sh', meson.project_version())
|
|
||||||
endif
|
|
||||||
|
|
||||||
pa_version_str = meson.project_version()
|
pa_version_str = meson.project_version()
|
||||||
# For tarballs, the first split will do nothing, but for builds in git, we
|
# 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
|
# The stable ABI for client applications, for the version info x:y:z
|
||||||
# always will hold x=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
|
# A simplified, synchronous, ABI-stable interface for client
|
||||||
# applications, for the version info x:y:z always will hold x=z
|
# 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],
|
libpulse_mainloop_glib_version_info[1],
|
||||||
)
|
)
|
||||||
|
|
||||||
i18n = import('i18n')
|
|
||||||
|
|
||||||
# Paths
|
# Paths
|
||||||
|
|
||||||
prefix = get_option('prefix')
|
prefix = get_option('prefix')
|
||||||
|
|
@ -72,7 +68,6 @@ localedir = join_paths(prefix, get_option('localedir'))
|
||||||
localstatedir = join_paths(prefix, get_option('localstatedir'))
|
localstatedir = join_paths(prefix, get_option('localstatedir'))
|
||||||
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
|
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
|
||||||
privlibdir = join_paths(libdir, 'pulseaudio')
|
privlibdir = join_paths(libdir, 'pulseaudio')
|
||||||
po_dir = join_paths(meson.current_source_dir(), 'po')
|
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
if host_machine.system() == 'windows'
|
||||||
# Windows only supports loading libraries from the same dir as the executable
|
# 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')
|
modlibexecdir = get_option('modlibexecdir')
|
||||||
if modlibexecdir == ''
|
if modlibexecdir == ''
|
||||||
modlibexecdir = join_paths(libdir, 'pulseaudio', 'modules')
|
modlibexecdir = join_paths(libdir, 'pulse-' + pa_version_major_minor, 'modules')
|
||||||
endif
|
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
|
||||||
# Windows only supports loading libraries from the same dir as the executable
|
|
||||||
modlibexecdir = bindir
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
padsplibdir = get_option('padsplibdir')
|
padsplibdir = get_option('padsplibdir')
|
||||||
|
|
@ -123,7 +113,7 @@ bashcompletiondir = get_option('bashcompletiondir')
|
||||||
if bashcompletiondir == ''
|
if bashcompletiondir == ''
|
||||||
bash_completion_dep = dependency('bash-completion', required : false)
|
bash_completion_dep = dependency('bash-completion', required : false)
|
||||||
if bash_completion_dep.found()
|
if bash_completion_dep.found()
|
||||||
bashcompletiondir = bash_completion_dep.get_variable(pkgconfig : 'completionsdir')
|
bashcompletiondir = bash_completion_dep.get_pkgconfig_variable('completionsdir')
|
||||||
else
|
else
|
||||||
bashcompletiondir = join_paths(datadir, 'bash-completion', 'completions')
|
bashcompletiondir = join_paths(datadir, 'bash-completion', 'completions')
|
||||||
endif
|
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_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_SRCDIR', join_paths(meson.current_source_dir(), 'src'))
|
||||||
cdata.set_quoted('PA_BUILDDIR', meson.current_build_dir())
|
cdata.set_quoted('PA_BUILDDIR', meson.current_build_dir())
|
||||||
if host_machine.system() == 'windows'
|
cdata.set_quoted('PA_SOEXT', '.so')
|
||||||
cdata.set_quoted('PA_SOEXT', '.dll')
|
|
||||||
else
|
|
||||||
cdata.set_quoted('PA_SOEXT', '.so')
|
|
||||||
endif
|
|
||||||
cdata.set_quoted('PA_DEFAULT_CONFIG_DIR', pulsesysconfdir)
|
cdata.set_quoted('PA_DEFAULT_CONFIG_DIR', pulsesysconfdir)
|
||||||
cdata.set('PA_DEFAULT_CONFIG_DIR_UNQUOTED', pulsesysconfdir)
|
cdata.set('PA_DEFAULT_CONFIG_DIR_UNQUOTED', pulsesysconfdir)
|
||||||
cdata.set_quoted('PA_BINARY', join_paths(bindir, 'pulseaudio'))
|
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_SYSTEM_GROUP', get_option('system_group'))
|
||||||
cdata.set_quoted('PA_ACCESS_GROUP', get_option('access_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_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('DESKTOPFILEDIR', join_paths(datadir, 'applications'))
|
||||||
cdata.set_quoted('PULSE_LOCALEDIR', localedir)
|
cdata.set_quoted('PULSE_LOCALEDIR', localedir)
|
||||||
cdata.set_quoted('GETTEXT_PACKAGE', 'pulseaudio')
|
cdata.set_quoted('GETTEXT_PACKAGE', 'pulseaudio')
|
||||||
cdata.set('ENABLE_NLS', 1)
|
cdata.set('ENABLE_NLS', 1)
|
||||||
cdata.set('top_srcdir', meson.project_source_root())
|
cdata.set('top_srcdir', meson.source_root())
|
||||||
|
|
||||||
# Platform specifics
|
# Platform specifics
|
||||||
# First some defaults to keep config file generation happy
|
# First some defaults to keep config file generation happy
|
||||||
|
|
@ -190,7 +177,6 @@ endif
|
||||||
# rather than ending up in the config.h file?
|
# rather than ending up in the config.h file?
|
||||||
if host_machine.system() == 'darwin'
|
if host_machine.system() == 'darwin'
|
||||||
cdata.set('OS_IS_DARWIN', 1)
|
cdata.set('OS_IS_DARWIN', 1)
|
||||||
cdata.set('HAVE_COREAUDIO', 1)
|
|
||||||
cdata.set('_DARWIN_C_SOURCE', '200112L') # Needed to get NSIG on Mac OS
|
cdata.set('_DARWIN_C_SOURCE', '200112L') # Needed to get NSIG on Mac OS
|
||||||
elif host_machine.system() == 'windows'
|
elif host_machine.system() == 'windows'
|
||||||
cdata.set('OS_IS_WIN32', 1)
|
cdata.set('OS_IS_WIN32', 1)
|
||||||
|
|
@ -230,6 +216,7 @@ endif
|
||||||
check_headers = [
|
check_headers = [
|
||||||
'arpa/inet.h',
|
'arpa/inet.h',
|
||||||
'byteswap.h',
|
'byteswap.h',
|
||||||
|
'cpuid.h',
|
||||||
'dlfcn.h',
|
'dlfcn.h',
|
||||||
'execinfo.h',
|
'execinfo.h',
|
||||||
'grp.h',
|
'grp.h',
|
||||||
|
|
@ -289,19 +276,6 @@ if cc.has_header_symbol('pthread.h', 'PTHREAD_PRIO_INHERIT')
|
||||||
cdata.set('HAVE_PTHREAD_PRIO_INHERIT', 1)
|
cdata.set('HAVE_PTHREAD_PRIO_INHERIT', 1)
|
||||||
endif
|
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
|
# Functions
|
||||||
|
|
||||||
check_functions = [
|
check_functions = [
|
||||||
|
|
@ -430,7 +404,7 @@ cdata.set('MESON_BUILD', 1)
|
||||||
# so we request the nodelete flag to be enabled.
|
# 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.
|
# 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.
|
# 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']
|
nodelete_link_args = ['-Wl,-z,nodelete']
|
||||||
else
|
else
|
||||||
nodelete_link_args = []
|
nodelete_link_args = []
|
||||||
|
|
@ -439,7 +413,6 @@ endif
|
||||||
# Code coverage
|
# Code coverage
|
||||||
|
|
||||||
if get_option('gcov')
|
if get_option('gcov')
|
||||||
add_languages('cpp', native: false)
|
|
||||||
add_project_arguments('--coverage', language: ['c', 'cpp'])
|
add_project_arguments('--coverage', language: ['c', 'cpp'])
|
||||||
add_project_link_arguments('--coverage', language: ['c', 'cpp'])
|
add_project_link_arguments('--coverage', language: ['c', 'cpp'])
|
||||||
endif
|
endif
|
||||||
|
|
@ -505,24 +478,22 @@ endif
|
||||||
|
|
||||||
need_libatomic_ops = false
|
need_libatomic_ops = false
|
||||||
|
|
||||||
atomictest = '''int main() {
|
atomictest = '''void func() {
|
||||||
volatile int atomic = 2;
|
volatile int atomic = 2;
|
||||||
__sync_bool_compare_and_swap (&atomic, 2, 3);
|
__sync_bool_compare_and_swap (&atomic, 2, 3);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if cc.links(atomictest)
|
if cc.compiles(atomictest)
|
||||||
cdata.set('HAVE_ATOMIC_BUILTINS', 1)
|
cdata.set('HAVE_ATOMIC_BUILTINS', 1)
|
||||||
|
|
||||||
newatomictest = '''int main() {
|
newatomictest = '''void func() {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
__atomic_store_n(&c, 4, __ATOMIC_SEQ_CST);
|
__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)
|
cdata.set('HAVE_ATOMIC_BUILTINS_MEMORY_MODEL', 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -594,245 +565,219 @@ if host_machine.cpu_family() == 'arm'
|
||||||
endif
|
endif
|
||||||
# NEON checks are automatically done by the unstable-simd module
|
# 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')
|
if get_option('ipv6')
|
||||||
cdata.set('HAVE_IPV6', 1)
|
cdata.set('HAVE_IPV6', 1)
|
||||||
endif
|
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'))
|
dbus_dep = dependency('dbus-1', version : '>= 1.4.12', required : get_option('dbus'))
|
||||||
if dbus_dep.found()
|
if dbus_dep.found()
|
||||||
cdata.set('HAVE_DBUS', 1)
|
cdata.set('HAVE_DBUS', 1)
|
||||||
endif
|
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'))
|
glib_dep = dependency('glib-2.0', version : '>= 2.28.0', required: get_option('glib'))
|
||||||
if glib_dep.found()
|
if glib_dep.found()
|
||||||
cdata.set('HAVE_GLIB', 1)
|
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
|
endif
|
||||||
|
|
||||||
sndfile_dep = dependency('sndfile', version : '>= 1.0.20')
|
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'))
|
libsystemd_dep = dependency('libsystemd', required : get_option('systemd'))
|
||||||
if libsystemd_dep.found()
|
if libsystemd_dep.found()
|
||||||
cdata.set('HAVE_SYSTEMD_DAEMON', 1)
|
cdata.set('HAVE_SYSTEMD_DAEMON', 1)
|
||||||
cdata.set('HAVE_SYSTEMD_LOGIN', 1)
|
cdata.set('HAVE_SYSTEMD_LOGIN', 1)
|
||||||
cdata.set('HAVE_SYSTEMD_JOURNAL', 1)
|
cdata.set('HAVE_SYSTEMD_JOURNAL', 1)
|
||||||
endif
|
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'))
|
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'))
|
if cc.has_header('sys/soundcard.h', required: get_option('oss-output'))
|
||||||
# OSS output via daemon module-detect
|
|
||||||
cdata.set('HAVE_OSS_OUTPUT', 1)
|
cdata.set('HAVE_OSS_OUTPUT', 1)
|
||||||
# OSS wrapper
|
|
||||||
cdata.set('HAVE_OSS_WRAPPER', 1)
|
cdata.set('HAVE_OSS_WRAPPER', 1)
|
||||||
cdata.set('PULSEDSP_LOCATION', pulsedsp_location)
|
cdata.set('PULSEDSP_LOCATION', pulsedsp_location)
|
||||||
endif
|
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'))
|
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
|
||||||
if fftw_dep.found()
|
if fftw_dep.found()
|
||||||
cdata.set('HAVE_FFTW', 1)
|
cdata.set('HAVE_FFTW', 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Client library dependencies
|
jack_dep = dependency('jack', version : '>= 0.117.0', required : get_option('jack'))
|
||||||
|
if jack_dep.found()
|
||||||
if get_option('client')
|
cdata.set('HAVE_JACK', 1)
|
||||||
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
|
|
||||||
endif
|
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')
|
openssl_dep = dependency('openssl', version : '>= 0.9', required : get_option('openssl'))
|
||||||
# FIXME: make sure it's >= 2.2
|
if openssl_dep.found()
|
||||||
ltdl_dep = cc.find_library('ltdl', required : true)
|
cdata.set('HAVE_OPENSSL', 1)
|
||||||
|
endif
|
||||||
|
|
||||||
# FIXME: can meson support libtool -dlopen/-dlpreopen things?
|
speex_dep = dependency('speexdsp', version : '>= 1.2', required : get_option('speex'))
|
||||||
# and do we still want to support this at all?
|
if speex_dep.found()
|
||||||
cdata.set('DISABLE_LIBTOOL_PRELOAD', 1)
|
cdata.set('HAVE_SPEEX', 1)
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('database') == 'tdb'
|
udev_dep = dependency('libudev', version : '>= 143', required : get_option('udev'))
|
||||||
database_dep = dependency('tdb')
|
if udev_dep.found()
|
||||||
elif get_option('database') == 'gdbm'
|
cdata.set('HAVE_UDEV', 1)
|
||||||
database_dep = cc.find_library('gdbm', required : true)
|
endif
|
||||||
else
|
|
||||||
database_dep = dependency('', required: false)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('legacy-database-entry-format')
|
webrtc_dep = dependency('webrtc-audio-processing', version : '>= 0.2', required : get_option('webrtc-aec'))
|
||||||
cdata.set('ENABLE_LEGACY_DATABASE_ENTRY_FORMAT', 1)
|
if webrtc_dep.found()
|
||||||
endif
|
cdata.set('HAVE_WEBRTC', 1)
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('stream-restore-clear-old-devices')
|
gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('gstreamer'))
|
||||||
cdata.set('STREAM_RESTORE_CLEAR_OLD_DEVICES', 1)
|
gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('gstreamer'))
|
||||||
endif
|
gstrtp_dep = dependency('gstreamer-rtp-1.0', required : get_option('gstreamer'))
|
||||||
|
|
||||||
if get_option('running-from-build-tree')
|
have_gstreamer = false
|
||||||
cdata.set('HAVE_RUNNING_FROM_BUILD_TREE', 1)
|
if gst_dep.found() and gstapp_dep.found() and gstrtp_dep.found()
|
||||||
endif
|
have_gstreamer = true
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('enable-smoother-2')
|
bluez5_gst_dep = dependency('gstreamer-1.0', version : '>= 1.14', required : get_option('bluez5-gstreamer'))
|
||||||
cdata.set('USE_SMOOTHER_2', 1)
|
bluez5_gstapp_dep = dependency('gstreamer-app-1.0', required : get_option('bluez5-gstreamer'))
|
||||||
endif
|
have_bluez5_gstreamer = false
|
||||||
|
if bluez5_gst_dep.found() and bluez5_gstapp_dep.found()
|
||||||
alsa_dep = dependency('alsa', version : '>= 1.0.24', required : get_option('alsa'))
|
have_bluez5_gstreamer = true
|
||||||
if alsa_dep.found()
|
cdata.set('HAVE_GSTLDAC', 1)
|
||||||
cdata.set('HAVE_ALSA', 1)
|
cdata.set('HAVE_GSTAPTX', 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
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# These are required for the CMake file generation
|
# These are required for the CMake file generation
|
||||||
cdata.set('PA_LIBDIR', libdir)
|
cdata.set('PA_LIBDIR', libdir)
|
||||||
cdata.set('PA_INCDIR', includedir)
|
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
|
# Test dependencies
|
||||||
|
|
||||||
|
|
@ -840,90 +785,84 @@ check_dep = dependency('check', version : '>= 0.9.10', required : get_option('te
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
|
|
||||||
subdir('doxygen')
|
if get_option('doxygen')
|
||||||
if get_option('client')
|
subdir('doxygen')
|
||||||
subdir('po')
|
|
||||||
endif
|
endif
|
||||||
|
subdir('po')
|
||||||
if get_option('man')
|
if get_option('man')
|
||||||
subdir('man')
|
subdir('man')
|
||||||
endif
|
endif
|
||||||
subdir('shell-completion/bash')
|
subdir('shell-completion/bash')
|
||||||
subdir('shell-completion/zsh')
|
subdir('shell-completion/zsh')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
if get_option('client')
|
subdir('vala')
|
||||||
subdir('vala')
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Now generate config.h from everything above
|
# Now generate config.h from everything above
|
||||||
configure_file(output : 'config.h', configuration : cdata)
|
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_files = [
|
||||||
pc_cdata.set('exec_prefix', prefix)
|
'libpulse.pc',
|
||||||
pc_cdata.set('libdir', libdir)
|
'libpulse-simple.pc',
|
||||||
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 = [
|
if glib_dep.found()
|
||||||
'libpulse.pc',
|
pc_files += 'libpulse-mainloop-glib.pc'
|
||||||
'libpulse-simple.pc',
|
endif
|
||||||
]
|
|
||||||
|
|
||||||
if glib_dep.found()
|
|
||||||
pc_files += 'libpulse-mainloop-glib.pc'
|
|
||||||
endif
|
|
||||||
|
|
||||||
foreach file : pc_files
|
|
||||||
configure_file(
|
|
||||||
input : file + '.in',
|
|
||||||
output : file,
|
|
||||||
configuration : pc_cdata,
|
|
||||||
install_dir : pkgconfigdir)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
# CMake files
|
|
||||||
|
|
||||||
m4 = find_program('m4', required: true)
|
|
||||||
|
|
||||||
cmakedir = join_paths(libdir, 'cmake', 'PulseAudio')
|
|
||||||
|
|
||||||
cmake_template_file = configure_file(
|
|
||||||
input : 'PulseAudioConfig.cmake.in',
|
|
||||||
output : 'PulseAudioConfig.cmake.tmp',
|
|
||||||
configuration: cdata,
|
|
||||||
)
|
|
||||||
|
|
||||||
custom_target('PulseAudioConfig.cmake',
|
|
||||||
input : cmake_template_file,
|
|
||||||
output : 'PulseAudioConfig.cmake',
|
|
||||||
capture : true,
|
|
||||||
command : [m4, '@INPUT@'],
|
|
||||||
build_by_default : true,
|
|
||||||
install : true,
|
|
||||||
install_dir : cmakedir,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
foreach file : pc_files
|
||||||
configure_file(
|
configure_file(
|
||||||
input : 'PulseAudioConfigVersion.cmake.in',
|
input : file + '.in',
|
||||||
output : 'PulseAudioConfigVersion.cmake',
|
output : file,
|
||||||
configuration: cdata,
|
configuration : pc_cdata,
|
||||||
install : true,
|
install_dir : pkgconfigdir)
|
||||||
install_dir : cmakedir,
|
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}),
|
# 'LIBS: @0@'.format(${LIBS}),
|
||||||
'',
|
'',
|
||||||
'Enable pulseaudio daemon: @0@'.format(get_option('daemon')),
|
'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 memfd shared memory: @0@'.format(cdata.has('HAVE_MEMFD')),
|
||||||
'Enable X11: @0@'.format(x11_dep.found()),
|
'Enable X11: @0@'.format(x11_dep.found()),
|
||||||
'Enable D-Bus: @0@'.format(dbus_dep.found()),
|
' Safe X11 I/O errors: @0@'.format(cdata.has('HAVE_XSETIOERROREXITHANDLER')),
|
||||||
'Enable GLib 2: @0@'.format(glib_dep.found()),
|
|
||||||
'Enable systemd integration: @0@'.format(libsystemd_dep.found()),
|
|
||||||
'Enable FFTW: @0@'.format(fftw_dep.found()),
|
|
||||||
'Enable IPv6: @0@'.format(get_option('ipv6')),
|
|
||||||
'Enable Gcov coverage: @0@'.format(get_option('gcov')),
|
|
||||||
'Enable Valgrind: @0@'.format(cdata.has('HAVE_VALGRIND_MEMCHECK_H')),
|
|
||||||
'Enable man pages: @0@'.format(get_option('man')),
|
|
||||||
'Enable unit tests: @0@'.format(get_option('tests')),
|
|
||||||
]
|
|
||||||
|
|
||||||
if get_option('client')
|
|
||||||
summary += [
|
|
||||||
'',
|
|
||||||
'--- Pulseaudio client features ---',
|
|
||||||
'',
|
|
||||||
'Enable Gtk+ 3: @0@'.format(gtk_dep.found()),
|
|
||||||
'Enable Async DNS: @0@'.format(asyncns_dep.found()),
|
|
||||||
'Enable OSS Wrapper: @0@'.format(cdata.has('HAVE_OSS_WRAPPER')),
|
|
||||||
]
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('daemon')
|
|
||||||
summary += [
|
|
||||||
'',
|
|
||||||
'--- Pulseaudio daemon features ---',
|
|
||||||
'',
|
|
||||||
'Safe X11 I/O errors: @0@'.format(cdata.has('HAVE_XSETIOERROREXITHANDLER')),
|
|
||||||
'Enable Avahi: @0@'.format(avahi_dep.found()),
|
|
||||||
'Enable OSS Output: @0@'.format(cdata.has('HAVE_OSS_OUTPUT')),
|
'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 EsounD: @0@'.format(${ENABLE_ESOUND}),
|
||||||
'Enable Alsa: @0@'.format(alsa_dep.found()),
|
'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 CoreAudio: @0@'.format(${ENABLE_COREAUDIO}),
|
||||||
# 'Enable Solaris: @0@'.format(${ENABLE_SOLARIS}),
|
# 'Enable Solaris: @0@'.format(${ENABLE_SOLARIS}),
|
||||||
# 'Enable WaveOut: @0@'.format(${ENABLE_WAVEOUT}),
|
# 'Enable WaveOut: @0@'.format(${ENABLE_WAVEOUT}),
|
||||||
|
'Enable GLib 2: @0@'.format(glib_dep.found()),
|
||||||
'Enable GSettings: @0@'.format(gio_dep.found()),
|
'Enable GSettings: @0@'.format(gio_dep.found()),
|
||||||
'Enable BlueZ 5: @0@'.format(cdata.has('HAVE_BLUEZ_5')),
|
'Enable Gtk+ 3: @0@'.format(gtk_dep.found()),
|
||||||
' Enable native headsets: @0@'.format(cdata.has('HAVE_BLUEZ_5_NATIVE_HEADSET')),
|
'Enable Avahi: @0@'.format(avahi_dep.found()),
|
||||||
' Enable ofono headsets: @0@'.format(cdata.has('HAVE_BLUEZ_5_OFONO_HEADSET')),
|
'Enable Jack: @0@'.format(jack_dep.found()),
|
||||||
' Enable GStreamer based codecs: @0@'.format(have_bluez5_gstreamer),
|
'Enable Async DNS: @0@'.format(asyncns_dep.found()),
|
||||||
'Enable GStreamer: @0@'.format(have_gstreamer),
|
'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 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 ORC: @0@'.format(have_orcc),
|
||||||
|
'Enable GStreamer: @0@'.format(have_gstreamer),
|
||||||
'Enable Adrian echo canceller: @0@'.format(get_option('adrian-aec')),
|
'Enable Adrian echo canceller: @0@'.format(get_option('adrian-aec')),
|
||||||
'Enable Speex (resampler, AEC): @0@'.format(speex_dep.found()),
|
'Enable Speex (resampler, AEC): @0@'.format(speex_dep.found()),
|
||||||
'Enable SoXR (resampler): @0@'.format(soxr_dep.found()),
|
'Enable SoXR (resampler): @0@'.format(soxr_dep.found()),
|
||||||
'Enable WebRTC echo canceller: @0@'.format(webrtc_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')),
|
'Database: @0@'.format(get_option('database')),
|
||||||
'Legacy Database Entry Support: @0@'.format(get_option('legacy-database-entry-format')),
|
'Legacy Database Entry Support: @0@'.format(get_option('legacy-database-entry-format')),
|
||||||
'module-stream-restore:',
|
'module-stream-restore:',
|
||||||
|
|
@ -1027,48 +948,47 @@ summary += [
|
||||||
# 'Force preopen: @0@'.format(${FORCE_PREOPEN}),
|
# 'Force preopen: @0@'.format(${FORCE_PREOPEN}),
|
||||||
# 'Preopened modules: @0@'.format(${PREOPEN_MODS}),
|
# 'Preopened modules: @0@'.format(${PREOPEN_MODS}),
|
||||||
]
|
]
|
||||||
endif
|
|
||||||
|
|
||||||
message('\n '.join(summary))
|
message('\n '.join(summary))
|
||||||
|
|
||||||
# Sanity checks
|
# 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!')
|
error('At least one echo canceller implementation must be available!')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('daemon') and samplerate_dep.found()
|
if samplerate_dep.found()
|
||||||
warning('Support for libsamplerate is DEPRECATED')
|
warning('Support for libsamplerate is DEPRECATED')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if host_machine.system() != 'windows' and not dbus_dep.found()
|
if host_machine.system() != 'windows'
|
||||||
message = [
|
if not dbus_dep.found()
|
||||||
'You do not have D-Bus support enabled. It is strongly recommended',
|
message = [
|
||||||
'that you enable D-Bus support if your platform supports it.',
|
'You do not have D-Bus support enabled. It is strongly recommended',
|
||||||
'Many parts of PulseAudio use D-Bus, from ConsoleKit interaction',
|
'that you enable D-Bus support if your platform supports it.',
|
||||||
'to the Device Reservation Protocol to speak to JACK, Bluetooth',
|
'Many parts of PulseAudio use D-Bus, from ConsoleKit interaction',
|
||||||
'support and even a native control protocol for communicating and',
|
'to the Device Reservation Protocol to speak to JACK, Bluetooth',
|
||||||
'controlling the PulseAudio daemon itself.',
|
'support and even a native control protocol for communicating and',
|
||||||
]
|
'controlling the PulseAudio daemon itself.',
|
||||||
warning('\n' + '\n'.join(message))
|
]
|
||||||
endif
|
warning('\n' + '\n'.join(message))
|
||||||
|
endif
|
||||||
if get_option('daemon') and host_machine.system() == 'linux' and not udev_dep.found()
|
if host_machine.system() == 'linux' and not udev_dep.found()
|
||||||
message = [
|
message = [
|
||||||
'You do not have udev support enabled. It is strongly recommended',
|
'You do not have udev support enabled. It is strongly recommended',
|
||||||
'that you enable udev support if your platform supports it as it is',
|
'that you enable udev support if your platform supports it as it is',
|
||||||
'the primary method used to detect hardware audio devices (on Linux)',
|
'the primary method used to detect hardware audio devices (on Linux)',
|
||||||
'and is thus a critical part of PulseAudio on that platform.',
|
'and is thus a critical part of PulseAudio on that platform.',
|
||||||
]
|
]
|
||||||
warning('\n' + '\n'.join(message))
|
warning('\n' + '\n'.join(message))
|
||||||
endif
|
endif
|
||||||
|
if not speex_dep.found()
|
||||||
if get_option('daemon') and host_machine.system() != 'windows' and not speex_dep.found()
|
message = [
|
||||||
message = [
|
'You do not have speex support enabled. It is strongly recommended',
|
||||||
'You do not have speex support enabled. It is strongly recommended',
|
'that you enable speex support if your platform supports it as it is',
|
||||||
'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',
|
||||||
'the primary method used for audio resampling and is thus a critical',
|
'part of PulseAudio on that platform.',
|
||||||
'part of PulseAudio on that platform.',
|
]
|
||||||
]
|
warning('\n' + '\n'.join(message))
|
||||||
warning('\n' + '\n'.join(message))
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
option('daemon',
|
option('daemon',
|
||||||
type : 'boolean', value : true,
|
type : 'boolean', value : true,
|
||||||
description : 'Enable building and installation of pulseaudio daemon and supporting configuration files')
|
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',
|
option('doxygen',
|
||||||
type : 'feature',
|
type : 'boolean', value : true,
|
||||||
description : 'Enable building and installation of documentation generated with doxygen')
|
description : 'Enable building and installation of documentation generated with doxygen')
|
||||||
option('gcov',
|
option('gcov',
|
||||||
type : 'boolean', value : false,
|
type : 'boolean', value : false,
|
||||||
|
|
@ -14,7 +11,7 @@ option('man',
|
||||||
type : 'boolean',
|
type : 'boolean',
|
||||||
description : 'Enable building and installation of man pages')
|
description : 'Enable building and installation of man pages')
|
||||||
option('tests',
|
option('tests',
|
||||||
type : 'feature',
|
type : 'boolean',
|
||||||
description : 'Enable unit tests')
|
description : 'Enable unit tests')
|
||||||
|
|
||||||
option('system_user',
|
option('system_user',
|
||||||
|
|
@ -88,7 +85,7 @@ option('avahi',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'auto',
|
||||||
description : 'Optional Avahi support')
|
description : 'Optional Avahi support')
|
||||||
option('bluez5',
|
option('bluez5',
|
||||||
type : 'feature', value : 'auto',
|
type : 'boolean', value : 'true',
|
||||||
description : 'Optional BlueZ 5 support')
|
description : 'Optional BlueZ 5 support')
|
||||||
option('bluez5-gstreamer',
|
option('bluez5-gstreamer',
|
||||||
type : 'feature', value: 'auto',
|
type : 'feature', value: 'auto',
|
||||||
|
|
@ -99,9 +96,6 @@ option('bluez5-native-headset',
|
||||||
option('bluez5-ofono-headset',
|
option('bluez5-ofono-headset',
|
||||||
type : 'boolean',
|
type : 'boolean',
|
||||||
description : 'Optional oFono headset backend support (BlueZ 5)')
|
description : 'Optional oFono headset backend support (BlueZ 5)')
|
||||||
option('consolekit',
|
|
||||||
type : 'feature', value : 'auto',
|
|
||||||
description : 'Optional ConsoleKit support')
|
|
||||||
option('dbus',
|
option('dbus',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'auto',
|
||||||
description : 'Optional D-Bus support')
|
description : 'Optional D-Bus support')
|
||||||
|
|
@ -118,7 +112,7 @@ option('gsettings',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'auto',
|
||||||
description : 'Optional GSettings support')
|
description : 'Optional GSettings support')
|
||||||
option('gstreamer',
|
option('gstreamer',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'disabled',
|
||||||
description : 'Optional GStreamer dependency for media-related functionality')
|
description : 'Optional GStreamer dependency for media-related functionality')
|
||||||
option('gtk',
|
option('gtk',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'auto',
|
||||||
|
|
@ -168,9 +162,6 @@ option('valgrind',
|
||||||
option('x11',
|
option('x11',
|
||||||
type : 'feature', value : 'auto',
|
type : 'feature', value : 'auto',
|
||||||
description : 'Optional X11 support')
|
description : 'Optional X11 support')
|
||||||
option('enable-smoother-2',
|
|
||||||
type : 'boolean', value : true,
|
|
||||||
description : 'Use alternative time smoother implementation')
|
|
||||||
|
|
||||||
# Echo cancellation
|
# Echo cancellation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,3 @@ zh_CN
|
||||||
zh_TW
|
zh_TW
|
||||||
eo
|
eo
|
||||||
si
|
si
|
||||||
ka
|
|
||||||
eu
|
|
||||||
ar
|
|
||||||
sl
|
|
||||||
ro
|
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,6 @@ src/pulsecore/thread-mq.c
|
||||||
src/pulsecore/thread-posix.c
|
src/pulsecore/thread-posix.c
|
||||||
src/pulsecore/thread-win32.c
|
src/pulsecore/thread-win32.c
|
||||||
src/pulsecore/time-smoother.c
|
src/pulsecore/time-smoother.c
|
||||||
src/pulsecore/time-smoother_2.c
|
|
||||||
src/pulsecore/tokenizer.c
|
src/pulsecore/tokenizer.c
|
||||||
src/pulsecore/x11prop.c
|
src/pulsecore/x11prop.c
|
||||||
src/pulsecore/x11wrap.c
|
src/pulsecore/x11wrap.c
|
||||||
|
|
|
||||||
619
po/bn_IN.po
619
po/bn_IN.po
File diff suppressed because it is too large
Load diff
619
po/de_CH.po
619
po/de_CH.po
File diff suppressed because it is too large
Load diff
|
|
@ -1,3 +1,4 @@
|
||||||
|
i18n = import('i18n')
|
||||||
i18n.gettext(
|
i18n.gettext(
|
||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
preset: 'glib',
|
preset: 'glib',
|
||||||
|
|
@ -6,3 +7,5 @@ i18n.gettext(
|
||||||
args: ['--msgid-bugs-address=https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new',
|
args: ['--msgid-bugs-address=https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new',
|
||||||
'--width=90'],
|
'--width=90'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
po_dir = meson.current_source_dir()
|
||||||
|
|
|
||||||
782
po/pt_BR.po
782
po/pt_BR.po
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
619
po/sr@latin.po
619
po/sr@latin.po
File diff suppressed because it is too large
Load diff
845
po/zh_CN.po
845
po/zh_CN.po
File diff suppressed because it is too large
Load diff
629
po/zh_TW.po
629
po/zh_TW.po
File diff suppressed because it is too large
Load diff
|
|
@ -17,14 +17,7 @@ print_map_file() {
|
||||||
echo "};"
|
echo "};"
|
||||||
}
|
}
|
||||||
|
|
||||||
print_def_file() {
|
TARGET_FILE=$1
|
||||||
echo "EXPORTS"
|
shift
|
||||||
ctags -I ${CTAGS_IDENTIFIER_LIST} -f - --c-kinds=p "$@" | awk '/^pa_/ && !/(^pa_glib_|^pa_simple_)/ { print $1 }' | sort
|
|
||||||
}
|
|
||||||
|
|
||||||
MAP_FILE=$1
|
cd "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}" && print_map_file "$@" > ${TARGET_FILE}
|
||||||
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}
|
|
||||||
|
|
|
||||||
|
|
@ -3,33 +3,25 @@ if bashcompletiondir != 'no'
|
||||||
|
|
||||||
if get_option('daemon')
|
if get_option('daemon')
|
||||||
aliases += [
|
aliases += [
|
||||||
'pulseaudio',
|
|
||||||
'pacmd',
|
'pacmd',
|
||||||
'pasuspender',
|
'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
|
endif
|
||||||
|
|
||||||
if get_option('client')
|
aliases += [
|
||||||
aliases += [
|
'pacat',
|
||||||
'pacat',
|
'pactl',
|
||||||
'padsp',
|
'padsp',
|
||||||
'paplay',
|
'paplay',
|
||||||
'parec',
|
'parec',
|
||||||
'parecord',
|
'parecord',
|
||||||
]
|
]
|
||||||
install_data('pactl', install_dir : bashcompletiondir)
|
|
||||||
endif
|
install_data('pulseaudio', install_dir : bashcompletiondir)
|
||||||
|
|
||||||
foreach alias : aliases
|
foreach alias : aliases
|
||||||
dst = join_paths(bashcompletiondir, alias)
|
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)
|
meson.add_install_script('sh', '-c', cmd)
|
||||||
endforeach
|
endforeach
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -109,20 +109,19 @@ in_array() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_pactl() {
|
_pactl() {
|
||||||
local cur prev words cword preprev word command
|
local cur prev words cword preprev command
|
||||||
local comps
|
local comps
|
||||||
local flags='-h --help --version -s --server= --client-name='
|
local flags='-h --help --version -s --server= --client-name='
|
||||||
local list_types='short sinks sources sink-inputs source-outputs cards
|
local list_types='short sinks sources sink-inputs source-outputs cards
|
||||||
modules samples clients message-handlers'
|
modules samples clients message-handlers'
|
||||||
local commands=(stat info list exit upload-sample play-sample remove-sample
|
local commands=(stat info list exit upload-sample play-sample remove-sample
|
||||||
load-module unload-module move-sink-input move-source-output
|
load-module unload-module move-sink-input move-source-output
|
||||||
suspend-sink suspend-source set-card-profile get-default-sink
|
suspend-sink suspend-source set-card-profile set-default-sink
|
||||||
set-default-sink set-sink-port get-default-source set-default-source
|
set-sink-port set-default-source set-source-port set-sink-volume
|
||||||
set-source-port get-sink-volume set-sink-volume get-source-volume
|
|
||||||
set-source-volume set-sink-input-volume set-source-output-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-mute set-source-mute set-sink-input-mute
|
||||||
set-sink-input-mute set-source-output-mute set-sink-formats
|
set-source-output-mute set-sink-formats set-port-latency-offset
|
||||||
set-port-latency-offset subscribe send-message help)
|
subscribe send-message help)
|
||||||
|
|
||||||
_init_completion -n = || return
|
_init_completion -n = || return
|
||||||
preprev=${words[$cword-2]}
|
preprev=${words[$cword-2]}
|
||||||
|
|
@ -187,8 +186,6 @@ _pactl() {
|
||||||
|
|
||||||
remove-sample) ;; # TODO
|
remove-sample) ;; # TODO
|
||||||
|
|
||||||
get-default*) ;;
|
|
||||||
|
|
||||||
load-module)
|
load-module)
|
||||||
comps=$(__all_modules)
|
comps=$(__all_modules)
|
||||||
COMPREPLY=($(compgen -W '${comps[*]}' -- "$cur"))
|
COMPREPLY=($(compgen -W '${comps[*]}' -- "$cur"))
|
||||||
|
|
@ -258,7 +255,7 @@ _pactl() {
|
||||||
complete -F _pactl pactl
|
complete -F _pactl pactl
|
||||||
|
|
||||||
_pacmd() {
|
_pacmd() {
|
||||||
local cur prev words cword preprev word command
|
local cur prev words cword preprev command
|
||||||
local comps
|
local comps
|
||||||
local flags='-h --help --version'
|
local flags='-h --help --version'
|
||||||
local commands=(exit help list-modules list-cards list-sinks list-sources list-clients
|
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=
|
--start -k --kill --check --system= -D --daemonize= --fail= --high-priority=
|
||||||
--realtime= --disallow-module-loading= --disallow-exit= --exit-idle-time=
|
--realtime= --disallow-module-loading= --disallow-exit= --exit-idle-time=
|
||||||
--scache-idle-time= --log-level= -v --log-target= --log-meta= --log-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'
|
--no-cpu-limit= --disable-shm= --enable-memfd= -L --load= -F --file= -C -n'
|
||||||
_init_completion -n = || return
|
_init_completion -n = || return
|
||||||
|
|
||||||
|
|
@ -18,12 +18,10 @@ _devices() {
|
||||||
if [[ $service == pactl || $service == pacmd ]]; then
|
if [[ $service == pactl || $service == pacmd ]]; then
|
||||||
case $words[$((CURRENT - 1))] in
|
case $words[$((CURRENT - 1))] in
|
||||||
set-sink-input-*) cmd=('sink-inputs');;
|
set-sink-input-*) cmd=('sink-inputs');;
|
||||||
get-sink-*) cmd=('sinks');;
|
|
||||||
set-sink-*) cmd=('sinks');;
|
set-sink-*) cmd=('sinks');;
|
||||||
set-default-sink) cmd=('sinks');;
|
set-default-sink) cmd=('sinks');;
|
||||||
set-default-source) cmd=('sources');;
|
set-default-source) cmd=('sources');;
|
||||||
set-source-output-*) cmd=('source-outputs');;
|
set-source-output-*) cmd=('source-outputs');;
|
||||||
get-source-*) cmd=('sources');;
|
|
||||||
set-source-*) cmd=('sources');;
|
set-source-*) cmd=('sources');;
|
||||||
suspend-sink) cmd=('sinks');;
|
suspend-sink) cmd=('sinks');;
|
||||||
suspend-source) cmd=('sources');;
|
suspend-source) cmd=('sources');;
|
||||||
|
|
@ -259,22 +257,16 @@ _pactl_completion() {
|
||||||
'suspend-sink: suspend or resume a sink'
|
'suspend-sink: suspend or resume a sink'
|
||||||
'suspend-source: suspend or resume a source'
|
'suspend-source: suspend or resume a source'
|
||||||
'set-card-profile: set a card profile'
|
'set-card-profile: set a card profile'
|
||||||
'get-default-sink: get the default sink'
|
|
||||||
'set-default-sink: set 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-default-source: set the default source'
|
||||||
'set-sink-port: set the sink port of a sink'
|
'set-sink-port: set the sink port of a sink'
|
||||||
'set-source-port: set the source port of a source'
|
'set-source-port: set the source port of a source'
|
||||||
'set-port-latency-offset: set a latency offset on a port'
|
'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'
|
'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-source-volume: set the volume of a source'
|
||||||
'set-sink-input-volume: set the volume of a stream'
|
'set-sink-input-volume: set the volume of a stream'
|
||||||
'set-source-output-volume: set the volume of a recording 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'
|
'set-sink-mute: mute a sink'
|
||||||
'get-source-mute: get the mute status of a source'
|
|
||||||
'set-source-mute: mute a source'
|
'set-source-mute: mute a source'
|
||||||
'set-sink-input-mute: mute a stream'
|
'set-sink-input-mute: mute a stream'
|
||||||
'set-source-output-mute: mute a recording 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-default-source) if ((CURRENT == 2)); then _devices; fi;;
|
||||||
set-sink-port) _set_sink_port_parameter;;
|
set-sink-port) _set_sink_port_parameter;;
|
||||||
set-source-port) _set_source_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;;
|
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-source-volume) if ((CURRENT == 2)); then _devices; fi;;
|
||||||
set-sink-input-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;;
|
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;;
|
set-sink-mute) _set_sink_mute_parameter;;
|
||||||
get-source-mute) if ((CURRENT == 2)); then _devices; fi;;
|
|
||||||
set-source-mute) _set_source_mute_parameter;;
|
set-source-mute) _set_source_mute_parameter;;
|
||||||
set-sink-input-mute) _set_sink_input_mute_parameter;;
|
set-sink-input-mute) _set_sink_input_mute_parameter;;
|
||||||
set-source-output-mute) _set_source_output_mute_parameter;;
|
set-source-output-mute) _set_source_output_mute_parameter;;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
if get_option('client')
|
if zshcompletiondir != 'no'
|
||||||
if zshcompletiondir != 'no'
|
install_data('_pulseaudio', install_dir : zshcompletiondir)
|
||||||
install_data('_pulseaudio', install_dir : zshcompletiondir)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
1
src/.gitignore
vendored
1
src/.gitignore
vendored
|
|
@ -71,7 +71,6 @@ proplist-test
|
||||||
queue-test
|
queue-test
|
||||||
remix-test
|
remix-test
|
||||||
resampler-test
|
resampler-test
|
||||||
resampler-rewind-test
|
|
||||||
rtpoll-test
|
rtpoll-test
|
||||||
rtstutter
|
rtstutter
|
||||||
sig2str-test
|
sig2str-test
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
|
||||||
|
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
if (pa_daemon_conf_set_log_level(conf, optarg) < 0) {
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,5 @@ load-module module-filter-apply
|
||||||
|
|
||||||
### Allow including a default.pa.d directory, which if present, can be used
|
### Allow including a default.pa.d directory, which if present, can be used
|
||||||
### for additional configuration snippets.
|
### for additional configuration snippets.
|
||||||
### Note that those snippet files must have a .pa file extension, not .conf
|
|
||||||
.nofail
|
.nofail
|
||||||
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/default.pa.d
|
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/default.pa.d
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ executable('pulseaudio',
|
||||||
install_rpath : privlibdir,
|
install_rpath : privlibdir,
|
||||||
include_directories : [configinc, topinc],
|
include_directories : [configinc, topinc],
|
||||||
link_args : ['-ffast-math'],
|
link_args : ['-ffast-math'],
|
||||||
link_with : [libpulsecore],
|
link_with : [libpulsecore, libpulsecommon, libpulse],
|
||||||
dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep, platform_dep, platform_socket_dep, libpulsecommon_dep, libpulse_dep],
|
dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep, platform_dep, platform_socket_dep],
|
||||||
c_args : pa_c_args,
|
c_args : pa_c_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ custom_target('system.pa',
|
||||||
|
|
||||||
if dbus_dep.found()
|
if dbus_dep.found()
|
||||||
install_data('pulseaudio-system.conf',
|
install_data('pulseaudio-system.conf',
|
||||||
install_dir : join_paths(datadir, 'dbus-1', 'system.d')
|
install_dir : join_paths(sysconfdir, 'dbus-1', 'system.d')
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,5 @@ load-module module-position-event-sounds
|
||||||
|
|
||||||
### Allow including a system.pa.d directory, which if present, can be used
|
### Allow including a system.pa.d directory, which if present, can be used
|
||||||
### for additional configuration snippets.
|
### for additional configuration snippets.
|
||||||
### Note that those snippet files must have a .pa file extension, not .conf
|
|
||||||
.nofail
|
.nofail
|
||||||
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/system.pa.d
|
.include @PA_DEFAULT_CONFIG_DIR_UNQUOTED@/system.pa.d
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,12 @@ libpulsecommon_sources = [
|
||||||
'pulsecore/shm.c',
|
'pulsecore/shm.c',
|
||||||
'pulsecore/bitset.c',
|
'pulsecore/bitset.c',
|
||||||
'pulsecore/socket-client.c',
|
'pulsecore/socket-client.c',
|
||||||
|
'pulsecore/socket-server.c',
|
||||||
'pulsecore/socket-util.c',
|
'pulsecore/socket-util.c',
|
||||||
'pulsecore/strbuf.c',
|
'pulsecore/strbuf.c',
|
||||||
'pulsecore/strlist.c',
|
'pulsecore/strlist.c',
|
||||||
'pulsecore/tagstruct.c',
|
'pulsecore/tagstruct.c',
|
||||||
'pulsecore/time-smoother.c',
|
'pulsecore/time-smoother.c',
|
||||||
'pulsecore/time-smoother_2.c',
|
|
||||||
'pulsecore/tokenizer.c',
|
'pulsecore/tokenizer.c',
|
||||||
'pulsecore/usergroup.c',
|
'pulsecore/usergroup.c',
|
||||||
'pulsecore/sndfile-util.c',
|
'pulsecore/sndfile-util.c',
|
||||||
|
|
@ -136,13 +136,13 @@ libpulsecommon_headers = [
|
||||||
'pulsecore/shm.h',
|
'pulsecore/shm.h',
|
||||||
'pulsecore/bitset.h',
|
'pulsecore/bitset.h',
|
||||||
'pulsecore/socket-client.h',
|
'pulsecore/socket-client.h',
|
||||||
|
'pulsecore/socket-server.h',
|
||||||
'pulsecore/socket-util.h',
|
'pulsecore/socket-util.h',
|
||||||
'pulsecore/strbuf.h',
|
'pulsecore/strbuf.h',
|
||||||
'pulsecore/strlist.h',
|
'pulsecore/strlist.h',
|
||||||
'pulsecore/tagstruct.h',
|
'pulsecore/tagstruct.h',
|
||||||
'pulsecore/thread.h',
|
'pulsecore/thread.h',
|
||||||
'pulsecore/time-smoother.h',
|
'pulsecore/time-smoother.h',
|
||||||
'pulsecore/time-smoother_2.h',
|
|
||||||
'pulsecore/tokenizer.h',
|
'pulsecore/tokenizer.h',
|
||||||
'pulsecore/usergroup.h',
|
'pulsecore/usergroup.h',
|
||||||
'pulsecore/sndfile-util.h',
|
'pulsecore/sndfile-util.h',
|
||||||
|
|
@ -182,47 +182,37 @@ if host_machine.system() == 'windows'
|
||||||
else
|
else
|
||||||
libpulsecommon_sources += [
|
libpulsecommon_sources += [
|
||||||
'pulsecore/mutex-posix.c',
|
'pulsecore/mutex-posix.c',
|
||||||
'pulsecore/poll-posix.c',
|
'pulsecore/semaphore-posix.c',
|
||||||
'pulsecore/thread-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
|
endif
|
||||||
# FIXME: Do SIMD things
|
# FIXME: Do SIMD things
|
||||||
|
|
||||||
if not get_option('client')
|
libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
|
||||||
libpulsecommon_dep = cc.find_library('pulsecommon-' + pa_version_major_minor, dirs : privlibdir, required : true)
|
libpulsecommon_sources,
|
||||||
libpulse_dep = dependency('libpulse', required : true)
|
libpulsecommon_headers,
|
||||||
libpulse_simple_dep = dependency('libpulse-simple', required : true)
|
include_directories : [configinc, topinc],
|
||||||
else
|
c_args : [pa_c_args],
|
||||||
libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
|
link_args : [nodelete_link_args],
|
||||||
libpulsecommon_sources,
|
install : true,
|
||||||
libpulsecommon_headers,
|
install_dir : privlibdir,
|
||||||
include_directories : [configinc, topinc],
|
dependencies : [
|
||||||
c_args : [pa_c_args],
|
libm_dep, thread_dep, dl_dep, shm_dep, iconv_dep, sndfile_dep, dbus_dep,
|
||||||
link_args : [nodelete_link_args],
|
x11_dep, libsystemd_dep, glib_dep.partial_dependency(compile_args: true),
|
||||||
install : true,
|
gtk_dep.partial_dependency(compile_args: true), asyncns_dep, libintl_dep,
|
||||||
install_dir : privlibdir,
|
platform_dep, tcpwrap_dep, platform_socket_dep, execinfo_dep,
|
||||||
dependencies : [
|
],
|
||||||
libm_dep, thread_dep, dl_dep, shm_dep, iconv_dep, sndfile_dep, dbus_dep,
|
implicit_include_directories : false)
|
||||||
x11_dep, libsystemd_dep, glib_dep.partial_dependency(compile_args: true),
|
|
||||||
gtk_dep.partial_dependency(compile_args: true), asyncns_dep, libintl_dep,
|
|
||||||
platform_dep, platform_socket_dep, execinfo_dep, libatomic_ops_dep,
|
|
||||||
],
|
|
||||||
implicit_include_directories : false)
|
|
||||||
|
|
||||||
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
|
libpulsecommon_dep = declare_dependency(link_with: libpulsecommon)
|
||||||
|
|
||||||
subdir('pulse')
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
subdir('pulse')
|
||||||
if get_option('daemon')
|
if get_option('daemon')
|
||||||
subdir('pulsecore')
|
subdir('pulsecore')
|
||||||
subdir('daemon')
|
subdir('daemon')
|
||||||
subdir('modules')
|
subdir('modules')
|
||||||
endif
|
endif
|
||||||
subdir('tests')
|
if get_option('tests')
|
||||||
|
subdir('tests')
|
||||||
|
endif
|
||||||
subdir('utils')
|
subdir('utils')
|
||||||
|
|
|
||||||
|
|
@ -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"
|
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}=="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}=="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}=="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}=="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}=="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}=="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}=="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"
|
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}=="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}=="1294", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", 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
|
# ID 1038:12c4 is for Arctis 9
|
||||||
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12c4", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="12c4", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
|
||||||
# Lucidsound LS31
|
# 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}=="005f", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
|
||||||
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="00a1", 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"
|
GOTO="pulseaudio_end"
|
||||||
|
|
||||||
LABEL="pulseaudio_check_pci"
|
LABEL="pulseaudio_check_pci"
|
||||||
|
|
|
||||||
|
|
@ -2838,7 +2838,7 @@ static int path_verify(pa_alsa_path *p) {
|
||||||
if (p->device_port_type == PA_DEVICE_PORT_TYPE_UNKNOWN)
|
if (p->device_port_type == PA_DEVICE_PORT_TYPE_UNKNOWN)
|
||||||
p->device_port_type = map->type;
|
p->device_port_type = map->type;
|
||||||
if (!p->description)
|
if (!p->description)
|
||||||
p->description = pa_xstrdup(_(map->description));
|
p->description = pa_xstrdup(map->description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->description) {
|
if (!p->description) {
|
||||||
|
|
@ -2851,44 +2851,41 @@ static int path_verify(pa_alsa_path *p) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_data_path(const char *data_dir, const char *data_type, const char *fname) {
|
static char *get_path_config_path(const char *paths_dir, const char *fname) {
|
||||||
char *result;
|
char *path_config_path;
|
||||||
char *dir;
|
char *dir;
|
||||||
char *data_home;
|
char *data_home;
|
||||||
pa_dynarray *data_dirs;
|
pa_dynarray *data_dirs;
|
||||||
|
|
||||||
if (data_dir) {
|
if (paths_dir) {
|
||||||
result = pa_maybe_prefix_path(fname, data_dir);
|
path_config_path = pa_maybe_prefix_path(fname, paths_dir);
|
||||||
if (access(result, R_OK) == 0)
|
if (access(path_config_path, R_OK) == 0)
|
||||||
return result;
|
return path_config_path;
|
||||||
else
|
else
|
||||||
pa_xfree(result);
|
pa_xfree(path_config_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
|
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
|
||||||
if (pa_run_from_build_tree()) {
|
if (pa_run_from_build_tree()) {
|
||||||
dir = pa_sprintf_malloc(PA_SRCDIR "/modules/alsa/mixer/%s/", data_type);
|
path_config_path = pa_maybe_prefix_path(fname, PA_SRCDIR "/modules/alsa/mixer/paths/");
|
||||||
result = pa_maybe_prefix_path(fname, dir);
|
if (access(path_config_path, R_OK) == 0)
|
||||||
pa_xfree(dir);
|
return path_config_path;
|
||||||
|
|
||||||
if (access(result, R_OK) == 0)
|
|
||||||
return result;
|
|
||||||
else
|
else
|
||||||
pa_xfree(result);
|
pa_xfree(path_config_path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pa_get_data_home_dir(&data_home) == 0) {
|
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);
|
pa_xfree(data_home);
|
||||||
|
|
||||||
result = pa_maybe_prefix_path(fname, dir);
|
path_config_path = pa_maybe_prefix_path(fname, dir);
|
||||||
pa_xfree(dir);
|
pa_xfree(dir);
|
||||||
|
|
||||||
if (access(result, R_OK) == 0)
|
if (access(path_config_path, R_OK) == 0)
|
||||||
return result;
|
return path_config_path;
|
||||||
else
|
else
|
||||||
pa_xfree(result);
|
pa_xfree(path_config_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pa_get_data_dirs(&data_dirs) == 0) {
|
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;
|
const char *n;
|
||||||
|
|
||||||
PA_DYNARRAY_FOREACH(n, data_dirs, idx) {
|
PA_DYNARRAY_FOREACH(n, data_dirs, idx) {
|
||||||
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "%s", n, data_type);
|
dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", n);
|
||||||
result = pa_maybe_prefix_path(fname, dir);
|
path_config_path = pa_maybe_prefix_path(fname, dir);
|
||||||
pa_xfree(dir);
|
pa_xfree(dir);
|
||||||
|
|
||||||
if (access(result, R_OK) == 0) {
|
if (access(path_config_path, R_OK) == 0) {
|
||||||
pa_dynarray_free(data_dirs);
|
pa_dynarray_free(data_dirs);
|
||||||
return result;
|
return path_config_path;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pa_xfree(result);
|
pa_xfree(path_config_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_dynarray_free(data_dirs);
|
pa_dynarray_free(data_dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = pa_sprintf_malloc(PA_ALSA_DATA_DIR PA_PATH_SEP "%s", data_type);
|
path_config_path = pa_maybe_prefix_path(fname, PA_ALSA_PATHS_DIR);
|
||||||
result = pa_maybe_prefix_path(fname, dir);
|
return path_config_path;
|
||||||
pa_xfree(dir);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) {
|
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[2].data = &p->description;
|
||||||
items[3].data = &mute_during_activation;
|
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);
|
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)
|
if (!fname)
|
||||||
fname = "default.conf";
|
fname = "default.conf";
|
||||||
|
|
||||||
fn = get_data_path(NULL, "profile-sets", fname);
|
fn = pa_maybe_prefix_path(fname,
|
||||||
|
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
|
||||||
pa_log_info("Loading profile set: %s", fn);
|
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);
|
r = pa_config_parse(fn, NULL, items, NULL, false, ps);
|
||||||
pa_xfree(fn);
|
pa_xfree(fn);
|
||||||
|
|
@ -5078,7 +5074,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
|
||||||
handle = pa_alsa_open_by_template(
|
handle = pa_alsa_open_by_template(
|
||||||
m->device_strings, dev_id, NULL, &try_ss,
|
m->device_strings, dev_id, NULL, &try_ss,
|
||||||
&try_map, mode, &try_period_size,
|
&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) {
|
if (handle && !exact_channels && m->channel_map.channels != try_map.channels) {
|
||||||
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
|
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||||
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
|
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,8 @@ struct pa_alsa_setting {
|
||||||
|
|
||||||
/* An entry for one ALSA mixer */
|
/* An entry for one ALSA mixer */
|
||||||
struct pa_alsa_mixer {
|
struct pa_alsa_mixer {
|
||||||
struct pa_alsa_mixer *alias;
|
|
||||||
snd_mixer_t *mixer_handle;
|
snd_mixer_t *mixer_handle;
|
||||||
|
int card_index;
|
||||||
pa_alsa_fdlist *fdl;
|
pa_alsa_fdlist *fdl;
|
||||||
bool used_for_probe_only:1;
|
bool used_for_probe_only:1;
|
||||||
};
|
};
|
||||||
|
|
@ -318,7 +318,7 @@ struct pa_alsa_mapping {
|
||||||
pa_sink *sink;
|
pa_sink *sink;
|
||||||
pa_source *source;
|
pa_source *source;
|
||||||
|
|
||||||
/* ucm device context */
|
/* ucm device context*/
|
||||||
pa_alsa_ucm_mapping_context ucm_context;
|
pa_alsa_ucm_mapping_context ucm_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -342,9 +342,6 @@ struct pa_alsa_profile {
|
||||||
|
|
||||||
pa_idxset *input_mappings;
|
pa_idxset *input_mappings;
|
||||||
pa_idxset *output_mappings;
|
pa_idxset *output_mappings;
|
||||||
|
|
||||||
/* ucm device context */
|
|
||||||
pa_alsa_ucm_profile_context ucm_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_alsa_decibel_fix {
|
struct pa_alsa_decibel_fix {
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,7 @@
|
||||||
#include <pulsecore/thread.h>
|
#include <pulsecore/thread.h>
|
||||||
#include <pulsecore/thread-mq.h>
|
#include <pulsecore/thread-mq.h>
|
||||||
#include <pulsecore/rtpoll.h>
|
#include <pulsecore/rtpoll.h>
|
||||||
|
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
#include <pulsecore/time-smoother_2.h>
|
|
||||||
#else
|
|
||||||
#include <pulsecore/time-smoother.h>
|
#include <pulsecore/time-smoother.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <modules/reserve-wrap.h>
|
#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_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*/
|
#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_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_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_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 */
|
#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 */
|
#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;
|
pa_rtpoll_item *alsa_rtpoll_item;
|
||||||
|
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_smoother_2 *smoother;
|
|
||||||
#else
|
|
||||||
pa_smoother *smoother;
|
pa_smoother *smoother;
|
||||||
#endif
|
|
||||||
uint64_t write_count;
|
uint64_t write_count;
|
||||||
uint64_t since_start;
|
uint64_t since_start;
|
||||||
|
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t smoother_interval;
|
pa_usec_t smoother_interval;
|
||||||
pa_usec_t last_smoother_update;
|
pa_usec_t last_smoother_update;
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_idxset *formats;
|
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 */
|
/* Reset smoother and counters */
|
||||||
static void reset_vars(struct userdata *u) {
|
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);
|
pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
|
||||||
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
||||||
u->last_smoother_update = 0;
|
u->last_smoother_update = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
u->first = true;
|
u->first = true;
|
||||||
u->since_start = 0;
|
u->since_start = 0;
|
||||||
|
|
@ -975,10 +955,7 @@ static void update_smoother(struct userdata *u) {
|
||||||
snd_pcm_sframes_t delay = 0;
|
snd_pcm_sframes_t delay = 0;
|
||||||
int64_t position;
|
int64_t position;
|
||||||
int err;
|
int err;
|
||||||
pa_usec_t now1 = 0;
|
pa_usec_t now1 = 0, now2;
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t now2;
|
|
||||||
#endif
|
|
||||||
snd_pcm_status_t *status;
|
snd_pcm_status_t *status;
|
||||||
snd_htimestamp_t htstamp = { 0, 0 };
|
snd_htimestamp_t htstamp = { 0, 0 };
|
||||||
|
|
||||||
|
|
@ -1001,16 +978,13 @@ static void update_smoother(struct userdata *u) {
|
||||||
if (now1 <= 0)
|
if (now1 <= 0)
|
||||||
now1 = pa_rtclock_now();
|
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 */
|
/* check if the time since the last update is bigger than the interval */
|
||||||
if (u->last_smoother_update > 0)
|
if (u->last_smoother_update > 0)
|
||||||
if (u->last_smoother_update + u->smoother_interval > now1)
|
if (u->last_smoother_update + u->smoother_interval > now1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
position = (int64_t) u->write_count - ((int64_t) delay * (int64_t) u->frame_size);
|
||||||
|
|
||||||
if (PA_UNLIKELY(position < 0))
|
if (PA_UNLIKELY(position < 0))
|
||||||
position = 0;
|
position = 0;
|
||||||
|
|
||||||
|
|
@ -1021,26 +995,18 @@ static void update_smoother(struct userdata *u) {
|
||||||
u->last_smoother_update = now1;
|
u->last_smoother_update = now1;
|
||||||
/* exponentially increase the update interval up to the MAX limit */
|
/* exponentially increase the update interval up to the MAX limit */
|
||||||
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
|
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t sink_get_latency(struct userdata *u) {
|
static int64_t sink_get_latency(struct userdata *u) {
|
||||||
int64_t delay;
|
int64_t delay;
|
||||||
pa_usec_t now1;
|
pa_usec_t now1, now2;
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t now2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
|
|
||||||
now1 = pa_rtclock_now();
|
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);
|
now2 = pa_smoother_get(u->smoother, now1);
|
||||||
|
|
||||||
delay = (int64_t) pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - (int64_t) now2;
|
delay = (int64_t) pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - (int64_t) now2;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (u->memchunk.memblock)
|
if (u->memchunk.memblock)
|
||||||
delay += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
|
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)
|
if (!u->pcm_handle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_smoother_2_pause(u->smoother, pa_rtclock_now());
|
|
||||||
#else
|
|
||||||
pa_smoother_pause(u->smoother, pa_rtclock_now());
|
pa_smoother_pause(u->smoother, pa_rtclock_now());
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Close PCM device */
|
/* Close PCM device */
|
||||||
close_pcm(u);
|
close_pcm(u);
|
||||||
|
|
@ -1532,7 +1494,6 @@ static void sink_set_volume_cb(pa_sink *s) {
|
||||||
pa_cvolume r;
|
pa_cvolume r;
|
||||||
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
|
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
|
||||||
bool deferred_volume = !!(s->flags & PA_SINK_DEFERRED_VOLUME);
|
bool deferred_volume = !!(s->flags & PA_SINK_DEFERRED_VOLUME);
|
||||||
bool write_to_hw = !deferred_volume;
|
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(u->mixer_path);
|
pa_assert(u->mixer_path);
|
||||||
|
|
@ -1541,14 +1502,7 @@ static void sink_set_volume_cb(pa_sink *s) {
|
||||||
/* Shift up by the base volume */
|
/* Shift up by the base volume */
|
||||||
pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->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
|
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, !deferred_volume) < 0)
|
||||||
* 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)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Shift down by the base volume, so that 0dB becomes maximum volume */
|
/* 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
|
else
|
||||||
sync_mixer(u, p);
|
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) {
|
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;
|
int i;
|
||||||
bool format_supported = false;
|
bool format_supported = false;
|
||||||
bool rate_supported = false;
|
bool rate_supported = false;
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_sample_spec effective_spec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_assert(u);
|
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++) {
|
for (i = 0; u->supported_formats[i] != PA_SAMPLE_MAX; i++) {
|
||||||
if (u->supported_formats[i] == spec->format) {
|
if (u->supported_formats[i] == spec->format) {
|
||||||
pa_sink_set_sample_format(u->sink, spec->format);
|
pa_sink_set_sample_format(u->sink, spec->format);
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
effective_spec.format = spec->format;
|
|
||||||
#endif
|
|
||||||
format_supported = true;
|
format_supported = true;
|
||||||
break;
|
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_log_info("Sink does not support sample format of %s, set it to a verified value",
|
||||||
pa_sample_format_to_string(spec->format));
|
pa_sample_format_to_string(spec->format));
|
||||||
pa_sink_set_sample_format(u->sink, u->verified_sample_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++) {
|
for (i = 0; u->supported_rates[i]; i++) {
|
||||||
if (u->supported_rates[i] == spec->rate) {
|
if (u->supported_rates[i] == spec->rate) {
|
||||||
pa_sink_set_sample_rate(u->sink, spec->rate);
|
pa_sink_set_sample_rate(u->sink, spec->rate);
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
effective_spec.rate = spec->rate;
|
|
||||||
#endif
|
|
||||||
rate_supported = true;
|
rate_supported = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1866,15 +1804,8 @@ static void sink_reconfigure_cb(pa_sink *s, pa_sample_spec *spec, bool passthrou
|
||||||
if (!rate_supported) {
|
if (!rate_supported) {
|
||||||
pa_log_info("Sink does not support sample rate of %u, set it to a verified value", spec->rate);
|
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);
|
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 */
|
/* Passthrough status change is handled during unsuspend */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2008,11 +1939,7 @@ static void thread_func(void *userdata) {
|
||||||
pa_log_info("Starting playback.");
|
pa_log_info("Starting playback.");
|
||||||
snd_pcm_start(u->pcm_handle);
|
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);
|
pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
|
||||||
#endif
|
|
||||||
|
|
||||||
u->first = false;
|
u->first = false;
|
||||||
}
|
}
|
||||||
|
|
@ -2046,11 +1973,7 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
/* Convert from the sound card time domain to the
|
/* Convert from the sound card time domain to the
|
||||||
* system time domain */
|
* 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);
|
cusec = pa_smoother_translate(u->smoother, pa_rtclock_now(), sleep_usec);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_TIMING
|
#ifdef DEBUG_TIMING
|
||||||
pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
|
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,
|
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);
|
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) {
|
if (mdev) {
|
||||||
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, true);
|
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, true);
|
||||||
} else {
|
} 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
|
* will be NULL, but the UCM device enable sequence will still need to be
|
||||||
* executed. */
|
* executed. */
|
||||||
if (u->sink->active_port && u->ucm_context) {
|
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;
|
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 volume_is_set;
|
||||||
bool mute_is_set;
|
bool mute_is_set;
|
||||||
pa_alsa_profile_set *profile_set = NULL;
|
pa_alsa_profile_set *profile_set = NULL;
|
||||||
void *state = NULL;
|
void *state;
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
snd_pcm_info_t* pcm_info;
|
|
||||||
const char *id;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_assert(m);
|
pa_assert(m);
|
||||||
pa_assert(ma);
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
u->smoother = pa_smoother_new(
|
u->smoother = pa_smoother_new(
|
||||||
SMOOTHER_ADJUST_USEC,
|
SMOOTHER_ADJUST_USEC,
|
||||||
SMOOTHER_WINDOW_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(),
|
pa_rtclock_now(),
|
||||||
true);
|
true);
|
||||||
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* use ucm */
|
/* use ucm */
|
||||||
if (mapping && mapping->ucm_context.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,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d,
|
&b, &d, mapping)))
|
||||||
&u->supported_formats, &u->supported_rates,
|
|
||||||
mapping)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
} 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,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d,
|
&b, &d, profile_set, &mapping)))
|
||||||
&u->supported_formats, &u->supported_rates,
|
|
||||||
profile_set, &mapping)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2556,9 +2470,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d,
|
&b, &d, false)))
|
||||||
&u->supported_formats, &u->supported_rates,
|
|
||||||
false)))
|
|
||||||
goto fail;
|
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->verified_sample_spec = ss;
|
||||||
|
|
||||||
|
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
|
||||||
if (!u->supported_formats) {
|
if (!u->supported_formats) {
|
||||||
pa_log_error("Failed to find any supported sample formats.");
|
pa_log_error("Failed to find any supported sample formats.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
|
||||||
if (!u->supported_rates) {
|
if (!u->supported_rates) {
|
||||||
pa_log_error("Failed to find any supported sample rates.");
|
pa_log_error("Failed to find any supported sample rates.");
|
||||||
goto fail;
|
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;
|
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) {
|
if (u->ucm_context) {
|
||||||
pa_device_port *port;
|
pa_device_port *port;
|
||||||
unsigned h_prio = 0;
|
unsigned h_prio = 0;
|
||||||
|
|
@ -2914,11 +2809,7 @@ static void userdata_free(struct userdata *u) {
|
||||||
pa_hashmap_free(u->mixers);
|
pa_hashmap_free(u->mixers);
|
||||||
|
|
||||||
if (u->smoother)
|
if (u->smoother)
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_smoother_2_free(u->smoother);
|
|
||||||
#else
|
|
||||||
pa_smoother_free(u->smoother);
|
pa_smoother_free(u->smoother);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (u->formats)
|
if (u->formats)
|
||||||
pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);
|
pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,7 @@
|
||||||
#include <pulsecore/thread.h>
|
#include <pulsecore/thread.h>
|
||||||
#include <pulsecore/thread-mq.h>
|
#include <pulsecore/thread-mq.h>
|
||||||
#include <pulsecore/rtpoll.h>
|
#include <pulsecore/rtpoll.h>
|
||||||
|
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
#include <pulsecore/time-smoother_2.h>
|
|
||||||
#else
|
|
||||||
#include <pulsecore/time-smoother.h>
|
#include <pulsecore/time-smoother.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <modules/reserve-wrap.h>
|
#include <modules/reserve-wrap.h>
|
||||||
|
|
||||||
|
|
@ -76,15 +71,11 @@
|
||||||
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
||||||
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */
|
#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_WINDOW_USEC (10*PA_USEC_PER_SEC) /* 10s */
|
||||||
#define SMOOTHER_ADJUST_USEC (1*PA_USEC_PER_SEC) /* 1s */
|
#define SMOOTHER_ADJUST_USEC (1*PA_USEC_PER_SEC) /* 1s */
|
||||||
|
|
||||||
#define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC) /* 2ms */
|
#define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC) /* 2ms */
|
||||||
#define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC) /* 200ms */
|
#define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC) /* 200ms */
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100)
|
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100)
|
||||||
|
|
||||||
|
|
@ -149,17 +140,10 @@ struct userdata {
|
||||||
|
|
||||||
pa_rtpoll_item *alsa_rtpoll_item;
|
pa_rtpoll_item *alsa_rtpoll_item;
|
||||||
|
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_smoother_2 *smoother;
|
|
||||||
#else
|
|
||||||
pa_smoother *smoother;
|
pa_smoother *smoother;
|
||||||
#endif
|
|
||||||
uint64_t read_count;
|
uint64_t read_count;
|
||||||
|
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t smoother_interval;
|
pa_usec_t smoother_interval;
|
||||||
pa_usec_t last_smoother_update;
|
pa_usec_t last_smoother_update;
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_reserve_wrapper *reserve;
|
pa_reserve_wrapper *reserve;
|
||||||
pa_hook_slot *reserve_slot;
|
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 */
|
/* Reset smoother and counters */
|
||||||
static void reset_vars(struct userdata *u) {
|
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);
|
pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
|
||||||
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
||||||
u->last_smoother_update = 0;
|
u->last_smoother_update = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
u->read_count = 0;
|
u->read_count = 0;
|
||||||
u->first = true;
|
u->first = true;
|
||||||
|
|
@ -482,12 +462,7 @@ static void reset_vars(struct userdata *u) {
|
||||||
|
|
||||||
/* Called from IO context */
|
/* Called from IO context */
|
||||||
static void close_pcm(struct userdata *u) {
|
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());
|
pa_smoother_pause(u->smoother, pa_rtclock_now());
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Let's suspend */
|
/* Let's suspend */
|
||||||
snd_pcm_close(u->pcm_handle);
|
snd_pcm_close(u->pcm_handle);
|
||||||
|
|
@ -902,10 +877,7 @@ static void update_smoother(struct userdata *u) {
|
||||||
snd_pcm_sframes_t delay = 0;
|
snd_pcm_sframes_t delay = 0;
|
||||||
uint64_t position;
|
uint64_t position;
|
||||||
int err;
|
int err;
|
||||||
pa_usec_t now1 = 0;
|
pa_usec_t now1 = 0, now2;
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t now2;
|
|
||||||
#endif
|
|
||||||
snd_pcm_status_t *status;
|
snd_pcm_status_t *status;
|
||||||
snd_htimestamp_t htstamp = { 0, 0 };
|
snd_htimestamp_t htstamp = { 0, 0 };
|
||||||
|
|
||||||
|
|
@ -928,16 +900,12 @@ static void update_smoother(struct userdata *u) {
|
||||||
if (now1 <= 0)
|
if (now1 <= 0)
|
||||||
now1 = pa_rtclock_now();
|
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 */
|
/* check if the time since the last update is bigger than the interval */
|
||||||
if (u->last_smoother_update > 0)
|
if (u->last_smoother_update > 0)
|
||||||
if (u->last_smoother_update + u->smoother_interval > now1)
|
if (u->last_smoother_update + u->smoother_interval > now1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
position = u->read_count + ((uint64_t) delay * (uint64_t) u->frame_size);
|
||||||
now2 = pa_bytes_to_usec(position, &u->source->sample_spec);
|
now2 = pa_bytes_to_usec(position, &u->source->sample_spec);
|
||||||
|
|
||||||
pa_smoother_put(u->smoother, now1, now2);
|
pa_smoother_put(u->smoother, now1, now2);
|
||||||
|
|
@ -945,27 +913,18 @@ static void update_smoother(struct userdata *u) {
|
||||||
u->last_smoother_update = now1;
|
u->last_smoother_update = now1;
|
||||||
/* exponentially increase the update interval up to the MAX limit */
|
/* exponentially increase the update interval up to the MAX limit */
|
||||||
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
|
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t source_get_latency(struct userdata *u) {
|
static int64_t source_get_latency(struct userdata *u) {
|
||||||
int64_t delay;
|
int64_t delay;
|
||||||
pa_usec_t now1;
|
pa_usec_t now1, now2;
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
pa_usec_t now2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
|
|
||||||
now1 = pa_rtclock_now();
|
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);
|
now2 = pa_smoother_get(u->smoother, now1);
|
||||||
|
|
||||||
delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec(u->read_count, &u->source->sample_spec);
|
delay = (int64_t) now2 - (int64_t) pa_bytes_to_usec(u->read_count, &u->source->sample_spec);
|
||||||
#endif
|
|
||||||
|
|
||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
@ -1406,7 +1365,6 @@ static void source_set_volume_cb(pa_source *s) {
|
||||||
pa_cvolume r;
|
pa_cvolume r;
|
||||||
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
|
char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
|
||||||
bool deferred_volume = !!(s->flags & PA_SOURCE_DEFERRED_VOLUME);
|
bool deferred_volume = !!(s->flags & PA_SOURCE_DEFERRED_VOLUME);
|
||||||
bool write_to_hw = !deferred_volume;
|
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(u->mixer_path);
|
pa_assert(u->mixer_path);
|
||||||
|
|
@ -1415,14 +1373,7 @@ static void source_set_volume_cb(pa_source *s) {
|
||||||
/* Shift up by the base volume */
|
/* Shift up by the base volume */
|
||||||
pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->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
|
if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r, deferred_volume, !deferred_volume) < 0)
|
||||||
* 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)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Shift down by the base volume, so that 0dB becomes maximum volume */
|
/* 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
|
else
|
||||||
sync_mixer(u, p);
|
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) {
|
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;
|
int i;
|
||||||
bool format_supported = false;
|
bool format_supported = false;
|
||||||
bool rate_supported = false;
|
bool rate_supported = false;
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_sample_spec effective_spec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pa_assert(u);
|
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++) {
|
for (i = 0; u->supported_formats[i] != PA_SAMPLE_MAX; i++) {
|
||||||
if (u->supported_formats[i] == spec->format) {
|
if (u->supported_formats[i] == spec->format) {
|
||||||
pa_source_set_sample_format(u->source, spec->format);
|
pa_source_set_sample_format(u->source, spec->format);
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
effective_spec.format = spec->format;
|
|
||||||
#endif
|
|
||||||
format_supported = true;
|
format_supported = true;
|
||||||
break;
|
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_log_info("Source does not support sample format of %s, set it to a verified value",
|
||||||
pa_sample_format_to_string(spec->format));
|
pa_sample_format_to_string(spec->format));
|
||||||
pa_source_set_sample_format(u->source, u->verified_sample_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++) {
|
for (i = 0; u->supported_rates[i]; i++) {
|
||||||
if (u->supported_rates[i] == spec->rate) {
|
if (u->supported_rates[i] == spec->rate) {
|
||||||
pa_source_set_sample_rate(u->source, spec->rate);
|
pa_source_set_sample_rate(u->source, spec->rate);
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
effective_spec.rate = spec->rate;
|
|
||||||
#endif
|
|
||||||
rate_supported = true;
|
rate_supported = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1681,15 +1616,7 @@ static void source_reconfigure_cb(pa_source *s, pa_sample_spec *spec, bool passt
|
||||||
if (!rate_supported) {
|
if (!rate_supported) {
|
||||||
pa_log_info("Source does not support sample rate of %u, set it to a verfied value", spec->rate);
|
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);
|
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) {
|
static void thread_func(void *userdata) {
|
||||||
|
|
@ -1723,11 +1650,7 @@ static void thread_func(void *userdata) {
|
||||||
pa_log_info("Starting capture.");
|
pa_log_info("Starting capture.");
|
||||||
snd_pcm_start(u->pcm_handle);
|
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);
|
pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
|
||||||
#endif
|
|
||||||
|
|
||||||
u->first = false;
|
u->first = false;
|
||||||
}
|
}
|
||||||
|
|
@ -1755,11 +1678,7 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
/* Convert from the sound card time domain to the
|
/* Convert from the sound card time domain to the
|
||||||
* system time domain */
|
* 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);
|
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); */
|
/* 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,
|
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);
|
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) {
|
if (mdev) {
|
||||||
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, false);
|
u->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, mdev, false);
|
||||||
} else {
|
} 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
|
* will be NULL, but the UCM device enable sequence will still need to be
|
||||||
* executed. */
|
* executed. */
|
||||||
if (u->source->active_port && u->ucm_context) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2158,7 +2078,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_SMOOTHER_2
|
|
||||||
u->smoother = pa_smoother_new(
|
u->smoother = pa_smoother_new(
|
||||||
SMOOTHER_ADJUST_USEC,
|
SMOOTHER_ADJUST_USEC,
|
||||||
SMOOTHER_WINDOW_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(),
|
pa_rtclock_now(),
|
||||||
true);
|
true);
|
||||||
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* use ucm */
|
/* use ucm */
|
||||||
if (mapping && mapping->ucm_context.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,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, &u->supported_formats, &u->supported_rates, mapping)))
|
&b, &d, mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
} 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,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, &u->supported_formats, &u->supported_rates, profile_set, &mapping)))
|
&b, &d, profile_set, &mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2243,7 +2161,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, &u->supported_formats, &u->supported_rates, false)))
|
&b, &d, false)))
|
||||||
goto fail;
|
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->verified_sample_spec = ss;
|
||||||
|
|
||||||
|
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
|
||||||
if (!u->supported_formats) {
|
if (!u->supported_formats) {
|
||||||
pa_log_error("Failed to find any supported sample formats.");
|
pa_log_error("Failed to find any supported sample formats.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
|
||||||
if (!u->supported_rates) {
|
if (!u->supported_rates) {
|
||||||
pa_log_error("Failed to find any supported sample rates.");
|
pa_log_error("Failed to find any supported sample rates.");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -2366,10 +2286,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
goto fail;
|
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) {
|
if (u->ucm_context) {
|
||||||
pa_device_port *port;
|
pa_device_port *port;
|
||||||
unsigned h_prio = 0;
|
unsigned h_prio = 0;
|
||||||
|
|
@ -2531,11 +2447,7 @@ static void userdata_free(struct userdata *u) {
|
||||||
pa_hashmap_free(u->mixers);
|
pa_hashmap_free(u->mixers);
|
||||||
|
|
||||||
if (u->smoother)
|
if (u->smoother)
|
||||||
#ifdef USE_SMOOTHER_2
|
|
||||||
pa_smoother_2_free(u->smoother);
|
|
||||||
#else
|
|
||||||
pa_smoother_free(u->smoother);
|
pa_smoother_free(u->smoother);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (u->supported_formats)
|
if (u->supported_formats)
|
||||||
pa_xfree(u->supported_formats);
|
pa_xfree(u->supported_formats);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -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_device pa_alsa_ucm_device;
|
||||||
typedef struct pa_alsa_ucm_config pa_alsa_ucm_config;
|
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_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_port_data pa_alsa_ucm_port_data;
|
||||||
typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
|
typedef struct pa_alsa_ucm_volume pa_alsa_ucm_volume;
|
||||||
|
|
||||||
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index);
|
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);
|
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);
|
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,
|
pa_card *card,
|
||||||
snd_pcm_t *pcm_handle,
|
snd_pcm_t *pcm_handle,
|
||||||
bool ignore_dB);
|
bool ignore_dB);
|
||||||
void pa_alsa_ucm_add_port(
|
void pa_alsa_ucm_add_ports_combination(
|
||||||
pa_hashmap *hash,
|
pa_hashmap *hash,
|
||||||
pa_alsa_ucm_mapping_context *context,
|
pa_alsa_ucm_mapping_context *context,
|
||||||
bool is_sink,
|
bool is_sink,
|
||||||
pa_hashmap *ports,
|
pa_hashmap *ports,
|
||||||
pa_card_profile *cp,
|
pa_card_profile *cp,
|
||||||
pa_core *core);
|
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_free(pa_alsa_ucm_config *ucm);
|
||||||
void pa_alsa_ucm_mapping_context_free(pa_alsa_ucm_mapping_context *context);
|
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_proplist *proplist;
|
||||||
|
|
||||||
pa_idxset *conflicting_devices;
|
int n_confdev;
|
||||||
pa_idxset *supported_devices;
|
int n_suppdev;
|
||||||
|
|
||||||
|
const char **conflicting_devices;
|
||||||
|
const char **supported_devices;
|
||||||
|
|
||||||
pa_direction_t action_direction;
|
pa_direction_t action_direction;
|
||||||
|
|
||||||
|
|
@ -251,7 +253,6 @@ struct pa_alsa_ucm_config {
|
||||||
pa_core *core;
|
pa_core *core;
|
||||||
snd_use_case_mgr_t *ucm_mgr;
|
snd_use_case_mgr_t *ucm_mgr;
|
||||||
pa_alsa_ucm_verb *active_verb;
|
pa_alsa_ucm_verb *active_verb;
|
||||||
char *alib_prefix;
|
|
||||||
|
|
||||||
pa_hashmap *mixers;
|
pa_hashmap *mixers;
|
||||||
PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
|
PA_LLIST_HEAD(pa_alsa_ucm_verb, verbs);
|
||||||
|
|
@ -262,23 +263,21 @@ struct pa_alsa_ucm_mapping_context {
|
||||||
pa_alsa_ucm_config *ucm;
|
pa_alsa_ucm_config *ucm;
|
||||||
pa_direction_t direction;
|
pa_direction_t direction;
|
||||||
|
|
||||||
pa_alsa_ucm_device *ucm_device;
|
pa_idxset *ucm_devices;
|
||||||
pa_alsa_ucm_modifier *ucm_modifier;
|
pa_idxset *ucm_modifiers;
|
||||||
};
|
|
||||||
|
|
||||||
struct pa_alsa_ucm_profile_context {
|
|
||||||
pa_alsa_ucm_verb *verb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pa_alsa_ucm_port_data {
|
struct pa_alsa_ucm_port_data {
|
||||||
pa_alsa_ucm_config *ucm;
|
pa_alsa_ucm_config *ucm;
|
||||||
pa_device_port *core_port;
|
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;
|
pa_hashmap *paths;
|
||||||
/* Current path, set when activating verb */
|
/* Current path, set when activating profile */
|
||||||
pa_alsa_path *path;
|
pa_alsa_path *path;
|
||||||
|
|
||||||
/* ELD info */
|
/* ELD info */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
#include <pulsecore/thread.h>
|
#include <pulsecore/thread.h>
|
||||||
#include <pulsecore/conf-parser.h>
|
#include <pulsecore/conf-parser.h>
|
||||||
#include <pulsecore/core-rtclock.h>
|
#include <pulsecore/core-rtclock.h>
|
||||||
#include <pulsecore/strbuf.h>
|
|
||||||
|
|
||||||
#include "alsa-util.h"
|
#include "alsa-util.h"
|
||||||
#include "alsa-mixer.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,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
pa_sample_format_t **query_supported_formats,
|
|
||||||
unsigned int **query_supported_rates,
|
|
||||||
pa_alsa_profile_set *ps,
|
pa_alsa_profile_set *ps,
|
||||||
pa_alsa_mapping **mapping) {
|
pa_alsa_mapping **mapping) {
|
||||||
|
|
||||||
|
|
@ -563,8 +560,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
query_supported_formats,
|
|
||||||
query_supported_rates,
|
|
||||||
m);
|
m);
|
||||||
|
|
||||||
if (pcm_handle) {
|
if (pcm_handle) {
|
||||||
|
|
@ -592,8 +587,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
query_supported_formats,
|
|
||||||
query_supported_rates,
|
|
||||||
m);
|
m);
|
||||||
|
|
||||||
if (pcm_handle) {
|
if (pcm_handle) {
|
||||||
|
|
@ -618,8 +611,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
query_supported_formats,
|
|
||||||
query_supported_rates,
|
|
||||||
false);
|
false);
|
||||||
pa_xfree(d);
|
pa_xfree(d);
|
||||||
|
|
||||||
|
|
@ -640,8 +631,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
pa_sample_format_t **query_supported_formats,
|
|
||||||
unsigned int **query_supported_rates,
|
|
||||||
pa_alsa_mapping *m) {
|
pa_alsa_mapping *m) {
|
||||||
|
|
||||||
snd_pcm_t *pcm_handle;
|
snd_pcm_t *pcm_handle;
|
||||||
|
|
@ -671,8 +660,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
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 */);
|
pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
|
||||||
|
|
||||||
if (!pcm_handle)
|
if (!pcm_handle)
|
||||||
|
|
@ -696,8 +683,6 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
pa_sample_format_t **query_supported_formats,
|
|
||||||
unsigned int **query_supported_rates,
|
|
||||||
bool require_exact_channel_number) {
|
bool require_exact_channel_number) {
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -725,12 +710,6 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
|
|
||||||
pa_log_debug("Managed to open %s", d);
|
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(
|
if ((err = pa_alsa_set_hw_params(
|
||||||
pcm_handle,
|
pcm_handle,
|
||||||
ss,
|
ss,
|
||||||
|
|
@ -804,8 +783,6 @@ snd_pcm_t *pa_alsa_open_by_template(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
pa_sample_format_t **query_supported_formats,
|
|
||||||
unsigned int **query_supported_rates,
|
|
||||||
bool require_exact_channel_number) {
|
bool require_exact_channel_number) {
|
||||||
|
|
||||||
snd_pcm_t *pcm_handle;
|
snd_pcm_t *pcm_handle;
|
||||||
|
|
@ -827,8 +804,6 @@ snd_pcm_t *pa_alsa_open_by_template(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
query_supported_formats,
|
|
||||||
query_supported_rates,
|
|
||||||
require_exact_channel_number);
|
require_exact_channel_number);
|
||||||
|
|
||||||
pa_xfree(d);
|
pa_xfree(d);
|
||||||
|
|
@ -1431,31 +1406,13 @@ char *pa_alsa_get_reserve_name(const char *device) {
|
||||||
return pa_sprintf_malloc("Audio%i", i);
|
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) {
|
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
|
||||||
static unsigned int all_rates[] = { 8000, 11025, 12000,
|
static unsigned int all_rates[] = { 8000, 11025, 12000,
|
||||||
16000, 22050, 24000,
|
16000, 22050, 24000,
|
||||||
32000, 44100, 48000,
|
32000, 44100, 48000,
|
||||||
64000, 88200, 96000,
|
64000, 88200, 96000,
|
||||||
128000, 176400, 192000,
|
128000, 176400, 192000,
|
||||||
352800, 384000,
|
384000 };
|
||||||
705600, 768000 };
|
|
||||||
bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
|
bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
|
||||||
snd_pcm_hw_params_t *hwparams;
|
snd_pcm_hw_params_t *hwparams;
|
||||||
unsigned int i, j, n, *rates = NULL;
|
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;
|
rates[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_supported_rates(rates);
|
|
||||||
return rates;
|
return rates;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
|
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[] = {
|
static const snd_pcm_format_t format_trans_to_pa[] = {
|
||||||
[PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
|
[SND_PCM_FORMAT_U8] = PA_SAMPLE_U8,
|
||||||
[PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
|
[SND_PCM_FORMAT_A_LAW] = PA_SAMPLE_ALAW,
|
||||||
[PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
|
[SND_PCM_FORMAT_MU_LAW] = PA_SAMPLE_ULAW,
|
||||||
[PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
|
[SND_PCM_FORMAT_S16_LE] = PA_SAMPLE_S16LE,
|
||||||
[PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
|
[SND_PCM_FORMAT_S16_BE] = PA_SAMPLE_S16BE,
|
||||||
[PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
|
[SND_PCM_FORMAT_FLOAT_LE] = PA_SAMPLE_FLOAT32LE,
|
||||||
[PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
|
[SND_PCM_FORMAT_FLOAT_BE] = PA_SAMPLE_FLOAT32BE,
|
||||||
[PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
|
[SND_PCM_FORMAT_S32_LE] = PA_SAMPLE_S32LE,
|
||||||
[PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
|
[SND_PCM_FORMAT_S32_BE] = PA_SAMPLE_S32BE,
|
||||||
[PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
|
[SND_PCM_FORMAT_S24_3LE] = PA_SAMPLE_S24LE,
|
||||||
[PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
|
[SND_PCM_FORMAT_S24_3BE] = PA_SAMPLE_S24BE,
|
||||||
[PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
|
[SND_PCM_FORMAT_S24_LE] = PA_SAMPLE_S24_32LE,
|
||||||
[PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
|
[SND_PCM_FORMAT_S24_BE] = PA_SAMPLE_S24_32BE,
|
||||||
};
|
};
|
||||||
static const pa_sample_format_t all_formats[] = {
|
static const snd_pcm_format_t all_formats[] = {
|
||||||
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,
|
||||||
};
|
};
|
||||||
bool supported[PA_ELEMENTSOF(all_formats)] = {
|
bool supported[PA_ELEMENTSOF(all_formats)] = {
|
||||||
false,
|
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++) {
|
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;
|
supported[i] = true;
|
||||||
n++;
|
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++) {
|
for (i = 0, j = 0; i < PA_ELEMENTSOF(all_formats); i++) {
|
||||||
if (supported[i])
|
if (supported[i])
|
||||||
formats[j++] = all_formats[i];
|
formats[j++] = format_trans_to_pa[all_formats[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
formats[j] = PA_SAMPLE_MAX;
|
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 = pa_xnew(pa_sample_format_t, 2);
|
||||||
|
|
||||||
formats[0] = fallback_format;
|
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_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret));
|
||||||
pa_xfree(formats);
|
pa_xfree(formats);
|
||||||
return NULL;
|
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,
|
snd_ctl_elem_iface_t iface,
|
||||||
const char *name,
|
const char *name,
|
||||||
unsigned int index,
|
unsigned int index,
|
||||||
unsigned int device,
|
unsigned int device) {
|
||||||
unsigned int subdevice) {
|
|
||||||
snd_mixer_elem_t *elem;
|
snd_mixer_elem_t *elem;
|
||||||
|
|
||||||
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(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)
|
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
|
||||||
continue;
|
continue;
|
||||||
_helem = snd_mixer_elem_get_private(elem);
|
helem = snd_mixer_elem_get_private(elem);
|
||||||
helem = *_helem;
|
|
||||||
if (snd_hctl_elem_get_interface(helem) != iface)
|
if (snd_hctl_elem_get_interface(helem) != iface)
|
||||||
continue;
|
continue;
|
||||||
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
|
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;
|
continue;
|
||||||
if (snd_hctl_elem_get_device(helem) != device)
|
if (snd_hctl_elem_get_device(helem) != device)
|
||||||
continue;
|
continue;
|
||||||
if (snd_hctl_elem_get_subdevice(helem) != subdevice)
|
|
||||||
continue;
|
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
return NULL;
|
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) {
|
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) {
|
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)
|
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);
|
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,
|
static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
|
||||||
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
|
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
const char *name = snd_hctl_elem_get_name(helem);
|
const char *name = snd_hctl_elem_get_name(helem);
|
||||||
snd_hctl_elem_t **_helem;
|
if (mask & SND_CTL_EVENT_MASK_ADD) {
|
||||||
/* NOTE: The remove event is defined as '~0U`. */
|
|
||||||
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
|
|
||||||
/* NOTE: Unless we remove the pointer to melem from the linked-list at
|
|
||||||
* private_data of helem, an assertion will be hit in alsa-lib since
|
|
||||||
* the list is not empty. */
|
|
||||||
_helem = snd_mixer_elem_get_private(melem);
|
|
||||||
*_helem = NULL;
|
|
||||||
snd_mixer_elem_detach(melem, helem);
|
|
||||||
} else if (mask & SND_CTL_EVENT_MASK_ADD) {
|
|
||||||
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
|
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) {
|
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;
|
snd_mixer_elem_t *new_melem;
|
||||||
bool found = true;
|
|
||||||
|
|
||||||
new_melem = pa_alsa_mixer_find(mixer, iface, name, index, device, subdevice);
|
/* Put the hctl pointer as our private data - it will be useful for callbacks */
|
||||||
if (!new_melem) {
|
if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) {
|
||||||
_helem = pa_xmalloc(sizeof(snd_hctl_elem_t *));
|
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
|
||||||
*_helem = helem;
|
return 0;
|
||||||
/* Put the hctl pointer as our private data - it will be useful for callbacks */
|
|
||||||
if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, _helem, mixer_melem_free)) < 0) {
|
|
||||||
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
found = false;
|
|
||||||
} else {
|
|
||||||
_helem = snd_mixer_elem_get_private(new_melem);
|
|
||||||
if (_helem) {
|
|
||||||
char *s1, *s2;
|
|
||||||
snd_ctl_elem_id_t *id1, *id2;
|
|
||||||
snd_ctl_elem_id_alloca(&id1);
|
|
||||||
snd_ctl_elem_id_alloca(&id2);
|
|
||||||
snd_hctl_elem_get_id(helem, id1);
|
|
||||||
snd_hctl_elem_get_id(*_helem, id2);
|
|
||||||
s1 = snd_ctl_ascii_elem_id_get(id1);
|
|
||||||
s2 = snd_ctl_ascii_elem_id_get(id2);
|
|
||||||
pa_log_warn("mixer_class_event - duplicate mixer controls: %s | %s", s1, s2);
|
|
||||||
free(s2);
|
|
||||||
free(s1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*_helem = helem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
|
if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
|
||||||
pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
|
||||||
if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
|
pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
|
||||||
pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1783,14 +1687,14 @@ static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
|
||||||
return 0;
|
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;
|
int err;
|
||||||
snd_mixer_class_t *class;
|
snd_mixer_class_t *class;
|
||||||
|
|
||||||
pa_assert(mixer);
|
pa_assert(mixer);
|
||||||
pa_assert(dev);
|
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));
|
pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1829,29 +1733,37 @@ snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool pr
|
||||||
return m;
|
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) {
|
snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) {
|
||||||
int err;
|
int err;
|
||||||
snd_mixer_t *m;
|
snd_mixer_t *m;
|
||||||
snd_hctl_t *hctl;
|
|
||||||
pa_alsa_mixer *pm;
|
pa_alsa_mixer *pm;
|
||||||
|
char *dev2;
|
||||||
|
void *state;
|
||||||
|
|
||||||
pa_assert(mixers);
|
pa_assert(mixers);
|
||||||
pa_assert(dev);
|
pa_assert(dev);
|
||||||
|
|
||||||
pm = pa_hashmap_get(mixers, 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 (pm) {
|
||||||
if (!probe)
|
if (!probe)
|
||||||
pm->used_for_probe_only = false;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_hctl_open(&hctl, dev, 0);
|
if (prepare_mixer(m, dev) >= 0) {
|
||||||
if (err < 0) {
|
pm = pa_xnew0(pa_alsa_mixer, 1);
|
||||||
pa_log("Error opening hctl device: %s", pa_alsa_strerror(err));
|
if (pm) {
|
||||||
goto __close;
|
snd_hctl_t *hctl;
|
||||||
}
|
pm->card_index = -1;
|
||||||
|
/* determine the ALSA card number (index) and store it to card_index */
|
||||||
if (prepare_mixer(m, dev, hctl) >= 0) {
|
err = snd_mixer_get_hctl(m, dev, &hctl);
|
||||||
/* get the ALSA card number (index) and ID (alias) and create two identical mixers */
|
if (err >= 0) {
|
||||||
char *p, *dev2, *dev_idx, *dev_id;
|
snd_ctl_card_info_t *info;
|
||||||
snd_ctl_card_info_t *info;
|
snd_ctl_card_info_alloca(&info);
|
||||||
snd_ctl_card_info_alloca(&info);
|
err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
|
||||||
err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
|
if (err >= 0)
|
||||||
if (err < 0)
|
pm->card_index = snd_ctl_card_info_get_card(info);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
pm->used_for_probe_only = probe;
|
||||||
pa_xfree(dev_id);
|
pm->mixer_handle = m;
|
||||||
pa_xfree(dev_idx);
|
pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
|
||||||
pa_xfree(dev2);
|
|
||||||
__std:
|
|
||||||
if (pm == NULL)
|
|
||||||
pm = pa_alsa_create_mixer(mixers, dev, m, probe);
|
|
||||||
if (pm)
|
|
||||||
return m;
|
return m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__close:
|
|
||||||
snd_mixer_close(m);
|
snd_mixer_close(m);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1952,10 +1836,8 @@ void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
|
||||||
{
|
{
|
||||||
if (mixer->fdl)
|
if (mixer->fdl)
|
||||||
pa_alsa_fdlist_free(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);
|
snd_mixer_close(mixer->mixer_handle);
|
||||||
if (mixer->alias)
|
|
||||||
mixer->alias->alias = NULL;
|
|
||||||
pa_xfree(mixer);
|
pa_xfree(mixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* 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_profile_set *ps,
|
||||||
pa_alsa_mapping **mapping); /* modified at return */
|
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,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* 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);
|
pa_alsa_mapping *mapping);
|
||||||
|
|
||||||
/* Opens the explicit ALSA device */
|
/* Opens the explicit ALSA device */
|
||||||
|
|
@ -100,8 +96,6 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* 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);
|
bool require_exact_channel_number);
|
||||||
|
|
||||||
/* Opens the explicit ALSA device with a fallback list */
|
/* 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,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* 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);
|
bool require_exact_channel_number);
|
||||||
|
|
||||||
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
|
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,6 @@ description-key = analog-input-microphone-rear
|
||||||
[Jack Rear Mic]
|
[Jack Rear Mic]
|
||||||
required-any = any
|
required-any = any
|
||||||
|
|
||||||
[Jack Rear Mic - Input]
|
|
||||||
required-any = any
|
|
||||||
|
|
||||||
[Jack Rear Mic Phantom]
|
[Jack Rear Mic Phantom]
|
||||||
required-any = any
|
required-any = any
|
||||||
state.plugged = unknown
|
state.plugged = unknown
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -13,29 +13,22 @@
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
# 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
|
; Default mapping only allows to use stereo input and sound card has two
|
||||||
; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and
|
; physical input channels.
|
||||||
; some unbranded "usb mini microphone".
|
|
||||||
;
|
;
|
||||||
; Behringer UMC22 has stereo input (representing two physical mono inputs),
|
; However in case of only using a single input channel (like condenser
|
||||||
; others have mono input.
|
; 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
|
; This config includes mono input options which makes it much more
|
||||||
; doesn't have any input mixer controls.
|
; friendly in single input configuration.
|
||||||
;
|
|
||||||
; Since the UMC22 card has only stereo input PCM device but is commonly used
|
|
||||||
; with mono mics, we define special mono mappings using "mono,aux1" and
|
|
||||||
; "aux1,mono" channel maps. If we had only had the standard stereo input
|
|
||||||
; mapping, the user would have to record stereo tracks with one channel silent,
|
|
||||||
; which would be inconvenient.
|
|
||||||
;
|
;
|
||||||
; This config also removes default digital input/output mappings that do
|
; 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
|
; Added by Nazar Mokrynskyi <nazar@mokrynskyi.com>
|
||||||
; UMC22.
|
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
auto-profiles = yes
|
auto-profiles = yes
|
||||||
|
|
@ -43,28 +36,28 @@ auto-profiles = yes
|
||||||
[Mapping analog-stereo-input]
|
[Mapping analog-stereo-input]
|
||||||
device-strings = hw:%f
|
device-strings = hw:%f
|
||||||
channel-map = left,right
|
channel-map = left,right
|
||||||
paths-input = analog-input-mic analog-input
|
paths-input = analog-input-mic
|
||||||
direction = input
|
direction = input
|
||||||
priority = 4
|
priority = 4
|
||||||
|
|
||||||
[Mapping analog-mono]
|
[Mapping analog-mono]
|
||||||
device-strings = hw:%f
|
device-strings = hw:%f
|
||||||
channel-map = mono
|
channel-map = mono,mono
|
||||||
paths-input = analog-input-mic analog-input
|
paths-input = analog-input-mic
|
||||||
direction = input
|
direction = input
|
||||||
priority = 3
|
priority = 3
|
||||||
|
|
||||||
[Mapping analog-mono-left]
|
[Mapping analog-mono-left]
|
||||||
device-strings = hw:%f
|
device-strings = hw:%f
|
||||||
channel-map = mono,aux1
|
channel-map = mono,aux1
|
||||||
paths-input = analog-input-mic analog-input
|
paths-input = analog-input-mic
|
||||||
direction = input
|
direction = input
|
||||||
priority = 2
|
priority = 2
|
||||||
|
|
||||||
[Mapping analog-mono-right]
|
[Mapping analog-mono-right]
|
||||||
device-strings = hw:%f
|
device-strings = hw:%f
|
||||||
channel-map = aux1,mono
|
channel-map = aux1,mono
|
||||||
paths-input = analog-input-mic analog-input
|
paths-input = analog-input-mic
|
||||||
direction = input
|
direction = input
|
||||||
priority = 1
|
priority = 1
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ channel-map = aux0,aux1,left,right,aux2,aux3
|
||||||
direction = output
|
direction = output
|
||||||
|
|
||||||
[Mapping stereo-out-ef]
|
[Mapping stereo-out-ef]
|
||||||
description = Stereo 5/6 (S/PDIF)
|
description = Analog Stereo 5/6
|
||||||
device-strings = hw:%f,0,0
|
device-strings = hw:%f,0,0
|
||||||
channel-map = aux0,aux1,aux2,aux3,left,right
|
channel-map = aux0,aux1,aux2,aux3,left,right
|
||||||
direction = output
|
direction = output
|
||||||
|
|
@ -51,7 +51,7 @@ channel-map = mono,aux0,aux1,aux2,aux3,aux4
|
||||||
direction = input
|
direction = input
|
||||||
|
|
||||||
[Mapping analog-mono-in-b]
|
[Mapping analog-mono-in-b]
|
||||||
description = Analog Mono Input 2
|
description = Anlog Mono Input 2
|
||||||
device-strings = hw:%f,0,0
|
device-strings = hw:%f,0,0
|
||||||
channel-map = aux0,mono,aux1,aux2,aux3,aux4
|
channel-map = aux0,mono,aux1,aux2,aux3,aux4
|
||||||
direction = input
|
direction = input
|
||||||
|
|
@ -69,7 +69,7 @@ channel-map = aux0,aux1,left,right,aux2,aux3
|
||||||
direction = input
|
direction = input
|
||||||
|
|
||||||
[Mapping stereo-in-ef]
|
[Mapping stereo-in-ef]
|
||||||
description = Stereo Input 5/6 (S/PDIF)
|
description = Stereo Input 5/6
|
||||||
device-strings = hw:%f,0,0
|
device-strings = hw:%f,0,0
|
||||||
channel-map = aux0,aux1,aux2,aux3,left,right
|
channel-map = aux0,aux1,aux2,aux3,left,right
|
||||||
direction = input
|
direction = input
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
|
||||||
if (u->use_ucm)
|
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
|
else
|
||||||
pa_alsa_path_set_add_ports(m->output_path_set, cp, ports, NULL, u->core);
|
pa_alsa_path_set_add_ports(m->output_path_set, cp, ports, NULL, u->core);
|
||||||
if (m->channel_map.channels > cp->max_sink_channels)
|
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) {
|
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
|
||||||
if (u->use_ucm)
|
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
|
else
|
||||||
pa_alsa_path_set_add_ports(m->input_path_set, cp, ports, NULL, u->core);
|
pa_alsa_path_set_add_ports(m->input_path_set, cp, ports, NULL, u->core);
|
||||||
if (m->channel_map.channels > cp->max_source_channels)
|
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 UCM is available for this card then update the verb */
|
||||||
if (u->use_ucm) {
|
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;
|
ret = -1;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +302,7 @@ static void init_profile(struct userdata *u) {
|
||||||
|
|
||||||
if (d->profile && u->use_ucm) {
|
if (d->profile && u->use_ucm) {
|
||||||
/* Set initial verb */
|
/* 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);
|
pa_log("Failed to set ucm profile %s", d->profile->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -370,7 +371,7 @@ struct temp_port_avail {
|
||||||
|
|
||||||
static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
|
static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
|
||||||
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
|
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;
|
snd_ctl_elem_value_t *elem_value;
|
||||||
bool plugged_in;
|
bool plugged_in;
|
||||||
void *state;
|
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_available_t active_available = PA_AVAILABLE_UNKNOWN;
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
pa_assert(_elem);
|
|
||||||
elem = *_elem;
|
|
||||||
|
|
||||||
/* Changing the jack state may cause a port change, and a port change will
|
/* 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
|
* 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) {
|
static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
|
||||||
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
|
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);
|
||||||
int device;
|
int device = snd_hctl_elem_get_device(elem);
|
||||||
const char *old_monitor_name;
|
const char *old_monitor_name;
|
||||||
pa_device_port *p;
|
pa_device_port *p;
|
||||||
pa_hdmi_eld eld;
|
pa_hdmi_eld eld;
|
||||||
bool changed = false;
|
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)
|
if (mask == SND_CTL_EVENT_MASK_REMOVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ typedef struct pa_a2dp_endpoint_conf {
|
||||||
/* A2DP codec id */
|
/* A2DP codec id */
|
||||||
pa_a2dp_codec_id 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 */
|
/* Returns true if the codec can be supported on the system */
|
||||||
bool (*can_be_supported)(bool for_encoding);
|
bool (*can_be_supported)(bool for_encoding);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
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;
|
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))
|
if (PA_UNLIKELY(*processed == 0 || *processed != input_size))
|
||||||
pa_log_error("aptX encoding error");
|
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) {
|
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;
|
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.
|
/* 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)
|
* 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 = {
|
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx = {
|
||||||
.id = { A2DP_CODEC_VENDOR, APTX_VENDOR_ID, APTX_CODEC_ID },
|
.id = { A2DP_CODEC_VENDOR, APTX_VENDOR_ID, APTX_CODEC_ID },
|
||||||
|
.support_backchannel = false,
|
||||||
.can_be_supported = can_be_supported,
|
.can_be_supported = can_be_supported,
|
||||||
.can_accept_capabilities = can_accept_capabilities,
|
.can_accept_capabilities = can_accept_capabilities,
|
||||||
.choose_remote_endpoint = choose_remote_endpoint,
|
.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 = {
|
const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx_hd = {
|
||||||
.id = { A2DP_CODEC_VENDOR, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID },
|
.id = { A2DP_CODEC_VENDOR, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID },
|
||||||
|
.support_backchannel = false,
|
||||||
.can_be_supported = can_be_supported,
|
.can_be_supported = can_be_supported,
|
||||||
.can_accept_capabilities = can_accept_capabilities_hd,
|
.can_accept_capabilities = can_accept_capabilities_hd,
|
||||||
.choose_remote_endpoint = choose_remote_endpoint_hd,
|
.choose_remote_endpoint = choose_remote_endpoint_hd,
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <pulsecore/log.h>
|
#include <pulsecore/log.h>
|
||||||
#include <pulsecore/macro.h>
|
#include <pulsecore/macro.h>
|
||||||
#include <pulsecore/once.h>
|
#include <pulsecore/once.h>
|
||||||
#include <pulsecore/core-util.h>
|
#include <pulsecore/core-util.h>
|
||||||
#include <pulse/sample.h>
|
#include <pulse/sample.h>
|
||||||
#include <pulse/timeval.h>
|
|
||||||
#include <pulse/util.h>
|
#include <pulse/util.h>
|
||||||
|
|
||||||
#include "a2dp-codecs.h"
|
#include "a2dp-codecs.h"
|
||||||
|
|
@ -41,19 +39,83 @@ static void app_sink_eos(GstAppSink *appsink, gpointer userdata) {
|
||||||
pa_log_debug("Sink got EOS");
|
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) {
|
static void gst_deinit_common(struct gst_info *info) {
|
||||||
if (!info)
|
if (!info)
|
||||||
return;
|
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)
|
if (info->app_sink)
|
||||||
gst_object_unref(info->app_sink);
|
gst_object_unref(info->app_sink);
|
||||||
if (info->bin)
|
if (info->sink_adapter)
|
||||||
gst_object_unref(info->bin);
|
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) {
|
bool gst_init_common(struct gst_info *info) {
|
||||||
GstElement *bin = NULL;
|
GstElement *pipeline = NULL;
|
||||||
GstElement *appsink = NULL;
|
GstElement *appsrc = NULL, *appsink = NULL;
|
||||||
|
GstAdapter *adapter;
|
||||||
GstAppSinkCallbacks callbacks = { 0, };
|
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");
|
appsink = gst_element_factory_make("appsink", "app_sink");
|
||||||
if (!appsink) {
|
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);
|
g_object_set(appsink, "sync", FALSE, "async", FALSE, "enable-last-sample", FALSE, NULL);
|
||||||
|
|
||||||
callbacks.eos = app_sink_eos;
|
callbacks.eos = app_sink_eos;
|
||||||
|
callbacks.new_sample = app_sink_new_sample;
|
||||||
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &callbacks, info, NULL);
|
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &callbacks, info, NULL);
|
||||||
|
|
||||||
bin = gst_bin_new(NULL);
|
adapter = gst_adapter_new();
|
||||||
pa_assert(bin);
|
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->app_sink = appsink;
|
||||||
info->bin = bin;
|
info->sink_adapter = adapter;
|
||||||
|
info->pipeline = pipeline;
|
||||||
|
info->sample_ready_fdsem = pa_fdsem_new();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if (appsrc)
|
||||||
|
gst_object_unref(appsrc);
|
||||||
if (appsink)
|
if (appsink)
|
||||||
gst_object_unref(appsink);
|
gst_object_unref(appsink);
|
||||||
|
|
||||||
return false;
|
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) {
|
static GstCaps *gst_create_caps_from_sample_spec(const pa_sample_spec *ss) {
|
||||||
gchar *sample_format;
|
gchar *sample_format;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
uint64_t channel_mask;
|
int channel_mask;
|
||||||
|
|
||||||
switch (ss->format) {
|
switch (ss->format) {
|
||||||
case PA_SAMPLE_S16LE:
|
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) {
|
bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transcoder) {
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstEvent *event;
|
|
||||||
GstSegment segment;
|
|
||||||
GstEvent *stream_start;
|
|
||||||
guint group_id;
|
|
||||||
|
|
||||||
pa_assert(transcoder);
|
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))
|
if (!gst_init_common(info))
|
||||||
goto common_fail;
|
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");
|
pa_log_error("Failed to link codec elements into pipeline");
|
||||||
goto pipeline_fail;
|
goto pipeline_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pad = gst_element_get_static_pad(transcoder, "sink");
|
if (gst_element_set_state(info->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
|
||||||
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) {
|
|
||||||
pa_log_error("Could not start pipeline");
|
pa_log_error("Could not start pipeline");
|
||||||
goto pipeline_fail;
|
goto pipeline_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First, send stream-start sticky event */
|
/* See the comment on buffer probe functions */
|
||||||
group_id = gst_util_group_id_next();
|
pad = gst_element_get_static_pad(transcoder, "sink");
|
||||||
stream_start = gst_event_new_stream_start("gst-codec-pa");
|
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, gst_sink_buffer_probe, info, NULL);
|
||||||
gst_event_set_group_id(stream_start, group_id);
|
gst_object_unref(pad);
|
||||||
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);
|
|
||||||
|
|
||||||
pa_log_info("GStreamer pipeline initialisation succeeded");
|
pa_log_info("GStreamer pipeline initialisation succeeded");
|
||||||
|
|
||||||
|
|
@ -208,58 +295,40 @@ common_fail:
|
||||||
return false;
|
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;
|
struct gst_info *info = (struct gst_info *) codec_info;
|
||||||
gsize transcoded;
|
gsize available, transcoded;
|
||||||
GstBuffer *in_buf;
|
GstBuffer *in_buf;
|
||||||
|
GstMapInfo map_info;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
GstSample *sample;
|
|
||||||
|
|
||||||
pa_assert(info->pad_sink);
|
in_buf = gst_buffer_new_allocate(NULL, input_size, NULL);
|
||||||
|
|
||||||
in_buf = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY,
|
|
||||||
(gpointer)input_buffer, input_size, 0, input_size, NULL, NULL);
|
|
||||||
pa_assert(in_buf);
|
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)
|
pa_assert_se(gst_buffer_map(in_buf, &map_info, GST_MAP_WRITE));
|
||||||
GST_BUFFER_TIMESTAMP(in_buf) = GST_CLOCK_TIME_NONE;
|
memcpy(map_info.data, input_buffer, input_size);
|
||||||
else {
|
gst_buffer_unmap(in_buf, &map_info);
|
||||||
// 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));
|
|
||||||
|
|
||||||
|
ret = gst_app_src_push_buffer(GST_APP_SRC(info->app_src), in_buf);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (ret != GST_FLOW_OK) {
|
||||||
pa_log_error("failed to push buffer for transcoding %d", ret);
|
pa_log_error("failed to push buffer for transcoding %d", ret);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((sample = gst_app_sink_try_pull_sample(GST_APP_SINK(info->app_sink), 0))) {
|
pa_fdsem_wait(info->sample_ready_fdsem);
|
||||||
in_buf = gst_sample_get_buffer(sample);
|
|
||||||
|
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;
|
written += transcoded;
|
||||||
pa_assert(written <= output_size);
|
} else
|
||||||
|
pa_log_debug("No transcoded data available in adapter");
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
*processed = input_size;
|
*processed = input_size;
|
||||||
|
|
||||||
|
|
@ -274,13 +343,17 @@ fail:
|
||||||
void gst_codec_deinit(void *codec_info) {
|
void gst_codec_deinit(void *codec_info) {
|
||||||
struct gst_info *info = (struct gst_info *) codec_info;
|
struct gst_info *info = (struct gst_info *) codec_info;
|
||||||
|
|
||||||
if (info->bin) {
|
if (info->sample_ready_fdsem)
|
||||||
gst_element_set_state(info->bin, GST_STATE_NULL);
|
pa_fdsem_free(info->sample_ready_fdsem);
|
||||||
gst_object_unref(info->bin);
|
|
||||||
|
|
||||||
|
if (info->pipeline) {
|
||||||
|
gst_element_set_state(info->pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref(info->pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->pad_sink)
|
if (info->sink_adapter)
|
||||||
gst_object_unref(GST_OBJECT(info->pad_sink));
|
g_object_unref(info->sink_adapter);
|
||||||
|
|
||||||
pa_xfree(info);
|
pa_xfree(info);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,15 +43,15 @@ struct gst_info {
|
||||||
const a2dp_ldac_t *ldac_config;
|
const a2dp_ldac_t *ldac_config;
|
||||||
} a2dp_codec_t;
|
} a2dp_codec_t;
|
||||||
|
|
||||||
/* The appsink element that accumulates encoded/decoded buffers */
|
GstElement *app_src, *app_sink;
|
||||||
GstElement *app_sink;
|
GstElement *pipeline;
|
||||||
GstElement *bin;
|
GstAdapter *sink_adapter;
|
||||||
/* The sink pad to push to-be-encoded/decoded buffers into */
|
|
||||||
GstPad *pad_sink;
|
pa_fdsem *sample_ready_fdsem;
|
||||||
|
|
||||||
uint16_t seq_num;
|
uint16_t seq_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool gst_codec_init(struct gst_info *info, bool for_encoding, GstElement *transcoder);
|
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);
|
void gst_codec_deinit(void *codec_info);
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue