Merge branch 'master' into dbus-work

Conflicts:
	src/daemon/daemon-conf.c
This commit is contained in:
Tanu Kaskinen 2009-10-02 17:24:44 +03:00
commit 019331d25b
130 changed files with 24774 additions and 14714 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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

1248
po/as.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1116
po/ca.po

File diff suppressed because it is too large Load diff

856
po/cs.po

File diff suppressed because it is too large Load diff

1120
po/de.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

830
po/el.po

File diff suppressed because it is too large Load diff

835
po/es.po

File diff suppressed because it is too large Load diff

1198
po/fi.po

File diff suppressed because it is too large Load diff

812
po/fr.po

File diff suppressed because it is too large Load diff

1324
po/gu.po

File diff suppressed because it is too large Load diff

1239
po/hi.po

File diff suppressed because it is too large Load diff

1187
po/it.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1262
po/kn.po

File diff suppressed because it is too large Load diff

2569
po/ml.po Normal file

File diff suppressed because it is too large Load diff

1260
po/mr.po

File diff suppressed because it is too large Load diff

1407
po/nl.po

File diff suppressed because it is too large Load diff

1309
po/or.po

File diff suppressed because it is too large Load diff

1238
po/pa.po

File diff suppressed because it is too large Load diff

850
po/pl.po

File diff suppressed because it is too large Load diff

1330
po/pt.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1355
po/sr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

825
po/sv.po

File diff suppressed because it is too large Load diff

1277
po/ta.po

File diff suppressed because it is too large Load diff

1235
po/te.po

File diff suppressed because it is too large Load diff

1287
po/uk.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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;
}

View file

@ -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 */

View file

@ -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]

View file

@ -56,7 +56,7 @@ volume = off
switch = off
volume = off
[Element Sourround]
[Element Surround]
switch = off
volume = off

View file

@ -62,7 +62,7 @@ volume = off
switch = off
volume = off
[Element Sourround]
[Element Surround]
switch = off
volume = off

View file

@ -59,7 +59,7 @@ volume = off
switch = off
volume = off
[Element Sourround]
[Element Surround]
switch = off
volume = off

View file

@ -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__;

View 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)) {

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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();
}

View file

@ -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

View file

@ -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)));

View file

@ -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) {

View file

@ -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;
}

View file

@ -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);

View file

@ -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)))

View file

@ -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);

View file

@ -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")))

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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 */

View file

@ -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();

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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. */

View file

@ -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
*

View file

@ -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);

View file

@ -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);

View file

@ -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 */);

View file

@ -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);

View file

@ -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 +

View file

@ -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

View file

@ -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:

View file

@ -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);

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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";
}

View file

@ -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

View file

@ -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);

View file

@ -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