- version upgrade

f38
Andreas Bierfert 16 years ago
parent 656e3cbce1
commit 0ff522185f

@ -1 +1 @@
wine-1.1.15-fe.tar.bz2 wine-1.1.18-fe.tar.bz2

@ -1 +1 @@
cfeb6cfd7404c2fed2c9f2623976ea7e wine-1.1.15-fe.tar.bz2 1933049a7cc725bcb488c6669fa5ca9e wine-1.1.18-fe.tar.bz2

@ -1,6 +1,6 @@
Name: wine Name: wine
Version: 1.1.15 Version: 1.1.18
Release: 3%{?dist} Release: 1%{?dist}
Summary: A Windows 16/32/64 bit emulator Summary: A Windows 16/32/64 bit emulator
Group: Applications/Emulators Group: Applications/Emulators
@ -43,7 +43,7 @@ Source300: wine-mime-msi.desktop
# see http://bugs.winehq.org/show_bug.cgi?id=10495 # see http://bugs.winehq.org/show_bug.cgi?id=10495
# and http://art.ified.ca/?page_id=40 # and http://art.ified.ca/?page_id=40
Patch400: http://art.ified.ca/downloads/winepulse-0.17-configure.ac.patch Patch400: http://art.ified.ca/downloads/winepulse-0.17-configure.ac.patch
Patch401: http://art.ified.ca/downloads/winepulse-0.20.patch Patch401: http://art.ified.ca/downloads/winepulse-0.24.patch
Patch402: http://art.ified.ca/downloads/adding-pulseaudio-to-winecfg.patch Patch402: http://art.ified.ca/downloads/adding-pulseaudio-to-winecfg.patch
Source402: README-FEDORA-PULSEAUDIO Source402: README-FEDORA-PULSEAUDIO
@ -402,15 +402,12 @@ update-desktop-database &>/dev/null || :
%{_bindir}/regsvr32 %{_bindir}/regsvr32
%{_bindir}/wine %{_bindir}/wine
%{_bindir}/wineboot %{_bindir}/wineboot
%{_bindir}/winebrowser
%{_bindir}/wineconsole %{_bindir}/wineconsole
%{_bindir}/wineprefixcreate %{_bindir}/wineprefixcreate
%{_mandir}/man1/wineprefixcreate.1* %{_mandir}/man1/wineprefixcreate.1*
%{_bindir}/winecfg %{_bindir}/winecfg
%{_bindir}/uninstaller
%{_libdir}/wine/cacls.exe.so %{_libdir}/wine/cacls.exe.so
%{_libdir}/wine/expand.exe.so %{_libdir}/wine/expand.exe.so
%{_libdir}/wine/winhelp.exe16
%{_libdir}/wine/winhlp32.exe.so %{_libdir}/wine/winhlp32.exe.so
%{_libdir}/wine/msiexec.exe.so %{_libdir}/wine/msiexec.exe.so
%{_libdir}/wine/net.exe.so %{_libdir}/wine/net.exe.so
@ -438,11 +435,7 @@ update-desktop-database &>/dev/null || :
%lang(fr) %{_mandir}/fr.UTF-8/man1/* %lang(fr) %{_mandir}/fr.UTF-8/man1/*
%{_datadir}/wine/generic.ppd %{_datadir}/wine/generic.ppd
%{_datadir}/wine/wine.inf %{_datadir}/wine/wine.inf
%{_bindir}/wine-kthread
%{_bindir}/wine-preloader %{_bindir}/wine-preloader
%{_bindir}/wine-pthread
# < 0.9.60
#%{_bindir}/winelauncher
%{_bindir}/wineserver %{_bindir}/wineserver
%{_libdir}/libwine.so.1* %{_libdir}/libwine.so.1*
%dir %{_libdir}/wine %dir %{_libdir}/wine
@ -458,7 +451,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/authz.dll.so %{_libdir}/wine/authz.dll.so
%{_libdir}/wine/avicap32.dll.so %{_libdir}/wine/avicap32.dll.so
%{_libdir}/wine/avifil32.dll.so %{_libdir}/wine/avifil32.dll.so
%{_libdir}/wine/avifile.dll16
%{_libdir}/wine/browseui.dll.so %{_libdir}/wine/browseui.dll.so
%{_libdir}/wine/cabinet.dll.so %{_libdir}/wine/cabinet.dll.so
%{_libdir}/wine/cards.dll.so %{_libdir}/wine/cards.dll.so
@ -468,9 +460,7 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/comcat.dll.so %{_libdir}/wine/comcat.dll.so
%{_libdir}/wine/comctl32.dll.so %{_libdir}/wine/comctl32.dll.so
%{_libdir}/wine/comdlg32.dll.so %{_libdir}/wine/comdlg32.dll.so
%{_libdir}/wine/comm.drv16
%{_libdir}/wine/commdlg.dll16 %{_libdir}/wine/commdlg.dll16
%{_libdir}/wine/compobj.dll16
%{_libdir}/wine/compstui.dll.so %{_libdir}/wine/compstui.dll.so
%{_libdir}/wine/credui.dll.so %{_libdir}/wine/credui.dll.so
%{_libdir}/wine/crtdll.dll.so %{_libdir}/wine/crtdll.dll.so
@ -480,9 +470,7 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/cryptnet.dll.so %{_libdir}/wine/cryptnet.dll.so
%{_libdir}/wine/cryptui.dll.so %{_libdir}/wine/cryptui.dll.so
%{_libdir}/wine/ctapi32.dll.so %{_libdir}/wine/ctapi32.dll.so
%{_libdir}/wine/ctl3d.dll16
%{_libdir}/wine/ctl3d32.dll.so %{_libdir}/wine/ctl3d32.dll.so
%{_libdir}/wine/ctl3dv2.dll16
%{_libdir}/wine/d3d10.dll.so %{_libdir}/wine/d3d10.dll.so
%{_libdir}/wine/d3d10core.dll.so %{_libdir}/wine/d3d10core.dll.so
%{_libdir}/wine/d3dim.dll.so %{_libdir}/wine/d3dim.dll.so
@ -497,8 +485,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/devenum.dll.so %{_libdir}/wine/devenum.dll.so
%{_libdir}/wine/dinput.dll.so %{_libdir}/wine/dinput.dll.so
%{_libdir}/wine/dinput8.dll.so %{_libdir}/wine/dinput8.dll.so
%{_libdir}/wine/dispdib.dll16
%{_libdir}/wine/display.drv16
%{_libdir}/wine/dmband.dll.so %{_libdir}/wine/dmband.dll.so
%{_libdir}/wine/dmcompos.dll.so %{_libdir}/wine/dmcompos.dll.so
%{_libdir}/wine/dmime.dll.so %{_libdir}/wine/dmime.dll.so
@ -543,7 +529,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/ifsmgr.vxd.so %{_libdir}/wine/ifsmgr.vxd.so
%{_libdir}/wine/imaadp32.acm.so %{_libdir}/wine/imaadp32.acm.so
%{_libdir}/wine/imagehlp.dll.so %{_libdir}/wine/imagehlp.dll.so
%{_libdir}/wine/imm.dll16
%{_libdir}/wine/imm32.dll.so %{_libdir}/wine/imm32.dll.so
%{_libdir}/wine/inetcomm.dll.so %{_libdir}/wine/inetcomm.dll.so
%{_libdir}/wine/inetmib1.dll.so %{_libdir}/wine/inetmib1.dll.so
@ -556,14 +541,12 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/itss.dll.so %{_libdir}/wine/itss.dll.so
%{_libdir}/wine/jscript.dll.so %{_libdir}/wine/jscript.dll.so
%{_libdir}/wine/kernel32.dll.so %{_libdir}/wine/kernel32.dll.so
%{_libdir}/wine/keyboard.drv16
%{_libdir}/wine/krnl386.exe16 %{_libdir}/wine/krnl386.exe16
%{_libdir}/wine/loadperf.dll.so %{_libdir}/wine/loadperf.dll.so
%{_libdir}/wine/localspl.dll.so %{_libdir}/wine/localspl.dll.so
%{_libdir}/wine/localui.dll.so %{_libdir}/wine/localui.dll.so
%{_libdir}/wine/lodctr.exe.so %{_libdir}/wine/lodctr.exe.so
%{_libdir}/wine/lz32.dll.so %{_libdir}/wine/lz32.dll.so
%{_libdir}/wine/lzexpand.dll16
%{_libdir}/wine/mapi32.dll.so %{_libdir}/wine/mapi32.dll.so
%{_libdir}/wine/mciavi32.dll.so %{_libdir}/wine/mciavi32.dll.so
%{_libdir}/wine/mcicda.dll.so %{_libdir}/wine/mcicda.dll.so
@ -575,10 +558,8 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/mmsystem.dll16 %{_libdir}/wine/mmsystem.dll16
%{_libdir}/wine/monodebg.vxd.so %{_libdir}/wine/monodebg.vxd.so
%{_libdir}/wine/mountmgr.sys.so %{_libdir}/wine/mountmgr.sys.so
%{_libdir}/wine/mouse.drv16
%{_libdir}/wine/mpr.dll.so %{_libdir}/wine/mpr.dll.so
%{_libdir}/wine/mprapi.dll.so %{_libdir}/wine/mprapi.dll.so
%{_libdir}/wine/msacm.dll16
%{_libdir}/wine/msacm32.dll.so %{_libdir}/wine/msacm32.dll.so
%{_libdir}/wine/msacm32.drv.so %{_libdir}/wine/msacm32.drv.so
%{_libdir}/wine/msadp32.acm.so %{_libdir}/wine/msadp32.acm.so
@ -620,20 +601,12 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/objsel.dll.so %{_libdir}/wine/objsel.dll.so
%{_libdir}/wine/odbc32.dll.so %{_libdir}/wine/odbc32.dll.so
%{_libdir}/wine/odbccp32.dll.so %{_libdir}/wine/odbccp32.dll.so
%{_libdir}/wine/ole2.dll16
%{_libdir}/wine/ole2conv.dll16
%{_libdir}/wine/ole2disp.dll16
%{_libdir}/wine/ole2nls.dll16
%{_libdir}/wine/ole2prox.dll16
%{_libdir}/wine/ole2thk.dll16
%{_libdir}/wine/ole32.dll.so %{_libdir}/wine/ole32.dll.so
%{_libdir}/wine/oleacc.dll.so %{_libdir}/wine/oleacc.dll.so
%{_libdir}/wine/oleaut32.dll.so %{_libdir}/wine/oleaut32.dll.so
%{_libdir}/wine/olecli.dll16
%{_libdir}/wine/olecli32.dll.so %{_libdir}/wine/olecli32.dll.so
%{_libdir}/wine/oledlg.dll.so %{_libdir}/wine/oledlg.dll.so
%{_libdir}/wine/olepro32.dll.so %{_libdir}/wine/olepro32.dll.so
%{_libdir}/wine/olesvr.dll16
%{_libdir}/wine/olesvr32.dll.so %{_libdir}/wine/olesvr32.dll.so
%{_libdir}/wine/olethk32.dll.so %{_libdir}/wine/olethk32.dll.so
%{_libdir}/wine/pdh.dll.so %{_libdir}/wine/pdh.dll.so
@ -649,7 +622,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/qmgrprxy.dll.so %{_libdir}/wine/qmgrprxy.dll.so
%{_libdir}/wine/quartz.dll.so %{_libdir}/wine/quartz.dll.so
%{_libdir}/wine/query.dll.so %{_libdir}/wine/query.dll.so
%{_libdir}/wine/rasapi16.dll16
%{_libdir}/wine/rasapi32.dll.so %{_libdir}/wine/rasapi32.dll.so
%{_libdir}/wine/rasdlg.dll.so %{_libdir}/wine/rasdlg.dll.so
%{_libdir}/wine/resutils.dll.so %{_libdir}/wine/resutils.dll.so
@ -676,13 +648,10 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/slc.dll.so %{_libdir}/wine/slc.dll.so
%{_libdir}/wine/snmpapi.dll.so %{_libdir}/wine/snmpapi.dll.so
%{_libdir}/wine/softpub.dll.so %{_libdir}/wine/softpub.dll.so
%{_libdir}/wine/sound.drv16
%{_libdir}/wine/spoolsv.exe.so %{_libdir}/wine/spoolsv.exe.so
%{_libdir}/wine/stdole2.tlb.so %{_libdir}/wine/stdole2.tlb.so
%{_libdir}/wine/stdole32.tlb.so %{_libdir}/wine/stdole32.tlb.so
%{_libdir}/wine/sti.dll.so %{_libdir}/wine/sti.dll.so
%{_libdir}/wine/storage.dll16
%{_libdir}/wine/stress.dll16
%{_libdir}/wine/svchost.exe.so %{_libdir}/wine/svchost.exe.so
%{_libdir}/wine/svrapi.dll.so %{_libdir}/wine/svrapi.dll.so
%{_libdir}/wine/sxs.dll.so %{_libdir}/wine/sxs.dll.so
@ -690,7 +659,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/tapi32.dll.so %{_libdir}/wine/tapi32.dll.so
%{_libdir}/wine/toolhelp.dll16 %{_libdir}/wine/toolhelp.dll16
%{_libdir}/wine/traffic.dll.so %{_libdir}/wine/traffic.dll.so
%{_libdir}/wine/typelib.dll16
%{_libdir}/wine/unicows.dll.so %{_libdir}/wine/unicows.dll.so
%{_libdir}/wine/unlodctr.exe.so %{_libdir}/wine/unlodctr.exe.so
%{_libdir}/wine/updspapi.dll.so %{_libdir}/wine/updspapi.dll.so
@ -711,11 +679,6 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/vtdapi.vxd.so %{_libdir}/wine/vtdapi.vxd.so
%{_libdir}/wine/vwin32.vxd.so %{_libdir}/wine/vwin32.vxd.so
%{_libdir}/wine/w32skrnl.dll.so %{_libdir}/wine/w32skrnl.dll.so
%{_libdir}/wine/w32sys.dll16
%{_libdir}/wine/win32s16.dll16
%{_libdir}/wine/win87em.dll16
%{_libdir}/wine/winaspi.dll16
%{_libdir}/wine/windebug.dll16
%{_libdir}/wine/wineaudioio.drv.so %{_libdir}/wine/wineaudioio.drv.so
%{_libdir}/wine/winedos.dll.so %{_libdir}/wine/winedos.dll.so
%{_libdir}/wine/wineoss.drv.so %{_libdir}/wine/wineoss.drv.so
@ -727,15 +690,12 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/winhttp.dll.so %{_libdir}/wine/winhttp.dll.so
%{_libdir}/wine/wininet.dll.so %{_libdir}/wine/wininet.dll.so
%{_libdir}/wine/winmm.dll.so %{_libdir}/wine/winmm.dll.so
%{_libdir}/wine/winnls.dll16
%{_libdir}/wine/winnls32.dll.so %{_libdir}/wine/winnls32.dll.so
%{_libdir}/wine/winsock.dll16 %{_libdir}/wine/winsock.dll16
%{_libdir}/wine/winspool.drv.so %{_libdir}/wine/winspool.drv.so
%{_libdir}/wine/wmi.dll.so %{_libdir}/wine/wmi.dll.so
%{_libdir}/wine/spoolss.dll.so %{_libdir}/wine/spoolss.dll.so
%{_libdir}/wine/winoldap.mod16
%{_libdir}/wine/winscard.dll.so %{_libdir}/wine/winscard.dll.so
%{_libdir}/wine/wintab.dll16
%{_libdir}/wine/wintab32.dll.so %{_libdir}/wine/wintab32.dll.so
%{_libdir}/wine/wintrust.dll.so %{_libdir}/wine/wintrust.dll.so
%{_libdir}/wine/wnaspi32.dll.so %{_libdir}/wine/wnaspi32.dll.so
@ -764,11 +724,47 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/xinput1_3.dll.so %{_libdir}/wine/xinput1_3.dll.so
%{_libdir}/wine/xinput9_1_0.dll.so %{_libdir}/wine/xinput9_1_0.dll.so
%{_sysconfdir}/ld.so.conf.d/wine-32.conf %{_sysconfdir}/ld.so.conf.d/wine-32.conf
# 16bit
%{_libdir}/wine/avifile.dll16.so
%{_libdir}/wine/comm.drv16.so
%{_libdir}/wine/compobj.dll16.so
%{_libdir}/wine/ctl3d.dll16.so
%{_libdir}/wine/ctl3dv2.dll16.so
%{_libdir}/wine/dispdib.dll16.so
%{_libdir}/wine/display.drv16.so
%{_libdir}/wine/imm.dll16.so
%{_libdir}/wine/keyboard.drv16.so
%{_libdir}/wine/lzexpand.dll16.so
%{_libdir}/wine/mciqtz32.dll.so
%{_libdir}/wine/mouse.drv16.so
%{_libdir}/wine/msacm.dll16.so
%{_libdir}/wine/ole2.dll16.so
%{_libdir}/wine/ole2conv.dll16.so
%{_libdir}/wine/ole2disp.dll16.so
%{_libdir}/wine/ole2nls.dll16.so
%{_libdir}/wine/ole2prox.dll16.so
%{_libdir}/wine/ole2thk.dll16.so
%{_libdir}/wine/olecli.dll16.so
%{_libdir}/wine/olesvr.dll16.so
%{_libdir}/wine/rasapi16.dll16.so
%{_libdir}/wine/sound.drv16.so
%{_libdir}/wine/storage.dll16.so
%{_libdir}/wine/stress.dll16.so
%{_libdir}/wine/twain.dll16.so
%{_libdir}/wine/typelib.dll16.so
%{_libdir}/wine/w32sys.dll16.so
%{_libdir}/wine/win32s16.dll16.so
%{_libdir}/wine/win87em.dll16.so
%{_libdir}/wine/winaspi.dll16.so
%{_libdir}/wine/windebug.dll16.so
%{_libdir}/wine/winhelp.exe16.so
%{_libdir}/wine/winnls.dll16.so
%{_libdir}/wine/winoldap.mod16.so
%{_libdir}/wine/wintab.dll16.so
%files tools %files tools
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_bindir}/notepad %{_bindir}/notepad
%{_bindir}/progman
%{_bindir}/winedbg %{_bindir}/winedbg
%{_bindir}/winedump %{_bindir}/winedump
%{_bindir}/winefile %{_bindir}/winefile
@ -826,7 +822,6 @@ update-desktop-database &>/dev/null || :
%files twain %files twain
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_libdir}/wine/twain.dll16
%{_libdir}/wine/twain_32.dll.so %{_libdir}/wine/twain_32.dll.so
%{_libdir}/wine/sane.ds.so %{_libdir}/wine/sane.ds.so
@ -869,6 +864,11 @@ update-desktop-database &>/dev/null || :
%{_libdir}/wine/winepulse.drv.so %{_libdir}/wine/winepulse.drv.so
%changelog %changelog
* Mon Mar 30 2009 Andreas Bierfert <andreas.bierfert[AT]lowlatency.de>
- 1.1.18-1
- version upgrade (#490672, #491321)
- winepulse update
* Sun Mar 15 2009 Nicolas Mailhot <nicolas.mailhot at laposte.net> - 1.1.15-3 * Sun Mar 15 2009 Nicolas Mailhot <nicolas.mailhot at laposte.net> - 1.1.15-3
— Make sure F11 font packages have been built with F11 fontforge — Make sure F11 font packages have been built with F11 fontforge

@ -22,10 +22,10 @@ index 0000000..327f225
+@DEPENDENCIES@ # everything below this line is overwritten by make depend +@DEPENDENCIES@ # everything below this line is overwritten by make depend
diff --git a/dlls/winepulse.drv/dsoutput.c b/dlls/winepulse.drv/dsoutput.c diff --git a/dlls/winepulse.drv/dsoutput.c b/dlls/winepulse.drv/dsoutput.c
new file mode 100644 new file mode 100644
index 0000000..5086917 index 0000000..b37313a
--- /dev/null --- /dev/null
+++ b/dlls/winepulse.drv/dsoutput.c +++ b/dlls/winepulse.drv/dsoutput.c
@@ -0,0 +1,568 @@ @@ -0,0 +1,576 @@
+/* +/*
+ * Wine Driver for PulseAudio - DSound Output Functionality + * Wine Driver for PulseAudio - DSound Output Functionality
+ * http://pulseaudio.org/ + * http://pulseaudio.org/
@ -74,6 +74,22 @@ index 0000000..5086917
+ * Low level DSOUND implementation * + * Low level DSOUND implementation *
+ *======================================================================*/ + *======================================================================*/
+ +
+/* A buffer is allocated with a pointer indicating the read position in the
+ * buffer. The pulse write callback reads data from the buffer, updating the
+ * read pointer to the location at the end of the read. Upon reaching the end
+ * or attempting to read past the end of buffer the read pointer wraps around
+ * to the beginning again. DirectSound applications can write anywhere in the
+ * buffer at anytime without locking and can know the location of the read
+ * pointer. The position of the read pointer cannot be changed by the
+ * application and access to it uses a locking scheme. A fake pointer
+ * indicating estimated playback position is also available to the application.
+ * Applications can potentially write to the same area of memory which is also
+ * being read by the pulse thread. However, this is uncommon as directsound
+ * applications know where pulse should be reading from via the pointer
+ * locations and MSDN says that such an operation should be avoided with the
+ * results being undefined.
+ */
+
+/* Fragment lengths try to be a power of two close to 10ms worth of data. See +/* Fragment lengths try to be a power of two close to 10ms worth of data. See
+ * dlls/dsound/mixer.c + * dlls/dsound/mixer.c
+ */ + */
@ -100,24 +116,25 @@ index 0000000..5086917
+ /* Fraglens are always powers of 2 */ + /* Fraglens are always powers of 2 */
+ nbytes+= This->fraglen - 1; + nbytes+= This->fraglen - 1;
+ nbytes&= ~(This->fraglen - 1); + nbytes&= ~(This->fraglen - 1);
+
+ /* If we advance more than 10 fragments at a time it appears that the buffer + /* If we advance more than 10 fragments at a time it appears that the buffer
+ * pointer is never advancing because of wrap-around. Evil magic numbers. */ + * pointer is never advancing because of wrap-around. Evil magic numbers. */
+ if (nbytes > This->fraglen * 6) + if (nbytes > This->fraglen * 5)
+ nbytes = This->fraglen * 6; + nbytes = This->fraglen * 5;
+ +
+ TRACE("Reading %u bytes.\n", nbytes); + TRACE("Reading %u bytes.\n", nbytes);
+ +
+ if (This->buffer_read_offset + nbytes > This->buffer_length) { + if (This->buffer_read_offset + nbytes <= This->buffer_length) {
+ pa_stream_write(s, This->buffer + This->buffer_read_offset, nbytes, NULL, 0, PA_SEEK_RELATIVE);
+ This->buffer_play_offset = This->buffer_read_offset;
+ This->buffer_read_offset += nbytes;
+ } else {
+ size_t write_length = This->buffer_length - This->buffer_read_offset; + size_t write_length = This->buffer_length - This->buffer_read_offset;
+ if (nbytes > This->buffer_length)
+ nbytes = This->buffer_length;
+ nbytes -= write_length; + nbytes -= write_length;
+ pa_stream_write(s, This->buffer + This->buffer_read_offset, write_length, NULL, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, This->buffer + This->buffer_read_offset, write_length, NULL, 0, PA_SEEK_RELATIVE);
+ pa_stream_write(s, This->buffer, nbytes, NULL, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, This->buffer, nbytes, NULL, 0, PA_SEEK_RELATIVE);
+ This->buffer_play_offset = This->buffer_read_offset;
+ This->buffer_read_offset = nbytes; + This->buffer_read_offset = nbytes;
+ } else {
+ pa_stream_write(s, This->buffer + This->buffer_read_offset, nbytes, NULL, 0, PA_SEEK_RELATIVE);
+ This->buffer_read_offset += nbytes;
+ } + }
+ +
+ This->buffer_read_offset %= This->buffer_length; + This->buffer_read_offset %= This->buffer_length;
@ -128,25 +145,31 @@ index 0000000..5086917
+ WARN("(%p) underrun.\n", userdata); + WARN("(%p) underrun.\n", userdata);
+} +}
+ +
+/* Connects a stream to the server for use in setting the sample format or +/* Connects a stream to the server. Does not update
+ * stream creation. Does not update IDsDriverBufferImpl->fraglen */ + * IDsDriverBufferImpl->fraglen. Does not lock the pulse mainloop or free
+ * objects in case of failure. This should be handled by the calling function.
+ */
+static HRESULT DSPULSE_ConnectStream(IDsDriverBufferImpl* This) { +static HRESULT DSPULSE_ConnectStream(IDsDriverBufferImpl* This) {
+ pa_buffer_attr ba_request; + pa_buffer_attr ba_request;
+ const pa_buffer_attr *ba_obtained; + const pa_buffer_attr *ba_obtained;
+ char c[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char c[PA_SAMPLE_SPEC_SNPRINT_MAX];
+ pa_stream_flags_t flags = PA_STREAM_START_CORKED; + pa_stream_flags_t stream_flags = PA_STREAM_START_CORKED;
+ +
+#if PA_API_VERSION >= 12 +#if PA_PROTOCOL_VERSION >= 14
+ flags |= PA_STREAM_EARLY_REQUESTS; + /* We are a "fragment wait based" application, so this flag should be
+ * acceptable. */
+ stream_flags |= PA_STREAM_EARLY_REQUESTS;
+#elif PA_PROTOCOL_VERSION >= 13 && PA_API_VERSION >= 12
+ stream_flags |= PA_STREAM_ADJUST_LATENCY;
+#endif +#endif
+ +
+ pa_sample_spec_snprint(c, PA_SAMPLE_SPEC_SNPRINT_MAX, &This->sample_spec); + pa_sample_spec_snprint(c, PA_SAMPLE_SPEC_SNPRINT_MAX, &This->sample_spec);
+ TRACE("Sample spec %s fragment size %u.\n", c, This->fraglen); + TRACE("Sample spec %s fragment size %u.\n", c, This->fraglen);
+ +
+ ba_request.tlength = This->fraglen * 4; + ba_request.tlength = This->fraglen * 4; // ~40ms
+ ba_request.minreq = This->fraglen / 2; + ba_request.minreq = This->fraglen; // ~10ms
+ ba_request.prebuf = (uint32_t) -1; /* same as tlength */ + ba_request.prebuf = (uint32_t)-1; // same as tlength
+ ba_request.maxlength = This->buffer_length; + ba_request.maxlength = This->buffer_length; // 2^x = ~3s
+ +
+ TRACE("Asking for buffer tlength:%u (%llums) minreq:%u (%llums)\n", + TRACE("Asking for buffer tlength:%u (%llums) minreq:%u (%llums)\n",
+ ba_request.tlength, pa_bytes_to_usec(ba_request.tlength, &This->sample_spec)/1000, + ba_request.tlength, pa_bytes_to_usec(ba_request.tlength, &This->sample_spec)/1000,
@ -160,7 +183,7 @@ index 0000000..5086917
+ pa_stream_set_underflow_callback(This->stream, DSPULSE_BufferUnderflowCallback, This); + pa_stream_set_underflow_callback(This->stream, DSPULSE_BufferUnderflowCallback, This);
+ +
+ TRACE("Attempting to connect (%p)->stream for playback on %s\n", This, WOutDev[This->drv->wDevID].device_name); + TRACE("Attempting to connect (%p)->stream for playback on %s\n", This, WOutDev[This->drv->wDevID].device_name);
+ pa_stream_connect_playback(This->stream, WOutDev[This->drv->wDevID].device_name, &ba_request, flags, NULL, NULL); + pa_stream_connect_playback(This->stream, WOutDev[This->drv->wDevID].device_name, &ba_request, stream_flags, NULL, NULL);
+ for (;;) { + for (;;) {
+ pa_context_state_t cstate = pa_context_get_state(PULSE_context); + pa_context_state_t cstate = pa_context_get_state(PULSE_context);
+ pa_stream_state_t sstate = pa_stream_get_state(This->stream); + pa_stream_state_t sstate = pa_stream_get_state(This->stream);
@ -211,20 +234,15 @@ index 0000000..5086917
+ return refCount; + return refCount;
+ +
+ TRACE("mmap buffer %p destroyed\n", This->buffer); + TRACE("mmap buffer %p destroyed\n", This->buffer);
+
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+ PULSE_WaitForOperation(pa_stream_cork(This->stream, 1, PULSE_StreamSuccessCallback, This)); + PULSE_WaitForOperation(pa_stream_cork(This->stream, 1, PULSE_StreamSuccessCallback, This));
+ pa_stream_disconnect(This->stream); + pa_stream_disconnect(This->stream);
+
+ if (This == This->drv->primary) + if (This == This->drv->primary)
+ This->drv->primary = NULL; + This->drv->primary = NULL;
+
+ HeapFree(GetProcessHeap(), 0, This->buffer); + HeapFree(GetProcessHeap(), 0, This->buffer);
+ This->buffer = NULL; + This->buffer = NULL;
+
+ pa_stream_unref(This->stream); + pa_stream_unref(This->stream);
+ This->stream = NULL; + This->stream = NULL;
+
+ HeapFree(GetProcessHeap(), 0, This); + HeapFree(GetProcessHeap(), 0, This);
+ pa_threaded_mainloop_unlock(PULSE_ml); + pa_threaded_mainloop_unlock(PULSE_ml);
+ +
@ -255,7 +273,6 @@ index 0000000..5086917
+ * destroy and re-create the stream if the sample spec is different */ + * destroy and re-create the stream if the sample spec is different */
+static HRESULT WINAPI IDsDriverBufferImpl_SetFormat(PIDSDRIVERBUFFER iface, LPWAVEFORMATEX pwfx) { +static HRESULT WINAPI IDsDriverBufferImpl_SetFormat(PIDSDRIVERBUFFER iface, LPWAVEFORMATEX pwfx) {
+ IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; + IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
+ HRESULT ret = DS_OK;
+ pa_sample_spec old_spec; + pa_sample_spec old_spec;
+ +
+ TRACE("(%p, %p)\n", iface, pwfx); + TRACE("(%p, %p)\n", iface, pwfx);
@ -267,27 +284,16 @@ index 0000000..5086917
+ if (!PULSE_SetupFormat(pwfx, &This->sample_spec)) + if (!PULSE_SetupFormat(pwfx, &This->sample_spec))
+ return DSERR_BADFORMAT; + return DSERR_BADFORMAT;
+ +
+ pa_threaded_mainloop_lock(PULSE_ml);
+ if (old_spec.rate == This->sample_spec.rate && + if (old_spec.rate == This->sample_spec.rate &&
+ old_spec.format == This->sample_spec.format && + old_spec.format == This->sample_spec.format &&
+ old_spec.channels == This->sample_spec.channels) { + old_spec.channels == This->sample_spec.channels) {
+ TRACE("same as original sample spec, exiting.\n"); + TRACE("same as original sample spec, exiting.\n");
+ ret = DS_OK; + return DS_OK;
+ goto leave;
+ } + }
+ +
+ This->fraglen = fragment_length(&This->sample_spec); + /* If the format doesn't match, return an error and the buffer will be remade */
+ + TRACE("Formats don't match, failing causing re-creation.\n");
+ TRACE("Disconnecting old stream.\n"); + return DSERR_BUFFERLOST;
+ pa_stream_disconnect(This->stream);
+ pa_stream_unref(This->stream);
+ ret = DSPULSE_ConnectStream(This);
+
+leave:
+ pa_threaded_mainloop_unlock(PULSE_ml);
+
+ TRACE("Exiting\n");
+ return ret;
+} +}
+ +
+static HRESULT WINAPI IDsDriverBufferImpl_SetFrequency(PIDSDRIVERBUFFER iface, DWORD dwFreq) +static HRESULT WINAPI IDsDriverBufferImpl_SetFrequency(PIDSDRIVERBUFFER iface, DWORD dwFreq)
@ -342,15 +348,13 @@ index 0000000..5086917
+ IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; + IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface;
+ +
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+
+ if (!This->buffer || pa_stream_get_state(This->stream) != PA_STREAM_READY) { + if (!This->buffer || pa_stream_get_state(This->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(PULSE_ml); + pa_threaded_mainloop_unlock(PULSE_ml);
+ return DSERR_UNINITIALIZED; + return DSERR_UNINITIALIZED;
+ } + }
+ +
+ /* These values are fake, and must remain so */
+ if (lpdwPlay) + if (lpdwPlay)
+ *lpdwPlay = (This->buffer_read_offset + This->buffer_length - This->fraglen * 2) % This->buffer_length; + *lpdwPlay = This->buffer_play_offset;
+ if (lpdwWrite) + if (lpdwWrite)
+ *lpdwWrite = This->buffer_read_offset; + *lpdwWrite = This->buffer_read_offset;
+ pa_threaded_mainloop_unlock(PULSE_ml); + pa_threaded_mainloop_unlock(PULSE_ml);
@ -409,6 +413,7 @@ index 0000000..5086917
+ +
+ TRACE("(%p,%p,%x,%x)\n",iface,pwfx,dwFlags,dwCardAddress); + TRACE("(%p,%p,%x,%x)\n",iface,pwfx,dwFlags,dwCardAddress);
+ /* we only support primary buffers */ + /* we only support primary buffers */
+
+ if (!(dwFlags & DSBCAPS_PRIMARYBUFFER)) + if (!(dwFlags & DSBCAPS_PRIMARYBUFFER))
+ return DSERR_UNSUPPORTED; + return DSERR_UNSUPPORTED;
+ if (This->primary) + if (This->primary)
@ -425,7 +430,9 @@ index 0000000..5086917
+ That = *ippdsdb; + That = *ippdsdb;
+ That->lpVtbl = &dsdbvt; + That->lpVtbl = &dsdbvt;
+ That->ref = 1; + That->ref = 1;
+
+ That->drv = This; + That->drv = This;
+ TRACE("IdsDriverBufferImpl %p created.\n", That);
+ +
+ if (!PULSE_SetupFormat(pwfx, &That->sample_spec)) { + if (!PULSE_SetupFormat(pwfx, &That->sample_spec)) {
+ WARN("Bad audio format.\n"); + WARN("Bad audio format.\n");
@ -437,8 +444,13 @@ index 0000000..5086917
+ * dlls/dsound/mixer.c fails to correctly understand buffer wrap around. */ + * dlls/dsound/mixer.c fails to correctly understand buffer wrap around. */
+ That->fraglen = fragment_length(&That->sample_spec); + That->fraglen = fragment_length(&That->sample_spec);
+ That->buffer_length = That->fraglen * 32; + That->buffer_length = That->fraglen * 32;
+ That->buffer = pa_xmalloc0(That->buffer_length); + That->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, That->buffer_length);
+ if (!That->buffer) {
+ ret = DSERR_OUTOFMEMORY;
+ goto err;
+ }
+ That->buffer_read_offset = 0; + That->buffer_read_offset = 0;
+ That->buffer_play_offset = 0;
+ +
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+ ret = DSPULSE_ConnectStream(That); + ret = DSPULSE_ConnectStream(That);
@ -462,13 +474,9 @@ index 0000000..5086917
+ That->stream = NULL; + That->stream = NULL;
+ } + }
+ pa_threaded_mainloop_unlock(PULSE_ml); + pa_threaded_mainloop_unlock(PULSE_ml);
+ if (That->buffer)
+ HeapFree(GetProcessHeap(), 0, That->buffer); + HeapFree(GetProcessHeap(), 0, That->buffer);
+ + HeapFree(GetProcessHeap(), 0, *ippdsdb);
+ if (*ippdsdb) + WARN("exiting with failure.\n");
+ HeapFree(GetProcessHeap(), 0, That);
+ *ippdsdb = NULL;
+ TRACE("exiting with failure\n");
+ return ret; + return ret;
+} +}
+ +
@ -578,7 +586,7 @@ index 0000000..5086917
+ if (!*idrv) + if (!*idrv)
+ return MMSYSERR_NOMEM; + return MMSYSERR_NOMEM;
+ +
+ TRACE("driver created\n"); + TRACE("IDsDriverImpl %p created.\n", *idrv);
+ +
+ (*idrv)->lpVtbl = &dsdvt; + (*idrv)->lpVtbl = &dsdvt;
+ (*idrv)->ref = 1; + (*idrv)->ref = 1;
@ -596,15 +604,15 @@ index 0000000..5086917
+#endif /* HAVE_PULSEAUDIO */ +#endif /* HAVE_PULSEAUDIO */
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
new file mode 100644 new file mode 100644
index 0000000..337814d index 0000000..aa84c9b
--- /dev/null --- /dev/null
+++ b/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c
@@ -0,0 +1,922 @@ @@ -0,0 +1,861 @@
+/* +/*
+ * Wine Driver for PulseAudio + * Wine Driver for PulseAudio
+ * http://pulseaudio.org/ + * http://pulseaudio.org/
+ * + *
+ * Copyright 2008 Arthur Taylor <theycallhimart@gmail.com> + * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
+ * + *
+ * Contains code from other wine sound drivers. + * Contains code from other wine sound drivers.
+ * + *
@ -653,11 +661,6 @@ index 0000000..337814d
+#include <pulse/pulseaudio.h> +#include <pulse/pulseaudio.h>
+WINE_DEFAULT_DEBUG_CHANNEL(wave); +WINE_DEFAULT_DEBUG_CHANNEL(wave);
+ +
+/*
+ * - Need to subscribe to sink/source events and keep the WInDev and WOutDev
+ * structures updated
+ */
+
+/* These strings used only for tracing */ +/* These strings used only for tracing */
+const char * PULSE_getCmdString(enum win_wm_message msg) { +const char * PULSE_getCmdString(enum win_wm_message msg) {
+ static char unknown[32]; + static char unknown[32];
@ -868,9 +871,16 @@ index 0000000..337814d
+ +
+ switch (wf->wFormatTag) { + switch (wf->wFormatTag) {
+ case WAVE_FORMAT_PCM: + case WAVE_FORMAT_PCM:
+ if (ss->channels > 2 || ss->channels < 1) return FALSE; + /* 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 + ss->format = wf->wBitsPerSample == 8 ? PA_SAMPLE_U8
+ : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE + : wf->wBitsPerSample == 16 ? PA_SAMPLE_S16NE
+#if PA_PROTOCOL_VERSION >= 15
+ : wf->wBitsPerSample == 24 ? PA_SAMPLE_S24NE
+#endif
+ : wf->wBitsPerSample == 32 ? PA_SAMPLE_S32NE
+ : PA_SAMPLE_INVALID; + : PA_SAMPLE_INVALID;
+ break; + break;
+ +
@ -1160,6 +1170,7 @@ index 0000000..337814d
+ +
+ switch (pa_context_get_state(c)) { + switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME: + case PA_CONTEXT_SETTING_NAME:
+ break; + break;
@ -1170,217 +1181,141 @@ index 0000000..337814d
+ break; + break;
+ +
+ case PA_CONTEXT_FAILED: + case PA_CONTEXT_FAILED:
+ default:
+ ERR("Context failure: %s\n", pa_strerror(pa_context_errno(c))); + ERR("Context failure: %s\n", pa_strerror(pa_context_errno(c)));
+ pa_threaded_mainloop_signal(PULSE_ml, 0); + pa_threaded_mainloop_signal(PULSE_ml, 0);
+ break;
+ } + }
+} +}
+ +
+/************************************************************************** +/**************************************************************************
+ * PULSE_SourceInfoCallback [internal] + * PULSE_AllocateWaveinDevice [internal]
+ * + *
+ * Creates or adds a device to WInDev based on the pa_source_info. + * 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) {
+static void PULSE_SourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata) {
+ DWORD *allocated = (DWORD*)userdata;
+ WINE_WAVEDEV *wdi; + WINE_WAVEDEV *wdi;
+ +
+ if (eol || !i) {
+ pa_threaded_mainloop_signal(PULSE_ml, 0);
+ return;
+ }
+
+ if (WInDev) + if (WInDev)
+ wdi = HeapReAlloc(GetProcessHeap(), 0, WInDev, sizeof(WINE_WAVEDEV) * (*allocated + 1)); + wdi = HeapReAlloc(GetProcessHeap(), 0, WInDev, sizeof(WINE_WAVEDEV) * (PULSE_WidNumDevs + 1));
+ else + else
+ wdi = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV)); + wdi = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
+ +
+ if (!wdi) return; + if (!wdi) return;
+ +
+ WInDev = wdi; + WInDev = wdi;
+ wdi = &WInDev[(*allocated)++]; + wdi = &WInDev[PULSE_WidNumDevs++];
+ memset(wdi, 0, sizeof(WINE_WAVEDEV)); + memset(wdi, 0, sizeof(WINE_WAVEDEV));
+ memset(&(wdi->caps.in), 0, sizeof(wdi->caps.in)); + memset(&(wdi->caps.in), 0, sizeof(wdi->caps.in));
+ + snprintf(wdi->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
+ wdi->device_name = pa_xstrdup(i->name); + wdi->device_name = pa_xstrdup(device);
+ strcpy(wdi->interface_name, "winepulse: "); + strcpy(wdi->interface_name, "winepulse: ");
+ memcpy(wdi->interface_name + strlen(wdi->interface_name), + MultiByteToWideChar(CP_ACP, 0, description, -1, wdi->caps.in.szPname, sizeof(wdi->caps.in.szPname)/sizeof(WCHAR));
+ i->name, min(strlen(i->name), sizeof(wdi->interface_name) - strlen("winepulse: ")));
+ MultiByteToWideChar(CP_ACP, 0, i->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.szPname[sizeof(wdi->caps.in.szPname)/sizeof(WCHAR) - 1] = '\0';
+ wdi->caps.in.wMid = MM_CREATIVE; + wdi->caps.in.wMid = MM_CREATIVE;
+ wdi->caps.in.wPid = MM_CREATIVE_SBP16_WAVEOUT; + wdi->caps.in.wPid = MM_CREATIVE_SBP16_WAVEOUT;
+ wdi->caps.in.vDriverVersion = 0x0100; + wdi->caps.in.vDriverVersion = 0x0100;
+ wdi->caps.in.wChannels = i->sample_spec.channels == 1 ? 1 : 2; + wdi->caps.in.wChannels = v->channels == 1 ? 1 : 2;
+ wdi->caps.in.dwFormats = PULSE_ALL_FORMATS; + wdi->caps.in.dwFormats = PULSE_ALL_FORMATS;
+ pa_threaded_mainloop_signal(PULSE_ml, 0); + 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_SinkInfoCallback [internal] + * PULSE_AllocateWaveoutDevice [internal]
+ * + *
+ * Creates or adds a sink to the WOutDev array. + * Creates or adds a sink to the WOutDev array.
+ */ + */
+static void PULSE_SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { +static void PULSE_AllocateWaveoutDevice(const char *name, const char *device, const char *description, const pa_cvolume *v) {
+ DWORD *allocated = (DWORD*)userdata;
+ WINE_WAVEDEV *wdo; + WINE_WAVEDEV *wdo;
+ int x; + int x;
+ +
+ if (eol || !i) {
+ pa_threaded_mainloop_signal(PULSE_ml, 0);
+ return;
+ }
+
+ if (WOutDev) + if (WOutDev)
+ wdo = HeapReAlloc(GetProcessHeap(), 0, WOutDev, sizeof(WINE_WAVEDEV) * (*allocated + 1)); + wdo = HeapReAlloc(GetProcessHeap(), 0, WOutDev, sizeof(WINE_WAVEDEV) * (PULSE_WodNumDevs + 1));
+ else + else
+ wdo = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV)); + wdo = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WAVEDEV));
+ +
+ if (!wdo) return; + if (!wdo) return;
+ +
+ WOutDev = wdo; + WOutDev = wdo;
+ wdo = &WOutDev[(*allocated)++]; + wdo = &WOutDev[PULSE_WodNumDevs++];
+ memset(wdo, 0, sizeof(WINE_WAVEDEV)); + memset(wdo, 0, sizeof(WINE_WAVEDEV));
+ +
+ wdo->device_name = pa_xstrdup(i->name); + wdo->device_name = pa_xstrdup(device);
+ wdo->volume.channels = i->volume.channels; + wdo->volume.channels = v->channels;
+ for (x = 0; x < i->volume.channels; x++) wdo->volume.values[x] = i->volume.values[x]; + for (x = 0; x < v->channels; x++) wdo->volume.values[x] = v->values[x];
+ strcpy(wdo->interface_name, "winepulse: "); + snprintf(wdo->interface_name, MAXPNAMELEN * 2, "winepulse: %s", name);
+ memcpy(wdo->interface_name + strlen(wdo->interface_name), + MultiByteToWideChar(CP_ACP, 0, description, -1, wdo->caps.out.szPname, sizeof(wdo->caps.out.szPname)/sizeof(WCHAR));
+ i->name, min(strlen(i->name),
+ sizeof(wdo->interface_name) - strlen("winepulse: ")));
+ MultiByteToWideChar(CP_ACP, 0, i->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.szPname[sizeof(wdo->caps.out.szPname)/sizeof(WCHAR) - 1] = '\0';
+ wdo->caps.out.wMid = MM_CREATIVE; + wdo->caps.out.wMid = MM_CREATIVE;
+ wdo->caps.out.wPid = MM_CREATIVE_SBP16_WAVEOUT; + wdo->caps.out.wPid = MM_CREATIVE_SBP16_WAVEOUT;
+ wdo->caps.out.vDriverVersion = 0x0100; + wdo->caps.out.vDriverVersion = 0x0100;
+ wdo->caps.out.dwSupport = WAVECAPS_VOLUME | WAVECAPS_SAMPLEACCURATE; + wdo->caps.out.dwSupport = WAVECAPS_VOLUME | WAVECAPS_SAMPLEACCURATE | WAVECAPS_DIRECTSOUND;
+ if (i->sample_spec.channels == 2) { + if (v->channels >= 2) {
+ wdo->caps.out.wChannels = 2; + wdo->caps.out.wChannels = 2;
+ wdo->caps.out.dwSupport |= WAVECAPS_LRVOLUME; + wdo->caps.out.dwSupport |= WAVECAPS_LRVOLUME;
+ } else + } else
+ wdo->caps.out.wChannels = i->sample_spec.channels == 1 ? 1 : 2; + wdo->caps.out.wChannels = 1;
+ wdo->caps.out.dwFormats = PULSE_ALL_FORMATS; + wdo->caps.out.dwFormats = PULSE_ALL_FORMATS;
+ memset(&wdo->ds_desc, 0, sizeof(DSDRIVERDESC)); + memset(&wdo->ds_desc, 0, sizeof(DSDRIVERDESC));
+ memcpy(wdo->ds_desc.szDesc, i->description, min(sizeof(wdo->ds_desc.szDesc) - 1, strlen(i->description))); + memcpy(wdo->ds_desc.szDesc, description, min(sizeof(wdo->ds_desc.szDesc) - 1, strlen(description)));
+ strcpy(wdo->ds_desc.szDrvname, "winepulse.drv"); + memcpy(wdo->ds_desc.szDrvname, "winepulse.drv", 14);
+ wdo->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; + wdo->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+ wdo->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; + wdo->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+ wdo->ds_caps.dwPrimaryBuffers = 1; + wdo->ds_caps.dwPrimaryBuffers = 1;
+ + wdo->ds_caps.dwFlags = \
+ pa_threaded_mainloop_signal(PULSE_ml, 0); + DSCAPS_PRIMARYMONO |
+ DSCAPS_PRIMARYSTEREO |
+ DSCAPS_PRIMARY8BIT |
+ DSCAPS_PRIMARY16BIT |
+ DSCAPS_SECONDARYMONO |
+ DSCAPS_SECONDARYSTEREO |
+ DSCAPS_SECONDARY8BIT |
+ DSCAPS_SECONDARY16BIT |
+ DSCAPS_CERTIFIED;
+} +}
+ +
+/************************************************************************** +/**************************************************************************
+ * PULSE_UpdateWavedevs [internal] + * PULSE_SourceInfoCallback [internal]
+ * + */
+ * Calls PULSE_add_output_device to add the sink to the list of devices +static void PULSE_SourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata) {
+ */
+BOOL PULSE_UpdateWavedevs(int devices) {
+ WINE_WAVEDEV *old_devs;
+ DWORD old_numdevs;
+ DWORD rc;
+ HKEY key;
+ BOOL show_monitor_sources = TRUE;
+
+ rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Pulse Driver", 0, KEY_QUERY_VALUE, &key);
+ if (rc == ERROR_SUCCESS) {
+ DWORD type;
+ DWORD bufsize;
+ char *bufp;
+
+ rc = RegQueryValueExA(key, "MonitorDevices", NULL, &type, NULL, &bufsize);
+ if (rc == ERROR_SUCCESS || type == REG_SZ) {
+ bufp = HeapAlloc(GetProcessHeap(), 0, bufsize);
+ if (bufp) {
+ rc = RegQueryValueExA(key, "MonitorDevices", NULL, NULL, (LPBYTE)bufp, &bufsize);
+ if (rc == ERROR_SUCCESS && (
+ *bufp == 'n' || *bufp == 'N' ||
+ *bufp == 'f' || *bufp == 'F' ||
+ *bufp == 'd' || *bufp == 'D' ||
+ *bufp == '0'))
+ show_monitor_sources = FALSE;
+ HeapFree(GetProcessHeap(), 0, bufp);
+ }
+ }
+ }
+ if (key)
+ RegCloseKey(key);
+
+ pa_threaded_mainloop_lock(PULSE_ml);
+ if (devices & PULSE_OUT_DEVS) {
+ old_devs = WOutDev;
+ old_numdevs = PULSE_WodNumDevs;
+ WOutDev = NULL;
+ PULSE_WodNumDevs = 0;
+ +
+ /* Ask for all the sinks and create objects in the WOutDev array */ + if (!eol && i)
+ PULSE_WaitForOperation(pa_context_get_sink_info_list(PULSE_context, PULSE_SinkInfoCallback, &PULSE_WodNumDevs)); + PULSE_AllocateWaveinDevice(i->name, i->name, i->description, &i->volume);
+ if (PULSE_WodNumDevs) {
+ if (old_devs)
+ HeapFree(GetProcessHeap(), 0, old_devs);
+ TRACE("Allocated %i output device%s.\n", PULSE_WodNumDevs, PULSE_WodNumDevs > 1 ? "s" : "");
+ } else {
+ WARN("Didn't seem to find any waveout devices upon update, not updating!\n");
+ if (WOutDev)
+ HeapFree(GetProcessHeap(), 0, WOutDev);
+ WOutDev = old_devs;
+ PULSE_WodNumDevs = old_numdevs;
+ }
+ }
+ +
+ if (devices & PULSE_IN_DEVS) { + pa_threaded_mainloop_signal(PULSE_ml, 0);
+ old_devs = WInDev; +}
+ old_numdevs = PULSE_WidNumDevs;
+ WInDev = NULL;
+ PULSE_WidNumDevs = 0;
+
+ /* Ask for all the sources and create objects in the WOutDev array */
+ PULSE_WaitForOperation(pa_context_get_source_info_list(PULSE_context, PULSE_SourceInfoCallback, &PULSE_WidNumDevs));
+ if (PULSE_WidNumDevs) {
+ if (old_devs)
+ HeapFree(GetProcessHeap(), 0, old_devs);
+ TRACE("Allocated %i input device%s.\n", PULSE_WidNumDevs, PULSE_WidNumDevs > 1 ? "s" : "");
+ } else {
+ WARN("Didn't seem to find any wavein devices upon update, not updating!\n");
+ if (WInDev)
+ HeapFree(GetProcessHeap(), 0, WInDev);
+ WInDev = old_devs;
+ PULSE_WidNumDevs = old_numdevs;
+ }
+ +
+ /* Swap around the devices so monitor streams come last. */ +/**************************************************************************
+ { + * PULSE_SinkInfoCallback [internal]
+ int x; + */
+ int count = 0; +static void PULSE_SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
+ WINE_WAVEDEV tmp[PULSE_WidNumDevs];
+ +
+ memcpy(tmp, WInDev, sizeof(WINE_WAVEDEV) * PULSE_WidNumDevs); + if (!eol && i)
+ for (x = 0; x < PULSE_WidNumDevs; x++) { + PULSE_AllocateWaveoutDevice(i->name, i->name, i->description, &i->volume);
+ if (!strstr(tmp[x].device_name, ".monitor")) {
+ memcpy(&WInDev[count++], &tmp[x], sizeof(WINE_WAVEDEV));
+ }
+ }
+ if (show_monitor_sources) {
+ for (x = 0; x < PULSE_WidNumDevs; x++) {
+ if (strstr(tmp[x].device_name, ".monitor")) {
+ memcpy(&WInDev[count++], &tmp[x], sizeof(WINE_WAVEDEV));
+ }
+ }
+ }
+ if (PULSE_WidNumDevs != count) {
+ TRACE("Removed monitors sources, now have %u input devices.\n", count);
+ WInDev = HeapReAlloc(GetProcessHeap(), 0, WInDev, sizeof(WINE_WAVEDEV) * count);
+ PULSE_WidNumDevs = count;
+ }
+ }
+ }
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ +
+ return TRUE; + pa_threaded_mainloop_signal(PULSE_ml, 0);
+} +}
+ +
+/**************************************************************************
+ * PULSE_ContextNotifyCallback [internal]
+ */
+static void PULSE_ContextNotifyCallback(pa_context *c, void *userdata) { +static void PULSE_ContextNotifyCallback(pa_context *c, void *userdata) {
+ pa_threaded_mainloop_signal(PULSE_ml, 0); + pa_threaded_mainloop_signal(PULSE_ml, 0);
+} +}
@ -1393,10 +1328,14 @@ index 0000000..337814d
+ */ + */
+ +
+static LONG PULSE_WaveClose(void) { +static LONG PULSE_WaveClose(void) {
+ int x;
+ TRACE("()\n"); + TRACE("()\n");
+ if (!PULSE_ml) return 1; + if (!PULSE_ml) return DRV_FAILURE;
+ +
+ pa_threaded_mainloop_lock(PULSE_ml); + 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, WOutDev);
+ HeapFree(GetProcessHeap(), 0, WInDev); + HeapFree(GetProcessHeap(), 0, WInDev);
+ if (PULSE_context) { + if (PULSE_context) {
@ -1425,6 +1364,7 @@ index 0000000..337814d
+ char path[PATH_MAX]; + char path[PATH_MAX];
+ char *offset = NULL; + char *offset = NULL;
+ int x = 0; + int x = 0;
+ pa_cvolume fake_cvolume;
+ +
+ WOutDev = NULL; + WOutDev = NULL;
+ WInDev = NULL; + WInDev = NULL;
@ -1443,12 +1383,11 @@ index 0000000..337814d
+ +
+ /* Get binary path, and remove path a-la strrchr */ + /* Get binary path, and remove path a-la strrchr */
+ if (GetModuleFileNameA(NULL, path, PATH_MAX)) + if (GetModuleFileNameA(NULL, path, PATH_MAX))
+ for (offset = path; *offset; offset++) + offset = strrchr(path, '\\');
+ if (*offset == '\\') x = offset - path + 1;
+ +
+ if (offset || path[x]) { + if (offset && ++offset && offset < path + PATH_MAX) {
+ app_name = pa_xmalloc(strlen(path + x) + 8); + app_name = pa_xmalloc(strlen(offset) + 8);
+ snprintf(app_name, strlen(path + x) + 8, "WINE [%s]", path + x); + snprintf(app_name, strlen(offset) + 8, "WINE [%s]", offset);
+ } else + } else
+ app_name = pa_xstrdup("WINE Application"); + app_name = pa_xstrdup("WINE Application");
+ +
@ -1463,7 +1402,7 @@ index 0000000..337814d
+ +
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+ +
+ TRACE("libpulse protocol version: %u.\n", pa_context_get_protocol_version(PULSE_context)); + 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"); + TRACE("Attempting to connect to pulseaudio server.\n");
+ if (pa_context_connect(PULSE_context, NULL, 0, NULL) < 0) + if (pa_context_connect(PULSE_context, NULL, 0, NULL) < 0)
+ goto fail; + goto fail;
@ -1484,7 +1423,16 @@ index 0000000..337814d
+ x = pa_context_get_server_protocol_version(PULSE_context); + 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); + TRACE("Connected to server %s with protocol version: %i.\n", pa_context_get_server(PULSE_context), x);
+ if (x < 14) + if (x < 14)
+ WARN("Server is old, expect poor latency or bugginess!\n"); + 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); + pa_threaded_mainloop_unlock(PULSE_ml);
+ +
@ -1506,8 +1454,7 @@ index 0000000..337814d
+ +
+ switch(wMsg) { + switch(wMsg) {
+#ifdef HAVE_PULSEAUDIO +#ifdef HAVE_PULSEAUDIO
+ case DRV_LOAD: PULSE_WaveInit(); + case DRV_LOAD: return PULSE_WaveInit();
+ return 1;
+ case DRV_FREE: return PULSE_WaveClose(); + case DRV_FREE: return PULSE_WaveClose();
+ case DRV_OPEN: return 1; + case DRV_OPEN: return 1;
+ case DRV_CLOSE: return 1; + case DRV_CLOSE: return 1;
@ -1524,10 +1471,10 @@ index 0000000..337814d
+} +}
diff --git a/dlls/winepulse.drv/wavein.c b/dlls/winepulse.drv/wavein.c diff --git a/dlls/winepulse.drv/wavein.c b/dlls/winepulse.drv/wavein.c
new file mode 100644 new file mode 100644
index 0000000..7024ccd index 0000000..1534d6e
--- /dev/null --- /dev/null
+++ b/dlls/winepulse.drv/wavein.c +++ b/dlls/winepulse.drv/wavein.c
@@ -0,0 +1,555 @@ @@ -0,0 +1,572 @@
+/* +/*
+ * Wine Driver for PulseAudio - WaveIn Functionality + * Wine Driver for PulseAudio - WaveIn Functionality
+ * http://pulseaudio.org/ + * http://pulseaudio.org/
@ -1608,11 +1555,13 @@ index 0000000..7024ccd
+ size_t size; + size_t size;
+ while (lpWaveHdr && wwi->state == WINE_WS_PLAYING && wwi->buffer) { + while (lpWaveHdr && wwi->state == WINE_WS_PLAYING && wwi->buffer) {
+ size = min(wwi->buffer_length - wwi->buffer_read_offset, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded); + size = min(wwi->buffer_length - wwi->buffer_read_offset, lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded);
+ if (size == 0) { ERR("Size is 0! buffer is full but not freed?\n"); continue; } + if (size == 0) ERR("Size is 0! buffer is full but not freed?\n");
+ memcpy(lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, (PBYTE)wwi->buffer + wwi->buffer_read_offset, size); + memcpy(lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded, (PBYTE)wwi->buffer + wwi->buffer_read_offset, size);
+ wwi->buffer_read_offset += size; + wwi->buffer_read_offset += size;
+ if (wwi->buffer_read_offset == wwi->buffer_length) { + if (wwi->buffer_read_offset == wwi->buffer_length) {
+ pa_threaded_mainloop_lock(PULSE_ml);
+ pa_stream_drop(wwi->stream); + pa_stream_drop(wwi->stream);
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ wwi->buffer = NULL; + wwi->buffer = NULL;
+ wwi->buffer_length = 0; + wwi->buffer_length = 0;
+ wwi->buffer_read_offset = 0; + wwi->buffer_read_offset = 0;
@ -1634,19 +1583,20 @@ index 0000000..7024ccd
+* Switches the current fragment to the next based upon a message from the +* Switches the current fragment to the next based upon a message from the
+* server. +* server.
+*/ +*/
+static void widRecorder_NextFragment(WINE_WAVEINST *wwi, size_t size) { +static void widRecorder_NextFragment(WINE_WAVEINST *wwi, size_t sizer) {
+ LPWAVEHDR lpWaveHdr = wwi->lpQueuePtr;
+ size_t request = 0;
+
+ for (;lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext)
+ request += lpWaveHdr->dwBufferLength;
+
+ lpWaveHdr = wwi->lpQueuePtr;
+ pa_threaded_mainloop_lock(PULSE_ml);
+ pa_stream_peek(wwi->stream, &wwi->buffer, &request);
+ wwi->buffer_length = request;
+ pa_threaded_mainloop_unlock(PULSE_ml);
+
+ widRecorder_CopyData(wwi); + widRecorder_CopyData(wwi);
+ if (wwi->buffer) {
+ if (wwi->buffer_read_offset != wwi->buffer_length)
+ ERR("We didn't read all of the data, there will be gaps. FO:%u, FS: %u\n", wwi->buffer_read_offset, wwi->buffer_length);
+ pa_stream_drop(wwi->stream);
+ wwi->buffer = NULL;
+ wwi->buffer_length = 0;
+ wwi->buffer_read_offset = 0;
+ }
+ pa_stream_peek(wwi->stream, &wwi->buffer, &size);
+ wwi->buffer_length = size;
+ wwi->buffer_read_offset = 0;
+} +}
+ +
+/************************************************************************** +/**************************************************************************
@ -1672,12 +1622,12 @@ index 0000000..7024ccd
+ SetEvent(ev); + SetEvent(ev);
+ if (wwi->state == WINE_WS_PLAYING) + if (wwi->state == WINE_WS_PLAYING)
+ widRecorder_NextFragment(wwi, param); + widRecorder_NextFragment(wwi, param);
+ else
+ (pa_stream_drop(wwi->stream));
+ break; + break;
+ case WINE_WM_STARTING: + case WINE_WM_STARTING:
+ wwi->state = WINE_WS_PLAYING; + wwi->state = WINE_WS_PLAYING;
+ pa_threaded_mainloop_lock(PULSE_ml);
+ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 0, PULSE_StreamSuccessCallback, NULL)); + PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 0, PULSE_StreamSuccessCallback, NULL));
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ SetEvent(ev); + SetEvent(ev);
+ break; + break;
+ case WINE_WM_HEADER: + case WINE_WM_HEADER:
@ -1693,8 +1643,10 @@ index 0000000..7024ccd
+ break; + break;
+ case WINE_WM_STOPPING: + case WINE_WM_STOPPING:
+ if (wwi->state != WINE_WS_STOPPED) { + if (wwi->state != WINE_WS_STOPPED) {
+ pa_threaded_mainloop_lock(PULSE_ml);
+ PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL)); + PULSE_WaitForOperation(pa_stream_cork(wwi->stream, 1, PULSE_StreamSuccessCallback, NULL));
+ pa_stream_drop(wwi->stream); + pa_stream_drop(wwi->stream);
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ +
+ /* return current buffer to app */ + /* return current buffer to app */
+ lpWaveHdr = wwi->lpQueuePtr; + lpWaveHdr = wwi->lpQueuePtr;
@ -1711,24 +1663,28 @@ index 0000000..7024ccd
+ SetEvent(ev); + SetEvent(ev);
+ break; + break;
+ case WINE_WM_RESETTING: + case WINE_WM_RESETTING:
+ if (wwi->state != WINE_WS_STOPPED) + if (wwi->state != WINE_WS_STOPPED) {
+ pa_threaded_mainloop_lock(PULSE_ml);
+ pa_stream_drop(wwi->stream); + pa_stream_drop(wwi->stream);
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ }
+ wwi->state = WINE_WS_STOPPED; + wwi->state = WINE_WS_STOPPED;
+ +
+ /* return all buffers to the app */ + /* return all buffers to the app */
+ for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) { + for (lpWaveHdr = wwi->lpQueuePtr; lpWaveHdr; lpWaveHdr = wwi->lpQueuePtr) {
+ TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext); + TRACE("reset %p %p\n", lpWaveHdr, lpWaveHdr->lpNext);
+ lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
+ lpWaveHdr->dwFlags |= WHDR_DONE; + lpWaveHdr->dwFlags |= WHDR_DONE;
+ wwi->lpQueuePtr = lpWaveHdr->lpNext; + wwi->lpQueuePtr = lpWaveHdr->lpNext;
+ widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0); + widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
+ } + }
+
+ wwi->lpQueuePtr = NULL; + wwi->lpQueuePtr = NULL;
+ SetEvent(ev); + SetEvent(ev);
+ break; + break;
+ case WINE_WM_XRUN: + case WINE_WM_XRUN:
+ pa_threaded_mainloop_lock(PULSE_ml);
+ pa_stream_drop(wwi->stream); + pa_stream_drop(wwi->stream);
+ pa_threaded_mainloop_unlock(PULSE_ml);
+ wwi->buffer_read_offset = 0; + wwi->buffer_read_offset = 0;
+ break; + break;
+ case WINE_WM_CLOSING: + case WINE_WM_CLOSING:
@ -1754,10 +1710,7 @@ index 0000000..7024ccd
+ break; + break;
+ } + }
+ } + }
+ + } /* for (;;) */
+ widRecorder_CopyData(wwi);
+
+} /* for (;;) */
+} +}
+ +
+/************************************************************************** +/**************************************************************************
@ -1822,7 +1775,11 @@ index 0000000..7024ccd
+ +
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+ TRACE("Asking to open %s for recording.\n", wdi->device_name); + TRACE("Asking to open %s for recording.\n", wdi->device_name);
+ pa_stream_connect_record(wwi->stream, wdi->device_name, NULL, PA_STREAM_START_CORKED | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING); + pa_stream_connect_record(wwi->stream, wdi->device_name, NULL,
+ PA_STREAM_START_CORKED |
+ PA_STREAM_AUTO_TIMING_UPDATE |
+ PA_STREAM_INTERPOLATE_TIMING);
+
+ for (;;) { + for (;;) {
+ pa_context_state_t cstate = pa_context_get_state(PULSE_context); + pa_context_state_t cstate = pa_context_get_state(PULSE_context);
+ pa_stream_state_t sstate = pa_stream_get_state(wwi->stream); + pa_stream_state_t sstate = pa_stream_get_state(wwi->stream);
@ -2007,8 +1964,6 @@ index 0000000..7024ccd
+ if (pa_context_get_state(PULSE_context) != PA_CONTEXT_READY) + if (pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
+ return 0; + return 0;
+ +
+ PULSE_UpdateWavedevs(PULSE_IN_DEVS);
+
+ return PULSE_WidNumDevs; + return PULSE_WidNumDevs;
+} +}
+ +
@ -2038,6 +1993,15 @@ index 0000000..7024ccd
+} +}
+ +
+/************************************************************************** +/**************************************************************************
+ * widDsDesc [internal]
+ */
+DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
+{
+ *desc = WInDev[wDevID].ds_desc;
+ return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ * widMessage (WINEPULSE.@) + * widMessage (WINEPULSE.@)
+ */ + */
+DWORD WINAPI PULSE_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser, +DWORD WINAPI PULSE_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
@ -2063,8 +2027,8 @@ index 0000000..7024ccd
+ case WIDM_STOP: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STOPPING); + case WIDM_STOP: return widRecorderMessage((WINE_WAVEINST*)dwUser, WINE_WM_STOPPING);
+ case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1); + case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize (wDevID, (LPDWORD)dwParam1);
+ case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2); + case DRV_QUERYDEVICEINTERFACE: return widDevInterface (wDevID, (PWCHAR)dwParam1, dwParam2);
+ case DRV_QUERYDSOUNDIFACE: return 0; + case DRV_QUERYDSOUNDIFACE: return MMSYSERR_NOTSUPPORTED; /* Use emulation, as there is no advantage */
+ case DRV_QUERYDSOUNDDESC: return 0; + case DRV_QUERYDSOUNDDESC: return widDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
+ default: + default:
+ FIXME("unknown message %d!\n", wMsg); + FIXME("unknown message %d!\n", wMsg);
+ } + }
@ -2085,10 +2049,10 @@ index 0000000..7024ccd
+#endif /* HAVE_PULSEAUDIO */ +#endif /* HAVE_PULSEAUDIO */
diff --git a/dlls/winepulse.drv/waveout.c b/dlls/winepulse.drv/waveout.c diff --git a/dlls/winepulse.drv/waveout.c b/dlls/winepulse.drv/waveout.c
new file mode 100644 new file mode 100644
index 0000000..968d1bd index 0000000..4539103
--- /dev/null --- /dev/null
+++ b/dlls/winepulse.drv/waveout.c +++ b/dlls/winepulse.drv/waveout.c
@@ -0,0 +1,1098 @@ @@ -0,0 +1,1092 @@
+/* +/*
+ * Wine Driver for PulseAudio - WaveOut Functionality + * Wine Driver for PulseAudio - WaveOut Functionality
+ * http://pulseaudio.org/ + * http://pulseaudio.org/
@ -2327,7 +2291,7 @@ index 0000000..968d1bd
+ wwo->buffer_attr.prebuf = (uint32_t) -1; + wwo->buffer_attr.prebuf = (uint32_t) -1;
+ wwo->buffer_attr.minreq = (uint32_t) -1; + wwo->buffer_attr.minreq = (uint32_t) -1;
+ wwo->buffer_attr.maxlength = (uint32_t) -1; + wwo->buffer_attr.maxlength = (uint32_t) -1;
+ WARN("Asking for new buffer tlength of %u.\n", wwo->buffer_attr.tlength); + WARN("Asking for new buffer tlength of %ums (%u bytes)\n", (unsigned int)(pa_bytes_to_usec(wwo->buffer_attr.tlength, &wwo->sample_spec)/1000), wwo->buffer_attr.tlength);
+ pa_stream_set_buffer_attr(wwo->stream, &wwo->buffer_attr, PULSE_StreamSuccessCallback, wwo); + pa_stream_set_buffer_attr(wwo->stream, &wwo->buffer_attr, PULSE_StreamSuccessCallback, wwo);
+ } else { + } else {
+ /* Fake playback start earlier, introducing latency */ + /* Fake playback start earlier, introducing latency */
@ -2702,6 +2666,7 @@ index 0000000..968d1bd
+ WINE_WAVEDEV *wdo; + WINE_WAVEDEV *wdo;
+ WINE_WAVEINST *wwo = NULL; + WINE_WAVEINST *wwo = NULL;
+ DWORD ret = MMSYSERR_NOERROR; + DWORD ret = MMSYSERR_NOERROR;
+ pa_stream_flags_t stream_flags;
+ +
+ TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags); + TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
+ if (lpDesc == NULL) { + if (lpDesc == NULL) {
@ -2760,27 +2725,21 @@ index 0000000..968d1bd
+ pa_stream_set_moved_callback (wwo->stream, PULSE_StreamMovedCallback, wwo); + pa_stream_set_moved_callback (wwo->stream, PULSE_StreamMovedCallback, wwo);
+ pa_stream_set_suspended_callback (wwo->stream, PULSE_StreamSuspendedCallback, wwo); + pa_stream_set_suspended_callback (wwo->stream, PULSE_StreamSuspendedCallback, wwo);
+ +
+ stream_flags = PA_STREAM_AUTO_TIMING_UPDATE;
+
+#if PA_API_VERSION >= 12 +#if PA_API_VERSION >= 12
+ if (pa_context_get_server_protocol_version(PULSE_context) >= 15) { + if (pa_context_get_server_protocol_version(PULSE_context) >= 15) {
+ pa_stream_set_started_callback(wwo->stream, WAVEOUT_StreamStartedCallback, wwo); + pa_stream_set_started_callback(wwo->stream, WAVEOUT_StreamStartedCallback, wwo);
+ stream_flags |= PA_STREAM_ADJUST_LATENCY;
+ } else + } else
+#endif +#endif
+ {
+ pa_stream_set_latency_update_callback(wwo->stream, WAVEOUT_StreamTimingInfoUpdateCallback, wwo); + pa_stream_set_latency_update_callback(wwo->stream, WAVEOUT_StreamTimingInfoUpdateCallback, wwo);
+ + }
+ +
+ TRACE("Connecting stream for playback on %s.\n", wdo->device_name); + TRACE("Connecting stream for playback on %s.\n", wdo->device_name);
+ pa_threaded_mainloop_lock(PULSE_ml); + pa_threaded_mainloop_lock(PULSE_ml);
+ pa_stream_connect_playback(wwo->stream, + pa_stream_connect_playback(wwo->stream, wdo->device_name, NULL, stream_flags, NULL, NULL);
+ /* Use WAVE_FORMAT_DIRECT to detect if we are being called by the
+ * wavemapper, in which case don't specify a device so that libpulse
+ * chooses based upon environment variables, x11 root window info, etc. If
+ * WAVE_FORMAT_DIRECT is inappropriate, maybe winmm could stop eating
+ * WAVE_MAPPER? */
+ dwFlags & WAVE_FORMAT_DIRECT ? NULL : wdo->device_name,
+ NULL,
+ PA_STREAM_AUTO_TIMING_UPDATE,
+ NULL,
+ NULL);
+ +
+ for (;;) { + for (;;) {
+ pa_context_state_t cstate = pa_context_get_state(PULSE_context); + pa_context_state_t cstate = pa_context_get_state(PULSE_context);
@ -2978,7 +2937,6 @@ index 0000000..968d1bd
+ if (!PULSE_ml || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY) + if (!PULSE_ml || !PULSE_context || pa_context_get_state(PULSE_context) != PA_CONTEXT_READY)
+ return 0; + return 0;
+ +
+ PULSE_UpdateWavedevs(PULSE_OUT_DEVS);
+ return PULSE_WodNumDevs; + return PULSE_WodNumDevs;
+} +}
+ +
@ -3057,7 +3015,7 @@ index 0000000..968d1bd
+ } else { + } else {
+ if (value1 != value2) FIXME("Non-stereo streams can't pan!\n"); + if (value1 != value2) FIXME("Non-stereo streams can't pan!\n");
+ wwo->volume.channels = wwo->sample_spec.channels; + wwo->volume.channels = wwo->sample_spec.channels;
+ pa_cvolume_set(&wwo->volume, wwo->volume.channels, pa_sw_volume_from_dB(MAX(value1, value2))); + pa_cvolume_set(&wwo->volume, wwo->volume.channels, pa_sw_volume_from_dB(max(value1, value2)));
+ } + }
+ +
+ if (TRACE_ON(wave)) { + if (TRACE_ON(wave)) {
@ -3198,13 +3156,13 @@ index 0000000..1b49460
+@ stdcall -private widMessage(long long long long long long) PULSE_widMessage +@ 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 diff --git a/dlls/winepulse.drv/winepulse.h b/dlls/winepulse.drv/winepulse.h
new file mode 100644 new file mode 100644
index 0000000..27690d3 index 0000000..59fbb38
--- /dev/null --- /dev/null
+++ b/dlls/winepulse.drv/winepulse.h +++ b/dlls/winepulse.drv/winepulse.h
@@ -0,0 +1,232 @@ @@ -0,0 +1,228 @@
+/* Definitions for PulseAudio Wine Driver +/* Definitions for PulseAudio Wine Driver
+ * + *
+ * Copyright 2008 Arthur Taylor + * Copyright 2009 Arthur Taylor <theycallhimart@gmail.com>
+ * + *
+ * This library is free software; you can redistribute it and/or + * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public + * modify it under the terms of the GNU Lesser General Public
@ -3262,10 +3220,6 @@ index 0000000..27690d3
+#define WINE_WS_CLOSED 4 +#define WINE_WS_CLOSED 4
+#define WINE_WS_FAILED 5 +#define WINE_WS_FAILED 5
+ +
+#define PULSE_OUT_DEVS 0x1
+#define PULSE_IN_DEVS 0x2
+#define PULSE_ALL_DEVS PULSE_IN_DEVS | PULSE_OUT_DEVS
+
+#define PULSE_ALL_FORMATS \ +#define PULSE_ALL_FORMATS \
+ WAVE_FORMAT_1M08 | /* Mono 11025Hz 8-bit */\ + WAVE_FORMAT_1M08 | /* Mono 11025Hz 8-bit */\
+ WAVE_FORMAT_1M16 | /* Mono 11025Hz 16-bit */\ + WAVE_FORMAT_1M16 | /* Mono 11025Hz 16-bit */\
@ -3338,10 +3292,11 @@ index 0000000..27690d3
+ pa_sample_spec sample_spec; + pa_sample_spec sample_spec;
+ pa_cvolume volume; + pa_cvolume volume;
+ +
+ PBYTE buffer; /* Pointer to the latest data fragment for recording streams */ + PBYTE buffer;
+ size_t buffer_length; /* How large the latest data fragment is */ + DWORD buffer_length;
+ size_t buffer_read_offset; /* How far into latest data fragment we last read */ + DWORD buffer_read_offset;
+ size_t fraglen; + DWORD buffer_play_offset;
+ DWORD fraglen;
+}; +};
+ +
+/* Per-playback/record device */ +/* Per-playback/record device */
@ -3388,9 +3343,9 @@ index 0000000..27690d3
+ +
+ /* waveIn */ + /* waveIn */
+ const void *buffer; /* Pointer to the latest data fragment for recording streams */ + const void *buffer; /* Pointer to the latest data fragment for recording streams */
+ size_t buffer_length; /* How large the latest data fragment is */ + DWORD buffer_length; /* How large the latest data fragment is */
+ size_t buffer_read_offset; /* How far into latest data fragment we last read */ + DWORD buffer_read_offset; /* How far into latest data fragment we last read */
+ size_t fraglen; + DWORD fraglen;
+ +
+ /* Thread communication and synchronization stuff */ + /* Thread communication and synchronization stuff */
+ HANDLE hStartUpEvent; + HANDLE hStartUpEvent;
@ -3428,7 +3383,6 @@ index 0000000..27690d3
+int PULSE_AddRingMessage(PULSE_MSG_RING* omr, enum win_wm_message msg, DWORD param, BOOL wait); +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); +int PULSE_RetrieveRingMessage(PULSE_MSG_RING* omr, enum win_wm_message *msg, DWORD *param, HANDLE *hEvent);
+const char * PULSE_getCmdString(enum win_wm_message msg); +const char * PULSE_getCmdString(enum win_wm_message msg);
+BOOL PULSE_UpdateWavedevs(int devices);
+ +
+/* dsoutput.c */ +/* dsoutput.c */
+DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv); +DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
Loading…
Cancel
Save