mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
Merge branch 'master' into dbus-work
Conflicts: src/daemon/daemon-conf.c
This commit is contained in:
commit
019331d25b
130 changed files with 24774 additions and 14714 deletions
17
Makefile.am
17
Makefile.am
|
|
@ -17,12 +17,27 @@
|
|||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = bootstrap.sh git-version-gen LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo
|
||||
EXTRA_DIST = \
|
||||
bootstrap.sh \
|
||||
git-version-gen \
|
||||
LICENSE \
|
||||
GPL \
|
||||
LGPL \
|
||||
doxygen/Makefile.am \
|
||||
doxygen/Makefile.in \
|
||||
doxygen/doxygen.conf.in \
|
||||
README \
|
||||
todo \
|
||||
vala/libpulse.vapi
|
||||
|
||||
SUBDIRS = src doxygen man po
|
||||
|
||||
MAINTAINERCLEANFILES =
|
||||
noinst_DATA =
|
||||
|
||||
vapidir = $(datadir)/vala/vapi
|
||||
vapi_DATA = vala/libpulse.vapi
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libpulse.pc libpulse-simple.pc
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 16)
|
|||
|
||||
# The stable ABI for client applications, for the version info x:y:z
|
||||
# always will hold y=z
|
||||
AC_SUBST(LIBPULSE_VERSION_INFO, [9:0:9])
|
||||
AC_SUBST(LIBPULSE_VERSION_INFO, [12:0:12])
|
||||
|
||||
# A simplified, synchronous, ABI-stable interface for client
|
||||
# applications, for the version info x:y:z always will hold y=z
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h ../src/pulse/gccmacro.h ../src/pulse/ext-stream-restore.h
|
||||
INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h ../src/pulse/gccmacro.h ../src/pulse/ext-stream-restore.h ../src/pulse/rtclock.h
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
|
|
|||
|
|
@ -133,11 +133,11 @@ USA.
|
|||
</option>
|
||||
|
||||
<option>
|
||||
<p><opt>cpu-limit=</opt> If disabled d not install the CPU load
|
||||
<p><opt>cpu-limit=</opt> If disabled do not install the CPU load
|
||||
limiter, even on platforms where it is supported. This option is
|
||||
useful when debugging/profiling PulseAudio to disable disturbing
|
||||
SIGXCPU signals. Takes a boolean argument, defaults to
|
||||
<opt>yes</opt>. The <opt>--no-cpu-limit</opt> command line
|
||||
<opt>no</opt>. The <opt>--no-cpu-limit</opt> command line
|
||||
argument takes precedence.</p>
|
||||
</option>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ as
|
|||
bn_IN
|
||||
ca
|
||||
cs
|
||||
de_CH
|
||||
de
|
||||
de_CH
|
||||
el
|
||||
es
|
||||
fi
|
||||
|
|
@ -11,17 +11,18 @@ fr
|
|||
gu
|
||||
hi
|
||||
it
|
||||
ja
|
||||
kn
|
||||
ko
|
||||
ml
|
||||
mr
|
||||
nl
|
||||
or
|
||||
pa
|
||||
pl
|
||||
pt_BR
|
||||
pt
|
||||
sr@latin
|
||||
pt_BR
|
||||
sr
|
||||
sr@latin
|
||||
sv
|
||||
ta
|
||||
te
|
||||
|
|
|
|||
|
|
@ -192,3 +192,5 @@ src/modules/alsa/alsa-source.c
|
|||
src/modules/alsa/module-alsa-card.c
|
||||
src/modules/bluetooth/module-bluetooth-device.c
|
||||
src/modules/reserve-wrap.c
|
||||
src/modules/module-rygel-media-server.c
|
||||
src/modules/alsa/alsa-mixer.c
|
||||
|
|
|
|||
1306
po/bn_IN.po
1306
po/bn_IN.po
File diff suppressed because it is too large
Load diff
1190
po/de_CH.po
1190
po/de_CH.po
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
768
po/pt_BR.po
768
po/pt_BR.po
File diff suppressed because it is too large
Load diff
1357
po/sr@latin.po
1357
po/sr@latin.po
File diff suppressed because it is too large
Load diff
810
po/zh_CN.po
810
po/zh_CN.po
File diff suppressed because it is too large
Load diff
|
|
@ -178,8 +178,8 @@ pulseaudio_SOURCES = \
|
|||
daemon/main.c \
|
||||
daemon/server-lookup.c daemon/server-lookup.h
|
||||
|
||||
pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS)
|
||||
pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS)
|
||||
pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(DBUS_CFLAGS)
|
||||
pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(DBUS_LIBS)
|
||||
# This is needed because automake doesn't properly expand the foreach below
|
||||
pulseaudio_DEPENDENCIES = libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(PREOPEN_LIBS)
|
||||
|
||||
|
|
@ -497,18 +497,18 @@ sig2str_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
|||
|
||||
resampler_test_SOURCES = tests/resampler-test.c
|
||||
resampler_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
resampler_test_CFLAGS = $(AM_CFLAGS)
|
||||
resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
mix_test_SOURCES = tests/mix-test.c
|
||||
mix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
mix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
mix_test_CFLAGS = $(AM_CFLAGS)
|
||||
mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
remix_test_SOURCES = tests/remix-test.c
|
||||
remix_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
remix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
remix_test_CFLAGS = $(AM_CFLAGS)
|
||||
remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
smoother_test_SOURCES = tests/smoother-test.c
|
||||
smoother_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
|
|
@ -517,38 +517,38 @@ smoother_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
|||
|
||||
envelope_test_SOURCES = tests/envelope-test.c
|
||||
envelope_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
envelope_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
envelope_test_CFLAGS = $(AM_CFLAGS)
|
||||
envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
proplist_test_SOURCES = tests/proplist-test.c
|
||||
proplist_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
proplist_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
proplist_test_CFLAGS = $(AM_CFLAGS)
|
||||
proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
rtstutter_SOURCES = tests/rtstutter.c
|
||||
rtstutter_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
rtstutter_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
rtstutter_CFLAGS = $(AM_CFLAGS)
|
||||
rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
stripnul_SOURCES = tests/stripnul.c
|
||||
stripnul_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
stripnul_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
stripnul_CFLAGS = $(AM_CFLAGS)
|
||||
stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
lock_autospawn_test_SOURCES = tests/lock-autospawn-test.c
|
||||
lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
lock_autospawn_test_CFLAGS = $(AM_CFLAGS)
|
||||
lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
prioq_test_SOURCES = tests/prioq-test.c
|
||||
prioq_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
prioq_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
prioq_test_CFLAGS = $(AM_CFLAGS)
|
||||
prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
sigbus_test_SOURCES = tests/sigbus-test.c
|
||||
sigbus_test_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la
|
||||
sigbus_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
sigbus_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
|
||||
sigbus_test_CFLAGS = $(AM_CFLAGS)
|
||||
sigbus_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
gtk_test_SOURCES = tests/gtk-test.c
|
||||
gtk_test_LDADD = $(AM_LDADD) libpulse.la libpulse-mainloop-glib.la
|
||||
|
|
@ -859,9 +859,9 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
|
|||
pulsecore/time-smoother.c pulsecore/time-smoother.h \
|
||||
pulsecore/database.h
|
||||
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(WINSOCK_CFLAGS) $(LIBOIL_CFLAGS)
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(WINSOCK_CFLAGS)
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS = -avoid-version
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libpulsecore-foreign.la
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libpulsecore-foreign.la
|
||||
|
||||
if HAVE_X11
|
||||
libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/x11wrap.c pulsecore/x11wrap.h
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ static const pa_daemon_conf default_conf = {
|
|||
#ifdef HAVE_DBUS
|
||||
.local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
|
||||
#endif
|
||||
.no_cpu_limit = FALSE,
|
||||
.no_cpu_limit = TRUE,
|
||||
.disable_shm = FALSE,
|
||||
.lock_memory = FALSE,
|
||||
.default_n_fragments = 4,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
; enable-shm = yes
|
||||
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
|
||||
; lock-memory = no
|
||||
; cpu-limit = yes
|
||||
; cpu-limit = no
|
||||
|
||||
; high-priority = yes
|
||||
; nice-level = -11
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
; rlimit-msgqueue = -1
|
||||
; rlimit-nice = 31
|
||||
; rlimit-rtprio = 9
|
||||
; rlimit-rtttime = 1000000
|
||||
; rlimit-rttime = 1000000
|
||||
|
||||
; default-sample-format = s16le
|
||||
; default-sample-rate = 44100
|
||||
|
|
|
|||
|
|
@ -260,9 +260,14 @@ static int change_user(void) {
|
|||
pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
|
||||
|
||||
/* Relevant for pa_runtime_path() */
|
||||
pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
|
||||
pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
|
||||
pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
|
||||
if (!getenv("PULSE_RUNTIME_PATH"))
|
||||
pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
|
||||
|
||||
if (!getenv("PULSE_CONFIG_PATH"))
|
||||
pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
|
||||
|
||||
if (!getenv("PULSE_STATE_PATH"))
|
||||
pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
|
||||
|
||||
pa_log_info(_("Successfully dropped root privileges."));
|
||||
|
||||
|
|
@ -413,23 +418,28 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (!getenv("LD_BIND_NOW")) {
|
||||
char *rp;
|
||||
char *canonical_rp;
|
||||
|
||||
/* We have to execute ourselves, because the libc caches the
|
||||
* value of $LD_BIND_NOW on initialization. */
|
||||
|
||||
pa_set_env("LD_BIND_NOW", "1");
|
||||
|
||||
canonical_rp = pa_realpath(PA_BINARY);
|
||||
|
||||
if ((rp = pa_readlink("/proc/self/exe"))) {
|
||||
|
||||
if (pa_streq(rp, PA_BINARY))
|
||||
if (pa_streq(rp, canonical_rp))
|
||||
pa_assert_se(execv(rp, argv) == 0);
|
||||
else
|
||||
pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?");
|
||||
pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
|
||||
|
||||
pa_xfree(rp);
|
||||
|
||||
} else
|
||||
pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
|
||||
|
||||
pa_xfree(canonical_rp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -731,7 +741,7 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
}
|
||||
|
||||
pa_set_env("PULSE_INTERNAL", "1");
|
||||
pa_set_env_and_record("PULSE_INTERNAL", "1");
|
||||
pa_assert_se(chdir("/") == 0);
|
||||
umask(0022);
|
||||
|
||||
|
|
@ -746,7 +756,7 @@ int main(int argc, char *argv[]) {
|
|||
if (change_user() < 0)
|
||||
goto finish;
|
||||
|
||||
pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
|
||||
pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
|
||||
|
||||
pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
|
||||
pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
|
||||
|
|
@ -853,8 +863,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
pa_memtrap_install();
|
||||
|
||||
pa_cpu_init_x86();
|
||||
pa_cpu_init_arm();
|
||||
if (!getenv("PULSE_NO_SIMD")) {
|
||||
pa_cpu_init_x86();
|
||||
pa_cpu_init_arm();
|
||||
}
|
||||
|
||||
pa_assert_se(mainloop = pa_mainloop_new());
|
||||
|
||||
|
|
@ -1021,6 +1033,9 @@ finish:
|
|||
if (valid_pid_file)
|
||||
pa_pid_file_remove();
|
||||
|
||||
/* This has no real purpose except making things valgrind-clean */
|
||||
pa_unset_env_recorded();
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
|
||||
<!DOCTYPE policyconfig PUBLIC
|
||||
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
|
||||
<!--
|
||||
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 Lesser General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
-->
|
||||
|
||||
<policyconfig>
|
||||
<vendor>The PulseAudio Project</vendor>
|
||||
<vendor_url>http://pulseaudio.org/</vendor_url>
|
||||
<icon_name>audio-card</icon_name>
|
||||
|
||||
<action id="org.pulseaudio.acquire-real-time">
|
||||
<_description>Real-time scheduling for the PulseAudio daemon</_description>
|
||||
<_message>System policy prevents PulseAudio from acquiring real-time scheduling.</_message>
|
||||
<defaults>
|
||||
<allow_any>no</allow_any>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>no</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.pulseaudio.acquire-high-priority">
|
||||
<_description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</_description>
|
||||
<_message>System policy prevents PulseAudio from acquiring high-priority scheduling.</_message>
|
||||
<defaults>
|
||||
<allow_any>no</allow_any>
|
||||
<allow_inactive>no</allow_inactive>
|
||||
<allow_active>no</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2004-2006 Lennart Poettering
|
||||
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <polkit-dbus/polkit-dbus.h>
|
||||
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "polkit.h"
|
||||
|
||||
int pa_polkit_check(const char *action_id) {
|
||||
int ret = -1;
|
||||
DBusError dbus_error;
|
||||
DBusConnection *bus = NULL;
|
||||
PolKitCaller *caller = NULL;
|
||||
PolKitAction *action = NULL;
|
||||
PolKitContext *context = NULL;
|
||||
PolKitError *polkit_error = NULL;
|
||||
PolKitSession *session = NULL;
|
||||
PolKitResult polkit_result;
|
||||
|
||||
dbus_error_init(&dbus_error);
|
||||
|
||||
if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) {
|
||||
pa_log_error(_("Cannot connect to system bus: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* There seems to be a bug in some versions of D-Bus that causes
|
||||
* dbus_shutdown() to call exit() when a connection without this
|
||||
* flag disabled was created during runtime.*/
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
if (!(caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error))) {
|
||||
pa_log_error(_("Cannot get caller from PID: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* This function is called when PulseAudio is called SUID root. We
|
||||
* want to authenticate the real user that called us and not the
|
||||
* effective user we gained through being SUID root. Hence we
|
||||
* overwrite the UID caller data here explicitly, just for
|
||||
* paranoia. In fact PolicyKit should fill in the UID here anyway
|
||||
* -- an not the EUID or any other user id. */
|
||||
|
||||
if (!(polkit_caller_set_uid(caller, getuid()))) {
|
||||
pa_log_error(_("Cannot set UID on caller object."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(polkit_caller_get_ck_session(caller, &session))) {
|
||||
pa_log_error(_("Failed to get CK session."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* We need to overwrite the UID in both the caller and the session
|
||||
* object */
|
||||
|
||||
if (!(polkit_session_set_uid(session, getuid()))) {
|
||||
pa_log_error(_("Cannot set UID on session object."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(action = polkit_action_new())) {
|
||||
pa_log_error(_("Cannot allocate PolKitAction."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!polkit_action_set_action_id(action, action_id)) {
|
||||
pa_log_error(_("Cannot set action_id"));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(context = polkit_context_new())) {
|
||||
pa_log_error(_("Cannot allocate PolKitContext."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!polkit_context_init(context, &polkit_error)) {
|
||||
pa_log_error(_("Cannot initialize PolKitContext: %s"), polkit_error_get_error_message(polkit_error));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
|
||||
|
||||
if (polkit_error_is_set(polkit_error)) {
|
||||
pa_log_error(_("Could not determine whether caller is authorized: %s"), polkit_error_get_error_message(polkit_error));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS ||
|
||||
polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
|
||||
) {
|
||||
|
||||
if (polkit_auth_obtain(action_id, 0, getpid(), &dbus_error)) {
|
||||
polkit_result = POLKIT_RESULT_YES;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dbus_error_is_set(&dbus_error)) {
|
||||
pa_log_error(_("Cannot obtain auth: %s"), dbus_error.message);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (polkit_result != POLKIT_RESULT_YES && polkit_result != POLKIT_RESULT_NO)
|
||||
pa_log_warn(_("PolicyKit responded with '%s'"), polkit_result_to_string_representation(polkit_result));
|
||||
|
||||
ret = polkit_result == POLKIT_RESULT_YES;
|
||||
|
||||
finish:
|
||||
|
||||
if (caller)
|
||||
polkit_caller_unref(caller);
|
||||
|
||||
if (action)
|
||||
polkit_action_unref(action);
|
||||
|
||||
if (context)
|
||||
polkit_context_unref(context);
|
||||
|
||||
if (bus)
|
||||
dbus_connection_unref(bus);
|
||||
|
||||
dbus_error_free(&dbus_error);
|
||||
|
||||
if (polkit_error)
|
||||
polkit_error_free(polkit_error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef foopolkithfoo
|
||||
#define foopolkithfoo
|
||||
|
||||
/***
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2007 Lennart Poettering
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published
|
||||
by the Free Software Foundation; either version 2.1 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
PulseAudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with PulseAudio; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
***/
|
||||
|
||||
int pa_polkit_check(const char *action);
|
||||
|
||||
#endif
|
||||
|
|
@ -479,7 +479,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -546,9 +545,6 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
f = from_alsa_volume(value, e->min_volume, e->max_volume);
|
||||
}
|
||||
|
||||
if (f > max_channel_volume)
|
||||
max_channel_volume = f;
|
||||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
|
||||
if (v->values[k] < f)
|
||||
|
|
@ -559,7 +555,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
|
||||
v->values[k] = max_channel_volume;
|
||||
v->values[k] = PA_VOLUME_NORM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -681,7 +677,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
snd_mixer_elem_t *me;
|
||||
snd_mixer_selem_channel_id_t c;
|
||||
pa_channel_position_mask_t mask = 0;
|
||||
pa_volume_t max_channel_volume = PA_VOLUME_MUTED;
|
||||
unsigned k;
|
||||
|
||||
pa_assert(m);
|
||||
|
|
@ -771,9 +766,6 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
f = from_alsa_volume(value, e->min_volume, e->max_volume);
|
||||
}
|
||||
|
||||
if (f > max_channel_volume)
|
||||
max_channel_volume = f;
|
||||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (e->masks[c][e->n_channels-1] & PA_CHANNEL_POSITION_MASK(cm->map[k]))
|
||||
if (rv.values[k] < f)
|
||||
|
|
@ -784,7 +776,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
|
|||
|
||||
for (k = 0; k < cm->channels; k++)
|
||||
if (!(mask & PA_CHANNEL_POSITION_MASK(cm->map[k])))
|
||||
rv.values[k] = max_channel_volume;
|
||||
rv.values[k] = PA_VOLUME_NORM;
|
||||
|
||||
*v = rv;
|
||||
return 0;
|
||||
|
|
@ -1716,11 +1708,11 @@ static int option_verify(pa_alsa_option *o) {
|
|||
{ "input-radio", N_("Radio") },
|
||||
{ "input-video", N_("Video") },
|
||||
{ "input-agc-on", N_("Automatic Gain Control") },
|
||||
{ "input-agc-off", "" },
|
||||
{ "input-agc-off", N_("No Automatic Gain Control") },
|
||||
{ "input-boost-on", N_("Boost") },
|
||||
{ "input-boost-off", "" },
|
||||
{ "input-boost-off", N_("No Boost") },
|
||||
{ "output-amplifier-on", N_("Amplifier") },
|
||||
{ "output-amplifier-off", "" }
|
||||
{ "output-amplifier-off", N_("No Amplifier") }
|
||||
};
|
||||
|
||||
pa_assert(o);
|
||||
|
|
@ -2889,7 +2881,7 @@ static void profile_set_add_auto_pair(
|
|||
else
|
||||
name = pa_sprintf_malloc("input:%s", n->name);
|
||||
|
||||
if ((p = pa_hashmap_get(ps->profiles, name))) {
|
||||
if (pa_hashmap_get(ps->profiles, name)) {
|
||||
pa_xfree(name);
|
||||
return;
|
||||
}
|
||||
|
|
@ -3145,7 +3137,13 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss) {
|
||||
void pa_alsa_profile_set_probe(
|
||||
pa_alsa_profile_set *ps,
|
||||
const char *dev_id,
|
||||
const pa_sample_spec *ss,
|
||||
unsigned default_n_fragments,
|
||||
unsigned default_fragment_size_msec) {
|
||||
|
||||
void *state;
|
||||
pa_alsa_profile *p, *last = NULL;
|
||||
pa_alsa_mapping *m;
|
||||
|
|
@ -3160,6 +3158,7 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
|
||||
pa_sample_spec try_ss;
|
||||
pa_channel_map try_map;
|
||||
snd_pcm_uframes_t try_period_size, try_buffer_size;
|
||||
uint32_t idx;
|
||||
|
||||
/* Is this already marked that it is supported? (i.e. from the config file) */
|
||||
|
|
@ -3213,13 +3212,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
try_ss = *ss;
|
||||
try_ss.channels = try_map.channels;
|
||||
|
||||
try_period_size =
|
||||
pa_usec_to_bytes(default_fragment_size_msec * PA_USEC_PER_MSEC, &try_ss) /
|
||||
pa_frame_size(&try_ss);
|
||||
try_buffer_size = default_n_fragments * try_period_size;
|
||||
|
||||
if (!(m ->output_pcm = pa_alsa_open_by_template(
|
||||
m->device_strings,
|
||||
dev_id,
|
||||
NULL,
|
||||
&try_ss, &try_map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
&try_period_size, &try_buffer_size, 0, NULL, NULL,
|
||||
TRUE))) {
|
||||
p->supported = FALSE;
|
||||
break;
|
||||
|
|
@ -3237,13 +3241,18 @@ void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, cons
|
|||
try_ss = *ss;
|
||||
try_ss.channels = try_map.channels;
|
||||
|
||||
try_period_size =
|
||||
pa_usec_to_bytes(default_fragment_size_msec*PA_USEC_PER_MSEC, &try_ss) /
|
||||
pa_frame_size(&try_ss);
|
||||
try_buffer_size = default_n_fragments * try_period_size;
|
||||
|
||||
if (!(m ->input_pcm = pa_alsa_open_by_template(
|
||||
m->device_strings,
|
||||
dev_id,
|
||||
NULL,
|
||||
&try_ss, &try_map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
NULL, NULL, 0, NULL, NULL,
|
||||
&try_period_size, &try_buffer_size, 0, NULL, NULL,
|
||||
TRUE))) {
|
||||
p->supported = FALSE;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void pa_alsa_mapping_dump(pa_alsa_mapping *m);
|
|||
void pa_alsa_profile_dump(pa_alsa_profile *p);
|
||||
|
||||
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus);
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss);
|
||||
void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec);
|
||||
void pa_alsa_profile_set_free(pa_alsa_profile_set *s);
|
||||
void pa_alsa_profile_set_dump(pa_alsa_profile_set *s);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,9 +69,12 @@
|
|||
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- On underrun, increase watermark by this */
|
||||
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms -- When everything's great, decrease watermark by this */
|
||||
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s -- How long after a drop out recheck if things are good now */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms -- If the buffer level ever below this theshold, increase the watermark */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms -- If the buffer level ever below this theshold, increase the watermark */
|
||||
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms -- If the buffer level didn't drop below this theshold in the verification time, decrease the watermark */
|
||||
|
||||
/* Note that TSCHED_WATERMARK_INC_THRESHOLD_USEC == 0 means tht we
|
||||
* will increase the watermark only if we hit a real underrun. */
|
||||
|
||||
#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*/
|
||||
|
||||
|
|
@ -113,7 +116,6 @@ struct userdata {
|
|||
|
||||
pa_usec_t watermark_dec_not_before;
|
||||
|
||||
unsigned nfragments;
|
||||
pa_memchunk memchunk;
|
||||
|
||||
char *device_name; /* name of the PCM device */
|
||||
|
|
@ -410,6 +412,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
|
||||
static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
|
||||
size_t left_to_play;
|
||||
pa_bool_t underrun = FALSE;
|
||||
|
||||
/* We use <= instead of < for this check here because an underrun
|
||||
* only happens after the last sample was processed, not already when
|
||||
|
|
@ -422,6 +425,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
|
|||
|
||||
/* We got a dropout. What a mess! */
|
||||
left_to_play = 0;
|
||||
underrun = TRUE;
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
PA_DEBUG_TRAP;
|
||||
|
|
@ -443,7 +447,7 @@ static size_t check_left_to_play(struct userdata *u, size_t n_bytes, pa_bool_t o
|
|||
pa_bool_t reset_not_before = TRUE;
|
||||
|
||||
if (!u->first && !u->after_rewind) {
|
||||
if (left_to_play < u->watermark_inc_threshold)
|
||||
if (underrun || left_to_play < u->watermark_inc_threshold)
|
||||
increase_watermark(u);
|
||||
else if (left_to_play > u->watermark_dec_threshold) {
|
||||
reset_not_before = FALSE;
|
||||
|
|
@ -651,6 +655,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
|
|||
snd_pcm_sframes_t n;
|
||||
size_t n_bytes;
|
||||
int r;
|
||||
pa_bool_t after_avail = TRUE;
|
||||
|
||||
if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
|
||||
|
||||
|
|
@ -705,7 +710,6 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle
|
|||
for (;;) {
|
||||
snd_pcm_sframes_t frames;
|
||||
void *p;
|
||||
pa_bool_t after_avail = TRUE;
|
||||
|
||||
/* pa_log_debug("%lu frames to write", (unsigned long) frames); */
|
||||
|
||||
|
|
@ -938,8 +942,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_sample_spec ss;
|
||||
int err;
|
||||
pa_bool_t b, d;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_uframes_t period_size, buffer_size;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(!u->pcm_handle);
|
||||
|
|
@ -947,7 +950,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_log_info("Trying resume...");
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
|
||||
/*SND_PCM_NONBLOCK|*/
|
||||
SND_PCM_NONBLOCK|
|
||||
SND_PCM_NO_AUTO_RESAMPLE|
|
||||
SND_PCM_NO_AUTO_CHANNELS|
|
||||
SND_PCM_NO_AUTO_FORMAT)) < 0) {
|
||||
|
|
@ -956,12 +959,12 @@ static int unsuspend(struct userdata *u) {
|
|||
}
|
||||
|
||||
ss = u->sink->sample_spec;
|
||||
nfrags = u->nfragments;
|
||||
period_size = u->fragment_size / u->frame_size;
|
||||
buffer_size = u->hwbuf_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
d = u->use_tsched;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -976,10 +979,11 @@ static int unsuspend(struct userdata *u) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
|
||||
(unsigned long) u->nfragments, (unsigned long) u->fragment_size,
|
||||
(unsigned long) nfrags, period_size * u->frame_size);
|
||||
if (period_size*u->frame_size != u->fragment_size ||
|
||||
buffer_size*u->frame_size != u->hwbuf_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
|
||||
(unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
|
||||
(unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -1007,7 +1011,7 @@ fail:
|
|||
u->pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
/* Called from IO context */
|
||||
|
|
@ -1031,28 +1035,33 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
|||
|
||||
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
|
||||
|
||||
case PA_SINK_SUSPENDED:
|
||||
case PA_SINK_SUSPENDED: {
|
||||
int r;
|
||||
|
||||
pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
|
||||
|
||||
if (suspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SINK_IDLE:
|
||||
case PA_SINK_RUNNING:
|
||||
case PA_SINK_RUNNING: {
|
||||
int r;
|
||||
|
||||
if (u->sink->thread_info.state == PA_SINK_INIT) {
|
||||
if (build_pollfd(u) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
|
||||
if (unsuspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = unsuspend(u)) < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SINK_UNLINKED:
|
||||
case PA_SINK_INIT:
|
||||
|
|
@ -1080,7 +1089,7 @@ static int sink_set_state_cb(pa_sink *s, pa_sink_state_t new_state) {
|
|||
reserve_done(u);
|
||||
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
|
||||
if (reserve_init(u, u->device_name) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_BUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1633,8 +1642,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
const char *dev_id = NULL;
|
||||
pa_sample_spec ss, requested_ss;
|
||||
pa_channel_map map;
|
||||
uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, tsched_frames;
|
||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
|
||||
pa_sink_new_data data;
|
||||
|
|
@ -1668,8 +1677,10 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
goto fail;
|
||||
}
|
||||
|
||||
hwbuf_size = frag_size * nfrags;
|
||||
buffer_size = nfrags * frag_size;
|
||||
|
||||
period_frames = frag_size/frame_size;
|
||||
buffer_frames = buffer_size/frame_size;
|
||||
tsched_frames = tsched_size/frame_size;
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
|
||||
|
|
@ -1736,7 +1747,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, mapping)))
|
||||
|
||||
goto fail;
|
||||
|
|
@ -1751,7 +1762,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, profile_set, &mapping)))
|
||||
|
||||
goto fail;
|
||||
|
|
@ -1763,7 +1774,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_PLAYBACK,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, FALSE)))
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1789,11 +1800,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
|
||||
pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
|
||||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
|
|
@ -1815,7 +1821,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
|
||||
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
|
||||
|
||||
|
|
@ -1856,13 +1862,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
pa_sink_set_rtpoll(u->sink, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
|
||||
u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
|
||||
pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
|
||||
|
||||
pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
|
||||
nfrags, (long unsigned) u->fragment_size,
|
||||
pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
|
||||
(double) u->hwbuf_size / (double) u->fragment_size,
|
||||
(long unsigned) u->fragment_size,
|
||||
(double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
|
||||
(long unsigned) u->hwbuf_size,
|
||||
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
|
||||
|
||||
pa_sink_set_max_request(u->sink, u->hwbuf_size);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
#define TSCHED_WATERMARK_INC_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
||||
#define TSCHED_WATERMARK_DEC_STEP_USEC (5*PA_USEC_PER_MSEC) /* 5ms */
|
||||
#define TSCHED_WATERMARK_VERIFY_AFTER_USEC (20*PA_USEC_PER_SEC) /* 20s */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (1*PA_USEC_PER_MSEC) /* 3ms */
|
||||
#define TSCHED_WATERMARK_INC_THRESHOLD_USEC (0*PA_USEC_PER_MSEC) /* 0ms */
|
||||
#define TSCHED_WATERMARK_DEC_THRESHOLD_USEC (100*PA_USEC_PER_MSEC) /* 100ms */
|
||||
#define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */
|
||||
|
||||
|
|
@ -111,8 +111,6 @@ struct userdata {
|
|||
|
||||
pa_usec_t watermark_dec_not_before;
|
||||
|
||||
unsigned nfragments;
|
||||
|
||||
char *device_name;
|
||||
char *control_device;
|
||||
|
||||
|
|
@ -406,6 +404,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
|
|||
static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
|
||||
size_t left_to_record;
|
||||
size_t rec_space = u->hwbuf_size - u->hwbuf_unused;
|
||||
pa_bool_t overrun = FALSE;
|
||||
|
||||
/* We use <= instead of < for this check here because an overrun
|
||||
* only happens after the last sample was processed, not already when
|
||||
|
|
@ -418,6 +417,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
|
|||
|
||||
/* We got a dropout. What a mess! */
|
||||
left_to_record = 0;
|
||||
overrun = TRUE;
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
PA_DEBUG_TRAP;
|
||||
|
|
@ -434,7 +434,7 @@ static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t
|
|||
if (u->use_tsched) {
|
||||
pa_bool_t reset_not_before = TRUE;
|
||||
|
||||
if (left_to_record < u->watermark_inc_threshold)
|
||||
if (overrun || left_to_record < u->watermark_inc_threshold)
|
||||
increase_watermark(u);
|
||||
else if (left_to_record > u->watermark_dec_threshold) {
|
||||
reset_not_before = FALSE;
|
||||
|
|
@ -889,8 +889,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_sample_spec ss;
|
||||
int err;
|
||||
pa_bool_t b, d;
|
||||
unsigned nfrags;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_uframes_t period_size, buffer_size;
|
||||
|
||||
pa_assert(u);
|
||||
pa_assert(!u->pcm_handle);
|
||||
|
|
@ -898,7 +897,7 @@ static int unsuspend(struct userdata *u) {
|
|||
pa_log_info("Trying resume...");
|
||||
|
||||
if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
|
||||
/*SND_PCM_NONBLOCK|*/
|
||||
SND_PCM_NONBLOCK|
|
||||
SND_PCM_NO_AUTO_RESAMPLE|
|
||||
SND_PCM_NO_AUTO_CHANNELS|
|
||||
SND_PCM_NO_AUTO_FORMAT)) < 0) {
|
||||
|
|
@ -907,12 +906,12 @@ static int unsuspend(struct userdata *u) {
|
|||
}
|
||||
|
||||
ss = u->source->sample_spec;
|
||||
nfrags = u->nfragments;
|
||||
period_size = u->fragment_size / u->frame_size;
|
||||
buffer_size = u->hwbuf_size / u->frame_size;
|
||||
b = u->use_mmap;
|
||||
d = u->use_tsched;
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
|
||||
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -927,10 +926,11 @@ static int unsuspend(struct userdata *u) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
|
||||
(unsigned long) u->nfragments, (unsigned long) u->fragment_size,
|
||||
(unsigned long) nfrags, period_size * u->frame_size);
|
||||
if (period_size*u->frame_size != u->fragment_size ||
|
||||
buffer_size*u->frame_size != u->hwbuf_size) {
|
||||
pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",
|
||||
(unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size,
|
||||
(unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -959,7 +959,7 @@ fail:
|
|||
u->pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
}
|
||||
|
||||
static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
|
||||
|
|
@ -982,30 +982,34 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
|
|||
|
||||
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
|
||||
|
||||
case PA_SOURCE_SUSPENDED:
|
||||
case PA_SOURCE_SUSPENDED: {
|
||||
int r;
|
||||
pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
|
||||
|
||||
if (suspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = suspend(u)) < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SOURCE_IDLE:
|
||||
case PA_SOURCE_RUNNING:
|
||||
case PA_SOURCE_RUNNING: {
|
||||
int r;
|
||||
|
||||
if (u->source->thread_info.state == PA_SOURCE_INIT) {
|
||||
if (build_pollfd(u) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_IO;
|
||||
|
||||
snd_pcm_start(u->pcm_handle);
|
||||
}
|
||||
|
||||
if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
|
||||
if (unsuspend(u) < 0)
|
||||
return -1;
|
||||
if ((r = unsuspend(u)) < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PA_SOURCE_UNLINKED:
|
||||
case PA_SOURCE_INIT:
|
||||
|
|
@ -1033,7 +1037,7 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t new_state) {
|
|||
reserve_done(u);
|
||||
else if (old_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(new_state))
|
||||
if (reserve_init(u, u->device_name) < 0)
|
||||
return -1;
|
||||
return -PA_ERR_BUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1481,8 +1485,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
const char *dev_id = NULL;
|
||||
pa_sample_spec ss, requested_ss;
|
||||
pa_channel_map map;
|
||||
uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, tsched_frames;
|
||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
||||
size_t frame_size;
|
||||
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
|
||||
pa_source_new_data data;
|
||||
|
|
@ -1516,8 +1520,10 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
goto fail;
|
||||
}
|
||||
|
||||
hwbuf_size = frag_size * nfrags;
|
||||
buffer_size = nfrags * frag_size;
|
||||
|
||||
period_frames = frag_size/frame_size;
|
||||
buffer_frames = buffer_size/frame_size;
|
||||
tsched_frames = tsched_size/frame_size;
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
|
||||
|
|
@ -1583,7 +1589,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, mapping)))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -1597,7 +1603,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, profile_set, &mapping)))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -1608,7 +1614,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
&u->device_name,
|
||||
&ss, &map,
|
||||
SND_PCM_STREAM_CAPTURE,
|
||||
&nfrags, &period_frames, tsched_frames,
|
||||
&period_frames, &buffer_frames, tsched_frames,
|
||||
&b, &d, FALSE)))
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1634,11 +1640,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
|
||||
pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
|
||||
u->use_tsched = use_tsched = FALSE;
|
||||
}
|
||||
|
||||
if (u->use_mmap)
|
||||
pa_log_info("Successfully enabled mmap() mode.");
|
||||
|
||||
|
|
@ -1660,7 +1661,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
|
||||
pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (buffer_frames * frame_size));
|
||||
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
|
||||
|
||||
|
|
@ -1701,13 +1702,15 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
pa_source_set_rtpoll(u->source, u->rtpoll);
|
||||
|
||||
u->frame_size = frame_size;
|
||||
u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size);
|
||||
u->nfragments = nfrags;
|
||||
u->hwbuf_size = u->fragment_size * nfrags;
|
||||
u->fragment_size = frag_size = (size_t) (period_frames * frame_size);
|
||||
u->hwbuf_size = buffer_size = (size_t) (buffer_frames * frame_size);
|
||||
pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
|
||||
|
||||
pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
|
||||
nfrags, (long unsigned) u->fragment_size,
|
||||
pa_log_info("Using %0.1f fragments of size %lu bytes (%0.2fms), buffer size is %lu bytes (%0.2fms)",
|
||||
(double) u->hwbuf_size / (double) u->fragment_size,
|
||||
(long unsigned) u->fragment_size,
|
||||
(double) pa_bytes_to_usec(u->fragment_size, &ss) / PA_USEC_PER_MSEC,
|
||||
(long unsigned) u->hwbuf_size,
|
||||
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
|
||||
|
||||
if (u->use_tsched) {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s
|
|||
int ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
pa_assert(f);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
|
||||
|
|
@ -148,33 +149,71 @@ try_auto:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
|
||||
snd_pcm_uframes_t s;
|
||||
int d, ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
|
||||
s = size;
|
||||
d = 0;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
|
||||
s = size;
|
||||
d = -1;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
|
||||
s = size;
|
||||
d = 1;
|
||||
if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
|
||||
int ret;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(hwparams);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the hardware parameters of the given ALSA device. Returns the
|
||||
* selected fragment settings in *period and *period_size */
|
||||
* selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
|
||||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss,
|
||||
uint32_t *periods,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
pa_bool_t require_exact_channel_number) {
|
||||
|
||||
int ret = -1;
|
||||
snd_pcm_hw_params_t *hwparams, *hwparams_copy;
|
||||
int dir;
|
||||
snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
|
||||
unsigned int _periods = periods ? *periods : 0;
|
||||
unsigned int r = ss->rate;
|
||||
unsigned int c = ss->channels;
|
||||
pa_sample_format_t f = ss->format;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
|
||||
pa_bool_t _use_mmap = use_mmap && *use_mmap;
|
||||
pa_bool_t _use_tsched = use_tsched && *use_tsched;
|
||||
int dir;
|
||||
pa_sample_spec _ss = *ss;
|
||||
|
||||
pa_assert(pcm_handle);
|
||||
pa_assert(ss);
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_hw_params_alloca(&hwparams_copy);
|
||||
|
||||
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
|
||||
|
|
@ -208,114 +247,143 @@ int pa_alsa_set_hw_params(
|
|||
if (!_use_mmap)
|
||||
_use_tsched = FALSE;
|
||||
|
||||
if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
|
||||
if (!pa_alsa_pcm_is_hw(pcm_handle))
|
||||
_use_tsched = FALSE;
|
||||
|
||||
if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
|
||||
goto finish;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
|
||||
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (require_exact_channel_number) {
|
||||
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", c, pa_alsa_strerror(ret));
|
||||
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
} else {
|
||||
unsigned int c = _ss.channels;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", c, pa_alsa_strerror(ret));
|
||||
pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
_ss.channels = c;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
if (_use_tsched && tsched_size > 0) {
|
||||
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
|
||||
_period_size = _buffer_size;
|
||||
} else {
|
||||
_period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
|
||||
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
|
||||
}
|
||||
|
||||
if (_period_size > 0 && tsched_size > 0 && _periods > 0) {
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
unsigned int p;
|
||||
if (_buffer_size > 0 || _period_size > 0) {
|
||||
snd_pcm_uframes_t max_frames = 0;
|
||||
|
||||
/* Adjust the buffer sizes, if we didn't get the rate we were asking for */
|
||||
_period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
|
||||
tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
|
||||
|
||||
if (_use_tsched) {
|
||||
buffer_size = 0;
|
||||
|
||||
if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size)) < 0)
|
||||
pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
|
||||
else
|
||||
pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
|
||||
|
||||
_period_size = tsched_size;
|
||||
_periods = 1;
|
||||
}
|
||||
if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
|
||||
pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
|
||||
else
|
||||
pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
|
||||
|
||||
/* Some ALSA drivers really don't like if we set the buffer
|
||||
* size first and the number of periods second. (which would
|
||||
* make a lot more sense to me) So, follow this rule and
|
||||
* adjust the periods first and the buffer size second */
|
||||
* make a lot more sense to me) So, try a few combinations
|
||||
* before we give up. */
|
||||
|
||||
/* First we pass 0 as direction to get exactly what we
|
||||
* asked for. That this is necessary is presumably a bug
|
||||
* in ALSA. All in all this is mostly a hint to ALSA, so
|
||||
* we don't care if this fails. */
|
||||
if (_buffer_size > 0 && _period_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
p = _periods;
|
||||
dir = 0;
|
||||
if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
|
||||
p = _periods;
|
||||
dir = 1;
|
||||
if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
|
||||
p = _periods;
|
||||
dir = -1;
|
||||
if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir)) < 0)
|
||||
pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
|
||||
/* First try: set buffer size first, followed by period size */
|
||||
if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set buffer size first, period size second.");
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* Second try: set period size first, followed by buffer size */
|
||||
if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set period size first, buffer size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the buffer size */
|
||||
buffer_size = _periods * _period_size;
|
||||
if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
|
||||
pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
|
||||
if (_buffer_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
/* Third try: set only buffer size */
|
||||
if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set only buffer size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
if (_period_size > 0) {
|
||||
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
|
||||
|
||||
/* Fourth try: set only period size */
|
||||
if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
|
||||
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
|
||||
pa_log_debug("Set only period size second.");
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
|
||||
pa_log_debug("Set neither period nor buffer size.");
|
||||
|
||||
/* Last chance, set nothing */
|
||||
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (ss->rate != r)
|
||||
pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
|
||||
success:
|
||||
|
||||
if (ss->channels != c)
|
||||
pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
|
||||
if (ss->rate != _ss.rate)
|
||||
pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
|
||||
|
||||
if (ss->format != f)
|
||||
pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
|
||||
if (ss->channels != _ss.channels)
|
||||
pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
|
||||
|
||||
if (ss->format != _ss.format)
|
||||
pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(_ss.format));
|
||||
|
||||
if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
|
||||
pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
|
||||
(ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_get_period{s|_size}() failed: %s", pa_alsa_strerror(ret));
|
||||
(ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
|
||||
pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* If the sample rate deviates too much, we need to resample */
|
||||
if (r < ss->rate*.95 || r > ss->rate*1.05)
|
||||
ss->rate = r;
|
||||
ss->channels = (uint8_t) c;
|
||||
ss->format = f;
|
||||
if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
|
||||
ss->rate = _ss.rate;
|
||||
ss->channels = _ss.channels;
|
||||
ss->format = _ss.format;
|
||||
|
||||
pa_assert(_periods > 0);
|
||||
pa_assert(_period_size > 0);
|
||||
pa_assert(_buffer_size > 0);
|
||||
|
||||
if (periods)
|
||||
*periods = _periods;
|
||||
if (buffer_size)
|
||||
*buffer_size = _buffer_size;
|
||||
|
||||
if (period_size)
|
||||
*period_size = _period_size;
|
||||
|
|
@ -393,8 +461,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -410,8 +478,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
pa_assert(ps);
|
||||
|
||||
/* First we try to find a device string with a superset of the
|
||||
|
|
@ -433,8 +499,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -460,8 +526,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -478,7 +544,18 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
/* OK, we didn't find any good device, so let's try the raw hw: stuff */
|
||||
d = pa_sprintf_malloc("hw:%s", dev_id);
|
||||
pa_log_debug("Trying %s as last resort...", d);
|
||||
pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
|
||||
pcm_handle = pa_alsa_open_by_device_string(
|
||||
d,
|
||||
dev,
|
||||
ss,
|
||||
map,
|
||||
mode,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
FALSE);
|
||||
pa_xfree(d);
|
||||
|
||||
if (pcm_handle && mapping)
|
||||
|
|
@ -493,8 +570,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -508,8 +585,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_assert(dev);
|
||||
pa_assert(ss);
|
||||
pa_assert(map);
|
||||
pa_assert(nfrags);
|
||||
pa_assert(period_size);
|
||||
pa_assert(m);
|
||||
|
||||
try_ss.channels = m->channel_map.channels;
|
||||
|
|
@ -524,8 +599,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
&try_ss,
|
||||
&try_map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -547,8 +622,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -579,7 +654,15 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
|
||||
pa_log_debug("Managed to open %s", d);
|
||||
|
||||
if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
|
||||
if ((err = pa_alsa_set_hw_params(
|
||||
pcm_handle,
|
||||
ss,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
require_exact_channel_number)) < 0) {
|
||||
|
||||
if (!reformat) {
|
||||
reformat = TRUE;
|
||||
|
|
@ -632,8 +715,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
pa_sample_spec *ss,
|
||||
pa_channel_map* map,
|
||||
int mode,
|
||||
uint32_t *nfrags,
|
||||
snd_pcm_uframes_t *period_size,
|
||||
snd_pcm_uframes_t *buffer_size,
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap,
|
||||
pa_bool_t *use_tsched,
|
||||
|
|
@ -653,8 +736,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
ss,
|
||||
map,
|
||||
mode,
|
||||
nfrags,
|
||||
period_size,
|
||||
buffer_size,
|
||||
tsched_size,
|
||||
use_mmap,
|
||||
use_tsched,
|
||||
|
|
@ -900,7 +983,7 @@ void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
|
|||
snd_ctl_card_info_alloca(&info);
|
||||
|
||||
if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
|
||||
pa_log_warn("Error opening low-level control device '%s'", name);
|
||||
pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
int pa_alsa_set_hw_params(
|
||||
snd_pcm_t *pcm_handle,
|
||||
pa_sample_spec *ss, /* modified at return */
|
||||
uint32_t *periods, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -60,8 +60,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -75,8 +75,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -89,8 +89,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
@ -104,8 +104,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
|||
pa_sample_spec *ss, /* modified at return */
|
||||
pa_channel_map* map, /* modified at return */
|
||||
int mode,
|
||||
uint32_t *nfrags, /* modified at return */
|
||||
snd_pcm_uframes_t *period_size, /* modified at return */
|
||||
snd_pcm_uframes_t *buffer_size, /* modified at return */
|
||||
snd_pcm_uframes_t tsched_size,
|
||||
pa_bool_t *use_mmap, /* modified at return */
|
||||
pa_bool_t *use_tsched, /* modified at return */
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ priority = 19
|
|||
name = input-microphone
|
||||
priority = 19
|
||||
|
||||
[Option Input Source:Internal Mic]
|
||||
name = input-microphone
|
||||
priority = 19
|
||||
|
||||
[Option Input Source:Line]
|
||||
name = input-linein
|
||||
priority = 18
|
||||
|
|
@ -90,6 +94,10 @@ priority = 18
|
|||
name = input-linein
|
||||
priority = 18
|
||||
|
||||
[Option Input Source:Docking-Station]
|
||||
name = input-docking
|
||||
priority = 17
|
||||
|
||||
;;; ' Capture Source'
|
||||
|
||||
[Element Capture Source]
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ volume = off
|
|||
switch = off
|
||||
volume = off
|
||||
|
||||
[Element Sourround]
|
||||
[Element Surround]
|
||||
switch = off
|
||||
volume = off
|
||||
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ int pa__init(pa_module *m) {
|
|||
if (!u->profile_set)
|
||||
goto fail;
|
||||
|
||||
pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec);
|
||||
pa_alsa_profile_set_probe(u->profile_set, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
|
||||
|
||||
pa_card_new_data_init(&data);
|
||||
data.driver = __FILE__;
|
||||
|
|
|
|||
|
|
@ -221,9 +221,7 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
|
|||
pa_assert(u);
|
||||
pa_assert(u->service_fd >= 0);
|
||||
pa_assert(msg);
|
||||
|
||||
if (room <= 0)
|
||||
room = BT_SUGGESTED_BUFFER_SIZE;
|
||||
pa_assert(room >= sizeof(*msg));
|
||||
|
||||
pa_log_debug("Trying to receive message from audio service...");
|
||||
|
||||
|
|
@ -236,6 +234,11 @@ static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t r
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (msg->length > room) {
|
||||
pa_log_error("Not enough room.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Secondly, read the payload */
|
||||
if (msg->length > sizeof(*msg)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ int pa__init(pa_module*m) {
|
|||
|
||||
if ((u->fd = pa_start_child_for_read(
|
||||
#if defined(__linux__) && !defined(__OPTIMIZE__)
|
||||
pa_run_from_build_tree() ? PA_BUILDDIR "/.libs/gconf-helper" :
|
||||
pa_run_from_build_tree() ? PA_BUILDDIR "/gconf-helper" :
|
||||
#endif
|
||||
PA_GCONF_HELPER, NULL, &u->pid)) < 0)
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error)) < 0) {
|
||||
if (!(udis = libhal_find_device_by_capability(hal, "sound", &n, &error))) {
|
||||
pa_log_error("Couldn't find devices: %s: %s", error.name, error.message);
|
||||
goto finish;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#endif
|
||||
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/sink-input.h>
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
#include "module-always-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Colin Guthrie");
|
||||
PA_MODULE_DESCRIPTION("Always keeps at least one sink loaded even if it's a null one");
|
||||
PA_MODULE_DESCRIPTION(_("Always keeps at least one sink loaded even if it's a null one"));
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_LOAD_ONCE(TRUE);
|
||||
PA_MODULE_USAGE(
|
||||
|
|
@ -78,7 +79,8 @@ static void load_null_sink_if_needed(pa_core *c, pa_sink *sink, struct userdata*
|
|||
|
||||
u->ignore = TRUE;
|
||||
|
||||
t = pa_sprintf_malloc("sink_name=%s", u->sink_name);
|
||||
t = pa_sprintf_malloc("sink_name=%s sink_properties='device.description=\"%s\"'", u->sink_name,
|
||||
_("Dummy Output"));
|
||||
m = pa_module_load(c, "module-null-sink", t);
|
||||
u->null_module = m ? m->index : PA_INVALID_INDEX;
|
||||
pa_xfree(t);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pulsecore/module.h>
|
||||
#include <pulsecore/iochannel.h>
|
||||
|
|
@ -33,6 +35,8 @@
|
|||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
|
||||
#include "module-cli-symdef.h"
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ int pa__init(pa_module*m) {
|
|||
pa_iochannel *io;
|
||||
pa_modargs *ma;
|
||||
pa_bool_t exit_on_eof = FALSE;
|
||||
int fd;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
|
|
@ -88,15 +93,28 @@ int pa__init(pa_module*m) {
|
|||
}
|
||||
|
||||
if (pa_stdio_acquire() < 0) {
|
||||
pa_log("STDIN/STDUSE already in use.");
|
||||
pa_log("STDIN/STDOUT already in use.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
pa_iochannel_set_noclose(io, 1);
|
||||
/* We try to open the controlling tty anew here. This has the
|
||||
* benefit of giving us a new fd that doesn't share the O_NDELAY
|
||||
* flag with fds 0, 1, or 2. Since pa_iochannel_xxx needs O_NDELAY
|
||||
* on its fd using those fds directly could set O_NDELAY which
|
||||
* fprintf() doesn't really like, resulting in truncated output
|
||||
* of log messages, particularly because if stdout and stderr are
|
||||
* dup'ed they share the same O_NDELAY, too. */
|
||||
|
||||
if ((fd = open("/dev/tty", O_RDWR|O_CLOEXEC|O_NONBLOCK)) >= 0) {
|
||||
io = pa_iochannel_new(m->core->mainloop, fd, fd);
|
||||
pa_log_debug("Managed to open /dev/tty.");
|
||||
} else {
|
||||
io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO);
|
||||
pa_iochannel_set_noclose(io, TRUE);
|
||||
pa_log_debug("Failed to open /dev/tty, using stdin/stdout fds instead.");
|
||||
}
|
||||
|
||||
m->userdata = pa_cli_new(m->core, io, m);
|
||||
|
||||
pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
|
||||
|
||||
pa_modargs_free(ma);
|
||||
|
|
@ -114,7 +132,7 @@ fail:
|
|||
void pa__done(pa_module*m) {
|
||||
pa_assert(m);
|
||||
|
||||
if (m->core->running_as_daemon == 0) {
|
||||
if (m->userdata) {
|
||||
pa_cli_free(m->userdata);
|
||||
pa_stdio_release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -435,9 +435,7 @@ static int hal_device_add_all(struct userdata *u) {
|
|||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
struct device *d;
|
||||
|
||||
if ((d = hal_device_add(u, udis[i]))) {
|
||||
if (hal_device_add(u, udis[i])) {
|
||||
count++;
|
||||
pa_log_debug("Loaded device %s", udis[i]);
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ struct userdata {
|
|||
LADSPA_Data control_out;
|
||||
|
||||
pa_memblockq *memblockq;
|
||||
|
||||
pa_bool_t auto_desc;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -423,6 +425,19 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
|
|||
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
|
||||
} else
|
||||
pa_sink_set_asyncmsgq(u->sink, NULL);
|
||||
|
||||
if (u->auto_desc && dest) {
|
||||
const char *z;
|
||||
pa_proplist *pl;
|
||||
|
||||
pl = pa_proplist_new();
|
||||
z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s",
|
||||
pa_proplist_gets(u->sink->proplist, "device.ladspa.name"), z ? z : dest->name);
|
||||
|
||||
pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -451,7 +466,6 @@ int pa__init(pa_module*m) {
|
|||
pa_channel_map map;
|
||||
pa_modargs *ma;
|
||||
char *t;
|
||||
const char *z;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data sink_input_data;
|
||||
pa_sink_new_data sink_data;
|
||||
|
|
@ -765,8 +779,6 @@ int pa__init(pa_module*m) {
|
|||
sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
|
||||
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&sink_data, &map);
|
||||
z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
|
||||
pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
|
||||
|
|
@ -782,6 +794,13 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
|
||||
const char *z;
|
||||
|
||||
z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
|
||||
}
|
||||
|
||||
u->sink = pa_sink_new(m->core, &sink_data,
|
||||
PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
|
||||
(master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <pulse/rtclock.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/xmalloc.h>
|
||||
#include <pulse/i18n.h>
|
||||
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/sink.h>
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
#include "module-null-sink-symdef.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering");
|
||||
PA_MODULE_DESCRIPTION("Clocked NULL sink");
|
||||
PA_MODULE_DESCRIPTION(_("Clocked NULL sink"));
|
||||
PA_MODULE_VERSION(PACKAGE_VERSION);
|
||||
PA_MODULE_LOAD_ONCE(FALSE);
|
||||
PA_MODULE_USAGE(
|
||||
|
|
@ -287,7 +288,7 @@ int pa__init(pa_module*m) {
|
|||
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
|
||||
pa_sink_new_data_set_sample_spec(&data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&data, &map);
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Output"));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", _("Null Output")));
|
||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
|
||||
|
||||
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
|
||||
|
|
|
|||
|
|
@ -57,35 +57,69 @@ struct userdata {
|
|||
pa_hook_slot *sink_input_fixate_hook_slot;
|
||||
};
|
||||
|
||||
static int parse_pos(const char *pos, double *f) {
|
||||
|
||||
if (pa_atod(pos, f) < 0) {
|
||||
pa_log_warn("Failed to parse hpos/vpos property '%s'.", pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*f < 0.0 || *f > 1.0) {
|
||||
pa_log_debug("Property hpos/vpos out of range %0.2f", *f);
|
||||
|
||||
*f = PA_CLAMP(*f, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) {
|
||||
const char *hpos;
|
||||
const char *hpos, *vpos, *role;
|
||||
double f;
|
||||
char t[PA_CVOLUME_SNPRINT_MAX];
|
||||
pa_cvolume v;
|
||||
|
||||
pa_assert(data);
|
||||
|
||||
if (!(role = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ROLE)))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!pa_streq(role, "event"))
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS)))
|
||||
hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS);
|
||||
|
||||
if (!(vpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_VPOS)))
|
||||
vpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_VPOS);
|
||||
|
||||
if (!hpos && !vpos)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_atod(hpos, &f) < 0) {
|
||||
pa_log_warn("Failed to parse "PA_PROP_EVENT_MOUSE_HPOS" property '%s'.", hpos);
|
||||
return PA_HOOK_OK;
|
||||
pa_cvolume_reset(&v, data->sink->sample_spec.channels);
|
||||
|
||||
if (hpos) {
|
||||
if (parse_pos(hpos, &f) < 0)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_channel_map_can_balance(&data->sink->channel_map)) {
|
||||
pa_log_debug("Positioning event sound '%s' horizontally at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
pa_cvolume_set_balance(&v, &data->sink->channel_map, f*2.0-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (f < 0.0 || f > 1.0) {
|
||||
pa_log_warn("Property "PA_PROP_EVENT_MOUSE_HPOS" out of range %0.2f", f);
|
||||
return PA_HOOK_OK;
|
||||
if (vpos) {
|
||||
if (parse_pos(vpos, &f) < 0)
|
||||
return PA_HOOK_OK;
|
||||
|
||||
if (pa_channel_map_can_fade(&data->sink->channel_map)) {
|
||||
pa_log_debug("Positioning event sound '%s' vertically at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
pa_cvolume_set_fade(&v, &data->sink->channel_map, f*2.0-1.0);
|
||||
}
|
||||
}
|
||||
|
||||
pa_log_debug("Positioning event sound '%s' at %0.2f.", pa_strnull(pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID)), f);
|
||||
|
||||
pa_cvolume_reset(&v, data->sample_spec.channels);
|
||||
pa_cvolume_set_balance(&v, &data->channel_map, f*2.0-1.0);
|
||||
|
||||
pa_log_debug("Final volume factor %s.", pa_cvolume_snprint(t, sizeof(t), &v));
|
||||
|
||||
pa_sink_input_new_data_apply_volume_factor(data, &v);
|
||||
pa_sink_input_new_data_apply_volume_factor_sink(data, &v);
|
||||
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ struct userdata {
|
|||
|
||||
pa_sink *sink;
|
||||
pa_sink_input *sink_input;
|
||||
|
||||
pa_bool_t auto_desc;
|
||||
};
|
||||
|
||||
static const char* const valid_modargs[] = {
|
||||
|
|
@ -307,6 +309,18 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
|
|||
pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
|
||||
} else
|
||||
pa_sink_set_asyncmsgq(u->sink, NULL);
|
||||
|
||||
if (u->auto_desc && dest) {
|
||||
const char *k;
|
||||
pa_proplist *pl;
|
||||
|
||||
pl = pa_proplist_new();
|
||||
k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
|
||||
|
||||
pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
}
|
||||
|
||||
int pa__init(pa_module*m) {
|
||||
|
|
@ -314,7 +328,6 @@ int pa__init(pa_module*m) {
|
|||
pa_sample_spec ss;
|
||||
pa_channel_map sink_map, stream_map;
|
||||
pa_modargs *ma;
|
||||
const char *k;
|
||||
pa_sink *master;
|
||||
pa_sink_input_new_data sink_input_data;
|
||||
pa_sink_new_data sink_data;
|
||||
|
|
@ -370,8 +383,6 @@ int pa__init(pa_module*m) {
|
|||
sink_data.name = pa_sprintf_malloc("%s.remapped", master->name);
|
||||
pa_sink_new_data_set_sample_spec(&sink_data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
|
||||
k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
|
||||
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
|
||||
|
||||
|
|
@ -381,6 +392,13 @@ int pa__init(pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
|
||||
const char *k;
|
||||
|
||||
k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
|
||||
pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
|
||||
}
|
||||
|
||||
u->sink = pa_sink_new(m->core, &sink_data, master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY));
|
||||
pa_sink_new_data_done(&sink_data);
|
||||
|
||||
|
|
|
|||
|
|
@ -1476,7 +1476,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
|
|||
if (!so->source)
|
||||
continue;
|
||||
|
||||
/* It might happen that a stream and a sink are set up at the
|
||||
/* It might happen that a stream and a source are set up at the
|
||||
same time, in which case we want to make sure we don't
|
||||
interfere with that */
|
||||
if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ static void command_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
|
||||
static void command_stream_buffer_attr_changed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
uint32_t channel, maxlength, tlength, fragsize, prebuf, minreq;
|
||||
uint32_t channel, maxlength, tlength = 0, fragsize, prebuf, minreq;
|
||||
pa_usec_t usec;
|
||||
|
||||
pa_assert(pd);
|
||||
|
|
@ -1069,6 +1069,33 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
|
|||
}
|
||||
}
|
||||
|
||||
if (u->version >= 16) {
|
||||
uint32_t n_ports;
|
||||
const char *s;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &n_ports)) {
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < n_ports; j++) {
|
||||
uint32_t priority;
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0 || /* name */
|
||||
pa_tagstruct_gets(t, &s) < 0 || /* description */
|
||||
pa_tagstruct_getu32(t, &priority) < 0) {
|
||||
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pa_tagstruct_eof(t)) {
|
||||
pa_log("Packet too long");
|
||||
goto fail;
|
||||
|
|
@ -1097,7 +1124,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag
|
|||
uint32_t idx, owner_module, client, sink;
|
||||
pa_usec_t buffer_usec, sink_usec;
|
||||
const char *name, *driver, *resample_method;
|
||||
pa_bool_t mute;
|
||||
pa_bool_t mute = FALSE;
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
pa_cvolume volume;
|
||||
|
|
@ -1245,6 +1272,33 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
|
|||
}
|
||||
}
|
||||
|
||||
if (u->version >= 16) {
|
||||
uint32_t n_ports;
|
||||
const char *s;
|
||||
|
||||
if (pa_tagstruct_getu32(t, &n_ports)) {
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < n_ports; j++) {
|
||||
uint32_t priority;
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0 || /* name */
|
||||
pa_tagstruct_gets(t, &s) < 0 || /* description */
|
||||
pa_tagstruct_getu32(t, &priority) < 0) {
|
||||
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_tagstruct_gets(t, &s) < 0) { /* active port */
|
||||
pa_log("Parse failure");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pa_tagstruct_eof(t)) {
|
||||
pa_log("Packet too long");
|
||||
goto fail;
|
||||
|
|
@ -1345,12 +1399,11 @@ static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32
|
|||
/* Called from main context */
|
||||
static void start_subscribe(struct userdata *u) {
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
pa_assert(u);
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SERVER|
|
||||
#ifdef TUNNEL_SINK
|
||||
PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SINK
|
||||
|
|
@ -1526,7 +1579,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
|
|||
|
||||
reply = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
|
||||
pa_tagstruct_putu32(reply, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(reply, u->ctag++);
|
||||
|
||||
if (u->version >= 13) {
|
||||
pa_proplist *pl;
|
||||
|
|
@ -1753,7 +1806,6 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
|
|||
static void sink_set_volume(pa_sink *sink) {
|
||||
struct userdata *u;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(sink);
|
||||
u = sink->userdata;
|
||||
|
|
@ -1761,7 +1813,7 @@ static void sink_set_volume(pa_sink *sink) {
|
|||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->device_index);
|
||||
pa_tagstruct_put_cvolume(t, &sink->real_volume);
|
||||
pa_pstream_send_tagstruct(u->pstream, t);
|
||||
|
|
@ -1771,7 +1823,6 @@ static void sink_set_volume(pa_sink *sink) {
|
|||
static void sink_set_mute(pa_sink *sink) {
|
||||
struct userdata *u;
|
||||
pa_tagstruct *t;
|
||||
uint32_t tag;
|
||||
|
||||
pa_assert(sink);
|
||||
u = sink->userdata;
|
||||
|
|
@ -1782,7 +1833,7 @@ static void sink_set_mute(pa_sink *sink) {
|
|||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_MUTE);
|
||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->ctag++);
|
||||
pa_tagstruct_putu32(t, u->device_index);
|
||||
pa_tagstruct_put_boolean(t, !!sink->muted);
|
||||
pa_pstream_send_tagstruct(u->pstream, t);
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@
|
|||
#include <sys/inotify.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <pulse/timeval.h>
|
||||
|
||||
#include <pulsecore/modargs.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/namereg.h>
|
||||
#include <pulsecore/ratelimit.h>
|
||||
|
||||
#include "module-udev-detect-symdef.h"
|
||||
|
||||
|
|
@ -50,6 +53,7 @@ struct device {
|
|||
char *card_name;
|
||||
char *args;
|
||||
uint32_t module;
|
||||
pa_ratelimit ratelimit;
|
||||
};
|
||||
|
||||
struct userdata {
|
||||
|
|
@ -110,6 +114,9 @@ static pa_bool_t is_card_busy(const char *id) {
|
|||
|
||||
pa_assert(id);
|
||||
|
||||
/* This simply uses /proc/asound/card.../pcm.../sub.../status to
|
||||
* check whether there is still a process using this audio device. */
|
||||
|
||||
card_path = pa_sprintf_malloc("/proc/asound/card%s", id);
|
||||
|
||||
if (!(card_dir = opendir(card_path))) {
|
||||
|
|
@ -234,14 +241,41 @@ static void verify_access(struct userdata *u, struct device *d) {
|
|||
pa_log_debug("%s is busy: %s", d->path, pa_yes_no(busy));
|
||||
|
||||
if (!busy) {
|
||||
pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
|
||||
m = pa_module_load(u->core, "module-alsa-card", d->args);
|
||||
|
||||
if (m) {
|
||||
d->module = m->index;
|
||||
pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
|
||||
/* So, why do we rate limit here? It's certainly ugly,
|
||||
* but there seems to be no other way. Problem is
|
||||
* this: if we are unable to configure/probe an audio
|
||||
* device after opening it we will close it again and
|
||||
* the module initialization will fail. This will then
|
||||
* cause an inotify event on the device node which
|
||||
* will be forwarded to us. We then try to reopen the
|
||||
* audio device again, practically entering a busy
|
||||
* loop.
|
||||
*
|
||||
* A clean fix would be if we would be able to ignore
|
||||
* our own inotify close events. However, inotify
|
||||
* lacks such functionality. Also, during probing of
|
||||
* the device we cannot really distuingish between
|
||||
* other processes causing EBUSY or ourselves, which
|
||||
* means we have no way to figure out if the probing
|
||||
* during opening was canceled by a "try again"
|
||||
* failure or a "fatal" failure. */
|
||||
|
||||
if (pa_ratelimit_test(&d->ratelimit)) {
|
||||
pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
|
||||
m = pa_module_load(u->core, "module-alsa-card", d->args);
|
||||
|
||||
if (m) {
|
||||
d->module = m->index;
|
||||
pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
|
||||
} else
|
||||
pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
|
||||
} else
|
||||
pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
|
||||
pa_log_warn("Tried to configure %s (%s) more often than %u times in %llus",
|
||||
d->path,
|
||||
d->card_name,
|
||||
d->ratelimit.burst,
|
||||
(long long unsigned) (d->ratelimit.interval / PA_USEC_PER_SEC));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +311,7 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
|
|||
d = pa_xnew0(struct device, 1);
|
||||
d->path = pa_xstrdup(path);
|
||||
d->module = PA_INVALID_INDEX;
|
||||
PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5);
|
||||
|
||||
if (!(t = udev_device_get_property_value(dev, "PULSE_NAME")))
|
||||
if (!(t = udev_device_get_property_value(dev, "ID_ID")))
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ int pa_base64_encode(const void *data, int size, char **str)
|
|||
|
||||
p = s = pa_xnew(char, size * 4 / 3 + 4);
|
||||
q = (const unsigned char *) data;
|
||||
i = 0;
|
||||
for (i = 0; i < size;) {
|
||||
c = q[i++];
|
||||
c *= 256;
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static void browser_cb(
|
|||
struct tunnel *t2;
|
||||
|
||||
if ((t2 = pa_hashmap_get(u->tunnels, t))) {
|
||||
pa_module_unload_by_index(u->core, t2->module_index, TRUE);
|
||||
pa_module_unload_request_by_index(u->core, t2->module_index, TRUE);
|
||||
pa_hashmap_remove(u->tunnels, t2);
|
||||
tunnel_free(t2);
|
||||
}
|
||||
|
|
@ -386,7 +386,7 @@ void pa__done(pa_module*m) {
|
|||
struct tunnel *t;
|
||||
|
||||
while ((t = pa_hashmap_steal_first(u->tunnels))) {
|
||||
pa_module_unload_by_index(u->core, t->module_index, TRUE);
|
||||
pa_module_unload_request_by_index(u->core, t->module_index, TRUE);
|
||||
tunnel_free(t);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (!(r->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
|
||||
pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
|
||||
/* We don't treat this as error here because we want allow PA
|
||||
* to run even when no session bus is available. */
|
||||
|
|
@ -154,10 +154,10 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
|
|||
NULL)) < 0) {
|
||||
|
||||
if (k == -EBUSY) {
|
||||
pa_log_error("Device '%s' already locked.", device_name);
|
||||
pa_log_debug("Device '%s' already locked.", device_name);
|
||||
goto fail;
|
||||
} else {
|
||||
pa_log_warn("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
pa_log_debug("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
@ -280,7 +280,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
|
|||
|
||||
#ifdef HAVE_DBUS
|
||||
if (!(w->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
|
||||
pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
|
||||
|
||||
/* We don't treat this as error here because we want allow PA
|
||||
* to run even when no session bus is available. */
|
||||
|
|
@ -294,7 +294,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha
|
|||
change_cb,
|
||||
NULL)) < 0) {
|
||||
|
||||
pa_log_warn("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
pa_log_debug("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ struct pa_rtsp_client {
|
|||
uint16_t port;
|
||||
|
||||
pa_socket_client *sc;
|
||||
pa_iochannel *io;
|
||||
pa_ioline *ioline;
|
||||
|
||||
pa_rtsp_cb_t callback;
|
||||
|
|
@ -111,10 +110,8 @@ void pa_rtsp_client_free(pa_rtsp_client* c) {
|
|||
|
||||
if (c->sc)
|
||||
pa_socket_client_unref(c->sc);
|
||||
if (c->ioline)
|
||||
pa_ioline_close(c->ioline);
|
||||
else if (c->io)
|
||||
pa_iochannel_free(c->io);
|
||||
|
||||
pa_rtsp_disconnect(c);
|
||||
|
||||
pa_xfree(c->hostname);
|
||||
pa_xfree(c->url);
|
||||
|
|
@ -187,7 +184,6 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
|
|||
if (!s) {
|
||||
/* Keep the ioline/iochannel open as they will be freed automatically */
|
||||
c->ioline = NULL;
|
||||
c->io = NULL;
|
||||
c->callback(c, STATE_DISCONNECTED, NULL, c->userdata);
|
||||
return;
|
||||
}
|
||||
|
|
@ -303,8 +299,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
|
|||
pa_log("Connection failed: %s", pa_cstrerror(errno));
|
||||
return;
|
||||
}
|
||||
pa_assert(!c->io);
|
||||
c->io = io;
|
||||
pa_assert(!c->ioline);
|
||||
|
||||
c->ioline = pa_ioline_new(io);
|
||||
pa_ioline_set_callback(c->ioline, line_callback, c);
|
||||
|
|
@ -360,9 +355,6 @@ void pa_rtsp_disconnect(pa_rtsp_client *c) {
|
|||
|
||||
if (c->ioline)
|
||||
pa_ioline_close(c->ioline);
|
||||
else if (c->io)
|
||||
pa_iochannel_free(c->io);
|
||||
c->io = NULL;
|
||||
c->ioline = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -408,13 +400,11 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
|
|||
pa_headerlist* headers) {
|
||||
pa_strbuf* buf;
|
||||
char* hdrs;
|
||||
ssize_t l;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(c->url);
|
||||
|
||||
if (!cmd)
|
||||
return -1;
|
||||
pa_assert(cmd);
|
||||
pa_assert(c->ioline);
|
||||
|
||||
pa_log_debug("Sending command: %s", cmd);
|
||||
|
||||
|
|
@ -453,7 +443,7 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
|
|||
hdrs = pa_strbuf_tostring_free(buf);
|
||||
/*pa_log_debug("Submitting request:");
|
||||
pa_log_debug(hdrs);*/
|
||||
l = pa_iochannel_write(c->io, hdrs, strlen(hdrs));
|
||||
pa_ioline_puts(c->ioline, hdrs);
|
||||
pa_xfree(hdrs);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ static void publish_servers(struct userdata *u, pa_strlist *l) {
|
|||
|
||||
l = pa_strlist_reverse(l);
|
||||
s = pa_strlist_tostring(l);
|
||||
l = pa_strlist_reverse(l);
|
||||
pa_strlist_reverse(l);
|
||||
|
||||
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s);
|
||||
pa_xfree(s);
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,10 @@ pa_context_state_t pa_context_get_state(pa_context *c) {
|
|||
}
|
||||
|
||||
int pa_context_errno(pa_context *c) {
|
||||
pa_assert(c);
|
||||
|
||||
if (!c)
|
||||
return PA_ERR_INVALID;
|
||||
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
return c->error;
|
||||
|
|
|
|||
|
|
@ -147,12 +147,6 @@
|
|||
* server. A pa_context object wraps a connection to a PulseAudio
|
||||
* server using its native protocol. */
|
||||
|
||||
/** \example pacat.c
|
||||
* A playback and recording tool using the asynchronous API */
|
||||
|
||||
/** \example paplay.c
|
||||
* A sound file playback tool using the asynchronous API, based on libsndfile */
|
||||
|
||||
PA_C_DECL_BEGIN
|
||||
|
||||
/** An opaque connection context to a daemon */
|
||||
|
|
@ -267,7 +261,6 @@ pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_even
|
|||
for mainloop->time_restart). \since 0.9.16 */
|
||||
void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec);
|
||||
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -95,13 +95,14 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
|
|||
typedef enum pa_operation_state {
|
||||
PA_OPERATION_RUNNING, /**< The operation is still running */
|
||||
PA_OPERATION_DONE, /**< The operation has been completed */
|
||||
PA_OPERATION_CANCELED /**< The operation has been canceled */
|
||||
PA_OPERATION_CANCELLED /**< The operation has been cancelled. Before 0.9.18 this was called PA_OPERATION_CANCELED. That name is still available for compatibility. */
|
||||
} pa_operation_state_t;
|
||||
|
||||
/** \cond fulldocs */
|
||||
#define PA_OPERATION_RUNNING PA_OPERATION_RUNNING
|
||||
#define PA_OPERATION_DONE PA_OPERATION_DONE
|
||||
#define PA_OPERATION_CANCELED PA_OPERATION_CANCELED
|
||||
#define PA_OPERATION_CANCELED PA_OPERATION_CANCELLED
|
||||
#define PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
|
||||
/** \endcond */
|
||||
|
||||
/** An invalid index */
|
||||
|
|
@ -109,6 +110,8 @@ typedef enum pa_operation_state {
|
|||
|
||||
/** Some special flags for contexts. */
|
||||
typedef enum pa_context_flags {
|
||||
PA_CONTEXT_NOFLAGS = 0x0000U,
|
||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||
PA_CONTEXT_NOAUTOSPAWN = 0x0001U,
|
||||
/**< Disabled autospawning of the PulseAudio daemon if required */
|
||||
PA_CONTEXT_NOFAIL = 0x0002U
|
||||
|
|
@ -139,6 +142,9 @@ typedef enum pa_stream_direction {
|
|||
/** Some special flags for stream connections. */
|
||||
typedef enum pa_stream_flags {
|
||||
|
||||
PA_STREAM_NOFLAGS = 0x0000U,
|
||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||
|
||||
PA_STREAM_START_CORKED = 0x0001U,
|
||||
/**< Create the stream corked, requiring an explicit
|
||||
* pa_stream_cork() call to uncork it. */
|
||||
|
|
@ -394,6 +400,7 @@ enum {
|
|||
PA_ERR_NOTIMPLEMENTED, /**< Missing implementation. \since 0.9.15 */
|
||||
PA_ERR_FORKED, /**< The caller forked without calling execve() and tried to reuse the context. \since 0.9.15 */
|
||||
PA_ERR_IO, /**< An IO error happened. \since 0.9.16 */
|
||||
PA_ERR_BUSY, /**< Device or resource busy. \since 0.9.17 */
|
||||
PA_ERR_MAX /**< Not really an error but the first invalid error code */
|
||||
};
|
||||
|
||||
|
|
@ -686,6 +693,9 @@ typedef enum pa_seek_mode {
|
|||
|
||||
/** Special sink flags. */
|
||||
typedef enum pa_sink_flags {
|
||||
PA_SINK_NOFLAGS = 0x0000U,
|
||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||
|
||||
PA_SINK_HW_VOLUME_CTRL = 0x0001U,
|
||||
/**< Supports hardware volume control */
|
||||
|
||||
|
|
@ -773,6 +783,9 @@ static inline int PA_SINK_IS_OPENED(pa_sink_state_t x) {
|
|||
|
||||
/** Special source flags. */
|
||||
typedef enum pa_source_flags {
|
||||
PA_SOURCE_NOFLAGS = 0x0000U,
|
||||
/**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */
|
||||
|
||||
PA_SOURCE_HW_VOLUME_CTRL = 0x0001U,
|
||||
/**< Supports hardware volume control */
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,9 @@ const char*pa_strerror(int error) {
|
|||
[PA_ERR_NOEXTENSION] = N_("No such extension"),
|
||||
[PA_ERR_OBSOLETE] = N_("Obsolete functionality"),
|
||||
[PA_ERR_NOTIMPLEMENTED] = N_("Missing implementation"),
|
||||
[PA_ERR_FORKED] = N_("Client forked")
|
||||
[PA_ERR_FORKED] = N_("Client forked"),
|
||||
[PA_ERR_IO] = N_("Input/Output error"),
|
||||
[PA_ERR_BUSY] = N_("Device or resource busy")
|
||||
};
|
||||
|
||||
pa_init_i18n();
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef PA_GCC_WEAKREF
|
||||
#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
|
||||
#if defined(__GNUC__) && defined(__ELF__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) || (__GNUC__ > 4))
|
||||
/** Macro for usgae of GCC's weakref attribute */
|
||||
#define PA_GCC_WEAKREF(x) __attribute__((weakref(#x)));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -834,6 +834,8 @@ pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char*name, p
|
|||
}
|
||||
|
||||
pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata) {
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
return pa_context_send_simple_command(c, PA_COMMAND_GET_CARD_INFO_LIST, context_get_card_info_callback, (pa_operation_cb_t) cb, userdata);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -331,6 +331,12 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i
|
|||
/** Set the mute switch of a source device specified by its name */
|
||||
pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
/** Suspend/Resume a source. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Change the profile of a source. \since 0.9.16 */
|
||||
pa_operation* pa_context_set_source_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
|
|
@ -557,12 +563,6 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx,
|
|||
/** Move the specified source output to a different source. \since 0.9.5 */
|
||||
pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a source. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
|
||||
pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
|
||||
|
||||
/** Kill a source output. */
|
||||
pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ struct pa_time_event {
|
|||
pa_bool_t dead:1;
|
||||
|
||||
pa_bool_t enabled:1;
|
||||
pa_bool_t use_rtclock:1;
|
||||
pa_usec_t time;
|
||||
|
||||
pa_time_event_cb_t callback;
|
||||
|
|
@ -112,7 +113,7 @@ struct pa_mainloop {
|
|||
struct pollfd *pollfds;
|
||||
unsigned max_pollfds, n_pollfds;
|
||||
|
||||
int prepared_timeout;
|
||||
pa_usec_t prepared_timeout;
|
||||
pa_time_event *cached_next_time_event;
|
||||
|
||||
pa_mainloop_api api;
|
||||
|
|
@ -172,17 +173,14 @@ static pa_io_event* mainloop_io_new(
|
|||
m = a->userdata;
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_io_event, 1);
|
||||
e = pa_xnew0(pa_io_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = FALSE;
|
||||
|
||||
e->fd = fd;
|
||||
e->events = events;
|
||||
e->pollfd = NULL;
|
||||
|
||||
e->callback = callback;
|
||||
e->userdata = userdata;
|
||||
e->destroy_callback = NULL;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
{
|
||||
|
|
@ -265,16 +263,14 @@ static pa_defer_event* mainloop_defer_new(
|
|||
m = a->userdata;
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_defer_event, 1);
|
||||
e = pa_xnew0(pa_defer_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = FALSE;
|
||||
|
||||
e->enabled = TRUE;
|
||||
m->n_enabled_defer_events++;
|
||||
|
||||
e->callback = callback;
|
||||
e->userdata = userdata;
|
||||
e->destroy_callback = NULL;
|
||||
|
||||
PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e);
|
||||
|
||||
|
|
@ -320,18 +316,20 @@ static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy
|
|||
}
|
||||
|
||||
/* Time events */
|
||||
static pa_usec_t timeval_load(const struct timeval *tv) {
|
||||
pa_bool_t is_rtclock;
|
||||
static pa_usec_t make_rt(const struct timeval *tv, pa_bool_t *use_rtclock) {
|
||||
struct timeval ttv;
|
||||
|
||||
if (!tv)
|
||||
if (!tv) {
|
||||
*use_rtclock = FALSE;
|
||||
return PA_USEC_INVALID;
|
||||
}
|
||||
|
||||
ttv = *tv;
|
||||
is_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
|
||||
ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
|
||||
*use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK);
|
||||
|
||||
if (!is_rtclock)
|
||||
if (*use_rtclock)
|
||||
ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
|
||||
else
|
||||
pa_rtclock_from_wallclock(&ttv);
|
||||
|
||||
return pa_timeval_load(&ttv);
|
||||
|
|
@ -346,22 +344,23 @@ static pa_time_event* mainloop_time_new(
|
|||
pa_mainloop *m;
|
||||
pa_time_event *e;
|
||||
pa_usec_t t;
|
||||
pa_bool_t use_rtclock = FALSE;
|
||||
|
||||
pa_assert(a);
|
||||
pa_assert(a->userdata);
|
||||
pa_assert(callback);
|
||||
|
||||
t = timeval_load(tv);
|
||||
t = make_rt(tv, &use_rtclock);
|
||||
|
||||
m = a->userdata;
|
||||
pa_assert(a == &m->api);
|
||||
|
||||
e = pa_xnew(pa_time_event, 1);
|
||||
e = pa_xnew0(pa_time_event, 1);
|
||||
e->mainloop = m;
|
||||
e->dead = FALSE;
|
||||
|
||||
if ((e->enabled = (t != PA_USEC_INVALID))) {
|
||||
e->time = t;
|
||||
e->use_rtclock= use_rtclock;
|
||||
|
||||
m->n_enabled_time_events++;
|
||||
|
||||
|
|
@ -375,7 +374,6 @@ static pa_time_event* mainloop_time_new(
|
|||
|
||||
e->callback = callback;
|
||||
e->userdata = userdata;
|
||||
e->destroy_callback = NULL;
|
||||
|
||||
PA_LLIST_PREPEND(pa_time_event, m->time_events, e);
|
||||
|
||||
|
|
@ -388,11 +386,12 @@ static pa_time_event* mainloop_time_new(
|
|||
static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
|
||||
pa_bool_t valid;
|
||||
pa_usec_t t;
|
||||
pa_bool_t use_rtclock = FALSE;
|
||||
|
||||
pa_assert(e);
|
||||
pa_assert(!e->dead);
|
||||
|
||||
t = timeval_load(tv);
|
||||
t = make_rt(tv, &use_rtclock);
|
||||
|
||||
valid = (t != PA_USEC_INVALID);
|
||||
if (e->enabled && !valid) {
|
||||
|
|
@ -403,6 +402,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) {
|
|||
|
||||
if ((e->enabled = valid)) {
|
||||
e->time = t;
|
||||
e->use_rtclock = use_rtclock;
|
||||
pa_mainloop_wakeup(e->mainloop);
|
||||
}
|
||||
|
||||
|
|
@ -480,9 +480,8 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
|
||||
pa_init_i18n();
|
||||
|
||||
m = pa_xnew(pa_mainloop, 1);
|
||||
m = pa_xnew0(pa_mainloop, 1);
|
||||
|
||||
m->wakeup_pipe_type = 0;
|
||||
if (pipe(m->wakeup_pipe) < 0) {
|
||||
pa_log_error("ERROR: cannot create wakeup pipe");
|
||||
pa_xfree(m);
|
||||
|
|
@ -493,43 +492,23 @@ pa_mainloop *pa_mainloop_new(void) {
|
|||
pa_make_fd_nonblock(m->wakeup_pipe[1]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[0]);
|
||||
pa_make_fd_cloexec(m->wakeup_pipe[1]);
|
||||
m->wakeup_requested = FALSE;
|
||||
|
||||
PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
|
||||
PA_LLIST_HEAD_INIT(pa_time_event, m->time_events);
|
||||
PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events);
|
||||
|
||||
m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0;
|
||||
m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0;
|
||||
|
||||
m->cached_next_time_event = NULL;
|
||||
m->prepared_timeout = 0;
|
||||
|
||||
m->pollfds = NULL;
|
||||
m->max_pollfds = m->n_pollfds = 0;
|
||||
m->rebuild_pollfds = TRUE;
|
||||
|
||||
m->quit = FALSE;
|
||||
m->retval = 0;
|
||||
|
||||
m->api = vtable;
|
||||
m->api.userdata = m;
|
||||
|
||||
m->state = STATE_PASSIVE;
|
||||
|
||||
m->poll_func = NULL;
|
||||
m->poll_func_userdata = NULL;
|
||||
m->poll_func_ret = -1;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_io_event *e;
|
||||
pa_io_event *e, *n;
|
||||
|
||||
e = m->io_events;
|
||||
while (e) {
|
||||
pa_io_event *n = e->next;
|
||||
PA_LLIST_FOREACH_SAFE(e, n, m->io_events) {
|
||||
|
||||
if (!force && m->io_events_please_scan <= 0)
|
||||
break;
|
||||
|
|
@ -549,19 +528,15 @@ static void cleanup_io_events(pa_mainloop *m, pa_bool_t force) {
|
|||
|
||||
m->rebuild_pollfds = TRUE;
|
||||
}
|
||||
|
||||
e = n;
|
||||
}
|
||||
|
||||
pa_assert(m->io_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_time_event *e;
|
||||
pa_time_event *e, *n;
|
||||
|
||||
e = m->time_events;
|
||||
while (e) {
|
||||
pa_time_event *n = e->next;
|
||||
PA_LLIST_FOREACH_SAFE(e, n, m->time_events) {
|
||||
|
||||
if (!force && m->time_events_please_scan <= 0)
|
||||
break;
|
||||
|
|
@ -585,19 +560,15 @@ static void cleanup_time_events(pa_mainloop *m, pa_bool_t force) {
|
|||
|
||||
pa_xfree(e);
|
||||
}
|
||||
|
||||
e = n;
|
||||
}
|
||||
|
||||
pa_assert(m->time_events_please_scan == 0);
|
||||
}
|
||||
|
||||
static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
|
||||
pa_defer_event *e;
|
||||
pa_defer_event *e, *n;
|
||||
|
||||
e = m->defer_events;
|
||||
while (e) {
|
||||
pa_defer_event *n = e->next;
|
||||
PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) {
|
||||
|
||||
if (!force && m->defer_events_please_scan <= 0)
|
||||
break;
|
||||
|
|
@ -621,8 +592,6 @@ static void cleanup_defer_events(pa_mainloop *m, pa_bool_t force) {
|
|||
|
||||
pa_xfree(e);
|
||||
}
|
||||
|
||||
e = n;
|
||||
}
|
||||
|
||||
pa_assert(m->defer_events_please_scan == 0);
|
||||
|
|
@ -679,7 +648,7 @@ static void rebuild_pollfds(pa_mainloop *m) {
|
|||
m->n_pollfds++;
|
||||
}
|
||||
|
||||
for (e = m->io_events; e; e = e->next) {
|
||||
PA_LLIST_FOREACH(e, m->io_events) {
|
||||
if (e->dead) {
|
||||
e->pollfd = NULL;
|
||||
continue;
|
||||
|
|
@ -697,36 +666,46 @@ static void rebuild_pollfds(pa_mainloop *m) {
|
|||
m->rebuild_pollfds = FALSE;
|
||||
}
|
||||
|
||||
static int dispatch_pollfds(pa_mainloop *m) {
|
||||
static unsigned dispatch_pollfds(pa_mainloop *m) {
|
||||
pa_io_event *e;
|
||||
int r = 0, k;
|
||||
unsigned r = 0, k;
|
||||
|
||||
pa_assert(m->poll_func_ret > 0);
|
||||
|
||||
for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
|
||||
k = m->poll_func_ret;
|
||||
|
||||
PA_LLIST_FOREACH(e, m->io_events) {
|
||||
|
||||
if (k <= 0 || m->quit)
|
||||
break;
|
||||
|
||||
if (e->dead || !e->pollfd || !e->pollfd->revents)
|
||||
continue;
|
||||
|
||||
pa_assert(e->pollfd->fd == e->fd);
|
||||
pa_assert(e->callback);
|
||||
|
||||
e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
|
||||
e->pollfd->revents = 0;
|
||||
r++;
|
||||
|
||||
k--;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int dispatch_defer(pa_mainloop *m) {
|
||||
static unsigned dispatch_defer(pa_mainloop *m) {
|
||||
pa_defer_event *e;
|
||||
int r = 0;
|
||||
unsigned r = 0;
|
||||
|
||||
if (m->n_enabled_defer_events <= 0)
|
||||
return 0;
|
||||
|
||||
for (e = m->defer_events; e && !m->quit; e = e->next) {
|
||||
PA_LLIST_FOREACH(e, m->defer_events) {
|
||||
|
||||
if (m->quit)
|
||||
break;
|
||||
|
||||
if (e->dead || !e->enabled)
|
||||
continue;
|
||||
|
||||
|
|
@ -745,7 +724,7 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
|
|||
if (m->cached_next_time_event)
|
||||
return m->cached_next_time_event;
|
||||
|
||||
for (t = m->time_events; t; t = t->next) {
|
||||
PA_LLIST_FOREACH(t, m->time_events) {
|
||||
|
||||
if (t->dead || !t->enabled)
|
||||
continue;
|
||||
|
|
@ -763,12 +742,12 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) {
|
|||
return n;
|
||||
}
|
||||
|
||||
static int calc_next_timeout(pa_mainloop *m) {
|
||||
static pa_usec_t calc_next_timeout(pa_mainloop *m) {
|
||||
pa_time_event *t;
|
||||
pa_usec_t clock_now;
|
||||
|
||||
if (!m->n_enabled_time_events)
|
||||
return -1;
|
||||
if (m->n_enabled_time_events <= 0)
|
||||
return PA_USEC_INVALID;
|
||||
|
||||
pa_assert_se(t = find_next_time_event(m));
|
||||
|
||||
|
|
@ -780,13 +759,13 @@ static int calc_next_timeout(pa_mainloop *m) {
|
|||
if (t->time <= clock_now)
|
||||
return 0;
|
||||
|
||||
return (int) ((t->time - clock_now) / 1000); /* in milliseconds */
|
||||
return t->time - clock_now;
|
||||
}
|
||||
|
||||
static int dispatch_timeout(pa_mainloop *m) {
|
||||
static unsigned dispatch_timeout(pa_mainloop *m) {
|
||||
pa_time_event *e;
|
||||
pa_usec_t now;
|
||||
int r = 0;
|
||||
unsigned r = 0;
|
||||
pa_assert(m);
|
||||
|
||||
if (m->n_enabled_time_events <= 0)
|
||||
|
|
@ -794,7 +773,10 @@ static int dispatch_timeout(pa_mainloop *m) {
|
|||
|
||||
now = pa_rtclock_now();
|
||||
|
||||
for (e = m->time_events; e && !m->quit; e = e->next) {
|
||||
PA_LLIST_FOREACH(e, m->time_events) {
|
||||
|
||||
if (m->quit)
|
||||
break;
|
||||
|
||||
if (e->dead || !e->enabled)
|
||||
continue;
|
||||
|
|
@ -806,7 +788,7 @@ static int dispatch_timeout(pa_mainloop *m) {
|
|||
/* Disable time event */
|
||||
mainloop_time_restart(e, NULL);
|
||||
|
||||
e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, TRUE), e->userdata);
|
||||
e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata);
|
||||
|
||||
r++;
|
||||
}
|
||||
|
|
@ -834,7 +816,8 @@ static void clear_wakeup(pa_mainloop *m) {
|
|||
return;
|
||||
|
||||
if (m->wakeup_requested) {
|
||||
while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c));
|
||||
while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c))
|
||||
;
|
||||
m->wakeup_requested = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -850,12 +833,17 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) {
|
|||
goto quit;
|
||||
|
||||
if (m->n_enabled_defer_events <= 0) {
|
||||
|
||||
if (m->rebuild_pollfds)
|
||||
rebuild_pollfds(m);
|
||||
|
||||
m->prepared_timeout = calc_next_timeout(m);
|
||||
if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
|
||||
m->prepared_timeout = timeout;
|
||||
if (timeout >= 0) {
|
||||
uint64_t u = (uint64_t) timeout * PA_USEC_PER_MSEC;
|
||||
|
||||
if (u < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID)
|
||||
m->prepared_timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
m->state = STATE_PREPARED;
|
||||
|
|
@ -866,6 +854,13 @@ quit:
|
|||
return -2;
|
||||
}
|
||||
|
||||
static int usec_to_timeout(pa_usec_t u) {
|
||||
if (u == PA_USEC_INVALID)
|
||||
return -1;
|
||||
|
||||
return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
int pa_mainloop_poll(pa_mainloop *m) {
|
||||
pa_assert(m);
|
||||
pa_assert(m->state == STATE_PREPARED);
|
||||
|
|
@ -881,9 +876,24 @@ int pa_mainloop_poll(pa_mainloop *m) {
|
|||
pa_assert(!m->rebuild_pollfds);
|
||||
|
||||
if (m->poll_func)
|
||||
m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
|
||||
else
|
||||
m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout);
|
||||
m->poll_func_ret = m->poll_func(
|
||||
m->pollfds, m->n_pollfds,
|
||||
usec_to_timeout(m->prepared_timeout),
|
||||
m->poll_func_userdata);
|
||||
else {
|
||||
#ifdef HAVE_PPOLL
|
||||
struct timespec ts;
|
||||
|
||||
m->poll_func_ret = ppoll(
|
||||
m->pollfds, m->n_pollfds,
|
||||
m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),
|
||||
NULL);
|
||||
#else
|
||||
m->poll_func_ret = poll(
|
||||
m->pollfds, m->n_pollfds,
|
||||
usec_to_timeout(m->prepared_timeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m->poll_func_ret < 0) {
|
||||
if (errno == EINTR)
|
||||
|
|
@ -902,7 +912,7 @@ quit:
|
|||
}
|
||||
|
||||
int pa_mainloop_dispatch(pa_mainloop *m) {
|
||||
int dispatched = 0;
|
||||
unsigned dispatched = 0;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(m->state == STATE_POLLED);
|
||||
|
|
@ -928,7 +938,7 @@ int pa_mainloop_dispatch(pa_mainloop *m) {
|
|||
|
||||
m->state = STATE_PASSIVE;
|
||||
|
||||
return dispatched;
|
||||
return (int) dispatched;
|
||||
|
||||
quit:
|
||||
m->state = STATE_QUIT;
|
||||
|
|
@ -937,6 +947,7 @@ quit:
|
|||
|
||||
int pa_mainloop_get_retval(pa_mainloop *m) {
|
||||
pa_assert(m);
|
||||
|
||||
return m->retval;
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +976,8 @@ quit:
|
|||
int pa_mainloop_run(pa_mainloop *m, int *retval) {
|
||||
int r;
|
||||
|
||||
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
|
||||
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
|
||||
;
|
||||
|
||||
if (r == -2)
|
||||
return 1;
|
||||
|
|
@ -985,6 +997,7 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) {
|
|||
|
||||
pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) {
|
||||
pa_assert(m);
|
||||
|
||||
return &m->api;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,27 @@ PA_C_DECL_BEGIN
|
|||
/** For streams that belong to a window on the screen: an XDG icon name for the window. e.g. "totem" */
|
||||
#define PA_PROP_WINDOW_ICON_NAME "window.icon_name"
|
||||
|
||||
/** For streams that belong to a window on the screen: absolute horizontal window position on the screen, integer formatted as text string. e.g. "865". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_X "window.x"
|
||||
|
||||
/** For streams that belong to a window on the screen: absolute vertical window position on the screen, integer formatted as text string. e.g. "343". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_Y "window.y"
|
||||
|
||||
/** For streams that belong to a window on the screen: window width on the screen, integer formatted as text string. e.g. "365". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_WIDTH "window.width"
|
||||
|
||||
/** For streams that belong to a window on the screen: window height on the screen, integer formatted as text string. e.g. "643". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_HEIGHT "window.height"
|
||||
|
||||
/** For streams that belong to a window on the screen: relative position of the window center on the screen, float formatted as text string, ranging from 0.0 (left side of the screen) to 1.0 (right side of the screen). e.g. "0.65". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_HPOS "window.hpos"
|
||||
|
||||
/** For streams that belong to a window on the screen: relative position of the window center on the screen, float formatted as text string, ranging from 0.0 (top of the screen) to 1.0 (bottom of the screen). e.g. "0.43". \since 0.9.17 */
|
||||
#define PA_PROP_WINDOW_VPOS "window.vpos"
|
||||
|
||||
/** For streams that belong to a window on the screen: if the windowing system supports multiple desktops, a comma seperated list of indexes of the desktops this window is visible on. If this property is an empty string, it is visible on all desktops (i.e. 'sticky'). The first desktop is 0. e.g. "0,2,3" \since 0.9.18 */
|
||||
#define PA_PROP_WINDOW_DESKTOP "window.desktop"
|
||||
|
||||
/** For streams that belong to an X11 window on the screen: the X11 display string. e.g. ":0.0" */
|
||||
#define PA_PROP_WINDOW_X11_DISPLAY "window.x11.display"
|
||||
|
||||
|
|
@ -197,7 +218,7 @@ PA_C_DECL_BEGIN
|
|||
/** For filter devices: master device id if applicable. */
|
||||
#define PA_PROP_DEVICE_MASTER_DEVICE "device.master_device"
|
||||
|
||||
/** For devices: buffer size in bytes, integer formatted as string.. */
|
||||
/** For devices: buffer size in bytes, integer formatted as string. */
|
||||
#define PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE "device.buffering.buffer_size"
|
||||
|
||||
/** For devices: fragment size in bytes, integer formatted as string. */
|
||||
|
|
|
|||
|
|
@ -44,15 +44,17 @@
|
|||
#include <pulse/util.h>
|
||||
#include <pulse/timeval.h>
|
||||
#include <pulse/proplist.h>
|
||||
#include <pulse/rtclock.h>
|
||||
|
||||
/** \file
|
||||
* Include all libpulse header files at once. The following
|
||||
* files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h,
|
||||
* \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h,
|
||||
* \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h,
|
||||
* \ref operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref
|
||||
* thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref proplist.h, \ref timeval.h and
|
||||
* \ref mainloop-signal.h at once */
|
||||
* Include all libpulse header files at once. The following files are
|
||||
* included: \ref mainloop-api.h, \ref sample.h, \ref def.h, \ref
|
||||
* context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, \ref
|
||||
* scache.h, \ref version.h, \ref error.h, \ref channelmap.h, \ref
|
||||
* operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref
|
||||
* thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref proplist.h,
|
||||
* \ref timeval.h, \ref rtclock.h and \ref mainloop-signal.h at
|
||||
* once */
|
||||
|
||||
/** \mainpage
|
||||
*
|
||||
|
|
|
|||
|
|
@ -302,6 +302,13 @@ pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE;
|
|||
/** Pretty print a sample type specification to a string */
|
||||
char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec);
|
||||
|
||||
/** Maximum required string length for pa_bytes_snprint(). Please note
|
||||
* that this value can change with any release without warning and
|
||||
* without being considered API or ABI breakage. You should not use
|
||||
* this definition anywhere where it might become part of an
|
||||
* ABI. \since 0.9.16 */
|
||||
#define PA_BYTES_SNPRINT_MAX 11
|
||||
|
||||
/** Pretty print a byte size value. (i.e. "2.5 MiB") */
|
||||
char* pa_bytes_snprint(char *s, size_t l, unsigned v);
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char
|
|||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, dev);
|
||||
|
||||
if (volume == (pa_volume_t) -1 && c->version < 15)
|
||||
if (volume == PA_VOLUME_INVALID && c->version < 15)
|
||||
volume = PA_VOLUME_NORM;
|
||||
|
||||
pa_tagstruct_putu32(t, volume);
|
||||
|
|
@ -216,7 +216,6 @@ pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *na
|
|||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, p, PA_ERR_INVALID);
|
||||
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
|
||||
|
||||
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
|
||||
|
|
@ -228,12 +227,19 @@ pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *na
|
|||
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
|
||||
pa_tagstruct_puts(t, dev);
|
||||
|
||||
if (volume == (pa_volume_t) -1 && c->version < 15)
|
||||
if (volume == PA_VOLUME_INVALID && c->version < 15)
|
||||
volume = PA_VOLUME_NORM;
|
||||
|
||||
pa_tagstruct_putu32(t, volume);
|
||||
pa_tagstruct_puts(t, name);
|
||||
pa_tagstruct_put_proplist(t, p);
|
||||
|
||||
if (p)
|
||||
pa_tagstruct_put_proplist(t, p);
|
||||
else {
|
||||
p = pa_proplist_new();
|
||||
pa_tagstruct_put_proplist(t, p);
|
||||
pa_proplist_free(p);
|
||||
}
|
||||
|
||||
pa_pstream_send_tagstruct(c->pstream, t);
|
||||
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_with_proplist_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ pa_operation* pa_context_play_sample(
|
|||
pa_context *c /**< Context */,
|
||||
const char *name /**< Name of the sample to play */,
|
||||
const char *dev /**< Sink to play this sample on */,
|
||||
pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here (pa_volume_t) -1 which will leave the decision about the volume to the server side which is a good idea. */ ,
|
||||
pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ ,
|
||||
pa_context_success_cb_t cb /**< Call this function after successfully starting playback, or NULL */,
|
||||
void *userdata /**< Userdata to pass to the callback */);
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ pa_operation* pa_context_play_sample_with_proplist(
|
|||
pa_context *c /**< Context */,
|
||||
const char *name /**< Name of the sample to play */,
|
||||
const char *dev /**< Sink to play this sample on */,
|
||||
pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here (pa_volume_t) -1 which will leave the decision about the volume to the server side which is a good idea. */ ,
|
||||
pa_volume_t volume /**< Volume to play this sample with. Starting with 0.9.15 you may pass here PA_VOLUME_INVALID which will leave the decision about the volume to the server side which is a good idea. */ ,
|
||||
pa_proplist *proplist /**< Property list for this sound. The property list of the cached entry will be merged into this property list */,
|
||||
pa_context_play_sample_cb_t cb /**< Call this function after successfully starting playback, or NULL */,
|
||||
void *userdata /**< Userdata to pass to the callback */);
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ typedef struct pa_stream pa_stream;
|
|||
typedef void (*pa_stream_success_cb_t) (pa_stream*s, int success, void *userdata);
|
||||
|
||||
/** A generic request callback */
|
||||
typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t bytes, void *userdata);
|
||||
typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t nbytes, void *userdata);
|
||||
|
||||
/** A generic notification callback */
|
||||
typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <pulsecore/winsock.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
|
||||
#include "timeval.h"
|
||||
|
||||
|
|
@ -54,9 +55,9 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
|
|||
#define EPOCHFILETIME (116444736000000000LL)
|
||||
#endif
|
||||
|
||||
FILETIME ft;
|
||||
LARGE_INTEGER li;
|
||||
__int64 t;
|
||||
FILETIME ft;
|
||||
LARGE_INTEGER li;
|
||||
int64_t t;
|
||||
|
||||
pa_assert(tv);
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
|||
pa_assert(b);
|
||||
|
||||
/* Check which whan is the earlier time and swap the two arguments if required. */
|
||||
if (pa_timeval_cmp(a, b) < 0) {
|
||||
if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
|
||||
const struct timeval *c;
|
||||
c = a;
|
||||
a = b;
|
||||
|
|
@ -94,9 +95,9 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
|||
|
||||
/* Calculate the microsecond difference */
|
||||
if (a->tv_usec > b->tv_usec)
|
||||
r += ((pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec);
|
||||
r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
|
||||
else if (a->tv_usec < b->tv_usec)
|
||||
r -= ((pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec);
|
||||
r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -128,45 +129,77 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) {
|
|||
}
|
||||
|
||||
struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
|
||||
unsigned long secs;
|
||||
time_t secs;
|
||||
pa_assert(tv);
|
||||
|
||||
secs = (unsigned long) (v/PA_USEC_PER_SEC);
|
||||
tv->tv_sec += (time_t) secs;
|
||||
v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
|
||||
secs = (time_t) (v/PA_USEC_PER_SEC);
|
||||
|
||||
if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
|
||||
goto overflow;
|
||||
|
||||
tv->tv_sec += secs;
|
||||
v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
|
||||
tv->tv_usec += (suseconds_t) v;
|
||||
|
||||
/* Normalize */
|
||||
while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) {
|
||||
while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
|
||||
|
||||
if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
|
||||
goto overflow;
|
||||
|
||||
tv->tv_sec++;
|
||||
tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
return tv;
|
||||
|
||||
overflow:
|
||||
tv->tv_sec = PA_INT_TYPE_MAX(time_t);
|
||||
tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
|
||||
return tv;
|
||||
}
|
||||
|
||||
struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
|
||||
unsigned long secs;
|
||||
time_t secs;
|
||||
pa_assert(tv);
|
||||
|
||||
secs = (unsigned long) (v/PA_USEC_PER_SEC);
|
||||
tv->tv_sec -= (time_t) secs;
|
||||
v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
|
||||
secs = (time_t) (v/PA_USEC_PER_SEC);
|
||||
|
||||
if (PA_UNLIKELY(tv->tv_sec < secs))
|
||||
goto underflow;
|
||||
|
||||
tv->tv_sec -= secs;
|
||||
v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
|
||||
|
||||
if (tv->tv_usec >= (suseconds_t) v)
|
||||
tv->tv_usec -= (suseconds_t) v;
|
||||
else {
|
||||
|
||||
if (PA_UNLIKELY(tv->tv_sec <= 0))
|
||||
goto underflow;
|
||||
|
||||
tv->tv_sec --;
|
||||
tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
|
||||
}
|
||||
|
||||
return tv;
|
||||
|
||||
underflow:
|
||||
tv->tv_sec = 0;
|
||||
tv->tv_usec = 0;
|
||||
return tv;
|
||||
}
|
||||
|
||||
struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
|
||||
pa_assert(tv);
|
||||
|
||||
if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
|
||||
tv->tv_sec = PA_INT_TYPE_MAX(time_t);
|
||||
tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
||||
tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
|
||||
tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
|
||||
|
||||
|
|
@ -174,7 +207,9 @@ struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
|
|||
}
|
||||
|
||||
pa_usec_t pa_timeval_load(const struct timeval *tv) {
|
||||
pa_assert(tv);
|
||||
|
||||
if (PA_UNLIKELY(!tv))
|
||||
return PA_USEC_INVALID;
|
||||
|
||||
return
|
||||
(pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
|
||||
|
|
|
|||
|
|
@ -51,12 +51,15 @@ PA_C_DECL_BEGIN
|
|||
/** The number of nanoseconds in a microsecond */
|
||||
#define PA_NSEC_PER_USEC ((unsigned long long) 1000ULL)
|
||||
|
||||
/** Invalid time in usec */
|
||||
/** Invalid time in usec. \since 0.9.15 */
|
||||
#define PA_USEC_INVALID ((pa_usec_t) -1)
|
||||
|
||||
/** Biggest time in usec. \since 0.9.18 */
|
||||
#define PA_USEC_MAX ((pa_usec_t) -2)
|
||||
|
||||
struct timeval;
|
||||
|
||||
/** Return the current timestamp, just like UNIX gettimeofday() */
|
||||
/** Return the current wallclock timestamp, just like UNIX gettimeofday(). */
|
||||
struct timeval *pa_gettimeofday(struct timeval *tv);
|
||||
|
||||
/** Calculate the difference between the two specified timeval
|
||||
|
|
|
|||
|
|
@ -120,10 +120,8 @@ static char* utf8_validate(const char *str, char *output) {
|
|||
size = 4;
|
||||
min = (1 << 16);
|
||||
val = (uint32_t) (*p & 0x07);
|
||||
} else {
|
||||
size = 1;
|
||||
} else
|
||||
goto error;
|
||||
}
|
||||
|
||||
p++;
|
||||
if (!is_continuation_char(*p))
|
||||
|
|
@ -150,12 +148,9 @@ ONE_REMAINING:
|
|||
|
||||
if (o) {
|
||||
memcpy(o, last, (size_t) size);
|
||||
o += size - 1;
|
||||
o += size;
|
||||
}
|
||||
|
||||
if (o)
|
||||
o++;
|
||||
|
||||
continue;
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
|
|||
a->channels = 0;
|
||||
|
||||
for (c = 0; c < PA_CHANNELS_MAX; c++)
|
||||
a->values[c] = (pa_volume_t) -1;
|
||||
a->values[c] = PA_VOLUME_INVALID;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ pa_volume_t pa_cvolume_min(const pa_cvolume *a) {
|
|||
|
||||
pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
|
||||
pa_volume_t m = PA_VOLUME_MUTED;
|
||||
unsigned c, n;
|
||||
unsigned c;
|
||||
|
||||
pa_assert(a);
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, p
|
|||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
|
||||
|
||||
for (c = n = 0; c < a->channels; c++) {
|
||||
for (c = 0; c < a->channels; c++) {
|
||||
|
||||
if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
|
||||
continue;
|
||||
|
|
@ -178,7 +178,7 @@ pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, p
|
|||
|
||||
pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
|
||||
pa_volume_t m = PA_VOLUME_MAX;
|
||||
unsigned c, n;
|
||||
unsigned c;
|
||||
|
||||
pa_assert(a);
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, p
|
|||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
|
||||
|
||||
for (c = n = 0; c < a->channels; c++) {
|
||||
for (c = 0; c < a->channels; c++) {
|
||||
|
||||
if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
|
||||
continue;
|
||||
|
|
@ -201,6 +201,9 @@ pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, p
|
|||
|
||||
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
|
||||
|
||||
pa_return_val_if_fail(a != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
|
||||
pa_return_val_if_fail(b != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
|
||||
|
||||
/* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
|
||||
|
||||
return (pa_volume_t) (((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM);
|
||||
|
|
@ -208,6 +211,9 @@ pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
|
|||
|
||||
pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
|
||||
|
||||
pa_return_val_if_fail(a != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
|
||||
pa_return_val_if_fail(b != PA_VOLUME_INVALID, PA_VOLUME_INVALID);
|
||||
|
||||
if (b <= PA_VOLUME_MUTED)
|
||||
return 0;
|
||||
|
||||
|
|
@ -232,6 +238,8 @@ pa_volume_t pa_sw_volume_from_dB(double dB) {
|
|||
|
||||
double pa_sw_volume_to_dB(pa_volume_t v) {
|
||||
|
||||
pa_return_val_if_fail(v != PA_VOLUME_INVALID, PA_DECIBEL_MININFTY);
|
||||
|
||||
if (v <= PA_VOLUME_MUTED)
|
||||
return PA_DECIBEL_MININFTY;
|
||||
|
||||
|
|
@ -259,6 +267,8 @@ pa_volume_t pa_sw_volume_from_linear(double v) {
|
|||
double pa_sw_volume_to_linear(pa_volume_t v) {
|
||||
double f;
|
||||
|
||||
pa_return_val_if_fail(v != PA_VOLUME_INVALID, 0.0);
|
||||
|
||||
if (v <= PA_VOLUME_MUTED)
|
||||
return 0.0;
|
||||
|
||||
|
|
@ -307,7 +317,7 @@ char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
|
|||
|
||||
pa_init_i18n();
|
||||
|
||||
if (v == (pa_volume_t) -1) {
|
||||
if (v == PA_VOLUME_INVALID) {
|
||||
pa_snprintf(s, l, _("(invalid)"));
|
||||
return s;
|
||||
}
|
||||
|
|
@ -357,7 +367,7 @@ char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
|
|||
|
||||
pa_init_i18n();
|
||||
|
||||
if (v == (pa_volume_t) -1) {
|
||||
if (v == PA_VOLUME_INVALID) {
|
||||
pa_snprintf(s, l, _("(invalid)"));
|
||||
return s;
|
||||
}
|
||||
|
|
@ -374,6 +384,7 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
|
|||
pa_assert(a);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(a), 0);
|
||||
pa_return_val_if_fail(v != PA_VOLUME_INVALID, 0);
|
||||
|
||||
for (c = 0; c < a->channels; c++)
|
||||
if (a->values[c] != v)
|
||||
|
|
@ -407,6 +418,7 @@ pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a,
|
|||
pa_assert(a);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
|
||||
pa_return_val_if_fail(b != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
for (i = 0; i < a->channels; i++)
|
||||
dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
|
||||
|
|
@ -441,6 +453,7 @@ pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, p
|
|||
pa_assert(a);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
|
||||
pa_return_val_if_fail(b != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
for (i = 0; i < a->channels; i++)
|
||||
dest->values[i] = pa_sw_volume_divide(a->values[i], b);
|
||||
|
|
@ -459,7 +472,7 @@ int pa_cvolume_valid(const pa_cvolume *v) {
|
|||
return 0;
|
||||
|
||||
for (c = 0; c < v->channels; c++)
|
||||
if (v->values[c] == (pa_volume_t) -1)
|
||||
if (v->values[c] == PA_VOLUME_INVALID)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
|
@ -497,8 +510,6 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa
|
|||
pa_assert(from);
|
||||
pa_assert(to);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(from), NULL);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
|
||||
|
||||
|
|
@ -600,8 +611,6 @@ float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
|
|||
pa_assert(v);
|
||||
pa_assert(map);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
|
||||
|
||||
if (!pa_channel_map_can_balance(map))
|
||||
|
|
@ -633,12 +642,10 @@ pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, flo
|
|||
|
||||
pa_assert(map);
|
||||
pa_assert(v);
|
||||
pa_assert(new_balance >= -1.0f);
|
||||
pa_assert(new_balance <= 1.0f);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
|
||||
pa_return_val_if_fail(new_balance >= -1.0f, NULL);
|
||||
pa_return_val_if_fail(new_balance <= 1.0f, NULL);
|
||||
|
||||
if (!pa_channel_map_can_balance(map))
|
||||
return v;
|
||||
|
|
@ -679,7 +686,7 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
|
|||
pa_assert(v);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
|
||||
pa_return_val_if_fail(max != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
t = pa_cvolume_max(v);
|
||||
|
||||
|
|
@ -698,8 +705,12 @@ pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map
|
|||
|
||||
pa_assert(v);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
|
||||
pa_return_val_if_fail(max != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
if (!cm)
|
||||
return pa_cvolume_scale(v, max);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL);
|
||||
|
||||
t = pa_cvolume_max_mask(v, cm, mask);
|
||||
|
||||
|
|
@ -750,8 +761,6 @@ float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
|
|||
pa_assert(v);
|
||||
pa_assert(map);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
|
||||
|
||||
if (!pa_channel_map_can_fade(map))
|
||||
|
|
@ -774,12 +783,10 @@ pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float
|
|||
|
||||
pa_assert(map);
|
||||
pa_assert(v);
|
||||
pa_assert(new_fade >= -1.0f);
|
||||
pa_assert(new_fade <= 1.0f);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
|
||||
pa_return_val_if_fail(new_fade >= -1.0f, NULL);
|
||||
pa_return_val_if_fail(new_fade <= 1.0f, NULL);
|
||||
|
||||
if (!pa_channel_map_can_fade(map))
|
||||
return v;
|
||||
|
|
@ -827,6 +834,7 @@ pa_cvolume* pa_cvolume_set_position(
|
|||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
|
||||
pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
|
||||
pa_return_val_if_fail(v != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
for (c = 0; c < map->channels; c++)
|
||||
if (map->map[c] == t) {
|
||||
|
|
@ -883,6 +891,7 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
|
|||
pa_assert(v);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(inc != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
m = pa_cvolume_max(v);
|
||||
|
||||
|
|
@ -900,6 +909,7 @@ pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
|
|||
pa_assert(v);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
|
||||
pa_return_val_if_fail(dec != PA_VOLUME_INVALID, NULL);
|
||||
|
||||
m = pa_cvolume_max(v);
|
||||
|
||||
|
|
|
|||
|
|
@ -106,11 +106,14 @@ typedef uint32_t pa_volume_t;
|
|||
/** Normal volume (100%, 0 dB) */
|
||||
#define PA_VOLUME_NORM ((pa_volume_t) 0x10000U)
|
||||
|
||||
/** Muted volume (0%, -inf dB) */
|
||||
/** Muted (minimal valid) volume (0%, -inf dB) */
|
||||
#define PA_VOLUME_MUTED ((pa_volume_t) 0U)
|
||||
|
||||
/** Maximum volume we can store. \since 0.9.15 */
|
||||
#define PA_VOLUME_MAX ((pa_volume_t) UINT32_MAX)
|
||||
/** Maximum valid volume we can store. \since 0.9.15 */
|
||||
#define PA_VOLUME_MAX ((pa_volume_t) UINT32_MAX-1)
|
||||
|
||||
/** Special 'invalid' volume. \since 0.9.16 */
|
||||
#define PA_VOLUME_INVALID ((pa_volume_t) UINT32_MAX)
|
||||
|
||||
/** A structure encapsulating a per-channel volume */
|
||||
typedef struct pa_cvolume {
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf
|
|||
static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
|
||||
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||
char s[256];
|
||||
char bytes[PA_BYTES_SNPRINT_MAX];
|
||||
const pa_mempool_stat *stat;
|
||||
unsigned k;
|
||||
pa_sink *def_sink;
|
||||
|
|
@ -352,22 +352,22 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
|
||||
pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_allocated),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->allocated_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->allocated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_accumulated),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->accumulated_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->accumulated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_imported),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->imported_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->imported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_exported),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->exported_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->exported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
|
||||
|
||||
pa_strbuf_printf(buf, "Default sample spec: %s\n",
|
||||
pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
|
||||
|
|
@ -529,7 +529,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -571,7 +571,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -607,7 +607,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, source->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_source_set_volume(source, &cvolume, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1549,7 +1549,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
pa_card *card;
|
||||
int nl;
|
||||
pa_bool_t nl;
|
||||
uint32_t idx;
|
||||
char txt[256];
|
||||
time_t now;
|
||||
|
|
@ -1567,7 +1567,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
|
||||
#endif
|
||||
|
||||
for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
|
||||
PA_IDXSET_FOREACH(m, c->modules, idx) {
|
||||
|
||||
pa_strbuf_printf(buf, "load-module %s", m->name);
|
||||
|
||||
|
|
@ -1577,58 +1577,58 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_strbuf_puts(buf, "\n");
|
||||
}
|
||||
|
||||
nl = 0;
|
||||
|
||||
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(sink, c->sinks, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
|
||||
}
|
||||
|
||||
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(source, c->sources, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
|
||||
}
|
||||
|
||||
for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(card, c->cards, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
if (card->active_profile)
|
||||
pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
|
||||
}
|
||||
|
||||
nl = 0;
|
||||
|
||||
nl = FALSE;
|
||||
if ((sink = pa_namereg_get_default_sink(c))) {
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
|
||||
}
|
||||
|
||||
if ((source = pa_namereg_get_default_source(c))) {
|
||||
if (!nl) {
|
||||
if (!nl)
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
|
||||
}
|
||||
|
||||
|
|
@ -1813,8 +1813,6 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_b
|
|||
|
||||
ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static int parse_line(const char *filename, unsigned line, char **section, const
|
|||
return 0;
|
||||
|
||||
if (pa_startswith(b, ".include ")) {
|
||||
char *path, *fn;
|
||||
char *path = NULL, *fn;
|
||||
int r;
|
||||
|
||||
fn = strip(b+9);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
|
|||
|
||||
pa_assert(tv);
|
||||
|
||||
/* pa_timeval_sub() saturates on underflow! */
|
||||
|
||||
if (pa_timeval_cmp(&wc_now, tv) < 0)
|
||||
pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
|
||||
else
|
||||
|
|
@ -144,13 +146,29 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
|
|||
}
|
||||
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts) {
|
||||
pa_assert(ts);
|
||||
|
||||
if (PA_UNLIKELY(!ts))
|
||||
return PA_USEC_INVALID;
|
||||
|
||||
return
|
||||
(pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC +
|
||||
(pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v) {
|
||||
pa_assert(ts);
|
||||
|
||||
if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
|
||||
ts->tv_sec = PA_INT_TYPE_MAX(time_t);
|
||||
ts->tv_nsec = (long) (PA_NSEC_PER_SEC-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ts->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
|
||||
ts->tv_nsec = (long) ((v % PA_USEC_PER_SEC) * PA_NSEC_PER_USEC);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
|
||||
|
||||
|
|
@ -162,6 +180,8 @@ static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
|
|||
|
||||
pa_assert(tv);
|
||||
|
||||
/* pa_timeval_sub() saturates on underflow! */
|
||||
|
||||
if (pa_timeval_cmp(&rt_now, tv) < 0)
|
||||
pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
|
||||
else
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ void pa_rtclock_hrtimer_enable(void);
|
|||
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
|
||||
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts);
|
||||
struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v);
|
||||
|
||||
struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock);
|
||||
|
||||
|
|
|
|||
|
|
@ -335,12 +335,12 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
|
|||
|
||||
pass_volume = TRUE;
|
||||
|
||||
if (e->volume_is_set && volume != (pa_volume_t) -1) {
|
||||
if (e->volume_is_set && volume != PA_VOLUME_INVALID) {
|
||||
pa_cvolume_set(&r, e->sample_spec.channels, volume);
|
||||
pa_sw_cvolume_multiply(&r, &r, &e->volume);
|
||||
} else if (e->volume_is_set)
|
||||
r = e->volume;
|
||||
else if (volume != (pa_volume_t) -1)
|
||||
else if (volume != PA_VOLUME_INVALID)
|
||||
pa_cvolume_set(&r, e->sample_spec.channels, volume);
|
||||
else
|
||||
pass_volume = FALSE;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/usergroup.h>
|
||||
#include <pulsecore/strlist.h>
|
||||
|
||||
#include "core-util.h"
|
||||
|
||||
|
|
@ -124,6 +125,8 @@
|
|||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
static pa_strlist *recorded_env = NULL;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
|
||||
#define PULSE_ROOTENV "PULSE_ROOT"
|
||||
|
|
@ -588,13 +591,13 @@ static int set_scheduler(int rtprio) {
|
|||
sp.sched_priority = rtprio;
|
||||
|
||||
#ifdef SCHED_RESET_ON_FORK
|
||||
if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
|
||||
pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
|
||||
pa_log_debug("SCHED_RR worked.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -609,6 +612,11 @@ static int set_scheduler(int rtprio) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* We need to disable exit on disconnect because otherwise
|
||||
* dbus_shutdown will kill us. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
r = rtkit_make_realtime(bus, 0, rtprio);
|
||||
dbus_connection_unref(bus);
|
||||
|
||||
|
|
@ -677,6 +685,11 @@ static int set_nice(int nice_level) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* We need to disable exit on disconnect because otherwise
|
||||
* dbus_shutdown will kill us. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
r = rtkit_make_high_priority(bus, 0, nice_level);
|
||||
dbus_connection_unref(bus);
|
||||
|
||||
|
|
@ -773,7 +786,6 @@ int pa_match(const char *expr, const char *v) {
|
|||
/* Try to parse a boolean string value.*/
|
||||
int pa_parse_boolean(const char *v) {
|
||||
const char *expr;
|
||||
int r;
|
||||
pa_assert(v);
|
||||
|
||||
/* First we check language independant */
|
||||
|
|
@ -785,12 +797,12 @@ int pa_parse_boolean(const char *v) {
|
|||
/* And then we check language dependant */
|
||||
if ((expr = nl_langinfo(YESEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = pa_match(expr, v)) > 0)
|
||||
if (pa_match(expr, v) > 0)
|
||||
return 1;
|
||||
|
||||
if ((expr = nl_langinfo(NOEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = pa_match(expr, v)) > 0)
|
||||
if (pa_match(expr, v) > 0)
|
||||
return 0;
|
||||
|
||||
errno = EINVAL;
|
||||
|
|
@ -1182,7 +1194,7 @@ char* pa_strip_nl(char *s) {
|
|||
|
||||
/* Create a temporary lock file and lock it. */
|
||||
int pa_lock_lockfile(const char *fn) {
|
||||
int fd = -1;
|
||||
int fd;
|
||||
pa_assert(fn);
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -1225,8 +1237,6 @@ int pa_lock_lockfile(const char *fn) {
|
|||
fd = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
|
@ -1368,19 +1378,10 @@ static char* make_random_dir(mode_t m) {
|
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
|
||||
const char *tmpdir;
|
||||
char *fn;
|
||||
size_t pathlen;
|
||||
|
||||
if (!(tmpdir = getenv("TMPDIR")))
|
||||
if (!(tmpdir = getenv("TMP")))
|
||||
if (!(tmpdir = getenv("TEMP")))
|
||||
tmpdir = getenv("TEMPDIR");
|
||||
|
||||
if (!tmpdir || !pa_is_path_absolute(tmpdir))
|
||||
tmpdir = "/tmp";
|
||||
|
||||
fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
|
||||
fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
|
||||
pathlen = strlen(fn);
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -2394,7 +2395,7 @@ int pa_reset_sigs(int except, ...) {
|
|||
p[i++] = except;
|
||||
|
||||
while ((sig = va_arg(ap, int)) >= 0)
|
||||
sig = p[i++];
|
||||
p[i++] = sig;
|
||||
}
|
||||
p[i] = -1;
|
||||
|
||||
|
|
@ -2451,9 +2452,38 @@ void pa_set_env(const char *key, const char *value) {
|
|||
pa_assert(key);
|
||||
pa_assert(value);
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
putenv(pa_sprintf_malloc("%s=%s", key, value));
|
||||
}
|
||||
|
||||
void pa_set_env_and_record(const char *key, const char *value) {
|
||||
pa_assert(key);
|
||||
pa_assert(value);
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
pa_set_env(key, value);
|
||||
recorded_env = pa_strlist_prepend(recorded_env, key);
|
||||
}
|
||||
|
||||
void pa_unset_env_recorded(void) {
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
for (;;) {
|
||||
char *s;
|
||||
|
||||
recorded_env = pa_strlist_pop(recorded_env, &s);
|
||||
|
||||
if (!s)
|
||||
break;
|
||||
|
||||
unsetenv(s);
|
||||
pa_xfree(s);
|
||||
}
|
||||
}
|
||||
|
||||
pa_bool_t pa_in_system_mode(void) {
|
||||
const char *e;
|
||||
|
||||
|
|
@ -2837,3 +2867,25 @@ pa_bool_t pa_run_from_build_tree(void) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *pa_get_temp_dir(void) {
|
||||
const char *t;
|
||||
|
||||
if ((t = getenv("TMPDIR")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TMP")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TEMP")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TEMPDIR")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
return "/tmp";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ int pa_reset_sigs(int except, ...);
|
|||
int pa_reset_sigsv(const int except[]);
|
||||
|
||||
void pa_set_env(const char *key, const char *value);
|
||||
void pa_set_env_and_record(const char *key, const char *value);
|
||||
void pa_unset_env_recorded(void);
|
||||
|
||||
pa_bool_t pa_in_system_mode(void);
|
||||
|
||||
|
|
@ -254,4 +256,6 @@ void pa_reset_personality(void);
|
|||
pa_bool_t pa_run_from_build_tree(void);
|
||||
#endif
|
||||
|
||||
const char *pa_get_temp_dir(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void pa_cpu_init_x86 (void) {
|
|||
pa_remap_func_init_mmx (flags);
|
||||
}
|
||||
|
||||
if (flags & PA_CPU_X86_SSE) {
|
||||
if (flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) {
|
||||
pa_volume_func_init_sse (flags);
|
||||
pa_remap_func_init_sse (flags);
|
||||
pa_convert_func_init_sse (flags);
|
||||
|
|
|
|||
|
|
@ -130,15 +130,22 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
|
|||
}
|
||||
|
||||
int pa_flist_push(pa_flist*l, void *p) {
|
||||
unsigned idx, n, len;
|
||||
unsigned idx, n;
|
||||
pa_atomic_ptr_t*cells;
|
||||
#ifdef PROFILE
|
||||
unsigned len;
|
||||
#endif
|
||||
|
||||
pa_assert(l);
|
||||
pa_assert(p);
|
||||
|
||||
cells = PA_FLIST_CELLS(l);
|
||||
|
||||
n = len = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
|
||||
n = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
|
||||
|
||||
#ifdef PROFILE
|
||||
len = n;
|
||||
#endif
|
||||
|
||||
_Y;
|
||||
idx = reduce(l, (unsigned) pa_atomic_load(&l->write_idx));
|
||||
|
|
@ -171,14 +178,21 @@ int pa_flist_push(pa_flist*l, void *p) {
|
|||
}
|
||||
|
||||
void* pa_flist_pop(pa_flist*l) {
|
||||
unsigned idx, len, n;
|
||||
unsigned idx, n;
|
||||
pa_atomic_ptr_t *cells;
|
||||
#ifdef PROFILE
|
||||
unsigned len;
|
||||
#endif
|
||||
|
||||
pa_assert(l);
|
||||
|
||||
cells = PA_FLIST_CELLS(l);
|
||||
|
||||
n = len = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
|
||||
n = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
|
||||
|
||||
#ifdef PROFILE
|
||||
len = n;
|
||||
#endif
|
||||
|
||||
_Y;
|
||||
idx = reduce(l, (unsigned) pa_atomic_load(&l->read_idx));
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue