mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Rebase against 8f3bd63b52f03ff05e9d2a00a2e129a0b0092969.
This commit is contained in:
parent
28fad42582
commit
7d08bb86e1
@ -1,4 +1,4 @@
|
||||
From f058e0e1425aab869a1a7d0db0446944af9bc8d6 Mon Sep 17 00:00:00 2001
|
||||
From 51cde3dff5de27d1aebc964a4802758534d56773 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 5 Aug 2017 03:39:55 +0200
|
||||
Subject: [PATCH] ntdll: Implement process token elevation through manifests.
|
||||
@ -74,7 +74,7 @@ index 6290cbcb4e6..9a8f13901b2 100644
|
||||
RemoveEntryList( &wm->ldr.InLoadOrderLinks );
|
||||
InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderLinks );
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index 7875db09801..d7334ffc959 100644
|
||||
index fa8495511e0..df72efdecc8 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -1086,6 +1086,14 @@ int set_process_debug_flag( struct process *process, int flag )
|
||||
@ -93,7 +93,7 @@ index 7875db09801..d7334ffc959 100644
|
||||
DECL_HANDLER(new_process)
|
||||
{
|
||||
diff --git a/server/process.h b/server/process.h
|
||||
index 3944a67d571..3cbf70fda21 100644
|
||||
index 0fdf070b78e..43e8cc1ad7e 100644
|
||||
--- a/server/process.h
|
||||
+++ b/server/process.h
|
||||
@@ -129,6 +129,7 @@ extern void kill_console_processes( struct thread *renderer, int exit_code );
|
||||
@ -103,12 +103,12 @@ index 3944a67d571..3cbf70fda21 100644
|
||||
+extern void replace_process_token( struct process *process, struct token *token );
|
||||
|
||||
/* console functions */
|
||||
extern obj_handle_t inherit_console( struct thread *parent_thread, struct process *parent,
|
||||
extern obj_handle_t inherit_console( struct thread *parent_thread, obj_handle_t handle,
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index b84d1d10004..65bcb99d486 100644
|
||||
index a9308904afc..8c40fba8d0a 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3526,6 +3526,13 @@ struct handle_info
|
||||
@@ -3489,6 +3489,13 @@ struct handle_info
|
||||
@END
|
||||
|
||||
|
||||
@ -145,5 +145,5 @@ index 970ed1838da..1c1d49989b3 100644
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.27.0
|
||||
2.28.0
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
From bb72b7bf3df86b284c169125e52d6e385ff46cbc Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Tue, 2 Feb 2016 12:53:47 +0800
|
||||
Subject: [PATCH] ole32: Add a check for hglobal pointer to
|
||||
GetHGlobalFromStream.
|
||||
|
||||
---
|
||||
dlls/ole32/hglobalstream.c | 4 ++--
|
||||
dlls/ole32/tests/hglobalstream.c | 6 ++++++
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ole32/hglobalstream.c b/dlls/ole32/hglobalstream.c
|
||||
index 4590bb9c431..4cfedd66a1b 100644
|
||||
--- a/dlls/ole32/hglobalstream.c
|
||||
+++ b/dlls/ole32/hglobalstream.c
|
||||
@@ -664,10 +664,10 @@ HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)
|
||||
{
|
||||
HGLOBALStreamImpl* pStream;
|
||||
|
||||
- if (pstm == NULL)
|
||||
+ if (!pstm || !phglobal)
|
||||
return E_INVALIDARG;
|
||||
|
||||
- pStream = (HGLOBALStreamImpl*) pstm;
|
||||
+ pStream = impl_from_IStream(pstm);
|
||||
|
||||
/*
|
||||
* Verify that the stream object was created with CreateStreamOnHGlobal.
|
||||
diff --git a/dlls/ole32/tests/hglobalstream.c b/dlls/ole32/tests/hglobalstream.c
|
||||
index 2f386914afc..5bcf9abfbda 100644
|
||||
--- a/dlls/ole32/tests/hglobalstream.c
|
||||
+++ b/dlls/ole32/tests/hglobalstream.c
|
||||
@@ -561,6 +561,12 @@ static void test_IStream_Clone(void)
|
||||
hr = CreateStreamOnHGlobal(orig_hmem, TRUE, &stream);
|
||||
ok(hr == S_OK, "unexpected %#x\n", hr);
|
||||
|
||||
+ hr = GetHGlobalFromStream(stream, NULL);
|
||||
+ ok(hr == E_INVALIDARG, "unexpected %#x\n", hr);
|
||||
+
|
||||
+ hr = GetHGlobalFromStream(NULL, &hmem);
|
||||
+ ok(hr == E_INVALIDARG, "unexpected %#x\n", hr);
|
||||
+
|
||||
stream_info(stream, &hmem, &size, &pos);
|
||||
ok(hmem == orig_hmem, "handles should match\n");
|
||||
ok(size == 0, "unexpected %d\n", size);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -52,7 +52,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "019fcaa36410f5b52e9c3fb90a621b56a4f10f35"
|
||||
echo "8f3bd63b52f03ff05e9d2a00a2e129a0b0092969"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
@ -205,7 +205,6 @@ patch_enable_all ()
|
||||
enable_nvcuda_CUDA_Support="$1"
|
||||
enable_nvcuvid_CUDA_Video_Support="$1"
|
||||
enable_nvencodeapi_Video_Encoder="$1"
|
||||
enable_ole32_HGLOBALStream="$1"
|
||||
enable_oleaut32_CreateTypeLib="$1"
|
||||
enable_oleaut32_Load_Save_EMF="$1"
|
||||
enable_oleaut32_OLEPictureImpl_SaveAsFile="$1"
|
||||
@ -706,9 +705,6 @@ patch_enable ()
|
||||
nvencodeapi-Video_Encoder)
|
||||
enable_nvencodeapi_Video_Encoder="$2"
|
||||
;;
|
||||
ole32-HGLOBALStream)
|
||||
enable_ole32_HGLOBALStream="$2"
|
||||
;;
|
||||
oleaut32-CreateTypeLib)
|
||||
enable_oleaut32_CreateTypeLib="$2"
|
||||
;;
|
||||
@ -4196,18 +4192,6 @@ if test "$enable_nvencodeapi_Video_Encoder" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ole32-HGLOBALStream
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ole32/hglobalstream.c, dlls/ole32/tests/hglobalstream.c
|
||||
# |
|
||||
if test "$enable_ole32_HGLOBALStream" -eq 1; then
|
||||
patch_apply ole32-HGLOBALStream/0002-ole32-Add-a-check-for-hglobal-pointer-to-GetHGlobalF.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Dmitry Timoshkov", "ole32: Add a check for hglobal pointer to GetHGlobalFromStream.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset oleaut32-CreateTypeLib
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
@ -5966,39 +5950,22 @@ fi
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#37042] Implement exclusive mode in PulseAudio backend
|
||||
# | * [#28282] Sound constantly crackling in a lot of games
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/winepulse.drv/Makefile.in, dlls/winepulse.drv/mmdevdrv.c
|
||||
# |
|
||||
if test "$enable_winepulse_PulseAudio_Support" -eq 1; then
|
||||
patch_apply winepulse-PulseAudio_Support/0001-winepulse.drv-Use-a-separate-mainloop-and-ctx-for-pu.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0002-winepulse-Don-t-rely-on-pulseaudio-callbacks-for-tim.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0003-winepulse-expose-audio-devices-directly-to-programs.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0004-winepulse-fix-segfault-in-pulse_rd_loop.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0005-winepulse-implement-GetPropValue.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0006-winepulse-fetch-actual-program-name-if-possible.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0007-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0008-winepulse-Fix-up-recording.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0009-winepulse.drv-Fix-getting-the-same-timing-info.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0010-winepulse-Update-last-time-on-underrun.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0011-winepulse-account-for-PA-devices-that-fall-way-behin.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0012-winepulse-Fix-local-buffer-offset-wrapping.patch
|
||||
patch_apply winepulse-PulseAudio_Support/0013-winepulse-Don-t-fake-being-one-period-behind-in-GetP.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "winepulse.drv: Use a separate mainloop and ctx for pulse_test_connect.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Don'\''t rely on pulseaudio callbacks for timing.", 1 },';
|
||||
printf '%s\n' '+ { "Mark Harmstone", "winepulse: Expose audio devices directly to programs.", 1 },';
|
||||
printf '%s\n' '+ { "Mark Harmstone", "winepulse: Fix segfault in pulse_rd_loop.", 1 },';
|
||||
printf '%s\n' '+ { "Mark Harmstone", "winepulse: Implement GetPropValue.", 1 },';
|
||||
printf '%s\n' '+ { "Mark Harmstone", "winepulse: Fetch actual program name if possible.", 1 },';
|
||||
printf '%s\n' '+ { "Mark Harmstone", "winepulse: Return PKEY_AudioEndpoint_PhysicalSpeakers device prop.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Fix up recording.", 1 },';
|
||||
printf '%s\n' '+ { "Zhiyi Zhang", "winepulse.drv: Fix getting the same timing info.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Update last time on underrun.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Account for PA devices that fall way behind.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Fix local buffer offset wrapping.", 1 },';
|
||||
printf '%s\n' '+ { "Andrew Eikum", "winepulse: Don'\''t fake being one period behind in GetPosition.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
@ -1,873 +0,0 @@
|
||||
From 27c55ba097430b8e245b2e0d2f2077580196ba0c Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Fri, 3 Jan 2020 18:14:03 +1100
|
||||
Subject: [PATCH] winepulse: Don't rely on pulseaudio callbacks for timing
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 521 +++++++++++++++-------------------
|
||||
1 file changed, 236 insertions(+), 285 deletions(-)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index ef9fc34e405..7d6327d2fe8 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -172,13 +172,16 @@ struct ACImpl {
|
||||
EDataFlow dataflow;
|
||||
DWORD flags;
|
||||
AUDCLNT_SHAREMODE share;
|
||||
- HANDLE event;
|
||||
+ HANDLE event, timer;
|
||||
|
||||
INT32 locked;
|
||||
- UINT32 bufsize_frames, bufsize_bytes, capture_period, pad, started, peek_ofs, wri_offs_bytes, lcl_offs_bytes;
|
||||
- UINT32 tmp_buffer_bytes, held_bytes, peek_len, peek_buffer_len;
|
||||
+ UINT32 bufsize_frames, real_bufsize_bytes, period_bytes;
|
||||
+ UINT32 started, peek_ofs, read_offs_bytes, lcl_offs_bytes, pa_offs_bytes;
|
||||
+ UINT32 tmp_buffer_bytes, held_bytes, peek_len, peek_buffer_len, pa_held_bytes;
|
||||
BYTE *local_buffer, *tmp_buffer, *peek_buffer;
|
||||
void *locked_ptr;
|
||||
+ BOOL please_quit, just_started, just_underran;
|
||||
+ pa_usec_t last_time, mmdev_period_usec;
|
||||
|
||||
pa_stream *stream;
|
||||
pa_sample_spec ss;
|
||||
@@ -704,18 +707,7 @@ static void silence_buffer(pa_sample_format_t format, BYTE *buffer, UINT32 bytes
|
||||
memset(buffer, format == PA_SAMPLE_U8 ? 0x80 : 0, bytes);
|
||||
}
|
||||
|
||||
-static void pulse_free_noop(void *buf)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
-enum write_buffer_flags
|
||||
-{
|
||||
- WINEPULSE_WRITE_NOFREE = 0x01,
|
||||
- WINEPULSE_WRITE_SILENT = 0x02
|
||||
-};
|
||||
-
|
||||
-static int write_buffer(const ACImpl *This, BYTE *buffer, UINT32 bytes,
|
||||
- enum write_buffer_flags flags)
|
||||
+static int write_buffer(const ACImpl *This, BYTE *buffer, UINT32 bytes)
|
||||
{
|
||||
float vol[PA_CHANNELS_MAX];
|
||||
BOOL adjust = FALSE;
|
||||
@@ -723,7 +715,7 @@ static int write_buffer(const ACImpl *This, BYTE *buffer, UINT32 bytes,
|
||||
BYTE *end;
|
||||
|
||||
if (!bytes) return 0;
|
||||
- if (This->session->mute || (flags & WINEPULSE_WRITE_SILENT))
|
||||
+ if (This->session->mute)
|
||||
{
|
||||
silence_buffer(This->ss.format, buffer, bytes);
|
||||
goto write;
|
||||
@@ -850,9 +842,7 @@ static int write_buffer(const ACImpl *This, BYTE *buffer, UINT32 bytes,
|
||||
}
|
||||
|
||||
write:
|
||||
- return pa_stream_write(This->stream, buffer, bytes,
|
||||
- (flags & WINEPULSE_WRITE_NOFREE) ? pulse_free_noop : NULL,
|
||||
- 0, PA_SEEK_RELATIVE);
|
||||
+ return pa_stream_write(This->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
|
||||
}
|
||||
|
||||
static void dump_attr(const pa_buffer_attr *attr) {
|
||||
@@ -875,107 +865,69 @@ static void pulse_attr_update(pa_stream *s, void *user) {
|
||||
dump_attr(attr);
|
||||
}
|
||||
|
||||
-/* Here's the buffer setup:
|
||||
- *
|
||||
- * vvvvvvvv sent to HW already
|
||||
- * vvvvvvvv in Pulse buffer but rewindable
|
||||
- * [dddddddddddddddd] Pulse buffer
|
||||
- * [dddddddddddddddd--------] mmdevapi buffer
|
||||
- * ^^^^^^^^^^^^^^^^ pad
|
||||
- * ^ lcl_offs_bytes
|
||||
- * ^^^^^^^^^ held_bytes
|
||||
- * ^ wri_offs_bytes
|
||||
- *
|
||||
- * GetCurrentPadding is pad
|
||||
- *
|
||||
- * During pulse_wr_callback, we decrement pad, fill Pulse buffer, and move
|
||||
- * lcl_offs forward
|
||||
- *
|
||||
- * During Stop, we flush the Pulse buffer
|
||||
- */
|
||||
-static void pulse_wr_callback(pa_stream *s, size_t bytes, void *userdata)
|
||||
+static void pulse_write(ACImpl *This)
|
||||
{
|
||||
- ACImpl *This = userdata;
|
||||
- UINT32 oldpad = This->pad;
|
||||
-
|
||||
- if(This->local_buffer){
|
||||
- UINT32 to_write;
|
||||
- BYTE *buf = This->local_buffer + This->lcl_offs_bytes;
|
||||
-
|
||||
- if(This->pad > bytes){
|
||||
- This->clock_written += bytes;
|
||||
- This->pad -= bytes;
|
||||
- }else{
|
||||
- This->clock_written += This->pad;
|
||||
- This->pad = 0;
|
||||
- }
|
||||
+ /* write as much data to PA as we can */
|
||||
+ UINT32 to_write;
|
||||
+ BYTE *buf = This->local_buffer + This->pa_offs_bytes;
|
||||
+ UINT32 bytes = pa_stream_writable_size(This->stream);
|
||||
|
||||
- bytes = min(bytes, This->held_bytes);
|
||||
-
|
||||
- if(This->lcl_offs_bytes + bytes > This->bufsize_bytes){
|
||||
- to_write = This->bufsize_bytes - This->lcl_offs_bytes;
|
||||
- TRACE("writing small chunk of %u bytes\n", to_write);
|
||||
- write_buffer(This, buf, to_write, 0);
|
||||
- This->held_bytes -= to_write;
|
||||
- to_write = bytes - to_write;
|
||||
- This->lcl_offs_bytes = 0;
|
||||
- buf = This->local_buffer;
|
||||
- }else
|
||||
- to_write = bytes;
|
||||
-
|
||||
- TRACE("writing main chunk of %u bytes\n", to_write);
|
||||
- write_buffer(This, buf, to_write, 0);
|
||||
- This->lcl_offs_bytes += to_write;
|
||||
- This->lcl_offs_bytes %= This->bufsize_bytes;
|
||||
- This->held_bytes -= to_write;
|
||||
- }else{
|
||||
- if (bytes < This->bufsize_bytes)
|
||||
- This->pad = This->bufsize_bytes - bytes;
|
||||
- else
|
||||
- This->pad = 0;
|
||||
-
|
||||
- if (oldpad == This->pad)
|
||||
- return;
|
||||
-
|
||||
- assert(oldpad > This->pad);
|
||||
+ if(This->just_underran){
|
||||
+ /* prebuffer with silence if needed */
|
||||
+ if(This->pa_held_bytes < bytes){
|
||||
+ to_write = bytes - This->pa_held_bytes;
|
||||
+ TRACE("prebuffering %u frames of silence\n",
|
||||
+ (int)(to_write / pa_frame_size(&This->ss)));
|
||||
+ buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, to_write);
|
||||
+ pa_stream_write(This->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
|
||||
+ HeapFree(GetProcessHeap(), 0, buf);
|
||||
+ }
|
||||
|
||||
- This->clock_written += oldpad - This->pad;
|
||||
- TRACE("New pad: %zu (-%zu)\n", This->pad / pa_frame_size(&This->ss), (oldpad - This->pad) / pa_frame_size(&This->ss));
|
||||
+ This->just_underran = FALSE;
|
||||
}
|
||||
|
||||
- if (This->event)
|
||||
- SetEvent(This->event);
|
||||
-}
|
||||
+ buf = This->local_buffer + This->pa_offs_bytes;
|
||||
+ TRACE("held: %u, avail: %u\n",
|
||||
+ This->pa_held_bytes, bytes);
|
||||
+ bytes = min(This->pa_held_bytes, bytes);
|
||||
+
|
||||
+ if(This->pa_offs_bytes + bytes > This->real_bufsize_bytes){
|
||||
+ to_write = This->real_bufsize_bytes - This->pa_offs_bytes;
|
||||
+ TRACE("writing small chunk of %u bytes\n", to_write);
|
||||
+ write_buffer(This, buf, to_write);
|
||||
+ This->pa_held_bytes -= to_write;
|
||||
+ to_write = bytes - to_write;
|
||||
+ This->pa_offs_bytes = 0;
|
||||
+ buf = This->local_buffer;
|
||||
+ }else
|
||||
+ to_write = bytes;
|
||||
|
||||
-static void pulse_underflow_callback(pa_stream *s, void *userdata)
|
||||
-{
|
||||
- WARN("Underflow\n");
|
||||
+ TRACE("writing main chunk of %u bytes\n", to_write);
|
||||
+ write_buffer(This, buf, to_write);
|
||||
+ This->pa_offs_bytes += to_write;
|
||||
+ This->pa_offs_bytes %= This->real_bufsize_bytes;
|
||||
+ This->pa_held_bytes -= to_write;
|
||||
}
|
||||
|
||||
-/* Latency is periodically updated even when nothing is played,
|
||||
- * because of PA_STREAM_AUTO_TIMING_UPDATE so use it as timer
|
||||
- *
|
||||
- * Perfect for passing all tests :)
|
||||
- */
|
||||
-static void pulse_latency_callback(pa_stream *s, void *userdata)
|
||||
+static void pulse_underflow_callback(pa_stream *s, void *userdata)
|
||||
{
|
||||
ACImpl *This = userdata;
|
||||
- if (!This->pad && This->event)
|
||||
- SetEvent(This->event);
|
||||
+ WARN("%p: Underflow\n", userdata);
|
||||
+ This->just_underran = TRUE;
|
||||
}
|
||||
|
||||
static void pulse_started_callback(pa_stream *s, void *userdata)
|
||||
{
|
||||
- TRACE("(Re)started playing\n");
|
||||
+ TRACE("%p: (Re)started playing\n", userdata);
|
||||
}
|
||||
|
||||
static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
{
|
||||
- while (bytes >= This->capture_period) {
|
||||
+ while (bytes >= This->period_bytes) {
|
||||
ACPacket *p, *next;
|
||||
LARGE_INTEGER stamp, freq;
|
||||
BYTE *dst, *src;
|
||||
- size_t src_len, copy, rem = This->capture_period;
|
||||
+ size_t src_len, copy, rem = This->period_bytes;
|
||||
if (!(p = (ACPacket*)list_head(&This->packet_free_head))) {
|
||||
p = (ACPacket*)list_head(&This->packet_filled_head);
|
||||
if (!p->discont) {
|
||||
@@ -983,11 +935,8 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
next->discont = 1;
|
||||
} else
|
||||
p = (ACPacket*)list_tail(&This->packet_filled_head);
|
||||
- assert(This->pad == This->bufsize_bytes);
|
||||
} else {
|
||||
- assert(This->pad < This->bufsize_bytes);
|
||||
- This->pad += This->capture_period;
|
||||
- assert(This->pad <= This->bufsize_bytes);
|
||||
+ This->held_bytes += This->period_bytes;
|
||||
}
|
||||
QueryPerformanceCounter(&stamp);
|
||||
QueryPerformanceFrequency(&freq);
|
||||
@@ -1008,12 +957,14 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
This->peek_ofs += copy;
|
||||
if(This->peek_len == This->peek_ofs)
|
||||
This->peek_len = 0;
|
||||
- } else {
|
||||
- pa_stream_peek(This->stream, (const void**)&src, &src_len);
|
||||
+ } else if (pa_stream_peek(This->stream, (const void**)&src, &src_len) == 0 && src_len) {
|
||||
|
||||
copy = min(rem, src_len);
|
||||
|
||||
- memcpy(dst, src, rem);
|
||||
+ if(src)
|
||||
+ memcpy(dst, src, copy);
|
||||
+ else
|
||||
+ silence_buffer(This->ss.format, dst, copy);
|
||||
|
||||
dst += copy;
|
||||
rem -= copy;
|
||||
@@ -1025,7 +976,11 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
This->peek_buffer_len = src_len;
|
||||
}
|
||||
|
||||
- memcpy(This->peek_buffer, src + copy, src_len - copy);
|
||||
+ if(src)
|
||||
+ memcpy(This->peek_buffer, src + copy, src_len - copy);
|
||||
+ else
|
||||
+ silence_buffer(This->ss.format, This->peek_buffer, src_len - copy);
|
||||
+
|
||||
This->peek_len = src_len - copy;
|
||||
This->peek_ofs = 0;
|
||||
}
|
||||
@@ -1034,21 +989,18 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
- bytes -= This->capture_period;
|
||||
+ bytes -= This->period_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void pulse_rd_drop(ACImpl *This, size_t bytes)
|
||||
{
|
||||
- while (bytes >= This->capture_period) {
|
||||
- size_t src_len, copy, rem = This->capture_period;
|
||||
+ while (bytes >= This->period_bytes) {
|
||||
+ size_t src_len, copy, rem = This->period_bytes;
|
||||
while (rem) {
|
||||
const void *src;
|
||||
pa_stream_peek(This->stream, &src, &src_len);
|
||||
- assert(src_len);
|
||||
- assert(This->peek_ofs < src_len);
|
||||
src_len -= This->peek_ofs;
|
||||
- assert(src_len <= bytes);
|
||||
|
||||
copy = rem;
|
||||
if (copy > src_len)
|
||||
@@ -1067,23 +1019,95 @@ static void pulse_rd_drop(ACImpl *This, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
-static void pulse_rd_callback(pa_stream *s, size_t bytes, void *userdata)
|
||||
+static void pulse_read(ACImpl *This)
|
||||
{
|
||||
- ACImpl *This = userdata;
|
||||
-
|
||||
- TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(s)->fragsize);
|
||||
- assert(bytes >= This->peek_ofs);
|
||||
+ size_t bytes = pa_stream_readable_size(This->stream);
|
||||
+ TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(This->stream)->fragsize);
|
||||
bytes -= This->peek_ofs;
|
||||
- if (bytes < This->capture_period)
|
||||
+ if (bytes < This->period_bytes)
|
||||
return;
|
||||
|
||||
if (This->started)
|
||||
pulse_rd_loop(This, bytes);
|
||||
else
|
||||
pulse_rd_drop(This, bytes);
|
||||
+}
|
||||
+
|
||||
+static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
+{
|
||||
+ DWORD delay;
|
||||
+ UINT32 adv_bytes;
|
||||
+ ACImpl *This = user;
|
||||
+
|
||||
+ pthread_mutex_lock(&pulse_lock);
|
||||
+ delay = This->mmdev_period_usec / 1000;
|
||||
+ pa_stream_get_time(This->stream, &This->last_time);
|
||||
+ pthread_mutex_unlock(&pulse_lock);
|
||||
+
|
||||
+ while(!This->please_quit){
|
||||
+ pa_usec_t now, adv_usec = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ Sleep(delay);
|
||||
+
|
||||
+ pthread_mutex_lock(&pulse_lock);
|
||||
+
|
||||
+ delay = This->mmdev_period_usec / 1000;
|
||||
+
|
||||
+ err = pa_stream_get_time(This->stream, &now);
|
||||
+ if(err == 0){
|
||||
+ TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(This->last_time));
|
||||
+ if(This->started && (This->dataflow == eCapture || This->held_bytes)){
|
||||
+ if(This->just_started){
|
||||
+ /* let it play out a period to absorb some latency and get accurate timing */
|
||||
+ pa_usec_t diff = now - This->last_time;
|
||||
+
|
||||
+ if(diff > This->mmdev_period_usec){
|
||||
+ This->just_started = FALSE;
|
||||
+ This->last_time = now;
|
||||
+ }
|
||||
+ }else{
|
||||
+ INT32 adjust = This->last_time + This->mmdev_period_usec - now;
|
||||
+
|
||||
+ adv_usec = now - This->last_time;
|
||||
+
|
||||
+ if(adjust > ((INT32)(This->mmdev_period_usec / 2)))
|
||||
+ adjust = This->mmdev_period_usec / 2;
|
||||
+ else if(adjust < -((INT32)(This->mmdev_period_usec / 2)))
|
||||
+ adjust = -1 * This->mmdev_period_usec / 2;
|
||||
+
|
||||
+ delay = (This->mmdev_period_usec + adjust) / 1000;
|
||||
+
|
||||
+ This->last_time += This->mmdev_period_usec;
|
||||
+ }
|
||||
+
|
||||
+ if(This->dataflow == eRender){
|
||||
+ pulse_write(This);
|
||||
+
|
||||
+ /* regardless of what PA does, advance one period */
|
||||
+ adv_bytes = min(This->period_bytes, This->held_bytes);
|
||||
+ This->lcl_offs_bytes += adv_bytes;
|
||||
+ This->held_bytes -= adv_bytes;
|
||||
+ }else if(This->dataflow == eCapture){
|
||||
+ pulse_read(This);
|
||||
+ }
|
||||
+ }else{
|
||||
+ This->last_time = now;
|
||||
+ delay = This->mmdev_period_usec / 1000;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (This->event)
|
||||
+ SetEvent(This->event);
|
||||
|
||||
- if (This->event)
|
||||
- SetEvent(This->event);
|
||||
+ TRACE("%p after update, adv usec: %d, held: %u, delay: %u\n",
|
||||
+ This, (int)adv_usec,
|
||||
+ (int)(This->held_bytes/ pa_frame_size(&This->ss)), delay);
|
||||
+
|
||||
+ pthread_mutex_unlock(&pulse_lock);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
@@ -1112,15 +1136,16 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
|
||||
/* PulseAudio will fill in correct values */
|
||||
attr.minreq = attr.fragsize = period_bytes;
|
||||
- attr.maxlength = attr.tlength = This->bufsize_bytes;
|
||||
+ attr.tlength = period_bytes * 3;
|
||||
+ attr.maxlength = This->bufsize_frames * pa_frame_size(&This->ss);
|
||||
attr.prebuf = pa_frame_size(&This->ss);
|
||||
dump_attr(&attr);
|
||||
if (This->dataflow == eRender)
|
||||
ret = pa_stream_connect_playback(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_EARLY_REQUESTS, NULL, NULL);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY, NULL, NULL);
|
||||
else
|
||||
ret = pa_stream_connect_record(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_EARLY_REQUESTS);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY);
|
||||
if (ret < 0) {
|
||||
WARN("Returns %i\n", ret);
|
||||
return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
|
||||
@@ -1131,11 +1156,9 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
|
||||
|
||||
if (This->dataflow == eRender) {
|
||||
- pa_stream_set_write_callback(This->stream, pulse_wr_callback, This);
|
||||
pa_stream_set_underflow_callback(This->stream, pulse_underflow_callback, This);
|
||||
pa_stream_set_started_callback(This->stream, pulse_started_callback, This);
|
||||
- } else
|
||||
- pa_stream_set_read_callback(This->stream, pulse_rd_callback, This);
|
||||
+ }
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1270,6 +1293,11 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
|
||||
TRACE("(%p) Refcount now %u\n", This, ref);
|
||||
if (!ref) {
|
||||
if (This->stream) {
|
||||
+ if(This->timer){
|
||||
+ This->please_quit = TRUE;
|
||||
+ WaitForSingleObject(This->timer, INFINITE);
|
||||
+ CloseHandle(This->timer);
|
||||
+ }
|
||||
pthread_mutex_lock(&pulse_lock);
|
||||
if (PA_STREAM_IS_GOOD(pa_stream_get_state(This->stream))) {
|
||||
pa_stream_disconnect(This->stream);
|
||||
@@ -1565,7 +1593,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
|
||||
{
|
||||
ACImpl *This = impl_from_IAudioClient(iface);
|
||||
HRESULT hr = S_OK;
|
||||
- UINT period_bytes;
|
||||
+ UINT32 bufsize_bytes;
|
||||
|
||||
TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
|
||||
wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
|
||||
@@ -1610,38 +1638,19 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
- if (mode == AUDCLNT_SHAREMODE_SHARED) {
|
||||
- REFERENCE_TIME def = pulse_def_period[This->dataflow == eCapture];
|
||||
- REFERENCE_TIME min = pulse_min_period[This->dataflow == eCapture];
|
||||
-
|
||||
- /* Switch to low latency mode if below 2 default periods,
|
||||
- * which is 20 ms by default, this will increase the amount
|
||||
- * of interrupts but allows very low latency. In dsound I
|
||||
- * managed to get a total latency of ~8ms, which is well below
|
||||
- * default
|
||||
- */
|
||||
- if (duration < 2 * def)
|
||||
- period = min;
|
||||
- else
|
||||
- period = def;
|
||||
- if (duration < 2 * period)
|
||||
- duration = 2 * period;
|
||||
+ period = pulse_def_period[This->dataflow == eCapture];
|
||||
+ if (duration < 3 * period)
|
||||
+ duration = 3 * period;
|
||||
|
||||
- /* Uh oh, really low latency requested.. */
|
||||
- if (duration <= 2 * period)
|
||||
- period /= 2;
|
||||
- }
|
||||
- period_bytes = pa_frame_size(&This->ss) * MulDiv(period, This->ss.rate, 10000000);
|
||||
+ This->period_bytes = pa_frame_size(&This->ss) * MulDiv(period, This->ss.rate, 10000000);
|
||||
|
||||
- if (duration < 20000000)
|
||||
- This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec);
|
||||
- else
|
||||
- This->bufsize_frames = 2 * fmt->nSamplesPerSec;
|
||||
- This->bufsize_bytes = This->bufsize_frames * pa_frame_size(&This->ss);
|
||||
+ This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec);
|
||||
+ bufsize_bytes = This->bufsize_frames * pa_frame_size(&This->ss);
|
||||
+ This->mmdev_period_usec = period / 10;
|
||||
|
||||
This->share = mode;
|
||||
This->flags = flags;
|
||||
- hr = pulse_stream_connect(This, period_bytes);
|
||||
+ hr = pulse_stream_connect(This, This->period_bytes);
|
||||
if (SUCCEEDED(hr)) {
|
||||
UINT32 unalign;
|
||||
const pa_buffer_attr *attr = pa_stream_get_buffer_attr(This->stream);
|
||||
@@ -1649,39 +1658,34 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
|
||||
/* Update frames according to new size */
|
||||
dump_attr(attr);
|
||||
if (This->dataflow == eRender) {
|
||||
- if (attr->tlength < This->bufsize_bytes) {
|
||||
- TRACE("PulseAudio buffer too small (%u < %u), using tmp buffer\n", attr->tlength, This->bufsize_bytes);
|
||||
-
|
||||
- This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->bufsize_bytes);
|
||||
- if(!This->local_buffer)
|
||||
- hr = E_OUTOFMEMORY;
|
||||
- }
|
||||
+ This->real_bufsize_bytes = This->bufsize_frames * 2 * pa_frame_size(&This->ss);
|
||||
+ This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->real_bufsize_bytes);
|
||||
+ if(!This->local_buffer)
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
} else {
|
||||
UINT32 i, capture_packets;
|
||||
|
||||
- This->capture_period = period_bytes = attr->fragsize;
|
||||
- if ((unalign = This->bufsize_bytes % period_bytes))
|
||||
- This->bufsize_bytes += period_bytes - unalign;
|
||||
- This->bufsize_frames = This->bufsize_bytes / pa_frame_size(&This->ss);
|
||||
+ if ((unalign = bufsize_bytes % This->period_bytes))
|
||||
+ bufsize_bytes += This->period_bytes - unalign;
|
||||
+ This->bufsize_frames = bufsize_bytes / pa_frame_size(&This->ss);
|
||||
+ This->real_bufsize_bytes = bufsize_bytes;
|
||||
|
||||
- capture_packets = This->bufsize_bytes / This->capture_period;
|
||||
+ capture_packets = This->real_bufsize_bytes / This->period_bytes;
|
||||
|
||||
- This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->bufsize_bytes + capture_packets * sizeof(ACPacket));
|
||||
+ This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->real_bufsize_bytes + capture_packets * sizeof(ACPacket));
|
||||
if (!This->local_buffer)
|
||||
hr = E_OUTOFMEMORY;
|
||||
else {
|
||||
- ACPacket *cur_packet = (ACPacket*)((char*)This->local_buffer + This->bufsize_bytes);
|
||||
+ ACPacket *cur_packet = (ACPacket*)((char*)This->local_buffer + This->real_bufsize_bytes);
|
||||
BYTE *data = This->local_buffer;
|
||||
- silence_buffer(This->ss.format, This->local_buffer, This->bufsize_bytes);
|
||||
+ silence_buffer(This->ss.format, This->local_buffer, This->real_bufsize_bytes);
|
||||
list_init(&This->packet_free_head);
|
||||
list_init(&This->packet_filled_head);
|
||||
for (i = 0; i < capture_packets; ++i, ++cur_packet) {
|
||||
list_add_tail(&This->packet_free_head, &cur_packet->entry);
|
||||
cur_packet->data = data;
|
||||
- data += This->capture_period;
|
||||
+ data += This->period_bytes;
|
||||
}
|
||||
- assert(!This->capture_period || This->bufsize_bytes == This->capture_period * capture_packets);
|
||||
- assert(!capture_packets || data - This->bufsize_bytes == This->local_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1746,12 +1750,12 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
|
||||
attr = pa_stream_get_buffer_attr(This->stream);
|
||||
if (This->dataflow == eRender){
|
||||
lat = attr->minreq / pa_frame_size(&This->ss);
|
||||
- lat += pulse_def_period[0];
|
||||
}else
|
||||
lat = attr->fragsize / pa_frame_size(&This->ss);
|
||||
*latency = 10000000;
|
||||
*latency *= lat;
|
||||
*latency /= This->ss.rate;
|
||||
+ *latency += pulse_def_period[0];
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
TRACE("Latency: %u ms\n", (DWORD)(*latency / 10000));
|
||||
return S_OK;
|
||||
@@ -1759,7 +1763,7 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
|
||||
|
||||
static void ACImpl_GetRenderPad(ACImpl *This, UINT32 *out)
|
||||
{
|
||||
- *out = This->pad / pa_frame_size(&This->ss);
|
||||
+ *out = This->held_bytes / pa_frame_size(&This->ss);
|
||||
}
|
||||
|
||||
static void ACImpl_GetCapturePad(ACImpl *This, UINT32 *out)
|
||||
@@ -1771,7 +1775,7 @@ static void ACImpl_GetCapturePad(ACImpl *This, UINT32 *out)
|
||||
list_remove(&packet->entry);
|
||||
}
|
||||
if (out)
|
||||
- *out = This->pad / pa_frame_size(&This->ss);
|
||||
+ *out = This->held_bytes / pa_frame_size(&This->ss);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
|
||||
@@ -2017,6 +2021,8 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||
return AUDCLNT_E_NOT_STOPPED;
|
||||
}
|
||||
|
||||
+ pulse_write(This);
|
||||
+
|
||||
if (pa_stream_is_corked(This->stream)) {
|
||||
o = pa_stream_cork(This->stream, 0, pulse_op_cb, &success);
|
||||
if (o) {
|
||||
@@ -2031,8 +2037,10 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
This->started = TRUE;
|
||||
- if (This->dataflow == eRender && This->event)
|
||||
- pa_stream_set_latency_update_callback(This->stream, pulse_latency_callback, This);
|
||||
+ This->just_started = TRUE;
|
||||
+
|
||||
+ if(!This->timer)
|
||||
+ This->timer = CreateThread(NULL, 0, pulse_timer_cb, This, 0, NULL);
|
||||
}
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
return hr;
|
||||
@@ -2104,7 +2112,7 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
|
||||
if (This->dataflow == eRender) {
|
||||
/* If there is still data in the render buffer it needs to be removed from the server */
|
||||
int success = 0;
|
||||
- if (This->pad) {
|
||||
+ if (This->held_bytes) {
|
||||
pa_operation *o = pa_stream_flush(This->stream, pulse_op_cb, &success);
|
||||
if (o) {
|
||||
while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
|
||||
@@ -2112,14 +2120,14 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
}
|
||||
- if (success || !This->pad){
|
||||
- This->clock_lastpos = This->clock_written = This->pad = 0;
|
||||
- This->wri_offs_bytes = This->lcl_offs_bytes = This->held_bytes = 0;
|
||||
+ if (success || !This->held_bytes){
|
||||
+ This->clock_lastpos = This->clock_written = 0;
|
||||
+ This->pa_offs_bytes = This->lcl_offs_bytes = This->held_bytes = This->pa_held_bytes = 0;
|
||||
}
|
||||
} else {
|
||||
ACPacket *p;
|
||||
- This->clock_written += This->pad;
|
||||
- This->pad = 0;
|
||||
+ This->clock_written += This->held_bytes;
|
||||
+ This->held_bytes = 0;
|
||||
|
||||
if ((p = This->locked_ptr)) {
|
||||
This->locked_ptr = NULL;
|
||||
@@ -2285,10 +2293,9 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
||||
UINT32 frames, BYTE **data)
|
||||
{
|
||||
ACImpl *This = impl_from_IAudioRenderClient(iface);
|
||||
- size_t avail, req, bytes = frames * pa_frame_size(&This->ss);
|
||||
- UINT32 pad;
|
||||
+ size_t bytes = frames * pa_frame_size(&This->ss);
|
||||
HRESULT hr = S_OK;
|
||||
- int ret = -1;
|
||||
+ UINT32 wri_offs_bytes;
|
||||
|
||||
TRACE("(%p)->(%u, %p)\n", This, frames, data);
|
||||
|
||||
@@ -2307,37 +2314,19 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
- ACImpl_GetRenderPad(This, &pad);
|
||||
- avail = This->bufsize_frames - pad;
|
||||
- if (avail < frames || bytes > This->bufsize_bytes) {
|
||||
+ if(This->held_bytes / pa_frame_size(&This->ss) + frames > This->bufsize_frames){
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
- WARN("Wanted to write %u, but only %zu available\n", frames, avail);
|
||||
return AUDCLNT_E_BUFFER_TOO_LARGE;
|
||||
}
|
||||
|
||||
- if(This->local_buffer){
|
||||
- if(This->wri_offs_bytes + bytes > This->bufsize_bytes){
|
||||
- alloc_tmp_buffer(This, bytes);
|
||||
- *data = This->tmp_buffer;
|
||||
- This->locked = -frames;
|
||||
- }else{
|
||||
- *data = This->local_buffer + This->wri_offs_bytes;
|
||||
- This->locked = frames;
|
||||
- }
|
||||
+ wri_offs_bytes = (This->lcl_offs_bytes + This->held_bytes) % This->real_bufsize_bytes;
|
||||
+ if(wri_offs_bytes + bytes > This->real_bufsize_bytes){
|
||||
+ alloc_tmp_buffer(This, bytes);
|
||||
+ *data = This->tmp_buffer;
|
||||
+ This->locked = -bytes;
|
||||
}else{
|
||||
- req = bytes;
|
||||
- ret = pa_stream_begin_write(This->stream, &This->locked_ptr, &req);
|
||||
- if (ret < 0 || req < bytes) {
|
||||
- FIXME("%p Not using pulse locked data: %i %zu/%u %u/%u\n", This, ret, req/pa_frame_size(&This->ss), frames, pad, This->bufsize_frames);
|
||||
- if (ret >= 0)
|
||||
- pa_stream_cancel_write(This->stream);
|
||||
- alloc_tmp_buffer(This, bytes);
|
||||
- *data = This->tmp_buffer;
|
||||
- This->locked_ptr = NULL;
|
||||
- } else
|
||||
- *data = This->locked_ptr;
|
||||
-
|
||||
- This->locked = frames;
|
||||
+ *data = This->local_buffer + wri_offs_bytes;
|
||||
+ This->locked = bytes;
|
||||
}
|
||||
|
||||
silence_buffer(This->ss.format, *data, bytes);
|
||||
@@ -2349,12 +2338,13 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
|
||||
|
||||
static void pulse_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_bytes)
|
||||
{
|
||||
- UINT32 chunk_bytes = This->bufsize_bytes - This->wri_offs_bytes;
|
||||
+ UINT32 wri_offs_bytes = (This->lcl_offs_bytes + This->held_bytes) % This->real_bufsize_bytes;
|
||||
+ UINT32 chunk_bytes = This->real_bufsize_bytes - wri_offs_bytes;
|
||||
|
||||
if(written_bytes <= chunk_bytes){
|
||||
- memcpy(This->local_buffer + This->wri_offs_bytes, buffer, written_bytes);
|
||||
+ memcpy(This->local_buffer + wri_offs_bytes, buffer, written_bytes);
|
||||
}else{
|
||||
- memcpy(This->local_buffer + This->wri_offs_bytes, buffer, chunk_bytes);
|
||||
+ memcpy(This->local_buffer + wri_offs_bytes, buffer, chunk_bytes);
|
||||
memcpy(This->local_buffer, buffer + chunk_bytes,
|
||||
written_bytes - chunk_bytes);
|
||||
}
|
||||
@@ -2365,88 +2355,42 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
|
||||
{
|
||||
ACImpl *This = impl_from_IAudioRenderClient(iface);
|
||||
UINT32 written_bytes = written_frames * pa_frame_size(&This->ss);
|
||||
+ BYTE *buffer;
|
||||
|
||||
TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
|
||||
|
||||
pthread_mutex_lock(&pulse_lock);
|
||||
if (!This->locked || !written_frames) {
|
||||
- if (This->locked_ptr)
|
||||
- pa_stream_cancel_write(This->stream);
|
||||
This->locked = 0;
|
||||
- This->locked_ptr = NULL;
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
|
||||
}
|
||||
|
||||
- if (This->locked < written_frames) {
|
||||
+ if(written_frames * pa_frame_size(&This->ss) > (This->locked >= 0 ? This->locked : -This->locked)){
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
return AUDCLNT_E_INVALID_SIZE;
|
||||
}
|
||||
|
||||
- if(This->local_buffer){
|
||||
- BYTE *buffer;
|
||||
-
|
||||
- if(This->locked >= 0)
|
||||
- buffer = This->local_buffer + This->wri_offs_bytes;
|
||||
- else
|
||||
- buffer = This->tmp_buffer;
|
||||
-
|
||||
- if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
|
||||
- silence_buffer(This->ss.format, buffer, written_bytes);
|
||||
-
|
||||
- if(This->locked < 0)
|
||||
- pulse_wrap_buffer(This, buffer, written_bytes);
|
||||
-
|
||||
- This->wri_offs_bytes += written_bytes;
|
||||
- This->wri_offs_bytes %= This->bufsize_bytes;
|
||||
-
|
||||
- This->pad += written_bytes;
|
||||
- This->held_bytes += written_bytes;
|
||||
-
|
||||
- if(This->held_bytes == This->pad){
|
||||
- int e;
|
||||
- UINT32 to_write = min(This->attr.tlength, written_bytes);
|
||||
-
|
||||
- /* nothing in PA, so send data immediately */
|
||||
-
|
||||
- TRACE("pre-writing %u bytes\n", to_write);
|
||||
-
|
||||
- e = write_buffer(This, buffer, to_write, 0);
|
||||
- if(e)
|
||||
- ERR("pa_stream_write failed: 0x%x\n", e);
|
||||
-
|
||||
- This->lcl_offs_bytes += to_write;
|
||||
- This->lcl_offs_bytes %= This->bufsize_bytes;
|
||||
- This->held_bytes -= to_write;
|
||||
- }
|
||||
-
|
||||
- }else{
|
||||
- enum write_buffer_flags wr_flags = 0;
|
||||
+ if(This->locked >= 0)
|
||||
+ buffer = This->local_buffer + (This->lcl_offs_bytes + This->held_bytes) % This->real_bufsize_bytes;
|
||||
+ else
|
||||
+ buffer = This->tmp_buffer;
|
||||
|
||||
- if (flags & AUDCLNT_BUFFERFLAGS_SILENT) wr_flags |= WINEPULSE_WRITE_SILENT;
|
||||
- if (!This->locked_ptr) wr_flags |= WINEPULSE_WRITE_NOFREE;
|
||||
+ if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
|
||||
+ silence_buffer(This->ss.format, buffer, written_bytes);
|
||||
|
||||
- write_buffer(This, This->locked_ptr ? This->locked_ptr : This->tmp_buffer, written_bytes, wr_flags);
|
||||
- This->pad += written_bytes;
|
||||
- }
|
||||
-
|
||||
- if (!pa_stream_is_corked(This->stream)) {
|
||||
- int success;
|
||||
- pa_operation *o;
|
||||
- o = pa_stream_trigger(This->stream, pulse_op_cb, &success);
|
||||
- if (o) {
|
||||
- while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
|
||||
- pthread_cond_wait(&pulse_cond, &pulse_lock);
|
||||
- pa_operation_unref(o);
|
||||
- }
|
||||
- }
|
||||
+ if(This->locked < 0)
|
||||
+ pulse_wrap_buffer(This, buffer, written_bytes);
|
||||
|
||||
+ This->held_bytes += written_bytes;
|
||||
+ This->pa_held_bytes += written_bytes;
|
||||
+ This->clock_written += written_bytes;
|
||||
This->locked = 0;
|
||||
- This->locked_ptr = NULL;
|
||||
- TRACE("Released %u, pad %zu\n", written_frames, This->pad / pa_frame_size(&This->ss));
|
||||
- assert(This->pad <= This->bufsize_bytes);
|
||||
+
|
||||
+ TRACE("Released %u, held %zu\n", written_frames, This->held_bytes / pa_frame_size(&This->ss));
|
||||
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
+
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -2523,13 +2467,13 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
|
||||
|
||||
ACImpl_GetCapturePad(This, NULL);
|
||||
if ((packet = This->locked_ptr)) {
|
||||
- *frames = This->capture_period / pa_frame_size(&This->ss);
|
||||
+ *frames = This->period_bytes / pa_frame_size(&This->ss);
|
||||
*flags = 0;
|
||||
if (packet->discont)
|
||||
*flags |= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY;
|
||||
if (devpos) {
|
||||
if (packet->discont)
|
||||
- *devpos = (This->clock_written + This->capture_period) / pa_frame_size(&This->ss);
|
||||
+ *devpos = (This->clock_written + This->period_bytes) / pa_frame_size(&This->ss);
|
||||
else
|
||||
*devpos = This->clock_written / pa_frame_size(&This->ss);
|
||||
}
|
||||
@@ -2563,11 +2507,11 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
|
||||
if (done) {
|
||||
ACPacket *packet = This->locked_ptr;
|
||||
This->locked_ptr = NULL;
|
||||
- This->pad -= This->capture_period;
|
||||
+ This->held_bytes -= This->period_bytes;
|
||||
if (packet->discont)
|
||||
- This->clock_written += 2 * This->capture_period;
|
||||
+ This->clock_written += 2 * This->period_bytes;
|
||||
else
|
||||
- This->clock_written += This->capture_period;
|
||||
+ This->clock_written += This->period_bytes;
|
||||
list_add_tail(&This->packet_free_head, &packet->entry);
|
||||
}
|
||||
This->locked = 0;
|
||||
@@ -2587,7 +2531,7 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
|
||||
pthread_mutex_lock(&pulse_lock);
|
||||
ACImpl_GetCapturePad(This, NULL);
|
||||
if (This->locked_ptr)
|
||||
- *frames = This->capture_period / pa_frame_size(&This->ss);
|
||||
+ *frames = This->period_bytes / pa_frame_size(&This->ss);
|
||||
else
|
||||
*frames = 0;
|
||||
pthread_mutex_unlock(&pulse_lock);
|
||||
@@ -2679,7 +2623,14 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
|
||||
return hr;
|
||||
}
|
||||
|
||||
- *pos = This->clock_written;
|
||||
+ *pos = This->clock_written - This->held_bytes;
|
||||
+
|
||||
+ if(This->started){
|
||||
+ if(*pos < This->period_bytes)
|
||||
+ *pos = 0;
|
||||
+ else if(This->held_bytes > This->period_bytes)
|
||||
+ *pos -= This->period_bytes;
|
||||
+ }
|
||||
|
||||
if (This->share == AUDCLNT_SHAREMODE_EXCLUSIVE)
|
||||
*pos /= pa_frame_size(&This->ss);
|
||||
--
|
||||
2.24.1
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 0f1a7d67f08eb916407ed4e8f2eb51e829b8c876 Mon Sep 17 00:00:00 2001
|
||||
From 5e002013b359e3278e9c1ef30514e4be274ea032 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Harmstone <mark@harmstone.com>
|
||||
Date: Mon, 3 Nov 2014 02:06:40 +0000
|
||||
Subject: [PATCH 3/7] winepulse: expose audio devices directly to programs
|
||||
Subject: [PATCH] winepulse: expose audio devices directly to programs
|
||||
|
||||
At present, winepulse only exposes one input device and one output device. This
|
||||
patch adds support for individual audio devices, allowing (among other things)
|
||||
@ -16,11 +16,11 @@ Changes by Sebastian Lackner <sebastian@fds-team.de>:
|
||||
* Some style fixes and better error handling
|
||||
* Move initialization code to pulse_test_connect()
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 252 +++++++++++++++++++++++++++++++++++++-----
|
||||
dlls/winepulse.drv/mmdevdrv.c | 252 ++++++++++++++++++++++++++++++----
|
||||
1 file changed, 224 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 0039c34..e521794 100644
|
||||
index 7fc7dccb367..59cfa3db4f2 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -79,12 +79,25 @@ static pthread_mutex_t pulse_lock;
|
||||
@ -49,7 +49,7 @@ index 0039c34..e521794 100644
|
||||
static GUID pulse_render_guid =
|
||||
{ 0xfd47d9cc, 0x4218, 0x4135, { 0x9c, 0xe2, 0x0c, 0x19, 0x5c, 0x87, 0x40, 0x5b } };
|
||||
static GUID pulse_capture_guid =
|
||||
@@ -103,6 +116,13 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
|
||||
@@ -106,6 +119,13 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
|
||||
if (pthread_mutex_init(&pulse_lock, &attr) != 0)
|
||||
pthread_mutex_init(&pulse_lock, NULL);
|
||||
} else if (reason == DLL_PROCESS_DETACH) {
|
||||
@ -63,7 +63,7 @@ index 0039c34..e521794 100644
|
||||
if (pulse_thread)
|
||||
SetThreadPriority(pulse_thread, 0);
|
||||
if (pulse_ctx) {
|
||||
@@ -164,6 +184,7 @@ struct ACImpl {
|
||||
@@ -167,6 +187,7 @@ struct ACImpl {
|
||||
IMMDevice *parent;
|
||||
struct list entry;
|
||||
float vol[PA_CHANNELS_MAX];
|
||||
@ -71,7 +71,7 @@ index 0039c34..e521794 100644
|
||||
|
||||
LONG ref;
|
||||
EDataFlow dataflow;
|
||||
@@ -193,8 +214,6 @@ struct ACImpl {
|
||||
@@ -196,8 +217,6 @@ struct ACImpl {
|
||||
struct list packet_filled_head;
|
||||
};
|
||||
|
||||
@ -80,7 +80,7 @@ index 0039c34..e521794 100644
|
||||
static const IAudioClientVtbl AudioClient_Vtbl;
|
||||
static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
|
||||
static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
|
||||
@@ -517,12 +536,92 @@ fail:
|
||||
@@ -605,12 +624,92 @@ fail:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ index 0039c34..e521794 100644
|
||||
}
|
||||
|
||||
/* some poorly-behaved applications call audio functions during DllMain, so we
|
||||
@@ -538,6 +637,10 @@ static HRESULT pulse_test_connect(void)
|
||||
@@ -626,6 +725,10 @@ static HRESULT pulse_test_connect(void)
|
||||
pa_mainloop *ml;
|
||||
pa_context *ctx;
|
||||
|
||||
@ -187,7 +187,7 @@ index 0039c34..e521794 100644
|
||||
ml = pa_mainloop_new();
|
||||
|
||||
pa_mainloop_set_poll_func(ml, pulse_poll_func, NULL);
|
||||
@@ -588,6 +691,9 @@ static HRESULT pulse_test_connect(void)
|
||||
@@ -676,6 +779,9 @@ static HRESULT pulse_test_connect(void)
|
||||
pulse_probe_settings(ml, ctx, 0, &pulse_fmt[1]);
|
||||
|
||||
g_phys_speakers_mask = 0;
|
||||
@ -197,7 +197,7 @@ index 0039c34..e521794 100644
|
||||
o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
|
||||
if (o) {
|
||||
while (pa_mainloop_iterate(ml, 1, &ret) >= 0 &&
|
||||
@@ -596,6 +702,14 @@ static HRESULT pulse_test_connect(void)
|
||||
@@ -684,6 +790,14 @@ static HRESULT pulse_test_connect(void)
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ index 0039c34..e521794 100644
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
return S_OK;
|
||||
@@ -883,6 +997,8 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
@@ -1111,6 +1225,8 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
char buffer[64];
|
||||
static LONG number;
|
||||
pa_buffer_attr attr;
|
||||
@ -221,7 +221,7 @@ index 0039c34..e521794 100644
|
||||
if (This->stream) {
|
||||
pa_stream_disconnect(This->stream);
|
||||
while (pa_stream_get_state(This->stream) == PA_STREAM_READY)
|
||||
@@ -908,12 +1024,18 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
@@ -1136,12 +1252,18 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
attr.maxlength = This->bufsize_frames * pa_frame_size(&This->ss);
|
||||
attr.prebuf = pa_frame_size(&This->ss);
|
||||
dump_attr(&attr);
|
||||
@ -233,16 +233,16 @@ index 0039c34..e521794 100644
|
||||
+
|
||||
if (This->dataflow == eRender)
|
||||
ret = pa_stream_connect_playback(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY, NULL, NULL);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY|moving, NULL, NULL);
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY, NULL, NULL);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving, NULL, NULL);
|
||||
else
|
||||
ret = pa_stream_connect_record(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY|moving);
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving);
|
||||
if (ret < 0) {
|
||||
WARN("Returns %i\n", ret);
|
||||
return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
|
||||
@@ -930,39 +1052,53 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
@@ -1158,39 +1280,53 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -315,7 +315,7 @@ index 0039c34..e521794 100644
|
||||
}
|
||||
|
||||
int WINAPI AUDDRV_GetPriority(void)
|
||||
@@ -974,20 +1110,79 @@ int WINAPI AUDDRV_GetPriority(void)
|
||||
@@ -1202,20 +1338,79 @@ int WINAPI AUDDRV_GetPriority(void)
|
||||
return SUCCEEDED(hr) ? Priority_Preferred : Priority_Unavailable;
|
||||
}
|
||||
|
||||
@ -397,7 +397,7 @@ index 0039c34..e521794 100644
|
||||
|
||||
*out = NULL;
|
||||
|
||||
@@ -1005,6 +1200,7 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
|
||||
@@ -1233,6 +1428,7 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
|
||||
This->parent = dev;
|
||||
for (i = 0; i < PA_CHANNELS_MAX; ++i)
|
||||
This->vol[i] = 1.f;
|
||||
@ -406,5 +406,5 @@ index 0039c34..e521794 100644
|
||||
hr = CoCreateFreeThreadedMarshaler((IUnknown*)&This->IAudioClient_iface, &This->marshal);
|
||||
if (hr) {
|
||||
--
|
||||
1.9.1
|
||||
2.28.0
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
From 8c4a9cd1290fe9240a8de0d3ce5771f528153b06 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Harmstone <mark@harmstone.com>
|
||||
Date: Tue, 18 Nov 2014 18:39:58 +0000
|
||||
Subject: [PATCH 4/7] winepulse: fix segfault in pulse_rd_loop
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index e521794..583690b 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -818,6 +818,7 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
size_t src_len, copy, rem = This->period_bytes;
|
||||
if (!(p = (ACPacket*)list_head(&This->packet_free_head))) {
|
||||
p = (ACPacket*)list_head(&This->packet_filled_head);
|
||||
+ if (!p) return;
|
||||
if (!p->discont) {
|
||||
next = (ACPacket*)p->entry.next;
|
||||
next->discont = 1;
|
||||
--
|
||||
1.9.1
|
||||
|
@ -1,163 +0,0 @@
|
||||
From 80d921c3a7e93df6dcf34daa01829a13fac23179 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Tue, 7 Aug 2018 11:26:16 -0500
|
||||
Subject: [PATCH] winepulse: Fix up recording
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 115 +++++++++++++++++-------------------------
|
||||
1 file changed, 46 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 9c3ff0f..56f6c2b 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -986,53 +986,70 @@ static void pulse_started_callback(pa_stream *s, void *userdata)
|
||||
TRACE("%p: (Re)started playing\n", userdata);
|
||||
}
|
||||
|
||||
-static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
+static void pulse_read(ACImpl *This)
|
||||
{
|
||||
+ size_t bytes = pa_stream_readable_size(This->stream);
|
||||
+
|
||||
+ TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(This->stream)->fragsize);
|
||||
+
|
||||
+ bytes += This->peek_len - This->peek_ofs;
|
||||
+
|
||||
while (bytes >= This->period_bytes) {
|
||||
- ACPacket *p, *next;
|
||||
- LARGE_INTEGER stamp, freq;
|
||||
- BYTE *dst, *src;
|
||||
+ BYTE *dst = NULL, *src;
|
||||
size_t src_len, copy, rem = This->period_bytes;
|
||||
- if (!(p = (ACPacket*)list_head(&This->packet_free_head))) {
|
||||
- p = (ACPacket*)list_head(&This->packet_filled_head);
|
||||
- if (!p) return;
|
||||
- if (!p->discont) {
|
||||
- next = (ACPacket*)p->entry.next;
|
||||
- next->discont = 1;
|
||||
- } else
|
||||
- p = (ACPacket*)list_tail(&This->packet_filled_head);
|
||||
- } else {
|
||||
- This->held_bytes += This->period_bytes;
|
||||
+
|
||||
+ if (This->started) {
|
||||
+ LARGE_INTEGER stamp, freq;
|
||||
+ ACPacket *p, *next;
|
||||
+
|
||||
+ if (!(p = (ACPacket*)list_head(&This->packet_free_head))) {
|
||||
+ p = (ACPacket*)list_head(&This->packet_filled_head);
|
||||
+ if (!p) return;
|
||||
+ if (!p->discont) {
|
||||
+ next = (ACPacket*)p->entry.next;
|
||||
+ next->discont = 1;
|
||||
+ } else
|
||||
+ p = (ACPacket*)list_tail(&This->packet_filled_head);
|
||||
+ } else {
|
||||
+ This->held_bytes += This->period_bytes;
|
||||
+ }
|
||||
+ QueryPerformanceCounter(&stamp);
|
||||
+ QueryPerformanceFrequency(&freq);
|
||||
+ p->qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
|
||||
+ p->discont = 0;
|
||||
+ list_remove(&p->entry);
|
||||
+ list_add_tail(&This->packet_filled_head, &p->entry);
|
||||
+
|
||||
+ dst = p->data;
|
||||
}
|
||||
- QueryPerformanceCounter(&stamp);
|
||||
- QueryPerformanceFrequency(&freq);
|
||||
- p->qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
|
||||
- p->discont = 0;
|
||||
- list_remove(&p->entry);
|
||||
- list_add_tail(&This->packet_filled_head, &p->entry);
|
||||
|
||||
- dst = p->data;
|
||||
while (rem) {
|
||||
if (This->peek_len) {
|
||||
copy = min(rem, This->peek_len - This->peek_ofs);
|
||||
|
||||
- memcpy(dst, This->peek_buffer + This->peek_ofs, copy);
|
||||
+ if (dst) {
|
||||
+ memcpy(dst, This->peek_buffer + This->peek_ofs, copy);
|
||||
+ dst += copy;
|
||||
+ }
|
||||
|
||||
rem -= copy;
|
||||
- dst += copy;
|
||||
This->peek_ofs += copy;
|
||||
if(This->peek_len == This->peek_ofs)
|
||||
- This->peek_len = 0;
|
||||
+ This->peek_len = This->peek_ofs = 0;
|
||||
+
|
||||
} else if (pa_stream_peek(This->stream, (const void**)&src, &src_len) == 0 && src_len) {
|
||||
|
||||
copy = min(rem, src_len);
|
||||
|
||||
- if(src)
|
||||
- memcpy(dst, src, copy);
|
||||
- else
|
||||
- silence_buffer(This->ss.format, dst, copy);
|
||||
+ if (dst) {
|
||||
+ if(src)
|
||||
+ memcpy(dst, src, copy);
|
||||
+ else
|
||||
+ silence_buffer(This->ss.format, dst, copy);
|
||||
+
|
||||
+ dst += copy;
|
||||
+ }
|
||||
|
||||
- dst += copy;
|
||||
rem -= copy;
|
||||
|
||||
if (copy < src_len) {
|
||||
@@ -1059,46 +1076,6 @@ static void pulse_rd_loop(ACImpl *This, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
-static void pulse_rd_drop(ACImpl *This, size_t bytes)
|
||||
-{
|
||||
- while (bytes >= This->period_bytes) {
|
||||
- size_t src_len, copy, rem = This->period_bytes;
|
||||
- while (rem) {
|
||||
- const void *src;
|
||||
- pa_stream_peek(This->stream, &src, &src_len);
|
||||
- src_len -= This->peek_ofs;
|
||||
-
|
||||
- copy = rem;
|
||||
- if (copy > src_len)
|
||||
- copy = src_len;
|
||||
-
|
||||
- src_len -= copy;
|
||||
- rem -= copy;
|
||||
-
|
||||
- if (!src_len) {
|
||||
- This->peek_ofs = 0;
|
||||
- pa_stream_drop(This->stream);
|
||||
- } else
|
||||
- This->peek_ofs += copy;
|
||||
- bytes -= copy;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void pulse_read(ACImpl *This)
|
||||
-{
|
||||
- size_t bytes = pa_stream_readable_size(This->stream);
|
||||
- TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(This->stream)->fragsize);
|
||||
- bytes -= This->peek_ofs;
|
||||
- if (bytes < This->period_bytes)
|
||||
- return;
|
||||
-
|
||||
- if (This->started)
|
||||
- pulse_rd_loop(This, bytes);
|
||||
- else
|
||||
- pulse_rd_drop(This, bytes);
|
||||
-}
|
||||
-
|
||||
static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
{
|
||||
DWORD delay;
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,73 +0,0 @@
|
||||
From d2238287ffb1db3ebde4339548019920c694abbc Mon Sep 17 00:00:00 2001
|
||||
From: Zhiyi Zhang <zzhang@codeweavers.com>
|
||||
Date: Mon, 27 Aug 2018 08:20:17 -0500
|
||||
Subject: winepulse.drv: Fix getting the same timing info.
|
||||
To: wine-devel <wine-devel@winehq.org>
|
||||
Reply-To: wine-devel <wine-devel@winehq.org>,Andrew Eikum <aeikum@codeweavers.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------2.18.0"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------2.18.0
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
pa_stream_get_time would return the same time if pa_stream_update_timing_info
|
||||
is not called before, causing wrong delay. Since we're updating the timing
|
||||
info by ourselves, no need to use PA_STREAM_AUTO_TIMING_UPDATE. Also
|
||||
PA_STREAM_INTERPOLATE_TIMING is removed because we want the real time.
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
|
||||
--------------2.18.0
|
||||
Content-Type: text/x-patch; name="0009-winepulse.drv-Fix-getting-the-same-timing-info.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="0009-winepulse.drv-Fix-getting-the-same-timing-info.patch"
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 5d74ce093d..48ed585cc1 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -1082,6 +1082,8 @@ static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
DWORD delay;
|
||||
UINT32 adv_bytes;
|
||||
ACImpl *This = user;
|
||||
+ int success;
|
||||
+ pa_operation *o;
|
||||
|
||||
pthread_mutex_lock(&pulse_lock);
|
||||
delay = This->mmdev_period_usec / 1000;
|
||||
@@ -1098,6 +1100,13 @@ static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
|
||||
delay = This->mmdev_period_usec / 1000;
|
||||
|
||||
+ o = pa_stream_update_timing_info(This->stream, pulse_op_cb, &success);
|
||||
+ if (o)
|
||||
+ {
|
||||
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
|
||||
+ pthread_cond_wait(&pulse_cond, &pulse_lock);
|
||||
+ pa_operation_unref(o);
|
||||
+ }
|
||||
err = pa_stream_get_time(This->stream, &now);
|
||||
if(err == 0){
|
||||
TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(This->last_time));
|
||||
@@ -1194,10 +1203,10 @@ static HRESULT pulse_stream_connect(ACImpl *This, UINT32 period_bytes) {
|
||||
|
||||
if (This->dataflow == eRender)
|
||||
ret = pa_stream_connect_playback(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY|moving, NULL, NULL);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving, NULL, NULL);
|
||||
else
|
||||
ret = pa_stream_connect_record(This->stream, NULL, &attr,
|
||||
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_ADJUST_LATENCY|moving);
|
||||
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving);
|
||||
if (ret < 0) {
|
||||
WARN("Returns %i\n", ret);
|
||||
return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
|
||||
|
||||
--------------2.18.0--
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
From 5b10bce652ede36e8f6861b9086933ce97889696 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Mon, 27 Aug 2018 08:33:32 -0500
|
||||
Subject: winepulse: Update last time on underrun
|
||||
To: wine-devel <wine-devel@winehq.org>
|
||||
Reply-To: wine-devel <wine-devel@winehq.org>,Andrew Eikum <aeikum@codeweavers.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="------------2.18.0"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------2.18.0
|
||||
Content-Type: text/plain; charset=UTF-8; format=fixed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
|
||||
--------------2.18.0
|
||||
Content-Type: text/x-patch; name="0010-winepulse-Update-last-time-on-underrun.patch"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Disposition: inline; filename="0010-winepulse-Update-last-time-on-underrun.patch"
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 48ed585cc1..1ce6cea9d6 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -1111,6 +1111,11 @@ static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
if(err == 0){
|
||||
TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(This->last_time));
|
||||
if(This->started && (This->dataflow == eCapture || This->held_bytes)){
|
||||
+ if(This->just_underran){
|
||||
+ This->last_time = now;
|
||||
+ This->just_started = TRUE;
|
||||
+ }
|
||||
+
|
||||
if(This->just_started){
|
||||
/* let it play out a period to absorb some latency and get accurate timing */
|
||||
pa_usec_t diff = now - This->last_time;
|
||||
|
||||
--------------2.18.0--
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
From 262abc1d8daf243cf295c060ff4c47f93dcdbe2f Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Tue, 4 Sep 2018 13:40:58 -0500
|
||||
Subject: [PATCH 1/3] winepulse: account for PA devices that fall way behind
|
||||
To: wine-devel <wine-devel@winehq.org>
|
||||
Reply-To: wine-devel <wine-devel@winehq.org>,Andrew Eikum <aeikum@codeweavers.com>
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 1ce6cea9d6..6b994ada4e 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -980,6 +980,9 @@ static void pulse_underflow_callback(pa_stream *s, void *userdata)
|
||||
ACImpl *This = userdata;
|
||||
WARN("%p: Underflow\n", userdata);
|
||||
This->just_underran = TRUE;
|
||||
+ /* re-sync */
|
||||
+ This->pa_offs_bytes = This->lcl_offs_bytes;
|
||||
+ This->pa_held_bytes = This->held_bytes;
|
||||
}
|
||||
|
||||
static void pulse_started_callback(pa_stream *s, void *userdata)
|
||||
@@ -2524,6 +2527,11 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
|
||||
|
||||
This->held_bytes += written_bytes;
|
||||
This->pa_held_bytes += written_bytes;
|
||||
+ if(This->pa_held_bytes > This->real_bufsize_bytes){
|
||||
+ This->pa_offs_bytes += This->pa_held_bytes - This->real_bufsize_bytes;
|
||||
+ This->pa_offs_bytes %= This->real_bufsize_bytes;
|
||||
+ This->pa_held_bytes = This->real_bufsize_bytes;
|
||||
+ }
|
||||
This->clock_written += written_bytes;
|
||||
This->locked = 0;
|
||||
|
||||
--
|
||||
2.19.2
|
||||
|
@ -1,26 +0,0 @@
|
||||
From 6f0f6b7e3d3a28df29577f7da93f8e3837386ab1 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Fri, 19 Oct 2018 14:22:35 -0500
|
||||
Subject: [PATCH 2/3] winepulse: Fix local buffer offset wrapping
|
||||
To: wine-devel <wine-devel@winehq.org>
|
||||
Reply-To: wine-devel <wine-devel@winehq.org>,Andrew Eikum <aeikum@codeweavers.com>
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 6b994ada4e..fb2e3678f8 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -1148,6 +1148,7 @@ static DWORD WINAPI pulse_timer_cb(void *user)
|
||||
/* regardless of what PA does, advance one period */
|
||||
adv_bytes = min(This->period_bytes, This->held_bytes);
|
||||
This->lcl_offs_bytes += adv_bytes;
|
||||
+ This->lcl_offs_bytes %= This->real_bufsize_bytes;
|
||||
This->held_bytes -= adv_bytes;
|
||||
}else if(This->dataflow == eCapture){
|
||||
pulse_read(This);
|
||||
--
|
||||
2.19.2
|
||||
|
@ -1,33 +0,0 @@
|
||||
From cf1e1aa8a37ea52f70874931b80611eee7a27f83 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Eikum <aeikum@codeweavers.com>
|
||||
Date: Mon, 26 Nov 2018 15:04:38 -0600
|
||||
Subject: [PATCH 3/3] winepulse: Don't fake being one period behind in
|
||||
GetPosition
|
||||
To: wine-devel <wine-devel@winehq.org>
|
||||
Reply-To: wine-devel <wine-devel@winehq.org>,Andrew Eikum <aeikum@codeweavers.com>
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index fb2e3678f8..39284e55ad 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -2769,13 +2769,6 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
|
||||
|
||||
*pos = This->clock_written - This->held_bytes;
|
||||
|
||||
- if(This->started){
|
||||
- if(*pos < This->period_bytes)
|
||||
- *pos = 0;
|
||||
- else if(This->held_bytes > This->period_bytes)
|
||||
- *pos -= This->period_bytes;
|
||||
- }
|
||||
-
|
||||
if (This->share == AUDCLNT_SHAREMODE_EXCLUSIVE)
|
||||
*pos /= pa_frame_size(&This->ss);
|
||||
|
||||
--
|
||||
2.19.2
|
||||
|
@ -1,8 +1,5 @@
|
||||
Fixes: Allow selection of audio device for PulseAudio backend
|
||||
Fixes: [37042] Implement exclusive mode in PulseAudio backend
|
||||
Fixes: Fix possible segfault in pulse_rd_loop of PulseAudio backend
|
||||
Fixes: Add support for GetPropValue to PulseAudio backend
|
||||
Fixes: Use actual program name if available to describe PulseAudio streams
|
||||
Fixes: Expose PKEY_AudioEndpoint_PhysicalSpeakers device property in PulseAudio driver
|
||||
# Patches 0002, 0008-0010 fix the following bug:
|
||||
Fixes: [28282] Sound constantly crackling in a lot of games
|
@ -1 +1 @@
|
||||
447bce4117a58910690a0d2610ebcbdd49ae9127
|
||||
8f3bd63b52f03ff05e9d2a00a2e129a0b0092969
|
||||
|
Loading…
x
Reference in New Issue
Block a user