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
|
||||
# USA.
|
||||
|
||||
EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
|
||||
SUBDIRS=polyp doc libltdl
|
||||
EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
|
||||
SUBDIRS=libltdl polyp doc
|
||||
|
||||
MAINTAINERCLEANFILES=README
|
||||
noinst_DATA = README
|
||||
MAINTAINERCLEANFILES =
|
||||
noinst_DATA =
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
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
|
||||
endif
|
||||
|
||||
if USE_LYNX
|
||||
EXTRA_DIST += README
|
||||
MAINTAINERCLEANFILES += README
|
||||
noinst_DATA += README
|
||||
|
||||
README:
|
||||
rm -f README
|
||||
$(MAKE) -C doc README
|
||||
cd $(srcdir) && ln -s doc/README README
|
||||
endif
|
||||
|
||||
homepage: all dist doxygen
|
||||
test -d $$HOME/homepage/private
|
||||
|
|
@ -49,8 +55,8 @@ homepage: all dist 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
|
||||
|
||||
distcleancheck:
|
||||
@:
|
||||
#distcleancheck:
|
||||
# @:
|
||||
|
||||
doxygen:
|
||||
$(MAKE) -C doxygen doxygen
|
||||
|
|
|
|||
41
acinclude.m4
41
acinclude.m4
|
|
@ -197,3 +197,44 @@ else
|
|||
fi
|
||||
AC_LANG_RESTORE
|
||||
])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}"
|
||||
fi
|
||||
|
||||
# Checks for programs.
|
||||
#### Checks for programs. ####
|
||||
|
||||
# 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_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 test "x$GCC" = "xyes" ; then
|
||||
CFLAGS="$CFLAGS -pipe -W -Wall -pedantic"
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
# M4
|
||||
|
||||
AC_PATH_PROG([M4], [m4 gm4], [no])
|
||||
if test "x$M4" = xno ; then
|
||||
AC_MSG_ERROR([m4 missing])
|
||||
fi
|
||||
|
||||
# LYNX documentation generation
|
||||
AC_ARG_ENABLE(lynx,
|
||||
AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation),
|
||||
|
|
@ -212,9 +75,296 @@ if test x$lynx = xyes ; then
|
|||
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
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# along with polypaudio; if not, write to the Free Software Foundation,
|
||||
# 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
|
||||
|
||||
MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html
|
||||
|
|
@ -26,6 +26,7 @@ if USE_LYNX
|
|||
README: README.html
|
||||
lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@
|
||||
|
||||
noinst_DATA += README
|
||||
CLEANFILES += README
|
||||
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) {
|
||||
int fd = -1;
|
||||
int writable = 1;
|
||||
int unlock = 0, ret;
|
||||
int unlock = 0, ret = -1;
|
||||
ssize_t r;
|
||||
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) {
|
||||
assert(fn && s && l > 0);
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
if (fn[0] != '/') {
|
||||
#else
|
||||
if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
|
||||
#endif
|
||||
char homedir[PATH_MAX];
|
||||
if (!pa_get_home_dir(homedir, sizeof(homedir)))
|
||||
return NULL;
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
snprintf(s, l, "%s/%s", homedir, fn);
|
||||
#else
|
||||
snprintf(s, l, "%s\\%s", homedir, fn);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include "log.h"
|
||||
#include "caps.h"
|
||||
|
||||
#ifdef HAVE_GETUID
|
||||
|
||||
/* Drop root rights when called SUID root */
|
||||
void pa_drop_root(void) {
|
||||
uid_t uid = getuid();
|
||||
|
|
@ -54,6 +56,13 @@ void pa_drop_root(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void pa_drop_root(void) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_CAPABILITY_H
|
||||
|
||||
/* 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);
|
||||
|
||||
#ifdef HAVE_CTIME_R
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -33,11 +37,21 @@
|
|||
#include "authkey.h"
|
||||
|
||||
#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
|
||||
|
||||
#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf"
|
||||
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf"
|
||||
#ifndef OS_IS_WIN32
|
||||
# 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_DEFAULT_SINK "POLYP_SINK"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.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));
|
||||
|
||||
#ifdef SIGPIPE
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
#endif
|
||||
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) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec+= c->exit_idle_time;
|
||||
c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
|
||||
} else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
|
||||
|
|
|
|||
|
|
@ -23,15 +23,20 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGXCPU
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "cpulimit.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
|
@ -219,3 +224,16 @@ void pa_cpu_limit_done(void) {
|
|||
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"
|
||||
|
||||
#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
|
||||
|
||||
#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa"
|
||||
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa"
|
||||
#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf"
|
||||
#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf"
|
||||
#ifndef OS_IS_WIN32
|
||||
# define PATH_SEP "/"
|
||||
#else
|
||||
# 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_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 "modinfo.h"
|
||||
#include "util.h"
|
||||
|
||||
#define PREFIX "module-"
|
||||
|
||||
|
|
@ -80,10 +81,7 @@ static int callback(const char *path, lt_ptr data) {
|
|||
const char *e;
|
||||
struct pa_daemon_conf *c = (data);
|
||||
|
||||
if ((e = (const char*) strrchr(path, '/')))
|
||||
e++;
|
||||
else
|
||||
e = path;
|
||||
e = pa_path_get_filename(path);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv)
|
|||
struct timeval now;
|
||||
assert(e && e->mainloop && !e->dead);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
if (e->source) {
|
||||
g_source_destroy(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;
|
||||
assert(e && e->mainloop && !e->dead);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
if (e->source != (guint) -1)
|
||||
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 <unistd.h>
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "iochannel.h"
|
||||
#include "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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
enable_mainloop_sources(io);
|
||||
}
|
||||
|
|
|
|||
16
polyp/log.c
16
polyp/log.c
|
|
@ -25,9 +25,12 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include "xmalloc.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 enum pa_log_level maximal_level = PA_LOG_NOTICE;
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
static const int level_to_syslog[] = {
|
||||
[PA_LOG_ERROR] = LOG_ERR,
|
||||
[PA_LOG_WARN] = LOG_WARNING,
|
||||
|
|
@ -46,6 +50,7 @@ static const int level_to_syslog[] = {
|
|||
[PA_LOG_INFO] = LOG_INFO,
|
||||
[PA_LOG_DEBUG] = LOG_DEBUG
|
||||
};
|
||||
#endif
|
||||
|
||||
void pa_log_set_ident(const char *p) {
|
||||
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:
|
||||
vfprintf(stderr, format, ap);
|
||||
break;
|
||||
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
case PA_LOG_SYSLOG:
|
||||
openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER);
|
||||
vsyslog(level_to_syslog[level], format, ap);
|
||||
closelog();
|
||||
break;
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
case PA_LOG_USER: {
|
||||
char *t = pa_vsprintf_malloc(format, ap);
|
||||
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:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
111
polyp/main.c
111
polyp/main.c
|
|
@ -35,13 +35,20 @@
|
|||
#include <memblock.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBWRAP
|
||||
#include <syslog.h>
|
||||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "core.h"
|
||||
#include "mainloop.h"
|
||||
#include "module.h"
|
||||
|
|
@ -66,24 +73,47 @@ int allow_severity = LOG_INFO;
|
|||
int deny_severity = LOG_WARNING;
|
||||
#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) {
|
||||
pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
|
||||
|
||||
switch (sig) {
|
||||
#ifdef SIGUSR1
|
||||
case SIGUSR1:
|
||||
pa_module_load(userdata, "module-cli", NULL);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIGUSR2
|
||||
case SIGUSR2:
|
||||
pa_module_load(userdata, "module-cli-protocol-unix", NULL);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIGHUP
|
||||
case SIGHUP: {
|
||||
char *c = pa_full_status_string(userdata);
|
||||
pa_log_notice(c);
|
||||
pa_xfree(c);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
|
|
@ -111,24 +141,42 @@ int main(int argc, char *argv[]) {
|
|||
char *s;
|
||||
int r, retval = 1, d = 0;
|
||||
int daemon_pipe[2] = { -1, -1 };
|
||||
gid_t gid = (gid_t) -1;
|
||||
int suid_root;
|
||||
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();
|
||||
|
||||
#ifdef HAVE_GETUID
|
||||
suid_root = getuid() != 0 && geteuid() == 0;
|
||||
|
||||
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_drop_root();
|
||||
}
|
||||
#else
|
||||
suid_root = 0;
|
||||
#endif
|
||||
|
||||
LTDL_SET_PRELOADED_SYMBOLS();
|
||||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
{
|
||||
WSADATA data;
|
||||
WSAStartup(MAKEWORD(2, 0), &data);
|
||||
}
|
||||
#endif
|
||||
|
||||
pa_log_set_ident("polypaudio");
|
||||
|
||||
conf = pa_daemon_conf_new();
|
||||
|
|
@ -217,6 +265,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
if (pipe(daemon_pipe) < 0) {
|
||||
pa_log(__FILE__": failed to create pipe.\n");
|
||||
goto finish;
|
||||
|
|
@ -248,13 +297,19 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
close(daemon_pipe[0]);
|
||||
daemon_pipe[0] = -1;
|
||||
#endif
|
||||
|
||||
if (conf->auto_log_target)
|
||||
pa_log_set_target(PA_LOG_SYSLOG, NULL);
|
||||
|
||||
#ifdef HAVE_SETSID
|
||||
setsid();
|
||||
#endif
|
||||
#ifdef HAVE_SETPGID
|
||||
setpgid(0,0);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
|
|
@ -262,23 +317,37 @@ int main(int argc, char *argv[]) {
|
|||
open("/dev/null", O_RDONLY);
|
||||
open("/dev/null", O_WRONLY);
|
||||
open("/dev/null", O_WRONLY);
|
||||
|
||||
#else
|
||||
FreeConsole();
|
||||
#endif
|
||||
|
||||
#ifdef SIGTTOU
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SIGTTIN
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
#endif
|
||||
|
||||
#ifdef TIOCNOTTY
|
||||
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
|
||||
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
|
||||
close(tty_fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
|
||||
if (conf->use_pid_file) {
|
||||
if (pa_pid_file_create() < 0) {
|
||||
pa_log(__FILE__": pa_pid_file_create() failed.\n");
|
||||
#ifdef HAVE_FORK
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
#endif
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -288,20 +357,34 @@ int main(int argc, char *argv[]) {
|
|||
mainloop = pa_mainloop_new();
|
||||
assert(mainloop);
|
||||
|
||||
c = pa_core_new(pa_mainloop_get_api(mainloop));
|
||||
assert(c);
|
||||
|
||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, signal_callback, c);
|
||||
pa_signal_new(SIGTERM, signal_callback, c);
|
||||
#ifdef SIGPIPE
|
||||
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)
|
||||
c->running_as_daemon = 1;
|
||||
|
||||
|
||||
#ifdef SIGUSR1
|
||||
pa_signal_new(SIGUSR1, signal_callback, c);
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
pa_signal_new(SIGUSR2, signal_callback, c);
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
pa_signal_new(SIGHUP, signal_callback, c);
|
||||
#endif
|
||||
|
||||
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
|
|
@ -318,17 +401,23 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (r < 0 && conf->fail) {
|
||||
pa_log(__FILE__": failed to initialize daemon.\n");
|
||||
#ifdef HAVE_FORK
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
#endif
|
||||
} else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
|
||||
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
|
||||
#ifdef HAVE_FORK
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
#endif
|
||||
} else {
|
||||
|
||||
retval = 0;
|
||||
#ifdef HAVE_FORK
|
||||
if (conf->daemonize)
|
||||
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
|
||||
#endif
|
||||
|
||||
c->disallow_module_loading = conf->disallow_module_loading;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
pa_mainloop_get_api(mainloop)->defer_free(defer);
|
||||
#endif
|
||||
|
||||
pa_core_free(c);
|
||||
|
||||
pa_cpu_limit_done();
|
||||
|
|
@ -365,6 +458,10 @@ finish:
|
|||
|
||||
close_pipe(daemon_pipe);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
lt_dlexit();
|
||||
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "mainloop-signal.h"
|
||||
#include "util.h"
|
||||
|
|
@ -38,7 +43,11 @@
|
|||
|
||||
struct pa_signal_event {
|
||||
int sig;
|
||||
#ifdef HAVE_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 *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 int signal_pipe[2] = { -1, -1 };
|
||||
static struct pa_io_event* io_event = NULL;
|
||||
static struct pa_defer_event *defer_event = 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) {
|
||||
#ifndef HAVE_SIGACTION
|
||||
signal(sig, signal_handler);
|
||||
#endif
|
||||
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) {
|
||||
ssize_t r;
|
||||
int sig;
|
||||
struct pa_signal_event*s;
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
for (s = signals; s; s = s->next)
|
||||
if (s->sig == sig) {
|
||||
assert(s->callback);
|
||||
s->callback(a, s, sig, s->userdata);
|
||||
break;
|
||||
}
|
||||
|
||||
dispatch(a, sig);
|
||||
}
|
||||
|
||||
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) {
|
||||
#endif
|
||||
pa_log(__FILE__": pipe() failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -96,20 +158,36 @@ int pa_signal_init(struct pa_mainloop_api *a) {
|
|||
pa_fd_set_cloexec(signal_pipe[1], 1);
|
||||
|
||||
api = a;
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
|
||||
assert(io_event);
|
||||
#else
|
||||
defer_event = api->defer_new(api, defer, NULL);
|
||||
assert(defer_event);
|
||||
|
||||
InitializeCriticalSection(&crit);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
pa_signal_free(signals);
|
||||
|
||||
|
||||
api->io_free(io_event);
|
||||
#ifndef OS_IS_WIN32
|
||||
api->io_free(io_event);
|
||||
io_event = NULL;
|
||||
#else
|
||||
api->defer_free(defer_event);
|
||||
defer_event = NULL;
|
||||
|
||||
DeleteCriticalSection(&crit);
|
||||
#endif
|
||||
|
||||
close(signal_pipe[0]);
|
||||
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 *e = NULL;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
assert(sig > 0 && callback);
|
||||
|
||||
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->destroy_callback = NULL;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = signal_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
|
||||
if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
|
||||
#else
|
||||
if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR)
|
||||
#endif
|
||||
goto fail;
|
||||
|
||||
e->previous = NULL;
|
||||
|
|
@ -162,7 +248,11 @@ void pa_signal_free(struct pa_signal_event *e) {
|
|||
else
|
||||
signals = e->next;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigaction(e->sig, &e->saved_sigaction, NULL);
|
||||
#else
|
||||
signal(e->sig, e->saved_handler);
|
||||
#endif
|
||||
|
||||
if (e->destroy_callback)
|
||||
e->destroy_callback(api, e, e->userdata);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
|
|||
de = a->defer_new(a, dcb, NULL);
|
||||
assert(de);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += 10;
|
||||
te = a->time_new(a, &tv, tcb, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,20 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.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 "util.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->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);
|
||||
m->rebuild_pollfds = 1;
|
||||
return e;
|
||||
|
|
@ -457,7 +484,7 @@ static int calc_next_timeout(struct pa_mainloop *m) {
|
|||
|
||||
/* Let's save a system call */
|
||||
if (!got_time) {
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
got_time = 1;
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +525,7 @@ static int dispatch_timeout(struct pa_mainloop *m) {
|
|||
|
||||
/* Let's save a system call */
|
||||
if (!got_time) {
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
got_time = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
c.length = r;
|
||||
pa_mcalign_push(a, &c);
|
||||
fprintf(stderr, "Read %u bytes\n", r);
|
||||
fprintf(stderr, "Read %d bytes\n", r);
|
||||
|
||||
c.index += r;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,12 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#else
|
||||
#include "poll.h"
|
||||
#endif
|
||||
|
||||
#include <asoundlib.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,12 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#else
|
||||
#include "poll.h"
|
||||
#endif
|
||||
|
||||
#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);
|
||||
|
||||
gettimeofday(&n, NULL);
|
||||
pa_gettimeofday(&n);
|
||||
n.tv_sec += u->adjust_time;
|
||||
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");
|
||||
|
||||
if (u->adjust_time > 0) {
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += u->adjust_time;
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
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"
|
||||
|
||||
/*
|
||||
* 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[] = {
|
||||
"device",
|
||||
"sink",
|
||||
|
|
@ -136,7 +147,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
struct pa_modargs *ma = NULL;
|
||||
struct userdata *u;
|
||||
int version;
|
||||
struct input_id input_id;
|
||||
struct _input_id input_id;
|
||||
char name[256];
|
||||
uint8_t evtype_bitmask[EV_MAX/8 + 1];
|
||||
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);
|
||||
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->block_size = pa_bytes_per_second(&ss) / 10;
|
||||
|
|
|
|||
|
|
@ -27,9 +27,20 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <arpa/inet.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>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "module.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 <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
@ -284,7 +283,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
|
|||
return;
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
|
||||
/* 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, u->channel);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
pa_tagstruct_put_timeval(t, &now);
|
||||
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);
|
||||
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += LATENCY_INTERVAL;
|
||||
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);
|
||||
#endif
|
||||
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += LATENCY_INTERVAL;
|
||||
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);
|
||||
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||
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) {
|
||||
struct timeval ntv;
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||
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 format, channels, speed, reqformat;
|
||||
static const int format_trans[] = {
|
||||
static const int format_trans[PA_SAMPLE_MAX] = {
|
||||
[PA_SAMPLE_U8] = AFMT_U8,
|
||||
[PA_SAMPLE_ALAW] = AFMT_A_LAW,
|
||||
[PA_SAMPLE_ULAW] = AFMT_MU_LAW,
|
||||
|
|
|
|||
|
|
@ -480,8 +480,12 @@ int main(int argc, char *argv[]) {
|
|||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
|
||||
#ifdef SIGUSR1
|
||||
pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
if (!(stdio_event = mainloop_api->io_new(mainloop_api,
|
||||
mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
|
||||
|
|
|
|||
|
|
@ -739,7 +739,9 @@ int main(int argc, char *argv[]) {
|
|||
r = pa_signal_init(mainloop_api);
|
||||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
||||
fprintf(stderr, "pa_context_new() failed.\n");
|
||||
|
|
|
|||
|
|
@ -338,7 +338,9 @@ int main(int argc, char *argv[]) {
|
|||
r = pa_signal_init(mainloop_api);
|
||||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
/* Create a new connection context */
|
||||
if (!(context = pa_context_new(mainloop_api, client_name))) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "xmalloc.h"
|
||||
#include "llist.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
/*#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->tag = tag;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += timeout;
|
||||
|
||||
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 <signal.h>
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "pid.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
|
@ -130,6 +134,10 @@ int pa_pid_file_create(void) {
|
|||
pid_t pid;
|
||||
size_t l;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
HANDLE process;
|
||||
#endif
|
||||
|
||||
pa_runtime_path("pid", fn, sizeof(fn));
|
||||
|
||||
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)
|
||||
pa_log(__FILE__": corrupt PID file, overwriting.\n");
|
||||
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) {
|
||||
#endif
|
||||
pa_log(__FILE__": daemon already running.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -198,6 +211,12 @@ int pa_pid_file_remove(void) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
pa_lock_fd(fd, 0);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
#endif
|
||||
|
||||
if (unlink(fn) < 0) {
|
||||
pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno));
|
||||
goto fail;
|
||||
|
|
@ -223,6 +242,8 @@ int pa_pid_file_check_running(pid_t *pid) {
|
|||
return pa_pid_file_kill(0, pid);
|
||||
}
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
|
||||
/* Kill a current running daemon. Return non-zero on success, -1
|
||||
* otherwise. If successful *pid contains the PID of the daemon
|
||||
* process. */
|
||||
|
|
@ -242,7 +263,7 @@ int pa_pid_file_kill(int sig, pid_t *pid) {
|
|||
|
||||
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
|
||||
goto fail;
|
||||
|
||||
|
||||
ret = kill(*pid, sig);
|
||||
|
||||
fail:
|
||||
|
|
@ -255,3 +276,11 @@ fail:
|
|||
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 <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.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-context.h"
|
||||
|
|
@ -110,8 +121,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
|
|||
c->autospawn_lock_fd = -1;
|
||||
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
|
||||
c->do_autospawn = 0;
|
||||
|
||||
|
||||
#ifdef SIGPIPE
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
#endif
|
||||
|
||||
c->conf = pa_client_conf_new();
|
||||
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);
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
|
||||
static int context_connect_spawn(struct pa_context *c) {
|
||||
pid_t pid;
|
||||
int status, r;
|
||||
|
|
@ -485,6 +500,8 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
#endif /* OS_IS_WIN32 */
|
||||
|
||||
static int try_next_connection(struct pa_context *c) {
|
||||
char *u = NULL;
|
||||
int r = -1;
|
||||
|
|
@ -499,10 +516,12 @@ static int try_next_connection(struct pa_context *c) {
|
|||
|
||||
if (!u) {
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
if (c->do_autospawn) {
|
||||
r = context_connect_spawn(c);
|
||||
goto finish;
|
||||
}
|
||||
#endif
|
||||
|
||||
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
|
||||
goto finish;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ struct pa_stream {
|
|||
uint32_t requested_bytes;
|
||||
uint64_t counter;
|
||||
pa_usec_t previous_time;
|
||||
pa_usec_t previous_ipol_time;
|
||||
enum pa_stream_state state;
|
||||
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->previous_time = 0;
|
||||
s->previous_ipol_time = 0;
|
||||
|
||||
s->corked = 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;
|
||||
}
|
||||
|
||||
gettimeofday(&tv2, NULL);
|
||||
pa_gettimeofday(&tv2);
|
||||
pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC);
|
||||
|
||||
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;
|
||||
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 */
|
||||
|
||||
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);
|
||||
goto finish;
|
||||
} else {
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
|
||||
if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
|
||||
/* 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, s->channel);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
pa_tagstruct_put_timeval(t, &now);
|
||||
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);
|
||||
else if (s->corked && !b)
|
||||
/* Unpausing */
|
||||
gettimeofday(&s->ipol_timestamp, NULL);
|
||||
pa_gettimeofday(&s->ipol_timestamp);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
s->previous_time = 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);
|
||||
}
|
||||
|
||||
if (usec < s->previous_time)
|
||||
usec = s->previous_time;
|
||||
if (usec < s->previous_ipol_time)
|
||||
usec = s->previous_ipol_time;
|
||||
|
||||
s->previous_ipol_time = usec;
|
||||
|
||||
s->previous_time = usec;
|
||||
return usec;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -239,11 +239,14 @@ static void* connection_write(struct connection *c, size_t length) {
|
|||
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);
|
||||
|
||||
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) {
|
||||
|
|
@ -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));
|
||||
|
||||
ss.rate = rate;
|
||||
format_esd2native(format, &ss);
|
||||
format_esd2native(format, c->swap_byte_order, &ss);
|
||||
|
||||
if (!pa_sample_spec_valid(&ss)) {
|
||||
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));
|
||||
|
||||
ss.rate = rate;
|
||||
format_esd2native(format, &ss);
|
||||
format_esd2native(format, c->swap_byte_order, &ss);
|
||||
|
||||
if (!pa_sample_spec_valid(&ss)) {
|
||||
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;
|
||||
else {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
|
||||
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)));
|
||||
|
||||
|
|
@ -1099,7 +1101,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
|
||||
if (!c->authorized) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += AUTH_TIMEOUT;
|
||||
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
||||
} 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_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
||||
pa_tagstruct_put_timeval(reply, &tv);
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
pa_tagstruct_put_timeval(reply, &now);
|
||||
pa_tagstruct_putu64(reply, counter);
|
||||
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_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
||||
pa_tagstruct_put_timeval(reply, &tv);
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
pa_tagstruct_put_timeval(reply, &now);
|
||||
pa_tagstruct_putu64(reply, counter);
|
||||
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) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
tv.tv_sec += AUTH_TIMEOUT;
|
||||
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -27,7 +27,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "pstream.h"
|
||||
#include "queue.h"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -31,13 +35,16 @@
|
|||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
#define RANDOM_DEVICE "/dev/urandom"
|
||||
#endif
|
||||
|
||||
void pa_random(void *ret_data, size_t length) {
|
||||
int fd;
|
||||
ssize_t r = 0;
|
||||
assert(ret_data && length);
|
||||
|
||||
|
||||
#ifdef RANDOM_DEVICE
|
||||
if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((size_t) r != length) {
|
||||
uint8_t *p;
|
||||
size_t l;
|
||||
|
||||
|
||||
#ifdef RANDOM_DEVICE
|
||||
pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
|
||||
", 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--)
|
||||
*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;
|
||||
|
||||
for (d = 0;; d += sizeof(float)) {
|
||||
float_t sum = 0;
|
||||
pa_volume_t sum = 0;
|
||||
unsigned c;
|
||||
|
||||
if (d >= length)
|
||||
|
|
|
|||
|
|
@ -51,11 +51,19 @@ enum pa_sample_format {
|
|||
#define PA_SAMPLE_S16NE PA_SAMPLE_S16BE
|
||||
/** 32 Bit IEEE floating point, native endian */
|
||||
#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
|
||||
/** Signed 16 Bit PCM, native endian */
|
||||
#define PA_SAMPLE_S16NE PA_SAMPLE_S16LE
|
||||
/** 32 Bit IEEE floating point, native endian */
|
||||
#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
|
||||
|
||||
/** A Shortcut for PA_SAMPLE_FLOAT32NE */
|
||||
|
|
|
|||
|
|
@ -32,7 +32,14 @@
|
|||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "scache.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);
|
||||
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||
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;
|
||||
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)
|
||||
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) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
struct timeval ntv;
|
||||
gettimeofday(&ntv, NULL);
|
||||
pa_gettimeofday(&ntv);
|
||||
ntv.tv_sec += UNLOAD_POLL_TIME;
|
||||
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;
|
||||
const char *e;
|
||||
|
||||
if (!(e = strrchr(pathname, '/')))
|
||||
e = pathname;
|
||||
else
|
||||
e++;
|
||||
e = pa_path_get_filename(pathname);
|
||||
|
||||
if (stat(pathname, &st) < 0) {
|
||||
pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(S_ISREG) && defined(S_ISLNK)
|
||||
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
|
||||
#endif
|
||||
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 */
|
||||
if (!(dir = opendir(pathname))) {
|
||||
#ifdef HAVE_GLOB_H
|
||||
glob_t p;
|
||||
unsigned int i;
|
||||
/* 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]);
|
||||
|
||||
globfree(&p);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
struct dirent *e;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,14 +31,29 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_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>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBASYNCNS
|
||||
#include <asyncns.h>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "socket-client.h"
|
||||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
|
@ -120,7 +135,7 @@ static void do_call(struct pa_socket_client *c) {
|
|||
goto finish;
|
||||
|
||||
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));
|
||||
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));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
|
||||
struct sockaddr_un sa;
|
||||
assert(m && filename);
|
||||
|
||||
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);
|
||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||
|
||||
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) {
|
||||
assert(c);
|
||||
assert(sa);
|
||||
|
|
@ -377,7 +402,7 @@ static void start_timeout(struct pa_socket_client *c) {
|
|||
assert(c);
|
||||
assert(!c->timeout_event);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
pa_gettimeofday(&tv);
|
||||
pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
|
||||
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);
|
||||
start_timeout(c);
|
||||
}
|
||||
#else
|
||||
#else /* HAVE_LIBASYNCNS */
|
||||
{
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
int ret;
|
||||
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 ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
|
||||
start_timeout(c);
|
||||
start_timeout(c);
|
||||
}
|
||||
|
||||
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 <sys/socket.h>
|
||||
|
||||
#include "mainloop-api.h"
|
||||
#include "iochannel.h"
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
struct pa_socket_client;
|
||||
|
||||
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 <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_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>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBWRAP
|
||||
#include <tcpd.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
#include "inet_ntop.h"
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "socket-server.h"
|
||||
#include "socket-util.h"
|
||||
#include "xmalloc.h"
|
||||
|
|
@ -137,6 +156,8 @@ struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *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) {
|
||||
int fd = -1;
|
||||
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);
|
||||
|
||||
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));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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);
|
||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||
|
||||
|
|
@ -182,6 +203,14 @@ fail:
|
|||
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 *ss;
|
||||
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);
|
||||
|
||||
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_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);
|
||||
|
||||
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_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) {
|
||||
case SOCKET_SERVER_IPV6: {
|
||||
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));
|
||||
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: {
|
||||
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));
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,16 +31,33 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.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>
|
||||
|
||||
#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>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
|
@ -57,6 +74,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
|||
return;
|
||||
}
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
if (S_ISSOCK(st.st_mode)) {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
|
|
@ -77,7 +95,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
|||
ip & 0xFF,
|
||||
ntohs(sa.in.sin_port));
|
||||
return;
|
||||
} else if (sa.sa.sa_family == AF_LOCAL) {
|
||||
} else if (sa.sa.sa_family == AF_UNIX) {
|
||||
snprintf(c, l, "UNIX socket client");
|
||||
return;
|
||||
}
|
||||
|
|
@ -89,17 +107,18 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
|
|||
snprintf(c, l, "STDIN/STDOUT client");
|
||||
return;
|
||||
}
|
||||
#endif /* OS_IS_WIN32 */
|
||||
|
||||
snprintf(c, l, "Unknown client");
|
||||
}
|
||||
|
||||
int pa_socket_low_delay(int fd) {
|
||||
#ifdef SO_PRIORITY
|
||||
int priority;
|
||||
assert(fd >= 0);
|
||||
|
||||
#ifdef SO_PRIORITY
|
||||
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;
|
||||
#endif
|
||||
|
||||
|
|
@ -114,12 +133,13 @@ int pa_socket_tcp_low_delay(int fd) {
|
|||
ret = pa_socket_low_delay(fd);
|
||||
|
||||
on = 1;
|
||||
tos = 0;
|
||||
|
||||
#if defined(SOL_TCP) || defined(IPPROTO_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
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
|
||||
#endif
|
||||
ret = -1;
|
||||
#endif
|
||||
|
|
@ -128,9 +148,9 @@ int pa_socket_tcp_low_delay(int fd) {
|
|||
defined(IPPROTO_IP))
|
||||
tos = IPTOS_LOWDELAY;
|
||||
#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
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
|
||||
#endif
|
||||
ret = -1;
|
||||
#endif
|
||||
|
|
@ -142,7 +162,7 @@ int pa_socket_tcp_low_delay(int fd) {
|
|||
int pa_socket_set_rcvbuf(int fd, size_t l) {
|
||||
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)); */
|
||||
/* 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) {
|
||||
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)); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
|
@ -161,16 +181,18 @@ int pa_socket_set_sndbuf(int fd, size_t l) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
int pa_unix_socket_is_stale(const char *fn) {
|
||||
struct sockaddr_un sa;
|
||||
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));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
sa.sun_family = AF_LOCAL;
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
|
||||
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
|
||||
|
||||
|
|
@ -202,3 +224,15 @@ int pa_unix_socket_remove_stale(const char *fn) {
|
|||
|
||||
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 <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "tagstruct.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
|
@ -118,7 +123,8 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
|
|||
assert(t);
|
||||
extend(t, 5);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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) {
|
||||
uint32_t rate;
|
||||
assert(t && ss);
|
||||
extend(t, 7);
|
||||
t->data[t->length] = TAG_SAMPLE_SPEC;
|
||||
t->data[t->length+1] = (uint8_t) ss->format;
|
||||
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;
|
||||
}
|
||||
|
||||
void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
|
||||
uint32_t tmp;
|
||||
assert(t && p);
|
||||
|
||||
extend(t, 5+length);
|
||||
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)
|
||||
memcpy(t->data+t->length+5, p, 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) {
|
||||
uint32_t tmp;
|
||||
assert(t);
|
||||
extend(t, 9);
|
||||
t->data[t->length] = TAG_TIMEVAL;
|
||||
*((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec);
|
||||
*((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec);
|
||||
tmp = htonl(tv->tv_sec);
|
||||
memcpy(t->data+t->length+1, &tmp, 4);
|
||||
tmp = htonl(tv->tv_usec);
|
||||
memcpy(t->data+t->length+5, &tmp, 4);
|
||||
t->length += 9;
|
||||
}
|
||||
|
||||
void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) {
|
||||
uint32_t tmp;
|
||||
assert(t);
|
||||
extend(t, 9);
|
||||
t->data[t->length] = TAG_USEC;
|
||||
*((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
|
||||
*((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
|
||||
tmp = htonl((uint32_t) (u >> 32));
|
||||
memcpy(t->data+t->length+1, &tmp, 4);
|
||||
tmp = htonl((uint32_t) u);
|
||||
memcpy(t->data+t->length+5, &tmp, 4);
|
||||
t->length += 9;
|
||||
}
|
||||
|
||||
void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) {
|
||||
uint32_t tmp;
|
||||
assert(t);
|
||||
extend(t, 9);
|
||||
t->data[t->length] = TAG_U64;
|
||||
*((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
|
||||
*((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
|
||||
tmp = htonl((uint32_t) (u >> 32));
|
||||
memcpy(t->data+t->length+1, &tmp, 4);
|
||||
tmp = htonl((uint32_t) u);
|
||||
memcpy(t->data+t->length+5, &tmp, 4);
|
||||
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)
|
||||
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;
|
||||
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->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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
|
||||
uint32_t len;
|
||||
assert(t && p);
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
*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)
|
||||
return -1;
|
||||
|
||||
tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
|
||||
tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
||||
|
||||
memcpy(&tv->tv_sec, t->data+t->rindex+1, 4);
|
||||
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;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
|
||||
uint32_t tmp;
|
||||
assert(t && u);
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
*u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
|
||||
*u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
||||
memcpy(&tmp, t->data+t->rindex+1, 4);
|
||||
*u = (pa_usec_t) ntohl(tmp) << 32;
|
||||
memcpy(&tmp, t->data+t->rindex+5, 4);
|
||||
*u |= (pa_usec_t) ntohl(tmp);
|
||||
t->rindex +=9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
|
||||
uint32_t tmp;
|
||||
assert(t && u);
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
*u = (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
|
||||
*u |= (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
||||
memcpy(&tmp, t->data+t->rindex+1, 4);
|
||||
*u = (pa_usec_t) ntohl(tmp) << 32;
|
||||
memcpy(&tmp, t->data+t->rindex+5, 4);
|
||||
*u |= (pa_usec_t) ntohl(tmp);
|
||||
t->rindex +=9;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
355
polyp/util.c
355
polyp/util.c
|
|
@ -32,35 +32,98 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#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 "xmalloc.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
#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 */
|
||||
void pa_make_nonblock_fd(int fd) {
|
||||
#ifdef O_NONBLOCK
|
||||
int v;
|
||||
assert(fd >= 0);
|
||||
|
||||
if ((v = fcntl(fd, F_GETFL)) >= 0)
|
||||
if (!(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 */
|
||||
|
|
@ -68,15 +131,27 @@ int pa_make_secure_dir(const char* dir) {
|
|||
struct stat st;
|
||||
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)
|
||||
return -1;
|
||||
|
||||
if (lstat(dir, &st) < 0)
|
||||
|
||||
#ifdef HAVE_LSTAT
|
||||
if (lstat(dir, &st) < 0)
|
||||
#else
|
||||
if (stat(dir, &st) < 0)
|
||||
#endif
|
||||
goto fail;
|
||||
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
|
||||
goto fail;
|
||||
#else
|
||||
fprintf(stderr, "FIXME: pa_make_secure_dir()\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -89,10 +164,11 @@ fail:
|
|||
int pa_make_secure_parent_dir(const char *fn) {
|
||||
int ret = -1;
|
||||
char *slash, *dir = pa_xstrdup(fn);
|
||||
|
||||
if (!(slash = strrchr(dir, '/')))
|
||||
|
||||
slash = pa_path_get_filename(dir);
|
||||
if (slash == fn)
|
||||
goto finish;
|
||||
*slash = 0;
|
||||
*(slash-1) = 0;
|
||||
|
||||
if (pa_make_secure_dir(dir) < 0)
|
||||
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
|
||||
* blocked or trapped */
|
||||
void pa_check_signal_is_blocked(int sig) {
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction sa;
|
||||
sigset_t set;
|
||||
|
||||
|
|
@ -185,6 +262,9 @@ void pa_check_signal_is_blocked(int sig) {
|
|||
return;
|
||||
|
||||
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
|
||||
|
|
@ -240,29 +320,46 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
|
|||
|
||||
/* Return the current username in the specified string buffer. */
|
||||
char *pa_get_user_name(char *s, size_t l) {
|
||||
struct passwd pw, *r;
|
||||
char buf[1024];
|
||||
char *p;
|
||||
char buf[1024];
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
struct passwd pw, *r;
|
||||
#endif
|
||||
|
||||
assert(s && l > 0);
|
||||
|
||||
if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
|
||||
#ifdef HAVE_PWD_H
|
||||
|
||||
#ifdef HAVE_GETPWUID_R
|
||||
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
|
||||
#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) {
|
||||
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
|
||||
* that do not support getpwuid_r. */
|
||||
if ((r = getpwuid(getuid())) == NULL) {
|
||||
#endif
|
||||
snprintf(s, l, "%lu", (unsigned long) getuid());
|
||||
return s;
|
||||
}
|
||||
|
||||
p = r->pw_name;
|
||||
snprintf(s, l, "%lu", (unsigned long) getuid());
|
||||
return s;
|
||||
}
|
||||
|
||||
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 the current hostname in the specified buffer. */
|
||||
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 */
|
||||
char *pa_get_home_dir(char *s, size_t l) {
|
||||
char *e;
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
char buf[1024];
|
||||
struct passwd pw, *r;
|
||||
#endif
|
||||
|
||||
assert(s && l);
|
||||
|
||||
if ((e = getenv("HOME")))
|
||||
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) {
|
||||
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 pa_strlcpy(s, r->pw_dir, l);
|
||||
#else /* HAVE_PWD_H */
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Similar to OpenBSD's strlcpy() function */
|
||||
|
|
@ -302,6 +417,42 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
|
|||
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
|
||||
* timestamsps. */
|
||||
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) {
|
||||
struct timeval now;
|
||||
assert(tv);
|
||||
gettimeofday(&now, NULL);
|
||||
pa_gettimeofday(&now);
|
||||
return pa_timeval_diff(&now, tv);
|
||||
}
|
||||
|
||||
|
|
@ -380,10 +531,12 @@ sensible: set the nice level to -15 and enable realtime scheduling if
|
|||
supported.*/
|
||||
void pa_raise_priority(void) {
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
|
||||
pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno));
|
||||
else
|
||||
pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL);
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||
{
|
||||
|
|
@ -403,10 +556,21 @@ void pa_raise_priority(void) {
|
|||
pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n");
|
||||
}
|
||||
#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() */
|
||||
void pa_reset_priority(void) {
|
||||
#ifdef OS_IS_WIN32
|
||||
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||
{
|
||||
struct sched_param sp;
|
||||
|
|
@ -416,11 +580,15 @@ void pa_reset_priority(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
setpriority(PRIO_PROCESS, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set the FD_CLOEXEC flag for a fd */
|
||||
int pa_fd_set_cloexec(int fd, int b) {
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
int v;
|
||||
assert(fd >= 0);
|
||||
|
||||
|
|
@ -431,7 +599,8 @@ int pa_fd_set_cloexec(int fd, int b) {
|
|||
|
||||
if (fcntl(fd, F_SETFD, v) < 0)
|
||||
return -1;
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
* non-NULL! */
|
||||
char *pa_get_binary_name(char *s, size_t l) {
|
||||
|
||||
#ifdef HAVE_READLINK
|
||||
char path[PATH_MAX];
|
||||
int i;
|
||||
assert(s && l);
|
||||
|
|
@ -451,6 +622,15 @@ char *pa_get_binary_name(char *s, size_t l) {
|
|||
|
||||
s[i] = 0;
|
||||
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
|
||||
|
|
@ -458,7 +638,7 @@ char *pa_get_binary_name(char *s, size_t l) {
|
|||
char *pa_path_get_filename(const char *p) {
|
||||
char *fn;
|
||||
|
||||
if ((fn = strrchr(p, '/')))
|
||||
if ((fn = strrchr(p, PATH_SEP)))
|
||||
return fn+1;
|
||||
|
||||
return (char*) p;
|
||||
|
|
@ -519,16 +699,29 @@ const char *pa_strsignal(int sig) {
|
|||
switch(sig) {
|
||||
case SIGINT: return "SIGINT";
|
||||
case SIGTERM: return "SIGTERM";
|
||||
#ifdef SIGUSR1
|
||||
case SIGUSR1: return "SIGUSR1";
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
case SIGUSR2: return "SIGUSR2";
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
case SIGXCPU: return "SIGXCPU";
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
case SIGPIPE: return "SIGPIPE";
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
case SIGCHLD: return "SIGCHLD";
|
||||
#endif
|
||||
#ifdef SIGHUP
|
||||
case SIGHUP: return "SIGHUP";
|
||||
#endif
|
||||
default: return "UNKNOWN SIGNAL";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GRP_H
|
||||
|
||||
/* Check whether the specified GID and the group name match */
|
||||
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 */
|
||||
int pa_uid_in_group(const char *name, gid_t *gid) {
|
||||
gid_t *gids, tgid;
|
||||
long n = sysconf(_SC_NGROUPS_MAX);
|
||||
GETGROUPS_T n = sysconf(_SC_NGROUPS_MAX);
|
||||
int r = -1, i;
|
||||
|
||||
assert(n > 0);
|
||||
|
|
@ -609,8 +802,18 @@ finish:
|
|||
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) {
|
||||
#ifdef F_SETLKW
|
||||
struct flock flock;
|
||||
|
||||
/* 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));
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -722,31 +938,51 @@ int pa_unlock_lockfile(const char *fn, int fd) {
|
|||
* allocated buffer containing the used configuration file is
|
||||
* stored there.*/
|
||||
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];
|
||||
|
||||
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)
|
||||
*result = pa_xstrdup(e);
|
||||
return fopen(e, "r");
|
||||
*result = pa_xstrdup(fn);
|
||||
|
||||
return fopen(fn, "r");
|
||||
}
|
||||
|
||||
if (local && pa_get_home_dir(h, sizeof(h))) {
|
||||
FILE *f;
|
||||
char *l;
|
||||
char *lfn;
|
||||
|
||||
l = pa_sprintf_malloc("%s/%s", h, local);
|
||||
f = fopen(l, "r");
|
||||
lfn = pa_sprintf_malloc("%s/%s", h, local);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
|
||||
return NULL;
|
||||
lfn = buf;
|
||||
#endif
|
||||
|
||||
f = fopen(lfn, "r");
|
||||
|
||||
if (f || errno != ENOENT) {
|
||||
if (result)
|
||||
*result = l;
|
||||
else
|
||||
pa_xfree(l);
|
||||
*result = pa_xstrdup(lfn);
|
||||
pa_xfree(lfn);
|
||||
return f;
|
||||
}
|
||||
|
||||
pa_xfree(l);
|
||||
pa_xfree(lfn);
|
||||
}
|
||||
|
||||
if (!global) {
|
||||
|
|
@ -756,6 +992,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
|
||||
return NULL;
|
||||
global = buf;
|
||||
#endif
|
||||
|
||||
if (result)
|
||||
*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 */
|
||||
char *pa_get_fqdn(char *s, size_t l) {
|
||||
char hn[256];
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo *a, hints;
|
||||
#endif
|
||||
|
||||
if (!pa_get_host_name(hn, sizeof(hn)))
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
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);
|
||||
freeaddrinfo(a);
|
||||
return s;
|
||||
#else
|
||||
return pa_strlcpy(s, hn, l);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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 u[256];
|
||||
|
||||
#ifndef OS_IS_WIN32
|
||||
if (fn && *fn == '/')
|
||||
#else
|
||||
if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
/* Wait t milliseconds */
|
||||
int pa_msleep(unsigned long t) {
|
||||
#ifdef OS_IS_WIN32
|
||||
Sleep(t);
|
||||
return 0;
|
||||
#elif defined(HAVE_NANOSLEEP)
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = t/1000;
|
||||
ts.tv_nsec = (t % 1000) * 1000000;
|
||||
|
||||
return nanosleep(&ts, NULL);
|
||||
#else
|
||||
#error "Platform lacks a sleep function."
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert the string s to a signed integer in *ret_i */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#include "gcc-printf.h"
|
||||
#include "sample.h"
|
||||
|
||||
struct timeval;
|
||||
|
||||
void pa_make_nonblock_fd(int fd);
|
||||
|
||||
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);
|
||||
|
||||
int pa_gettimeofday(struct timeval *tv);
|
||||
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);
|
||||
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 const char e[] = "Not enough memory\n";
|
||||
pa_loop_write(STDERR_FILENO, e, sizeof(e)-1);
|
||||
#ifdef SIGQUIT
|
||||
raise(SIGQUIT);
|
||||
#endif
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue