Merge branch 'master' of git://git.0pointer.de/pulseaudio

This commit is contained in:
Colin Guthrie 2008-07-30 23:43:45 +01:00
commit b30a5d601e
29 changed files with 423 additions and 155 deletions

View file

@ -29,12 +29,12 @@ m4_define(PA_MICRO, [11])
AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net])
AC_CONFIG_SRCDIR([src/daemon/main.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign -Wall])
AM_INIT_AUTOMAKE([foreign 1.10 -Wall])
AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR")
AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
AC_SUBST(PA_API_VERSION, 11)
AC_SUBST(PA_API_VERSION, 12)
AC_SUBST(PA_PROTOCOL_VERSION, 13)
# The stable ABI for client applications, for the version info x:y:z
@ -376,7 +376,7 @@ AC_SEARCH_LIBS([connect], [socket])
AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
AC_CHECK_LIB(gdbm, gdbm_open)
AC_CHECK_HEADERS(gdbm.h)
AC_CHECK_HEADERS(gdbm.h, [], [AC_MSG_ERROR([gdbm.h not found])])
#### Check for functions ####
@ -599,7 +599,7 @@ AC_ARG_ENABLE([alsa],
[alsa=auto])
if test "x${alsa}" != xno ; then
PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.16 ],
PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.17 ],
[
HAVE_ALSA=1
AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?])
@ -607,7 +607,7 @@ if test "x${alsa}" != xno ; then
[
HAVE_ALSA=0
if test "x$alsa" = xyes ; then
AC_MSG_ERROR([*** ALSA support not found])
AC_MSG_ERROR([*** Needed alsa >= 1.0.17 support not found])
fi
])
else
@ -693,7 +693,7 @@ AC_ARG_ENABLE([gconf],
*) AC_MSG_ERROR(bad value ${enableval} for --disable-gconf) ;;
esac
],
[glib=auto])
[gconf=auto])
if test "x${gconf}" != xno ; then
PKG_CHECK_MODULES(GCONF, [ gconf-2.0 >= 2.4.0 ],

1
doxygen/.gitignore vendored
View file

@ -1 +1,2 @@
doxygen.conf
html

2
src/.gitignore vendored
View file

@ -15,6 +15,7 @@ cpulimit-test
cpulimit-test2
daemon.conf
default.pa
system.pa
envelope-test
esdcompat
flist-test
@ -54,3 +55,4 @@ thread-mainloop-test
thread-test
utf8-test
voltest
start-pulseaudio-x11

View file

@ -96,23 +96,26 @@ EXTRA_DIST = \
pulse/version.h.in \
daemon/daemon.conf.in \
daemon/default.pa.in \
daemon/system.pa.in \
daemon/default.pa.win32 \
depmod.py \
daemon/esdcompat.in \
daemon/start-pulseaudio-x11.in \
utils/padsp \
modules/module-defs.h.m4 \
daemon/pulseaudio-module-xsmp.desktop \
daemon/pulseaudio.desktop \
map-file \
daemon/org.pulseaudio.policy
pulseconf_DATA = \
default.pa \
system.pa \
daemon.conf \
client.conf
if HAVE_X11
xdgautostart_DATA = \
daemon/pulseaudio-module-xsmp.desktop
daemon/pulseaudio.desktop
endif
BUILT_SOURCES = \
@ -184,7 +187,7 @@ if HAVE_AVAHI
bin_PROGRAMS += pabrowse
endif
bin_SCRIPTS = esdcompat
bin_SCRIPTS = esdcompat start-pulseaudio-x11
pacat_SOURCES = utils/pacat.c
pacat_LDADD = $(AM_LDADD) libpulse.la
@ -585,7 +588,7 @@ endif
libpulse_la_CFLAGS = $(AM_CFLAGS)
libpulse_la_LDFLAGS = -version-info $(LIBPULSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV)
libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LTLIBICONV)
if HAVE_X11
libpulse_la_CFLAGS += $(X_CFLAGS)
@ -801,7 +804,7 @@ endif
libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS)
libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO)
libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) libffmpeg-resampler.la
libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LIBSPEEX_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LTLIBICONV) libffmpeg-resampler.la
###################################
# Plug-in support libraries #
@ -1542,7 +1545,7 @@ suid: pulseaudio .libs/lt-pulseaudio
chown root $^
chmod u+s $^
CLEANFILES = esdcompat client.conf default.pa daemon.conf
CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11
esdcompat: daemon/esdcompat.in Makefile
sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
@ -1550,17 +1553,28 @@ esdcompat: daemon/esdcompat.in Makefile
-e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@
chmod +x esdcompat
start-pulseaudio-x11: daemon/start-pulseaudio-x11.in Makefile
sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \
-e 's,@PACTL_BINARY\@,$(bindir)/pactl,g' < $< > $@
chmod +x start-pulseaudio-x11
client.conf: pulse/client.conf.in Makefile
sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@
if OS_IS_WIN32
default.pa: daemon/default.pa.win32
cp $< $@
system.pa: daemon/default.pa.win32
cp $< $@
else
default.pa: daemon/default.pa.in Makefile
sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \
-e 's,@PA_DLSEARCHPATH\@,$(modlibexecdir),g' \
-e 's,@PA_SOEXT\@,.so,g' < $< > $@
system.pa: daemon/system.pa.in Makefile
sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \
-e 's,@PA_DLSEARCHPATH\@,$(modlibexecdir),g' \
-e 's,@PA_SOEXT\@,.so,g' < $< > $@
endif
daemon.conf: daemon/daemon.conf.in Makefile

