summaryrefslogtreecommitdiff
path: root/app-emulation/wine/files
diff options
context:
space:
mode:
authorGluzskiy Alexandr <sss123next@list.ru>2011-05-12 10:57:01 +0300
committerGluzskiy Alexandr <sss123next@list.ru>2011-05-12 10:57:01 +0300
commit2beca37987e0a9215f97f31df77d684df1ceaea0 (patch)
tree9b38d54a5609160387d21c1ba95513360a4cdd34 /app-emulation/wine/files
parent76f28277ebc16526c51efaa38bf977b1fdd648c5 (diff)
deleted: app-emulation/wine/Manifest
deleted: app-emulation/wine/files/0001-dinput-Read-raw-relative-mouse-movements-from-dev.patch deleted: app-emulation/wine/files/Patch_id_1.patch deleted: app-emulation/wine/files/mousepatch.diff deleted: app-emulation/wine/files/oblivion_winmm_badcheck_workaround.patch deleted: app-emulation/wine/files/wine-1.1.15-configure-host.patch deleted: app-emulation/wine/files/wine-1.1.15-winegcc.patch deleted: app-emulation/wine/files/wine-1.1.4-install-fix.patch deleted: app-emulation/wine/files/wine-gentoo-no-ssp.patch deleted: app-emulation/wine/files/winepulse-0.27.patch deleted: app-emulation/wine/files/winepulse-winecfg.patch deleted: app-emulation/wine/wine-9999.ebuild
Diffstat (limited to 'app-emulation/wine/files')
-rw-r--r--app-emulation/wine/files/0001-dinput-Read-raw-relative-mouse-movements-from-dev.patch77
-rw-r--r--app-emulation/wine/files/Patch_id_1.patch315
-rw-r--r--app-emulation/wine/files/mousepatch.diff11
-rw-r--r--app-emulation/wine/files/oblivion_winmm_badcheck_workaround.patch13
-rw-r--r--app-emulation/wine/files/wine-1.1.15-configure-host.patch13
-rw-r--r--app-emulation/wine/files/wine-1.1.15-winegcc.patch55
-rw-r--r--app-emulation/wine/files/wine-1.1.4-install-fix.patch22
-rw-r--r--app-emulation/wine/files/wine-gentoo-no-ssp.patch16
-rw-r--r--app-emulation/wine/files/winepulse-0.27.patch2711
-rw-r--r--app-emulation/wine/files/winepulse-winecfg.patch289
10 files changed, 0 insertions, 3522 deletions
diff --git a/app-emulation/wine/files/0001-dinput-Read-raw-relative-mouse-movements-from-dev.patch b/app-emulation/wine/files/0001-dinput-Read-raw-relative-mouse-movements-from-dev.patch
deleted file mode 100644
index e1d922c..0000000
--- a/app-emulation/wine/files/0001-dinput-Read-raw-relative-mouse-movements-from-dev.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From f0859f18b398a895286105a7b6a1ba9d8b2248af Mon Sep 17 00:00:00 2001
-From: Daniel Scharrer <dscharrer@gmail.com>
-Date: Tue, 13 Jan 2009 18:19:26 +0100
-Subject: dinput: Read raw relative mouse movements from /dev/input/mice.
-
----
- dlls/dinput/mouse.c | 26 ++++++++++++++++++++++----
- 1 files changed, 22 insertions(+), 4 deletions(-)
-
-diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
-index 178b8fb..273d605 100644
---- a/dlls/dinput/mouse.c
-+++ b/dlls/dinput/mouse.c
-@@ -25,6 +25,8 @@
- #include <stdarg.h>
- #include <string.h>
-
-+#include <fcntl.h>
-+
- #include "windef.h"
- #include "winbase.h"
- #include "wingdi.h"
-@@ -76,6 +78,8 @@ struct SysMouseImpl
- DIMOUSESTATE2 m_state;
-
- WARP_MOUSE warp_override;
-+
-+ int mouse;
- };
-
- static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam );
-@@ -198,6 +202,11 @@ static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputIm
- newDevice->base.dinput = dinput;
- newDevice->base.event_proc = dinput_mouse_hook;
-
-+ newDevice->mouse = open("/dev/input/mice", O_RDONLY);
-+
-+ if(newDevice->mouse < 0)
-+ WARN("unable to open /dev/input/mice for reading");
-+
- get_app_key(&hkey, &appkey);
- if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer)))
- {
-@@ -303,9 +312,17 @@ static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARA
- {
- POINT pt, pt1;
-
-- GetCursorPos(&pt);
-- This->m_state.lX += pt.x = hook->pt.x - pt.x;
-- This->m_state.lY += pt.y = hook->pt.y - pt.y;
-+ if(This->mouse >= 0)
-+ {
-+ char input[3] = {0,0,0};
-+ read(This->mouse, input, 3);
-+ This->m_state.lX += pt.x = input[1];
-+ This->m_state.lY += pt.y = input[2];
-+ } else {
-+ GetCursorPos(&pt);
-+ This->m_state.lX += pt.x = hook->pt.x - pt.x;
-+ This->m_state.lY += pt.y = hook->pt.y - pt.y;
-+ }
-
- if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
- {
-@@ -331,7 +348,8 @@ static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARA
-
- This->need_warp = This->warp_override != WARP_DISABLE &&
- (pt.x || pt.y) &&
-- (dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON);
-+ (dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON) &&
-+ This->mouse < 0;
- break;
- }
- case WM_MOUSEWHEEL:
---
-1.6.0.6
-
diff --git a/app-emulation/wine/files/Patch_id_1.patch b/app-emulation/wine/files/Patch_id_1.patch
deleted file mode 100644
index 0ea44a7..0000000
--- a/app-emulation/wine/files/Patch_id_1.patch
+++ /dev/null
@@ -1,315 +0,0 @@
---- wine-1.1.34/dlls/dinput/device.c 2009-12-04 18:05:35.000000000 +0000
-+++ wine-1.1.34/dlls/dinput/device.c.new 2009-12-07 01:07:57.000000000 +0000
-@@ -580,7 +580,7 @@
- This->acquired = 1;
- if (res == DI_OK)
- {
-- This->queue_head = This->queue_tail = This->overflow = 0;
-+ //This->queue_head = This->queue_tail = This->overflow = 0;
- check_dinput_hooks(iface);
- }
- LeaveCriticalSection(&This->crit);
---- wine-1.1.34/dlls/dinput/mouse.c 2009-12-04 18:05:35.000000000 +0000
-+++ wine-1.1.34/dlls/dinput/mouse.c.new 2009-12-07 01:25:12.000000000 +0000
-@@ -48,6 +48,8 @@
-
- static const IDirectInputDevice8AVtbl SysMouseAvt;
- static const IDirectInputDevice8WVtbl SysMouseWvt;
-+BOOL m_forceWarp=FALSE;
-+POINT m_joeCursorPlacement;
-
- typedef struct SysMouseImpl SysMouseImpl;
-
-@@ -55,7 +57,8 @@
- {
- WARP_DEFAULT,
- WARP_DISABLE,
-- WARP_FORCE_ON
-+ WARP_FORCE_ON,
-+ WARP_FORCEBOX_ON
- } WARP_MOUSE;
-
- struct SysMouseImpl
-@@ -76,9 +79,11 @@
- DIMOUSESTATE2 m_state;
-
- WARP_MOUSE warp_override;
-+ /* This defines the warp ``box'' */
-+ DWORD warp_boxpixels;
- };
-
--static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam );
-+static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam );
-
- const GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
- 0x9e573ed8, 0x7734, 0x11d2, {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
-@@ -185,6 +190,7 @@
- LPDIDATAFORMAT df = NULL;
- unsigned i;
- char buffer[20];
-+ char boxpixels[4];
- HKEY hkey, appkey;
-
- newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
-@@ -205,6 +211,14 @@
- newDevice->warp_override = WARP_DISABLE;
- else if (!strcasecmp(buffer, "force"))
- newDevice->warp_override = WARP_FORCE_ON;
-+ else if (!strcasecmp(buffer, "force-box")) {
-+ newDevice->warp_override = WARP_FORCEBOX_ON;
-+ newDevice->warp_boxpixels = 10;
-+ if (!get_config_key(hkey, appkey, "BoxPixels", boxpixels, sizeof(boxpixels)))
-+ {
-+ newDevice->warp_boxpixels = atoi(boxpixels);
-+ }
-+ }
- }
- if (appkey) RegCloseKey(appkey);
- if (hkey) RegCloseKey(hkey);
-@@ -286,25 +300,31 @@
- */
-
- /* low-level mouse hook */
--static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
-+static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
- {
- MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
- SysMouseImpl* This = (SysMouseImpl*) iface;
- DWORD dwCoop;
-- int wdata = 0, inst_id = -1, ret;
-+ //int wdata = 0, inst_id = -1, ret;
-+ POINT pt, pt1;
-+ RECT rect;
-+ int mouseForceOffset=4;
-
-- TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
-+ //TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
-+ int wdata = 0, inst_id = -1;
-
- EnterCriticalSection(&This->base.crit);
- dwCoop = This->base.dwCoopLevel;
-- ret = dwCoop & DISCL_EXCLUSIVE;
-+ //ret = dwCoop & DISCL_EXCLUSIVE;
-
- switch(wparam) {
- case WM_MOUSEMOVE:
- {
-- POINT pt, pt1;
-+ //POINT pt, pt1;
-+ POINT ptTarget;
-
- GetCursorPos(&pt);
-+ ptTarget=pt;
- This->m_state.lX += pt.x = hook->pt.x - pt.x;
- This->m_state.lY += pt.y = hook->pt.y - pt.y;
-
-@@ -315,6 +335,9 @@
- } else
- pt1 = pt;
-
-+ //FIXME("MouseMove Pt.x%d,pt.y%d\n",pt.x,pt.y);
-+ //FIXME("MouseMove Pt1.x%d,pt1.y%d\n",pt1.x,pt1.y);
-+
- if (pt.x)
- {
- inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
-@@ -323,16 +346,57 @@
- if (pt.y)
- {
- /* Already have X, need to queue it */
-- if (inst_id != -1)
-+ if (inst_id != -1) {
- queue_event((LPDIRECTINPUTDEVICE8A)This, inst_id,
- wdata, GetCurrentTime(), This->base.dinput->evsequence);
-+ //FIXME("EVENT Queued\n");
-+ }
- inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
- wdata = pt1.y;
- }
--
-+
-+ if (pt.x) {
-+ if (pt1.x) {
-+ m_joeCursorPlacement.x=pt1.x;
-+ }
-+ }
-+ if (pt.y) {
-+ if (pt1.y) {
-+ m_joeCursorPlacement.y=pt1.y;
-+ }
-+ }
-+ if (m_forceWarp) {
-+ /* Get the window dimension and find the center */
-+ //GetWindowRect(This->base.win, &rect);
-+ //This->win_centerX = (rect.right - rect.left) / 2;
-+ //This->win_centerY = (rect.bottom - rect.top ) / 2;
-+ //This->mapped_center.x = This->win_centerX;
-+ //This->mapped_center.y = This->win_centerY;
-+ //MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
-+ if (This->need_warp) {
-+ This->need_warp=FALSE;
-+ } else {
-+ This->need_warp = (hook->pt.x<=mouseForceOffset ||
-+ hook->pt.y<=mouseForceOffset ||
-+ hook->pt.x>=((2 * This->win_centerX)-mouseForceOffset) ||
-+ hook->pt.y>=((2 * This->win_centerY)-mouseForceOffset) );
-+ }
-+ }
-+ else {
- This->need_warp = This->warp_override != WARP_DISABLE &&
-- (pt.x || pt.y) &&
-- (dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON);
-+ (
-+ (pt.x || pt.y) &&
-+ (dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON)
-+ ||
-+ (
-+ hook->pt.x<This->warp_boxpixels ||
-+ hook->pt.y<This->warp_boxpixels ||
-+ hook->pt.x>((2 * This->win_centerX)-This->warp_boxpixels) ||
-+ hook->pt.y>((2 * This->win_centerY)-This->warp_boxpixels)
-+ ) && This->warp_override == WARP_FORCEBOX_ON
-+ );
-+ }
-+
- break;
- }
- case WM_MOUSEWHEEL:
-@@ -371,8 +435,8 @@
- inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON;
- This->m_state.rgbButtons[2 + HIWORD(hook->mouseData)] = wdata = 0x00;
- break;
-- default:
-- ret = 0;
-+ //default:
-+ //ret = 0;
- }
-
-
-@@ -381,10 +445,11 @@
- _dump_mouse_state(&This->m_state);
- queue_event((LPDIRECTINPUTDEVICE8A)This, inst_id,
- wdata, GetCurrentTime(), This->base.dinput->evsequence++);
-- }
-+ //FIXME("EVENT Queued\n");
-+ }
-
- LeaveCriticalSection(&This->base.crit);
-- return ret;
-+ //return ret;
- }
-
- static BOOL dinput_window_check(SysMouseImpl* This) {
-@@ -410,6 +475,13 @@
- /******************************************************************************
- * Acquire : gets exclusive control of the mouse
- */
-+
-+static HRESULT WINAPI SysMouseAImpl_AcquireJoe(LPDIRECTINPUTDEVICE8A iface)
-+{
-+ m_forceWarp=(getenv("WINEFORCEMOUSEWARP") == NULL) ? FALSE : TRUE;
-+ return DI_OK;
-+}
-+
- static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
- {
- SysMouseImpl *This = (SysMouseImpl *)iface;
-@@ -417,6 +489,8 @@
- POINT point;
- HRESULT res;
-
-+ m_forceWarp=(getenv("WINEFORCEMOUSEWARP") == NULL) ? FALSE : TRUE;
-+
- TRACE("(this=%p)\n",This);
-
- if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res;
-@@ -462,16 +536,23 @@
- This->win_centerY = (rect.bottom - rect.top ) / 2;
-
- /* Warp the mouse to the center of the window */
-- if (This->base.dwCoopLevel & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON)
-+ if (This->base.dwCoopLevel & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON || This->warp_override == WARP_FORCEBOX_ON)
- {
- This->mapped_center.x = This->win_centerX;
- This->mapped_center.y = This->win_centerY;
- MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
- TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
-+ This->need_warp = FALSE;
- SetCursorPos( This->mapped_center.x, This->mapped_center.y );
-+ GetCursorPos( &m_joeCursorPlacement);
- This->last_warped = GetCurrentTime();
-
-- This->need_warp = FALSE;
-+ //This->need_warp = FALSE;
-+ }
-+
-+ else {
-+ GetCursorPos(&m_joeCursorPlacement);
-+ SetCursorPos(m_joeCursorPlacement.x,m_joeCursorPlacement.y);
- }
-
- return DI_OK;
-@@ -482,6 +563,11 @@
- */
- static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
- {
-+ return DI_OK;
-+}
-+
-+static HRESULT WINAPI SysMouseAImpl_Unacquire25(LPDIRECTINPUTDEVICE8A iface)
-+{
- SysMouseImpl *This = (SysMouseImpl *)iface;
- HRESULT res;
-
-@@ -496,10 +582,16 @@
- }
-
- /* And put the mouse cursor back where it was at acquire time */
-- if (This->base.dwCoopLevel & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON)
-- {
-- TRACE(" warping mouse back to (%d , %d)\n", This->org_coords.x, This->org_coords.y);
-- SetCursorPos(This->org_coords.x, This->org_coords.y);
-+
-+ if (This->base.dwCoopLevel & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON || This->warp_override == WARP_FORCEBOX_ON)
-+ {
-+ //TRACE(" warping mouse back to (%d , %d)\n", This->org_coords.x, This->org_coords.y);
-+ //SetCursorPos(This->org_coords.x, This->org_coords.y);
-+ GetCursorPos(&m_joeCursorPlacement);
-+ }
-+ else {
-+ SetCursorPos(m_joeCursorPlacement.x,m_joeCursorPlacement.y);
-+ GetCursorPos(&m_joeCursorPlacement);
- }
-
- return DI_OK;
-@@ -568,10 +660,17 @@
- return DIERR_GENERIC;
- TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
- SetCursorPos( This->mapped_center.x, This->mapped_center.y );
-+ GetCursorPos(&m_joeCursorPlacement);
- This->last_warped = GetCurrentTime();
-
- This->need_warp = FALSE;
- }
-+
-+ else {
-+ GetCursorPos(&m_joeCursorPlacement);
-+ SetCursorPos(m_joeCursorPlacement.x,m_joeCursorPlacement.y);
-+ }
-+
- return res;
- }
-
-@@ -607,8 +706,10 @@
- /* Querying the range of either the X or the Y axis. As I do
- not know the range, do as if the range were
- unrestricted...*/
-- pr->lMin = DIPROPRANGE_NOMIN;
-- pr->lMax = DIPROPRANGE_NOMAX;
-+ //pr->lMin = DIPROPRANGE_NOMIN;
-+ //pr->lMax = DIPROPRANGE_NOMAX;
-+ pr->lMin = 0; //JoeFix MAX RANGE
-+ pr->lMax = 1280;
- }
-
- break;
diff --git a/app-emulation/wine/files/mousepatch.diff b/app-emulation/wine/files/mousepatch.diff
deleted file mode 100644
index 5cdd67d..0000000
--- a/app-emulation/wine/files/mousepatch.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/dlls/dinput/mouse.c
-+++ b/dlls/dinput/mouse.c
-@@ -330,7 +330,7 @@ static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARA
- }
-
- This->need_warp = This->warp_override != WARP_DISABLE &&
-- (pt.x || pt.y) &&
-+ (hook->pt.x<2 || hook->pt.y<2 || hook->pt.x>((2 * This->win_centerX)-2) || hook->pt.y>((2 * This->win_centerY)-2) ) &&
- (dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON);
- break;
- }
diff --git a/app-emulation/wine/files/oblivion_winmm_badcheck_workaround.patch b/app-emulation/wine/files/oblivion_winmm_badcheck_workaround.patch
deleted file mode 100644
index ce23a46..0000000
--- a/app-emulation/wine/files/oblivion_winmm_badcheck_workaround.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dlls/winmm/mmio.c b/dlls/winmm/mmio.c
-index 75439a4..5c9fc13 100644
---- a/dlls/winmm/mmio.c
-+++ b/dlls/winmm/mmio.c
-@@ -880,7 +880,7 @@ LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
- return -1;
- }
-
-- if (offset && offset >= wm->dwFileSize && wm->info.fccIOProc != FOURCC_MEM) {
-+ if (offset && offset >= wm->dwFileSize && wm->info.fccIOProc == FOURCC_DOS) {
- /* should check that write mode exists */
- if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
- return -1;
diff --git a/app-emulation/wine/files/wine-1.1.15-configure-host.patch b/app-emulation/wine/files/wine-1.1.15-configure-host.patch
deleted file mode 100644
index 47628f6..0000000
--- a/app-emulation/wine/files/wine-1.1.15-configure-host.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-http://bugs.gentoo.org/260726
-
---- wine-1.1.15/configure
-+++ wine-1.1.15/configure
-@@ -3943,7 +3943,7 @@
- $as_echo "$wine_cv_toolsdir" >&6; }
- TOOLSDIR=$wine_cv_toolsdir
-
--if test -n "$host_alias"
-+if test -n "$host_alias" -a "$host_alias" != "$build_alias"
- then
- TARGETFLAGS="-b $host_alias $TARGETFLAGS"
-
diff --git a/app-emulation/wine/files/wine-1.1.15-winegcc.patch b/app-emulation/wine/files/wine-1.1.15-winegcc.patch
deleted file mode 100644
index 6e5bb22..0000000
--- a/app-emulation/wine/files/wine-1.1.15-winegcc.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-http://bugs.gentoo.org/260726
-
---- wine-1.1.15/tools/winegcc/winegcc.c
-+++ wine-1.1.15/tools/winegcc/winegcc.c
-@@ -215,10 +215,13 @@
- strarray* files;
- };
-
-+#undef FORCE_POINTER_SIZE
- #ifdef __i386__
- static const enum target_cpu build_cpu = CPU_x86;
-+#define FORCE_POINTER_SIZE
- #elif defined(__x86_64__)
- static const enum target_cpu build_cpu = CPU_x86_64;
-+#define FORCE_POINTER_SIZE
- #elif defined(__sparc__)
- static const enum target_cpu build_cpu = CPU_SPARC;
- #elif defined(__ALPHA__)
-@@ -968,6 +971,9 @@
- opts.linker_args = strarray_alloc();
- opts.compiler_args = strarray_alloc();
- opts.winebuild_args = strarray_alloc();
-+#ifdef FORCE_POINTER_SIZE
-+ opts.force_pointer_size = sizeof(size_t);
-+#endif
-
- /* determine the processor type */
- if (strendswith(argv[0], "winecpp")) opts.processor = proc_cpp;
---- wine-1.1.15/tools/winebuild/main.c
-+++ wine-1.1.15/tools/winebuild/main.c
-@@ -50,10 +50,13 @@
- int link_ext_symbols = 0;
- int force_pointer_size = 0;
-
-+#undef FORCE_POINTER_SIZE
- #ifdef __i386__
- enum target_cpu target_cpu = CPU_x86;
-+#define FORCE_POINTER_SIZE
- #elif defined(__x86_64__)
- enum target_cpu target_cpu = CPU_x86_64;
-+#define FORCE_POINTER_SIZE
- #elif defined(__sparc__)
- enum target_cpu target_cpu = CPU_SPARC;
- #elif defined(__ALPHA__)
-@@ -574,6 +577,10 @@
- signal( SIGTERM, exit_on_signal );
- signal( SIGINT, exit_on_signal );
-
-+#ifdef FORCE_POINTER_SIZE
-+ force_pointer_size = sizeof(size_t);
-+#endif
-+
- output_file = stdout;
- argv = parse_options( argc, argv, spec );
-
diff --git a/app-emulation/wine/files/wine-1.1.4-install-fix.patch b/app-emulation/wine/files/wine-1.1.4-install-fix.patch
deleted file mode 100644
index 7ff5771..0000000
--- a/app-emulation/wine/files/wine-1.1.4-install-fix.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From: Alexandre Julliard <julliard@winehq.org>
-Date: Mon, 8 Sep 2008 10:37:56 +0000 (+0200)
-Subject: makefile: Fix dependency for programs install.
-X-Git-Url: http://source.winehq.org/git/wine.git/?a=commitdiff_plain;h=78c79ba349deea39
-
-makefile: Fix dependency for programs install.
----
-
-diff --git a/Makefile.in b/Makefile.in
-index 0b2c6c0..1dd8ef1 100644
---- a/Makefile.in
-+++ b/Makefile.in
-@@ -96,7 +96,8 @@ include/__install__ include/__install-dev__: include libs tools
- libs/__install__ libs/__install-lib__ libs/__install-dev__: libs
- loader/__install__ loader/__install-lib__: libs tools
- server/__install__ server/__install-lib__: libs tools
--programs/__install__ programs/__install-lib__: libs tools include dlls/__install-lib__
-+programs/__install__: libs tools include dlls/__install__
-+programs/__install-lib__: libs tools include dlls/__install-lib__
- tools/__install__ tools/__install-lib__ tools/__install-dev__: tools
-
- RECURSE_TARGETS = \
diff --git a/app-emulation/wine/files/wine-gentoo-no-ssp.patch b/app-emulation/wine/files/wine-gentoo-no-ssp.patch
deleted file mode 100644
index ee33c4b..0000000
--- a/app-emulation/wine/files/wine-gentoo-no-ssp.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-support older ssp (gcc-3.4.x). this ssp was never in mainline gcc, thus
-upstream wine wont accept it. can drop once hardened gets a stable gcc-4.x.
-
-http://bugs.gentoo.org/66002
-
---- loader/preloader.c
-+++ loader/preloader.c
-@@ -155,6 +155,8 @@ struct wld_link_map {
-
- /* similar to the above but for -fstack-protector */
- void *__stack_chk_guard = 0;
-+void *__guard = 0;
-+void __stack_smash_handler(void) { return; }
- void __stack_chk_fail(void) { return; }
-
- * The _start function is the entry and exit point of this program
diff --git a/app-emulation/wine/files/winepulse-0.27.patch b/app-emulation/wine/files/winepulse-0.27.patch
deleted file mode 100644
index 8726bcb..0000000
--- a/app-emulation/wine/files/winepulse-0.27.patch
+++ /dev/null
@@ -1,2711 +0,0 @@
-diff --git a/dlls/winepulse.drv/Makefile.in b/dlls/winepulse.drv/Makefile.in
-new file mode 100644
-index 0000000..4202b4f
---- /dev/null
-+++ b/dlls/winepulse.drv/Makefile.in
-@@ -0,0 +1,15 @@
-+TOPSRCDIR = @top_srcdir@
-+TOPOBJDIR = ../..
-+SRCDIR = @srcdir@
-+VPATH = @srcdir@
-+MODULE = winepulse.drv
-+IMPORTS = dxguid uuid winmm user32 advapi32 kernel32
-+EXTRALIBS = @PULSELIBS@
-+
-+C_SRCS = waveout.c \
-+ wavein.c \
-+ pulse.c
-+
-+@MAKE_DLL_RULES@
-+
-+@DEPENDENCIES@ # everything below this line is overwritten by make depend
-diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
-new file mode 100644
-index 0000000..e336a98
---- /dev/null
-+++ b/dlls/winepulse.drv/pulse.c
-@@ -0,0 +1,742 @@
-+/*
-+ * Wine Driver for PulseAudio
-+ * http://pulseaudio.org/
-+ *
-+ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
-+ *
-+ * Contains code from other wine sound drivers.
-+ *
-+ * This library 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.
-+ *
-+ * This library 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 this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-+ */
-+
-+#include "config.h"
-+
-+#include <stdarg.h>
-+#include <stdio.h>
-+
-+#include "windef.h"
-+#include "winbase.h"
-+#include "wingdi.h"
-+#include "winuser.h"
-+#include "winreg.h"
-+#include "mmddk.h"
-+#include "ks.h"
-+#include "ksguid.h"
-+#include "ksmedia.h"
-+
-+#ifdef HAVE_UNISTD_H
-+# include <unistd.h>
-+#endif
-+#include <poll.h>
-+
-+#ifdef HAVE_PULSEAUDIO
-+
-+#include "wine/unicode.h"
-+#include "wine/debug.h"
-+#include "wine/library.h"
-+
-+#include <winepulse.h>
-+#include <pulse/pulseaudio.h>
-+WINE_DEFAULT_DEBUG_CHANNEL(wave);
-+
-+/* These strings used only for tracing */
-+const char * PULSE_getCmdString(enum win_wm_message msg) {
-+ static char unknown[32];
-+#define MSG_TO_STR(x) case x: return #x
-+ switch(msg) {
-+ MSG_TO_STR(WINE_WM_PAUSING);
-+ MSG_TO_STR(WINE_WM_RESTARTING);
-+ MSG_TO_STR(WINE_WM_RESETTING);
-+ MSG_TO_STR(WINE_WM_HEADER);
-+ MSG_TO_STR(WINE_WM_BREAKLOOP);
-+ MSG_TO_STR(WINE_WM_CLOSING);
-+ MSG_TO_STR(WINE_WM_STARTING);
-+ MSG_TO_STR(WINE_WM_STOPPING);
-+ MSG_TO_STR(WINE_WM_XRUN);
-+ MSG_TO_STR(WINE_WM_FEED);
-+ }
-+#undef MSG_TO_STR
-+ sprintf(unknown, "UNKNOWN(0x%08x)", msg);
-+ return unknown;
-+}
-+
-+/*======================================================================*
-+ * Ring Buffer Functions - copied from winealsa.drv *
-+ *======================================================================*/
-+
-+/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
-+#define USE_PIPE_SYNC
-+
-+#ifdef USE_PIPE_SYNC
-+#define INIT_OMR(omr) do { if (pipe(omr->msg_pipe) < 0) { omr->msg_pipe[0] = omr->msg_pipe[1] = -1; } } while (0)
-+#define CLOSE_OMR(omr) do { close(omr->msg_pipe[0]); close(omr->msg_pipe[1]); } while (0)
-+#define SIGNAL_OMR(omr) do { int x = 0; write((omr)->msg_pipe[1], &x, sizeof(x)); } while (0)
-+#define CLEAR_OMR(omr) do { int x = 0; read((omr)->msg_pipe[0], &x, sizeof(x)); } while (0)
-+#define RESET_OMR(omr) do { } while (0)
-+#define WAIT_OMR(omr, sleep) \
-+ do { struct pollfd pfd; pfd.fd = (omr)->msg_pipe[0]; \
-+ pfd.events = POLLIN; poll(&pfd, 1, sleep); } while (0)
-+#else
-+#define INIT_OMR(omr) do { omr->msg_event = CreateEventW(NULL, FALSE, FALSE, NULL); } while (0)
-+#define CLOSE_OMR(omr) do { CloseHandle(omr->msg_event); } while (0)
-+#define SIGNAL_OMR(omr) do { SetEvent((omr)->msg_event); } while (0)
-+#define CLEAR_OMR(omr) do { } while (0)
-+#define RESET_OMR(omr) do { ResetEvent((omr)->msg_event); } while (0)
-+#define WAIT_OMR(omr, sleep) \
-+ do { WaitForSingleObject((omr)->msg_event, sleep); } while (0)
-+#endif
-+
-+#define PULSE_RING_BUFFER_INCREMENT 64
-+
-+/******************************************************************
-+ * PULSE_InitRingMessage
-+ *
-+ * Initialize the ring of messages for passing between driver's caller
-+ * and playback/record thread
-+ */
-+int PULSE_InitRingMessage(PULSE_MSG_RING* omr)
-+{
-+ omr->msg_toget = 0;
-+ omr->msg_tosave = 0;
-+ INIT_OMR(omr);
-+ omr->ring_buffer_size = PULSE_RING_BUFFER_INCREMENT;
-+ omr->messages = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,omr->ring_buffer_size * sizeof(PULSE_MSG));
-+
-+ InitializeCriticalSection(&omr->msg_crst);
-+ omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PULSE_MSG_RING.msg_crst");
-+ return 0;
-+}
-+
-+/******************************************************************
-+ * PULSE_DestroyRingMessage
-+ *
-+ */
-+int PULSE_DestroyRingMessage(PULSE_MSG_RING* omr)
-+{
-+ CLOSE_OMR(omr);
-+ HeapFree(GetProcessHeap(),0,omr->messages);
-+ omr->messages = NULL;
-+ omr->ring_buffer_size = PULSE_RING_BUFFER_INCREMENT;
-+ omr->msg_crst.DebugInfo->Spare[0] = 0;
-+ DeleteCriticalSection(&omr->msg_crst);
-+ return 0;
-+}
-+/******************************************************************
-+ * PULSE_ResetRingMessage
-+ *
-+ */
-+void PULSE_ResetRingMessage(PULSE_MSG_RING* omr)
-+{
-+ RESET_OMR(omr);
-+}
-+
-+/******************************************************************
-+ * PULSE_WaitRingMessage
-+ *
-+ */
-+void PULSE_WaitRingMessage(PULSE_MSG_RING* omr, DWORD sleep)
-+{
-+ WAIT_OMR(omr, sleep);
-+}
-+
-+/******************************************************************
-+ * PULSE_AddRingMessage
-+ *
-+ * Inserts a new message into the ring (should be called from DriverProc derived routines)
-+ */
-+int PULSE_AddRingMessage(PULSE_MSG_RING* omr, enum win_wm_message msg, DWORD param, BOOL wait)
-+{
-+ HANDLE hEvent = INVALID_HANDLE_VALUE;
-+
-+ EnterCriticalSection(&omr->msg_crst);
-+ if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
-+ {
-+ int old_ring_buffer_size = omr->ring_buffer_size;
-+ omr->ring_buffer_size += PULSE_RING_BUFFER_INCREMENT;
-+ omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(PULSE_MSG));
-+ /* Now we need to rearrange the ring buffer so that the new
-+ buffers just allocated are in between omr->msg_tosave and
-+ omr->msg_toget.
-+ */
-+ if (omr->msg_tosave < omr->msg_toget)
-+ {
-+ memmove(&(omr->messages[omr->msg_toget + PULSE_RING_BUFFER_INCREMENT]),
-+ &(omr->messages[omr->msg_toget]),
-+ sizeof(PULSE_MSG)*(old_ring_buffer_size - omr->msg_toget)
-+ );
-+ omr->msg_toget += PULSE_RING_BUFFER_INCREMENT;
-+ }
-+ }
-+ if (wait)
-+ {
-+ hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-+ if (hEvent == INVALID_HANDLE_VALUE)
-+ {
-+ ERR("can't create event !?\n");
-+ LeaveCriticalSection(&omr->msg_crst);
-+ return 0;
-+ }
-+ /* fast messages have to be added at the start of the queue */
-+ omr->msg_toget = (omr->msg_toget + omr->ring_buffer_size - 1) % omr->ring_buffer_size;
-+
-+ omr->messages[omr->msg_toget].msg = msg;
-+ omr->messages[omr->msg_toget].param = param;
-+ omr->messages[omr->msg_toget].hEvent = hEvent;
-+ }
-+ else
-+ {
-+ omr->messages[omr->msg_tosave].msg = msg;
-+ omr->messages[omr->msg_tosave].param = param;
-+ omr->messages[omr->msg_tosave].hEvent = INVALID_HANDLE_VALUE;
-+ omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
-+ }
-+ LeaveCriticalSection(&omr->msg_crst);
-+ /* signal a new message */
-+ SIGNAL_OMR(omr);
-+ if (wait)
-+ {
-+ /* wait for playback/record thread to have processed the message */
-+ WaitForSingleObject(hEvent, INFINITE);
-+ CloseHandle(hEvent);
-+ }
-+ return 1;
-+}
-+
-+/******************************************************************
-+ * PULSE_RetrieveRingMessage
-+ *
-+ * Get a message from the ring. Should be called by the playback/record thread.
-+ */
-+int PULSE_RetrieveRingMessage(PULSE_MSG_RING* omr,
-+ enum win_wm_message *msg, DWORD *param, HANDLE *hEvent)
-+{
-+ EnterCriticalSection(&omr->msg_crst);
-+
-+ if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
-+ {
-+ LeaveCriticalSection(&omr->msg_crst);
-+ return 0;
-+ }
-+
-+ *msg = omr->messages[omr->msg_toget].msg;
-+ omr->messages[omr->msg_toget].msg = 0;
-+ *param = omr->messages[omr->msg_toget].param;
-+ *hEvent = omr->messages[omr->msg_toget].hEvent;
-+ omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
-+ CLEAR_OMR(omr);
-+ LeaveCriticalSection(&omr->msg_crst);
-+ return 1;
-+}
-+
-+/**************************************************************************
-+ * Utility Functions
-+ *************************************************************************/
-+
-+/******************************************************************
-+ * PULSE_SetupFormat
-+ *
-+ * Checks to see if the audio format in wf is supported, and if so set up the
-+ * pa_sample_spec at ss to that format.
-+ */
-+BOOL PULSE_SetupFormat(LPWAVEFORMATEX wf, pa_sample_spec *ss) {
-+ WAVEFORMATEXTENSIBLE *wfex;
-+
-+ ss->channels = wf->nChannels;
-+ ss->rate = wf->nSamplesPerSec;
-+ ss->format = PA_SAMPLE_INVALID;
-+
-+ if (ss->rate < DSBFREQUENCY_MIN || ss->rate > DSBFREQUENCY_MAX) return FALSE;
-+
-+ switch (wf->wFormatTag) {
-+ case WAVE_FORMAT_PCM:
-+ /* MSDN says that for WAVE_FORMAT_PCM, nChannels must be 1 or 2 and
-+ * wBitsPerSample must be 8 or 16, yet other values are used by some
-+ * applications in the wild for surround. */
-+ if (ss->channels > 6 || ss->channels < 1) return FALSE;
-+ ss->format = wf->wBitsPerSample == 8 ? PA_SAMPLE_U8
-+ : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE
-+ : wf->wBitsPerSample == 32 ? PA_SAMPLE_S32NE
-+ : PA_SAMPLE_INVALID;
-+ break;
-+
-+ case WAVE_FORMAT_MULAW:
-+ if (wf->wBitsPerSample == 8) ss->format = PA_SAMPLE_ULAW;
-+ break;
-+
-+ case WAVE_FORMAT_ALAW:
-+ if (wf->wBitsPerSample == 8) ss->format = PA_SAMPLE_ALAW;
-+ break;
-+
-+ case WAVE_FORMAT_EXTENSIBLE:
-+ if (wf->cbSize > 22) return FALSE;
-+ if (ss->channels < 1 || ss->channels > 6) return FALSE;
-+ wfex = (WAVEFORMATEXTENSIBLE *)wf;
-+ if (IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
-+ if (wf->wBitsPerSample == wfex->Samples.wValidBitsPerSample) {
-+ ss->format = wf->wBitsPerSample == 8 ? PA_SAMPLE_U8
-+ : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE
-+ : wf->wBitsPerSample == 32 ? PA_SAMPLE_S32NE
-+ : PA_SAMPLE_INVALID;
-+ } else {
-+ return FALSE;
-+ }
-+ } else if (wf->wBitsPerSample != wfex->Samples.wValidBitsPerSample) {
-+ return FALSE;
-+ } else if ((IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))) {
-+ ss->format = PA_SAMPLE_FLOAT32NE;
-+ } else {
-+ WARN("only KSDATAFORMAT_SUBTYPE_PCM and KSDATAFORMAT_SUBTYPE_IEEE_FLOAT of WAVE_FORMAT_EXTENSIBLE supported\n");
-+ return FALSE;
-+ }
-+ break;
-+
-+ default:
-+ WARN("only WAVE_FORMAT_PCM, WAVE_FORMAT_MULAW, WAVE_FORMAT_ALAW and WAVE_FORMAT_EXTENSIBLE supported\n");
-+ return FALSE;
-+ }
-+
-+ if (!pa_sample_spec_valid(ss)) return FALSE;
-+ if (wf->nBlockAlign != pa_frame_size(ss)) {
-+ ERR("wf->nBlockAlign != the format frame size!\n");
-+ return FALSE;
-+ }
-+
-+ return TRUE;
-+}
-+
-+/**************************************************************************
-+ * PULSE_WaitForOperation
-+ *
-+ * Waits for pa operations to complete, and dereferences the operation.
-+ */
-+void PULSE_WaitForOperation(pa_operation *o) {
-+ if (!o) return;
-+
-+ for (;;) {
-+ if (pa_operation_get_state(o) != PA_OPERATION_RUNNING)
-+ break;
-+ pa_threaded_mainloop_wait(PULSE_ml);
-+ }
-+ pa_operation_unref(o);
-+}
-+
-+/**************************************************************************
-+ * Common Callbacks
-+ */
-+
-+/**************************************************************************
-+ * PULSE_StreamSuspendedCallback [internal]
-+ *
-+ * Called by the pulse mainloop any time stream playback is intentionally
-+ * suspended or resumed from being suspended.
-+ */
-+void PULSE_StreamSuspendedCallback(pa_stream *s, void *userdata) {
-+ WINE_WAVEINST *wwo = (WINE_WAVEINST*)userdata;
-+ assert(s && wwo);
-+
-+ /* Currently we handle this kinda like an underrun. Perhaps we should
-+ * tell the client somehow so it doesn't just hang? */
-+
-+ if (!pa_stream_is_suspended(s) && wwo->hThread != INVALID_HANDLE_VALUE && wwo->msgRing.ring_buffer_size > 0)
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_XRUN, 0, FALSE);
-+}
-+
-+/**************************************************************************
-+ * PULSE_StreamUnderflowCallback [internal]
-+ *
-+ * Called by the pulse mainloop when the prebuf runs out of data.
-+ */
-+void PULSE_StreamUnderflowCallback(pa_stream *s, void *userdata) {
-+ WINE_WAVEINST *wwo = (WINE_WAVEINST*)userdata;
-+ assert(s && wwo);
-+
-+ /* If we aren't playing, don't care ^_^ */
-+ if (wwo->state != WINE_WS_PLAYING) return;
-+
-+ TRACE("Underrun occurred.\n");
-+
-+ if (wwo->hThread != INVALID_HANDLE_VALUE && wwo->msgRing.ring_buffer_size > 0);
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_XRUN, 0, FALSE);
-+}
-+
-+/**************************************************************************
-+ * PULSE_StreamMovedCallback [internal]
-+ *
-+ * Called by the pulse mainloop when the stream gets moved, resulting in
-+ * possibly different metrics.
-+ */
-+void PULSE_StreamMovedCallback(pa_stream *s, void *userdata) {
-+ FIXME("stub");
-+}
-+
-+
-+/******************************************************************
-+ * PULSE_StreamStateCallback
-+ *
-+ * Called by pulse whenever the state of the stream changes.
-+ */
-+void PULSE_StreamStateCallback(pa_stream *s, void *userdata) {
-+ assert(s);
-+
-+ switch (pa_stream_get_state(s)) {
-+ case PA_STREAM_READY:
-+ TRACE("Stream %p ready\n", userdata);
-+ break;
-+
-+ case PA_STREAM_TERMINATED:
-+ TRACE("Stream %p terminated\n", userdata);
-+ break;
-+
-+ case PA_STREAM_FAILED:
-+ ERR("Stream %p failed!\n", userdata);
-+ break;
-+
-+ case PA_STREAM_UNCONNECTED:
-+ case PA_STREAM_CREATING:
-+ return;
-+ }
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * PULSE_StreamSucessCallback
-+ */
-+void PULSE_StreamSuccessCallback(pa_stream *s, int success, void *userdata) {
-+ if (!success)
-+ WARN("Stream %p operation failed: %s\n", userdata, pa_strerror(pa_context_errno(PULSE_context)));
-+
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * PULSE_ContextSuccessCallback
-+ */
-+void PULSE_ContextSuccessCallback(pa_context *c, int success, void *userdata) {
-+ if (!success) ERR("Context operation failed: %s\n", pa_strerror(pa_context_errno(c)));
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * Connection management and sink / source management.
-+ */
-+
-+/**************************************************************************
-+ * PULSE_ContextStateCallback [internal]
-+ */
-+static void PULSE_ContextStateCallback(pa_context *c, void *userdata) {
-+ assert(c);
-+
-+ switch (pa_context_get_state(c)) {
-+ case PA_CONTEXT_CONNECTING:
-+ case PA_CONTEXT_UNCONNECTED:
-+ case PA_CONTEXT_AUTHORIZING:
-+ case PA_CONTEXT_SETTING_NAME:
-+ break;
-+
-+ case PA_CONTEXT_READY:
-+ case PA_CONTEXT_TERMINATED:
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+ break;
-+
-+ case PA_CONTEXT_FAILED:
-+ ERR("Context failure: %s\n", pa_strerror(pa_context_errno(c)));
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+ break;
-+ }
-+}
-+
-+/**************************************************************************
-+ * PULSE_AllocateWaveinDevice [internal]
-+ *
-+ * Creates or adds a device to WInDev based on the pa_source_info.
-+ */
-+static void PULSE_AllocateWaveinDevice(const char *name, const char *device, const char *description, const pa_cvolume *v) {
-+ WINE_WAVEDEV *wdi;
-+
-+ if (WInDev)
-+ wdi = HeapReAlloc(GetProcessHeap(), 0, WInDev, sizeof(WINE_WAVEDEV) * (PULSE_WidNumDevs + 1));
-+ else
-+ wdi = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
-+
-+ if (!wdi) return;
-+
-+ WInDev = wdi;
-+ wdi = &WInDev[PULSE_WidNumDevs++];
-+ memset(wdi, 0, sizeof(WINE_WAVEDEV));
-+ memset(&(wdi->caps.in), 0, sizeof(wdi->caps.in));
-+ snprintf(wdi->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
-+ wdi->device_name = pa_xstrdup(device);
-+ strcpy(wdi->interface_name, "winepulse: ");
-+ MultiByteToWideChar(CP_ACP, 0, description, -1, wdi->caps.in.szPname, sizeof(wdi->caps.in.szPname)/sizeof(WCHAR));
-+ wdi->caps.in.szPname[sizeof(wdi->caps.in.szPname)/sizeof(WCHAR) - 1] = '\0';
-+ wdi->caps.in.wMid = MM_CREATIVE;
-+ wdi->caps.in.wPid = MM_CREATIVE_SBP16_WAVEOUT;
-+ wdi->caps.in.vDriverVersion = 0x0100;
-+ wdi->caps.in.wChannels = v->channels == 1 ? 1 : 2;
-+ wdi->caps.in.dwFormats = PULSE_ALL_FORMATS;
-+ memset(&wdi->ds_desc, 0, sizeof(DSDRIVERDESC));
-+ memcpy(wdi->ds_desc.szDesc, description, min(sizeof(wdi->ds_desc.szDesc) - 1, strlen(description)));
-+ memcpy(wdi->ds_desc.szDrvname, "winepulse.drv", 14);
-+ wdi->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-+ wdi->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-+ wdi->ds_caps.dwPrimaryBuffers = 1;
-+ wdi->ds_caps.dwFlags = \
-+ DSCAPS_PRIMARYMONO |
-+ DSCAPS_PRIMARYSTEREO |
-+ DSCAPS_PRIMARY8BIT |
-+ DSCAPS_PRIMARY16BIT |
-+ DSCAPS_SECONDARYMONO |
-+ DSCAPS_SECONDARYSTEREO |
-+ DSCAPS_SECONDARY8BIT |
-+ DSCAPS_SECONDARY16BIT |
-+ DSCCAPS_MULTIPLECAPTURE |
-+ DSCAPS_CERTIFIED | /* Useful? */
-+ DSCAPS_EMULDRIVER; /* Useful? */
-+
-+}
-+
-+/**************************************************************************
-+ * PULSE_AllocateWaveoutDevice [internal]
-+ *
-+ * Creates or adds a sink to the WOutDev array.
-+ */
-+static void PULSE_AllocateWaveoutDevice(const char *name, const char *device, const char *description, const pa_cvolume *v) {
-+ WINE_WAVEDEV *wdo;
-+ int x;
-+
-+ if (WOutDev)
-+ wdo = HeapReAlloc(GetProcessHeap(), 0, WOutDev, sizeof(WINE_WAVEDEV) * (PULSE_WodNumDevs + 1));
-+ else
-+ wdo = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
-+
-+ if (!wdo) return;
-+
-+ WOutDev = wdo;
-+ wdo = &WOutDev[PULSE_WodNumDevs++];
-+ memset(wdo, 0, sizeof(WINE_WAVEDEV));
-+
-+ wdo->device_name = pa_xstrdup(device);
-+ wdo->volume.channels = v->channels;
-+ for (x = 0; x < v->channels; x++) wdo->volume.values[x] = v->values[x];
-+ snprintf(wdo->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
-+ MultiByteToWideChar(CP_ACP, 0, description, -1, wdo->caps.out.szPname, sizeof(wdo->caps.out.szPname)/sizeof(WCHAR));
-+ wdo->caps.out.szPname[sizeof(wdo->caps.out.szPname)/sizeof(WCHAR) - 1] = '\0';
-+ wdo->caps.out.wMid = MM_CREATIVE;
-+ wdo->caps.out.wPid = MM_CREATIVE_SBP16_WAVEOUT;
-+ wdo->caps.out.vDriverVersion = 0x0100;
-+ wdo->caps.out.dwSupport = WAVECAPS_VOLUME | WAVECAPS_SAMPLEACCURATE | WAVECAPS_DIRECTSOUND;
-+ if (v->channels >= 2) {
-+ wdo->caps.out.wChannels = 2;
-+ wdo->caps.out.dwSupport |= WAVECAPS_LRVOLUME;
-+ } else
-+ wdo->caps.out.wChannels = 1;
-+ wdo->caps.out.dwFormats = PULSE_ALL_FORMATS;
-+ memset(&wdo->ds_desc, 0, sizeof(DSDRIVERDESC));
-+ memcpy(wdo->ds_desc.szDesc, description, min(sizeof(wdo->ds_desc.szDesc) - 1, strlen(description)));
-+ memcpy(wdo->ds_desc.szDrvname, "winepulse.drv", 14);
-+ wdo->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-+ wdo->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-+ wdo->ds_caps.dwPrimaryBuffers = 1;
-+ wdo->ds_caps.dwFlags = \
-+ DSCAPS_PRIMARYMONO |
-+ DSCAPS_PRIMARYSTEREO |
-+ DSCAPS_PRIMARY8BIT |
-+ DSCAPS_PRIMARY16BIT |
-+ DSCAPS_SECONDARYMONO |
-+ DSCAPS_SECONDARYSTEREO |
-+ DSCAPS_SECONDARY8BIT |
-+ DSCAPS_SECONDARY16BIT |
-+ DSCAPS_CERTIFIED |
-+ DSCAPS_EMULDRIVER; /* Useful? */
-+}
-+
-+/**************************************************************************
-+ * PULSE_SourceInfoCallback [internal]
-+ */
-+static void PULSE_SourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata) {
-+
-+ if (!eol && i)
-+ PULSE_AllocateWaveinDevice(i->name, i->name, i->description, &i->volume);
-+
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * PULSE_SinkInfoCallback [internal]
-+ */
-+static void PULSE_SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
-+
-+ if (!eol && i)
-+ PULSE_AllocateWaveoutDevice(i->name, i->name, i->description, &i->volume);
-+
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * PULSE_ContextNotifyCallback [internal]
-+ */
-+static void PULSE_ContextNotifyCallback(pa_context *c, void *userdata) {
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+}
-+
-+/**************************************************************************
-+ * PULSE_WaveClose [internal]
-+ *
-+ * Disconnect from the server, deallocated the WaveIn/WaveOut devices, stop and
-+ * free the mainloop.
-+ */
-+
-+static LONG PULSE_WaveClose(void) {
-+ int x;
-+ TRACE("()\n");
-+ if (!PULSE_ml) return DRV_FAILURE;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ /* device_name is allocated with pa_xstrdup, free with pa_xfree */
-+ for (x = 0; x < PULSE_WodNumDevs; x++) pa_xfree(WOutDev[x].device_name);
-+ for (x = 0; x < PULSE_WidNumDevs; x++) pa_xfree(WInDev[x].device_name);
-+ HeapFree(GetProcessHeap(), 0, WOutDev);
-+ HeapFree(GetProcessHeap(), 0, WInDev);
-+ if (PULSE_context) {
-+ PULSE_WaitForOperation(pa_context_drain(PULSE_context, PULSE_ContextNotifyCallback, NULL));
-+ pa_context_disconnect(PULSE_context);
-+ pa_context_unref(PULSE_context);
-+ PULSE_context = NULL;
-+ }
-+
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ pa_threaded_mainloop_stop(PULSE_ml);
-+ pa_threaded_mainloop_free(PULSE_ml);
-+ PULSE_ml = NULL;
-+
-+ return DRV_SUCCESS;
-+}
-+
-+/**************************************************************************
-+ * PULSE_WaveInit [internal]
-+ *
-+ * Connects to the pulseaudio server, tries to discover sinks and sources and
-+ * allocates the WaveIn/WaveOut devices.
-+ */
-+static LONG PULSE_WaveInit(void) {
-+ char *app_name;
-+ char path[PATH_MAX];
-+ char *offset = NULL;
-+ int x = 0;
-+ pa_cvolume fake_cvolume;
-+
-+ WOutDev = NULL;
-+ WInDev = NULL;
-+ PULSE_WodNumDevs = 0;
-+ PULSE_WidNumDevs = 0;
-+ PULSE_context = NULL;
-+ PULSE_ml = NULL;
-+
-+ if (!(PULSE_ml = pa_threaded_mainloop_new())) {
-+ WARN("Failed to create mainloop object.");
-+ return -1;
-+ }
-+
-+ /* Application name giving to pulse should be unique to the binary so that
-+ * pulse-*-restore can be useful */
-+
-+ /* Get binary path, and remove path a-la strrchr */
-+ if (GetModuleFileNameA(NULL, path, PATH_MAX))
-+ offset = strrchr(path, '\\');
-+
-+ if (offset && ++offset && offset < path + PATH_MAX) {
-+ app_name = pa_xmalloc(strlen(offset) + 8);
-+ snprintf(app_name, strlen(offset) + 8, "WINE [%s]", offset);
-+ } else
-+ app_name = pa_xstrdup("WINE Application");
-+
-+ TRACE("App name is \"%s\"\n", app_name);
-+
-+ pa_threaded_mainloop_start(PULSE_ml);
-+ PULSE_context = pa_context_new(pa_threaded_mainloop_get_api(PULSE_ml), app_name);
-+ assert(PULSE_context);
-+ pa_xfree(app_name);
-+
-+ pa_context_set_state_callback(PULSE_context, PULSE_ContextStateCallback, NULL);
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+
-+ TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(PULSE_context), PA_API_VERSION);
-+ TRACE("Attempting to connect to pulseaudio server.\n");
-+ if (pa_context_connect(PULSE_context, NULL, 0, NULL) < 0)
-+ goto fail;
-+
-+ /* Wait for connection */
-+ for (;;) {
-+ pa_context_state_t state = pa_context_get_state(PULSE_context);
-+
-+ if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
-+ goto fail;
-+
-+ if (state == PA_CONTEXT_READY)
-+ break;
-+
-+ pa_threaded_mainloop_wait(PULSE_ml);
-+ }
-+
-+ x = pa_context_get_server_protocol_version(PULSE_context);
-+ TRACE("Connected to server %s with protocol version: %i.\n", pa_context_get_server(PULSE_context), x);
-+ if (x < 14)
-+ WARN("Server is old, expect poor latency or buggy-ness!\n");
-+
-+ fake_cvolume.channels = 2;
-+ pa_cvolume_reset(&fake_cvolume, 2);
-+ /* FIXME Translations? */
-+ PULSE_AllocateWaveoutDevice("default", NULL, "Default", &fake_cvolume);
-+ PULSE_AllocateWaveinDevice("default", NULL, "Default", &fake_cvolume);
-+ PULSE_WaitForOperation(pa_context_get_sink_info_list(PULSE_context, PULSE_SinkInfoCallback, &PULSE_WodNumDevs));
-+ PULSE_WaitForOperation(pa_context_get_source_info_list(PULSE_context, PULSE_SourceInfoCallback, &PULSE_WidNumDevs));
-+ TRACE("Found %u output and %u input device(s).\n", PULSE_WodNumDevs - 1, PULSE_WidNumDevs - 1);
-+
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ return DRV_SUCCESS;
-+
-+fail:
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ ERR("Failed to connect to server\n");
-+ return DRV_FAILURE;
-+}
-+
-+#endif /* HAVE_PULSEAUDIO */
-+
-+/**************************************************************************
-+ * DriverProc (WINEPULSE.@)
-+ */
-+LRESULT CALLBACK PULSE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
-+ LPARAM dwParam1, LPARAM dwParam2) {
-+
-+ switch(wMsg) {
-+#ifdef HAVE_PULSEAUDIO
-+ case DRV_LOAD: return PULSE_WaveInit();
-+ case DRV_FREE: return PULSE_WaveClose();
-+ case DRV_OPEN: return 1;
-+ case DRV_CLOSE: return 1;
-+ case DRV_ENABLE: return 1;
-+ case DRV_DISABLE: return 1;
-+ case DRV_QUERYCONFIGURE: return 1;
-+ case DRV_CONFIGURE: MessageBoxA(0, "PulseAudio MultiMedia Driver !", "PulseAudio Driver", MB_OK); return 1;
-+ case DRV_INSTALL: return DRVCNF_RESTART;
-+ case DRV_REMOVE: return DRVCNF_RESTART;
-+#endif
-+ default:
-+ return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
-+ }
-+}
-diff --git a/dlls/winepulse.drv/wavein.c b/dlls/winepulse.drv/wavein.c
-new file mode 100644
-index 0000000..18c0152
---- /dev/null
-+++ b/dlls/winepulse.drv/wavein.c
-@@ -0,0 +1,620 @@
-+/*
-+ * Wine Driver for PulseAudio - WaveIn Functionality
-+ * http://pulseaudio.org/
-+ *
-+ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
-+ *
-+ * Contains code from other wine multimedia drivers.
-+ *
-+ * This library 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.
-+ *
-+ * This library 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 this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-+ */
-+
-+#include "config.h"
-+
-+#include <stdarg.h>
-+
-+#include "windef.h"
-+#include "winbase.h"
-+#include "wingdi.h"
-+#include "winuser.h"
-+#include "winnls.h"
-+#include "mmddk.h"
-+
-+#include <winepulse.h>
-+
-+#include "wine/debug.h"
-+
-+WINE_DEFAULT_DEBUG_CHANNEL(wave);
-+
-+#if HAVE_PULSEAUDIO
-+
-+/*======================================================================*
-+ * WAVE IN specific PulseAudio Callbacks *
-+ *======================================================================*/
-+
-+/**************************************************************************
-+* widNotifyClient [internal]
-+*/
-+static DWORD widNotifyClient(WINE_WAVEINST* wwi, WORD wMsg, DWORD dwParam1, DWORD dwParam2) {
-+ TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
-+
-+ switch (wMsg) {
-+ case WIM_OPEN:
-+ case WIM_CLOSE:
-+ case WIM_DATA:
-+ if (wwi->wFlags != DCB_NULL &&
-+ !DriverCallback(wwi->waveDesc.dwCallback, wwi->wFlags, (HDRVR)wwi->waveDesc.hWave,
-+ wMsg, wwi->waveDesc.dwInstance, dwParam1, dwParam2)) {
-+ WARN("can't notify client !\n");
-+ return MMSYSERR_ERROR;
-+ }
-+ break;
-+ default:
-+ FIXME("Unknown callback message %u\n", wMsg);
-+ return MMSYSERR_INVALPARAM;
-+ }
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widRecorder_NextFragment [internal]
-+ *
-+ * Gets the next fragment of data from the server.
-+ */
-+static size_t widRecorder_NextFragment(WINE_WAVEINST *wwi) {
-+ size_t nbytes;
-+
-+ pa_stream_peek(wwi->stream, &wwi->buffer, &nbytes);
-+ wwi->buffer_length = nbytes;
-+ wwi->buffer_read_offset = 0;
-+
-+ return nbytes;
-+}
-+
-+
-+/**************************************************************************
-+ * widRecorder_CopyData [internal]
-+ *
-+ * Copys data from the fragments pulse returns to queued buffers.
-+ */
-+static void widRecorder_CopyData(WINE_WAVEINST *wwi) {
-+ LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
-+ size_t nbytes;
-+
-+ while (lpWaveHdr && wwi->state == WINE_WS_PLAYING) {
-+
-+ nbytes = min(wwi->buffer_length - wwi->buffer_read_offset, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
-+ if (nbytes == 0) break;
-+
-+ TRACE("%u bytes from %p to %p\n", nbytes, (PBYTE)wwi->buffer + wwi->buffer_read_offset, lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded);
-+ memcpy(lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, (PBYTE)wwi->buffer + wwi->buffer_read_offset, nbytes);
-+
-+ lpWaveHdr->dwBytesRecorded += nbytes;
-+ wwi->buffer_read_offset += nbytes;
-+
-+ if (wwi->buffer_read_offset == wwi->buffer_length) {
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ pa_stream_drop(wwi->stream);
-+ if (pa_stream_readable_size(wwi->stream))
-+ widRecorder_NextFragment(wwi);
-+ else {
-+ wwi->buffer = NULL;
-+ wwi->buffer_length = 0;
-+ wwi->buffer_read_offset = 0;
-+ }
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ }
-+
-+ if (lpWaveHdr->dwBytesRecorded == lpWaveHdr->dwBufferLength) {
-+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
-+ lpWaveHdr->dwFlags |= WHDR_DONE;
-+ wwi->lpQueuePtr = lpWaveHdr->lpNext;
-+ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
-+ lpWaveHdr = wwi->lpQueuePtr;
-+ }
-+ }
-+}
-+
-+/**************************************************************************
-+ * widRecorder [internal]
-+ */
-+static DWORD CALLBACK widRecorder(LPVOID lpParam) {
-+ WINE_WAVEINST *wwi = (WINE_WAVEINST*)lpParam;
-+ LPWAVEHDR lpWaveHdr;
-+ enum win_wm_message msg;
-+ DWORD param;
-+ HANDLE ev;
-+ DWORD wait = INFINITE;
-+
-+ wwi->state = WINE_WS_STOPPED;
-+ SetEvent(wwi->hStartUpEvent);
-+
-+ for (;;) {
-+
-+ if (wwi->state != WINE_WS_PLAYING) {
-+ wait = INFINITE;
-+ } else {
-+ if (wwi->buffer == NULL && pa_stream_readable_size(wwi->stream)) {
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ wait = pa_bytes_to_usec(widRecorder_NextFragment(wwi), &wwi->sample_spec)/1000;
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ }
-+ }
-+
-+ widRecorder_CopyData(wwi);
-+
-+ PULSE_WaitRingMessage(&wwi->msgRing, wait);
-+
-+ while (PULSE_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev)) {
-+ TRACE("Received %s %x\n", PULSE_getCmdString(msg), param);
-+
-+ switch (msg) {
-+ case WINE_WM_FEED:
-+ SetEvent(ev);
-+ break;
-+ case WINE_WM_STARTING:
-+ wwi->state = WINE_WS_PLAYING;
-+ if (wwi->lpQueuePtr)
-+ wait = pa_bytes_to_usec(wwi->lpQueuePtr->dwBufferLength, &wwi->sample_spec)/1000;
-+ else
-+ wait = INFINITE;
-+ wwi->dwLastReset = wwi->timing_info->read_index;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 0, PULSE_StreamSuccessCallback, NULL));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ SetEvent(ev);
-+ break;
-+ case WINE_WM_HEADER:
-+ lpWaveHdr = (LPWAVEHDR)param;
-+ lpWaveHdr->lpNext = 0;
-+
-+ /* insert buffer at the end of queue */
-+ {
-+ LPWAVEHDR* wh;
-+ for (wh = &(wwi->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
-+ *wh = lpWaveHdr;
-+ }
-+ break;
-+ case WINE_WM_STOPPING:
-+ if (wwi->state != WINE_WS_STOPPED) {
-+ wwi->state = WINE_WS_STOPPED;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ /* return current buffer to app */
-+ lpWaveHdr = wwi->lpQueuePtr;
-+ if (lpWaveHdr) {
-+ LPWAVEHDR lpNext = lpWaveHdr->lpNext;
-+ TRACE("stop %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
-+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
-+ lpWaveHdr->dwFlags |= WHDR_DONE;
-+ wwi->lpQueuePtr = lpNext;
-+ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
-+ }
-+ }
-+ SetEvent(ev);
-+ break;
-+ case WINE_WM_RESETTING:
-+ if (wwi->state != WINE_WS_STOPPED) {
-+ wwi->state = WINE_WS_STOPPED;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ }
-+
-+ /* return all buffers to the app */
-+ for (lpWaveHdr = wwi->lpPlayPtr ? wwi->lpPlayPtr : wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = wwi->lpQueuePtr) {
-+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
-+ lpWaveHdr->dwFlags |= WHDR_DONE;
-+ wwi->lpQueuePtr = lpWaveHdr->lpNext;
-+ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
-+ }
-+
-+ SetEvent(ev);
-+ break;
-+ case WINE_WM_CLOSING:
-+ wwi->hThread = 0;
-+ if ((DWORD)param == 1) {
-+ /* If we are here, the stream failed */
-+ wwi->state = WINE_WS_FAILED;
-+ SetEvent(ev);
-+ PULSE_DestroyRingMessage(&wwi->msgRing);
-+ widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
-+ wwi->lpPlayPtr = wwi->lpQueuePtr = NULL;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ pa_stream_disconnect(wwi->stream);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ TRACE("Thread exiting because of failure.\n");
-+ ExitThread(1);
-+ }
-+ wwi->state = WINE_WS_CLOSED;
-+ SetEvent(ev);
-+ ExitThread(0);
-+ /* shouldn't go here */
-+ default:
-+ FIXME("unknown message %d\n", msg);
-+ break;
-+ } /* switch(msg) */
-+ } /* while(PULSE_RetrieveRingMessage()) */
-+ } /* for (;;) */
-+}
-+
-+/**************************************************************************
-+ * widOpen [internal]
-+ */
-+static DWORD widOpen(WORD wDevID, LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags) {
-+ WINE_WAVEDEV *wdi;
-+ WINE_WAVEINST *wwi = NULL;
-+ DWORD ret = MMSYSERR_NOERROR;
-+
-+ TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
-+ if (lpDesc == NULL) {
-+ WARN("Invalid Parameter !\n");
-+ return MMSYSERR_INVALPARAM;
-+ }
-+
-+ if (wDevID >= PULSE_WidNumDevs) {
-+ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WidNumDevs);
-+ return MMSYSERR_BADDEVICEID;
-+ }
-+ wdi = &WInDev[wDevID];
-+
-+ wwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_WAVEINST));
-+ if (!wwi) return MMSYSERR_NOMEM;
-+ *lpdwUser = (DWORD)wwi;
-+
-+ /* check to see if format is supported and make pa_sample_spec struct */
-+ if (!PULSE_SetupFormat(lpDesc->lpFormat, &wwi->sample_spec)) {
-+ WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
-+ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
-+ lpDesc->lpFormat->nSamplesPerSec);
-+ ret = WAVERR_BADFORMAT;
-+ goto exit;
-+ }
-+
-+ if (TRACE_ON(wave)) {
-+ char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
-+ pa_sample_spec_snprint(t, sizeof(t), &wwi->sample_spec);
-+ TRACE("Sample spec '%s'\n", t);
-+ }
-+
-+ if (dwFlags & WAVE_FORMAT_QUERY) {
-+ TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
-+ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
-+ lpDesc->lpFormat->nSamplesPerSec);
-+ ret = MMSYSERR_NOERROR;
-+ goto exit;
-+ }
-+
-+ wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
-+ wwi->waveDesc = *lpDesc;
-+ PULSE_InitRingMessage(&wwi->msgRing);
-+
-+ wwi->stream = pa_stream_new(PULSE_context, "WaveIn", &wwi->sample_spec, NULL);
-+ if (!wwi->stream) {
-+ ret = WAVERR_BADFORMAT;
-+ goto exit;
-+ }
-+
-+ pa_stream_set_state_callback(wwi->stream, PULSE_StreamStateCallback, wwi);
-+
-+ wwi->buffer_attr.maxlength = (uint32_t)-1;
-+ wwi->buffer_attr.fragsize = pa_bytes_per_second(&wwi->sample_spec) / 100;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ TRACE("Asking to open %s for recording.\n", wdi->device_name);
-+ pa_stream_connect_record(wwi->stream, wdi->device_name, &wwi->buffer_attr,
-+ PA_STREAM_START_CORKED |
-+ PA_STREAM_AUTO_TIMING_UPDATE |
-+ PA_STREAM_INTERPOLATE_TIMING);
-+
-+ for (;;) {
-+ pa_context_state_t cstate = pa_context_get_state(PULSE_context);
-+ pa_stream_state_t sstate = pa_stream_get_state(wwi->stream);
-+
-+ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
-+ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
-+ ERR("Failed to connect context object: %s\n", pa_strerror(pa_context_errno(PULSE_context)));
-+ ret = MMSYSERR_NODRIVER;
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ goto exit;
-+ }
-+
-+ if (sstate == PA_STREAM_READY)
-+ break;
-+
-+ pa_threaded_mainloop_wait(PULSE_ml);
-+ }
-+ TRACE("(%p)->stream connected for recording.\n", wwi);
-+
-+ PULSE_WaitForOperation(pa_stream_update_timing_info(wwi->stream, PULSE_StreamSuccessCallback, wwi));
-+
-+ wwi->timing_info = pa_stream_get_timing_info(wwi->stream);
-+ assert(wwi->timing_info);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ wwi->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-+ wwi->hThread = CreateThread(NULL, 0, widRecorder, (LPVOID)wwi, 0, &(wwi->dwThreadID));
-+ if (wwi->hThread)
-+ SetThreadPriority(wwi->hThread, THREAD_PRIORITY_TIME_CRITICAL);
-+ else {
-+ ERR("Thread creation for the widRecorder failed!\n");
-+ ret = MMSYSERR_NOMEM;
-+ goto exit;
-+ }
-+ WaitForSingleObject(wwi->hStartUpEvent, INFINITE);
-+ CloseHandle(wwi->hStartUpEvent);
-+ wwi->hStartUpEvent = INVALID_HANDLE_VALUE;
-+
-+ return widNotifyClient(wwi, WIM_OPEN, 0L, 0L);
-+
-+exit:
-+ if (!wwi)
-+ return ret;
-+
-+ if (wwi->hStartUpEvent != INVALID_HANDLE_VALUE)
-+ CloseHandle(wwi->hStartUpEvent);
-+
-+ if (wwi->msgRing.ring_buffer_size > 0)
-+ PULSE_DestroyRingMessage(&wwi->msgRing);
-+
-+ if (wwi->stream) {
-+ if (pa_stream_get_state(wwi->stream) == PA_STREAM_READY)
-+ pa_stream_disconnect(wwi->stream);
-+ pa_stream_unref(wwi->stream);
-+ }
-+ HeapFree(GetProcessHeap(), 0, wwi);
-+
-+ return ret;
-+}
-+/**************************************************************************
-+ * widClose [internal]
-+ */
-+static DWORD widClose(WORD wDevID, WINE_WAVEINST *wwi) {
-+ DWORD ret;
-+
-+ TRACE("(%u, %p);\n", wDevID, wwi);
-+ if (wDevID >= PULSE_WidNumDevs) {
-+ WARN("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
-+ return MMSYSERR_INVALHANDLE;
-+ } else if (!wwi) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (wwi->state != WINE_WS_FAILED) {
-+ if (wwi->lpQueuePtr) {
-+ WARN("buffers recording recording !\n");
-+ return WAVERR_STILLPLAYING;
-+ }
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ if (pa_stream_get_state(wwi->stream) == PA_STREAM_READY)
-+ pa_stream_drop(wwi->stream);
-+ pa_stream_disconnect(wwi->stream);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ if (wwi->hThread != INVALID_HANDLE_VALUE)
-+ PULSE_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
-+
-+ PULSE_DestroyRingMessage(&wwi->msgRing);
-+ }
-+ ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
-+
-+ pa_stream_unref(wwi->stream);
-+ TRACE("Deallocating record instance.\n");
-+ HeapFree(GetProcessHeap(), 0, wwi);
-+ return ret;
-+}
-+
-+/**************************************************************************
-+ * widAddBuffer [internal]
-+ *
-+ */
-+static DWORD widAddBuffer(WINE_WAVEINST* wwi, LPWAVEHDR lpWaveHdr, DWORD dwSize) {
-+ TRACE("(%p, %p, %08X);\n", wwi, lpWaveHdr, dwSize);
-+
-+ if (!wwi || wwi->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
-+ return WAVERR_UNPREPARED;
-+
-+ if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
-+ return WAVERR_STILLPLAYING;
-+
-+ lpWaveHdr->dwFlags &= ~WHDR_DONE;
-+ lpWaveHdr->dwFlags |= WHDR_INQUEUE;
-+ lpWaveHdr->dwBytesRecorded = 0;
-+ lpWaveHdr->lpNext = 0;
-+
-+ PULSE_AddRingMessage(&wwi->msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
-+
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widRecorderMessage [internal]
-+ */
-+static DWORD widRecorderMessage(WINE_WAVEINST *wwi, enum win_wm_message message) {
-+ if (!wwi || wwi->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ PULSE_AddRingMessage(&wwi->msgRing, message, 0, TRUE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widGetPosition [internal]
-+ */
-+static DWORD widGetPosition(WINE_WAVEINST *wwi, LPMMTIME lpTime, DWORD uSize) {
-+ DWORD bytes, time;
-+ if (!wwi || wwi->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (lpTime == NULL) return MMSYSERR_INVALPARAM;
-+
-+ bytes = wwi->timing_info->read_index - wwi->dwLastReset;
-+ time = pa_bytes_to_usec(bytes, &wwi->sample_spec) / 1000;
-+
-+ switch (lpTime->wType) {
-+ case TIME_SAMPLES:
-+ lpTime->u.sample = bytes / pa_frame_size(&wwi->sample_spec);
-+ TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
-+ break;
-+ case TIME_MS:
-+ lpTime->u.ms = time;
-+ TRACE("TIME_MS=%u\n", lpTime->u.ms);
-+ break;
-+ case TIME_SMPTE:
-+ lpTime->u.smpte.fps = 30;
-+ lpTime->u.smpte.sec = time/1000;
-+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
-+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
-+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
-+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
-+ lpTime->u.smpte.frame = time / lpTime->u.smpte.fps * 1000;
-+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
-+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
-+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
-+ break;
-+ default:
-+ WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
-+ lpTime->wType = TIME_BYTES;
-+ /* fall through */
-+ case TIME_BYTES:
-+ lpTime->u.cb = bytes;
-+ TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
-+ break;
-+ }
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widGetDevCaps [internal]
-+ */
-+static DWORD widGetDevCaps(DWORD wDevID, LPWAVEINCAPSW lpCaps, DWORD dwSize) {
-+ TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
-+
-+ if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
-+
-+ if (wDevID >= PULSE_WidNumDevs) {
-+ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WidNumDevs);
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ memcpy(lpCaps, &(WInDev[wDevID].caps.in), min(dwSize, sizeof(*lpCaps)));
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widGetNumDevs [internal]
-+ * Context-sanity check here, as if we respond with 0, WINE will move on
-+ * to the next wavein driver.
-+ */
-+static DWORD widGetNumDevs() {
-+ if (pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
-+ return 0;
-+
-+ return PULSE_WidNumDevs;
-+}
-+
-+/**************************************************************************
-+ * widDevInterfaceSize [internal]
-+ */
-+static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1) {
-+ TRACE("(%u, %p)\n", wDevID, dwParam1);
-+
-+ *dwParam1 = MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
-+ NULL, 0 ) * sizeof(WCHAR);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widDevInterface [internal]
-+ */
-+static DWORD widDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2) {
-+ if (dwParam2 >= MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
-+ NULL, 0 ) * sizeof(WCHAR))
-+ {
-+ MultiByteToWideChar(CP_UNIXCP, 0, WInDev[wDevID].interface_name, -1,
-+ dwParam1, dwParam2 / sizeof(WCHAR));
-+ return MMSYSERR_NOERROR;
-+ }
-+ return MMSYSERR_INVALPARAM;
-+}
-+
-+/**************************************************************************
-+ * widDsDesc [internal]
-+ */
-+DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
-+{
-+ *desc = WInDev[wDevID].ds_desc;
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * widMessage (WINEPULSE.@)
-+ */
-+DWORD WINAPI PULSE_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
-+ DWORD dwParam1, DWORD dwParam2) {
-+
-+ switch (wMsg) {
-+ case DRVM_INIT:
-+ case DRVM_EXIT:
-+ case DRVM_ENABLE:
-+ case DRVM_DISABLE:
-+ /* FIXME: Pretend this is supported */
-+ return 0;
-+ case WIDM_OPEN: return widOpen (wDevID, (LPDWORD)dwUser, (LPWAVEOPENDESC)dwParam1, dwParam2);
-+ case WIDM_CLOSE: return widClose (wDevID, (WINE_WAVEINST*)dwUser);
-+ case WIDM_ADDBUFFER: return widAddBuffer ((WINE_WAVEINST*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
-+ case WIDM_PREPARE: return MMSYSERR_NOTSUPPORTED;
-+ case WIDM_UNPREPARE: return MMSYSERR_NOTSUPPORTED;
-+ case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (LPWAVEINCAPSW)dwParam1, dwParam2);
-+ case WIDM_GETNUMDEVS: return widGetNumDevs ();
-+ case WIDM_GETPOS: return widGetPosition ((WINE_WAVEINST*)dwUser, (LPMMTIME)dwParam1, dwParam2);
-+ case WIDM_RESET: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_RESETTING);
-+ case WIDM_START: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STARTING);
-+ case WIDM_STOP: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STOPPING);
-+ case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
-+ case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
-+ case DRV_QUERYDSOUNDIFACE: return MMSYSERR_NOTSUPPORTED; /* Use emulation, as there is no advantage */
-+ case DRV_QUERYDSOUNDDESC: return widDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
-+ default:
-+ FIXME("unknown message %d!\n", wMsg);
-+ }
-+ return MMSYSERR_NOTSUPPORTED;
-+}
-+
-+#else /* HAVE_PULSEAUDIO */
-+
-+/**************************************************************************
-+ * widMessage (WINEPULSE.@)
-+ */
-+DWORD WINAPI PULSE_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
-+ DWORD dwParam1, DWORD dwParam2) {
-+// FIXME("(%u, %04X, %08X, %08X, %08X):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
-+ return MMSYSERR_NOTENABLED;
-+}
-+
-+#endif /* HAVE_PULSEAUDIO */
-diff --git a/dlls/winepulse.drv/waveout.c b/dlls/winepulse.drv/waveout.c
-new file mode 100644
-index 0000000..e976067
---- /dev/null
-+++ b/dlls/winepulse.drv/waveout.c
-@@ -0,0 +1,1100 @@
-+/*
-+ * Wine Driver for PulseAudio - WaveOut Functionality
-+ * http://pulseaudio.org/
-+ *
-+ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
-+ *
-+ * Contains code from other wine multimedia drivers.
-+ *
-+ * This library 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.
-+ *
-+ * This library 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 this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-+ */
-+
-+#include "config.h"
-+
-+#include <stdarg.h>
-+
-+#include "windef.h"
-+#include "winbase.h"
-+#include "wingdi.h"
-+#include "winuser.h"
-+#include "winnls.h"
-+#include "winerror.h"
-+#include "mmddk.h"
-+#include "mmreg.h"
-+
-+#include <winepulse.h>
-+
-+#include "wine/debug.h"
-+
-+WINE_DEFAULT_DEBUG_CHANNEL(wave);
-+
-+#if HAVE_PULSEAUDIO
-+
-+/* state diagram for waveOut writing:
-+ *
-+ * +---------+-------------+---------------+---------------------------------+
-+ * | state | function | event | new state |
-+ * +---------+-------------+---------------+---------------------------------+
-+ * | | open() | | STOPPED |
-+ * | PAUSED | write() | | PAUSED |
-+ * | STOPPED | write() | <thrd create> | PLAYING |
-+ * | PLAYING | write() | HEADER | PLAYING |
-+ * | (other) | write() | <error> | |
-+ * | (any) | pause() | PAUSING | PAUSED |
-+ * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
-+ * | PAUSED | reset() | RESETTING | PAUSED |
-+ * | (other) | reset() | RESETTING | STOPPED |
-+ * | (any) | close() | CLOSING | CLOSED |
-+ * +---------+-------------+---------------+---------------------------------+
-+ */
-+
-+/*
-+ * - It is currently unknown if pausing in a loop works the same as expected.
-+ */
-+
-+/*======================================================================*
-+ * WAVE OUT specific PulseAudio Callbacks *
-+ *======================================================================*/
-+
-+/**************************************************************************
-+ * WAVEOUT_StreamRequestCallback
-+ *
-+ * Called by the pulse mainloop whenever it wants audio data.
-+ */
-+static void WAVEOUT_StreamRequestCallback(pa_stream *s, size_t nbytes, void *userdata) {
-+ WINE_WAVEINST *ww = (WINE_WAVEINST*)userdata;
-+
-+ TRACE("Asking to be fed %u bytes\n", nbytes);
-+
-+ /* Make sure that the player/recorder is running */
-+ if (ww->hThread != INVALID_HANDLE_VALUE && ww->msgRing.messages) {
-+ PULSE_AddRingMessage(&ww->msgRing, WINE_WM_FEED, (DWORD)nbytes, FALSE);
-+ }
-+}
-+
-+/**************************************************************************
-+ * WAVEOUT_SinkInputInfoCallback [internal]
-+ *
-+ * Called by the pulse thread. Used for wodGetVolume.
-+ */
-+static void WAVEOUT_SinkInputInfoCallback(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) {
-+ WINE_WAVEINST* wwo = (WINE_WAVEINST*)userdata;
-+ if (!eol && i) {
-+ for (wwo->volume.channels = 0; wwo->volume.channels != i->volume.channels; wwo->volume.channels++)
-+ wwo->volume.values[wwo->volume.channels] = i->volume.values[wwo->volume.channels];
-+ pa_threaded_mainloop_signal(PULSE_ml, 0);
-+ }
-+}
-+
-+/*======================================================================*
-+ * "Low level" WAVE OUT implementation *
-+ *======================================================================*/
-+
-+/**************************************************************************
-+ * wodPlayer_NotifyClient [internal]
-+ */
-+static DWORD wodPlayer_NotifyClient(WINE_WAVEINST* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2) {
-+ TRACE("wMsg = 0x%04x dwParm1 = %04X dwParam2 = %04X\n", wMsg, dwParam1, dwParam2);
-+
-+ switch (wMsg) {
-+ case WOM_OPEN:
-+ case WOM_CLOSE:
-+ case WOM_DONE:
-+ if (wwo->wFlags != DCB_NULL &&
-+ !DriverCallback(wwo->waveDesc.dwCallback, wwo->wFlags, (HDRVR)wwo->waveDesc.hWave,
-+ wMsg, wwo->waveDesc.dwInstance, dwParam1, dwParam2)) {
-+ WARN("can't notify client !\n");
-+ return MMSYSERR_ERROR;
-+ }
-+ break;
-+ default:
-+ FIXME("Unknown callback message %u\n", wMsg);
-+ return MMSYSERR_INVALPARAM;
-+ }
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_BeginWaveHdr [internal]
-+ *
-+ * Makes the specified lpWaveHdr the currently playing wave header.
-+ * If the specified wave header is a begin loop and we're not already in
-+ * a loop, setup the loop.
-+ */
-+static void wodPlayer_BeginWaveHdr(WINE_WAVEINST* wwo, LPWAVEHDR lpWaveHdr) {
-+ wwo->lpPlayPtr = lpWaveHdr;
-+
-+ if (!lpWaveHdr) return;
-+
-+ if (lpWaveHdr->dwFlags & WHDR_BEGINLOOP) {
-+ if (wwo->lpLoopPtr) {
-+ WARN("Already in a loop. Discarding loop on this header (%p)\n", lpWaveHdr);
-+ } else {
-+ TRACE("Starting loop (%dx) with %p\n", lpWaveHdr->dwLoops, lpWaveHdr);
-+ wwo->lpLoopPtr = lpWaveHdr;
-+ /* Windows does not touch WAVEHDR.dwLoops,
-+ * so we need to make an internal copy */
-+ wwo->dwLoops = lpWaveHdr->dwLoops;
-+ }
-+ }
-+ wwo->dwPartialOffset = 0;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_PlayPtrNext [internal]
-+ *
-+ * Advance the play pointer to the next waveheader, looping if required.
-+ */
-+static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEINST* wwo) {
-+ LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
-+
-+ wwo->dwPartialOffset = 0;
-+ if ((lpWaveHdr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr) {
-+ /* We're at the end of a loop, loop if required */
-+ if (--wwo->dwLoops > 0) {
-+ wwo->lpPlayPtr = wwo->lpLoopPtr;
-+ } else {
-+ /* Handle overlapping loops correctly */
-+ if (wwo->lpLoopPtr != lpWaveHdr && (lpWaveHdr->dwFlags & WHDR_BEGINLOOP)) {
-+ FIXME("Correctly handled case ? (ending loop buffer also starts a new loop)\n");
-+ /* shall we consider the END flag for the closing loop or for
-+ * the opening one or for both ???
-+ * code assumes for closing loop only
-+ */
-+ } else {
-+ lpWaveHdr = lpWaveHdr->lpNext;
-+ }
-+ wwo->lpLoopPtr = NULL;
-+ wodPlayer_BeginWaveHdr(wwo, lpWaveHdr);
-+ }
-+ } else {
-+ /* We're not in a loop. Advance to the next wave header */
-+ wodPlayer_BeginWaveHdr(wwo, lpWaveHdr = lpWaveHdr->lpNext);
-+ }
-+
-+ return lpWaveHdr;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_CheckReleasing [internal]
-+ *
-+ * Check to make sure that playback has not stalled. If stalled ask to reduce
-+ * the size of the buffer on the pulse server side.
-+ */
-+static void wodPlayer_CheckReleasing(WINE_WAVEINST *wwo) {
-+ LPWAVEHDR lpWaveHdr = wwo->lpQueuePtr;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ if (!wwo->timing_info->playing && lpWaveHdr && !wwo->lpPlayPtr && wwo->state == WINE_WS_PLAYING) {
-+
-+ /* Try and adjust the buffer attributes so that playback can start.
-+ * Because of bugs this call does not work on servers 0.9.11 to 0.9.14.
-+ * Once new version of pulseaudio become ubiquitous we will drop
-+ * support for versions before 0.9.15 because they have too many bugs.
-+ */
-+
-+ /* Make sure the buffer_attr tlength hasn't been defined before */
-+ if (wwo->buffer_attr.tlength == -1) {
-+
-+ wwo->buffer_attr.tlength = wwo->timing_info->write_index;
-+ WARN("Asking for new buffer tlength of %llums (%u bytes)\n",
-+ pa_bytes_to_usec(wwo->buffer_attr.tlength, &wwo->sample_spec) / 1000,
-+ wwo->buffer_attr.tlength);
-+
-+ if (pa_context_get_server_protocol_version(PULSE_context) < 15)
-+ ERR("Might get disconnected because of a bug in this pulseaudio server version.\n");
-+
-+ PULSE_WaitForOperation(pa_stream_set_buffer_attr(wwo->stream, &wwo->buffer_attr, PULSE_StreamSuccessCallback, wwo));
-+ }
-+ }
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_NotifyCompletions [internal]
-+ *
-+ * Notifies the client of wavehdr completion starting from lpQueuePtr and
-+ * stopping when hitting an unwritten wavehdr, the beginning of a loop or a
-+ * wavehdr that has not been played, when referenced to the time parameter.
-+ */
-+static DWORD wodPlayer_NotifyCompletions(WINE_WAVEINST* wwo, BOOL force, pa_usec_t time) {
-+ LPWAVEHDR lpWaveHdr = wwo->lpQueuePtr;
-+ pa_usec_t wait;
-+
-+ while (lpWaveHdr) {
-+ if (!force) {
-+ /* Start from lpQueuePtr and keep notifying until:
-+ * - we hit an unwritten wavehdr
-+ * - we hit the beginning of a running loop
-+ * - we hit a wavehdr which hasn't finished playing
-+ */
-+ if (lpWaveHdr == wwo->lpLoopPtr) { TRACE("loop %p\n", lpWaveHdr); return INFINITE; }
-+ if (lpWaveHdr == wwo->lpPlayPtr) { TRACE("play %p\n", lpWaveHdr); return INFINITE; }
-+
-+ /* See if this data has been played, and if not, return when it will have been */
-+ wait = pa_bytes_to_usec(lpWaveHdr->reserved + lpWaveHdr->dwBufferLength, &wwo->sample_spec);
-+ if (wait >= time) {
-+ wait = ((wait - time) + 999) / 1000;
-+ return wait ?: 1;
-+ }
-+ }
-+
-+ /* return the wavehdr */
-+ wwo->lpQueuePtr = lpWaveHdr->lpNext;
-+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
-+ lpWaveHdr->dwFlags |= WHDR_DONE;
-+
-+ wodPlayer_NotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0);
-+ lpWaveHdr = wwo->lpQueuePtr;
-+ }
-+ /* No more wavehdrs */
-+ TRACE("Empty queue\n");
-+ return INFINITE;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_WriteMax [internal]
-+ *
-+ * Write either how much free space or how much data we have, depending on
-+ * which is less
-+ */
-+static int wodPlayer_WriteMax(WINE_WAVEINST *wwo, size_t *space) {
-+ LPWAVEHDR lpWaveHdr = wwo->lpPlayPtr;
-+ size_t nbytes;
-+
-+ nbytes = min(lpWaveHdr->dwBufferLength - wwo->dwPartialOffset, *space);
-+
-+ TRACE("Writing wavehdr %p.%u[%u]\n", lpWaveHdr, wwo->dwPartialOffset, lpWaveHdr->dwBufferLength);
-+ pa_stream_write(wwo->stream, lpWaveHdr->lpData + wwo->dwPartialOffset, nbytes, NULL, 0, PA_SEEK_RELATIVE);
-+
-+ /* Check to see if we wrote all of the wavehdr */
-+ if ((wwo->dwPartialOffset += nbytes) >= lpWaveHdr->dwBufferLength)
-+ wodPlayer_PlayPtrNext(wwo);
-+
-+ *space -= nbytes;
-+
-+ return nbytes;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_Feed [internal]
-+ *
-+ * Feed as much sound data as we can into pulse using wodPlayer_WriteMax.
-+ * size_t space _must_ have come from either pa_stream_writable_size() or
-+ * the value from a stream write callback, as if it isn't you run the risk
-+ * of a buffer overflow in which audio data will be lost.
-+ */
-+static void wodPlayer_Feed(WINE_WAVEINST* wwo, size_t space) {
-+
-+ /* No more room... no need to try to feed */
-+ if (space == 0) return;
-+
-+ if (!wwo->stream || !PULSE_context ||
-+ pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
-+ pa_stream_get_state(wwo->stream) != PA_STREAM_READY)
-+ return;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ /* Feed from a partial wavehdr */
-+ if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
-+ wodPlayer_WriteMax(wwo, &space);
-+
-+ /* Feed wavehdrs until we run out of wavehdrs or buffer space */
-+ if (wwo->dwPartialOffset == 0 && wwo->lpPlayPtr) {
-+ do {
-+ wwo->lpPlayPtr->reserved = wwo->timing_info->write_index;
-+ } while (wodPlayer_WriteMax(wwo, &space) > 0 && wwo->lpPlayPtr && space > 0);
-+ }
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_Reset [internal]
-+ *
-+ * wodPlayer helper. Resets current output stream.
-+ */
-+static void wodPlayer_Reset(WINE_WAVEINST* wwo) {
-+ enum win_wm_message msg;
-+ DWORD param;
-+ HANDLE ev;
-+
-+ TRACE("(%p)\n", wwo);
-+
-+ /* remove any buffer */
-+ wodPlayer_NotifyCompletions(wwo, TRUE, 0);
-+
-+ wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
-+ if (wwo->state != WINE_WS_PAUSED)
-+ wwo->state = WINE_WS_STOPPED;
-+ wwo->dwPartialOffset = 0;
-+
-+ if (!wwo->stream ||
-+ !PULSE_context ||
-+ pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
-+ pa_stream_get_state(wwo->stream) != PA_STREAM_READY) {
-+ return;
-+ }
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+
-+ /* flush the output buffer of written data*/
-+ PULSE_WaitForOperation(pa_stream_flush(wwo->stream, PULSE_StreamSuccessCallback, NULL));
-+
-+ /* Reset the written byte count as some data may have been flushed */
-+ if (wwo->timing_info->write_index_corrupt)
-+ PULSE_WaitForOperation(pa_stream_update_timing_info(wwo->stream, PULSE_StreamSuccessCallback, wwo));
-+ wwo->dwLastReset = wwo->timing_info->write_index;
-+
-+ /* return all pending headers in queue */
-+ EnterCriticalSection(&wwo->msgRing.msg_crst);
-+ while (PULSE_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
-+ if (msg != WINE_WM_HEADER) {
-+ SetEvent(ev);
-+ continue;
-+ }
-+ ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
-+ ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;
-+ wodPlayer_NotifyClient(wwo, WOM_DONE, param, 0);
-+ }
-+ PULSE_ResetRingMessage(&wwo->msgRing);
-+ LeaveCriticalSection(&wwo->msgRing.msg_crst);
-+
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_GetStreamTime [internal]
-+ *
-+ * Returns how many microseconds into the playback the audio stream is. Does
-+ * not reset to 0 on Reset() calls. Better than pa_stream_get_time() as it is
-+ * more constant.
-+ */
-+static pa_usec_t WAVEOUT_GetStreamTime(WINE_WAVEINST *wwo) {
-+ pa_usec_t time, temp;
-+ const pa_timing_info *t;
-+
-+ t = wwo->timing_info;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ time = pa_bytes_to_usec(t->read_index, &wwo->sample_spec);
-+
-+ if (t->read_index_corrupt) {
-+ WARN("Read index corrupt?!\n");
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ return time;
-+ }
-+
-+ if (t->playing) {
-+ time += pa_timeval_age(&t->timestamp);
-+
-+ temp = t->transport_usec + t->configured_sink_usec;
-+ if (temp > wwo->buffer_attr.tlength) temp = wwo->buffer_attr.tlength;
-+ if (temp < time) time -= temp; else time = 0;
-+ }
-+
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ return time;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer_ProcessMessages [internal]
-+ */
-+static DWORD wodPlayer_ProcessMessages(WINE_WAVEINST* wwo) {
-+ LPWAVEHDR lpWaveHdr;
-+ enum win_wm_message msg;
-+ DWORD param, msgcount = 0;
-+ HANDLE ev;
-+
-+ while (PULSE_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
-+ TRACE("Received %s %x\n", PULSE_getCmdString(msg), param);
-+ msgcount++;
-+
-+ switch (msg) {
-+ case WINE_WM_PAUSING:
-+ wwo->state = WINE_WS_PAUSED;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_cork(wwo->stream, 1, PULSE_StreamSuccessCallback, wwo));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_RESTARTING:
-+ if (wwo->state == WINE_WS_PAUSED) {
-+ wwo->state = WINE_WS_PLAYING;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_cork(wwo->stream, 0, PULSE_StreamSuccessCallback, wwo));
-+ /* If the serverside buffer was near full before pause, we need to
-+ * have space to write soon, so force playback start */
-+ PULSE_WaitForOperation(pa_stream_trigger(wwo->stream, PULSE_StreamSuccessCallback, wwo));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ }
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_HEADER:
-+ lpWaveHdr = (LPWAVEHDR)param;
-+ /* insert buffer at the end of queue */
-+ {
-+ LPWAVEHDR* wh;
-+ for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
-+ *wh = lpWaveHdr;
-+ }
-+
-+ if (!wwo->lpPlayPtr)
-+ wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
-+ if (wwo->state == WINE_WS_STOPPED)
-+ wwo->state = WINE_WS_PLAYING;
-+
-+ wodPlayer_Feed(wwo, pa_stream_writable_size(wwo->stream));
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_RESETTING:
-+ wodPlayer_Reset(wwo);
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_BREAKLOOP:
-+ if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL)
-+ /* ensure exit at end of current loop */
-+ wwo->dwLoops = 1;
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_FEED: /* Sent by the pulse thread */
-+ wodPlayer_Feed(wwo, pa_stream_writable_size(wwo->stream));
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_XRUN: /* Sent by the pulse thread */
-+ wodPlayer_NotifyCompletions(wwo, FALSE, (pa_usec_t)-1);
-+ SetEvent(ev);
-+ break;
-+
-+ case WINE_WM_CLOSING: /* If param = 1, close because of a failure */
-+ wwo->hThread = NULL;
-+ if ((DWORD)param == 1) {
-+ /* If we are here, the stream has failed */
-+ wwo->state = WINE_WS_FAILED;
-+ SetEvent(ev);
-+ PULSE_DestroyRingMessage(&wwo->msgRing);
-+ wodPlayer_NotifyCompletions(wwo, TRUE, 0);
-+ wodPlayer_NotifyClient(wwo, WOM_CLOSE, 0L, 0L);
-+ wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ pa_stream_disconnect(wwo->stream);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ TRACE("Thread exiting because of failure.\n");
-+ ExitThread(1);
-+ /* Stream instance will get dereferenced in wod_Close */
-+ }
-+ wwo->state = WINE_WS_CLOSED;
-+ /* sanity check: this should not happen since the device must have been reset before */
-+ if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
-+ SetEvent(ev);
-+ TRACE("Thread exiting.\n");
-+ ExitThread(0);
-+ /* shouldn't go here */
-+
-+ default:
-+ FIXME("unknown message %d\n", msg);
-+ break;
-+ }
-+ }
-+
-+ return msgcount;
-+}
-+
-+/**************************************************************************
-+ * wodPlayer [internal]
-+ *
-+ * The thread which is responsible for returning WaveHdrs via DriverCallback,
-+ * the writing of queued WaveHdrs, and all pause / reset stream management.
-+ */
-+static DWORD CALLBACK wodPlayer(LPVOID lpParam) {
-+ WINE_WAVEINST *wwo = (WINE_WAVEINST*)lpParam;
-+ DWORD dwSleepTime = INFINITE;
-+
-+ wwo->state = WINE_WS_STOPPED;
-+ SetEvent(wwo->hStartUpEvent);
-+
-+ /* Wait for the shortest time before an action is required. If there are
-+ * no pending actions, wait forever for a command. */
-+ for (;;) {
-+ TRACE("Waiting %u ms\n", dwSleepTime);
-+ PULSE_WaitRingMessage(&wwo->msgRing, dwSleepTime);
-+
-+ /* If no messages were processed during the timeout it might be because
-+ * audio is not flowing yet, so check. */
-+ if (wodPlayer_ProcessMessages(wwo) == 0)
-+ wodPlayer_CheckReleasing(wwo);
-+
-+ /* If there is audio playing, return headers and get next timeout */
-+ if (wwo->state == WINE_WS_PLAYING) {
-+ dwSleepTime = wodPlayer_NotifyCompletions(wwo, FALSE, WAVEOUT_GetStreamTime(wwo));
-+ } else
-+ dwSleepTime = INFINITE;
-+ }
-+}
-+
-+/**************************************************************************
-+ * wodOpen [internal]
-+ *
-+ * Create a new pa_stream and connect it to a sink while creating a new
-+ * WINE_WAVEINST to represent the device to the windows application.
-+ */
-+static DWORD wodOpen(WORD wDevID, LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags) {
-+ WINE_WAVEDEV *wdo;
-+ WINE_WAVEINST *wwo = NULL;
-+ DWORD ret = MMSYSERR_NOERROR;
-+ pa_stream_flags_t stream_flags;
-+
-+ TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
-+ if (lpDesc == NULL) {
-+ WARN("Invalid Parameter!\n");
-+ return MMSYSERR_INVALPARAM;
-+ }
-+
-+ if (wDevID >= PULSE_WodNumDevs) {
-+ WARN("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
-+ return MMSYSERR_BADDEVICEID;
-+ }
-+ wdo = &WOutDev[wDevID];
-+
-+ wwo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_WAVEINST));
-+ if (!wwo) {
-+ WARN("Out of memory?!\n");
-+ return MMSYSERR_NOMEM;
-+ }
-+ *lpdwUser = (DWORD)wwo;
-+
-+ /* check to see if format is supported and make pa_sample_spec struct */
-+ if (!PULSE_SetupFormat(lpDesc->lpFormat, &wwo->sample_spec)) {
-+ WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
-+ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
-+ lpDesc->lpFormat->nSamplesPerSec);
-+ ret = WAVERR_BADFORMAT;
-+ goto exit;
-+ }
-+
-+ /* Check to see if this was just a query */
-+ if (dwFlags & WAVE_FORMAT_QUERY) {
-+ TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
-+ lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
-+ lpDesc->lpFormat->nSamplesPerSec);
-+ ret = MMSYSERR_NOERROR;
-+ goto exit;
-+ }
-+
-+ if (TRACE_ON(wave)) {
-+ char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
-+ pa_sample_spec_snprint(t, sizeof(t), &wwo->sample_spec);
-+ TRACE("Sample spec '%s'\n", t);
-+ }
-+
-+ wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
-+ wwo->waveDesc = *lpDesc;
-+ PULSE_InitRingMessage(&wwo->msgRing);
-+
-+ wwo->stream = pa_stream_new(PULSE_context, "WaveOut", &wwo->sample_spec, NULL);
-+ /* If server doesn't support sample_spec, it will error out here (re: 24bit) */
-+ if (!wwo->stream) {
-+ ret = WAVERR_BADFORMAT;
-+ goto exit;
-+ }
-+
-+ /* Setup callbacks */
-+ pa_stream_set_write_callback (wwo->stream, WAVEOUT_StreamRequestCallback, wwo);
-+ pa_stream_set_state_callback (wwo->stream, PULSE_StreamStateCallback, wwo);
-+ pa_stream_set_underflow_callback (wwo->stream, PULSE_StreamUnderflowCallback, wwo);
-+ pa_stream_set_moved_callback (wwo->stream, PULSE_StreamMovedCallback, wwo);
-+ pa_stream_set_suspended_callback (wwo->stream, PULSE_StreamSuspendedCallback, wwo);
-+
-+ /* Setup Stream Flags */
-+#if PA_API_VERSION >= 12
-+ stream_flags = PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
-+#else
-+ stream_flags = PA_STREAM_AUTO_TIMING_UPDATE;
-+#endif
-+
-+ /* Blank (but don't send) Buffer Attributes
-+ * Note the maxlength bug on old servers */
-+ wwo->buffer_attr.prebuf = (uint32_t)-1;
-+ wwo->buffer_attr.tlength = (uint32_t)-1;
-+ wwo->buffer_attr.minreq = (uint32_t)-1;
-+ wwo->buffer_attr.maxlength =
-+ pa_context_get_server_protocol_version(PULSE_context) > 12 ?
-+ (uint32_t)-1 : 1048576; /* 2^20 */
-+
-+ /* Try and connect */
-+ TRACE("Connecting stream for playback on %s.\n", wdo->device_name);
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ pa_stream_connect_playback(wwo->stream, wdo->device_name, NULL, stream_flags, NULL, NULL);
-+
-+ /* Wait for connection */
-+ for (;;) {
-+ pa_context_state_t cstate = pa_context_get_state(PULSE_context);
-+ pa_stream_state_t sstate = pa_stream_get_state(wwo->stream);
-+
-+ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
-+ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
-+ ERR("Failed to connect stream context object: %s\n", pa_strerror(pa_context_errno(PULSE_context)));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ ret = MMSYSERR_NODRIVER;
-+ goto exit;
-+ }
-+
-+ if (sstate == PA_STREAM_READY)
-+ break;
-+
-+ pa_threaded_mainloop_wait(PULSE_ml);
-+ }
-+ TRACE("(%p)->stream connected for playback.\n", wwo);
-+
-+ /* Get the pa_timing_info structure */
-+ PULSE_WaitForOperation(pa_stream_update_timing_info(wwo->stream, PULSE_StreamSuccessCallback, wwo));
-+ wwo->timing_info = pa_stream_get_timing_info(wwo->stream);
-+ assert(wwo->timing_info);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ /* Create and start the wodPlayer() thread to manage playback */
-+ wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-+ wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)wwo, 0, &(wwo->dwThreadID));
-+ if (wwo->hThread)
-+ SetThreadPriority(wwo->hThread, THREAD_PRIORITY_TIME_CRITICAL);
-+ else {
-+ ERR("Thread creation for the wodPlayer failed!\n");
-+ ret = MMSYSERR_NOMEM;
-+ goto exit;
-+ }
-+ WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
-+ CloseHandle(wwo->hStartUpEvent);
-+ wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
-+
-+ return wodPlayer_NotifyClient (wwo, WOM_OPEN, 0L, 0L);
-+
-+exit:
-+ if (!wwo)
-+ return ret;
-+
-+ if (wwo->hStartUpEvent != INVALID_HANDLE_VALUE)
-+ CloseHandle(wwo->hStartUpEvent);
-+
-+ if (wwo->msgRing.ring_buffer_size > 0)
-+ PULSE_DestroyRingMessage(&wwo->msgRing);
-+
-+ if (wwo->stream) {
-+ if (pa_stream_get_state(wwo->stream) == PA_STREAM_READY)
-+ pa_stream_disconnect(wwo->stream);
-+ pa_stream_unref(wwo->stream);
-+ wwo->stream = NULL;
-+ }
-+ HeapFree(GetProcessHeap(), 0, wwo);
-+
-+ return ret;
-+}
-+
-+/**************************************************************************
-+ * wodClose [internal]
-+ */
-+static DWORD wodClose(WINE_WAVEINST *wwo) {
-+ DWORD ret;
-+
-+ TRACE("(%p);\n", wwo);
-+ if (!wwo) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (wwo->state != WINE_WS_FAILED) {
-+ if (wwo->lpQueuePtr && wwo->lpPlayPtr) {
-+ WARN("buffers still playing !\n");
-+ return WAVERR_STILLPLAYING;
-+ }
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ PULSE_WaitForOperation(pa_stream_drain(wwo->stream, PULSE_StreamSuccessCallback, NULL));
-+ pa_stream_disconnect(wwo->stream);
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+ if (wwo->hThread != INVALID_HANDLE_VALUE)
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);
-+
-+ PULSE_DestroyRingMessage(&wwo->msgRing);
-+ }
-+
-+ if (wwo->stream)
-+ pa_stream_unref(wwo->stream);
-+ ret = wodPlayer_NotifyClient(wwo, WOM_CLOSE, 0L, 0L);
-+
-+ HeapFree(GetProcessHeap(), 0, wwo);
-+
-+ return ret;
-+}
-+
-+/**************************************************************************
-+ * wodWrite [internal]
-+ */
-+static DWORD wodWrite(WINE_WAVEINST *wwo, LPWAVEHDR lpWaveHdr, DWORD dwSize) {
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))
-+ return WAVERR_UNPREPARED;
-+
-+ if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
-+ return WAVERR_STILLPLAYING;
-+
-+ lpWaveHdr->dwFlags &= ~WHDR_DONE;
-+ lpWaveHdr->dwFlags |= WHDR_INQUEUE;
-+ lpWaveHdr->lpNext = 0;
-+ lpWaveHdr->reserved = 0;
-+
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodPause [internal]
-+ */
-+static DWORD wodPause(WINE_WAVEINST *wwo) {
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_PAUSING, 0, TRUE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodGetPosition [internal]
-+ */
-+static DWORD wodGetPosition(WINE_WAVEINST *wwo, LPMMTIME lpTime, DWORD uSize) {
-+ DWORD64 time, temp;
-+ size_t bytes;
-+
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (lpTime == NULL) return MMSYSERR_INVALPARAM;
-+
-+ time = WAVEOUT_GetStreamTime(wwo);
-+
-+ temp = pa_bytes_to_usec(wwo->dwLastReset, &wwo->sample_spec);
-+ if (time > temp) time -= temp; else time = 0;
-+ time /= 1000; /* in milliseconds now */
-+
-+ bytes = time * pa_bytes_per_second(&wwo->sample_spec) / 1000;
-+ /* Align to frame size */
-+ bytes -= bytes % pa_frame_size(&wwo->sample_spec);
-+
-+ switch (lpTime->wType) {
-+ case TIME_SAMPLES:
-+ lpTime->u.sample = bytes / pa_frame_size(&wwo->sample_spec);
-+ TRACE("TIME_SAMPLES=%u\n", lpTime->u.sample);
-+ break;
-+ case TIME_MS:
-+ lpTime->u.ms = time;
-+ TRACE("TIME_MS=%u\n", lpTime->u.ms);
-+ break;
-+ case TIME_SMPTE:
-+ lpTime->u.smpte.fps = 30;
-+ lpTime->u.smpte.sec = time/1000;
-+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
-+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
-+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
-+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
-+ lpTime->u.smpte.frame = time / lpTime->u.smpte.fps * 1000;
-+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
-+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
-+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
-+ break;
-+ default:
-+ WARN("Format %d not supported, using TIME_BYTES !\n", lpTime->wType);
-+ lpTime->wType = TIME_BYTES;
-+ /* fall through */
-+ case TIME_BYTES:
-+ lpTime->u.cb = bytes;
-+ TRACE("TIME_BYTES=%u\n", lpTime->u.cb);
-+ break;
-+ }
-+ return MMSYSERR_NOERROR;
-+}
-+/**************************************************************************
-+ * wodBreakLoop [internal]
-+ */
-+static DWORD wodBreakLoop(WINE_WAVEINST *wwo) {
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_BREAKLOOP, 0, TRUE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodGetDevCaps [internal]
-+ */
-+static DWORD wodGetDevCaps(DWORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize) {
-+ TRACE("(%u, %p, %u);\n", wDevID, lpCaps, dwSize);
-+
-+ if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
-+
-+ if (wDevID >= PULSE_WodNumDevs) {
-+ TRACE("Asked for device %d, but only %d known!\n", wDevID, PULSE_WodNumDevs);
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ memcpy(lpCaps, &(WOutDev[wDevID].caps.out), min(dwSize, sizeof(*lpCaps)));
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodGetNumDevs [internal]
-+ * Context-sanity check here, as if we respond with 0, WINE will move on
-+ * to the next waveout driver.
-+ */
-+static DWORD wodGetNumDevs() {
-+ if (!PULSE_ml || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
-+ return 0;
-+
-+ return PULSE_WodNumDevs;
-+}
-+
-+/**************************************************************************
-+ * wodGetVolume [internal]
-+ */
-+static DWORD wodGetVolume(WINE_WAVEINST *wwo, LPDWORD lpdwVol) {
-+ float value1, value2;
-+ DWORD wleft, wright;
-+
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ TRACE("(%p, %p);\n", wwo, lpdwVol);
-+
-+ if (lpdwVol == NULL)
-+ return MMSYSERR_NOTENABLED;
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ if (wwo->stream && PULSE_context && pa_context_get_state(PULSE_context) == PA_CONTEXT_READY &&
-+ pa_stream_get_state(wwo->stream) == PA_STREAM_READY) {
-+ PULSE_WaitForOperation(pa_context_get_sink_input_info(PULSE_context, pa_stream_get_index(wwo->stream), WAVEOUT_SinkInputInfoCallback, wwo));
-+ }
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+
-+
-+ if (wwo->volume.channels == 2) {
-+ value1 = pa_sw_volume_to_dB(wwo->volume.values[0]);
-+ value2 = pa_sw_volume_to_dB(wwo->volume.values[1]);
-+ } else {
-+ value1 = pa_sw_volume_to_dB(pa_cvolume_avg(&wwo->volume));
-+ value2 = 0;
-+ }
-+
-+ if (value1 < -60)
-+ wleft = 0;
-+ else
-+
-+ if (value2 < -60)
-+ wright = 0;
-+ else
-+ wright = 0xFFFFl - ((value2 / -60)*(float)0xFFFFl);
-+
-+ if (wleft > 0xFFFFl)
-+ wleft = 0xFFFFl;
-+ if (wright > 0xFFFFl)
-+ wright = 0xFFFFl;
-+
-+ *lpdwVol = (WORD)wleft + (WORD)(wright << 16);
-+
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodSetVolume [internal]
-+ */
-+static DWORD wodSetVolume(WINE_WAVEINST *wwo, DWORD dwParam1) {
-+ double value1, value2;
-+
-+ TRACE("(%p, %08X);\n", wwo, dwParam1);
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ /* waveOut volumes are /supposed/ to be logarithmic */
-+ value1 = LOWORD(dwParam1) == 0 ? PA_DECIBEL_MININFTY : ((float)(0xFFFFl - LOWORD(dwParam1))/0xFFFFl) * -60.0;
-+ value2 = HIWORD(dwParam1) == 0 ? PA_DECIBEL_MININFTY : ((float)(0xFFFFl - HIWORD(dwParam1))/0xFFFFl) * -60.0;
-+
-+ if (wwo->sample_spec.channels == 2) {
-+ wwo->volume.channels = 2;
-+ wwo->volume.values[0] = pa_sw_volume_from_dB(value1);
-+ wwo->volume.values[1] = pa_sw_volume_from_dB(value2);
-+ } else {
-+ if (value1 != value2) FIXME("Non-stereo streams can't pan!\n");
-+ wwo->volume.channels = wwo->sample_spec.channels;
-+ pa_cvolume_set(&wwo->volume, wwo->volume.channels, pa_sw_volume_from_dB(max(value1, value2)));
-+ }
-+
-+ if (TRACE_ON(wave)) {
-+ char s[PA_CVOLUME_SNPRINT_MAX];
-+ pa_cvolume_snprint(s, PA_CVOLUME_SNPRINT_MAX, &wwo->volume);
-+ TRACE("%s\n", s);
-+ }
-+
-+ pa_threaded_mainloop_lock(PULSE_ml);
-+ if (!wwo->stream || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY ||
-+ pa_stream_get_state(wwo->stream) != PA_STREAM_READY || !pa_cvolume_valid(&wwo->volume)) {
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ return MMSYSERR_NOERROR;
-+ }
-+
-+ PULSE_WaitForOperation(pa_context_set_sink_input_volume(PULSE_context,
-+ pa_stream_get_index(wwo->stream), &wwo->volume,
-+ PULSE_ContextSuccessCallback, wwo));
-+ pa_threaded_mainloop_unlock(PULSE_ml);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodRestart [internal]
-+ */
-+static DWORD wodRestart(WINE_WAVEINST *wwo) {
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ if (wwo->state == WINE_WS_PAUSED)
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_RESTARTING, 0, TRUE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodReset [internal]
-+ */
-+static DWORD wodReset(WINE_WAVEINST *wwo) {
-+ if (!wwo || wwo->state == WINE_WS_FAILED) {
-+ WARN("Stream instance invalid.\n");
-+ return MMSYSERR_INVALHANDLE;
-+ }
-+
-+ PULSE_AddRingMessage(&wwo->msgRing, WINE_WM_RESETTING, 0, TRUE);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodDevInterfaceSize [internal]
-+ */
-+static DWORD wodDevInterfaceSize(UINT wDevID, LPDWORD dwParam1) {
-+
-+ *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1, NULL, 0) * sizeof(WCHAR);
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodDevInterface [internal]
-+ */
-+static DWORD wodDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2) {
-+ if (dwParam2 >= MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
-+ NULL, 0 ) * sizeof(WCHAR))
-+ {
-+ MultiByteToWideChar(CP_ACP, 0, WOutDev[wDevID].interface_name, -1,
-+ dwParam1, dwParam2 / sizeof(WCHAR));
-+ return MMSYSERR_NOERROR;
-+ }
-+ return MMSYSERR_INVALPARAM;
-+}
-+
-+DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc) {
-+ TRACE("(%u, %p)\n", wDevID, desc);
-+ *desc = WOutDev[wDevID].ds_desc;
-+ return MMSYSERR_NOERROR;
-+}
-+
-+/**************************************************************************
-+ * wodMessage (WINEPULSE.@)
-+ */
-+DWORD WINAPI PULSE_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) {
-+
-+ switch (wMsg) {
-+
-+ case DRVM_INIT:
-+ case DRVM_EXIT:
-+ case DRVM_ENABLE:
-+ case DRVM_DISABLE:
-+ return 0;
-+
-+ /* WaveOut Playback related functions */
-+ case WODM_OPEN: return wodOpen (wDevID, (LPDWORD)dwUser, (LPWAVEOPENDESC)dwParam1, dwParam2);
-+ case WODM_CLOSE: return wodClose ((WINE_WAVEINST*)dwUser);
-+ case WODM_WRITE: return wodWrite ((WINE_WAVEINST*)dwUser, (LPWAVEHDR)dwParam1, dwParam2);
-+ case WODM_PAUSE: return wodPause ((WINE_WAVEINST*)dwUser);
-+ case WODM_GETPOS: return wodGetPosition ((WINE_WAVEINST*)dwUser, (LPMMTIME)dwParam1, dwParam2);
-+ case WODM_BREAKLOOP: return wodBreakLoop ((WINE_WAVEINST*)dwUser);
-+ case WODM_RESTART: return wodRestart ((WINE_WAVEINST*)dwUser);
-+ case WODM_RESET: return wodReset ((WINE_WAVEINST*)dwUser);
-+
-+ case WODM_GETVOLUME: return wodGetVolume ((WINE_WAVEINST*)dwUser, (LPDWORD)dwParam1);
-+ case WODM_SETVOLUME: return wodSetVolume ((WINE_WAVEINST*)dwUser, dwParam1);
-+
-+ case WODM_PREPARE:
-+ case WODM_UNPREPARE:
-+
-+ case WODM_GETPITCH:
-+ case WODM_SETPITCH:
-+
-+ case WODM_GETPLAYBACKRATE:
-+ case WODM_SETPLAYBACKRATE:
-+ return MMSYSERR_NOTSUPPORTED;
-+
-+ /* Device enumeration, directsound and capabilities */
-+ case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (LPWAVEOUTCAPSW)dwParam1, dwParam2);
-+ case WODM_GETNUMDEVS: return wodGetNumDevs ();
-+ case DRV_QUERYDEVICEINTERFACESIZE: return wodDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
-+ case DRV_QUERYDEVICEINTERFACE: return wodDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
-+// case DRV_QUERYDSOUNDIFACE: return wodDsCreate (wDevID, (PIDSDRIVER*)dwParam1);
-+ case DRV_QUERYDSOUNDIFACE: return MMSYSERR_NOTSUPPORTED;
-+ case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
-+
-+ default:
-+ FIXME("unknown message %d!\n", wMsg);
-+ }
-+ return MMSYSERR_NOTSUPPORTED;
-+}
-+
-+#else /* !HAVE_PULSEAUDIO */
-+
-+/**************************************************************************
-+ * wodMessage (WINEPULSE.@)
-+ */
-+DWORD WINAPI PULSE_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
-+ DWORD dwParam1, DWORD dwParam2) {
-+ FIXME("(%u, %04X, %08X, %08X, %08X):stub\n", wDevID, wMsg, dwUser,
-+ dwParam1, dwParam2);
-+ return MMSYSERR_NOTENABLED;
-+}
-+
-+#endif /* HAVE_PULSEAUDIO */
-diff --git a/dlls/winepulse.drv/winepulse.drv.spec b/dlls/winepulse.drv/winepulse.drv.spec
-new file mode 100644
-index 0000000..1b49460
---- /dev/null
-+++ b/dlls/winepulse.drv/winepulse.drv.spec
-@@ -0,0 +1,3 @@
-+@ stdcall -private DriverProc(long long long long long long) PULSE_DriverProc
-+@ stdcall -private wodMessage(long long long long long long) PULSE_wodMessage
-+@ stdcall -private widMessage(long long long long long long) PULSE_widMessage
-diff --git a/dlls/winepulse.drv/winepulse.h b/dlls/winepulse.drv/winepulse.h
-new file mode 100644
-index 0000000..4dae23f
---- /dev/null
-+++ b/dlls/winepulse.drv/winepulse.h
-@@ -0,0 +1,195 @@
-+/* Definitions for PulseAudio Wine Driver
-+ *
-+ * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
-+ *
-+ * This library 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.
-+ *
-+ * This library 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 this library; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-+ */
-+
-+#ifndef __WINE_CONFIG_H
-+# error You must include config.h to use this header
-+#endif
-+
-+#if defined(HAVE_PULSEAUDIO) && !defined(__WINEPULSE_H)
-+#define __WINEPULSE_H
-+
-+#include "mmreg.h"
-+#include "dsound.h"
-+#include "dsdriver.h"
-+
-+#include "ks.h"
-+#include "ksmedia.h"
-+#include "ksguid.h"
-+
-+#include <pulse/pulseaudio.h>
-+
-+/* state diagram for waveOut writing:
-+ *
-+ * +---------+-------------+---------------+---------------------------------+
-+ * | state | function | event | new state |
-+ * +---------+-------------+---------------+---------------------------------+
-+ * | | open() | | STOPPED |
-+ * | PAUSED | write() | | PAUSED |
-+ * | STOPPED | write() | <thrd create> | PLAYING |
-+ * | PLAYING | write() | HEADER | PLAYING |
-+ * | (other) | write() | <error> | |
-+ * | (any) | pause() | PAUSING | PAUSED |
-+ * | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
-+ * | (any) | reset() | RESETTING | STOPPED |
-+ * | (any) | close() | CLOSING | CLOSED |
-+ * +---------+-------------+---------------+---------------------------------+
-+ */
-+
-+/* states of the playing device */
-+#define WINE_WS_PLAYING 1
-+#define WINE_WS_PAUSED 2
-+#define WINE_WS_STOPPED 3
-+#define WINE_WS_CLOSED 4
-+#define WINE_WS_FAILED 5
-+
-+#define PULSE_ALL_FORMATS \
-+ WAVE_FORMAT_1M08 | /* Mono 11025Hz 8-bit */\
-+ WAVE_FORMAT_1M16 | /* Mono 11025Hz 16-bit */\
-+ WAVE_FORMAT_1S08 | /* Stereo 11025Hz 8-bit */\
-+ WAVE_FORMAT_1S16 | /* Stereo 11025Hz 16-bit */\
-+ WAVE_FORMAT_2M08 | /* Mono 22050Hz 8-bit */\
-+ WAVE_FORMAT_2M16 | /* Mono 22050Hz 16-bit */\
-+ WAVE_FORMAT_2S08 | /* Stereo 22050Hz 8-bit */\
-+ WAVE_FORMAT_2S16 | /* Stereo 22050Hz 16-bit */\
-+ WAVE_FORMAT_4M08 | /* Mono 44100Hz 8-bit */\
-+ WAVE_FORMAT_4M16 | /* Mono 44100Hz 16-bit */\
-+ WAVE_FORMAT_4S08 | /* Stereo 44100Hz 8-bit */\
-+ WAVE_FORMAT_4S16 | /* Stereo 44100Hz 16-bit */\
-+ WAVE_FORMAT_48M08 | /* Mono 48000Hz 8-bit */\
-+ WAVE_FORMAT_48S08 | /* Stereo 48000Hz 8-bit */\
-+ WAVE_FORMAT_48M16 | /* Mono 48000Hz 16-bit */\
-+ WAVE_FORMAT_48S16 | /* Stereo 48000Hz 16-bit */\
-+ WAVE_FORMAT_96M08 | /* Mono 96000Hz 8-bit */\
-+ WAVE_FORMAT_96S08 | /* Stereo 96000Hz 8-bit */\
-+ WAVE_FORMAT_96M16 | /* Mono 96000Hz 16-bit */\
-+ WAVE_FORMAT_96S16 /* Stereo 96000Hz 16-bit */
-+
-+/* events to be sent to device */
-+enum win_wm_message {
-+ WINE_WM_PAUSING = WM_USER + 1, WINE_WM_RESTARTING, WINE_WM_RESETTING, WINE_WM_HEADER,
-+ WINE_WM_BREAKLOOP, WINE_WM_CLOSING, WINE_WM_STARTING, WINE_WM_STOPPING, WINE_WM_XRUN, WINE_WM_FEED
-+};
-+
-+typedef struct {
-+ enum win_wm_message msg; /* message identifier */
-+ DWORD param; /* parameter for this message */
-+ HANDLE hEvent; /* if message is synchronous, handle of event for synchro */
-+} PULSE_MSG;
-+
-+/* implement an in-process message ring for better performance
-+ * (compared to passing thru the server)
-+ * this ring will be used by the input (resp output) record (resp playback) routine
-+ */
-+typedef struct {
-+ PULSE_MSG * messages;
-+ int ring_buffer_size;
-+ int msg_tosave;
-+ int msg_toget;
-+/* Either pipe or event is used, but that is defined in pulse.c,
-+ * since this is a global header we define both here */
-+ int msg_pipe[2];
-+ HANDLE msg_event;
-+ CRITICAL_SECTION msg_crst;
-+} PULSE_MSG_RING;
-+
-+typedef struct WINE_WAVEDEV WINE_WAVEDEV;
-+typedef struct WINE_WAVEINST WINE_WAVEINST;
-+
-+/* Per-playback/record device */
-+struct WINE_WAVEDEV {
-+ char interface_name[MAXPNAMELEN * 2];
-+ char *device_name;
-+ pa_cvolume volume;
-+
-+ union {
-+ WAVEOUTCAPSW out;
-+ WAVEINCAPSW in;
-+ } caps;
-+
-+ /* DirectSound stuff */
-+ DSDRIVERDESC ds_desc;
-+ DSDRIVERCAPS ds_caps;
-+};
-+
-+/* Per-playback/record instance */
-+struct WINE_WAVEINST {
-+ volatile INT state; /* one of the WINE_WS_ manifest constants */
-+ WAVEOPENDESC waveDesc;
-+ WORD wFlags;
-+
-+ /* PulseAudio specific data */
-+ pa_stream *stream; /* The PulseAudio stream */
-+ const pa_timing_info *timing_info; /* The timing info structure for the stream */
-+ pa_sample_spec sample_spec; /* Sample spec of this stream / device */
-+ pa_cvolume volume; /* Software volume of the stream */
-+ pa_buffer_attr buffer_attr; /* Buffer attribute, may not be used */
-+
-+ /* waveIn / waveOut wavaHdr */
-+ LPWAVEHDR lpQueuePtr; /* Start of queued WAVEHDRs (waiting to be notified) */
-+ LPWAVEHDR lpPlayPtr; /* Start of not yet fully written buffers */
-+ DWORD dwPartialOffset; /* Offset of not yet written bytes in lpPlayPtr */
-+ LPWAVEHDR lpLoopPtr; /* Pointer of first buffer in loop, if any */
-+ DWORD dwLoops; /* Private copy of loop counter */
-+ DWORD dwLastReset; /* When the last reset occured, as pa stream time doesn't reset */
-+
-+ /* waveIn specific */
-+ const void *buffer; /* Pointer to the latest data fragment for recording streams */
-+ DWORD buffer_length; /* How large the latest data fragment is */
-+ DWORD buffer_read_offset; /* How far into latest data fragment we last read */
-+
-+ /* Thread communication and synchronization stuff */
-+ HANDLE hStartUpEvent;
-+ HANDLE hThread;
-+ DWORD dwThreadID;
-+ PULSE_MSG_RING msgRing;
-+};
-+
-+/* We establish one context per instance, so make it global to the lib */
-+pa_context *PULSE_context; /* Connection Context */
-+pa_threaded_mainloop *PULSE_ml; /* PA Runtime information */
-+
-+/* WaveIn / WaveOut devices */
-+WINE_WAVEDEV *WOutDev;
-+WINE_WAVEDEV *WInDev;
-+DWORD PULSE_WodNumDevs;
-+DWORD PULSE_WidNumDevs;
-+
-+/* pulse.c: PulseAudio Async Callbacks */
-+void PULSE_StreamSuccessCallback(pa_stream *s, int success, void *userdata);
-+void PULSE_StreamStateCallback(pa_stream *s, void *userdata);
-+void PULSE_StreamUnderflowCallback(pa_stream *s, void *userdata);
-+void PULSE_StreamSuspendedCallback(pa_stream *s, void *userdata);
-+void PULSE_StreamMovedCallback(pa_stream *s, void *userdata);
-+void PULSE_ContextSuccessCallback(pa_context *c, int success, void *userdata);
-+
-+/* pulse.c: General Functions */
-+void PULSE_WaitForOperation(pa_operation *o);
-+BOOL PULSE_SetupFormat(LPWAVEFORMATEX wf, pa_sample_spec *ss);
-+
-+/* pulse.c: Message Ring */
-+int PULSE_InitRingMessage(PULSE_MSG_RING* omr);
-+int PULSE_DestroyRingMessage(PULSE_MSG_RING* omr);
-+void PULSE_ResetRingMessage(PULSE_MSG_RING* omr);
-+void PULSE_WaitRingMessage(PULSE_MSG_RING* omr, DWORD sleep);
-+int PULSE_AddRingMessage(PULSE_MSG_RING* omr, enum win_wm_message msg, DWORD param, BOOL wait);
-+int PULSE_RetrieveRingMessage(PULSE_MSG_RING* omr, enum win_wm_message *msg, DWORD *param, HANDLE *hEvent);
-+
-+/* pulse.c: Tracing */
-+const char * PULSE_getCmdString(enum win_wm_message msg);
-+#endif
diff --git a/app-emulation/wine/files/winepulse-winecfg.patch b/app-emulation/wine/files/winepulse-winecfg.patch
deleted file mode 100644
index f8770eb..0000000
--- a/app-emulation/wine/files/winepulse-winecfg.patch
+++ /dev/null
@@ -1,289 +0,0 @@
-diff --git a/programs/winecfg/Bg.rc b/programs/winecfg/Bg.rc
-index 8861657..cf91012 100644
---- a/programs/winecfg/Bg.rc
-+++ b/programs/winecfg/Bg.rc
-@@ -274,6 +274,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Basic"
- IDS_ACCEL_EMULATION "Emulation"
-+ IDS_DRIVER_PULSE "PulseAudio Driver"
- IDS_DRIVER_ALSA "ALSA Driver"
- IDS_DRIVER_ESOUND "EsounD Driver"
- IDS_DRIVER_OSS "OSS Driver"
-diff --git a/programs/winecfg/Cs.rc b/programs/winecfg/Cs.rc
-index 07f035f..8897237 100644
---- a/programs/winecfg/Cs.rc
-+++ b/programs/winecfg/Cs.rc
-@@ -273,6 +273,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standardní"
- IDS_ACCEL_BASIC "Základní"
- IDS_ACCEL_EMULATION "Emulace"
-+ IDS_DRIVER_PULSE "Ovladaè PulseAudio"
- IDS_DRIVER_ALSA "Ovladaè ALSA"
- IDS_DRIVER_ESOUND "Ovladaè EsounD"
- IDS_DRIVER_OSS "Ovladaè OSS"
-diff --git a/programs/winecfg/Da.rc b/programs/winecfg/Da.rc
-index 1d655ad..a1c9653 100644
---- a/programs/winecfg/Da.rc
-+++ b/programs/winecfg/Da.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Grundlæggende"
- IDS_ACCEL_EMULATION "Emuléring"
-+ IDS_DRIVER_PULSE "PulseAudio-driver"
- IDS_DRIVER_ALSA "ALSA-driver"
- IDS_DRIVER_ESOUND "EsounD-driver"
- IDS_DRIVER_OSS "OSS-driver"
-diff --git a/programs/winecfg/De.rc b/programs/winecfg/De.rc
-index 9ed3d63..614247b 100644
---- a/programs/winecfg/De.rc
-+++ b/programs/winecfg/De.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Einfach"
- IDS_ACCEL_EMULATION "Emulation"
-+ IDS_DRIVER_PULSE "PulseAudio-Treiber"
- IDS_DRIVER_ALSA "ALSA-Treiber"
- IDS_DRIVER_ESOUND "EsounD-Treiber"
- IDS_DRIVER_OSS "OSS-Treiber"
-diff --git a/programs/winecfg/En.rc b/programs/winecfg/En.rc
-index 5743ba3..b165a81 100644
---- a/programs/winecfg/En.rc
-+++ b/programs/winecfg/En.rc
-@@ -270,6 +270,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Basic"
- IDS_ACCEL_EMULATION "Emulation"
-+ IDS_DRIVER_PULSE "PulseAudio Driver"
- IDS_DRIVER_ALSA "ALSA Driver"
- IDS_DRIVER_ESOUND "EsounD Driver"
- IDS_DRIVER_OSS "OSS Driver"
-diff --git a/programs/winecfg/Es.rc b/programs/winecfg/Es.rc
-index 440ea71..dd1b764 100644
---- a/programs/winecfg/Es.rc
-+++ b/programs/winecfg/Es.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Estándar"
- IDS_ACCEL_BASIC "Básica"
- IDS_ACCEL_EMULATION "Emulación"
-+ IDS_DRIVER_PULSE "Manejador PulseAudio"
- IDS_DRIVER_ALSA "Manejador ALSA"
- IDS_DRIVER_ESOUND "Manejador EsounD"
- IDS_DRIVER_OSS "Manejador OSS"
-diff --git a/programs/winecfg/Fi.rc b/programs/winecfg/Fi.rc
-index 1d761f8..e1b1583 100644
---- a/programs/winecfg/Fi.rc
-+++ b/programs/winecfg/Fi.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Basic"
- IDS_ACCEL_EMULATION "Emulation"
-+ IDS_DRIVER_PULSE "PulseAudio Driver"
- IDS_DRIVER_ALSA "ALSA Driver"
- IDS_DRIVER_ESOUND "EsounD Driver"
- IDS_DRIVER_OSS "OSS Driver"
-diff --git a/programs/winecfg/Fr.rc b/programs/winecfg/Fr.rc
-index 818c50f..97a1f44 100644
---- a/programs/winecfg/Fr.rc
-+++ b/programs/winecfg/Fr.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Basique"
- IDS_ACCEL_EMULATION "Émulation"
-+ IDS_DRIVER_PULSE "Pilote PulseAudio"
- IDS_DRIVER_ALSA "Pilote ALSA"
- IDS_DRIVER_ESOUND "Pilote EsounD"
- IDS_DRIVER_OSS "Pilote OSS"
-diff --git a/programs/winecfg/Hu.rc b/programs/winecfg/Hu.rc
-index 5afbf91..4131f5f 100644
---- a/programs/winecfg/Hu.rc
-+++ b/programs/winecfg/Hu.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Basic"
- IDS_ACCEL_EMULATION "Emulation"
-+ IDS_DRIVER_PULSE "PulseAudio Driver"
- IDS_DRIVER_ALSA "ALSA Driver"
- IDS_DRIVER_ESOUND "EsounD Driver"
- IDS_DRIVER_OSS "OSS Driver"
-diff --git a/programs/winecfg/Ja.rc b/programs/winecfg/Ja.rc
-index 8eaa603..543ed2c 100644
---- a/programs/winecfg/Ja.rc
-+++ b/programs/winecfg/Ja.rc
-@@ -273,6 +273,7 @@ BEGIN
- IDS_ACCEL_STANDARD "標準"
- IDS_ACCEL_BASIC "基本"
- IDS_ACCEL_EMULATION "エミュレーション"
-+ IDS_DRIVER_PULSE "PulseAudio Driver"
- IDS_DRIVER_ALSA "ALSA Driver"
- IDS_DRIVER_ESOUND "EsounD Driver"
- IDS_DRIVER_OSS "OSS Driver"
-diff --git a/programs/winecfg/Ko.rc b/programs/winecfg/Ko.rc
-index ca94b5b..a79cc03 100644
---- a/programs/winecfg/Ko.rc
-+++ b/programs/winecfg/Ko.rc
-@@ -272,6 +272,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Ç¥ÁØ"
- IDS_ACCEL_BASIC "񃧯"
- IDS_ACCEL_EMULATION "¾Ö¹Ä·¹À̼Ç"
-+ IDS_DRIVER_PULSE "PulseAudio µå¶óÀ̹ö"
- IDS_DRIVER_ALSA "ALSA µå¶óÀ̹ö"
- IDS_DRIVER_ESOUND "EsounD µå¶óÀ̹ö"
- IDS_DRIVER_OSS "OSS µå¶óÀ̹ö"
-diff --git a/programs/winecfg/Nl.rc b/programs/winecfg/Nl.rc
-index fb91290..b23e919 100644
---- a/programs/winecfg/Nl.rc
-+++ b/programs/winecfg/Nl.rc
-@@ -270,6 +270,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standaard"
- IDS_ACCEL_BASIC "Eenvoudig"
- IDS_ACCEL_EMULATION "Emulatie"
-+ IDS_DRIVER_PULSE "PulseAudio Stuurprogramma"
- IDS_DRIVER_ALSA "ALSA Stuurprogramma"
- IDS_DRIVER_ESOUND "EsounD Stuurprogramma"
- IDS_DRIVER_OSS "OSS Stuurprogramma"
-diff --git a/programs/winecfg/No.rc b/programs/winecfg/No.rc
-index aaa64c3..9dd3572 100644
---- a/programs/winecfg/No.rc
-+++ b/programs/winecfg/No.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Grunnleggende"
- IDS_ACCEL_EMULATION "Emulering"
-+ IDS_DRIVER_PULSE "PulseAudio-driver"
- IDS_DRIVER_ALSA "ALSA-driver"
- IDS_DRIVER_ESOUND "EsounD-driver"
- IDS_DRIVER_OSS "OSS-driver"
-diff --git a/programs/winecfg/Pl.rc b/programs/winecfg/Pl.rc
-index c426443..e3bf093 100644
---- a/programs/winecfg/Pl.rc
-+++ b/programs/winecfg/Pl.rc
-@@ -271,6 +271,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standardowe"
- IDS_ACCEL_BASIC "Podstawowe"
- IDS_ACCEL_EMULATION "Emulacja"
-+ IDS_DRIVER_PULSE "Sterownik PulseAudio"
- IDS_DRIVER_ALSA "Sterownik ALSA"
- IDS_DRIVER_ESOUND "Sterownik EsounD"
- IDS_DRIVER_OSS "Sterownik OSS"
-diff --git a/programs/winecfg/Pt.rc b/programs/winecfg/Pt.rc
-index 830cabf..0ed1dbd 100644
---- a/programs/winecfg/Pt.rc
-+++ b/programs/winecfg/Pt.rc
-@@ -465,6 +465,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Padrão"
- IDS_ACCEL_BASIC "Básico"
- IDS_ACCEL_EMULATION "Emulação"
-+ IDS_DRIVER_PULSE "Controlador PulseAudio"
- IDS_DRIVER_ALSA "Controlador ALSA"
- IDS_DRIVER_ESOUND "Controlador EsounD"
- IDS_DRIVER_OSS "Controlador OSS"
-diff --git a/programs/winecfg/Ro.rc b/programs/winecfg/Ro.rc
-index a4b0cad..c065d36 100644
---- a/programs/winecfg/Ro.rc
-+++ b/programs/winecfg/Ro.rc
-@@ -270,6 +270,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "De basă"
- IDS_ACCEL_EMULATION "Emulare"
-+ IDS_DRIVER_PULSE "Driver PulseAudio"
- IDS_DRIVER_ALSA "Driver ALSA"
- IDS_DRIVER_ESOUND "Driver Esound"
- IDS_DRIVER_OSS "Driver OSS"
-diff --git a/programs/winecfg/Ru.rc b/programs/winecfg/Ru.rc
-index 782e1fd..f516399 100644
---- a/programs/winecfg/Ru.rc
-+++ b/programs/winecfg/Ru.rc
-@@ -272,6 +272,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Ñòàíäàðòíîå"
- IDS_ACCEL_BASIC "Ìèíèìàëüíîå"
- IDS_ACCEL_EMULATION "Ýìóëÿöèÿ"
-+ IDS_DRIVER_PULSE "PulseAudio äðàéâåð"
- IDS_DRIVER_ALSA "ALSA äðàéâåð"
- IDS_DRIVER_ESOUND "EsounD äðàéâåð"
- IDS_DRIVER_OSS "OSS äðàéâåð"
-diff --git a/programs/winecfg/Si.rc b/programs/winecfg/Si.rc
-index 0bd04ef..c8bd35e 100644
---- a/programs/winecfg/Si.rc
-+++ b/programs/winecfg/Si.rc
-@@ -270,6 +270,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standardno"
- IDS_ACCEL_BASIC "Osnovno"
- IDS_ACCEL_EMULATION "Emulacija"
-+ IDS_DRIVER_PULSE "PulseAudio gonilnik"
- IDS_DRIVER_ALSA "ALSA gonilnik"
- IDS_DRIVER_ESOUND "EsounD gonilnik"
- IDS_DRIVER_OSS "OSS gonilnik"
-diff --git a/programs/winecfg/Sv.rc b/programs/winecfg/Sv.rc
-index 49bb236..7efe2c0 100644
---- a/programs/winecfg/Sv.rc
-+++ b/programs/winecfg/Sv.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standard"
- IDS_ACCEL_BASIC "Grundläggande"
- IDS_ACCEL_EMULATION "Emulering"
-+ IDS_DRIVER_PULSE "PulseAudio-drivrutin"
- IDS_DRIVER_ALSA "ALSA-drivrutin"
- IDS_DRIVER_ESOUND "EsounD-drivrutin"
- IDS_DRIVER_OSS "OSS-drivrutin"
-diff --git a/programs/winecfg/Tr.rc b/programs/winecfg/Tr.rc
-index 4157f86..1be23c5 100644
---- a/programs/winecfg/Tr.rc
-+++ b/programs/winecfg/Tr.rc
-@@ -268,6 +268,7 @@ BEGIN
- IDS_ACCEL_STANDARD "Standart"
- IDS_ACCEL_BASIC "Temel"
- IDS_ACCEL_EMULATION "Taklit"
-+ IDS_DRIVER_PULSE "PulseAudio Sürücüsü"
- IDS_DRIVER_ALSA "ALSA Sürücüsü"
- IDS_DRIVER_ESOUND "EsounD Sürücüsü"
- IDS_DRIVER_OSS "OSS Sürücüsü"
-diff --git a/programs/winecfg/Zh.rc b/programs/winecfg/Zh.rc
-index 4c18e99..029a26d 100644
---- a/programs/winecfg/Zh.rc
-+++ b/programs/winecfg/Zh.rc
-@@ -271,6 +271,7 @@ BEGIN
- IDS_ACCEL_STANDARD "标准"
- IDS_ACCEL_BASIC "基本"
- IDS_ACCEL_EMULATION "软件模拟"
-+ IDS_DRIVER_PULSE "PulseAudio 驱动"
- IDS_DRIVER_ALSA "ALSA 驱动"
- IDS_DRIVER_ESOUND "EsounD 驱动"
- IDS_DRIVER_OSS "OSS 驱动"
-diff --git a/programs/winecfg/audio.c b/programs/winecfg/audio.c
-index 8e966a5..9c2cde3 100644
---- a/programs/winecfg/audio.c
-+++ b/programs/winecfg/audio.c
-@@ -88,6 +88,7 @@ typedef struct
- } AUDIO_DRIVER;
-
- static const AUDIO_DRIVER sAudioDrivers[] = {
-+ {IDS_DRIVER_PULSE, "pulse"},
- {IDS_DRIVER_ALSA, "alsa"},
- {IDS_DRIVER_OSS, "oss"},
- {IDS_DRIVER_COREAUDIO, "coreaudio"},
-diff --git a/programs/winecfg/libraries.c b/programs/winecfg/libraries.c
-index 6abe04d..2fa6a95 100644
---- a/programs/winecfg/libraries.c
-+++ b/programs/winecfg/libraries.c
-@@ -67,6 +67,7 @@ static const char * const builtin_only[] =
- "user32",
- "vdmdbg",
- "w32skrnl",
-+ "winepulse.drv",
- "winealsa.drv",
- "wineaudioio.drv",
- "wined3d",
-diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
-index a18fe76..1c4a1e7 100644
---- a/programs/winecfg/resource.h
-+++ b/programs/winecfg/resource.h
-@@ -182,7 +182,7 @@
- #define IDS_ACCEL_BASIC 8302
- #define IDS_ACCEL_EMULATION 8303
- #define IDS_DRIVER_ALSA 8304
--
-+#define IDS_DRIVER_PULSE 8305
- #define IDS_DRIVER_ESOUND 8306
- #define IDS_DRIVER_OSS 8307
- #define IDS_DRIVER_JACK 8308