Port to Windows. This is mostly glue layers for the poor POSIX support

on Windows. A few notes

 * Only sockets behave somewhat like file descriptors in UNIX.

 * There are no fixed paths. Closes thing is environment variables that point
   to system directories. We also figure out where the binary/dll is
   located and use that as configuration directory.


git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@418 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Pierre Ossman 2006-01-05 22:51:37 +00:00
parent 2f74bb9d43
commit 19d9fcbda8
22 changed files with 712 additions and 58 deletions

View file

@ -138,7 +138,7 @@ AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0])
AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"]) AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"])
# Windows # Windows
AC_CHECK_HEADERS([winsock2.h ws2tcpip.h]) AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
# Other # Other
AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([sys/ioctl.h])

View file

@ -298,6 +298,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \
cdecl.h \ cdecl.h \
client-conf.c client-conf.h \ client-conf.c client-conf.h \
conf-parser.c conf-parser.h \ conf-parser.c conf-parser.h \
dllmain.c \
dynarray.c dynarray.h \ dynarray.c dynarray.h \
gcc-printf.h \ gcc-printf.h \
idxset.c idxset.h \ idxset.c idxset.h \
@ -432,6 +433,7 @@ libpolypcore_la_SOURCES = \
cli-text.c cli-text.h \ cli-text.c cli-text.h \
client.c client.h \ client.c client.h \
core.c core.h \ core.c core.h \
dllmain.c \
dynarray.c dynarray.h \ dynarray.c dynarray.h \
endianmacros.h \ endianmacros.h \
g711.c g711.h \ g711.c g711.h \
@ -562,7 +564,7 @@ libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la
libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_SOURCES = iochannel.c iochannel.h
libiochannel_la_LDFLAGS = -avoid-version libiochannel_la_LDFLAGS = -avoid-version
libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la $(WINSOCK_LIBS)
libpacket_la_SOURCES = packet.c packet.h libpacket_la_SOURCES = packet.c packet.h
libpacket_la_LDFLAGS = -avoid-version libpacket_la_LDFLAGS = -avoid-version
@ -727,6 +729,11 @@ modlib_LTLIBRARIES += \
module-mmkbd-evdev.la module-mmkbd-evdev.la
endif endif
if OS_IS_WIN32
modlib_LTLIBRARIES += \
module-waveout.la
endif
# These are generated by a M4 script # These are generated by a M4 script
SYMDEF_FILES = \ SYMDEF_FILES = \
@ -766,7 +773,8 @@ SYMDEF_FILES = \
module-oss-symdef.h \ module-oss-symdef.h \
module-oss-mmap-symdef.h \ module-oss-mmap-symdef.h \
module-alsa-sink-symdef.h \ module-alsa-sink-symdef.h \
module-alsa-source-symdef.h module-alsa-source-symdef.h \
module-waveout-symdef.h
EXTRA_DIST += $(SYMDEF_FILES) EXTRA_DIST += $(SYMDEF_FILES)
BUILT_SOURCES += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES)
@ -974,6 +982,13 @@ module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version
module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD)
module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS)
# Windows waveout
module_waveout_la_SOURCES = module-waveout.c
module_waveout_la_LDFLAGS = -module -avoid-version
module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm
module_waveout_la_CFLAGS = $(AM_CFLAGS)
################################### ###################################
# Some minor stuff # # Some minor stuff #
################################### ###################################
@ -990,8 +1005,13 @@ esdcompat.sh: esdcompat.sh.in Makefile
client.conf: client.conf.in Makefile client.conf: client.conf.in Makefile
sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
if OS_IS_WIN32
default.pa: default.pa.win32
cp $< $@
else
default.pa: default.pa.in Makefile default.pa: default.pa.in Makefile
sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
endif
daemon.conf: daemon.conf.in Makefile daemon.conf: daemon.conf.in Makefile
sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \

View file

@ -19,6 +19,10 @@
USA. USA.
***/ ***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
@ -33,11 +37,21 @@
#include "authkey.h" #include "authkey.h"
#ifndef DEFAULT_CONFIG_DIR #ifndef DEFAULT_CONFIG_DIR
#define DEFAULT_CONFIG_DIR "/etc/polypaudio" # ifndef OS_IS_WIN32
# define DEFAULT_CONFIG_DIR "/etc/polypaudio"
# else
# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
# endif
#endif #endif
#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf" #ifndef OS_IS_WIN32
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf" # define PATH_SEP "/"
#else
# define PATH_SEP "\\"
#endif
#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "client.conf"
#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG"
#define ENV_DEFAULT_SINK "POLYP_SINK" #define ENV_DEFAULT_SINK "POLYP_SINK"

View file

