mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
Merge Pierre's changes
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@445 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
80ae72ce45
commit
f7a99e9047
65 changed files with 3786 additions and 1050 deletions
18
Makefile.am
18
Makefile.am
|
|
@ -17,11 +17,11 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
# USA.
|
# USA.
|
||||||
|
|
||||||
EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
|
EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
|
||||||
SUBDIRS=polyp doc libltdl
|
SUBDIRS=libltdl polyp doc
|
||||||
|
|
||||||
MAINTAINERCLEANFILES=README
|
MAINTAINERCLEANFILES =
|
||||||
noinst_DATA = README
|
noinst_DATA =
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc
|
pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc
|
||||||
|
|
@ -36,10 +36,16 @@ pkgconfig_DATA += \
|
||||||
polyplib-glib12-mainloop.pc
|
polyplib-glib12-mainloop.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_LYNX
|
||||||
|
EXTRA_DIST += README
|
||||||
|
MAINTAINERCLEANFILES += README
|
||||||
|
noinst_DATA += README
|
||||||
|
|
||||||
README:
|
README:
|
||||||
rm -f README
|
rm -f README
|
||||||
$(MAKE) -C doc README
|
$(MAKE) -C doc README
|
||||||
cd $(srcdir) && ln -s doc/README README
|
cd $(srcdir) && ln -s doc/README README
|
||||||
|
endif
|
||||||
|
|
||||||
homepage: all dist doxygen
|
homepage: all dist doxygen
|
||||||
test -d $$HOME/homepage/private
|
test -d $$HOME/homepage/private
|
||||||
|
|
@ -49,8 +55,8 @@ homepage: all dist doxygen
|
||||||
cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen
|
cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen
|
||||||
cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html
|
cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html
|
||||||
|
|
||||||
distcleancheck:
|
#distcleancheck:
|
||||||
@:
|
# @:
|
||||||
|
|
||||||
doxygen:
|
doxygen:
|
||||||
$(MAKE) -C doxygen doxygen
|
$(MAKE) -C doxygen doxygen
|
||||||
|
|
|
||||||
41
acinclude.m4
41
acinclude.m4
|
|
@ -197,3 +197,44 @@ else
|
||||||
fi
|
fi
|
||||||
AC_LANG_RESTORE
|
AC_LANG_RESTORE
|
||||||
])dnl ACX_PTHREAD
|
])dnl ACX_PTHREAD
|
||||||
|
|
||||||
|
AC_DEFUN([AC_CHECK_DEFINE],[
|
||||||
|
AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl
|
||||||
|
AC_CACHE_CHECK([for $1 defined], ac_var,
|
||||||
|
AC_TRY_COMPILE([#include <$2>],[
|
||||||
|
#ifdef $1
|
||||||
|
int ok;
|
||||||
|
#else
|
||||||
|
choke me
|
||||||
|
#endif
|
||||||
|
],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no)))
|
||||||
|
AS_IF([test AS_VAR_GET(ac_var) != "no"], [$3], [$4])dnl
|
||||||
|
AS_VAR_POPDEF([ac_var])dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([ACX_LIBWRAP], [
|
||||||
|
LIBWRAP_LIBS=
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lwrap"
|
||||||
|
AC_MSG_CHECKING([for tcpwrap library and headers])
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
AC_LANG_PROGRAM(
|
||||||
|
[#include <tcpd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
int allow_severity = LOG_INFO;
|
||||||
|
int deny_severity = LOG_WARNING;],
|
||||||
|
[struct request_info *req;
|
||||||
|
return hosts_access (req);]),
|
||||||
|
[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?])
|
||||||
|
LIBWRAP_LIBS="-lwrap"
|
||||||
|
AC_MSG_RESULT(yes)],
|
||||||
|
[AC_MSG_RESULT(no)])
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([ACX_LIRC], [
|
||||||
|
LIRC_CFLAGS=
|
||||||
|
LIRC_LIBS=
|
||||||
|
AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1
|
||||||
|
LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0)
|
||||||
|
])
|
||||||
|
|
|
||||||
454
configure.ac
454
configure.ac
|
|
@ -35,166 +35,29 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then
|
||||||
ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
|
ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Checks for programs.
|
#### Checks for programs. ####
|
||||||
|
|
||||||
|
# CC
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
||||||
# libtool stuff
|
|
||||||
AC_LIBLTDL_INSTALLABLE
|
|
||||||
AC_SUBST(LTDLINCL)
|
|
||||||
AC_SUBST(LIBLTDL)
|
|
||||||
AC_LIBTOOL_DLOPEN
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_CONFIG_SUBDIRS(libltdl)
|
|
||||||
|
|
||||||
if test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
|
|
||||||
AC_MSG_ERROR([[
|
|
||||||
|
|
||||||
*** Cannot find the libltdl development files.
|
|
||||||
*** Maybe you need to install the libltdl-dev package.
|
|
||||||
]])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Checks for header files.
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h])
|
|
||||||
|
|
||||||
ACX_PTHREAD
|
|
||||||
AC_PATH_XTRA
|
|
||||||
|
|
||||||
HAVE_X11=0
|
|
||||||
test "x$no_x" != "xyes" && HAVE_X11=1
|
|
||||||
AC_SUBST(HAVE_X11)
|
|
||||||
AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes")
|
|
||||||
if test "x$no_x" != "xyes" ; then
|
|
||||||
AC_DEFINE([HAVE_X11], 1, [Have X11])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
AC_C_CONST
|
|
||||||
AC_TYPE_PID_T
|
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_TYPE_OFF_T
|
|
||||||
AC_HEADER_TIME
|
|
||||||
|
|
||||||
# Checks for library functions.
|
|
||||||
AC_FUNC_FORK
|
|
||||||
AC_PROG_GCC_TRADITIONAL
|
AC_PROG_GCC_TRADITIONAL
|
||||||
AC_FUNC_LSTAT
|
|
||||||
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
|
|
||||||
AC_FUNC_MALLOC
|
|
||||||
AC_FUNC_MEMCMP
|
|
||||||
AC_FUNC_MMAP
|
|
||||||
AC_FUNC_REALLOC
|
|
||||||
AC_FUNC_SETPGRP
|
|
||||||
AC_FUNC_VPRINTF
|
|
||||||
AC_FUNC_CLOSEDIR_VOID
|
|
||||||
AC_FUNC_SELECT_ARGTYPES
|
|
||||||
AC_TYPE_SIGNAL
|
|
||||||
AC_TYPE_UID_T
|
|
||||||
AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp ftruncate select])
|
|
||||||
AC_CHECK_LIB(m, pow)
|
|
||||||
AC_CHECK_FUNCS(pow)
|
|
||||||
AC_FUNC_STAT
|
|
||||||
AC_HEADER_SYS_WAIT
|
|
||||||
AC_HEADER_DIRENT
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
|
||||||
AC_FUNC_GETGROUPS
|
|
||||||
|
|
||||||
AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
|
|
||||||
AC_SUBST(CAP_LIBS)
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/capability.h)
|
|
||||||
|
|
||||||
AC_CHECK_FUNCS(setresuid)
|
|
||||||
AC_CHECK_FUNCS(setreuid)
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ])
|
|
||||||
AC_SUBST(LIBSAMPLERATE_CFLAGS)
|
|
||||||
AC_SUBST(LIBSAMPLERATE_LIBS)
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
|
|
||||||
AC_SUBST(LIBSNDFILE_CFLAGS)
|
|
||||||
AC_SUBST(LIBSNDFILE_LIBS)
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0])
|
|
||||||
AC_SUBST(ASOUNDLIB_CFLAGS)
|
|
||||||
AC_SUBST(ASOUNDLIB_LIBS)
|
|
||||||
AC_SUBST(HAVE_ALSA)
|
|
||||||
AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0)
|
|
||||||
AC_SUBST(GLIB20_CFLAGS)
|
|
||||||
AC_SUBST(GLIB20_LIBS)
|
|
||||||
AC_SUBST(HAVE_GLIB20)
|
|
||||||
AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0)
|
|
||||||
AC_SUBST(GLIB12_CFLAGS)
|
|
||||||
AC_SUBST(GLIB12_LIBS)
|
|
||||||
AC_SUBST(HAVE_GLIB12)
|
|
||||||
AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0)
|
|
||||||
AC_SUBST(HOWL_CFLAGS)
|
|
||||||
AC_SUBST(HOWL_LIBS)
|
|
||||||
AC_SUBST(HAVE_HOWL)
|
|
||||||
AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0)
|
|
||||||
AC_SUBST(LIBASYNCNS_CFLAGS)
|
|
||||||
AC_SUBST(LIBASYNCNS_LIBS)
|
|
||||||
AC_SUBST(HAVE_LIBASYNCNS)
|
|
||||||
AM_CONDITIONAL([HAVE_LIBASYNCNS], [test "x$HAVE_LIBASYNCNS" = x1])
|
|
||||||
|
|
||||||
if test "x$HAVE_LIBASYNCNS" != "x0" ; then
|
|
||||||
AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_PATH_PROG([M4], [m4 gm4], [no])
|
|
||||||
if test "x$M4" = xno ; then
|
|
||||||
AC_MSG_ERROR([m4 missing])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([for tcpwrap library and headers])
|
|
||||||
LIBWRAP_LIBS=
|
|
||||||
saved_LIBS="$LIBS"
|
|
||||||
LIBS="$LIBS -lwrap"
|
|
||||||
AC_LINK_IFELSE(
|
|
||||||
AC_LANG_PROGRAM(
|
|
||||||
[#include <tcpd.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
int allow_severity = LOG_INFO;
|
|
||||||
int deny_severity = LOG_WARNING;],
|
|
||||||
[struct request_info *req;
|
|
||||||
return hosts_access (req);]),
|
|
||||||
[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?])
|
|
||||||
LIBWRAP_LIBS="-lwrap"
|
|
||||||
AC_MSG_RESULT(yes)],
|
|
||||||
[AC_MSG_RESULT(no)])
|
|
||||||
AC_SUBST(LIBWRAP_LIBS)
|
|
||||||
LIBS="$saved_LIBS"
|
|
||||||
|
|
||||||
LIRC_CFLAGS=
|
|
||||||
LIRC_LIBS=
|
|
||||||
AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1
|
|
||||||
LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0)
|
|
||||||
AC_SUBST(LIRC_CFLAGS)
|
|
||||||
AC_SUBST(LIRC_LIBS)
|
|
||||||
AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
|
|
||||||
|
|
||||||
AC_CHECK_HEADER(linux/input.h,HAVE_EVDEV=1,HAVE_EVDEV=0)
|
|
||||||
AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = x1])
|
|
||||||
|
|
||||||
# If using GCC specify some additional parameters
|
# If using GCC specify some additional parameters
|
||||||
if test "x$GCC" = "xyes" ; then
|
if test "x$GCC" = "xyes" ; then
|
||||||
CFLAGS="$CFLAGS -pipe -W -Wall -pedantic"
|
CFLAGS="$CFLAGS -pipe -W -Wall -pedantic"
|
||||||
|
|
||||||
AC_LANG_CONFTEST([int main() {}])
|
AC_LANG_CONFTEST([int main() {}])
|
||||||
$CC -c conftest.c -std=c99 -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter"
|
$CC -c conftest.c -std=gnu9x -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=gnu9x -Wno-unused-parameter"
|
||||||
rm -f conftest.o
|
rm -f conftest.o
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# M4
|
||||||
|
|
||||||
|
AC_PATH_PROG([M4], [m4 gm4], [no])
|
||||||
|
if test "x$M4" = xno ; then
|
||||||
|
AC_MSG_ERROR([m4 missing])
|
||||||
|
fi
|
||||||
|
|
||||||
# LYNX documentation generation
|
# LYNX documentation generation
|
||||||
AC_ARG_ENABLE(lynx,
|
AC_ARG_ENABLE(lynx,
|
||||||
AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation),
|
AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation),
|
||||||
|
|
@ -212,9 +75,296 @@ if test x$lynx = xyes ; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes])
|
AM_CONDITIONAL([USE_LYNX], [test "x$have_lynx" = xyes])
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false)
|
#### libtool stuff ####
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-browse.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html])
|
AC_LTDL_ENABLE_INSTALL
|
||||||
|
AC_LIBLTDL_INSTALLABLE
|
||||||
|
AC_SUBST(LTDLINCL)
|
||||||
|
AC_SUBST(LIBLTDL)
|
||||||
|
AC_LIBTOOL_DLOPEN
|
||||||
|
AC_LIBTOOL_WIN32_DLL
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
AC_CONFIG_SUBDIRS(libltdl)
|
||||||
|
|
||||||
|
if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
|
||||||
|
AC_MSG_ERROR([[
|
||||||
|
|
||||||
|
*** Cannot find the libltdl development files.
|
||||||
|
*** Maybe you need to install the libltdl-dev package.
|
||||||
|
]])
|
||||||
|
fi
|
||||||
|
|
||||||
|
#### Determine build environment ####
|
||||||
|
|
||||||
|
os_is_win32=0
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
mingw*)
|
||||||
|
AC_DEFINE([OS_IS_WIN32], 1, [Build target is Windows.])
|
||||||
|
os_is_win32=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1")
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# Basic environment checks #
|
||||||
|
###################################
|
||||||
|
|
||||||
|
#### Checks for header files. ####
|
||||||
|
|
||||||
|
# ISO
|
||||||
|
AC_HEADER_STDC
|
||||||
|
|
||||||
|
# POSIX
|
||||||
|
AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
|
||||||
|
netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \
|
||||||
|
sys/resource.h sys/select.h sys/socket.h sys/wait.h \
|
||||||
|
syslog.h])
|
||||||
|
AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0])
|
||||||
|
AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_REGEX, test "x$HAVE_REGEX" = "x1")
|
||||||
|
AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1")
|
||||||
|
|
||||||
|
# XPG4-UNIX
|
||||||
|
AC_CHECK_HEADERS([sys/poll.h])
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"])
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
|
||||||
|
|
||||||
|
# Other
|
||||||
|
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||||
|
|
||||||
|
#### Typdefs, structures, etc. ####
|
||||||
|
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_CHECK_TYPES(ssize_t, , [AC_DEFINE([ssize_t], [signed long],
|
||||||
|
[Define ssize_t if it is not done by the standard libs.])])
|
||||||
|
AC_TYPE_OFF_T
|
||||||
|
AC_TYPE_SIGNAL
|
||||||
|
AC_TYPE_UID_T
|
||||||
|
|
||||||
|
AC_CHECK_DEFINE([SIGXCPU], [signal.h], [HAVE_SIGXCPU=1], [HAVE_SIGXCPU=0])
|
||||||
|
AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1")
|
||||||
|
|
||||||
|
# Solaris lacks this
|
||||||
|
AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [],
|
||||||
|
[AC_DEFINE([INADDR_NONE], [0xffffffff], [Define INADDR_NONE if not found in <netinet/in.h>])])
|
||||||
|
|
||||||
|
#### Check for libs ####
|
||||||
|
|
||||||
|
# ISO
|
||||||
|
AC_CHECK_LIB([m], [pow])
|
||||||
|
|
||||||
|
# POSIX
|
||||||
|
AC_CHECK_LIB([rt], [sched_setscheduler])
|
||||||
|
|
||||||
|
# BSD
|
||||||
|
AC_CHECK_LIB([socket], [connect])
|
||||||
|
|
||||||
|
# Non-standard
|
||||||
|
|
||||||
|
# This magic is needed so we do not needlessly add static libs to the win32
|
||||||
|
# build, disabling its ability to make dlls.
|
||||||
|
AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
|
||||||
|
|
||||||
|
#### Check for functions ####
|
||||||
|
|
||||||
|
# POSIX
|
||||||
|
AC_FUNC_FORK
|
||||||
|
AC_FUNC_GETGROUPS
|
||||||
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
|
AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
|
||||||
|
inet_ntop nanosleep setpgid setsid sigaction sleep])
|
||||||
|
AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
|
||||||
|
|
||||||
|
# X/OPEN
|
||||||
|
AC_CHECK_FUNCS([readlink])
|
||||||
|
|
||||||
|
# SUSv2
|
||||||
|
AC_CHECK_FUNCS([ctime_r usleep])
|
||||||
|
|
||||||
|
# BSD
|
||||||
|
AC_CHECK_FUNCS([lstat])
|
||||||
|
|
||||||
|
# Non-standard
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(setresuid)
|
||||||
|
AC_CHECK_FUNCS(setreuid)
|
||||||
|
|
||||||
|
#### POSIX threads ####
|
||||||
|
|
||||||
|
ACX_PTHREAD
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# External libraries #
|
||||||
|
###################################
|
||||||
|
|
||||||
|
#### X11 (optional) ####
|
||||||
|
|
||||||
|
HAVE_X11=0
|
||||||
|
|
||||||
|
# The macro tests the host, not the build target
|
||||||
|
if test "x$os_is_win32" != "x1" ; then
|
||||||
|
AC_PATH_XTRA
|
||||||
|
test "x$no_x" != "xyes" && HAVE_X11=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(HAVE_X11)
|
||||||
|
AM_CONDITIONAL(HAVE_X11, test "x$HAVE_X11" = "x1")
|
||||||
|
if test "x$HAVE_X11" = "x1" ; then
|
||||||
|
AC_DEFINE([HAVE_X11], 1, [Have X11])
|
||||||
|
fi
|
||||||
|
|
||||||
|
#### Capabilities (optional) ####
|
||||||
|
|
||||||
|
CAP_LIBS=''
|
||||||
|
|
||||||
|
AC_ARG_WITH(
|
||||||
|
[caps],
|
||||||
|
AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.]))
|
||||||
|
|
||||||
|
if test "x${with_caps}" != "xno"; then
|
||||||
|
AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
|
||||||
|
AC_CHECK_HEADERS([sys/capability.h])
|
||||||
|
fi
|
||||||
|
AC_SUBST(CAP_LIBS)
|
||||||
|
|
||||||
|
#### Sample rate conversion ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ])
|
||||||
|
AC_SUBST(LIBSAMPLERATE_CFLAGS)
|
||||||
|
AC_SUBST(LIBSAMPLERATE_LIBS)
|
||||||
|
|
||||||
|
#### Sound file ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
|
||||||
|
AC_SUBST(LIBSNDFILE_CFLAGS)
|
||||||
|
AC_SUBST(LIBSNDFILE_LIBS)
|
||||||
|
|
||||||
|
#### OSS support (optional) ####
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([sys/soundcard.h], [HAVE_OSS=1], [HAVE_OSS=0])
|
||||||
|
AC_SUBST(HAVE_OSS)
|
||||||
|
AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1])
|
||||||
|
|
||||||
|
#### ALSA support (optional) ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0])
|
||||||
|
AC_SUBST(ASOUNDLIB_CFLAGS)
|
||||||
|
AC_SUBST(ASOUNDLIB_LIBS)
|
||||||
|
AC_SUBST(HAVE_ALSA)
|
||||||
|
AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
|
||||||
|
|
||||||
|
#### Solaris audio support (optional) ####
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([sys/audio.h], [HAVE_SOLARIS=1], [HAVE_SOLARIS=0])
|
||||||
|
AC_SUBST(HAVE_SOLARIS)
|
||||||
|
AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1])
|
||||||
|
|
||||||
|
#### GLib 2 support (optional) ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0)
|
||||||
|
AC_SUBST(GLIB20_CFLAGS)
|
||||||
|
AC_SUBST(GLIB20_LIBS)
|
||||||
|
AC_SUBST(HAVE_GLIB20)
|
||||||
|
AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1])
|
||||||
|
|
||||||
|
#### GLib 1 support (optional) ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0)
|
||||||
|
AC_SUBST(GLIB12_CFLAGS)
|
||||||
|
AC_SUBST(GLIB12_LIBS)
|
||||||
|
AC_SUBST(HAVE_GLIB12)
|
||||||
|
AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1])
|
||||||
|
|
||||||
|
#### Howl support (optional) ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0)
|
||||||
|
AC_SUBST(HOWL_CFLAGS)
|
||||||
|
AC_SUBST(HOWL_LIBS)
|
||||||
|
AC_SUBST(HAVE_HOWL)
|
||||||
|
AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1])
|
||||||
|
|
||||||
|
#### Async DNS support (optional) ####
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0)
|
||||||
|
AC_SUBST(LIBASYNCNS_CFLAGS)
|
||||||
|
AC_SUBST(LIBASYNCNS_LIBS)
|
||||||
|
AC_SUBST(HAVE_LIBASYNCNS)
|
||||||
|
AM_CONDITIONAL([HAVE_LIBASYNCNS], [test "x$HAVE_LIBASYNCNS" = x1])
|
||||||
|
|
||||||
|
if test "x$HAVE_LIBASYNCNS" != "x0" ; then
|
||||||
|
AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?])
|
||||||
|
fi
|
||||||
|
|
||||||
|
#### TCP wrappers (optional) ####
|
||||||
|
|
||||||
|
ACX_LIBWRAP
|
||||||
|
AC_SUBST(LIBWRAP_LIBS)
|
||||||
|
|
||||||
|
#### LIRC support (optional) ####
|
||||||
|
|
||||||
|
ACX_LIRC
|
||||||
|
AC_SUBST(LIRC_CFLAGS)
|
||||||
|
AC_SUBST(LIRC_LIBS)
|
||||||
|
AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# Output #
|
||||||
|
###################################
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(
|
||||||
|
[static-bins],
|
||||||
|
AC_HELP_STRING([--enable-static-bins],[Statically link executables.]),
|
||||||
|
[STATIC_BINS=1], [STATIC_BINS=0])
|
||||||
|
AM_CONDITIONAL([STATIC_BINS], [test "x$STATIC_BINS" = "x1"])
|
||||||
|
|
||||||
|
AC_ARG_WITH(
|
||||||
|
[preopen-mods],
|
||||||
|
AC_HELP_STRING([--with-preopen-mods],[Modules to preopen in daemon (default: all).]),
|
||||||
|
[PREOPEN_MODS=$withval], [PREOPEN_MODS="all"])
|
||||||
|
AM_CONDITIONAL([PREOPEN_MODS], [test "x$PREOPEN_MODS" != "xall"])
|
||||||
|
if test "x$PREOPEN_MODS" != "xall" ; then
|
||||||
|
tmpLIBS=""
|
||||||
|
for mod in $PREOPEN_MODS; do
|
||||||
|
tmpLIBS="$tmpLIBS module-$mod.la"
|
||||||
|
done
|
||||||
|
PREOPEN_MODS="$tmpLIBS"
|
||||||
|
AC_SUBST(PREOPEN_MODS)
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
polyp/Makefile
|
||||||
|
polyplib.pc
|
||||||
|
polyplib-simple.pc
|
||||||
|
polyplib-mainloop.pc
|
||||||
|
polyplib-browse.pc
|
||||||
|
polyplib-error.pc
|
||||||
|
polyplib-glib-mainloop.pc
|
||||||
|
polyplib-glib12-mainloop.pc
|
||||||
|
doc/Makefile
|
||||||
|
doc/README.html
|
||||||
|
doc/cli.html
|
||||||
|
doc/daemon.html
|
||||||
|
doc/modules.html
|
||||||
|
doxygen/Makefile
|
||||||
|
doxygen/doxygen.conf
|
||||||
|
polyp/polyplib-version.h
|
||||||
|
doc/FAQ.html
|
||||||
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
# along with polypaudio; if not, write to the Free Software Foundation,
|
# along with polypaudio; if not, write to the Free Software Foundation,
|
||||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
|
||||||
noinst_DATA = README.html cli.html modules.html daemon.html README
|
noinst_DATA = README.html cli.html modules.html daemon.html
|
||||||
EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in
|
EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html
|
MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html
|
||||||
|
|
@ -26,6 +26,7 @@ if USE_LYNX
|
||||||
README: README.html
|
README: README.html
|
||||||
lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@
|
lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@
|
||||||
|
|
||||||
|
noinst_DATA += README
|
||||||
CLEANFILES += README
|
CLEANFILES += README
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
1582
polyp/Makefile.am
1582
polyp/Makefile.am
File diff suppressed because it is too large
Load diff
|
|
@ -63,7 +63,7 @@ static int generate(int fd, void *ret_data, size_t length) {
|
||||||
static int load(const char *fn, void *data, size_t length) {
|
static int load(const char *fn, void *data, size_t length) {
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int writable = 1;
|
int writable = 1;
|
||||||
int unlock = 0, ret;
|
int unlock = 0, ret = -1;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
assert(fn && data && length);
|
assert(fn && data && length);
|
||||||
|
|
||||||
|
|
@ -128,12 +128,20 @@ int pa_authkey_load(const char *path, void *data, size_t length) {
|
||||||
static const char *normalize_path(const char *fn, char *s, size_t l) {
|
static const char *normalize_path(const char *fn, char *s, size_t l) {
|
||||||
assert(fn && s && l > 0);
|
assert(fn && s && l > 0);
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
if (fn[0] != '/') {
|
if (fn[0] != '/') {
|
||||||
|
#else
|
||||||
|
if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
|
||||||
|
#endif
|
||||||
char homedir[PATH_MAX];
|
char homedir[PATH_MAX];
|
||||||
if (!pa_get_home_dir(homedir, sizeof(homedir)))
|
if (!pa_get_home_dir(homedir, sizeof(homedir)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
snprintf(s, l, "%s/%s", homedir, fn);
|
snprintf(s, l, "%s/%s", homedir, fn);
|
||||||
|
#else
|
||||||
|
snprintf(s, l, "%s\\%s", homedir, fn);
|
||||||
|
#endif
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "caps.h"
|
#include "caps.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GETUID
|
||||||
|
|
||||||
/* Drop root rights when called SUID root */
|
/* Drop root rights when called SUID root */
|
||||||
void pa_drop_root(void) {
|
void pa_drop_root(void) {
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
|
|
@ -54,6 +56,13 @@ void pa_drop_root(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void pa_drop_root(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_CAPABILITY_H
|
#ifdef HAVE_SYS_CAPABILITY_H
|
||||||
|
|
||||||
/* Limit capabilities set to CAPSYS_NICE */
|
/* Limit capabilities set to CAPSYS_NICE */
|
||||||
|
|
|
||||||
|
|
@ -641,7 +641,11 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct
|
||||||
|
|
||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
|
#ifdef HAVE_CTIME_R
|
||||||
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
|
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
|
||||||
|
#else
|
||||||
|
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) {
|
for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
USA.
|
USA.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -33,11 +37,21 @@
|
||||||
#include "authkey.h"
|
#include "authkey.h"
|
||||||
|
|
||||||
#ifndef DEFAULT_CONFIG_DIR
|
#ifndef DEFAULT_CONFIG_DIR
|
||||||
#define DEFAULT_CONFIG_DIR "/etc/polypaudio"
|
# ifndef OS_IS_WIN32
|
||||||
|
# define DEFAULT_CONFIG_DIR "/etc/polypaudio"
|
||||||
|
# else
|
||||||
|
# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf"
|
#ifndef OS_IS_WIN32
|
||||||
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf"
|
# define PATH_SEP "/"
|
||||||
|
#else
|
||||||
|
# define PATH_SEP "\\"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
|
||||||
|
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "client.conf"
|
||||||
|
|
||||||
#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG"
|
#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG"
|
||||||
#define ENV_DEFAULT_SINK "POLYP_SINK"
|
#define ENV_DEFAULT_SINK "POLYP_SINK"
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
USA.
|
USA.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
||||||
|
|
||||||
pa_random(&c->cookie, sizeof(c->cookie));
|
pa_random(&c->cookie, sizeof(c->cookie));
|
||||||
|
|
||||||
|
#ifdef SIGPIPE
|
||||||
pa_check_signal_is_blocked(SIGPIPE);
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
|
#endif
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +146,7 @@ void pa_core_check_quit(struct pa_core *c) {
|
||||||
|
|
||||||
if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
|
if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec+= c->exit_idle_time;
|
tv.tv_sec+= c->exit_idle_time;
|
||||||
c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
|
c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
|
||||||
} else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
|
} else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,20 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SIGXCPU
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cpulimit.h"
|
#include "cpulimit.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
@ -219,3 +224,16 @@ void pa_cpu_limit_done(void) {
|
||||||
installed = 0;
|
installed = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_SIGXCPU */
|
||||||
|
|
||||||
|
struct pa_mainloop_api;
|
||||||
|
|
||||||
|
int pa_cpu_limit_init(struct pa_mainloop_api *m) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pa_cpu_limit_done(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,23 @@
|
||||||
#include "resampler.h"
|
#include "resampler.h"
|
||||||
|
|
||||||
#ifndef DEFAULT_CONFIG_DIR
|
#ifndef DEFAULT_CONFIG_DIR
|
||||||
#define DEFAULT_CONFIG_DIR "/etc/polypaudio"
|
# ifndef OS_IS_WIN32
|
||||||
|
# define DEFAULT_CONFIG_DIR "/etc/polypaudio"
|
||||||
|
# else
|
||||||
|
# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa"
|
#ifndef OS_IS_WIN32
|
||||||
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa"
|
# define PATH_SEP "/"
|
||||||
#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf"
|
#else
|
||||||
#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf"
|
# define PATH_SEP "\\"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
|
||||||
|
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio" PATH_SEP "default.pa"
|
||||||
|
#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
|
||||||
|
#define DEFAULT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "daemon.conf"
|
||||||
|
|
||||||
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
#define ENV_SCRIPT_FILE "POLYP_SCRIPT"
|
||||||
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
#define ENV_CONFIG_FILE "POLYP_CONFIG"
|
||||||
|
|
|
||||||
43
polyp/default.pa.win32
Normal file
43
polyp/default.pa.win32
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#
|
||||||
|
# This file is part of polypaudio.
|
||||||
|
#
|
||||||
|
# polypaudio 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.
|
||||||
|
#
|
||||||
|
# polypaudio 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 polypaudio; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
|
||||||
|
|
||||||
|
# Load audio drivers statically
|
||||||
|
|
||||||
|
load-module module-waveout sink_name=output source_name=input
|
||||||
|
load-module module-null-sink
|
||||||
|
|
||||||
|
# Load audio drivers automatically on access
|
||||||
|
|
||||||
|
#add-autoload-sink output module-waveout sink_name=output source_name=input
|
||||||
|
#add-autoload-source input module-waveout sink_name=output source_name=input
|
||||||
|
|
||||||
|
# Load several protocols
|
||||||
|
#load-module module-esound-protocol-tcp
|
||||||
|
#load-module module-native-protocol-tcp
|
||||||
|
#load-module module-simple-protocol-tcp
|
||||||
|
#load-module module-cli-protocol-tcp
|
||||||
|
|
||||||
|
# Make some devices default
|
||||||
|
set-default-sink output
|
||||||
|
set-default-source input
|
||||||
|
|
||||||
|
.nofail
|
||||||
|
|
||||||
|
# Load something to the sample cache
|
||||||
|
load-sample x11-bell %WINDIR%\Media\ding.wav
|
||||||
|
load-sample-dir-lazy %WINDIR%\Media\*.wav
|
||||||
46
polyp/dllmain.c
Normal file
46
polyp/dllmain.c
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio 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.
|
||||||
|
|
||||||
|
polypaudio 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 polypaudio; 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
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
extern pa_set_root(HANDLE handle);
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||||
|
if (fdwReason != DLL_PROCESS_ATTACH)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (!pa_set_root(hinstDLL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* OS_IS_WIN32 */
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "dumpmodules.h"
|
#include "dumpmodules.h"
|
||||||
#include "modinfo.h"
|
#include "modinfo.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define PREFIX "module-"
|
#define PREFIX "module-"
|
||||||
|
|
||||||
|
|
@ -80,10 +81,7 @@ static int callback(const char *path, lt_ptr data) {
|
||||||
const char *e;
|
const char *e;
|
||||||
struct pa_daemon_conf *c = (data);
|
struct pa_daemon_conf *c = (data);
|
||||||
|
|
||||||
if ((e = (const char*) strrchr(path, '/')))
|
e = pa_path_get_filename(path);
|
||||||
e++;
|
|
||||||
else
|
|
||||||
e = path;
|
|
||||||
|
|
||||||
if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1))
|
if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1))
|
||||||
show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info);
|
show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info);
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv)
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
assert(e && e->mainloop && !e->dead);
|
assert(e && e->mainloop && !e->dead);
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
if (e->source) {
|
if (e->source) {
|
||||||
g_source_destroy(e->source);
|
g_source_destroy(e->source);
|
||||||
g_source_unref(e->source);
|
g_source_unref(e->source);
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv)
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
assert(e && e->mainloop && !e->dead);
|
assert(e && e->mainloop && !e->dead);
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
if (e->source != (guint) -1)
|
if (e->source != (guint) -1)
|
||||||
g_source_remove(e->source);
|
g_source_remove(e->source);
|
||||||
|
|
||||||
|
|
|
||||||
80
polyp/inet_ntop.c
Normal file
80
polyp/inet_ntop.c
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio 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.
|
||||||
|
|
||||||
|
polypaudio 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 polypaudio; 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 <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_NTOP
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
|
||||||
|
struct in_addr *in = (struct in_addr*)src;
|
||||||
|
struct in6_addr *in6 = (struct in6_addr*)src;
|
||||||
|
|
||||||
|
assert(src && dst);
|
||||||
|
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
snprintf(dst, cnt, "%d.%d.%d.%d",
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
(int)(in->s_addr >> 24) & 0xff,
|
||||||
|
(int)(in->s_addr >> 16) & 0xff,
|
||||||
|
(int)(in->s_addr >> 8) & 0xff,
|
||||||
|
(int)(in->s_addr >> 0) & 0xff);
|
||||||
|
#else
|
||||||
|
(int)(in->s_addr >> 0) & 0xff,
|
||||||
|
(int)(in->s_addr >> 8) & 0xff,
|
||||||
|
(int)(in->s_addr >> 16) & 0xff,
|
||||||
|
(int)(in->s_addr >> 24) & 0xff);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||||
|
in6->s6_addr[ 0] << 8 | in6->s6_addr[ 1],
|
||||||
|
in6->s6_addr[ 2] << 8 | in6->s6_addr[ 3],
|
||||||
|
in6->s6_addr[ 4] << 8 | in6->s6_addr[ 5],
|
||||||
|
in6->s6_addr[ 6] << 8 | in6->s6_addr[ 7],
|
||||||
|
in6->s6_addr[ 8] << 8 | in6->s6_addr[ 9],
|
||||||
|
in6->s6_addr[10] << 8 | in6->s6_addr[11],
|
||||||
|
in6->s6_addr[12] << 8 | in6->s6_addr[13],
|
||||||
|
in6->s6_addr[14] << 8 | in6->s6_addr[15]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INET_NTOP */
|
||||||
12
polyp/inet_ntop.h
Normal file
12
polyp/inet_ntop.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef fooinet_ntophfoo
|
||||||
|
#define fooinet_ntophfoo
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
|
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "iochannel.h"
|
#include "iochannel.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
|
|
@ -189,7 +191,19 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) {
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
assert(io && data && l && io->ofd >= 0);
|
assert(io && data && l && io->ofd >= 0);
|
||||||
|
|
||||||
if ((r = write(io->ofd, data, l)) >= 0) {
|
#ifdef OS_IS_WIN32
|
||||||
|
r = send(io->ofd, data, l, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
#endif
|
||||||
|
r = write(io->ofd, data, l);
|
||||||
|
if (r >= 0) {
|
||||||
io->writable = 0;
|
io->writable = 0;
|
||||||
enable_mainloop_sources(io);
|
enable_mainloop_sources(io);
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +215,19 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) {
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
assert(io && data && io->ifd >= 0);
|
assert(io && data && io->ifd >= 0);
|
||||||
|
|
||||||
if ((r = read(io->ifd, data, l)) >= 0) {
|
#ifdef OS_IS_WIN32
|
||||||
|
r = recv(io->ifd, data, l, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
#endif
|
||||||
|
r = read(io->ifd, data, l);
|
||||||
|
if (r >= 0) {
|
||||||
io->readable = 0;
|
io->readable = 0;
|
||||||
enable_mainloop_sources(io);
|
enable_mainloop_sources(io);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
polyp/log.c
16
polyp/log.c
|
|
@ -25,9 +25,12 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <syslog.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -39,6 +42,7 @@ static enum pa_log_target log_target = PA_LOG_STDERR;
|
||||||
static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL;
|
static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL;
|
||||||
static enum pa_log_level maximal_level = PA_LOG_NOTICE;
|
static enum pa_log_level maximal_level = PA_LOG_NOTICE;
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
static const int level_to_syslog[] = {
|
static const int level_to_syslog[] = {
|
||||||
[PA_LOG_ERROR] = LOG_ERR,
|
[PA_LOG_ERROR] = LOG_ERR,
|
||||||
[PA_LOG_WARN] = LOG_WARNING,
|
[PA_LOG_WARN] = LOG_WARNING,
|
||||||
|
|
@ -46,6 +50,7 @@ static const int level_to_syslog[] = {
|
||||||
[PA_LOG_INFO] = LOG_INFO,
|
[PA_LOG_INFO] = LOG_INFO,
|
||||||
[PA_LOG_DEBUG] = LOG_DEBUG
|
[PA_LOG_DEBUG] = LOG_DEBUG
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
void pa_log_set_ident(const char *p) {
|
void pa_log_set_ident(const char *p) {
|
||||||
if (log_ident)
|
if (log_ident)
|
||||||
|
|
@ -79,13 +84,15 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) {
|
||||||
case PA_LOG_STDERR:
|
case PA_LOG_STDERR:
|
||||||
vfprintf(stderr, format, ap);
|
vfprintf(stderr, format, ap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
case PA_LOG_SYSLOG:
|
case PA_LOG_SYSLOG:
|
||||||
openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER);
|
openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER);
|
||||||
vsyslog(level_to_syslog[level], format, ap);
|
vsyslog(level_to_syslog[level], format, ap);
|
||||||
closelog();
|
closelog();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case PA_LOG_USER: {
|
case PA_LOG_USER: {
|
||||||
char *t = pa_vsprintf_malloc(format, ap);
|
char *t = pa_vsprintf_malloc(format, ap);
|
||||||
assert(user_log_func);
|
assert(user_log_func);
|
||||||
|
|
@ -94,6 +101,7 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case PA_LOG_NULL:
|
case PA_LOG_NULL:
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
111
polyp/main.c
111
polyp/main.c
|
|
@ -35,13 +35,20 @@
|
||||||
#include <memblock.h>
|
#include <memblock.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBWRAP
|
#ifdef HAVE_LIBWRAP
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <tcpd.h>
|
#include <tcpd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "mainloop.h"
|
#include "mainloop.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
@ -66,24 +73,47 @@ int allow_severity = LOG_INFO;
|
||||||
int deny_severity = LOG_WARNING;
|
int deny_severity = LOG_WARNING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
|
||||||
|
static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
raise(SIGTERM);
|
||||||
|
else {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||||
pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
|
pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
|
#ifdef SIGUSR1
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
pa_module_load(userdata, "module-cli", NULL);
|
pa_module_load(userdata, "module-cli", NULL);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGUSR2
|
||||||
case SIGUSR2:
|
case SIGUSR2:
|
||||||
pa_module_load(userdata, "module-cli-protocol-unix", NULL);
|
pa_module_load(userdata, "module-cli-protocol-unix", NULL);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGHUP
|
||||||
case SIGHUP: {
|
case SIGHUP: {
|
||||||
char *c = pa_full_status_string(userdata);
|
char *c = pa_full_status_string(userdata);
|
||||||
pa_log_notice(c);
|
pa_log_notice(c);
|
||||||
pa_xfree(c);
|
pa_xfree(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
|
|
@ -111,24 +141,42 @@ int main(int argc, char *argv[]) {
|
||||||
char *s;
|
char *s;
|
||||||
int r, retval = 1, d = 0;
|
int r, retval = 1, d = 0;
|
||||||
int daemon_pipe[2] = { -1, -1 };
|
int daemon_pipe[2] = { -1, -1 };
|
||||||
gid_t gid = (gid_t) -1;
|
|
||||||
int suid_root;
|
int suid_root;
|
||||||
int valid_pid_file = 0;
|
int valid_pid_file = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_GETUID
|
||||||
|
gid_t gid = (gid_t) -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
struct pa_defer_event *defer;
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_limit_caps();
|
pa_limit_caps();
|
||||||
|
|
||||||
|
#ifdef HAVE_GETUID
|
||||||
suid_root = getuid() != 0 && geteuid() == 0;
|
suid_root = getuid() != 0 && geteuid() == 0;
|
||||||
|
|
||||||
if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) {
|
if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) {
|
||||||
pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n");
|
pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n");
|
||||||
pa_drop_root();
|
pa_drop_root();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
suid_root = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
LTDL_SET_PRELOADED_SYMBOLS();
|
LTDL_SET_PRELOADED_SYMBOLS();
|
||||||
|
|
||||||
r = lt_dlinit();
|
r = lt_dlinit();
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
{
|
||||||
|
WSADATA data;
|
||||||
|
WSAStartup(MAKEWORD(2, 0), &data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_log_set_ident("polypaudio");
|
pa_log_set_ident("polypaudio");
|
||||||
|
|
||||||
conf = pa_daemon_conf_new();
|
conf = pa_daemon_conf_new();
|
||||||
|
|
@ -217,6 +265,7 @@ int main(int argc, char *argv[]) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FORK
|
||||||
if (pipe(daemon_pipe) < 0) {
|
if (pipe(daemon_pipe) < 0) {
|
||||||
pa_log(__FILE__": failed to create pipe.\n");
|
pa_log(__FILE__": failed to create pipe.\n");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
@ -248,13 +297,19 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
close(daemon_pipe[0]);
|
close(daemon_pipe[0]);
|
||||||
daemon_pipe[0] = -1;
|
daemon_pipe[0] = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (conf->auto_log_target)
|
if (conf->auto_log_target)
|
||||||
pa_log_set_target(PA_LOG_SYSLOG, NULL);
|
pa_log_set_target(PA_LOG_SYSLOG, NULL);
|
||||||
|
|
||||||
|
#ifdef HAVE_SETSID
|
||||||
setsid();
|
setsid();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SETPGID
|
||||||
setpgid(0,0);
|
setpgid(0,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
close(0);
|
close(0);
|
||||||
close(1);
|
close(1);
|
||||||
close(2);
|
close(2);
|
||||||
|
|
@ -262,23 +317,37 @@ int main(int argc, char *argv[]) {
|
||||||
open("/dev/null", O_RDONLY);
|
open("/dev/null", O_RDONLY);
|
||||||
open("/dev/null", O_WRONLY);
|
open("/dev/null", O_WRONLY);
|
||||||
open("/dev/null", O_WRONLY);
|
open("/dev/null", O_WRONLY);
|
||||||
|
#else
|
||||||
|
FreeConsole();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGTTOU
|
||||||
signal(SIGTTOU, SIG_IGN);
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTIN
|
||||||
signal(SIGTTIN, SIG_IGN);
|
signal(SIGTTIN, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTSTP
|
||||||
signal(SIGTSTP, SIG_IGN);
|
signal(SIGTSTP, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TIOCNOTTY
|
||||||
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
|
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
|
||||||
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
|
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
|
||||||
close(tty_fd);
|
close(tty_fd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
chdir("/");
|
chdir("/");
|
||||||
|
|
||||||
if (conf->use_pid_file) {
|
if (conf->use_pid_file) {
|
||||||
if (pa_pid_file_create() < 0) {
|
if (pa_pid_file_create() < 0) {
|
||||||
|
pa_log(__FILE__": pa_pid_file_create() failed.\n");
|
||||||
|
#ifdef HAVE_FORK
|
||||||
if (conf->daemonize)
|
if (conf->daemonize)
|
||||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||||
|
#endif
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,20 +357,34 @@ int main(int argc, char *argv[]) {
|
||||||
mainloop = pa_mainloop_new();
|
mainloop = pa_mainloop_new();
|
||||||
assert(mainloop);
|
assert(mainloop);
|
||||||
|
|
||||||
|
c = pa_core_new(pa_mainloop_get_api(mainloop));
|
||||||
|
assert(c);
|
||||||
|
|
||||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
pa_signal_new(SIGINT, signal_callback, c);
|
pa_signal_new(SIGINT, signal_callback, c);
|
||||||
pa_signal_new(SIGTERM, signal_callback, c);
|
pa_signal_new(SIGTERM, signal_callback, c);
|
||||||
|
#ifdef SIGPIPE
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL);
|
||||||
|
assert(defer);
|
||||||
|
#endif
|
||||||
|
|
||||||
c = pa_core_new(pa_mainloop_get_api(mainloop));
|
|
||||||
assert(c);
|
|
||||||
if (conf->daemonize)
|
if (conf->daemonize)
|
||||||
c->running_as_daemon = 1;
|
c->running_as_daemon = 1;
|
||||||
|
|
||||||
|
#ifdef SIGUSR1
|
||||||
pa_signal_new(SIGUSR1, signal_callback, c);
|
pa_signal_new(SIGUSR1, signal_callback, c);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGUSR2
|
||||||
pa_signal_new(SIGUSR2, signal_callback, c);
|
pa_signal_new(SIGUSR2, signal_callback, c);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGHUP
|
||||||
pa_signal_new(SIGHUP, signal_callback, c);
|
pa_signal_new(SIGHUP, signal_callback, c);
|
||||||
|
#endif
|
||||||
|
|
||||||
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
|
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
|
|
@ -318,17 +401,23 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (r < 0 && conf->fail) {
|
if (r < 0 && conf->fail) {
|
||||||
pa_log(__FILE__": failed to initialize daemon.\n");
|
pa_log(__FILE__": failed to initialize daemon.\n");
|
||||||
|
#ifdef HAVE_FORK
|
||||||
if (conf->daemonize)
|
if (conf->daemonize)
|
||||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||||
|
#endif
|
||||||
} else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
|
} else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
|
||||||
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
|
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
|
||||||
|
#ifdef HAVE_FORK
|
||||||
if (conf->daemonize)
|
if (conf->daemonize)
|
||||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
#ifdef HAVE_FORK
|
||||||
if (conf->daemonize)
|
if (conf->daemonize)
|
||||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||||
|
#endif
|
||||||
|
|
||||||
c->disallow_module_loading = conf->disallow_module_loading;
|
c->disallow_module_loading = conf->disallow_module_loading;
|
||||||
c->exit_idle_time = conf->exit_idle_time;
|
c->exit_idle_time = conf->exit_idle_time;
|
||||||
|
|
@ -346,7 +435,11 @@ int main(int argc, char *argv[]) {
|
||||||
pa_log_info(__FILE__": Daemon shutdown initiated.\n");
|
pa_log_info(__FILE__": Daemon shutdown initiated.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
pa_mainloop_get_api(mainloop)->defer_free(defer);
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_core_free(c);
|
pa_core_free(c);
|
||||||
|
|
||||||
pa_cpu_limit_done();
|
pa_cpu_limit_done();
|
||||||
|
|
@ -365,6 +458,10 @@ finish:
|
||||||
|
|
||||||
close_pipe(daemon_pipe);
|
close_pipe(daemon_pipe);
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
lt_dlexit();
|
lt_dlexit();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mainloop-signal.h"
|
#include "mainloop-signal.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -38,7 +43,11 @@
|
||||||
|
|
||||||
struct pa_signal_event {
|
struct pa_signal_event {
|
||||||
int sig;
|
int sig;
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
struct sigaction saved_sigaction;
|
struct sigaction saved_sigaction;
|
||||||
|
#else
|
||||||
|
void (*saved_handler)(int sig);
|
||||||
|
#endif
|
||||||
void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata);
|
void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata);
|
||||||
void *userdata;
|
void *userdata;
|
||||||
void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata);
|
void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata);
|
||||||
|
|
@ -48,16 +57,70 @@ struct pa_signal_event {
|
||||||
static struct pa_mainloop_api *api = NULL;
|
static struct pa_mainloop_api *api = NULL;
|
||||||
static int signal_pipe[2] = { -1, -1 };
|
static int signal_pipe[2] = { -1, -1 };
|
||||||
static struct pa_io_event* io_event = NULL;
|
static struct pa_io_event* io_event = NULL;
|
||||||
|
static struct pa_defer_event *defer_event = NULL;
|
||||||
static struct pa_signal_event *signals = NULL;
|
static struct pa_signal_event *signals = NULL;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
static unsigned int waiting_signals = 0;
|
||||||
|
static CRITICAL_SECTION crit;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void signal_handler(int sig) {
|
static void signal_handler(int sig) {
|
||||||
|
#ifndef HAVE_SIGACTION
|
||||||
|
signal(sig, signal_handler);
|
||||||
|
#endif
|
||||||
write(signal_pipe[1], &sig, sizeof(sig));
|
write(signal_pipe[1], &sig, sizeof(sig));
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
EnterCriticalSection(&crit);
|
||||||
|
waiting_signals++;
|
||||||
|
LeaveCriticalSection(&crit);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispatch(struct pa_mainloop_api*a, int sig) {
|
||||||
|
struct pa_signal_event*s;
|
||||||
|
|
||||||
|
for (s = signals; s; s = s->next)
|
||||||
|
if (s->sig == sig) {
|
||||||
|
assert(s->callback);
|
||||||
|
s->callback(a, s, sig, s->userdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata) {
|
||||||
|
ssize_t r;
|
||||||
|
int sig;
|
||||||
|
unsigned int sigs;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
EnterCriticalSection(&crit);
|
||||||
|
sigs = waiting_signals;
|
||||||
|
waiting_signals = 0;
|
||||||
|
LeaveCriticalSection(&crit);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (sigs) {
|
||||||
|
if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) {
|
||||||
|
pa_log(__FILE__": read(): %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != sizeof(sig)) {
|
||||||
|
pa_log(__FILE__": short read()\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(a, sig);
|
||||||
|
|
||||||
|
sigs--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) {
|
static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) {
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int sig;
|
int sig;
|
||||||
struct pa_signal_event*s;
|
|
||||||
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
|
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,19 +136,18 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu
|
||||||
pa_log(__FILE__": short read()\n");
|
pa_log(__FILE__": short read()\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s = signals; s; s = s->next)
|
dispatch(a, sig);
|
||||||
if (s->sig == sig) {
|
|
||||||
assert(s->callback);
|
|
||||||
s->callback(a, s, sig, s->userdata);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_signal_init(struct pa_mainloop_api *a) {
|
int pa_signal_init(struct pa_mainloop_api *a) {
|
||||||
assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event);
|
assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event);
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if (_pipe(signal_pipe, 200, _O_BINARY) < 0) {
|
||||||
|
#else
|
||||||
if (pipe(signal_pipe) < 0) {
|
if (pipe(signal_pipe) < 0) {
|
||||||
|
#endif
|
||||||
pa_log(__FILE__": pipe() failed: %s\n", strerror(errno));
|
pa_log(__FILE__": pipe() failed: %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -96,20 +158,36 @@ int pa_signal_init(struct pa_mainloop_api *a) {
|
||||||
pa_fd_set_cloexec(signal_pipe[1], 1);
|
pa_fd_set_cloexec(signal_pipe[1], 1);
|
||||||
|
|
||||||
api = a;
|
api = a;
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
||||||
assert(io_event);
|
assert(io_event);
|
||||||
|
#else
|
||||||
|
defer_event = api->defer_new(api, defer, NULL);
|
||||||
|
assert(defer_event);
|
||||||
|
|
||||||
|
InitializeCriticalSection(&crit);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_signal_done(void) {
|
void pa_signal_done(void) {
|
||||||
assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event);
|
assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || defer_event));
|
||||||
|
|
||||||
while (signals)
|
while (signals)
|
||||||
pa_signal_free(signals);
|
pa_signal_free(signals);
|
||||||
|
|
||||||
|
|
||||||
api->io_free(io_event);
|
#ifndef OS_IS_WIN32
|
||||||
|
api->io_free(io_event);
|
||||||
io_event = NULL;
|
io_event = NULL;
|
||||||
|
#else
|
||||||
|
api->defer_free(defer_event);
|
||||||
|
defer_event = NULL;
|
||||||
|
|
||||||
|
DeleteCriticalSection(&crit);
|
||||||
|
#endif
|
||||||
|
|
||||||
close(signal_pipe[0]);
|
close(signal_pipe[0]);
|
||||||
close(signal_pipe[1]);
|
close(signal_pipe[1]);
|
||||||
|
|
@ -120,7 +198,11 @@ void pa_signal_done(void) {
|
||||||
|
|
||||||
struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) {
|
struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) {
|
||||||
struct pa_signal_event *e = NULL;
|
struct pa_signal_event *e = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(sig > 0 && callback);
|
assert(sig > 0 && callback);
|
||||||
|
|
||||||
for (e = signals; e; e = e->next)
|
for (e = signals; e; e = e->next)
|
||||||
|
|
@ -133,12 +215,16 @@ struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainl
|
||||||
e->userdata = userdata;
|
e->userdata = userdata;
|
||||||
e->destroy_callback = NULL;
|
e->destroy_callback = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = signal_handler;
|
sa.sa_handler = signal_handler;
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
|
|
||||||
if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
|
if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
|
||||||
|
#else
|
||||||
|
if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR)
|
||||||
|
#endif
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
e->previous = NULL;
|
e->previous = NULL;
|
||||||
|
|
@ -162,7 +248,11 @@ void pa_signal_free(struct pa_signal_event *e) {
|
||||||
else
|
else
|
||||||
signals = e->next;
|
signals = e->next;
|
||||||
|
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
sigaction(e->sig, &e->saved_sigaction, NULL);
|
sigaction(e->sig, &e->saved_sigaction, NULL);
|
||||||
|
#else
|
||||||
|
signal(e->sig, e->saved_handler);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (e->destroy_callback)
|
if (e->destroy_callback)
|
||||||
e->destroy_callback(api, e, e->userdata);
|
e->destroy_callback(api, e, e->userdata);
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
|
||||||
de = a->defer_new(a, dcb, NULL);
|
de = a->defer_new(a, dcb, NULL);
|
||||||
assert(de);
|
assert(de);
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec += 10;
|
tv.tv_sec += 10;
|
||||||
te = a->time_new(a, &tv, tcb, NULL);
|
te = a->time_new(a, &tv, tcb, NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,20 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_POLL_H
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#else
|
||||||
|
#include "poll.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "mainloop.h"
|
#include "mainloop.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "idxset.h"
|
#include "idxset.h"
|
||||||
|
|
@ -103,6 +110,26 @@ static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enu
|
||||||
e->destroy_callback = NULL;
|
e->destroy_callback = NULL;
|
||||||
e->pollfd = NULL;
|
e->pollfd = NULL;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
{
|
||||||
|
fd_set xset;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO (&xset);
|
||||||
|
FD_SET (fd, &xset);
|
||||||
|
|
||||||
|
if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
|
||||||
|
SELECT_TYPE_ARG5 &tv) == -1) &&
|
||||||
|
(WSAGetLastError() == WSAENOTSOCK)) {
|
||||||
|
pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n");
|
||||||
|
e->dead = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_idxset_put(m->io_events, e, NULL);
|
pa_idxset_put(m->io_events, e, NULL);
|
||||||
m->rebuild_pollfds = 1;
|
m->rebuild_pollfds = 1;
|
||||||
return e;
|
return e;
|
||||||
|
|
@ -457,7 +484,7 @@ static int calc_next_timeout(struct pa_mainloop *m) {
|
||||||
|
|
||||||
/* Let's save a system call */
|
/* Let's save a system call */
|
||||||
if (!got_time) {
|
if (!got_time) {
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
got_time = 1;
|
got_time = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,7 +525,7 @@ static int dispatch_timeout(struct pa_mainloop *m) {
|
||||||
|
|
||||||
/* Let's save a system call */
|
/* Let's save a system call */
|
||||||
if (!got_time) {
|
if (!got_time) {
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
got_time = 1;
|
got_time = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
c.length = r;
|
c.length = r;
|
||||||
pa_mcalign_push(a, &c);
|
pa_mcalign_push(a, &c);
|
||||||
fprintf(stderr, "Read %u bytes\n", r);
|
fprintf(stderr, "Read %d bytes\n", r);
|
||||||
|
|
||||||
c.index += r;
|
c.index += r;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,12 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_POLL_H
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
#else
|
||||||
|
#include "poll.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asoundlib.h>
|
#include <asoundlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,12 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_POLL_H
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
#else
|
||||||
|
#include "poll.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asoundlib.h>
|
#include <asoundlib.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, con
|
||||||
|
|
||||||
adjust_rates(u);
|
adjust_rates(u);
|
||||||
|
|
||||||
gettimeofday(&n, NULL);
|
pa_gettimeofday(&n);
|
||||||
n.tv_sec += u->adjust_time;
|
n.tv_sec += u->adjust_time;
|
||||||
u->sink->core->mainloop->time_restart(e, &n);
|
u->sink->core->mainloop->time_restart(e, &n);
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +363,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n");
|
pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n");
|
||||||
|
|
||||||
if (u->adjust_time > 0) {
|
if (u->adjust_time > 0) {
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec += u->adjust_time;
|
tv.tv_sec += u->adjust_time;
|
||||||
u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
|
u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ static int do_write(struct userdata *u) {
|
||||||
pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs));
|
pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs));
|
||||||
|
|
||||||
if (!u->memchunk.length)
|
if (!u->memchunk.length)
|
||||||
if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0)
|
if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
assert(u->memchunk.memblock && u->memchunk.length);
|
assert(u->memchunk.memblock && u->memchunk.length);
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,17 @@ PA_MODULE_USAGE("device=<evdev device> sink=<sink name>")
|
||||||
|
|
||||||
#define DEFAULT_DEVICE "/dev/input/event0"
|
#define DEFAULT_DEVICE "/dev/input/event0"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This isn't defined in older kernel headers and there is no way of
|
||||||
|
* detecting it.
|
||||||
|
*/
|
||||||
|
struct _input_id {
|
||||||
|
__u16 bustype;
|
||||||
|
__u16 vendor;
|
||||||
|
__u16 product;
|
||||||
|
__u16 version;
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const valid_modargs[] = {
|
static const char* const valid_modargs[] = {
|
||||||
"device",
|
"device",
|
||||||
"sink",
|
"sink",
|
||||||
|
|
@ -136,7 +147,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
struct pa_modargs *ma = NULL;
|
struct pa_modargs *ma = NULL;
|
||||||
struct userdata *u;
|
struct userdata *u;
|
||||||
int version;
|
int version;
|
||||||
struct input_id input_id;
|
struct _input_id input_id;
|
||||||
char name[256];
|
char name[256];
|
||||||
uint8_t evtype_bitmask[EV_MAX/8 + 1];
|
uint8_t evtype_bitmask[EV_MAX/8 + 1];
|
||||||
assert(c && m);
|
assert(c && m);
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
pa_sink_set_owner(u->sink, m);
|
pa_sink_set_owner(u->sink, m);
|
||||||
u->sink->description = pa_sprintf_malloc("NULL sink");
|
u->sink->description = pa_sprintf_malloc("NULL sink");
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
|
u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
|
||||||
|
|
||||||
u->block_size = pa_bytes_per_second(&ss) / 10;
|
u->block_size = pa_bytes_per_second(&ss) / 10;
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,20 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "socket-server.h"
|
#include "socket-server.h"
|
||||||
|
|
|
||||||
436
polyp/module-solaris.c
Normal file
436
polyp/module-solaris.c
Normal file
|
|
@ -0,0 +1,436 @@
|
||||||
|
/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio 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.
|
||||||
|
|
||||||
|
polypaudio 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 polypaudio; 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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stropts.h>
|
||||||
|
#include <sys/conf.h>
|
||||||
|
#include <sys/audio.h>
|
||||||
|
|
||||||
|
#include "iochannel.h"
|
||||||
|
#include "sink.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include "sample-util.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "modargs.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "module-solaris-symdef.h"
|
||||||
|
|
||||||
|
PA_MODULE_AUTHOR("Pierre Ossman")
|
||||||
|
PA_MODULE_DESCRIPTION("Solaris Sink/Source")
|
||||||
|
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||||
|
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> device=<OSS device> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> buffer_size=<record buffer size>")
|
||||||
|
|
||||||
|
#define PA_TYPEID_SOLARIS PA_TYPEID_MAKE('S', 'L', 'R', 'S')
|
||||||
|
|
||||||
|
struct userdata {
|
||||||
|
struct pa_sink *sink;
|
||||||
|
struct pa_source *source;
|
||||||
|
struct pa_iochannel *io;
|
||||||
|
struct pa_core *core;
|
||||||
|
|
||||||
|
struct pa_memchunk memchunk, silence;
|
||||||
|
|
||||||
|
uint32_t sample_size;
|
||||||
|
unsigned int written_bytes, read_bytes;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
struct pa_module *module;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* const valid_modargs[] = {
|
||||||
|
"sink_name",
|
||||||
|
"source_name",
|
||||||
|
"device",
|
||||||
|
"record",
|
||||||
|
"playback",
|
||||||
|
"buffer_size",
|
||||||
|
"format",
|
||||||
|
"rate",
|
||||||
|
"channels",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_SINK_NAME "solaris_output"
|
||||||
|
#define DEFAULT_SOURCE_NAME "solaris_input"
|
||||||
|
#define DEFAULT_DEVICE "/dev/audio"
|
||||||
|
|
||||||
|
#define CHUNK_SIZE 2048
|
||||||
|
|
||||||
|
static void update_usage(struct userdata *u) {
|
||||||
|
pa_module_set_used(u->module,
|
||||||
|
(u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) +
|
||||||
|
(u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) +
|
||||||
|
(u->source ? pa_idxset_ncontents(u->source->outputs) : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_write(struct userdata *u) {
|
||||||
|
struct pa_memchunk *memchunk;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
if (!u->sink || !pa_iochannel_is_writable(u->io))
|
||||||
|
return;
|
||||||
|
|
||||||
|
update_usage(u);
|
||||||
|
|
||||||
|
memchunk = &u->memchunk;
|
||||||
|
|
||||||
|
if (!memchunk->length)
|
||||||
|
if (pa_sink_render(u->sink, CHUNK_SIZE, memchunk) < 0)
|
||||||
|
memchunk = &u->silence;
|
||||||
|
|
||||||
|
assert(memchunk->memblock);
|
||||||
|
assert(memchunk->memblock->data);
|
||||||
|
assert(memchunk->length);
|
||||||
|
|
||||||
|
if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
|
||||||
|
pa_log(__FILE__": write() failed: %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memchunk == &u->silence)
|
||||||
|
assert(r % u->sample_size == 0);
|
||||||
|
else {
|
||||||
|
u->memchunk.index += r;
|
||||||
|
u->memchunk.length -= r;
|
||||||
|
|
||||||
|
if (u->memchunk.length <= 0) {
|
||||||
|
pa_memblock_unref(u->memchunk.memblock);
|
||||||
|
u->memchunk.memblock = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u->written_bytes += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_read(struct userdata *u) {
|
||||||
|
struct pa_memchunk memchunk;
|
||||||
|
int err, l;
|
||||||
|
ssize_t r;
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
if (!u->source || !pa_iochannel_is_readable(u->io))
|
||||||
|
return;
|
||||||
|
|
||||||
|
update_usage(u);
|
||||||
|
|
||||||
|
err = ioctl(u->fd, I_NREAD, &l);
|
||||||
|
assert(err >= 0);
|
||||||
|
|
||||||
|
memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat);
|
||||||
|
assert(memchunk.memblock);
|
||||||
|
if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) {
|
||||||
|
pa_memblock_unref(memchunk.memblock);
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
pa_log(__FILE__": read() failed: %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(r <= (ssize_t) memchunk.memblock->length);
|
||||||
|
memchunk.length = memchunk.memblock->length = r;
|
||||||
|
memchunk.index = 0;
|
||||||
|
|
||||||
|
pa_source_post(u->source, &memchunk);
|
||||||
|
pa_memblock_unref(memchunk.memblock);
|
||||||
|
|
||||||
|
u->read_bytes += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void io_callback(struct pa_iochannel *io, void*userdata) {
|
||||||
|
struct userdata *u = userdata;
|
||||||
|
assert(u);
|
||||||
|
do_write(u);
|
||||||
|
do_read(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pa_usec_t sink_get_latency_cb(struct pa_sink *s) {
|
||||||
|
pa_usec_t r = 0;
|
||||||
|
audio_info_t info;
|
||||||
|
int err;
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
assert(s && u && u->sink);
|
||||||
|
|
||||||
|
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||||
|
assert(err >= 0);
|
||||||
|
|
||||||
|
r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec);
|
||||||
|
r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec);
|
||||||
|
|
||||||
|
if (u->memchunk.memblock)
|
||||||
|
r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pa_usec_t source_get_latency_cb(struct pa_source *s) {
|
||||||
|
pa_usec_t r = 0;
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
audio_info_t info;
|
||||||
|
int err;
|
||||||
|
assert(s && u && u->source);
|
||||||
|
|
||||||
|
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||||
|
assert(err >= 0);
|
||||||
|
|
||||||
|
r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec);
|
||||||
|
r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pa_solaris_auto_format(int fd, int mode, struct pa_sample_spec *ss) {
|
||||||
|
audio_info_t info;
|
||||||
|
|
||||||
|
AUDIO_INITINFO(&info);
|
||||||
|
|
||||||
|
if (mode != O_RDONLY) {
|
||||||
|
info.play.sample_rate = ss->rate;
|
||||||
|
info.play.channels = ss->channels;
|
||||||
|
switch (ss->format) {
|
||||||
|
case PA_SAMPLE_U8:
|
||||||
|
info.play.precision = 8;
|
||||||
|
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_ALAW:
|
||||||
|
info.play.precision = 8;
|
||||||
|
info.play.encoding = AUDIO_ENCODING_ALAW;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_ULAW:
|
||||||
|
info.play.precision = 8;
|
||||||
|
info.play.encoding = AUDIO_ENCODING_ULAW;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_S16NE:
|
||||||
|
info.play.precision = 16;
|
||||||
|
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != O_WRONLY) {
|
||||||
|
info.record.sample_rate = ss->rate;
|
||||||
|
info.record.channels = ss->channels;
|
||||||
|
switch (ss->format) {
|
||||||
|
case PA_SAMPLE_U8:
|
||||||
|
info.record.precision = 8;
|
||||||
|
info.record.encoding = AUDIO_ENCODING_LINEAR;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_ALAW:
|
||||||
|
info.record.precision = 8;
|
||||||
|
info.record.encoding = AUDIO_ENCODING_ALAW;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_ULAW:
|
||||||
|
info.record.precision = 8;
|
||||||
|
info.record.encoding = AUDIO_ENCODING_ULAW;
|
||||||
|
break;
|
||||||
|
case PA_SAMPLE_S16NE:
|
||||||
|
info.record.precision = 16;
|
||||||
|
info.record.encoding = AUDIO_ENCODING_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
|
||||||
|
if (errno == EINVAL)
|
||||||
|
pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n");
|
||||||
|
else
|
||||||
|
pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pa_solaris_set_buffer(int fd, int buffer_size) {
|
||||||
|
audio_info_t info;
|
||||||
|
|
||||||
|
AUDIO_INITINFO(&info);
|
||||||
|
|
||||||
|
info.record.buffer_size = buffer_size;
|
||||||
|
|
||||||
|
if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
|
||||||
|
if (errno == EINVAL)
|
||||||
|
pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n");
|
||||||
|
else
|
||||||
|
pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
|
struct userdata *u = NULL;
|
||||||
|
const char *p;
|
||||||
|
int fd = -1;
|
||||||
|
int buffer_size;
|
||||||
|
int mode;
|
||||||
|
int record = 1, playback = 1;
|
||||||
|
struct pa_sample_spec ss;
|
||||||
|
struct pa_modargs *ma = NULL;
|
||||||
|
assert(c && m);
|
||||||
|
|
||||||
|
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||||
|
pa_log(__FILE__": failed to parse module arguments.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
|
||||||
|
pa_log(__FILE__": record= and playback= expect numeric argument.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playback && !record) {
|
||||||
|
pa_log(__FILE__": neither playback nor record enabled for device.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
|
||||||
|
|
||||||
|
buffer_size = -1;
|
||||||
|
if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) {
|
||||||
|
pa_log(__FILE__": failed to parse buffer size argument\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss = c->default_sample_spec;
|
||||||
|
if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
|
||||||
|
pa_log(__FILE__": failed to parse sample specification\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode)) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
|
||||||
|
|
||||||
|
if (pa_solaris_auto_format(fd, mode, &ss) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if ((mode != O_WRONLY) && (buffer_size >= 1))
|
||||||
|
if (pa_solaris_set_buffer(fd, buffer_size) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
u = pa_xmalloc(sizeof(struct userdata));
|
||||||
|
u->core = c;
|
||||||
|
|
||||||
|
if (mode != O_WRONLY) {
|
||||||
|
u->source = pa_source_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||||
|
assert(u->source);
|
||||||
|
u->source->userdata = u;
|
||||||
|
u->source->get_latency = source_get_latency_cb;
|
||||||
|
pa_source_set_owner(u->source, m);
|
||||||
|
u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p);
|
||||||
|
} else
|
||||||
|
u->source = NULL;
|
||||||
|
|
||||||
|
if (mode != O_RDONLY) {
|
||||||
|
u->sink = pa_sink_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||||
|
assert(u->sink);
|
||||||
|
u->sink->get_latency = sink_get_latency_cb;
|
||||||
|
u->sink->userdata = u;
|
||||||
|
pa_sink_set_owner(u->sink, m);
|
||||||
|
u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p);
|
||||||
|
} else
|
||||||
|
u->sink = NULL;
|
||||||
|
|
||||||
|
assert(u->source || u->sink);
|
||||||
|
|
||||||
|
u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0);
|
||||||
|
assert(u->io);
|
||||||
|
pa_iochannel_set_callback(u->io, io_callback, u);
|
||||||
|
u->fd = fd;
|
||||||
|
|
||||||
|
u->memchunk.memblock = NULL;
|
||||||
|
u->memchunk.length = 0;
|
||||||
|
u->sample_size = pa_frame_size(&ss);
|
||||||
|
|
||||||
|
u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat);
|
||||||
|
assert(u->silence.memblock);
|
||||||
|
pa_silence_memblock(u->silence.memblock, &ss);
|
||||||
|
u->silence.index = 0;
|
||||||
|
|
||||||
|
u->written_bytes = 0;
|
||||||
|
u->read_bytes = 0;
|
||||||
|
|
||||||
|
u->module = m;
|
||||||
|
m->userdata = u;
|
||||||
|
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (ma)
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pa__done(struct pa_core *c, struct pa_module*m) {
|
||||||
|
struct userdata *u;
|
||||||
|
assert(c && m);
|
||||||
|
|
||||||
|
if (!(u = m->userdata))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (u->memchunk.memblock)
|
||||||
|
pa_memblock_unref(u->memchunk.memblock);
|
||||||
|
if (u->silence.memblock)
|
||||||
|
pa_memblock_unref(u->silence.memblock);
|
||||||
|
|
||||||
|
if (u->sink) {
|
||||||
|
pa_sink_disconnect(u->sink);
|
||||||
|
pa_sink_unref(u->sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->source) {
|
||||||
|
pa_source_disconnect(u->source);
|
||||||
|
pa_source_unref(u->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_iochannel_free(u->io);
|
||||||
|
pa_xfree(u);
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <regex.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
@ -284,7 +283,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
|
|
||||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
|
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
|
||||||
/* local and remote seem to have synchronized clocks */
|
/* local and remote seem to have synchronized clocks */
|
||||||
|
|
@ -324,7 +323,7 @@ static void request_latency(struct userdata *u) {
|
||||||
pa_tagstruct_putu32(t, tag = u->ctag++);
|
pa_tagstruct_putu32(t, tag = u->ctag++);
|
||||||
pa_tagstruct_putu32(t, u->channel);
|
pa_tagstruct_putu32(t, u->channel);
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
pa_tagstruct_put_timeval(t, &now);
|
pa_tagstruct_put_timeval(t, &now);
|
||||||
pa_tagstruct_putu64(t, 0);
|
pa_tagstruct_putu64(t, 0);
|
||||||
|
|
||||||
|
|
@ -536,7 +535,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
|
||||||
|
|
||||||
request_latency(u);
|
request_latency(u);
|
||||||
|
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += LATENCY_INTERVAL;
|
ntv.tv_sec += LATENCY_INTERVAL;
|
||||||
m->time_restart(e, &ntv);
|
m->time_restart(e, &ntv);
|
||||||
}
|
}
|
||||||
|
|
@ -650,7 +649,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
pa_source_set_owner(u->source, m);
|
pa_source_set_owner(u->source, m);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += LATENCY_INTERVAL;
|
ntv.tv_sec += LATENCY_INTERVAL;
|
||||||
u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u);
|
u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u);
|
||||||
|
|
||||||
|
|
|
||||||
583
polyp/module-waveout.c
Normal file
583
polyp/module-waveout.c
Normal file
|
|
@ -0,0 +1,583 @@
|
||||||
|
/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of polypaudio.
|
||||||
|
|
||||||
|
polypaudio 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.
|
||||||
|
|
||||||
|
polypaudio 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 polypaudio; 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 <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "sink.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include "mainloop-api.h"
|
||||||
|
#include "modargs.h"
|
||||||
|
#include "sample-util.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "module-waveout-symdef.h"
|
||||||
|
|
||||||
|
PA_MODULE_AUTHOR("Pierre Ossman")
|
||||||
|
PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source")
|
||||||
|
PA_MODULE_VERSION(PACKAGE_VERSION)
|
||||||
|
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
|
||||||
|
|
||||||
|
#define PA_TYPEID_WAVEOUT PA_TYPEID_MAKE('W', 'A', 'V', 'E')
|
||||||
|
|
||||||
|
#define DEFAULT_SINK_NAME "wave_output"
|
||||||
|
#define DEFAULT_SOURCE_NAME "wave_input"
|
||||||
|
|
||||||
|
struct userdata {
|
||||||
|
struct pa_sink *sink;
|
||||||
|
struct pa_source *source;
|
||||||
|
struct pa_core *core;
|
||||||
|
struct pa_time_event *event;
|
||||||
|
struct pa_defer_event *defer;
|
||||||
|
pa_usec_t poll_timeout;
|
||||||
|
|
||||||
|
uint32_t fragments, fragment_size;
|
||||||
|
|
||||||
|
uint32_t free_ofrags, free_ifrags;
|
||||||
|
|
||||||
|
DWORD written_bytes;
|
||||||
|
|
||||||
|
int cur_ohdr, cur_ihdr;
|
||||||
|
unsigned int oremain;
|
||||||
|
WAVEHDR *ohdrs, *ihdrs;
|
||||||
|
struct pa_memchunk silence;
|
||||||
|
|
||||||
|
HWAVEOUT hwo;
|
||||||
|
HWAVEIN hwi;
|
||||||
|
struct pa_module *module;
|
||||||
|
|
||||||
|
CRITICAL_SECTION crit;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* const valid_modargs[] = {
|
||||||
|
"sink_name",
|
||||||
|
"source_name",
|
||||||
|
"record",
|
||||||
|
"playback",
|
||||||
|
"fragments",
|
||||||
|
"fragment_size",
|
||||||
|
"format",
|
||||||
|
"rate",
|
||||||
|
"channels",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void update_usage(struct userdata *u) {
|
||||||
|
pa_module_set_used(u->module,
|
||||||
|
(u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) +
|
||||||
|
(u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) +
|
||||||
|
(u->source ? pa_idxset_ncontents(u->source->outputs) : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_write(struct userdata *u)
|
||||||
|
{
|
||||||
|
uint32_t free_frags, remain;
|
||||||
|
struct pa_memchunk memchunk, *cur_chunk;
|
||||||
|
WAVEHDR *hdr;
|
||||||
|
MMRESULT res;
|
||||||
|
|
||||||
|
if (!u->sink)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
free_frags = u->free_ofrags;
|
||||||
|
u->free_ofrags = 0;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
while (free_frags) {
|
||||||
|
hdr = &u->ohdrs[u->cur_ohdr];
|
||||||
|
if (hdr->dwFlags & WHDR_PREPARED)
|
||||||
|
waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
remain = u->oremain;
|
||||||
|
while (remain) {
|
||||||
|
cur_chunk = &memchunk;
|
||||||
|
|
||||||
|
if (pa_sink_render(u->sink, remain, cur_chunk) < 0) {
|
||||||
|
/*
|
||||||
|
* Don't fill with silence unless we're getting close to
|
||||||
|
* underflowing.
|
||||||
|
*/
|
||||||
|
if (free_frags > u->fragments/2)
|
||||||
|
cur_chunk = &u->silence;
|
||||||
|
else {
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
u->free_ofrags += free_frags;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
u->oremain = remain;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(cur_chunk->memblock);
|
||||||
|
assert(cur_chunk->memblock->data);
|
||||||
|
assert(cur_chunk->length);
|
||||||
|
|
||||||
|
memcpy(hdr->lpData + u->fragment_size - remain,
|
||||||
|
(char*)cur_chunk->memblock->data + cur_chunk->index,
|
||||||
|
(cur_chunk->length < remain)?cur_chunk->length:remain);
|
||||||
|
|
||||||
|
remain -= (cur_chunk->length < remain)?cur_chunk->length:remain;
|
||||||
|
|
||||||
|
if (cur_chunk != &u->silence) {
|
||||||
|
pa_memblock_unref(cur_chunk->memblock);
|
||||||
|
cur_chunk->memblock = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
|
||||||
|
if (res != MMSYSERR_NOERROR) {
|
||||||
|
pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d\n",
|
||||||
|
res);
|
||||||
|
}
|
||||||
|
res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
|
||||||
|
if (res != MMSYSERR_NOERROR) {
|
||||||
|
pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d\n",
|
||||||
|
res);
|
||||||
|
}
|
||||||
|
|
||||||
|
u->written_bytes += u->fragment_size;
|
||||||
|
|
||||||
|
free_frags--;
|
||||||
|
u->cur_ohdr++;
|
||||||
|
u->cur_ohdr %= u->fragments;
|
||||||
|
u->oremain = u->fragment_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_read(struct userdata *u)
|
||||||
|
{
|
||||||
|
uint32_t free_frags;
|
||||||
|
struct pa_memchunk memchunk;
|
||||||
|
WAVEHDR *hdr;
|
||||||
|
MMRESULT res;
|
||||||
|
|
||||||
|
if (!u->source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
free_frags = u->free_ifrags;
|
||||||
|
u->free_ifrags = 0;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
while (free_frags) {
|
||||||
|
hdr = &u->ihdrs[u->cur_ihdr];
|
||||||
|
if (hdr->dwFlags & WHDR_PREPARED)
|
||||||
|
waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
|
||||||
|
|
||||||
|
if (hdr->dwBytesRecorded) {
|
||||||
|
memchunk.memblock = pa_memblock_new(hdr->dwBytesRecorded, u->core->memblock_stat);
|
||||||
|
assert(memchunk.memblock);
|
||||||
|
|
||||||
|
memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded);
|
||||||
|
|
||||||
|
memchunk.length = memchunk.memblock->length = hdr->dwBytesRecorded;
|
||||||
|
memchunk.index = 0;
|
||||||
|
|
||||||
|
pa_source_post(u->source, &memchunk);
|
||||||
|
pa_memblock_unref(memchunk.memblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
|
||||||
|
if (res != MMSYSERR_NOERROR) {
|
||||||
|
pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d\n",
|
||||||
|
res);
|
||||||
|
}
|
||||||
|
res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
|
||||||
|
if (res != MMSYSERR_NOERROR) {
|
||||||
|
pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d\n",
|
||||||
|
res);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_frags--;
|
||||||
|
u->cur_ihdr++;
|
||||||
|
u->cur_ihdr %= u->fragments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void poll_cb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) {
|
||||||
|
struct userdata *u = userdata;
|
||||||
|
struct timeval ntv;
|
||||||
|
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
update_usage(u);
|
||||||
|
|
||||||
|
do_write(u);
|
||||||
|
do_read(u);
|
||||||
|
|
||||||
|
pa_gettimeofday(&ntv);
|
||||||
|
pa_timeval_add(&ntv, u->poll_timeout);
|
||||||
|
|
||||||
|
a->time_restart(e, &ntv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void defer_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
|
||||||
|
struct userdata *u = userdata;
|
||||||
|
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
a->defer_enable(e, 0);
|
||||||
|
|
||||||
|
do_write(u);
|
||||||
|
do_read(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
|
||||||
|
struct userdata *u = (struct userdata *)inst;
|
||||||
|
|
||||||
|
if (msg != WOM_DONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
u->free_ofrags++;
|
||||||
|
assert(u->free_ofrags <= u->fragments);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
|
||||||
|
struct userdata *u = (struct userdata *)inst;
|
||||||
|
|
||||||
|
if (msg != WIM_DATA)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
u->free_ifrags++;
|
||||||
|
assert(u->free_ifrags <= u->fragments);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pa_usec_t sink_get_latency_cb(struct pa_sink *s) {
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
uint32_t free_frags;
|
||||||
|
MMTIME mmt;
|
||||||
|
assert(s && u && u->sink);
|
||||||
|
|
||||||
|
memset(&mmt, 0, sizeof(mmt));
|
||||||
|
mmt.wType = TIME_BYTES;
|
||||||
|
if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
|
||||||
|
return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &s->sample_spec);
|
||||||
|
else {
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
free_frags = u->free_ofrags;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size,
|
||||||
|
&s->sample_spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pa_usec_t source_get_latency_cb(struct pa_source *s) {
|
||||||
|
pa_usec_t r = 0;
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
uint32_t free_frags;
|
||||||
|
assert(s && u && u->sink);
|
||||||
|
|
||||||
|
EnterCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
free_frags = u->free_ifrags;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec);
|
||||||
|
|
||||||
|
fprintf(stderr, "Latency: %d us\n", (int)r);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void notify_sink_cb(struct pa_sink *s) {
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
u->core->mainloop->defer_enable(u->defer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void notify_source_cb(struct pa_source *s) {
|
||||||
|
struct userdata *u = s->userdata;
|
||||||
|
assert(u);
|
||||||
|
|
||||||
|
u->core->mainloop->defer_enable(u->defer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ss_to_waveformat(struct pa_sample_spec *ss, LPWAVEFORMATEX wf) {
|
||||||
|
wf->wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
|
||||||
|
if (ss->channels > 2) {
|
||||||
|
pa_log_error(__FILE__": ERROR: More than two channels not supported.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wf->nChannels = ss->channels;
|
||||||
|
|
||||||
|
switch (ss->rate) {
|
||||||
|
case 8000:
|
||||||
|
case 11025:
|
||||||
|
case 22005:
|
||||||
|
case 44100:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pa_log_error(__FILE__": ERROR: Unsupported sample rate.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wf->nSamplesPerSec = ss->rate;
|
||||||
|
|
||||||
|
if (ss->format == PA_SAMPLE_U8)
|
||||||
|
wf->wBitsPerSample = 8;
|
||||||
|
else if (ss->format == PA_SAMPLE_S16NE)
|
||||||
|
wf->wBitsPerSample = 16;
|
||||||
|
else {
|
||||||
|
pa_log_error(__FILE__": ERROR: Unsupported sample format.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
|
||||||
|
wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
|
||||||
|
|
||||||
|
wf->cbSize = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa__init(struct pa_core *c, struct pa_module*m) {
|
||||||
|
struct userdata *u = NULL;
|
||||||
|
HWAVEOUT hwo = INVALID_HANDLE_VALUE;
|
||||||
|
HWAVEIN hwi = INVALID_HANDLE_VALUE;
|
||||||
|
WAVEFORMATEX wf;
|
||||||
|
int nfrags, frag_size;
|
||||||
|
int record = 1, playback = 1;
|
||||||
|
struct pa_sample_spec ss;
|
||||||
|
struct pa_modargs *ma = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
assert(c && m);
|
||||||
|
|
||||||
|
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
|
||||||
|
pa_log(__FILE__": failed to parse module arguments.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
|
||||||
|
pa_log(__FILE__": record= and playback= expect boolean argument.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playback && !record) {
|
||||||
|
pa_log(__FILE__": neither playback nor record enabled for device.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfrags = 20;
|
||||||
|
frag_size = 1024;
|
||||||
|
if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
|
||||||
|
pa_log(__FILE__": failed to parse fragments arguments\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss = c->default_sample_spec;
|
||||||
|
if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
|
||||||
|
pa_log(__FILE__": failed to parse sample specification\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ss_to_waveformat(&ss, &wf) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
u = pa_xmalloc(sizeof(struct userdata));
|
||||||
|
|
||||||
|
if (record) {
|
||||||
|
if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
|
||||||
|
goto fail;
|
||||||
|
if (waveInStart(hwi) != MMSYSERR_NOERROR)
|
||||||
|
goto fail;
|
||||||
|
pa_log_debug(__FILE__": Opened waveIn subsystem.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playback) {
|
||||||
|
if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
|
||||||
|
goto fail;
|
||||||
|
pa_log_debug(__FILE__": Opened waveOut subsystem.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
if (hwi != INVALID_HANDLE_VALUE) {
|
||||||
|
u->source = pa_source_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||||
|
assert(u->source);
|
||||||
|
u->source->userdata = u;
|
||||||
|
u->source->notify = notify_source_cb;
|
||||||
|
u->source->get_latency = source_get_latency_cb;
|
||||||
|
pa_source_set_owner(u->source, m);
|
||||||
|
u->source->description = pa_sprintf_malloc("Windows waveIn PCM");
|
||||||
|
} else
|
||||||
|
u->source = NULL;
|
||||||
|
|
||||||
|
if (hwo != INVALID_HANDLE_VALUE) {
|
||||||
|
u->sink = pa_sink_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||||
|
assert(u->sink);
|
||||||
|
u->sink->notify = notify_sink_cb;
|
||||||
|
u->sink->get_latency = sink_get_latency_cb;
|
||||||
|
u->sink->userdata = u;
|
||||||
|
pa_sink_set_owner(u->sink, m);
|
||||||
|
u->sink->description = pa_sprintf_malloc("Windows waveOut PCM");
|
||||||
|
} else
|
||||||
|
u->sink = NULL;
|
||||||
|
|
||||||
|
assert(u->source || u->sink);
|
||||||
|
|
||||||
|
u->core = c;
|
||||||
|
u->hwi = hwi;
|
||||||
|
u->hwo = hwo;
|
||||||
|
|
||||||
|
u->fragments = nfrags;
|
||||||
|
u->free_ifrags = u->fragments;
|
||||||
|
u->free_ofrags = u->fragments;
|
||||||
|
u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
|
||||||
|
|
||||||
|
u->written_bytes = 0;
|
||||||
|
|
||||||
|
u->oremain = u->fragment_size;
|
||||||
|
|
||||||
|
u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 3, &ss);
|
||||||
|
|
||||||
|
pa_gettimeofday(&tv);
|
||||||
|
pa_timeval_add(&tv, u->poll_timeout);
|
||||||
|
|
||||||
|
u->event = c->mainloop->time_new(c->mainloop, &tv, poll_cb, u);
|
||||||
|
assert(u->event);
|
||||||
|
|
||||||
|
u->defer = c->mainloop->defer_new(c->mainloop, defer_cb, u);
|
||||||
|
assert(u->defer);
|
||||||
|
c->mainloop->defer_enable(u->defer, 0);
|
||||||
|
|
||||||
|
u->cur_ihdr = 0;
|
||||||
|
u->cur_ohdr = 0;
|
||||||
|
u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
|
||||||
|
assert(u->ihdrs);
|
||||||
|
u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
|
||||||
|
assert(u->ohdrs);
|
||||||
|
for (i = 0;i < u->fragments;i++) {
|
||||||
|
u->ihdrs[i].dwBufferLength = u->fragment_size;
|
||||||
|
u->ohdrs[i].dwBufferLength = u->fragment_size;
|
||||||
|
u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
|
||||||
|
assert(u->ihdrs);
|
||||||
|
u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
|
||||||
|
assert(u->ohdrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
u->silence.length = u->fragment_size;
|
||||||
|
u->silence.memblock = pa_memblock_new(u->silence.length, u->core->memblock_stat);
|
||||||
|
assert(u->silence.memblock);
|
||||||
|
pa_silence_memblock(u->silence.memblock, &ss);
|
||||||
|
u->silence.index = 0;
|
||||||
|
|
||||||
|
u->module = m;
|
||||||
|
m->userdata = u;
|
||||||
|
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (hwi != INVALID_HANDLE_VALUE)
|
||||||
|
waveInClose(hwi);
|
||||||
|
|
||||||
|
if (hwo != INVALID_HANDLE_VALUE)
|
||||||
|
waveOutClose(hwo);
|
||||||
|
|
||||||
|
if (u)
|
||||||
|
pa_xfree(u);
|
||||||
|
|
||||||
|
if (ma)
|
||||||
|
pa_modargs_free(ma);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pa__done(struct pa_core *c, struct pa_module*m) {
|
||||||
|
struct userdata *u;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
assert(c && m);
|
||||||
|
|
||||||
|
if (!(u = m->userdata))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (u->event)
|
||||||
|
c->mainloop->time_free(u->event);
|
||||||
|
|
||||||
|
if (u->defer)
|
||||||
|
c->mainloop->defer_free(u->defer);
|
||||||
|
|
||||||
|
if (u->sink) {
|
||||||
|
pa_sink_disconnect(u->sink);
|
||||||
|
pa_sink_unref(u->sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->source) {
|
||||||
|
pa_source_disconnect(u->source);
|
||||||
|
pa_source_unref(u->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->hwi != INVALID_HANDLE_VALUE) {
|
||||||
|
waveInReset(u->hwi);
|
||||||
|
waveInClose(u->hwi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->hwo != INVALID_HANDLE_VALUE) {
|
||||||
|
waveOutReset(u->hwo);
|
||||||
|
waveOutClose(u->hwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;i < u->fragments;i++) {
|
||||||
|
pa_xfree(u->ihdrs[i].lpData);
|
||||||
|
pa_xfree(u->ohdrs[i].lpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_xfree(u->ihdrs);
|
||||||
|
pa_xfree(u->ohdrs);
|
||||||
|
|
||||||
|
DeleteCriticalSection(&u->crit);
|
||||||
|
|
||||||
|
pa_xfree(u);
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
|
||||||
|
|
||||||
pa_module_unload_unused(c);
|
pa_module_unload_unused(c);
|
||||||
|
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||||
m->time_restart(e, &ntv);
|
m->time_restart(e, &ntv);
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char
|
||||||
|
|
||||||
if (!c->module_auto_unload_event) {
|
if (!c->module_auto_unload_event) {
|
||||||
struct timeval ntv;
|
struct timeval ntv;
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||||
c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
|
c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ fail:
|
||||||
|
|
||||||
int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) {
|
int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) {
|
||||||
int format, channels, speed, reqformat;
|
int format, channels, speed, reqformat;
|
||||||
static const int format_trans[] = {
|
static const int format_trans[PA_SAMPLE_MAX] = {
|
||||||
[PA_SAMPLE_U8] = AFMT_U8,
|
[PA_SAMPLE_U8] = AFMT_U8,
|
||||||
[PA_SAMPLE_ALAW] = AFMT_A_LAW,
|
[PA_SAMPLE_ALAW] = AFMT_A_LAW,
|
||||||
[PA_SAMPLE_ULAW] = AFMT_MU_LAW,
|
[PA_SAMPLE_ULAW] = AFMT_MU_LAW,
|
||||||
|
|
|
||||||
|
|
@ -480,8 +480,12 @@ int main(int argc, char *argv[]) {
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||||
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
|
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
|
||||||
|
#ifdef SIGUSR1
|
||||||
pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
|
pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!(stdio_event = mainloop_api->io_new(mainloop_api,
|
if (!(stdio_event = mainloop_api->io_new(mainloop_api,
|
||||||
mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
|
mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
|
||||||
|
|
|
||||||
|
|
@ -739,7 +739,9 @@ int main(int argc, char *argv[]) {
|
||||||
r = pa_signal_init(mainloop_api);
|
r = pa_signal_init(mainloop_api);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||||
|
#ifdef SIGPIPE
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
||||||
fprintf(stderr, "pa_context_new() failed.\n");
|
fprintf(stderr, "pa_context_new() failed.\n");
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,9 @@ int main(int argc, char *argv[]) {
|
||||||
r = pa_signal_init(mainloop_api);
|
r = pa_signal_init(mainloop_api);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||||
|
#ifdef SIGPIPE
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create a new connection context */
|
/* Create a new connection context */
|
||||||
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "llist.h"
|
#include "llist.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/*#define DEBUG_OPCODES */
|
/*#define DEBUG_OPCODES */
|
||||||
|
|
||||||
|
|
@ -245,7 +246,7 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time
|
||||||
r->userdata = userdata;
|
r->userdata = userdata;
|
||||||
r->tag = tag;
|
r->tag = tag;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec += timeout;
|
tv.tv_sec += timeout;
|
||||||
|
|
||||||
r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r);
|
r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r);
|
||||||
|
|
|
||||||
31
polyp/pid.c
31
polyp/pid.c
|
|
@ -35,6 +35,10 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
@ -130,6 +134,10 @@ int pa_pid_file_create(void) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
HANDLE process;
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_runtime_path("pid", fn, sizeof(fn));
|
pa_runtime_path("pid", fn, sizeof(fn));
|
||||||
|
|
||||||
if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
|
if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
|
||||||
|
|
@ -138,7 +146,12 @@ int pa_pid_file_create(void) {
|
||||||
if ((pid = read_pid(fn, fd)) == (pid_t) -1)
|
if ((pid = read_pid(fn, fd)) == (pid_t) -1)
|
||||||
pa_log(__FILE__": corrupt PID file, overwriting.\n");
|
pa_log(__FILE__": corrupt PID file, overwriting.\n");
|
||||||
else if (pid > 0) {
|
else if (pid > 0) {
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
|
||||||
|
CloseHandle(process);
|
||||||
|
#else
|
||||||
if (kill(pid, 0) >= 0 || errno != ESRCH) {
|
if (kill(pid, 0) >= 0 || errno != ESRCH) {
|
||||||
|
#endif
|
||||||
pa_log(__FILE__": daemon already running.\n");
|
pa_log(__FILE__": daemon already running.\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +211,12 @@ int pa_pid_file_remove(void) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
pa_lock_fd(fd, 0);
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (unlink(fn) < 0) {
|
if (unlink(fn) < 0) {
|
||||||
pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno));
|
pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno));
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -223,6 +242,8 @@ int pa_pid_file_check_running(pid_t *pid) {
|
||||||
return pa_pid_file_kill(0, pid);
|
return pa_pid_file_kill(0, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
|
|
||||||
/* Kill a current running daemon. Return non-zero on success, -1
|
/* Kill a current running daemon. Return non-zero on success, -1
|
||||||
* otherwise. If successful *pid contains the PID of the daemon
|
* otherwise. If successful *pid contains the PID of the daemon
|
||||||
* process. */
|
* process. */
|
||||||
|
|
@ -242,7 +263,7 @@ int pa_pid_file_kill(int sig, pid_t *pid) {
|
||||||
|
|
||||||
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
|
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = kill(*pid, sig);
|
ret = kill(*pid, sig);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
@ -255,3 +276,11 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* OS_IS_WIN32 */
|
||||||
|
|
||||||
|
int pa_pid_file_kill(int sig, pid_t *pid) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
190
polyp/poll.c
Normal file
190
polyp/poll.c
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
|
||||||
|
Copyright (C) 2005, Cendio AB.
|
||||||
|
This file is part of polypaudio.
|
||||||
|
Based on work for the GNU C Library.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with polypaudio; If not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
/* Poll the file descriptors described by the NFDS structures starting at
|
||||||
|
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
|
||||||
|
an event to occur; if TIMEOUT is -1, block until an event occurs.
|
||||||
|
Returns the number of file descriptors with events, zero if timed out,
|
||||||
|
or -1 for errors. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_SYS_POLL_H
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "poll.h"
|
||||||
|
|
||||||
|
int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set rset, wset, xset;
|
||||||
|
struct pollfd *f;
|
||||||
|
int ready;
|
||||||
|
int maxfd = 0;
|
||||||
|
char data[64];
|
||||||
|
|
||||||
|
FD_ZERO (&rset);
|
||||||
|
FD_ZERO (&wset);
|
||||||
|
FD_ZERO (&xset);
|
||||||
|
|
||||||
|
if (nfds == 0) {
|
||||||
|
if (timeout >= 0) {
|
||||||
|
pa_msleep(timeout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
/*
|
||||||
|
* Windows does not support signals properly so waiting for them would
|
||||||
|
* mean a deadlock.
|
||||||
|
*/
|
||||||
|
pa_msleep(100);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return select(0, NULL, NULL, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
for (f = fds; f < &fds[nfds]; ++f) {
|
||||||
|
if (f->fd != -1) {
|
||||||
|
if (f->events & POLLIN)
|
||||||
|
FD_SET (f->fd, &rset);
|
||||||
|
if (f->events & POLLOUT)
|
||||||
|
FD_SET (f->fd, &wset);
|
||||||
|
if (f->events & POLLPRI)
|
||||||
|
FD_SET (f->fd, &xset);
|
||||||
|
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
|
||||||
|
maxfd = f->fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
|
||||||
|
ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
|
||||||
|
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
|
||||||
|
SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
|
||||||
|
if ((ready == -1) && (errno == EBADF)) {
|
||||||
|
ready = 0;
|
||||||
|
|
||||||
|
FD_ZERO (&rset);
|
||||||
|
FD_ZERO (&wset);
|
||||||
|
FD_ZERO (&xset);
|
||||||
|
|
||||||
|
maxfd = -1;
|
||||||
|
|
||||||
|
for (f = fds; f < &fds[nfds]; ++f) {
|
||||||
|
if (f->fd != -1) {
|
||||||
|
fd_set sngl_rset, sngl_wset, sngl_xset;
|
||||||
|
|
||||||
|
FD_ZERO (&sngl_rset);
|
||||||
|
FD_ZERO (&sngl_wset);
|
||||||
|
FD_ZERO (&sngl_xset);
|
||||||
|
|
||||||
|
if (f->events & POLLIN)
|
||||||
|
FD_SET (f->fd, &sngl_rset);
|
||||||
|
if (f->events & POLLOUT)
|
||||||
|
FD_SET (f->fd, &sngl_wset);
|
||||||
|
if (f->events & POLLPRI)
|
||||||
|
FD_SET (f->fd, &sngl_xset);
|
||||||
|
if (f->events & (POLLIN|POLLOUT|POLLPRI)) {
|
||||||
|
struct timeval singl_tv;
|
||||||
|
|
||||||
|
singl_tv.tv_sec = 0;
|
||||||
|
singl_tv.tv_usec = 0;
|
||||||
|
|
||||||
|
if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset,
|
||||||
|
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
|
||||||
|
SELECT_TYPE_ARG5 &singl_tv) != -1) {
|
||||||
|
if (f->events & POLLIN)
|
||||||
|
FD_SET (f->fd, &rset);
|
||||||
|
if (f->events & POLLOUT)
|
||||||
|
FD_SET (f->fd, &wset);
|
||||||
|
if (f->events & POLLPRI)
|
||||||
|
FD_SET (f->fd, &xset);
|
||||||
|
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
|
||||||
|
maxfd = f->fd;
|
||||||
|
++ready;
|
||||||
|
} else if (errno == EBADF)
|
||||||
|
f->revents |= POLLNVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
/* Linux alters the tv struct... but it shouldn't matter here ...
|
||||||
|
* as we're going to be a little bit out anyway as we've just eaten
|
||||||
|
* more than a couple of cpu cycles above */
|
||||||
|
ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
|
||||||
|
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
|
||||||
|
SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
errno = WSAGetLastError();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ready > 0) {
|
||||||
|
ready = 0;
|
||||||
|
for (f = fds; f < &fds[nfds]; ++f) {
|
||||||
|
f->revents = 0;
|
||||||
|
if (f->fd != -1) {
|
||||||
|
if (FD_ISSET (f->fd, &rset)) {
|
||||||
|
/* support for POLLHUP. An hung up descriptor does not
|
||||||
|
increase the return value! */
|
||||||
|
if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
|
||||||
|
if (errno == ESHUTDOWN || errno == ECONNRESET ||
|
||||||
|
errno == ECONNABORTED || errno == ENETRESET) {
|
||||||
|
fprintf(stderr, "Hangup\n");
|
||||||
|
f->revents |= POLLHUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->revents == 0)
|
||||||
|
f->revents |= POLLIN;
|
||||||
|
}
|
||||||
|
if (FD_ISSET (f->fd, &wset))
|
||||||
|
f->revents |= POLLOUT;
|
||||||
|
if (FD_ISSET (f->fd, &xset))
|
||||||
|
f->revents |= POLLPRI;
|
||||||
|
}
|
||||||
|
if (f->revents)
|
||||||
|
ready++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SYS_POLL_H */
|
||||||
57
polyp/poll.h
Normal file
57
polyp/poll.h
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
|
||||||
|
|
||||||
|
/***
|
||||||
|
Compatibility definitions for System V `poll' interface.
|
||||||
|
Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc.
|
||||||
|
Copyright (C) 2005, Cendio AB.
|
||||||
|
This file is part of polypaudio.
|
||||||
|
Based on work for the GNU C Library.
|
||||||
|
|
||||||
|
polypaudio is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
polypaudio 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with polypaudio; If not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA.
|
||||||
|
***/
|
||||||
|
|
||||||
|
/* Event types that can be polled for. These bits may be set in `events'
|
||||||
|
to indicate the interesting event types; they will appear in `revents'
|
||||||
|
to indicate the status of the file descriptor. */
|
||||||
|
#define POLLIN 0x001 /* There is data to read. */
|
||||||
|
#define POLLPRI 0x002 /* There is urgent data to read. */
|
||||||
|
#define POLLOUT 0x004 /* Writing now will not block. */
|
||||||
|
|
||||||
|
/* Event types always implicitly polled for. These bits need not be set in
|
||||||
|
`events', but they will appear in `revents' to indicate the status of
|
||||||
|
the file descriptor. */
|
||||||
|
#define POLLERR 0x008 /* Error condition. */
|
||||||
|
#define POLLHUP 0x010 /* Hung up. */
|
||||||
|
#define POLLNVAL 0x020 /* Invalid polling request. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Type used for the number of file descriptors. */
|
||||||
|
typedef unsigned long int nfds_t;
|
||||||
|
|
||||||
|
/* Data structure describing a polling request. */
|
||||||
|
struct pollfd
|
||||||
|
{
|
||||||
|
int fd; /* File descriptor to poll. */
|
||||||
|
short int events; /* Types of events poller cares about. */
|
||||||
|
short int revents; /* Types of events that actually occurred. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Poll the file descriptors described by the NFDS structures starting at
|
||||||
|
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
|
||||||
|
an event to occur; if TIMEOUT is -1, block until an event occurs.
|
||||||
|
Returns the number of file descriptors with events, zero if timed out,
|
||||||
|
or -1 for errors. */
|
||||||
|
extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
|
||||||
|
|
@ -28,13 +28,24 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "polyplib-internal.h"
|
#include "polyplib-internal.h"
|
||||||
#include "polyplib-context.h"
|
#include "polyplib-context.h"
|
||||||
|
|
@ -110,8 +121,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
|
||||||
c->autospawn_lock_fd = -1;
|
c->autospawn_lock_fd = -1;
|
||||||
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
|
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
|
||||||
c->do_autospawn = 0;
|
c->do_autospawn = 0;
|
||||||
|
|
||||||
|
#ifdef SIGPIPE
|
||||||
pa_check_signal_is_blocked(SIGPIPE);
|
pa_check_signal_is_blocked(SIGPIPE);
|
||||||
|
#endif
|
||||||
|
|
||||||
c->conf = pa_client_conf_new();
|
c->conf = pa_client_conf_new();
|
||||||
pa_client_conf_load(c->conf, NULL);
|
pa_client_conf_load(c->conf, NULL);
|
||||||
|
|
@ -372,6 +385,8 @@ finish:
|
||||||
|
|
||||||
static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata);
|
static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata);
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
|
|
||||||
static int context_connect_spawn(struct pa_context *c) {
|
static int context_connect_spawn(struct pa_context *c) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status, r;
|
int status, r;
|
||||||
|
|
@ -485,6 +500,8 @@ fail:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* OS_IS_WIN32 */
|
||||||
|
|
||||||
static int try_next_connection(struct pa_context *c) {
|
static int try_next_connection(struct pa_context *c) {
|
||||||
char *u = NULL;
|
char *u = NULL;
|
||||||
int r = -1;
|
int r = -1;
|
||||||
|
|
@ -499,10 +516,12 @@ static int try_next_connection(struct pa_context *c) {
|
||||||
|
|
||||||
if (!u) {
|
if (!u) {
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
if (c->do_autospawn) {
|
if (c->do_autospawn) {
|
||||||
r = context_connect_spawn(c);
|
r = context_connect_spawn(c);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
|
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ struct pa_stream {
|
||||||
uint32_t requested_bytes;
|
uint32_t requested_bytes;
|
||||||
uint64_t counter;
|
uint64_t counter;
|
||||||
pa_usec_t previous_time;
|
pa_usec_t previous_time;
|
||||||
|
pa_usec_t previous_ipol_time;
|
||||||
enum pa_stream_state state;
|
enum pa_stream_state state;
|
||||||
struct pa_mcalign *mcalign;
|
struct pa_mcalign *mcalign;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st
|
||||||
|
|
||||||
s->counter = 0;
|
s->counter = 0;
|
||||||
s->previous_time = 0;
|
s->previous_time = 0;
|
||||||
|
s->previous_ipol_time = 0;
|
||||||
|
|
||||||
s->corked = 0;
|
s->corked = 0;
|
||||||
s->interpolate = 0;
|
s->interpolate = 0;
|
||||||
|
|
@ -217,7 +218,7 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co
|
||||||
s->ipol_requested = 1;
|
s->ipol_requested = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday(&tv2, NULL);
|
pa_gettimeofday(&tv2);
|
||||||
pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC);
|
pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC);
|
||||||
|
|
||||||
m->time_restart(e, &tv2);
|
m->time_restart(e, &tv2);
|
||||||
|
|
@ -256,7 +257,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL));
|
pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL));
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
|
tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
|
||||||
|
|
||||||
assert(!s->ipol_event);
|
assert(!s->ipol_event);
|
||||||
|
|
@ -412,7 +413,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c
|
||||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||||
goto finish;
|
goto finish;
|
||||||
} else {
|
} else {
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
|
|
||||||
if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
|
if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
|
||||||
/* local and remote seem to have synchronized clocks */
|
/* local and remote seem to have synchronized clocks */
|
||||||
|
|
@ -470,7 +471,7 @@ struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)(
|
||||||
pa_tagstruct_putu32(t, tag = s->context->ctag++);
|
pa_tagstruct_putu32(t, tag = s->context->ctag++);
|
||||||
pa_tagstruct_putu32(t, s->channel);
|
pa_tagstruct_putu32(t, s->channel);
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
pa_tagstruct_put_timeval(t, &now);
|
pa_tagstruct_put_timeval(t, &now);
|
||||||
pa_tagstruct_putu64(t, s->counter);
|
pa_tagstruct_putu64(t, s->counter);
|
||||||
|
|
||||||
|
|
@ -581,7 +582,7 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru
|
||||||
s->ipol_usec = pa_stream_get_interpolated_time(s);
|
s->ipol_usec = pa_stream_get_interpolated_time(s);
|
||||||
else if (s->corked && !b)
|
else if (s->corked && !b)
|
||||||
/* Unpausing */
|
/* Unpausing */
|
||||||
gettimeofday(&s->ipol_timestamp, NULL);
|
pa_gettimeofday(&s->ipol_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->corked = b;
|
s->corked = b;
|
||||||
|
|
@ -702,7 +703,7 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *
|
||||||
usec = s->previous_time;
|
usec = s->previous_time;
|
||||||
|
|
||||||
s->previous_time = usec;
|
s->previous_time = usec;
|
||||||
|
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,10 +763,11 @@ pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) {
|
||||||
usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp);
|
usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usec < s->previous_time)
|
if (usec < s->previous_ipol_time)
|
||||||
usec = s->previous_time;
|
usec = s->previous_ipol_time;
|
||||||
|
|
||||||
|
s->previous_ipol_time = usec;
|
||||||
|
|
||||||
s->previous_time = usec;
|
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,11 +239,14 @@ static void* connection_write(struct connection *c, size_t length) {
|
||||||
return (uint8_t*) c->write_data+i;
|
return (uint8_t*) c->write_data+i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void format_esd2native(int format, struct pa_sample_spec *ss) {
|
static void format_esd2native(int format, int swap_bytes, struct pa_sample_spec *ss) {
|
||||||
assert(ss);
|
assert(ss);
|
||||||
|
|
||||||
ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
|
ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
|
||||||
ss->format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8;
|
if ((format & ESD_MASK_BITS) == ESD_BITS16)
|
||||||
|
ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE;
|
||||||
|
else
|
||||||
|
ss->format = PA_SAMPLE_U8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int format_native2esd(struct pa_sample_spec *ss) {
|
static int format_native2esd(struct pa_sample_spec *ss) {
|
||||||
|
|
@ -303,7 +306,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons
|
||||||
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
||||||
|
|
||||||
ss.rate = rate;
|
ss.rate = rate;
|
||||||
format_esd2native(format, &ss);
|
format_esd2native(format, c->swap_byte_order, &ss);
|
||||||
|
|
||||||
if (!pa_sample_spec_valid(&ss)) {
|
if (!pa_sample_spec_valid(&ss)) {
|
||||||
pa_log(__FILE__": invalid sample specification\n");
|
pa_log(__FILE__": invalid sample specification\n");
|
||||||
|
|
@ -359,7 +362,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
|
||||||
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
||||||
|
|
||||||
ss.rate = rate;
|
ss.rate = rate;
|
||||||
format_esd2native(format, &ss);
|
format_esd2native(format, c->swap_byte_order, &ss);
|
||||||
|
|
||||||
if (!pa_sample_spec_valid(&ss)) {
|
if (!pa_sample_spec_valid(&ss)) {
|
||||||
pa_log(__FILE__": invalid sample specification.\n");
|
pa_log(__FILE__": invalid sample specification.\n");
|
||||||
|
|
@ -426,7 +429,6 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons
|
||||||
latency = 0;
|
latency = 0;
|
||||||
else {
|
else {
|
||||||
double usec = pa_sink_get_latency(sink);
|
double usec = pa_sink_get_latency(sink);
|
||||||
usec += PLAYBACK_BUFFER_SECONDS*1000000; /* A better estimation would be a good idea! */
|
|
||||||
latency = (int) ((usec*44100)/1000000);
|
latency = (int) ((usec*44100)/1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,7 +605,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con
|
||||||
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
|
||||||
|
|
||||||
ss.rate = rate;
|
ss.rate = rate;
|
||||||
format_esd2native(format, &ss);
|
format_esd2native(format, c->swap_byte_order, &ss);
|
||||||
|
|
||||||
sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2)));
|
sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2)));
|
||||||
|
|
||||||
|
|
@ -1099,7 +1101,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
||||||
|
|
||||||
if (!c->authorized) {
|
if (!c->authorized) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec += AUTH_TIMEOUT;
|
tv.tv_sec += AUTH_TIMEOUT;
|
||||||
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -928,7 +928,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma
|
||||||
pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
|
pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
|
||||||
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
||||||
pa_tagstruct_put_timeval(reply, &tv);
|
pa_tagstruct_put_timeval(reply, &tv);
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
pa_tagstruct_put_timeval(reply, &now);
|
pa_tagstruct_put_timeval(reply, &now);
|
||||||
pa_tagstruct_putu64(reply, counter);
|
pa_tagstruct_putu64(reply, counter);
|
||||||
pa_pstream_send_tagstruct(c->pstream, reply);
|
pa_pstream_send_tagstruct(c->pstream, reply);
|
||||||
|
|
@ -971,7 +971,7 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command
|
||||||
pa_tagstruct_put_boolean(reply, 0);
|
pa_tagstruct_put_boolean(reply, 0);
|
||||||
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
||||||
pa_tagstruct_put_timeval(reply, &tv);
|
pa_tagstruct_put_timeval(reply, &tv);
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
pa_tagstruct_put_timeval(reply, &now);
|
pa_tagstruct_put_timeval(reply, &now);
|
||||||
pa_tagstruct_putu64(reply, counter);
|
pa_tagstruct_putu64(reply, counter);
|
||||||
pa_pstream_send_tagstruct(c->pstream, reply);
|
pa_pstream_send_tagstruct(c->pstream, reply);
|
||||||
|
|
@ -2024,7 +2024,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
||||||
|
|
||||||
if (!c->authorized) {
|
if (!c->authorized) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
tv.tv_sec += AUTH_TIMEOUT;
|
tv.tv_sec += AUTH_TIMEOUT;
|
||||||
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,12 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "pstream.h"
|
#include "pstream.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
USA.
|
USA.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -31,13 +35,16 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
#define RANDOM_DEVICE "/dev/urandom"
|
#define RANDOM_DEVICE "/dev/urandom"
|
||||||
|
#endif
|
||||||
|
|
||||||
void pa_random(void *ret_data, size_t length) {
|
void pa_random(void *ret_data, size_t length) {
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t r = 0;
|
ssize_t r = 0;
|
||||||
assert(ret_data && length);
|
assert(ret_data && length);
|
||||||
|
|
||||||
|
#ifdef RANDOM_DEVICE
|
||||||
if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
|
if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
|
||||||
|
|
||||||
if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
|
if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
|
||||||
|
|
@ -45,17 +52,20 @@ void pa_random(void *ret_data, size_t length) {
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((size_t) r != length) {
|
if ((size_t) r != length) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
|
||||||
|
#ifdef RANDOM_DEVICE
|
||||||
pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
|
pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
|
||||||
", falling back to unsecure pseudo RNG.\n", strerror(errno));
|
", falling back to unsecure pseudo RNG.\n", strerror(errno));
|
||||||
|
#endif
|
||||||
|
|
||||||
srandom(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
for (p = ret_data, l = length; l > 0; p++, l--)
|
for (p = ret_data, l = length; l > 0; p++, l--)
|
||||||
*p = (uint8_t) random();
|
*p = (uint8_t) rand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
|
||||||
size_t d;
|
size_t d;
|
||||||
|
|
||||||
for (d = 0;; d += sizeof(float)) {
|
for (d = 0;; d += sizeof(float)) {
|
||||||
float_t sum = 0;
|
pa_volume_t sum = 0;
|
||||||
unsigned c;
|
unsigned c;
|
||||||
|
|
||||||
if (d >= length)
|
if (d >= length)
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,19 @@ enum pa_sample_format {
|
||||||
#define PA_SAMPLE_S16NE PA_SAMPLE_S16BE
|
#define PA_SAMPLE_S16NE PA_SAMPLE_S16BE
|
||||||
/** 32 Bit IEEE floating point, native endian */
|
/** 32 Bit IEEE floating point, native endian */
|
||||||
#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE
|
#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE
|
||||||
|
/** Signed 16 Bit PCM reverse endian */
|
||||||
|
#define PA_SAMPLE_S16RE PA_SAMPLE_S16LE
|
||||||
|
/** 32 Bit IEEE floating point, reverse endian */
|
||||||
|
#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE
|
||||||
#else
|
#else
|
||||||
/** Signed 16 Bit PCM, native endian */
|
/** Signed 16 Bit PCM, native endian */
|
||||||
#define PA_SAMPLE_S16NE PA_SAMPLE_S16LE
|
#define PA_SAMPLE_S16NE PA_SAMPLE_S16LE
|
||||||
/** 32 Bit IEEE floating point, native endian */
|
/** 32 Bit IEEE floating point, native endian */
|
||||||
#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE
|
#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE
|
||||||
|
/** Signed 16 Bit PCM reverse endian */
|
||||||
|
#define PA_SAMPLE_S16RE PA_SAMPLE_S16BE
|
||||||
|
/** 32 Bit IEEE floating point, reverse endian */
|
||||||
|
#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** A Shortcut for PA_SAMPLE_FLOAT32NE */
|
/** A Shortcut for PA_SAMPLE_FLOAT32NE */
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,14 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GLOB_H
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "scache.h"
|
#include "scache.h"
|
||||||
#include "sink-input.h"
|
#include "sink-input.h"
|
||||||
|
|
@ -55,7 +62,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
|
||||||
|
|
||||||
pa_scache_unload_unused(c);
|
pa_scache_unload_unused(c);
|
||||||
|
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||||
m->time_restart(e, &ntv);
|
m->time_restart(e, &ntv);
|
||||||
}
|
}
|
||||||
|
|
@ -144,6 +151,13 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
|
||||||
struct pa_memchunk chunk;
|
struct pa_memchunk chunk;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
|
||||||
|
if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
|
||||||
|
filename = buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
|
if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
@ -155,6 +169,14 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
|
||||||
|
|
||||||
int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) {
|
int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) {
|
||||||
struct pa_scache_entry *e;
|
struct pa_scache_entry *e;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
char buf[MAX_PATH];
|
||||||
|
|
||||||
|
if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
|
||||||
|
filename = buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(c && name);
|
assert(c && name);
|
||||||
|
|
||||||
if (!(e = scache_add_item(c, name)))
|
if (!(e = scache_add_item(c, name)))
|
||||||
|
|
@ -165,7 +187,7 @@ int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *fil
|
||||||
|
|
||||||
if (!c->scache_auto_unload_event) {
|
if (!c->scache_auto_unload_event) {
|
||||||
struct timeval ntv;
|
struct timeval ntv;
|
||||||
gettimeofday(&ntv, NULL);
|
pa_gettimeofday(&ntv);
|
||||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||||
c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
|
c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
|
||||||
}
|
}
|
||||||
|
|
@ -303,17 +325,16 @@ static void add_file(struct pa_core *c, const char *pathname) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *e;
|
const char *e;
|
||||||
|
|
||||||
if (!(e = strrchr(pathname, '/')))
|
e = pa_path_get_filename(pathname);
|
||||||
e = pathname;
|
|
||||||
else
|
|
||||||
e++;
|
|
||||||
|
|
||||||
if (stat(pathname, &st) < 0) {
|
if (stat(pathname, &st) < 0) {
|
||||||
pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno));
|
pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(S_ISREG) && defined(S_ISLNK)
|
||||||
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
|
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
|
||||||
|
#endif
|
||||||
pa_scache_add_file_lazy(c, e, pathname, NULL);
|
pa_scache_add_file_lazy(c, e, pathname, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,6 +344,7 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) {
|
||||||
|
|
||||||
/* First try to open this as directory */
|
/* First try to open this as directory */
|
||||||
if (!(dir = opendir(pathname))) {
|
if (!(dir = opendir(pathname))) {
|
||||||
|
#ifdef HAVE_GLOB_H
|
||||||
glob_t p;
|
glob_t p;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
/* If that fails, try to open it as shell glob */
|
/* If that fails, try to open it as shell glob */
|
||||||
|
|
@ -336,6 +358,9 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) {
|
||||||
add_file(c, p.gl_pathv[i]);
|
add_file(c, p.gl_pathv[i]);
|
||||||
|
|
||||||
globfree(&p);
|
globfree(&p);
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
struct dirent *e;
|
struct dirent *e;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,29 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBASYNCNS
|
#ifdef HAVE_LIBASYNCNS
|
||||||
#include <asyncns.h>
|
#include <asyncns.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "socket-client.h"
|
#include "socket-client.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -120,7 +135,7 @@ static void do_call(struct pa_socket_client *c) {
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
lerror = sizeof(error);
|
lerror = sizeof(error);
|
||||||
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) {
|
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
|
||||||
pa_log(__FILE__": getsockopt(): %s\n", strerror(errno));
|
pa_log(__FILE__": getsockopt(): %s\n", strerror(errno));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
@ -198,18 +213,28 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui
|
||||||
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
|
||||||
struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
assert(m && filename);
|
assert(m && filename);
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sun_family = AF_LOCAL;
|
sa.sun_family = AF_UNIX;
|
||||||
strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
|
strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
|
||||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||||
|
|
||||||
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
|
struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
|
static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(sa);
|
assert(sa);
|
||||||
|
|
@ -377,7 +402,7 @@ static void start_timeout(struct pa_socket_client *c) {
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(!c->timeout_event);
|
assert(!c->timeout_event);
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
pa_gettimeofday(&tv);
|
||||||
pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
|
pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
|
||||||
c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c);
|
c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c);
|
||||||
}
|
}
|
||||||
|
|
@ -426,8 +451,9 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m,
|
||||||
assert(c->asyncns_query);
|
assert(c->asyncns_query);
|
||||||
start_timeout(c);
|
start_timeout(c);
|
||||||
}
|
}
|
||||||
#else
|
#else /* HAVE_LIBASYNCNS */
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_GETADDRINFO
|
||||||
int ret;
|
int ret;
|
||||||
struct addrinfo *res = NULL;
|
struct addrinfo *res = NULL;
|
||||||
|
|
||||||
|
|
@ -438,12 +464,37 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m,
|
||||||
|
|
||||||
if (res->ai_addr) {
|
if (res->ai_addr) {
|
||||||
if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
|
if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
|
||||||
start_timeout(c);
|
start_timeout(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
#else /* HAVE_GETADDRINFO */
|
||||||
|
struct hostent *host = NULL;
|
||||||
|
struct sockaddr_in s;
|
||||||
|
|
||||||
|
/* FIXME: PF_INET6 support */
|
||||||
|
if (hints.ai_family != PF_INET)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
host = gethostbyname(a.path_or_host);
|
||||||
|
if (!host) {
|
||||||
|
unsigned int addr = inet_addr(a.path_or_host);
|
||||||
|
if (addr != INADDR_NONE)
|
||||||
|
host = gethostbyaddr((char*)&addr, 4, AF_INET);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
s.sin_family = AF_INET;
|
||||||
|
memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
|
||||||
|
s.sin_port = port;
|
||||||
|
|
||||||
|
if ((c = pa_socket_client_new_sockaddr(m, &s, sizeof(s))))
|
||||||
|
start_timeout(c);
|
||||||
|
#endif /* HAVE_GETADDRINFO */
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* HAVE_LIBASYNCNS */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,12 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include "mainloop-api.h"
|
#include "mainloop-api.h"
|
||||||
#include "iochannel.h"
|
#include "iochannel.h"
|
||||||
|
|
||||||
|
struct sockaddr;
|
||||||
|
|
||||||
struct pa_socket_client;
|
struct pa_socket_client;
|
||||||
|
|
||||||
struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port);
|
struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port);
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,36 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <netinet/in.h>
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(ptr) \
|
||||||
|
((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBWRAP
|
#ifdef HAVE_LIBWRAP
|
||||||
#include <tcpd.h>
|
#include <tcpd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_INET_NTOP
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "socket-server.h"
|
#include "socket-server.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
@ -137,6 +156,8 @@ struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
|
||||||
struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
|
|
@ -144,14 +165,14 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co
|
||||||
|
|
||||||
assert(m && filename);
|
assert(m && filename);
|
||||||
|
|
||||||
if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
|
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
pa_log(__FILE__": socket(): %s\n", strerror(errno));
|
pa_log(__FILE__": socket(): %s\n", strerror(errno));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_fd_set_cloexec(fd, 1);
|
pa_fd_set_cloexec(fd, 1);
|
||||||
|
|
||||||
sa.sun_family = AF_LOCAL;
|
sa.sun_family = AF_UNIX;
|
||||||
strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
|
strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
|
||||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||||
|
|
||||||
|
|
@ -182,6 +203,14 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
|
struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) {
|
struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) {
|
||||||
struct pa_socket_server *ss;
|
struct pa_socket_server *ss;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
@ -197,7 +226,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui
|
||||||
|
|
||||||
pa_fd_set_cloexec(fd, 1);
|
pa_fd_set_cloexec(fd, 1);
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
|
||||||
pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
|
pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
|
||||||
|
|
||||||
pa_socket_tcp_low_delay(fd);
|
pa_socket_tcp_low_delay(fd);
|
||||||
|
|
@ -246,7 +275,7 @@ struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, ui
|
||||||
|
|
||||||
pa_fd_set_cloexec(fd, 1);
|
pa_fd_set_cloexec(fd, 1);
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
|
||||||
pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
|
pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
|
||||||
|
|
||||||
pa_socket_tcp_low_delay(fd);
|
pa_socket_tcp_low_delay(fd);
|
||||||
|
|
@ -314,9 +343,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
|
||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
case SOCKET_SERVER_IPV6: {
|
case SOCKET_SERVER_IPV6: {
|
||||||
struct sockaddr_in6 sa;
|
struct sockaddr_in6 sa;
|
||||||
socklen_t l = sizeof(sa);
|
socklen_t sa_len = sizeof(sa);
|
||||||
|
|
||||||
if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) {
|
if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
|
||||||
pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
|
pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -350,9 +379,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
|
||||||
|
|
||||||
case SOCKET_SERVER_IPV4: {
|
case SOCKET_SERVER_IPV4: {
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
socklen_t l = sizeof(sa);
|
socklen_t sa_len = sizeof(sa);
|
||||||
|
|
||||||
if (getsockname(s->fd, &sa, &l) < 0) {
|
if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
|
||||||
pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
|
pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,33 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netinet/in_systm.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_SYSTM_H
|
||||||
|
#include <netinet/in_systm.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IP_H
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_TCP_H
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
@ -57,6 +74,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
if (S_ISSOCK(st.st_mode)) {
|
if (S_ISSOCK(st.st_mode)) {
|
||||||
union {
|
union {
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
|
|
@ -77,7 +95,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
||||||
ip & 0xFF,
|
ip & 0xFF,
|
||||||
ntohs(sa.in.sin_port));
|
ntohs(sa.in.sin_port));
|
||||||
return;
|
return;
|
||||||
} else if (sa.sa.sa_family == AF_LOCAL) {
|
} else if (sa.sa.sa_family == AF_UNIX) {
|
||||||
snprintf(c, l, "UNIX socket client");
|
snprintf(c, l, "UNIX socket client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -89,17 +107,18 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
||||||
snprintf(c, l, "STDIN/STDOUT client");
|
snprintf(c, l, "STDIN/STDOUT client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif /* OS_IS_WIN32 */
|
||||||
|
|
||||||
snprintf(c, l, "Unknown client");
|
snprintf(c, l, "Unknown client");
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_socket_low_delay(int fd) {
|
int pa_socket_low_delay(int fd) {
|
||||||
|
#ifdef SO_PRIORITY
|
||||||
int priority;
|
int priority;
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
#ifdef SO_PRIORITY
|
|
||||||
priority = 7;
|
priority = 7;
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
|
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -114,12 +133,13 @@ int pa_socket_tcp_low_delay(int fd) {
|
||||||
ret = pa_socket_low_delay(fd);
|
ret = pa_socket_low_delay(fd);
|
||||||
|
|
||||||
on = 1;
|
on = 1;
|
||||||
|
tos = 0;
|
||||||
|
|
||||||
#if defined(SOL_TCP) || defined(IPPROTO_TCP)
|
#if defined(SOL_TCP) || defined(IPPROTO_TCP)
|
||||||
#if defined(SOL_TCP)
|
#if defined(SOL_TCP)
|
||||||
if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
|
||||||
#else
|
#else
|
||||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
|
||||||
#endif
|
#endif
|
||||||
ret = -1;
|
ret = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -128,9 +148,9 @@ int pa_socket_tcp_low_delay(int fd) {
|
||||||
defined(IPPROTO_IP))
|
defined(IPPROTO_IP))
|
||||||
tos = IPTOS_LOWDELAY;
|
tos = IPTOS_LOWDELAY;
|
||||||
#ifdef SOL_IP
|
#ifdef SOL_IP
|
||||||
if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
|
||||||
#else
|
#else
|
||||||
if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
|
||||||
#endif
|
#endif
|
||||||
ret = -1;
|
ret = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -142,7 +162,7 @@ int pa_socket_tcp_low_delay(int fd) {
|
||||||
int pa_socket_set_rcvbuf(int fd, size_t l) {
|
int pa_socket_set_rcvbuf(int fd, size_t l) {
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { */
|
/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */
|
||||||
/* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */
|
/* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */
|
||||||
/* return -1; */
|
/* return -1; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
@ -153,7 +173,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) {
|
||||||
int pa_socket_set_sndbuf(int fd, size_t l) {
|
int pa_socket_set_sndbuf(int fd, size_t l) {
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { */
|
/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */
|
||||||
/* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */
|
/* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */
|
||||||
/* return -1; */
|
/* return -1; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
@ -161,16 +181,18 @@ int pa_socket_set_sndbuf(int fd, size_t l) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
|
||||||
int pa_unix_socket_is_stale(const char *fn) {
|
int pa_unix_socket_is_stale(const char *fn) {
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
int fd = -1, ret = -1;
|
int fd = -1, ret = -1;
|
||||||
|
|
||||||
if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
|
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
pa_log(__FILE__": socket(): %s\n", strerror(errno));
|
pa_log(__FILE__": socket(): %s\n", strerror(errno));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
sa.sun_family = AF_LOCAL;
|
sa.sun_family = AF_UNIX;
|
||||||
strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
|
strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
|
||||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||||
|
|
||||||
|
|
@ -202,3 +224,15 @@ int pa_unix_socket_remove_stale(const char *fn) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_SYS_UN_H */
|
||||||
|
|
||||||
|
int pa_unix_socket_is_stale(const char *fn) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pa_unix_socket_remove_stale(const char *fn) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_SYS_UN_H */
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,14 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "tagstruct.h"
|
#include "tagstruct.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
|
@ -118,7 +123,8 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
|
||||||
assert(t);
|
assert(t);
|
||||||
extend(t, 5);
|
extend(t, 5);
|
||||||
t->data[t->length] = TAG_U32;
|
t->data[t->length] = TAG_U32;
|
||||||
*((uint32_t*) (t->data+t->length+1)) = htonl(i);
|
i = htonl(i);
|
||||||
|
memcpy(t->data+t->length+1, &i, 4);
|
||||||
t->length += 5;
|
t->length += 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,21 +137,25 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
|
void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
|
||||||
|
uint32_t rate;
|
||||||
assert(t && ss);
|
assert(t && ss);
|
||||||
extend(t, 7);
|
extend(t, 7);
|
||||||
t->data[t->length] = TAG_SAMPLE_SPEC;
|
t->data[t->length] = TAG_SAMPLE_SPEC;
|
||||||
t->data[t->length+1] = (uint8_t) ss->format;
|
t->data[t->length+1] = (uint8_t) ss->format;
|
||||||
t->data[t->length+2] = ss->channels;
|
t->data[t->length+2] = ss->channels;
|
||||||
*(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
|
rate = htonl(ss->rate);
|
||||||
|
memcpy(t->data+t->length+3, &rate, 4);
|
||||||
t->length += 7;
|
t->length += 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
|
void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t && p);
|
assert(t && p);
|
||||||
|
|
||||||
extend(t, 5+length);
|
extend(t, 5+length);
|
||||||
t->data[t->length] = TAG_ARBITRARY;
|
t->data[t->length] = TAG_ARBITRARY;
|
||||||
*((uint32_t*) (t->data+t->length+1)) = htonl(length);
|
tmp = htonl(length);
|
||||||
|
memcpy(t->data+t->length+1, &tmp, 4);
|
||||||
if (length)
|
if (length)
|
||||||
memcpy(t->data+t->length+5, p, length);
|
memcpy(t->data+t->length+5, p, length);
|
||||||
t->length += 5+length;
|
t->length += 5+length;
|
||||||
|
|
@ -159,29 +169,38 @@ void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) {
|
void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t);
|
assert(t);
|
||||||
extend(t, 9);
|
extend(t, 9);
|
||||||
t->data[t->length] = TAG_TIMEVAL;
|
t->data[t->length] = TAG_TIMEVAL;
|
||||||
*((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec);
|
tmp = htonl(tv->tv_sec);
|
||||||
*((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec);
|
memcpy(t->data+t->length+1, &tmp, 4);
|
||||||
|
tmp = htonl(tv->tv_usec);
|
||||||
|
memcpy(t->data+t->length+5, &tmp, 4);
|
||||||
t->length += 9;
|
t->length += 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) {
|
void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t);
|
assert(t);
|
||||||
extend(t, 9);
|
extend(t, 9);
|
||||||
t->data[t->length] = TAG_USEC;
|
t->data[t->length] = TAG_USEC;
|
||||||
*((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
|
tmp = htonl((uint32_t) (u >> 32));
|
||||||
*((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
|
memcpy(t->data+t->length+1, &tmp, 4);
|
||||||
|
tmp = htonl((uint32_t) u);
|
||||||
|
memcpy(t->data+t->length+5, &tmp, 4);
|
||||||
t->length += 9;
|
t->length += 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) {
|
void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t);
|
assert(t);
|
||||||
extend(t, 9);
|
extend(t, 9);
|
||||||
t->data[t->length] = TAG_U64;
|
t->data[t->length] = TAG_U64;
|
||||||
*((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
|
tmp = htonl((uint32_t) (u >> 32));
|
||||||
*((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
|
memcpy(t->data+t->length+1, &tmp, 4);
|
||||||
|
tmp = htonl((uint32_t) u);
|
||||||
|
memcpy(t->data+t->length+5, &tmp, 4);
|
||||||
t->length += 9;
|
t->length += 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,8 +249,9 @@ int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) {
|
||||||
|
|
||||||
if (t->data[t->rindex] != TAG_U32)
|
if (t->data[t->rindex] != TAG_U32)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
|
memcpy(i, t->data+t->rindex+1, 4);
|
||||||
|
*i = ntohl(*i);
|
||||||
t->rindex += 5;
|
t->rindex += 5;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -261,13 +281,15 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *
|
||||||
|
|
||||||
ss->format = t->data[t->rindex+1];
|
ss->format = t->data[t->rindex+1];
|
||||||
ss->channels = t->data[t->rindex+2];
|
ss->channels = t->data[t->rindex+2];
|
||||||
ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
|
memcpy(&ss->rate, t->data+t->rindex+3, 4);
|
||||||
|
ss->rate = ntohl(ss->rate);
|
||||||
|
|
||||||
t->rindex += 7;
|
t->rindex += 7;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
|
int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
|
||||||
|
uint32_t len;
|
||||||
assert(t && p);
|
assert(t && p);
|
||||||
|
|
||||||
if (t->rindex+5+length > t->length)
|
if (t->rindex+5+length > t->length)
|
||||||
|
|
@ -276,7 +298,8 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le
|
||||||
if (t->data[t->rindex] != TAG_ARBITRARY)
|
if (t->data[t->rindex] != TAG_ARBITRARY)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length)
|
memcpy(&len, t->data+t->rindex+1, 4);
|
||||||
|
if (ntohl(len) != length)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*p = t->data+t->rindex+5;
|
*p = t->data+t->rindex+5;
|
||||||
|
|
@ -319,15 +342,18 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) {
|
||||||
|
|
||||||
if (t->data[t->rindex] != TAG_TIMEVAL)
|
if (t->data[t->rindex] != TAG_TIMEVAL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
|
memcpy(&tv->tv_sec, t->data+t->rindex+1, 4);
|
||||||
tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
tv->tv_sec = ntohl(tv->tv_sec);
|
||||||
|
memcpy(&tv->tv_usec, t->data+t->rindex+5, 4);
|
||||||
|
tv->tv_usec = ntohl(tv->tv_usec);
|
||||||
t->rindex += 9;
|
t->rindex += 9;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
|
int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t && u);
|
assert(t && u);
|
||||||
|
|
||||||
if (t->rindex+9 > t->length)
|
if (t->rindex+9 > t->length)
|
||||||
|
|
@ -336,13 +362,16 @@ int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
|
||||||
if (t->data[t->rindex] != TAG_USEC)
|
if (t->data[t->rindex] != TAG_USEC)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
|
memcpy(&tmp, t->data+t->rindex+1, 4);
|
||||||
*u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
*u = (pa_usec_t) ntohl(tmp) << 32;
|
||||||
|
memcpy(&tmp, t->data+t->rindex+5, 4);
|
||||||
|
*u |= (pa_usec_t) ntohl(tmp);
|
||||||
t->rindex +=9;
|
t->rindex +=9;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
|
int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
|
||||||
|
uint32_t tmp;
|
||||||
assert(t && u);
|
assert(t && u);
|
||||||
|
|
||||||
if (t->rindex+9 > t->length)
|
if (t->rindex+9 > t->length)
|
||||||
|
|
@ -351,8 +380,10 @@ int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
|
||||||
if (t->data[t->rindex] != TAG_U64)
|
if (t->data[t->rindex] != TAG_U64)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*u = (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
|
memcpy(&tmp, t->data+t->rindex+1, 4);
|
||||||
*u |= (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
*u = (pa_usec_t) ntohl(tmp) << 32;
|
||||||
|
memcpy(&tmp, t->data+t->rindex+5, 4);
|
||||||
|
*u |= (pa_usec_t) ntohl(tmp);
|
||||||
t->rindex +=9;
|
t->rindex +=9;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
355
polyp/util.c
355
polyp/util.c
|
|
@ -32,35 +32,98 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <pwd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SCHED_H
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <limits.h>
|
#endif
|
||||||
#include <unistd.h>
|
|
||||||
#include <grp.h>
|
#ifdef HAVE_PTHREAD
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <samplerate.h>
|
#include <samplerate.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GRP_H
|
||||||
|
#include <grp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "winsock.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
|
#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
|
||||||
|
#define PATH_SEP '/'
|
||||||
|
#else
|
||||||
|
#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\polypaudio-"
|
||||||
|
#define PATH_SEP '\\'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
|
||||||
|
#define POLYP_ROOTENV "POLYP_ROOT"
|
||||||
|
|
||||||
|
int pa_set_root(HANDLE handle) {
|
||||||
|
char library_path[MAX_PATH + sizeof(POLYP_ROOTENV) + 1], *sep;
|
||||||
|
|
||||||
|
strcpy(library_path, POLYP_ROOTENV "=");
|
||||||
|
|
||||||
|
if (!GetModuleFileName(handle, library_path + sizeof(POLYP_ROOTENV), MAX_PATH))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sep = strrchr(library_path, '\\');
|
||||||
|
if (sep)
|
||||||
|
*sep = '\0';
|
||||||
|
|
||||||
|
if (_putenv(library_path) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Make a file descriptor nonblock. Doesn't do any error checking */
|
/** Make a file descriptor nonblock. Doesn't do any error checking */
|
||||||
void pa_make_nonblock_fd(int fd) {
|
void pa_make_nonblock_fd(int fd) {
|
||||||
|
#ifdef O_NONBLOCK
|
||||||
int v;
|
int v;
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
if ((v = fcntl(fd, F_GETFL)) >= 0)
|
if ((v = fcntl(fd, F_GETFL)) >= 0)
|
||||||
if (!(v & O_NONBLOCK))
|
if (!(v & O_NONBLOCK))
|
||||||
fcntl(fd, F_SETFL, v|O_NONBLOCK);
|
fcntl(fd, F_SETFL, v|O_NONBLOCK);
|
||||||
|
#elif defined(OS_IS_WIN32)
|
||||||
|
u_long arg = 1;
|
||||||
|
if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
|
||||||
|
if (WSAGetLastError() == WSAENOTSOCK)
|
||||||
|
pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a directory securely */
|
/** Creates a directory securely */
|
||||||
|
|
@ -68,15 +131,27 @@ int pa_make_secure_dir(const char* dir) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
assert(dir);
|
assert(dir);
|
||||||
|
|
||||||
if (mkdir(dir, 0700) < 0)
|
#ifdef OS_IS_WIN32
|
||||||
|
if (mkdir(dir) < 0)
|
||||||
|
#else
|
||||||
|
if (mkdir(dir, 0700) < 0)
|
||||||
|
#endif
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (lstat(dir, &st) < 0)
|
#ifdef HAVE_LSTAT
|
||||||
|
if (lstat(dir, &st) < 0)
|
||||||
|
#else
|
||||||
|
if (stat(dir, &st) < 0)
|
||||||
|
#endif
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
|
if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "FIXME: pa_make_secure_dir()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -89,10 +164,11 @@ fail:
|
||||||
int pa_make_secure_parent_dir(const char *fn) {
|
int pa_make_secure_parent_dir(const char *fn) {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *slash, *dir = pa_xstrdup(fn);
|
char *slash, *dir = pa_xstrdup(fn);
|
||||||
|
|
||||||
if (!(slash = strrchr(dir, '/')))
|
slash = pa_path_get_filename(dir);
|
||||||
|
if (slash == fn)
|
||||||
goto finish;
|
goto finish;
|
||||||
*slash = 0;
|
*(slash-1) = 0;
|
||||||
|
|
||||||
if (pa_make_secure_dir(dir) < 0)
|
if (pa_make_secure_dir(dir) < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
@ -153,6 +229,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) {
|
||||||
/* Print a warning messages in case that the given signal is not
|
/* Print a warning messages in case that the given signal is not
|
||||||
* blocked or trapped */
|
* blocked or trapped */
|
||||||
void pa_check_signal_is_blocked(int sig) {
|
void pa_check_signal_is_blocked(int sig) {
|
||||||
|
#ifdef HAVE_SIGACTION
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
|
|
@ -185,6 +262,9 @@ void pa_check_signal_is_blocked(int sig) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig));
|
pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig));
|
||||||
|
#else /* HAVE_SIGACTION */
|
||||||
|
pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!\n", pa_strsignal(sig));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following function is based on an example from the GNU libc
|
/* The following function is based on an example from the GNU libc
|
||||||
|
|
@ -240,29 +320,46 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
|
||||||
|
|
||||||
/* Return the current username in the specified string buffer. */
|
/* Return the current username in the specified string buffer. */
|
||||||
char *pa_get_user_name(char *s, size_t l) {
|
char *pa_get_user_name(char *s, size_t l) {
|
||||||
struct passwd pw, *r;
|
|
||||||
char buf[1024];
|
|
||||||
char *p;
|
char *p;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
struct passwd pw, *r;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(s && l > 0);
|
assert(s && l > 0);
|
||||||
|
|
||||||
if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
|
if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
|
||||||
#ifdef HAVE_GETPWUID_R
|
#ifdef HAVE_GETPWUID_R
|
||||||
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
||||||
#else
|
#else
|
||||||
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
|
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
|
||||||
* that do not support getpwuid_r. */
|
* that do not support getpwuid_r. */
|
||||||
if ((r = getpwuid(getuid())) == NULL) {
|
if ((r = getpwuid(getuid())) == NULL) {
|
||||||
#endif
|
#endif
|
||||||
snprintf(s, l, "%lu", (unsigned long) getuid());
|
snprintf(s, l, "%lu", (unsigned long) getuid());
|
||||||
return s;
|
return s;
|
||||||
}
|
|
||||||
|
|
||||||
p = r->pw_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = r->pw_name;
|
||||||
|
|
||||||
|
#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
|
||||||
|
DWORD size = sizeof(buf);
|
||||||
|
|
||||||
|
if (!GetUserName(buf, &size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
|
||||||
|
#else /* HAVE_PWD_H */
|
||||||
|
return NULL;
|
||||||
|
#endif /* HAVE_PWD_H */
|
||||||
|
}
|
||||||
|
|
||||||
return pa_strlcpy(s, p, l);
|
return pa_strlcpy(s, p, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the current hostname in the specified buffer. */
|
/* Return the current hostname in the specified buffer. */
|
||||||
char *pa_get_host_name(char *s, size_t l) {
|
char *pa_get_host_name(char *s, size_t l) {
|
||||||
|
|
@ -278,19 +375,37 @@ char *pa_get_host_name(char *s, size_t l) {
|
||||||
/* Return the home directory of the current user */
|
/* Return the home directory of the current user */
|
||||||
char *pa_get_home_dir(char *s, size_t l) {
|
char *pa_get_home_dir(char *s, size_t l) {
|
||||||
char *e;
|
char *e;
|
||||||
|
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
struct passwd pw, *r;
|
struct passwd pw, *r;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(s && l);
|
assert(s && l);
|
||||||
|
|
||||||
if ((e = getenv("HOME")))
|
if ((e = getenv("HOME")))
|
||||||
return pa_strlcpy(s, e, l);
|
return pa_strlcpy(s, e, l);
|
||||||
|
|
||||||
|
if ((e = getenv("USERPROFILE")))
|
||||||
|
return pa_strlcpy(s, e, l);
|
||||||
|
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
#ifdef HAVE_GETPWUID_R
|
||||||
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
||||||
pa_log(__FILE__": getpwuid_r() failed\n");
|
pa_log(__FILE__": getpwuid_r() failed\n");
|
||||||
|
#else
|
||||||
|
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
|
||||||
|
* that do not support getpwuid_r. */
|
||||||
|
if ((r = getpwuid(getuid())) == NULL) {
|
||||||
|
pa_log(__FILE__": getpwuid_r() failed\n");
|
||||||
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pa_strlcpy(s, r->pw_dir, l);
|
return pa_strlcpy(s, r->pw_dir, l);
|
||||||
|
#else /* HAVE_PWD_H */
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar to OpenBSD's strlcpy() function */
|
/* Similar to OpenBSD's strlcpy() function */
|
||||||
|
|
@ -302,6 +417,42 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pa_gettimeofday(struct timeval *tv) {
|
||||||
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
|
return gettimeofday(tv, NULL);
|
||||||
|
#elif defined(OS_IS_WIN32)
|
||||||
|
/*
|
||||||
|
* Copied from implementation by Steven Edwards (LGPL).
|
||||||
|
* Found on wine mailing list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
|
#define EPOCHFILETIME (116444736000000000i64)
|
||||||
|
#else
|
||||||
|
#define EPOCHFILETIME (116444736000000000LL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FILETIME ft;
|
||||||
|
LARGE_INTEGER li;
|
||||||
|
__int64 t;
|
||||||
|
|
||||||
|
if (tv) {
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
li.LowPart = ft.dwLowDateTime;
|
||||||
|
li.HighPart = ft.dwHighDateTime;
|
||||||
|
t = li.QuadPart; /* In 100-nanosecond intervals */
|
||||||
|
t -= EPOCHFILETIME; /* Offset to the Epoch time */
|
||||||
|
t /= 10; /* In microseconds */
|
||||||
|
tv->tv_sec = (long)(t / 1000000);
|
||||||
|
tv->tv_usec = (long)(t % 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
#error "Platform lacks gettimeofday() or equivalent function."
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the difference between the two specfified timeval
|
/* Calculate the difference between the two specfified timeval
|
||||||
* timestamsps. */
|
* timestamsps. */
|
||||||
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
||||||
|
|
@ -351,7 +502,7 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
|
||||||
pa_usec_t pa_timeval_age(const struct timeval *tv) {
|
pa_usec_t pa_timeval_age(const struct timeval *tv) {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
assert(tv);
|
assert(tv);
|
||||||
gettimeofday(&now, NULL);
|
pa_gettimeofday(&now);
|
||||||
return pa_timeval_diff(&now, tv);
|
return pa_timeval_diff(&now, tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,10 +531,12 @@ sensible: set the nice level to -15 and enable realtime scheduling if
|
||||||
supported.*/
|
supported.*/
|
||||||
void pa_raise_priority(void) {
|
void pa_raise_priority(void) {
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
|
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
|
||||||
pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno));
|
pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno));
|
||||||
else
|
else
|
||||||
pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL);
|
pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||||
{
|
{
|
||||||
|
|
@ -403,10 +556,21 @@ void pa_raise_priority(void) {
|
||||||
pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n");
|
pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
|
||||||
|
pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X\n", GetLastError());
|
||||||
|
else
|
||||||
|
pa_log_info(__FILE__": Successfully gained high priority class.\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */
|
/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */
|
||||||
void pa_reset_priority(void) {
|
void pa_reset_priority(void) {
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||||
{
|
{
|
||||||
struct sched_param sp;
|
struct sched_param sp;
|
||||||
|
|
@ -416,11 +580,15 @@ void pa_reset_priority(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
setpriority(PRIO_PROCESS, 0, 0);
|
setpriority(PRIO_PROCESS, 0, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the FD_CLOEXEC flag for a fd */
|
/* Set the FD_CLOEXEC flag for a fd */
|
||||||
int pa_fd_set_cloexec(int fd, int b) {
|
int pa_fd_set_cloexec(int fd, int b) {
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
int v;
|
int v;
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
|
|
@ -431,7 +599,8 @@ int pa_fd_set_cloexec(int fd, int b) {
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFD, v) < 0)
|
if (fcntl(fd, F_SETFD, v) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -439,6 +608,8 @@ int pa_fd_set_cloexec(int fd, int b) {
|
||||||
* only. This shoul be used for eyecandy only, don't rely on return
|
* only. This shoul be used for eyecandy only, don't rely on return
|
||||||
* non-NULL! */
|
* non-NULL! */
|
||||||
char *pa_get_binary_name(char *s, size_t l) {
|
char *pa_get_binary_name(char *s, size_t l) {
|
||||||
|
|
||||||
|
#ifdef HAVE_READLINK
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int i;
|
int i;
|
||||||
assert(s && l);
|
assert(s && l);
|
||||||
|
|
@ -451,6 +622,15 @@ char *pa_get_binary_name(char *s, size_t l) {
|
||||||
|
|
||||||
s[i] = 0;
|
s[i] = 0;
|
||||||
return s;
|
return s;
|
||||||
|
#elif defined(OS_IS_WIN32)
|
||||||
|
char path[PATH_MAX];
|
||||||
|
if (!GetModuleFileName(NULL, path, PATH_MAX))
|
||||||
|
return NULL;
|
||||||
|
pa_strlcpy(s, pa_path_get_filename(path), l);
|
||||||
|
return s;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a pointer to the filename inside a path (which is the last
|
/* Return a pointer to the filename inside a path (which is the last
|
||||||
|
|
@ -458,7 +638,7 @@ char *pa_get_binary_name(char *s, size_t l) {
|
||||||
char *pa_path_get_filename(const char *p) {
|
char *pa_path_get_filename(const char *p) {
|
||||||
char *fn;
|
char *fn;
|
||||||
|
|
||||||
if ((fn = strrchr(p, '/')))
|
if ((fn = strrchr(p, PATH_SEP)))
|
||||||
return fn+1;
|
return fn+1;
|
||||||
|
|
||||||
return (char*) p;
|
return (char*) p;
|
||||||
|
|
@ -519,16 +699,29 @@ const char *pa_strsignal(int sig) {
|
||||||
switch(sig) {
|
switch(sig) {
|
||||||
case SIGINT: return "SIGINT";
|
case SIGINT: return "SIGINT";
|
||||||
case SIGTERM: return "SIGTERM";
|
case SIGTERM: return "SIGTERM";
|
||||||
|
#ifdef SIGUSR1
|
||||||
case SIGUSR1: return "SIGUSR1";
|
case SIGUSR1: return "SIGUSR1";
|
||||||
|
#endif
|
||||||
|
#ifdef SIGUSR2
|
||||||
case SIGUSR2: return "SIGUSR2";
|
case SIGUSR2: return "SIGUSR2";
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXCPU
|
||||||
case SIGXCPU: return "SIGXCPU";
|
case SIGXCPU: return "SIGXCPU";
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
case SIGPIPE: return "SIGPIPE";
|
case SIGPIPE: return "SIGPIPE";
|
||||||
|
#endif
|
||||||
|
#ifdef SIGCHLD
|
||||||
case SIGCHLD: return "SIGCHLD";
|
case SIGCHLD: return "SIGCHLD";
|
||||||
|
#endif
|
||||||
|
#ifdef SIGHUP
|
||||||
case SIGHUP: return "SIGHUP";
|
case SIGHUP: return "SIGHUP";
|
||||||
|
#endif
|
||||||
default: return "UNKNOWN SIGNAL";
|
default: return "UNKNOWN SIGNAL";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GRP_H
|
||||||
|
|
||||||
/* Check whether the specified GID and the group name match */
|
/* Check whether the specified GID and the group name match */
|
||||||
static int is_group(gid_t gid, const char *name) {
|
static int is_group(gid_t gid, const char *name) {
|
||||||
|
|
@ -575,7 +768,7 @@ finish:
|
||||||
/* Check the current user is member of the specified group */
|
/* Check the current user is member of the specified group */
|
||||||
int pa_uid_in_group(const char *name, gid_t *gid) {
|
int pa_uid_in_group(const char *name, gid_t *gid) {
|
||||||
gid_t *gids, tgid;
|
gid_t *gids, tgid;
|
||||||
long n = sysconf(_SC_NGROUPS_MAX);
|
GETGROUPS_T n = sysconf(_SC_NGROUPS_MAX);
|
||||||
int r = -1, i;
|
int r = -1, i;
|
||||||
|
|
||||||
assert(n > 0);
|
assert(n > 0);
|
||||||
|
|
@ -609,8 +802,18 @@ finish:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock or unlock a file entirely. (advisory) */
|
#else /* HAVE_GRP_H */
|
||||||
|
|
||||||
|
int pa_uid_in_group(const char *name, gid_t *gid) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Lock or unlock a file entirely.
|
||||||
|
(advisory on UNIX, mandatory on Windows) */
|
||||||
int pa_lock_fd(int fd, int b) {
|
int pa_lock_fd(int fd, int b) {
|
||||||
|
#ifdef F_SETLKW
|
||||||
struct flock flock;
|
struct flock flock;
|
||||||
|
|
||||||
/* Try a R/W lock first */
|
/* Try a R/W lock first */
|
||||||
|
|
@ -631,6 +834,19 @@ int pa_lock_fd(int fd, int b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno));
|
pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
||||||
|
|
||||||
|
if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
|
||||||
|
return 0;
|
||||||
|
if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pa_log(__FILE__": %slock failed: 0x%08X\n", !b ? "un" : "", GetLastError());
|
||||||
|
#endif
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -722,31 +938,51 @@ int pa_unlock_lockfile(const char *fn, int fd) {
|
||||||
* allocated buffer containing the used configuration file is
|
* allocated buffer containing the used configuration file is
|
||||||
* stored there.*/
|
* stored there.*/
|
||||||
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
|
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
|
||||||
const char *e;
|
const char *fn;
|
||||||
char h[PATH_MAX];
|
char h[PATH_MAX];
|
||||||
|
|
||||||
if (env && (e = getenv(env))) {
|
#ifdef OS_IS_WIN32
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
|
||||||
|
if (!getenv(POLYP_ROOTENV))
|
||||||
|
pa_set_root(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (env && (fn = getenv(env))) {
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
|
||||||
|
return NULL;
|
||||||
|
fn = buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
*result = pa_xstrdup(e);
|
*result = pa_xstrdup(fn);
|
||||||
return fopen(e, "r");
|
|
||||||
|
return fopen(fn, "r");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local && pa_get_home_dir(h, sizeof(h))) {
|
if (local && pa_get_home_dir(h, sizeof(h))) {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *l;
|
char *lfn;
|
||||||
|
|
||||||
l = pa_sprintf_malloc("%s/%s", h, local);
|
lfn = pa_sprintf_malloc("%s/%s", h, local);
|
||||||
f = fopen(l, "r");
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
|
||||||
|
return NULL;
|
||||||
|
lfn = buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
f = fopen(lfn, "r");
|
||||||
|
|
||||||
if (f || errno != ENOENT) {
|
if (f || errno != ENOENT) {
|
||||||
if (result)
|
if (result)
|
||||||
*result = l;
|
*result = pa_xstrdup(lfn);
|
||||||
else
|
pa_xfree(lfn);
|
||||||
pa_xfree(l);
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa_xfree(l);
|
pa_xfree(lfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global) {
|
if (!global) {
|
||||||
|
|
@ -756,6 +992,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
|
||||||
|
return NULL;
|
||||||
|
global = buf;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
*result = pa_xstrdup(global);
|
*result = pa_xstrdup(global);
|
||||||
|
|
||||||
|
|
@ -823,11 +1065,14 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
|
||||||
/* Return the fully qualified domain name in *s */
|
/* Return the fully qualified domain name in *s */
|
||||||
char *pa_get_fqdn(char *s, size_t l) {
|
char *pa_get_fqdn(char *s, size_t l) {
|
||||||
char hn[256];
|
char hn[256];
|
||||||
|
#ifdef HAVE_GETADDRINFO
|
||||||
struct addrinfo *a, hints;
|
struct addrinfo *a, hints;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!pa_get_host_name(hn, sizeof(hn)))
|
if (!pa_get_host_name(hn, sizeof(hn)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_GETADDRINFO
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
|
@ -838,6 +1083,9 @@ char *pa_get_fqdn(char *s, size_t l) {
|
||||||
pa_strlcpy(s, a->ai_canonname, l);
|
pa_strlcpy(s, a->ai_canonname, l);
|
||||||
freeaddrinfo(a);
|
freeaddrinfo(a);
|
||||||
return s;
|
return s;
|
||||||
|
#else
|
||||||
|
return pa_strlcpy(s, hn, l);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns nonzero when *s starts with *pfx */
|
/* Returns nonzero when *s starts with *pfx */
|
||||||
|
|
@ -855,21 +1103,44 @@ int pa_startswith(const char *s, const char *pfx) {
|
||||||
char *pa_runtime_path(const char *fn, char *s, size_t l) {
|
char *pa_runtime_path(const char *fn, char *s, size_t l) {
|
||||||
char u[256];
|
char u[256];
|
||||||
|
|
||||||
|
#ifndef OS_IS_WIN32
|
||||||
if (fn && *fn == '/')
|
if (fn && *fn == '/')
|
||||||
|
#else
|
||||||
|
if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
|
||||||
|
#endif
|
||||||
return pa_strlcpy(s, fn, l);
|
return pa_strlcpy(s, fn, l);
|
||||||
|
|
||||||
snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : "");
|
if (fn)
|
||||||
|
snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
|
||||||
|
else
|
||||||
|
snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
{
|
||||||
|
char buf[l];
|
||||||
|
strcpy(buf, s);
|
||||||
|
ExpandEnvironmentStrings(buf, s, l);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait t milliseconds */
|
/* Wait t milliseconds */
|
||||||
int pa_msleep(unsigned long t) {
|
int pa_msleep(unsigned long t) {
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
Sleep(t);
|
||||||
|
return 0;
|
||||||
|
#elif defined(HAVE_NANOSLEEP)
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
ts.tv_sec = t/1000;
|
ts.tv_sec = t/1000;
|
||||||
ts.tv_nsec = (t % 1000) * 1000000;
|
ts.tv_nsec = (t % 1000) * 1000000;
|
||||||
|
|
||||||
return nanosleep(&ts, NULL);
|
return nanosleep(&ts, NULL);
|
||||||
|
#else
|
||||||
|
#error "Platform lacks a sleep function."
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the string s to a signed integer in *ret_i */
|
/* Convert the string s to a signed integer in *ret_i */
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
#include "gcc-printf.h"
|
#include "gcc-printf.h"
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
|
|
||||||
|
struct timeval;
|
||||||
|
|
||||||
void pa_make_nonblock_fd(int fd);
|
void pa_make_nonblock_fd(int fd);
|
||||||
|
|
||||||
int pa_make_secure_dir(const char* dir);
|
int pa_make_secure_dir(const char* dir);
|
||||||
|
|
@ -53,6 +55,7 @@ char *pa_get_home_dir(char *s, size_t l);
|
||||||
|
|
||||||
char *pa_path_get_filename(const char *p);
|
char *pa_path_get_filename(const char *p);
|
||||||
|
|
||||||
|
int pa_gettimeofday(struct timeval *tv);
|
||||||
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b);
|
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b);
|
||||||
int pa_timeval_cmp(const struct timeval *a, const struct timeval *b);
|
int pa_timeval_cmp(const struct timeval *a, const struct timeval *b);
|
||||||
pa_usec_t pa_timeval_age(const struct timeval *tv);
|
pa_usec_t pa_timeval_age(const struct timeval *tv);
|
||||||
|
|
|
||||||
23
polyp/winsock.h
Normal file
23
polyp/winsock.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef foowinsockhfoo
|
||||||
|
#define foowinsockhfoo
|
||||||
|
|
||||||
|
#ifdef HAVE_WINSOCK2_H
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
#define ESHUTDOWN WSAESHUTDOWN
|
||||||
|
#define ECONNRESET WSAECONNRESET
|
||||||
|
#define ECONNABORTED WSAECONNABORTED
|
||||||
|
#define ENETRESET WSAENETRESET
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||||
|
#define ETIMEDOUT WSAETIMEDOUT
|
||||||
|
#define ECONNREFUSED WSAECONNREFUSED
|
||||||
|
#define EHOSTUNREACH WSAEHOSTUNREACH
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WS2TCPIP_H
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -45,7 +45,9 @@
|
||||||
static void oom(void) {
|
static void oom(void) {
|
||||||
static const char e[] = "Not enough memory\n";
|
static const char e[] = "Not enough memory\n";
|
||||||
pa_loop_write(STDERR_FILENO, e, sizeof(e)-1);
|
pa_loop_write(STDERR_FILENO, e, sizeof(e)-1);
|
||||||
|
#ifdef SIGQUIT
|
||||||
raise(SIGQUIT);
|
raise(SIGQUIT);
|
||||||
|
#endif
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue