AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"])
# Windows
-AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
+AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
# Other
AC_CHECK_HEADERS([sys/ioctl.h])
cdecl.h \
client-conf.c client-conf.h \
conf-parser.c conf-parser.h \
+ dllmain.c \
dynarray.c dynarray.h \
gcc-printf.h \
idxset.c idxset.h \
cli-text.c cli-text.h \
client.c client.h \
core.c core.h \
+ dllmain.c \
dynarray.c dynarray.h \
endianmacros.h \
g711.c g711.h \
libiochannel_la_SOURCES = iochannel.c iochannel.h
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_LDFLAGS = -avoid-version
module-mmkbd-evdev.la
endif
+if OS_IS_WIN32
+modlib_LTLIBRARIES += \
+ module-waveout.la
+endif
+
# These are generated by a M4 script
SYMDEF_FILES = \
module-oss-symdef.h \
module-oss-mmap-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)
BUILT_SOURCES += $(SYMDEF_FILES)
module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD)
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 #
###################################
client.conf: client.conf.in Makefile
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
sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
+endif
daemon.conf: daemon.conf.in Makefile
sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \
USA.
***/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#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
+
+#ifndef OS_IS_WIN32
+# define PATH_SEP "/"
+#else
+# define PATH_SEP "\\"
#endif
-#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf"
-#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf"
+#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"
#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"
--- /dev/null
+#\r
+# This file is part of polypaudio.\r
+#\r
+# polypaudio is free software; you can redistribute it and/or modify it\r
+# under the terms of the GNU Lesser General Public License as published by\r
+# the Free Software Foundation; either version 2 of the License, or\r
+# (at your option) any later version.\r
+#\r
+# polypaudio is distributed in the hope that it will be useful, but\r
+# WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+# General Public License for more details.\r
+#\r
+# You should have received a copy of the GNU Lesser General Public License\r
+# along with polypaudio; if not, write to the Free Software Foundation,\r
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.\r
+\r
+\r
+# Load audio drivers statically\r
+\r
+load-module module-waveout sink_name=output source_name=input\r
+load-module module-null-sink\r
+\r
+# Load audio drivers automatically on access\r
+\r
+#add-autoload-sink output module-waveout sink_name=output source_name=input\r
+#add-autoload-source input module-waveout sink_name=output source_name=input\r
+\r
+# Load several protocols\r
+#load-module module-esound-protocol-tcp\r
+#load-module module-native-protocol-tcp\r
+#load-module module-simple-protocol-tcp\r
+#load-module module-cli-protocol-tcp\r
+\r
+# Make some devices default\r
+set-default-sink output\r
+set-default-source input\r
+\r
+.nofail\r
+\r
+# Load something to the sample cache\r
+load-sample x11-bell %WINDIR%\Media\ding.wav\r
+load-sample-dir-lazy %WINDIR%\Media\*.wav\r
--- /dev/null
+/* $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 */
#include <fcntl.h>
#include <unistd.h>
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
#include "iochannel.h"
#include "util.h"
#include "socket-util.h"
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);
}
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);
}
#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_WINSOCK2_H
+#include <winsock2.h>
+#endif
#ifdef HAVE_LIBWRAP
#include <syslog.h>
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));
gid_t gid = (gid_t) -1;
#endif
+#ifdef OS_IS_WIN32
+ struct pa_defer_event *defer;
+#endif
+
pa_limit_caps();
#ifdef HAVE_GETUID
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();
goto finish;
}
+#ifdef HAVE_FORK
if (pipe(daemon_pipe) < 0) {
pa_log(__FILE__": failed to create pipe.\n");
goto finish;
close(daemon_pipe[0]);
daemon_pipe[0] = -1;
+#endif
if (conf->auto_log_target)
pa_log_set_target(PA_LOG_SYSLOG, NULL);
#ifdef HAVE_SETPGID
setpgid(0,0);
#endif
-
+
+#ifndef OS_IS_WIN32
close(0);
close(1);
close(2);
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
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;
}
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
+
if (conf->daemonize)
c->running_as_daemon = 1;
-
+
#ifdef SIGUSR1
pa_signal_new(SIGUSR1, signal_callback, c);
#endif
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;
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();
close_pipe(daemon_pipe);
+#ifdef OS_IS_WIN32
+ WSACleanup();
+#endif
+
lt_dlexit();
return retval;
#include <unistd.h>
#include <fcntl.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
#include "mainloop-signal.h"
#include "util.h"
#include "xmalloc.h"
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]);
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;
}
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);
+#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]);
#include "poll.h"
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
#include "mainloop.h"
#include "util.h"
#include "idxset.h"
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;
#include <netinet/in.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
#include "module.h"
#include "socket-server.h"
#include "socket-util.h"
#include <limits.h>
#include <signal.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
#include "pid.h"
#include "util.h"
#include "log.h"
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)
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;
}
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;
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. */
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
goto fail;
-
+
ret = kill(*pid, sig);
fail:
return ret;
}
+
+#else /* OS_IS_WIN32 */
+
+int pa_pid_file_kill(int sig, pid_t *pid) {
+ return -1;
+}
+
+#endif
#include <sys/select.h>
#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
#include "util.h"
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) {
}
}
+#ifdef OS_IS_WIN32
+ errno = WSAGetLastError();
+#endif
+
if (ready > 0) {
ready = 0;
for (f = fds; f < &fds[nfds]; ++f) {
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
+#include <limits.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#include <netdb.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+
#include "polyplib-internal.h"
#include "polyplib-context.h"
#include "native-common.h"
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;
return -1;
}
+#endif /* OS_IS_WIN32 */
+
static int try_next_connection(struct pa_context *c) {
char *u = NULL;
int r = -1;
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;
#include <netinet/in.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
#include "pstream.h"
#include "queue.h"
#include "xmalloc.h"
USA.
***/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#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)
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();
}
}
#include <glob.h>
#endif
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
#include "scache.h"
#include "sink-input.h"
#include "mainloop.h"
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;
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)))
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);
}
#include <netdb.h>
#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
#include <asyncns.h>
#endif
#include <netinet/in.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
#ifdef HAVE_LIBWRAP
#include <tcpd.h>
#endif
#include <netdb.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#define ETIMEDOUT WSAETIMEDOUT
+#endif
+
#include "socket-util.h"
#include "util.h"
#include "xmalloc.h"
return;
}
+#ifndef OS_IS_WIN32
if (S_ISSOCK(st.st_mode)) {
union {
struct sockaddr sa;
snprintf(c, l, "STDIN/STDOUT client");
return;
}
+#endif /* OS_IS_WIN32 */
snprintf(c, l, "Unknown client");
}
#include <netinet/in.h>
#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
#include "tagstruct.h"
#include "xmalloc.h"
#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 <signal.h>
#include <sys/time.h>
-#include <limits.h>
-#include <unistd.h>
#ifdef HAVE_SCHED_H
#include <sched.h>
#include <netdb.h>
#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>
#ifdef HAVE_PWD_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 */
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 OS_IS_WIN32
+ if (stat(dir, &st) < 0)
+#else
+ if (lstat(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;
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;
}
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 */
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) {
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
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
{
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;
}
#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);
if (fcntl(fd, F_SETFD, v) < 0)
return -1;
-
+#endif
+
return 0;
}
* 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);
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
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;
/* Lock or unlock a file entirely. (advisory) */
int pa_lock_fd(int fd, int b) {
+#ifdef F_SETLKW
struct flock flock;
/* Try a R/W lock first */
}
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;
}
* 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) {
return NULL;
}
+#ifdef OS_IS_WIN32
+ if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+ return NULL;
+ global = buf;
+#endif
+
if (result)
*result = pa_xstrdup(global);
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 */