@ -37,13 +37,23 @@
#include "resampler.h" #include "resampler.h"
#ifndef DEFAULT_CONFIG_DIR #ifndef DEFAULT_CONFIG_DIR
#define DEFAULT_CONFIG_DIR "/etc/polypaudio" # ifndef OS_IS_WIN32
# define DEFAULT_CONFIG_DIR "/etc/polypaudio"
# else
# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
# endif
#endif #endif
#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa" #ifndef OS_IS_WIN32
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa" # define PATH_SEP "/"
#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf" #else
#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf" # define PATH_SEP "\\"
#endif
#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
#define DEFAULT_SCRIPT_FILE_USER ".polypaudio" PATH_SEP "default.pa"
#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
#define DEFAULT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "daemon.conf"
#define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_SCRIPT_FILE "POLYP_SCRIPT"
#define ENV_CONFIG_FILE "POLYP_CONFIG" #define ENV_CONFIG_FILE "POLYP_CONFIG"

43
polyp/default.pa.win32 Normal file
View 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
View 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 */

View file

@ -28,6 +28,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#include "iochannel.h" #include "iochannel.h"
#include "util.h" #include "util.h"
#include "socket-util.h" #include "socket-util.h"
@ -189,7 +193,19 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) {
ssize_t r; ssize_t r;
assert(io && data && l && io->ofd >= 0); assert(io && data && l && io->ofd >= 0);
if ((r = write(io->ofd, data, l)) >= 0) { #ifdef OS_IS_WIN32
r = send(io->ofd, data, l, 0);
if (r < 0) {
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
return r;
}
}
if (r < 0)
#endif
r = write(io->ofd, data, l);
if (r >= 0) {
io->writable = 0; io->writable = 0;
enable_mainloop_sources(io); enable_mainloop_sources(io);
} }
@ -201,7 +217,19 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) {
ssize_t r; ssize_t r;
assert(io && data && io->ifd >= 0); assert(io && data && io->ifd >= 0);
if ((r = read(io->ifd, data, l)) >= 0) { #ifdef OS_IS_WIN32
r = recv(io->ifd, data, l, 0);
if (r < 0) {
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
return r;
}
}
if (r < 0)
#endif
r = read(io->ifd, data, l);
if (r >= 0) {
io->readable = 0; io->readable = 0;
enable_mainloop_sources(io); enable_mainloop_sources(io);
} }

View file