View file

@ -62,7 +62,7 @@ static const pa_daemon_conf default_conf = {
.realtime_scheduling = FALSE,
.realtime_priority = 5, /* Half of JACK's default rtprio */
.disallow_module_loading = FALSE,
.exit_idle_time = -1,
.exit_idle_time = 20,
.module_idle_time = 20,
.scache_idle_time = 20,
.auto_log_target = 1,

View file

@ -32,7 +32,7 @@
; realtime-scheduling = no
; realtime-priority = 5
; exit-idle-time = -1
; exit-idle-time = 20
; module-idle-time = 20
; scache-idle-time = 20

View file

@ -16,6 +16,9 @@
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
# This startup script is used only if PulseAudio is started per-user
# (i.e. not in system mode)
.nofail
### Load something into the sample cache
@ -80,14 +83,6 @@ load-module module-always-sink
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
### Load X11 bell module
#load-module module-x11-bell sample=bell-windowing-system
### Register ourselves in the X11 session manager
# Deactivated by default, to avoid deadlock when PA is started as esd from gnome-session
# Instead we load this via /etc/xdg/autostart/ and "pactl load-module" now
#load-module module-x11-xsmp
### If autoexit on idle is enabled we want to make sure we only quit
### when no local session needs us anymore.
load-module module-console-kit
@ -104,12 +99,21 @@ load-module module-gconf
.fail
.endif
# X11 modules should not be started from default.pa so that one daemon
# can be shared by multiple sessions.
### Load X11 bell module
#load-module module-x11-bell sample=bell-windowing-system
### Register ourselves in the X11 session manager
#load-module module-x11-xsmp
### Publish connection data in the X11 root window
.ifexists module-x11-publish@PA_SOEXT@
.nofail
load-module module-x11-publish
.fail
.endif
#.ifexists module-x11-publish@PA_SOEXT@
#.nofail
#load-module module-x11-publish
#.fail
#.endif
### Make some devices default
#set-default-sink output

View file

@ -496,7 +496,7 @@ int main(int argc, char *argv[]) {
if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START))
pa_raise_priority(conf->nice_level);
if (pa_have_caps()) {
if (!real_root && pa_have_caps()) {
pa_bool_t drop;
drop = (conf->cmd != PA_CMD_DAEMON && conf->cmd != PA_CMD_START) || !conf->realtime_scheduling;
@ -627,6 +627,11 @@ int main(int argc, char *argv[]) {
goto finish;
}
if (conf->cmd == PA_CMD_START && conf->system_instance) {
pa_log("--start not supported for system instances.");
goto finish;
}
if (conf->cmd == PA_CMD_START) {
/* If we shall start PA only when it is not running yet, we
* first take the autospawn lock to make things
@ -762,8 +767,6 @@ int main(int argc, char *argv[]) {
/* If we are already running and with are run in
* --start mode, then let's return this as success. */
pa_log_info("z=%i rock!", z);
retval = 0;
goto finish;
}

View file

@ -1,10 +0,0 @@
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=PulseAudio Session Management
Comment=Load module-x11-xsmp into PulseAudio
Exec=pactl load-module module-x11-xsmp
Terminal=false
Type=Application
Categories=
GenericName=

View file

@ -0,0 +1,10 @@
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=PulseAudio Sound System
Comment=Start the PulseAudio Sound System
Exec=start-pulseaudio-x11
Terminal=false
Type=Application
Categories=
GenericName=

View file

@ -0,0 +1,31 @@
#!/bin/sh
# 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 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.
set -e
@PA_BINARY@ --start "$@"
if [ x"$DISPLAY" != x ] ; then
@PACTL_BINARY@ load-module module-x11-publish "display=$DISPLAY" > /dev/null
if [ x"$SESSION_MANAGER" != x ] ; then
@PACTL_BINARY@ load-module module-x11-xsmp "display=$DISPLAY session_manager=$SESSION_MANAGER" > /dev/null
fi
fi

54
src/daemon/system.pa.in Executable file
View file

@ -0,0 +1,54 @@
#!@PA_BINARY@ -nF
#
# 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 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.
# This startup script is used only if PulseAudio is started in system
# mode.
### Automatically load driver modules depending on the hardware available
.ifexists module-hal-detect@PA_SOEXT@
load-module module-hal-detect
.else
### Alternatively use the static hardware detection module (for systems that
### lack HAL support)
load-module module-detect
.endif
### Load several protocols
.ifexists module-esound-protocol-unix@PA_SOEXT@
load-module module-esound-protocol-unix
.endif
load-module module-native-protocol-unix
### Automatically restore the volume of playback streams
load-module module-volume-restore
### Automatically restore the default sink/source when changed by the user during runtime
load-module module-default-device-restore
### Automatically move streams to the default sink if the sink they are
### connected to dies, similar for sources
load-module module-rescue-streams
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
### Enable positioned event sounds
load-module module-position-event-sounds

View file

@ -358,7 +358,6 @@ static int add_matches(struct userdata *u, pa_bool_t add) {
} else
dbus_bus_remove_match(pa_dbus_connection_get(u->dbus_connection), filter2, &e);
if (add)
pa_assert_se(dbus_connection_add_filter(pa_dbus_connection_get(u->dbus_connection), filter_func, u, NULL));
else

View file

@ -71,7 +71,7 @@ struct userdata {
static void add_session(struct userdata *u, const char *id) {
DBusError error;
DBusMessage *m = NULL, *reply = NULL;
int32_t uid;
uint32_t uid;
struct session *session;
char *t;
@ -92,10 +92,14 @@ static void add_session(struct userdata *u, const char *id) {
goto fail;
}
/* FIXME: Why is this in int32? and not an uint32? */
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID)) {
pa_log("Failed to parse GetUnixUser() result: %s: %s", error.name, error.message);
goto fail;
/* CK 0.3 this changed from int32 to uint32 */
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID)) {
dbus_error_free(&error);
if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID)) {
pa_log("Failed to parse GetUnixUser() result: %s: %s", error.name, error.message);
goto fail;
}
}
/* We only care about our own sessions */
@ -163,27 +167,39 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
if (dbus_message_is_signal(message, "org.freedesktop.ConsoleKit.Seat", "SessionAdded")) {
if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) {
pa_log_error("Failed to parse SessionAdded message: %s: %s", error.name, error.message);
goto finish;
/* CK API changed to match spec in 0.3 */
if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
dbus_error_free(&error);
if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) {
pa_log_error("Failed to parse SessionAdded message: %s: %s", error.name, error.message);
goto finish;
}
}
add_session(u, path);
return DBUS_HANDLER_RESULT_HANDLED;
} else if (dbus_message_is_signal(message, "org.freedesktop.ConsoleKit.Seat", "SessionRemoved")) {
if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) {
pa_log_error("Failed to parse SessionRemoved message: %s: %s", error.name, error.message);
goto finish;
/* CK API changed to match spec in 0.3 */
if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
dbus_error_free(&error);
if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) {
pa_log_error("Failed to parse SessionRemoved message: %s: %s", error.name, error.message);
goto finish;
}
}
remove_session(u, path);
return DBUS_HANDLER_RESULT_HANDLED;
}
finish:
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_HANDLED;
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static int get_session_list(struct userdata *u) {
@ -327,8 +343,17 @@ void pa__done(pa_module *m) {
pa_hashmap_free(u->sessions, NULL, NULL);
}
if (u->connection)
if (u->connection) {
DBusError error;
dbus_error_init(&error);
dbus_bus_remove_match(pa_dbus_connection_get(u->connection), "type='signal',sender='org.freedesktop.ConsoleKit', interface='org.freedesktop.ConsoleKit.Seat'", &error);
dbus_error_free(&error);
dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
pa_dbus_connection_unref(u->connection);
}
pa_xfree(u);
}