@ -35,7 +35,16 @@
#include <memblock.h> #include <memblock.h>
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_LIBWRAP #ifdef HAVE_LIBWRAP
#include <syslog.h> #include <syslog.h>
@ -66,6 +75,23 @@ int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING; int deny_severity = LOG_WARNING;
#endif #endif
#ifdef OS_IS_WIN32
static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
raise(SIGTERM);
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
#endif
static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig)); pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
@ -124,6 +150,10 @@ int main(int argc, char *argv[]) {
gid_t gid = (gid_t) -1; gid_t gid = (gid_t) -1;
#endif #endif
#ifdef OS_IS_WIN32
struct pa_defer_event *defer;
#endif
pa_limit_caps(); pa_limit_caps();
#ifdef HAVE_GETUID #ifdef HAVE_GETUID
@ -142,6 +172,13 @@ int main(int argc, char *argv[]) {
r = lt_dlinit(); r = lt_dlinit();
assert(r == 0); assert(r == 0);
#ifdef OS_IS_WIN32
{
WSADATA data;
WSAStartup(MAKEWORD(2, 0), &data);
}
#endif
pa_log_set_ident("polypaudio"); pa_log_set_ident("polypaudio");
conf = pa_daemon_conf_new(); conf = pa_daemon_conf_new();
@ -230,6 +267,7 @@ int main(int argc, char *argv[]) {
goto finish; goto finish;
} }
#ifdef HAVE_FORK
if (pipe(daemon_pipe) < 0) { if (pipe(daemon_pipe) < 0) {
pa_log(__FILE__": failed to create pipe.\n"); pa_log(__FILE__": failed to create pipe.\n");
goto finish; goto finish;
@ -261,6 +299,7 @@ int main(int argc, char *argv[]) {
close(daemon_pipe[0]); close(daemon_pipe[0]);
daemon_pipe[0] = -1; daemon_pipe[0] = -1;
#endif
if (conf->auto_log_target) if (conf->auto_log_target)
pa_log_set_target(PA_LOG_SYSLOG, NULL); pa_log_set_target(PA_LOG_SYSLOG, NULL);
@ -272,6 +311,7 @@ int main(int argc, char *argv[]) {
setpgid(0,0); setpgid(0,0);
#endif #endif
#ifndef OS_IS_WIN32
close(0); close(0);
close(1); close(1);
close(2); close(2);
@ -279,6 +319,9 @@ int main(int argc, char *argv[]) {
open("/dev/null", O_RDONLY); open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY); open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY); open("/dev/null", O_WRONLY);
#else
FreeConsole();
#endif
#ifdef SIGTTOU #ifdef SIGTTOU
signal(SIGTTOU, SIG_IGN); signal(SIGTTOU, SIG_IGN);
@ -290,18 +333,23 @@ int main(int argc, char *argv[]) {
signal(SIGTSTP, SIG_IGN); signal(SIGTSTP, SIG_IGN);
#endif #endif
#ifdef TIOCNOTTY
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
ioctl(tty_fd, TIOCNOTTY, (char*) 0); ioctl(tty_fd, TIOCNOTTY, (char*) 0);
close(tty_fd); close(tty_fd);
} }
#endif
} }
chdir("/"); chdir("/");
if (conf->use_pid_file) { if (conf->use_pid_file) {
if (pa_pid_file_create() < 0) { if (pa_pid_file_create() < 0) {
pa_log(__FILE__": pa_pid_file_create() failed.\n");
#ifdef HAVE_FORK
if (conf->daemonize) if (conf->daemonize)
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
#endif
goto finish; goto finish;
} }
@ -322,6 +370,11 @@ int main(int argc, char *argv[]) {
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif
#ifdef OS_IS_WIN32
defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL);
assert(defer);
#endif
if (conf->daemonize) if (conf->daemonize)
c->running_as_daemon = 1; c->running_as_daemon = 1;
@ -350,17 +403,23 @@ int main(int argc, char *argv[]) {
if (r < 0 && conf->fail) { if (r < 0 && conf->fail) {
pa_log(__FILE__": failed to initialize daemon.\n"); pa_log(__FILE__": failed to initialize daemon.\n");
#ifdef HAVE_FORK
if (conf->daemonize) if (conf->daemonize)
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
#endif
} else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
#ifdef HAVE_FORK
if (conf->daemonize) if (conf->daemonize)
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
#endif
} else { } else {
retval = 0; retval = 0;
#ifdef HAVE_FORK
if (conf->daemonize) if (conf->daemonize)
pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
#endif
c->disallow_module_loading = conf->disallow_module_loading; c->disallow_module_loading = conf->disallow_module_loading;
c->exit_idle_time = conf->exit_idle_time; c->exit_idle_time = conf->exit_idle_time;
@ -379,6 +438,10 @@ int main(int argc, char *argv[]) {
} }
} }
#ifdef OS_IS_WIN32
pa_mainloop_get_api(mainloop)->defer_free(defer);
#endif
pa_core_free(c); pa_core_free(c);
pa_cpu_limit_done(); pa_cpu_limit_done();
@ -397,6 +460,10 @@ finish:
close_pipe(daemon_pipe); close_pipe(daemon_pipe);
#ifdef OS_IS_WIN32
WSACleanup();
#endif
lt_dlexit(); lt_dlexit();
return retval; return retval;

View file

@ -32,6 +32,10 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "mainloop-signal.h" #include "mainloop-signal.h"
#include "util.h" #include "util.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -53,19 +57,70 @@ struct pa_signal_event {
static struct pa_mainloop_api *api = NULL; static struct pa_mainloop_api *api = NULL;
static int signal_pipe[2] = { -1, -1 }; static int signal_pipe[2] = { -1, -1 };
static struct pa_io_event* io_event = NULL; static struct pa_io_event* io_event = NULL;
static struct pa_defer_event *defer_event = NULL;
static struct pa_signal_event *signals = NULL; static struct pa_signal_event *signals = NULL;
#ifdef OS_IS_WIN32
static unsigned int waiting_signals = 0;
static CRITICAL_SECTION crit;
#endif
static void signal_handler(int sig) { static void signal_handler(int sig) {
#ifndef HAVE_SIGACTION #ifndef HAVE_SIGACTION
signal(sig, signal_handler); signal(sig, signal_handler);
#endif #endif
write(signal_pipe[1], &sig, sizeof(sig)); write(signal_pipe[1], &sig, sizeof(sig));
#ifdef OS_IS_WIN32
EnterCriticalSection(&crit);
waiting_signals++;
LeaveCriticalSection(&crit);
#endif
}
static void dispatch(struct pa_mainloop_api*a, int sig) {
struct pa_signal_event*s;
for (s = signals; s; s = s->next)
if (s->sig == sig) {
assert(s->callback);
s->callback(a, s, sig, s->userdata);
break;
}
}
static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata) {
ssize_t r;
int sig;
unsigned int sigs;
#ifdef OS_IS_WIN32
EnterCriticalSection(&crit);
sigs = waiting_signals;
waiting_signals = 0;
LeaveCriticalSection(&crit);
#endif
while (sigs) {
if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) {
pa_log(__FILE__": read(): %s\n", strerror(errno));
return;
}
if (r != sizeof(sig)) {
pa_log(__FILE__": short read()\n");
return;
}
dispatch(a, sig);
sigs--;
}
} }
static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) {
ssize_t r; ssize_t r;
int sig; int sig;
struct pa_signal_event*s;
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
@ -82,18 +137,17 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu
return; return;
} }
for (s = signals; s; s = s->next) dispatch(a, sig);
if (s->sig == sig) {
assert(s->callback);
s->callback(a, s, sig, s->userdata);
break;
}
} }
int pa_signal_init(struct pa_mainloop_api *a) { int pa_signal_init(struct pa_mainloop_api *a) {
assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event);
#ifdef OS_IS_WIN32
if (_pipe(signal_pipe, 200, _O_BINARY) < 0) {
#else
if (pipe(signal_pipe) < 0) { if (pipe(signal_pipe) < 0) {
#endif
pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); pa_log(__FILE__": pipe() failed: %s\n", strerror(errno));
return -1; return -1;
} }
@ -104,20 +158,36 @@ int pa_signal_init(struct pa_mainloop_api *a) {
pa_fd_set_cloexec(signal_pipe[1], 1); pa_fd_set_cloexec(signal_pipe[1], 1);
api = a; api = a;
#ifndef OS_IS_WIN32
io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
assert(io_event); assert(io_event);
#else
defer_event = api->defer_new(api, defer, NULL);
assert(defer_event);
InitializeCriticalSection(&crit);
#endif
return 0; return 0;
} }
void pa_signal_done(void) { void pa_signal_done(void) {
assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || defer_event));
while (signals) while (signals)
pa_signal_free(signals); pa_signal_free(signals);
#ifndef OS_IS_WIN32
api->io_free(io_event); api->io_free(io_event);
io_event = NULL; io_event = NULL;
#else
api->defer_free(defer_event);
defer_event = NULL;
DeleteCriticalSection(&crit);
#endif
close(signal_pipe[0]); close(signal_pipe[0]);
close(signal_pipe[1]); close(signal_pipe[1]);

View file

@ -38,6 +38,10 @@
#include "poll.h" #include "poll.h"
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#include "mainloop.h" #include "mainloop.h"
#include "util.h" #include "util.h"
#include "idxset.h" #include "idxset.h"
@ -108,6 +112,26 @@ static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enu
e->destroy_callback = NULL; e->destroy_callback = NULL;
e->pollfd = NULL; e->pollfd = NULL;
#ifdef OS_IS_WIN32
{
fd_set xset;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO (&xset);
FD_SET (fd, &xset);
if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
SELECT_TYPE_ARG5 &tv) == -1) &&
(WSAGetLastError() == WSAENOTSOCK)) {
pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n");
e->dead = 1;
}
}
#endif
pa_idxset_put(m->io_events, e, NULL); pa_idxset_put(m->io_events, e, NULL);
m->rebuild_pollfds = 1; m->rebuild_pollfds = 1;
return e; return e;

View file

@ -40,6 +40,13 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#include "module.h" #include "module.h"
#include "socket-server.h" #include "socket-server.h"
#include "socket-util.h" #include "socket-util.h"

View file

@ -35,6 +35,10 @@
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "pid.h" #include "pid.h"
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
@ -130,6 +134,10 @@ int pa_pid_file_create(void) {
pid_t pid; pid_t pid;
size_t l; size_t l;
#ifdef OS_IS_WIN32
HANDLE process;
#endif
pa_runtime_path("pid", fn, sizeof(fn)); pa_runtime_path("pid", fn, sizeof(fn));
if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0) if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
@ -138,7 +146,12 @@ int pa_pid_file_create(void) {
if ((pid = read_pid(fn, fd)) == (pid_t) -1) if ((pid = read_pid(fn, fd)) == (pid_t) -1)
pa_log(__FILE__": corrupt PID file, overwriting.\n"); pa_log(__FILE__": corrupt PID file, overwriting.\n");
else if (pid > 0) { else if (pid > 0) {
#ifdef OS_IS_WIN32
if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
CloseHandle(process);
#else
if (kill(pid, 0) >= 0 || errno != ESRCH) { if (kill(pid, 0) >= 0 || errno != ESRCH) {
#endif
pa_log(__FILE__": daemon already running.\n"); pa_log(__FILE__": daemon already running.\n");
goto fail; goto fail;
} }
@ -198,6 +211,12 @@ int pa_pid_file_remove(void) {
goto fail; goto fail;
} }
#ifdef OS_IS_WIN32
pa_lock_fd(fd, 0);
close(fd);
fd = -1;
#endif
if (unlink(fn) < 0) { if (unlink(fn) < 0) {
pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno)); pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno));
goto fail; goto fail;
@ -223,6 +242,8 @@ int pa_pid_file_check_running(pid_t *pid) {
return pa_pid_file_kill(0, pid); return pa_pid_file_kill(0, pid);
} }
#ifndef OS_IS_WIN32
/* Kill a current running daemon. Return non-zero on success, -1 /* Kill a current running daemon. Return non-zero on success, -1
* otherwise. If successful *pid contains the PID of the daemon * otherwise. If successful *pid contains the PID of the daemon
* process. */ * process. */
@ -255,3 +276,11 @@ fail:
return ret; return ret;
} }
#else /* OS_IS_WIN32 */
int pa_pid_file_kill(int sig, pid_t *pid) {
return -1;
}
#endif