View file

@ -615,6 +615,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
device_added_cb(u->context, udi);
}
return DBUS_HANDLER_RESULT_HANDLED;
} else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) {
/* We use this message to avoid a dirty race condition when we
get an ACLAdded message before the previously owning PA
@ -661,12 +663,14 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
} else
/* Yes, we don't check the UDI for validity, but hopefully HAL will */
device_added_cb(u->context, udi);
return DBUS_HANDLER_RESULT_HANDLED;
}
finish:
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_HANDLED;
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static void hal_context_free(LibHalContext* hal_context) {
@ -842,8 +846,20 @@ void pa__done(pa_module *m) {
if (u->devices)
pa_hashmap_free(u->devices, hal_device_free_cb, NULL);
if (u->connection)
if (u->connection) {
DBusError error;
dbus_error_init(&error);
dbus_bus_remove_match(pa_dbus_connection_get(u->connection), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
dbus_error_free(&error);
dbus_bus_remove_match(pa_dbus_connection_get(u->connection), "type='signal',interface='org.pulseaudio.Server'", &error);
dbus_error_free(&error);
dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
pa_dbus_connection_unref(u->connection);
}
pa_xfree(u);
}

View file

@ -47,7 +47,7 @@
PA_MODULE_AUTHOR("Lennart Poettering");
PA_MODULE_DESCRIPTION("X11 session management");
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(TRUE);
PA_MODULE_LOAD_ONCE(FALSE);
PA_MODULE_USAGE("session_manager=<session manager string> display=<X11 display>");
static pa_bool_t ice_in_use = FALSE;

View file

@ -47,8 +47,10 @@
*
* \li pa_channel_map_init_mono() - Create a channel map with only mono audio.
* \li pa_channel_map_init_stereo() - Create a standard stereo mapping.
* \li pa_channel_map_init_auto() - Create a standard channel map for up to
* six channels.
* \li pa_channel_map_init_auto() - Create a standard channel map for a specific number of channels
* \li pa_channel_map_init_extend() - Similar to
* pa_channel_map_init_auto() but synthesize a channel map if noone
* predefined one is known for the specified number of channels.
*
* \section conv_sec Convenience Functions
*

View file

@ -66,7 +66,7 @@ pa_client_conf *pa_client_conf_new(void) {
pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
c->daemon_binary = pa_xstrdup(PA_BINARY);
c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5");
c->extra_arguments = pa_xstrdup("--log-target=syslog");
c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE);
return c;

View file

@ -25,7 +25,7 @@
; autospawn = yes
; daemon-binary = @PA_BINARY@
; extra-arguments = --log-target=syslog --exit-idle-time=5
; extra-arguments = --log-target=syslog
; cookie-file =

View file

@ -35,7 +35,7 @@
* \section overv_sec Overview
*
* The asynchronous API is the native interface to the PulseAudio library.
* It allows full access to all available functions. This also means that
* It allows full access to all available functionality. This however means that
* it is rather complex and can take some time to fully master.
*
* \section mainloop_sec Main Loop Abstraction
@ -64,8 +64,7 @@
* implementation where all of PulseAudio's
* internal handling runs in a separate
* thread.
* \li \subpage glib-mainloop - A wrapper around GLIB's main loop. Available
* for both GLIB 1.2 and GLIB 2.x.
* \li \subpage glib-mainloop - A wrapper around GLib's main loop.
*
* UNIX signals may be hooked to a main loop using the functions from
* \ref mainloop-signal.h. These rely only on the main loop abstraction

View file

@ -233,12 +233,11 @@ typedef enum pa_stream_flags {
PA_STREAM_START_MUTED = 4096, /**< Create in muted state. \since 0.9.11 */
PA_STREAM_ADJUST_LATENCY = 8192, /**< Try to adjust the latency of
* the sink/source based on the
* requested buffer metrics and
* adjust buffer metrics
* accordingly. \since 0.9.11 */
* accordingly. See pa_buffer_attr \since 0.9.11 */
} pa_stream_flags_t;
@ -248,53 +247,86 @@ typedef enum pa_stream_flags {
/** Playback and record buffer metrics */
typedef struct pa_buffer_attr {
uint32_t maxlength; /**< Maximum length of the
* buffer. Setting this to 0 will
* buffer. Setting this to (uint32_t) -1 will
* initialize this to the maximum value
* supported by server, which is
* recommended. */
uint32_t tlength; /**< Playback only: target length of the
* buffer. The server tries to assure
* that at least tlength bytes are always
* available in the buffer. It is
* recommended to set this to 0, which
* will initialize this to a value that
* is deemed sensible by the
* available in the per-stream
* server-side playback buffer. It is
* recommended to set this to (uint32_t)
* -1, which will initialize this to a
* value that is deemed sensible by the
* server. However, this value will
* default to something like 2s, i.e. for
* applications that have specific
* latency requirements this value should
* be set to the maximum latency that the
* application can deal with. */
* application can deal with. When
* PA_STREAM_ADJUST_LATENCY is not set
* this value will influence only the
* per-stream playback buffer size. When
* PA_STREAM_ADJUST_LATENCY is set the
* overall latency of the sink plus the
* playback buffer size is configured to
* this value. Set
* PA_STREAM_ADJUST_LATENCY if you are
* interested in adjusting the overall
* latency. Don't set it if you are
* interested in configuring the
* server-sider per-stream playback
* buffer size. */
uint32_t prebuf; /**< Playback only: pre-buffering. The
* server does not start with playback
* before at least prebug bytes are
* available in the buffer. It is
* recommended to set this to 0, which
* will initialize this to the same value
* as tlength, whatever that may be. */
* recommended to set this to (uint32_t)
* -1, which will initialize this to the
* same value as tlength, whatever that
* may be. Initialize to 0 to enable
* manual start/stop control of the
* stream. This means that playback will
* not stop on underrun and playback will
* not start automatically. Instead
* pa_stream_corked() needs to be called
* explicitly. If you set this value to 0
* you should also set
* PA_STREAM_START_CORKED. */
uint32_t minreq; /**< Playback only: minimum request. The
* server does not request less than
* minreq bytes from the client, instead
* waits until the buffer is free enough
* to request more bytes at once. It is
* recommended to set this to 0, which
* will initialize this to a value that
* is deemed sensible by the server. */
* recommended to set this to (uint32_t)
* -1, which will initialize this to a
* value that is deemed sensible by the
* server. This should be set to a value
* that gives PulseAudio enough time to
* move the data from the per-stream
* playback buffer into the hardware
* playback buffer. */
uint32_t fragsize; /**< Recording only: fragment size. The
* server sends data in blocks of
* fragsize bytes size. Large values
* deminish interactivity with other
* operations on the connection context
* but decrease control overhead. It is
* recommended to set this to 0, which
* will initialize this to a value that
* is deemed sensible by the
* recommended to set this to (uint32_t)
* -1, which will initialize this to a
* value that is deemed sensible by the
* server. However, this value will
* default to something like 2s, i.e. for
* applications that have specific
* latency requirements this value should
* be set to the maximum latency that the
* application can deal with. */
* application can deal with. If
* PA_STREAM_ADJUST_LATENCY is set the
* overall source latency will be
* adjusted according to this value. If
* it is not set the source latency is
* left unmodified. */
} pa_buffer_attr;
/** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */
@ -431,9 +463,9 @@ typedef struct pa_timing_info {
* PA_SEEK_RELATIVE_ON_READ
* instead. */
pa_usec_t configured_sink_usec; /**< The static configured latency for
pa_usec_t configured_sink_usec; /**< The configured latency for
* the sink. \since 0.9.11 */
pa_usec_t configured_source_usec; /**< The static configured latency for
pa_usec_t configured_source_usec; /**< The configured latency for
* the source. \since 0.9.11 */
int64_t since_underrun; /**< Bytes that were handed to the sink

View file

@ -130,8 +130,10 @@
*
* \subsection autoload_subsec Autoload Entries
*
* Modules can be autoloaded as a result of a client requesting a certain
* sink or source. This mapping between sink/source names and modules can be
* Modules can be autoloaded as a result of a client requesting a
* certain sink or source. Please note that autoloading is deprecated
* in 0.9.11. and is likely to be removed from the API in a later
* version. This mapping between sink/source names and modules can be
* queried from the server:
*
* \li By index - pa_context_get_autoload_info_by_index()
@ -191,7 +193,9 @@
*
* New module autoloading rules can be added, and existing can be removed
* using pa_context_add_autoload() and pa_context_remove_autoload_by_index()
* / pa_context_remove_autoload_by_name().
* / pa_context_remove_autoload_by_name(). Please note that autoloading is deprecated
* in 0.9.11. and is likely to be removed from the API in a later
* version.
*
* \subsection client_subsec Clients
*

View file

@ -36,19 +36,20 @@ PA_C_DECL_BEGIN
* media.artist "Guns'N'Roses"
* media.language "de_DE"
* media.filename
* media.icon
* media.icon_name
* media.icon Binary blob containing PNG icon data
* media.icon_name Name from XDG icon naming spec
* media.role video, music, game, event, phone, production, filter, abstract, stream
* event.id button-click, session-login
* event.id Name from XDG sound naming spec
* event.description "Button blabla clicked" for a11y
* event.mouse.x
* event.mouse.y
* event.mouse.hpos
* event.mouse.vpos
* event.mouse.button
* event.mouse.hpos Float formatted as string in range 0..1
* event.mouse.vpos Float formatted as string in range 0..1
* event.mouse.button Button number following X11 ordering
* window.name
* window.id
* window.icon
* window.icon_name
* window.id "org.gnome.rhytmbox.MainWindow"
* window.icon Binary blob containing PNG icon data
* window.icon_name Name from XDG icon naming spec
* window.x11.display
* window.x11.screen
* window.x11.monitor
@ -56,23 +57,23 @@ PA_C_DECL_BEGIN
* application.name "Rhythmbox Media Player"
* application.id "org.gnome.rhythmbox"
* application.version
* application.icon
* application.icon_name
* application.icon Binary blob containing PNG icon data
* application.icon_name Name from XDG icon naming spec
* application.language
* application.process.id
* application.process.binary
* application.process.user
* application.process.host
* device.string
* device.api oss, alsa, sunaudio
* device.api oss, alsa, sunaudio
* device.description
* device.bus_path
* device.serial
* device.vendor_product_id
* device.class sound, modem, monitor, filter, abstract
* device.form_factor laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
* device.connector isa, pci, usb, firewire, bluetooth
* device.access_mode mmap, mmap_rewrite, serial
* device.class sound, modem, monitor, filter, abstract
* device.form_factor laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
* device.connector isa, pci, usb, firewire, bluetooth
* device.access_mode mmap, mmap_rewrite, serial
* device.master_device
* device.bufferin.buffer_size
* device.bufferin.fragment_size
@ -86,6 +87,7 @@ PA_C_DECL_BEGIN
#define PA_PROP_MEDIA_ICON_NAME "media.icon_name"
#define PA_PROP_MEDIA_ROLE "media.role"
#define PA_PROP_EVENT_ID "event.id"
#define PA_PROP_EVENT_DESCRIPTION "event.description"
#define PA_PROP_EVENT_MOUSE_X "event.mouse.x"
#define PA_PROP_EVENT_MOUSE_Y "event.mouse.y"
#define PA_PROP_EVENT_MOUSE_HPOS "event.mouse.hpos"

View file

@ -89,17 +89,17 @@
*
* \section thread_sec Threads
*
* The PulseAudio client libraries are not designed to be used in a
* heavily threaded environment. They are however designed to be reentrant
* safe.
* The PulseAudio client libraries are not designed to be directly
* thread-safe. They are however designed to be reentrant and
* threads-aware.
*
* To use a the libraries in a threaded environment, you must assure that
* To use the libraries in a threaded environment, you must assure that
* all objects are only used in one thread at a time. Normally, this means
* that all objects belonging to a single context must be accessed from the
* same thread.
*
* The included main loop implementation is also not thread safe. Take care
* to make sure event lists are not manipulated when any other code is
* to make sure event objects are not manipulated when any other code is
* using the main loop.
*
* \section pkgconfig pkg-config

View file

@ -52,7 +52,7 @@
* \li PA_SAMPLE_S32LE - Signed 32 bit integer PCM, little endian.
* \li PA_SAMPLE_S32BE - Signed 32 bit integer PCM, big endian.
*
* The floating point sample formats have the range from -1 to 1.
* The floating point sample formats have the range from -1.0 to 1.0.
*
* The sample formats that are sensitive to endianness have convenience
* macros for native endian (NE), and reverse endian (RE).

View file

@ -70,35 +70,85 @@
*
* \subsection bufattr_subsec Buffer Attributes
*
* Playback and record streams always have a server side buffer as
* part of the data flow. The size of this buffer strikes a
* compromise between low latency and sensitivity for buffer
* Playback and record streams always have a server-side buffer as
* part of the data flow. The size of this buffer needs to be chosen
* in a compromise between low latency and sensitivity for buffer
* overflows/underruns.
*
* The buffer metrics may be controlled by the application. They are
* described with a pa_buffer_attr structure which contains a number
* of fields:
*
* \li maxlength - The absolute maximum number of bytes that can be stored in
* the buffer. If this value is exceeded then data will be
* lost.
* \li tlength - The target length of a playback buffer. The server will only
* send requests for more data as long as the buffer has less
* than this number of bytes of data.
* \li prebuf - Number of bytes that need to be in the buffer before
* playback will commence. Start of playback can be forced using
* pa_stream_trigger() even though the prebuffer size hasn't been
* reached. If a buffer underrun occurs, this prebuffering will be
* again enabled. If the playback shall never stop in case of a buffer
* underrun, this value should be set to 0. In that case the read
* index of the output buffer overtakes the write index, and hence the
* fill level of the buffer is negative.
* \li minreq - Minimum free number of the bytes in the playback buffer before
* the server will request more data.
* \li fragsize - Maximum number of bytes that the server will push in one
* chunk for record streams.
* \li maxlength - The absolute maximum number of bytes that can be
* stored in the buffer. If this value is exceeded
* then data will be lost. It is recommended to pass
* (uint32_t) -1 here which will cause the server to
* fill in the maximum possible value.
*
* The server side playback buffers are indexed by a write and a read
* \li tlength - The target fill level of the playback buffer. The
* server will only send requests for more data as long
* as the buffer has less than this number of bytes of
* data. If you pass (uint32_t) -1 (which is
* recommended) here the server will choose the longest
* target buffer fill level possible to minimize the
* number of necessary wakeups and maximize drop-out
* safety. This can exceed 2s of buffering. For
* low-latency applications or applications where
* latency matters you should pass a proper value here.
*
* \li prebuf - Number of bytes that need to be in the buffer before
* playback will commence. Start of playback can be
* forced using pa_stream_trigger() even though the
* prebuffer size hasn't been reached. If a buffer
* underrun occurs, this prebuffering will be again
* enabled. If the playback shall never stop in case of a
* buffer underrun, this value should be set to 0. In
* that case the read index of the output buffer
* overtakes the write index, and hence the fill level of
* the buffer is negative. If you pass (uint32_t) -1 here
* (which is recommended) the server will choose the same
* value as tlength here.
*
* \li minreq - Minimum free number of the bytes in the playback
* buffer before the server will request more data. It is
* recommended to fill in (uint32_t) -1 here. This value
* influences how much time the sound server has to move
* data from the per-stream server-side playback buffer
* to the hardware playback buffer.
*
* \li fragsize - Maximum number of bytes that the server will push in
* one chunk for record streams. If you pass (uint32_t)
* -1 (which is recommended) here, the server will
* choose the longest fragment setting possible to
* minimize the number of necessary wakeups and
* maximize drop-out safety. This can exceed 2s of
* buffering. For low-latency applications or
* applications where latency matters you should pass a
* proper value here.
*
* If PA_STREAM_ADJUST_LATENCY is set, then the tlength/fragsize
* parameters will be interpreted slightly differently than described
* above when passed to pa_stream_connect_record() and
* pa_stream_connect_playback(): the overall latency that is comprised
* of both the server side playback buffer length, the hardware
* playback buffer length and additional latencies will be adjusted in
* a way that it matches tlength resp. fragsize. Set
* PA_STREAM_ADJUST_LATENCY if you want to control the overall
* playback latency for your stream. Unset it if you want to control
* only the latency induced by the server-side, rewritable playback
* buffer. The server will try to fulfill the clients latency requests
* as good as possible. However if the underlying hardware cannot
* change the hardware buffer length or only in a limited range, the
* actually resulting latency might be different from what the client
* requested. Thus, for synchronization clients always need to check
* the actual measured latency via pa_stream_get_latency() or a
* similar call, and not make any assumptions. about the latency
* available. The function pa_stream_get_buffer_attr() will always
* return the actual size of the server-side per-stream buffer in
* tlength/fragsize, regardless whether PA_STREAM_ADJUST_LATENCY is
* set or not.
*
* The server-side per-stream playback buffers are indexed by a write and a read
* index. The application writes to the write index and the sound
* device reads from the read index. The read index is increased
* monotonically, while the write index may be freely controlled by
@ -196,10 +246,10 @@
* accordingly.
*
* The raw timing data in the pa_timing_info structure is usually hard
* to deal with. Therefore a more simplistic interface is available:
* to deal with. Therefore a simpler interface is available:
* you can call pa_stream_get_time() or pa_stream_get_latency(). The
* former will return the current playback time of the hardware since
* the stream has been started. The latter returns the time a sample
* the stream has been started. The latter returns the overall time a sample
* that you write now takes to be played by the hardware. These two
* functions base their calculations on the same data that is returned
* by pa_stream_get_timing_info(). Hence the same rules for keeping
@ -512,9 +562,14 @@ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s);
/** Return a pointer to the stream's channel map. */
const pa_channel_map* pa_stream_get_channel_map(pa_stream *s);
/** Return the buffer metrics of the stream. Only valid after the
* stream has been connected successfuly and if the server is at least
* PulseAudio 0.9. \since 0.9.0 */
/** Return the per-stream server-side buffer metrics of the
* stream. Only valid after the stream has been connected successfuly
* and if the server is at least PulseAudio 0.9. This will return the
* actual configured buffering metrics, which may differ from what was
* requested during pa_stream_connect_record() or
* pa_stream_connect_playback(). This call will always return the
* actually per-stream server-side buffer metrics, regardless whether
* PA_STREAM_ADJUST_LATENCY is set or not. \since 0.9.0 */
const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s);
/** Change the buffer metrics of the stream during playback. The
@ -522,7 +577,9 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s);
* requested. The selected metrics may be queried with
* pa_stream_get_buffer_attr() as soon as the callback is called. Only
* valid after the stream has been connected successfully and if the
* server is at least PulseAudio 0.9.8. \since 0.9.8 */
* server is at least PulseAudio 0.9.8. Please be aware of the
* slightly different semantics of the call depending whether
* PA_STREAM_ADJUST_LATENCY is set or not. \since 0.9.8 */
pa_operation *pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata);
/** Change the stream sampling rate during playback. You need to pass

View file

@ -177,7 +177,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
#else
{
mode_t u;
u = umask(~m);
u = umask((~m) & 0777);
r = mkdir(dir, m);
umask(u);
}
@ -1887,17 +1887,21 @@ int pa_close_allv(const int except_fds[]) {
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return -1;
for (fd = 0; fd < (int) rl.rlim_max; fd++) {
for (fd = 3; fd < (int) rl.rlim_max; fd++) {
int i;
pa_bool_t found;
if (fd <= 3)
found = FALSE;
for (i = 0; except_fds[i] >= 0; i++)
if (except_fds[i] == fd) {
found = TRUE;
break;
}
if (found)
continue;
for (i = 0; except_fds[i] >= 0; i++)
if (except_fds[i] == fd)
continue;
if (close(fd) < 0 && errno != EBADF)
if (pa_close(fd) < 0 && errno != EBADF)
return -1;
}
@ -1972,10 +1976,11 @@ int pa_reset_sigs(int except, ...) {
i = 0;
if (except >= 1) {
int sig;
p[i++] = except;
while ((p[i++] = va_arg(ap, int)) >= 0)
;
while ((sig = va_arg(ap, int)) >= 0)
sig = p[i++];
}
p[i] = -1;

View file

@ -261,22 +261,31 @@ pa_sink* pa_sink_new(
static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
int ret;
pa_bool_t suspend_change;
pa_sink_state_t original_state;
pa_assert(s);
if (s->state == state)
return 0;
original_state = s->state;
suspend_change =
(s->state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
(PA_SINK_IS_OPENED(s->state) && state == PA_SINK_SUSPENDED);
(original_state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
(PA_SINK_IS_OPENED(original_state) && state == PA_SINK_SUSPENDED);
if (s->set_state)
if ((ret = s->set_state(s, state)) < 0)
return -1;
return ret;
if (s->asyncmsgq)
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
if (s->set_state)
s->set_state(s, original_state);
return ret;
}
s->state = state;

View file

@ -224,22 +224,31 @@ pa_source* pa_source_new(
static int source_set_state(pa_source *s, pa_source_state_t state) {
int ret;
pa_bool_t suspend_change;
pa_source_state_t original_state;
pa_assert(s);
if (s->state == state)
return 0;
original_state = s->state;
suspend_change =
(s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
(PA_SOURCE_IS_OPENED(s->state) && state == PA_SOURCE_SUSPENDED);
(original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
(PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
if (s->set_state)
if ((ret = s->set_state(s, state)) < 0)
return -1;
return ret;
if (s->asyncmsgq)
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
if (s->set_state)
s->set_state(s, original_state);
return ret;
}
s->state = state;