View file

@ -36,6 +36,17 @@
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#define EBADF WSAEBADF
#define ESHUTDOWN WSAESHUTDOWN
#define ECONNRESET WSAECONNRESET
#define ECONNABORTED WSAECONNABORTED
#define ENETRESET WSAENETRESET
#endif /* HAVE_WINSOCK2_H */
#ifndef HAVE_SYS_POLL_H #ifndef HAVE_SYS_POLL_H
#include "util.h" #include "util.h"
@ -59,7 +70,16 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
return 0; 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); return select(0, NULL, NULL, NULL, NULL);
#endif
} }
for (f = fds; f < &fds[nfds]; ++f) { for (f = fds; f < &fds[nfds]; ++f) {
@ -138,6 +158,10 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
} }
} }
#ifdef OS_IS_WIN32
errno = WSAGetLastError();
#endif
if (ready > 0) { if (ready > 0) {
ready = 0; ready = 0;
for (f = fds; f < &fds[nfds]; ++f) { for (f = fds; f < &fds[nfds]; ++f) {

View file

@ -32,6 +32,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <limits.h>
#ifdef HAVE_SYS_WAIT_H #ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h> #include <sys/wait.h>
@ -44,6 +45,13 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define EHOSTUNREACH WSAEHOSTUNREACH
#endif
#include "polyplib-internal.h" #include "polyplib-internal.h"
#include "polyplib-context.h" #include "polyplib-context.h"
#include "native-common.h" #include "native-common.h"
@ -382,6 +390,8 @@ finish:
static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata); static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata);
#ifndef OS_IS_WIN32
static int context_connect_spawn(struct pa_context *c) { static int context_connect_spawn(struct pa_context *c) {
pid_t pid; pid_t pid;
int status, r; int status, r;
@ -495,6 +505,8 @@ fail:
return -1; return -1;
} }
#endif /* OS_IS_WIN32 */
static int try_next_connection(struct pa_context *c) { static int try_next_connection(struct pa_context *c) {
char *u = NULL; char *u = NULL;
int r = -1; int r = -1;
@ -509,10 +521,12 @@ static int try_next_connection(struct pa_context *c) {
if (!u) { if (!u) {
#ifndef OS_IS_WIN32
if (c->do_autospawn) { if (c->do_autospawn) {
r = context_connect_spawn(c); r = context_connect_spawn(c);
goto finish; goto finish;
} }
#endif
pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
goto finish; goto finish;

View file

@ -32,6 +32,10 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#include "pstream.h" #include "pstream.h"
#include "queue.h" #include "queue.h"
#include "xmalloc.h" #include "xmalloc.h"

View file

@ -19,6 +19,10 @@
USA. USA.
***/ ***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -31,13 +35,16 @@
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
#ifndef OS_IS_WIN32
#define RANDOM_DEVICE "/dev/urandom" #define RANDOM_DEVICE "/dev/urandom"
#endif
void pa_random(void *ret_data, size_t length) { void pa_random(void *ret_data, size_t length) {
int fd; int fd;
ssize_t r = 0; ssize_t r = 0;
assert(ret_data && length); assert(ret_data && length);
#ifdef RANDOM_DEVICE
if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
@ -45,17 +52,20 @@ void pa_random(void *ret_data, size_t length) {
close(fd); close(fd);
} }
#endif
if ((size_t) r != length) { if ((size_t) r != length) {
uint8_t *p; uint8_t *p;
size_t l; size_t l;
#ifdef RANDOM_DEVICE
pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
", falling back to unsecure pseudo RNG.\n", strerror(errno)); ", falling back to unsecure pseudo RNG.\n", strerror(errno));
#endif
srandom(time(NULL)); srand(time(NULL));
for (p = ret_data, l = length; l > 0; p++, l--) for (p = ret_data, l = length; l > 0; p++, l--)
*p = (uint8_t) random(); *p = (uint8_t) rand();
} }
} }

View file

@ -37,6 +37,10 @@
#include <glob.h> #include <glob.h>
#endif #endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "scache.h" #include "scache.h"
#include "sink-input.h" #include "sink-input.h"
#include "mainloop.h" #include "mainloop.h"
@ -147,6 +151,13 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
struct pa_memchunk chunk; struct pa_memchunk chunk;
int r; int r;
#ifdef OS_IS_WIN32
char buf[MAX_PATH];
if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
filename = buf;
#endif
if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
return -1; return -1;
@ -158,6 +169,14 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) {
struct pa_scache_entry *e; struct pa_scache_entry *e;
#ifdef OS_IS_WIN32
char buf[MAX_PATH];
if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
filename = buf;
#endif
assert(c && name); assert(c && name);
if (!(e = scache_add_item(c, name))) if (!(e = scache_add_item(c, name)))
@ -313,7 +332,9 @@ static void add_file(struct pa_core *c, const char *pathname) {
return; return;
} }
#if defined(S_ISREG) && defined(S_ISLNK)
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
#endif
pa_scache_add_file_lazy(c, e, pathname, NULL); pa_scache_add_file_lazy(c, e, pathname, NULL);
} }

View file

@ -48,6 +48,15 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#define EINPROGRESS WSAEINPROGRESS
#define ETIMEDOUT WSAETIMEDOUT
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_LIBASYNCNS #ifdef HAVE_LIBASYNCNS
#include <asyncns.h> #include <asyncns.h>
#endif #endif

View file

@ -44,6 +44,13 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_LIBWRAP #ifdef HAVE_LIBWRAP
#include <tcpd.h> #include <tcpd.h>
#endif #endif

View file

@ -57,6 +57,11 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#define ETIMEDOUT WSAETIMEDOUT
#endif
#include "socket-util.h" #include "socket-util.h"
#include "util.h" #include "util.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -72,6 +77,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
return; return;
} }
#ifndef OS_IS_WIN32
if (S_ISSOCK(st.st_mode)) { if (S_ISSOCK(st.st_mode)) {
union { union {
struct sockaddr sa; struct sockaddr sa;
@ -104,6 +110,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
snprintf(c, l, "STDIN/STDOUT client"); snprintf(c, l, "STDIN/STDOUT client");
return; return;
} }
#endif /* OS_IS_WIN32 */
snprintf(c, l, "Unknown client"); snprintf(c, l, "Unknown client");
} }

View file

@ -33,6 +33,10 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#include "tagstruct.h" #include "tagstruct.h"
#include "xmalloc.h" #include "xmalloc.h"

View file

@ -32,12 +32,12 @@
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <signal.h>
#include <sys/time.h> #include <sys/time.h>
#include <limits.h>
#include <unistd.h>
#ifdef HAVE_SCHED_H #ifdef HAVE_SCHED_H
#include <sched.h> #include <sched.h>
@ -55,6 +55,17 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#include <samplerate.h> #include <samplerate.h>
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
@ -68,16 +79,56 @@
#include "xmalloc.h" #include "xmalloc.h"
#include "log.h" #include "log.h"
#ifndef OS_IS_WIN32
#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" #define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
#define PATH_SEP '/'
#else
#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\polypaudio-"
#define PATH_SEP '\\'
#endif
#ifdef OS_IS_WIN32
#define POLYP_ROOTENV "POLYP_ROOT"
int pa_set_root(HANDLE handle) {
char library_path[MAX_PATH + sizeof(POLYP_ROOTENV) + 1], *sep;
strcpy(library_path, POLYP_ROOTENV "=");
if (!GetModuleFileName(handle, library_path + sizeof(POLYP_ROOTENV), MAX_PATH))
return 0;
sep = strrchr(library_path, '\\');
if (sep)
*sep = '\0';
if (_putenv(library_path) < 0)
return 0;
return 1;
}
#endif
/** Make a file descriptor nonblock. Doesn't do any error checking */ /** Make a file descriptor nonblock. Doesn't do any error checking */
void pa_make_nonblock_fd(int fd) { void pa_make_nonblock_fd(int fd) {
#ifdef O_NONBLOCK
int v; int v;
assert(fd >= 0); assert(fd >= 0);
if ((v = fcntl(fd, F_GETFL)) >= 0) if ((v = fcntl(fd, F_GETFL)) >= 0)
if (!(v & O_NONBLOCK)) if (!(v & O_NONBLOCK))
fcntl(fd, F_SETFL, v|O_NONBLOCK); fcntl(fd, F_SETFL, v|O_NONBLOCK);
#elif defined(OS_IS_WIN32)
u_long arg = 1;
if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
if (WSAGetLastError() == WSAENOTSOCK)
pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!\n");
}
#else
pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!\n");
#endif
} }
/** Creates a directory securely */ /** Creates a directory securely */
@ -85,15 +136,27 @@ int pa_make_secure_dir(const char* dir) {
struct stat st; struct stat st;
assert(dir); assert(dir);
#ifdef OS_IS_WIN32
if (mkdir(dir) < 0)
#else
if (mkdir(dir, 0700) < 0) if (mkdir(dir, 0700) < 0)
#endif
if (errno != EEXIST) if (errno != EEXIST)
return -1; return -1;
#ifdef OS_IS_WIN32
if (stat(dir, &st) < 0)
#else
if (lstat(dir, &st) < 0) if (lstat(dir, &st) < 0)
#endif
goto fail; goto fail;
#ifndef OS_IS_WIN32
if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
goto fail; goto fail;
#else
fprintf(stderr, "FIXME: pa_make_secure_dir()\n");
#endif
return 0; return 0;
@ -107,9 +170,10 @@ int pa_make_secure_parent_dir(const char *fn) {
int ret = -1; int ret = -1;
char *slash, *dir = pa_xstrdup(fn); char *slash, *dir = pa_xstrdup(fn);
if (!(slash = strrchr(dir, '/'))) slash = pa_path_get_filename(dir);
if (slash == fn)
goto finish; goto finish;
*slash = 0; *(slash-1) = 0;
if (pa_make_secure_dir(dir) < 0) if (pa_make_secure_dir(dir) < 0)
goto finish; goto finish;
@ -285,6 +349,15 @@ char *pa_get_user_name(char *s, size_t l) {
} }
p = r->pw_name; p = r->pw_name;
#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
DWORD size = sizeof(buf);
if (!GetUserName(buf, &size))
return NULL;
p = buf;
#else /* HAVE_PWD_H */ #else /* HAVE_PWD_H */
return NULL; return NULL;
#endif /* HAVE_PWD_H */ #endif /* HAVE_PWD_H */
@ -318,6 +391,9 @@ char *pa_get_home_dir(char *s, size_t l) {
if ((e = getenv("HOME"))) if ((e = getenv("HOME")))
return pa_strlcpy(s, e, l); return pa_strlcpy(s, e, l);
if ((e = getenv("USERPROFILE")))
return pa_strlcpy(s, e, l);
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
#ifdef HAVE_GETPWUID_R #ifdef HAVE_GETPWUID_R
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
@ -349,6 +425,34 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
int pa_gettimeofday(struct timeval *tv) { int pa_gettimeofday(struct timeval *tv) {
#ifdef HAVE_GETTIMEOFDAY #ifdef HAVE_GETTIMEOFDAY
return gettimeofday(tv, NULL); 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 #else
#error "Platform lacks gettimeofday() or equivalent function." #error "Platform lacks gettimeofday() or equivalent function."
#endif #endif
@ -432,10 +536,12 @@ sensible: set the nice level to -15 and enable realtime scheduling if
supported.*/ supported.*/
void pa_raise_priority(void) { void pa_raise_priority(void) {
#ifdef HAVE_SYS_RESOURCE_H
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno)); pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno));
else else
pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL);
#endif
#ifdef _POSIX_PRIORITY_SCHEDULING #ifdef _POSIX_PRIORITY_SCHEDULING
{ {
@ -455,10 +561,21 @@ void pa_raise_priority(void) {
pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n");
} }
#endif #endif
#ifdef OS_IS_WIN32
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X\n", GetLastError());
else
pa_log_info(__FILE__": Successfully gained high priority class.\n");
#endif
} }
/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ /* Reset the priority to normal, inverting the changes made by pa_raise_priority() */
void pa_reset_priority(void) { void pa_reset_priority(void) {
#ifdef OS_IS_WIN32
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
#endif
#ifdef _POSIX_PRIORITY_SCHEDULING #ifdef _POSIX_PRIORITY_SCHEDULING
{ {
struct sched_param sp; struct sched_param sp;
@ -468,11 +585,15 @@ void pa_reset_priority(void) {
} }
#endif #endif
#ifdef HAVE_SYS_RESOURCE_H
setpriority(PRIO_PROCESS, 0, 0); setpriority(PRIO_PROCESS, 0, 0);
#endif
} }
/* Set the FD_CLOEXEC flag for a fd */ /* Set the FD_CLOEXEC flag for a fd */
int pa_fd_set_cloexec(int fd, int b) { int pa_fd_set_cloexec(int fd, int b) {
#ifdef FD_CLOEXEC
int v; int v;
assert(fd >= 0); assert(fd >= 0);
@ -483,6 +604,7 @@ int pa_fd_set_cloexec(int fd, int b) {
if (fcntl(fd, F_SETFD, v) < 0) if (fcntl(fd, F_SETFD, v) < 0)
return -1; return -1;
#endif
return 0; return 0;
} }
@ -491,6 +613,8 @@ int pa_fd_set_cloexec(int fd, int b) {
* only. This shoul be used for eyecandy only, don't rely on return * only. This shoul be used for eyecandy only, don't rely on return
* non-NULL! */ * non-NULL! */
char *pa_get_binary_name(char *s, size_t l) { char *pa_get_binary_name(char *s, size_t l) {
#ifdef HAVE_READLINK
char path[PATH_MAX]; char path[PATH_MAX];
int i; int i;
assert(s && l); assert(s && l);
@ -503,6 +627,15 @@ char *pa_get_binary_name(char *s, size_t l) {
s[i] = 0; s[i] = 0;
return s; return s;
#elif defined(OS_IS_WIN32)
char path[PATH_MAX];
if (!GetModuleFileName(NULL, path, PATH_MAX))
return NULL;
pa_strlcpy(s, pa_path_get_filename(path), l);
return s;
#else
return NULL;
#endif
} }
/* Return a pointer to the filename inside a path (which is the last /* Return a pointer to the filename inside a path (which is the last
@ -510,7 +643,7 @@ char *pa_get_binary_name(char *s, size_t l) {
char *pa_path_get_filename(const char *p) { char *pa_path_get_filename(const char *p) {
char *fn; char *fn;
if ((fn = strrchr(p, '/'))) if ((fn = strrchr(p, PATH_SEP)))
return fn+1; return fn+1;
return (char*) p; return (char*) p;
@ -684,6 +817,7 @@ int pa_uid_in_group(const char *name, gid_t *gid) {
/* Lock or unlock a file entirely. (advisory) */ /* Lock or unlock a file entirely. (advisory) */
int pa_lock_fd(int fd, int b) { int pa_lock_fd(int fd, int b) {
#ifdef F_SETLKW
struct flock flock; struct flock flock;
/* Try a R/W lock first */ /* Try a R/W lock first */
@ -704,6 +838,19 @@ int pa_lock_fd(int fd, int b) {
} }
pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno));
#endif
#ifdef OS_IS_WIN32
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
return 0;
if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
return 0;
pa_log(__FILE__": %slock failed: 0x%08X\n", !b ? "un" : "", GetLastError());
#endif
return -1; return -1;
} }
@ -795,31 +942,51 @@ int pa_unlock_lockfile(const char *fn, int fd) {
* allocated buffer containing the used configuration file is * allocated buffer containing the used configuration file is
* stored there.*/ * stored there.*/
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) { FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
const char *e; const char *fn;
char h[PATH_MAX]; char h[PATH_MAX];
if (env && (e = getenv(env))) { #ifdef OS_IS_WIN32
char buf[PATH_MAX];
if (!getenv(POLYP_ROOTENV))
pa_set_root(NULL);
#endif
if (env && (fn = getenv(env))) {
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
return NULL;
fn = buf;
#endif
if (result) if (result)
*result = pa_xstrdup(e); *result = pa_xstrdup(fn);
return fopen(e, "r");
return fopen(fn, "r");
} }
if (local && pa_get_home_dir(h, sizeof(h))) { if (local && pa_get_home_dir(h, sizeof(h))) {
FILE *f; FILE *f;
char *l; char *lfn;
l = pa_sprintf_malloc("%s/%s", h, local); lfn = pa_sprintf_malloc("%s/%s", h, local);
f = fopen(l, "r");
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
return NULL;
lfn = buf;
#endif
f = fopen(lfn, "r");
if (f || errno != ENOENT) { if (f || errno != ENOENT) {
if (result) if (result)
*result = l; *result = pa_xstrdup(lfn);
else pa_xfree(lfn);
pa_xfree(l);
return f; return f;
} }
pa_xfree(l); pa_xfree(lfn);
} }
if (!global) { if (!global) {
@ -829,6 +996,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
return NULL; return NULL;
} }
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
return NULL;
global = buf;
#endif
if (result) if (result)
*result = pa_xstrdup(global); *result = pa_xstrdup(global);
@ -934,21 +1107,44 @@ int pa_startswith(const char *s, const char *pfx) {
char *pa_runtime_path(const char *fn, char *s, size_t l) { char *pa_runtime_path(const char *fn, char *s, size_t l) {
char u[256]; char u[256];
#ifndef OS_IS_WIN32
if (fn && *fn == '/') if (fn && *fn == '/')
#else
if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
#endif
return pa_strlcpy(s, fn, l); return pa_strlcpy(s, fn, l);
snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : ""); if (fn)
snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
else
snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
#ifdef OS_IS_WIN32
{
char buf[l];
strcpy(buf, s);
ExpandEnvironmentStrings(buf, s, l);
}
#endif
return s; return s;
} }
/* Wait t milliseconds */ /* Wait t milliseconds */
int pa_msleep(unsigned long t) { int pa_msleep(unsigned long t) {
#ifdef OS_IS_WIN32
Sleep(t);
return 0;
#elif defined(HAVE_NANOSLEEP)
struct timespec ts; struct timespec ts;
ts.tv_sec = t/1000; ts.tv_sec = t/1000;
ts.tv_nsec = (t % 1000) * 1000000; ts.tv_nsec = (t % 1000) * 1000000;
return nanosleep(&ts, NULL); return nanosleep(&ts, NULL);
#else
#error "Platform lacks a sleep function."
#endif
} }
/* Convert the string s to a signed integer in *ret_i */ /* Convert the string s to a signed integer in *ret_i */