Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2022
- 80 participants
- 2903 messages
[PATCH 2/3] mshtml: Implement IDOMMessageEvent::data property.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 28 +++++++++++++++++++++++++---
dlls/mshtml/htmlevent.h | 1 +
dlls/mshtml/htmlwindow.c | 2 +-
dlls/mshtml/tests/events.js | 16 ++++++++++++++++
4 files changed, 43 insertions(+), 4 deletions(-)
March 1, 2022
[PATCH 1/3] mshtml: Add IDOMMessageEvent stub implementation.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/mshtml/htmlevent.c | 145 +++++++++++++++++++++++++++++++++++
dlls/mshtml/mshtml_private.h | 2 +
include/mshtml.idl | 32 ++++++++
3 files changed, 179 insertions(+)
March 1, 2022
Re: [PATCH v2 5/5] include/windows.media.speechrecognition.idl: Add SpeechRecognizer.
by Rémi Bernon
On 3/1/22 20:05, Alexandre Julliard wrote:
> Rémi Bernon <rbernon(a)codeweavers.com> writes:
>
>> @@ -433,6 +526,21 @@ namespace Windows {
>> [default] interface Windows.Media.SpeechRecognition.ISpeechRecognitionSemanticInterpretation;
>> }
>>
>> + [
>> + activatable(Windows.Foundation.UniversalApiContract, 1.0),
>> + activatable(Windows.Media.SpeechRecognition.ISpeechRecognizerFactory, Windows.Foundation.UniversalApiContract, 1.0),
>> + contract(Windows.Foundation.UniversalApiContract, 1.0),
>> + marshaling_behavior(agile),
>> + static(Windows.Media.SpeechRecognition.ISpeechRecognizerStatics, Windows.Foundation.UniversalApiContract, 1.0),
>> + static(Windows.Media.SpeechRecognition.ISpeechRecognizerStatics2, Windows.Foundation.UniversalApiContract, 5.0)
>> + ]
>> + runtimeclass SpeechRecognizer
>> + {
>> + [default] interface Windows.Media.SpeechRecognition.ISpeechRecognizer;
>> + interface Windows.Foundation.IClosable;
>> + [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Media.SpeechRecognition.ISpeechRecognizer2;
>> + }
>
> This is causing a warning:
>
> include/windows.media.speechrecognition.idl:532: warning: duplicate attribute activatable
>
Ah, I missed it somehow, sorry. It seems correct according to the SDK,
so probably something that needs fixing in widl.
--
Rémi Bernon <rbernon(a)codeweavers.com>
March 1, 2022
Re: [PATCH v2 5/5] include/windows.media.speechrecognition.idl: Add SpeechRecognizer.
by Alexandre Julliard
Rémi Bernon <rbernon(a)codeweavers.com> writes:
> @@ -433,6 +526,21 @@ namespace Windows {
> [default] interface Windows.Media.SpeechRecognition.ISpeechRecognitionSemanticInterpretation;
> }
>
> + [
> + activatable(Windows.Foundation.UniversalApiContract, 1.0),
> + activatable(Windows.Media.SpeechRecognition.ISpeechRecognizerFactory, Windows.Foundation.UniversalApiContract, 1.0),
> + contract(Windows.Foundation.UniversalApiContract, 1.0),
> + marshaling_behavior(agile),
> + static(Windows.Media.SpeechRecognition.ISpeechRecognizerStatics, Windows.Foundation.UniversalApiContract, 1.0),
> + static(Windows.Media.SpeechRecognition.ISpeechRecognizerStatics2, Windows.Foundation.UniversalApiContract, 5.0)
> + ]
> + runtimeclass SpeechRecognizer
> + {
> + [default] interface Windows.Media.SpeechRecognition.ISpeechRecognizer;
> + interface Windows.Foundation.IClosable;
> + [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Media.SpeechRecognition.ISpeechRecognizer2;
> + }
This is causing a warning:
include/windows.media.speechrecognition.idl:532: warning: duplicate attribute activatable
--
Alexandre Julliard
julliard(a)winehq.org
March 1, 2022
Re: [PATCH v2 5/5] include/windows.media.speechrecognition.idl: Add SpeechRecognizer.
by Bernhard Kölbl
Imho we should keep it like this because it's easier to compare against the
Windows IDLs.
I mean we also add a bunch of stuff which basically has no effect but keeps
similarity to the original sources, in case MS adds a use to that. Plus,
issues with the namespaces could arise in the future.
(Hope that makes sense.)
Bernhard
Rémi Bernon <rbernon(a)codeweavers.com> schrieb am Di., 1. März 2022, 18:46:
> On 3/1/22 18:34, Zebediah Figura (she/her) wrote:
> > On 3/1/22 10:42, Rémi Bernon wrote:
> >> From: Bernhard Kölbl <besentv(a)gmail.com>
> >>
> >> And its dependencies.
> >>
> >> Signed-off-by: Bernhard Kölbl <besentv(a)gmail.com>
> >> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
> >> ---
> >>
> >> v2: Minor alignment tweaking, though how long can these lines be, oof...
> >>
> >
> > Could we omit the fully qualified namespace?
> >
>
> Not for everything, only to reference things in the same namespace.
>
> Although it may seem a good idea, and I initially thought as much,
> there's a lot of cross-namespace references, and I find that it makes
> things less consistent and less readable overall.
>
> --
> Rémi Bernon <rbernon(a)codeweavers.com>
>
>
March 1, 2022
Re: [PATCH v2 5/5] include/windows.media.speechrecognition.idl: Add SpeechRecognizer.
by Rémi Bernon
On 3/1/22 18:34, Zebediah Figura (she/her) wrote:
> On 3/1/22 10:42, Rémi Bernon wrote:
>> From: Bernhard Kölbl <besentv(a)gmail.com>
>>
>> And its dependencies.
>>
>> Signed-off-by: Bernhard Kölbl <besentv(a)gmail.com>
>> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
>> ---
>>
>> v2: Minor alignment tweaking, though how long can these lines be, oof...
>>
>
> Could we omit the fully qualified namespace?
>
Not for everything, only to reference things in the same namespace.
Although it may seem a good idea, and I initially thought as much,
there's a lot of cross-namespace references, and I find that it makes
things less consistent and less readable overall.
--
Rémi Bernon <rbernon(a)codeweavers.com>
March 1, 2022
Re: [PATCH v11 2/2] ntdll: Properly track refcount with forwarded exports.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=109540
Your paranoid android.
=== w1064_tsign (32 bit report) ===
kernel32:
loader.c:3010: Test failed: attached thread count should be 2
=== w10pro64_ar (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1219: wrong status c000011b/c0000130
loader.c:720: Test failed: 1224: wrong status c000011b/c000007b
loader.c:720: Test failed: 1229: wrong status c000011b/c000007b
loader.c:720: Test failed: 1234: wrong status c000011b/c000007b
loader.c:720: Test failed: 1239: wrong status c000011b/c000007b
loader.c:720: Test failed: 1244: wrong status c000011b/c000007b
loader.c:720: Test failed: 1260: wrong status c000011b/0
loader.c:720: Test failed: 1264: wrong status c000011b/0
loader.c:720: Test failed: 1269: wrong status c000011b/0
loader.c:720: Test failed: 1273: wrong status c000011b/0
loader.c:720: Test failed: 1277: wrong status c000011b/0
loader.c:720: Test failed: 1431: wrong status c000011b/c000007b
loader.c:720: Test failed: 1439: wrong status c000011b/c000007b
loader.c:720: Test failed: 1444: wrong status c000011b/0
loader.c:724: Test failed: 1444: failed with c000011b expected fallback
loader.c:720: Test failed: 1450: wrong status c000011b/0
loader.c:724: Test failed: 1450: failed with c000011b expected fallback
loader.c:720: Test failed: 1456: wrong status c000011b/0
loader.c:724: Test failed: 1456: failed with c000011b expected fallback
loader.c:720: Test failed: 1463: wrong status c000011b/0
loader.c:724: Test failed: 1463: failed with c000011b expected fallback
loader.c:720: Test failed: 1469: wrong status c000011b/0
loader.c:720: Test failed: 1478: wrong status c000011b/0
loader.c:720: Test failed: 1482: wrong status c000011b/0
loader.c:720: Test failed: 1486: wrong status c000011b/0
loader.c:720: Test failed: 1490: wrong status c000011b/0
loader.c:720: Test failed: 1494: wrong status c000011b/0
=== w10pro64_he (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1197: wrong status c0000130/c000011b
loader.c:720: Test failed: 1224: wrong status c0000130/c000007b
loader.c:720: Test failed: 1229: wrong status c0000130/c000007b
loader.c:720: Test failed: 1234: wrong status c0000130/c000007b
loader.c:720: Test failed: 1239: wrong status c0000130/c000007b
loader.c:720: Test failed: 1244: wrong status c0000130/c000007b
loader.c:720: Test failed: 1260: wrong status c0000130/0
loader.c:720: Test failed: 1264: wrong status c0000130/0
loader.c:720: Test failed: 1269: wrong status c0000130/0
loader.c:720: Test failed: 1273: wrong status c0000130/0
loader.c:720: Test failed: 1277: wrong status c0000130/0
loader.c:720: Test failed: 1431: wrong status c0000130/c000007b
loader.c:720: Test failed: 1439: wrong status c0000130/c000007b
loader.c:720: Test failed: 1444: wrong status c0000130/0
loader.c:724: Test failed: 1444: failed with c0000130 expected fallback
loader.c:720: Test failed: 1450: wrong status c0000130/0
loader.c:724: Test failed: 1450: failed with c0000130 expected fallback
loader.c:720: Test failed: 1456: wrong status c0000130/0
loader.c:724: Test failed: 1456: failed with c0000130 expected fallback
loader.c:720: Test failed: 1463: wrong status c0000130/0
loader.c:724: Test failed: 1463: failed with c0000130 expected fallback
loader.c:720: Test failed: 1469: wrong status c0000130/0
loader.c:720: Test failed: 1478: wrong status c0000130/0
loader.c:720: Test failed: 1482: wrong status c0000130/0
loader.c:720: Test failed: 1486: wrong status c0000130/0
loader.c:720: Test failed: 1490: wrong status c0000130/0
loader.c:720: Test failed: 1494: wrong status c0000130/0
=== w10pro64_ja (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1219: wrong status c000011b/c0000130
loader.c:720: Test failed: 1224: wrong status c000011b/c000007b
loader.c:720: Test failed: 1229: wrong status c000011b/c000007b
loader.c:720: Test failed: 1234: wrong status c000011b/c000007b
loader.c:720: Test failed: 1239: wrong status c000011b/c000007b
loader.c:720: Test failed: 1244: wrong status c000011b/c000007b
loader.c:720: Test failed: 1260: wrong status c000011b/0
loader.c:720: Test failed: 1264: wrong status c000011b/0
loader.c:720: Test failed: 1269: wrong status c000011b/0
loader.c:720: Test failed: 1273: wrong status c000011b/0
loader.c:720: Test failed: 1277: wrong status c000011b/0
loader.c:720: Test failed: 1431: wrong status c000011b/c000007b
loader.c:720: Test failed: 1439: wrong status c000011b/c000007b
loader.c:720: Test failed: 1444: wrong status c000011b/0
loader.c:724: Test failed: 1444: failed with c000011b expected fallback
loader.c:720: Test failed: 1450: wrong status c000011b/0
loader.c:724: Test failed: 1450: failed with c000011b expected fallback
loader.c:720: Test failed: 1456: wrong status c000011b/0
loader.c:724: Test failed: 1456: failed with c000011b expected fallback
loader.c:720: Test failed: 1463: wrong status c000011b/0
loader.c:724: Test failed: 1463: failed with c000011b expected fallback
loader.c:720: Test failed: 1469: wrong status c000011b/0
loader.c:720: Test failed: 1478: wrong status c000011b/0
loader.c:720: Test failed: 1482: wrong status c000011b/0
loader.c:720: Test failed: 1486: wrong status c000011b/0
loader.c:720: Test failed: 1490: wrong status c000011b/0
loader.c:720: Test failed: 1494: wrong status c000011b/0
=== w10pro64_zh_CN (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1219: wrong status c000011b/c0000130
loader.c:720: Test failed: 1224: wrong status c000011b/c000007b
loader.c:720: Test failed: 1229: wrong status c000011b/c000007b
March 1, 2022
Re: [PATCH v2 5/5] include/windows.media.speechrecognition.idl: Add SpeechRecognizer.
by Zebediah Figura (she/her)
On 3/1/22 10:42, Rémi Bernon wrote:
> From: Bernhard Kölbl <besentv(a)gmail.com>
>
> And its dependencies.
>
> Signed-off-by: Bernhard Kölbl <besentv(a)gmail.com>
> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
> ---
>
> v2: Minor alignment tweaking, though how long can these lines be, oof...
>
Could we omit the fully qualified namespace?
March 1, 2022
Re: [PATCH v11 1/2] kernel32/tests: Test module refcounting with forwarded exports.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=109539
Your paranoid android.
=== w10pro64_ja (64 bit report) ===
kernel32:
comm.c:1586: Test failed: Unexpected time 250, expected around 500
=== w7u_2qxl (32 bit report) ===
kernel32:
debugger.c:1027: Test failed: ole32.dll was not reported
=== w7u_adm (32 bit report) ===
kernel32:
debugger.c:1027: Test failed: ole32.dll was not reported
=== w7u_el (32 bit report) ===
kernel32:
debugger.c:1027: Test failed: ole32.dll was not reported
=== w1064 (32 bit report) ===
kernel32:
debugger.c:1760: Test failed: unexpected instruction pointer 771516EC
=== w1064_tsign (32 bit report) ===
kernel32:
debugger.c:681: Test failed: debugger reported 7 failures
=== w10pro64 (32 bit report) ===
kernel32:
debugger.c:681: Test failed: debugger reported 7 failures
=== w10pro64 (32 bit report) ===
kernel32:
loader.c:3013: Test failed: attached thread count should be 2
=== w10pro64_ar (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1444: wrong status c000007b/0
loader.c:724: Test failed: 1444: failed with c000007b expected fallback
loader.c:720: Test failed: 1450: wrong status c000007b/0
loader.c:724: Test failed: 1450: failed with c000007b expected fallback
loader.c:720: Test failed: 1456: wrong status c000007b/0
loader.c:724: Test failed: 1456: failed with c000007b expected fallback
loader.c:720: Test failed: 1463: wrong status c000007b/0
loader.c:724: Test failed: 1463: failed with c000007b expected fallback
loader.c:720: Test failed: 1469: wrong status c000007b/0
=== w10pro64_ja (64 bit report) ===
kernel32:
loader.c:720: Test failed: 1192: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c0000131
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c0000130
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1197: wrong status c000012f/c000011b
loader.c:720: Test failed: 1214: wrong status c000012f/c0000130
loader.c:720: Test failed: 1219: wrong status c000012f/c0000130
loader.c:720: Test failed: 1224: wrong status c000012f/c000007b
loader.c:720: Test failed: 1229: wrong status c000012f/c000007b
loader.c:720: Test failed: 1234: wrong status c000012f/c000007b
loader.c:720: Test failed: 1239: wrong status c000012f/c000007b
loader.c:720: Test failed: 1244: wrong status c000012f/c000007b
loader.c:720: Test failed: 1260: wrong status c000012f/0
loader.c:720: Test failed: 1264: wrong status c000012f/0
loader.c:720: Test failed: 1269: wrong status c000012f/0
loader.c:720: Test failed: 1273: wrong status c000012f/0
loader.c:720: Test failed: 1277: wrong status c000012f/0
loader.c:720: Test failed: 1431: wrong status c000012f/c000007b
loader.c:720: Test failed: 1439: wrong status c000012f/c000007b
loader.c:720: Test failed: 1444: wrong status c000012f/0
loader.c:724: Test failed: 1444: failed with c000012f expected fallback
loader.c:720: Test failed: 1450: wrong status c000012f/0
loader.c:724: Test failed: 1450: failed with c000012f expected fallback
loader.c:720: Test failed: 1456: wrong status c000012f/0
loader.c:724: Test failed: 1456: failed with c000012f expected fallback
loader.c:720: Test failed: 1463: wrong status c000012f/0
loader.c:724: Test failed: 1463: failed with c000012f expected fallback
loader.c:720: Test failed: 1469: wrong status c000012f/0
loader.c:720: Test failed: 1478: wrong status c000012f/0
loader.c:720: Test failed: 1482: wrong status c000012f/0
=== w8adm (32 bit report) ===
kernel32:
path: Timeout
=== w10pro64_zh_CN (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w10pro64_zh_CN (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== w8 (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== debian11 (32 bit report) ===
kernel32:
change.c:309: Test failed: should be ready
change.c:339: Test failed: should be ready
March 1, 2022
Re: [PATCH 2/6] winealsa: Move timer_loop to the unixlib.
by Andrew Eikum
This one causes a ton of underruns with native xaudio2. I tested with
the "James Cameron's Avatar The Game Demo". I can provide you the
installation files, if you can't dig them up someplace.
It looks to me like the new thread timer slowly drifts, which means
the device eventually runs out of data and we never catch up (note
drifting thousandths and accumulating avail value):
8252.559:0174:trace:alsa:alsa_write_data avail: 3712
...
8252.619:0174:trace:alsa:alsa_write_data avail: 3616
8252.630:0174:trace:alsa:alsa_write_data avail: 3664
...
8252.720:0174:trace:alsa:alsa_write_data avail: 3712
8252.731:0174:trace:alsa:alsa_write_data avail: 3712
...
8252.841:0174:trace:alsa:alsa_write_data avail: 3808
8252.852:0174:trace:alsa:alsa_write_data avail: 3856
...
8252.972:0174:trace:alsa:alsa_write_data avail: 4000
8252.983:0174:trace:alsa:alsa_write_data avail: 4000
While the old timer-queue based method didn't drift (note consistent
thousandths):
8187.912:0140:trace:alsa:alsa_write_data avail: 1088
...
8188.072:0140:trace:alsa:alsa_write_data avail: 1088
8188.083:0140:trace:alsa:alsa_write_data avail: 1136
...
8188.212:0140:trace:alsa:alsa_write_data avail: 1280
...
8188.352:0140:trace:alsa:alsa_write_data avail: 1232
8188.362:0140:trace:alsa:alsa_write_data avail: 1280
...
8188.403:0140:trace:alsa:alsa_write_data avail: 1136
8188.412:0140:trace:alsa:alsa_write_data avail: 1184
The pulse driver doesn't run into this problem because it keeps track
of the time between callbacks and accounts for the drift, see the
'adjust' parameter and 'delay' calculation in
pulse.c:pulse_timer_loop.
We could do the same adjustment in ALSA, or find a way to keep using
the timer queue?
Andrew
On Fri, Feb 25, 2022 at 09:32:20AM +0000, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw(a)codeweavers.com>
> ---
> dlls/winealsa.drv/alsa.c | 230 +++++++++++++++++++++++++++++++++++
> dlls/winealsa.drv/mmdevdrv.c | 229 +++-------------------------------
> dlls/winealsa.drv/unixlib.h | 9 +-
> 3 files changed, 258 insertions(+), 210 deletions(-)
>
> diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
> index 73971c0f8bb..91ead000497 100644
> --- a/dlls/winealsa.drv/alsa.c
> +++ b/dlls/winealsa.drv/alsa.c
> @@ -960,6 +960,12 @@ static NTSTATUS release_stream(void *args)
> struct alsa_stream *stream = params->stream;
> SIZE_T size;
>
> + if(params->timer_thread){
> + stream->please_quit = TRUE;
> + NtWaitForSingleObject(params->timer_thread, FALSE, NULL);
> + NtClose(params->timer_thread);
> + }
> +
> snd_pcm_drop(stream->pcm_handle);
> snd_pcm_close(stream->pcm_handle);
> if(stream->local_buffer){
> @@ -1215,6 +1221,229 @@ static NTSTATUS write_best_effort(void *args)
> return STATUS_SUCCESS;
> }
>
> +static snd_pcm_sframes_t alsa_write_buffer_wrap(struct alsa_stream *stream, BYTE *buf,
> + snd_pcm_uframes_t buflen, snd_pcm_uframes_t offs,
> + snd_pcm_uframes_t to_write)
> +{
> + snd_pcm_sframes_t ret = 0;
> +
> + while(to_write){
> + snd_pcm_uframes_t chunk;
> + snd_pcm_sframes_t tmp;
> +
> + if(offs + to_write > buflen)
> + chunk = buflen - offs;
> + else
> + chunk = to_write;
> +
> + tmp = alsa_write_best_effort(stream, buf + offs * stream->fmt->nBlockAlign, chunk);
> + if(tmp < 0)
> + return ret;
> + if(!tmp)
> + break;
> +
> + ret += tmp;
> + to_write -= tmp;
> + offs += tmp;
> + offs %= buflen;
> + }
> +
> + return ret;
> +}
> +
> +static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize)
> +{
> + if(left <= right)
> + return right - left;
> + return bufsize - (left - right);
> +}
> +
> +static UINT data_not_in_alsa(struct alsa_stream *stream)
> +{
> + UINT32 diff;
> +
> + diff = buf_ptr_diff(stream->lcl_offs_frames, stream->wri_offs_frames, stream->bufsize_frames);
> + if(diff)
> + return diff;
> +
> + return stream->held_frames - stream->data_in_alsa_frames;
> +}
> +
> +/* Here's the buffer setup:
> + *
> + * vvvvvvvv sent to HW already
> + * vvvvvvvv in ALSA buffer but rewindable
> + * [dddddddddddddddd] ALSA buffer
> + * [dddddddddddddddd--------] mmdevapi buffer
> + * ^^^^^^^^ data_in_alsa_frames
> + * ^^^^^^^^^^^^^^^^ held_frames
> + * ^ lcl_offs_frames
> + * ^ wri_offs_frames
> + *
> + * GetCurrentPadding is held_frames
> + *
> + * During period callback, we decrement held_frames, fill ALSA buffer, and move
> + * lcl_offs forward
> + *
> + * During Stop, we rewind the ALSA buffer
> + */
> +static void alsa_write_data(struct alsa_stream *stream)
> +{
> + snd_pcm_sframes_t written;
> + snd_pcm_uframes_t avail, max_copy_frames, data_frames_played;
> + int err;
> +
> + /* this call seems to be required to get an accurate snd_pcm_state() */
> + avail = snd_pcm_avail_update(stream->pcm_handle);
> +
> + if(snd_pcm_state(stream->pcm_handle) == SND_PCM_STATE_XRUN){
> + TRACE("XRun state, recovering\n");
> +
> + avail = stream->alsa_bufsize_frames;
> +
> + if((err = snd_pcm_recover(stream->pcm_handle, -EPIPE, 1)) < 0)
> + WARN("snd_pcm_recover failed: %d (%s)\n", err, snd_strerror(err));
> +
> + if((err = snd_pcm_reset(stream->pcm_handle)) < 0)
> + WARN("snd_pcm_reset failed: %d (%s)\n", err, snd_strerror(err));
> +
> + if((err = snd_pcm_prepare(stream->pcm_handle)) < 0)
> + WARN("snd_pcm_prepare failed: %d (%s)\n", err, snd_strerror(err));
> + }
> +
> + TRACE("avail: %ld\n", avail);
> +
> + /* Add a lead-in when starting with too few frames to ensure
> + * continuous rendering. Additional benefit: Force ALSA to start. */
> + if(stream->data_in_alsa_frames == 0 && stream->held_frames < stream->alsa_period_frames)
> + {
> + alsa_write_best_effort(stream, stream->silence_buf,
> + stream->alsa_period_frames - stream->held_frames);
> + stream->vol_adjusted_frames = 0;
> + }
> +
> + if(stream->started)
> + max_copy_frames = data_not_in_alsa(stream);
> + else
> + max_copy_frames = 0;
> +
> + data_frames_played = min(stream->data_in_alsa_frames, avail);
> + stream->data_in_alsa_frames -= data_frames_played;
> +
> + if(stream->held_frames > data_frames_played){
> + if(stream->started)
> + stream->held_frames -= data_frames_played;
> + }else
> + stream->held_frames = 0;
> +
> + while(avail && max_copy_frames){
> + snd_pcm_uframes_t to_write;
> +
> + to_write = min(avail, max_copy_frames);
> +
> + written = alsa_write_buffer_wrap(stream, stream->local_buffer,
> + stream->bufsize_frames, stream->lcl_offs_frames, to_write);
> + if(written <= 0)
> + break;
> +
> + avail -= written;
> + stream->lcl_offs_frames += written;
> + stream->lcl_offs_frames %= stream->bufsize_frames;
> + stream->data_in_alsa_frames += written;
> + max_copy_frames -= written;
> + }
> +
> + if(stream->event)
> + NtSetEvent(stream->event, NULL);
> +}
> +
> +static void alsa_read_data(struct alsa_stream *stream)
> +{
> + snd_pcm_sframes_t nread;
> + UINT32 pos = stream->wri_offs_frames, limit = stream->held_frames;
> + unsigned int i;
> +
> + if(!stream->started)
> + goto exit;
> +
> + /* FIXME: Detect overrun and signal DATA_DISCONTINUITY
> + * How to count overrun frames and report them as position increase? */
> + limit = stream->bufsize_frames - max(limit, pos);
> +
> + nread = snd_pcm_readi(stream->pcm_handle,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> + TRACE("read %ld from %u limit %u\n", nread, pos, limit);
> + if(nread < 0){
> + int ret;
> +
> + if(nread == -EAGAIN) /* no data yet */
> + return;
> +
> + WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
> +
> + ret = snd_pcm_recover(stream->pcm_handle, nread, 0);
> + if(ret < 0){
> + WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
> + return;
> + }
> +
> + nread = snd_pcm_readi(stream->pcm_handle,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> + if(nread < 0){
> + WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
> + return;
> + }
> + }
> +
> + for(i = 0; i < stream->fmt->nChannels; i++)
> + if(stream->vols[i] != 0.0f)
> + break;
> + if(i == stream->fmt->nChannels){ /* mute */
> + int err;
> + if((err = snd_pcm_format_set_silence(stream->alsa_format,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign,
> + nread)) < 0)
> + WARN("Setting buffer to silence failed: %d (%s)\n", err,
> + snd_strerror(err));
> + }
> +
> + stream->wri_offs_frames += nread;
> + stream->wri_offs_frames %= stream->bufsize_frames;
> + stream->held_frames += nread;
> +
> +exit:
> + if(stream->event)
> + NtSetEvent(stream->event, NULL);
> +}
> +
> +static NTSTATUS timer_loop(void *args)
> +{
> + struct timer_loop_params *params = args;
> + struct alsa_stream *stream = params->stream;
> + LARGE_INTEGER delay;
> +
> + alsa_lock(stream);
> +
> + delay.QuadPart = -stream->mmdev_period_rt;
> +
> + while(!stream->please_quit){
> + NtQueryPerformanceCounter(&stream->last_period_time, NULL);
> +
> + if(stream->flow == eRender)
> + alsa_write_data(stream);
> + else if(stream->flow == eCapture)
> + alsa_read_data(stream);
> +
> + alsa_unlock(stream);
> + NtDelayExecution(FALSE, &delay);
> + alsa_lock(stream);
> + }
> +
> + alsa_unlock(stream);
> +
> + return STATUS_SUCCESS;
> +}
> +
> static NTSTATUS is_format_supported(void *args)
> {
> struct is_format_supported_params *params = args;
> @@ -1522,6 +1751,7 @@ unixlib_entry_t __wine_unix_call_funcs[] =
> get_endpoint_ids,
> create_stream,
> release_stream,
> + timer_loop,
> is_format_supported,
> get_mix_format,
> get_buffer_size,
> diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
> index c06b08709f2..2748cc552a6 100644
> --- a/dlls/winealsa.drv/mmdevdrv.c
> +++ b/dlls/winealsa.drv/mmdevdrv.c
> @@ -109,7 +109,7 @@ struct ACImpl {
> UINT32 channel_count;
> struct alsa_stream *stream;
>
> - HANDLE timer;
> + HANDLE timer_thread;
>
> AudioSession *session;
> AudioSessionWrapper *session_wrapper;
> @@ -128,8 +128,6 @@ typedef struct _SessionMgr {
> IMMDevice *device;
> } SessionMgr;
>
> -static HANDLE g_timer_q;
> -
> static CRITICAL_SECTION g_sessions_lock;
> static CRITICAL_SECTION_DEBUG g_sessions_lock_debug =
> {
> @@ -216,9 +214,6 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
> if(NtQueryVirtualMemory(GetCurrentProcess(), dll, MemoryWineUnixFuncs,
> &alsa_handle, sizeof(alsa_handle), NULL))
> return FALSE;
> - g_timer_q = CreateTimerQueue();
> - if(!g_timer_q)
> - return FALSE;
> break;
>
> case DLL_PROCESS_DETACH:
> @@ -252,17 +247,30 @@ static void alsa_unlock(struct alsa_stream *stream)
> pthread_mutex_unlock(&stream->lock);
> }
>
> -static HRESULT alsa_stream_release(struct alsa_stream *stream)
> +static HRESULT alsa_stream_release(struct alsa_stream *stream, HANDLE timer_thread)
> {
> struct release_stream_params params;
>
> params.stream = stream;
> + params.timer_thread = timer_thread;
>
> ALSA_CALL(release_stream, ¶ms);
>
> return params.result;
> }
>
> +static DWORD WINAPI alsa_timer_thread(void *user)
> +{
> + struct alsa_stream *stream = user;
> + struct timer_loop_params params;
> +
> + params.stream = stream;
> +
> + ALSA_CALL(timer_loop, ¶ms);
> +
> + return 0;
> +}
> +
> static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
> GUID *guid)
> {
> @@ -552,17 +560,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
> ref = InterlockedDecrement(&This->ref);
> TRACE("(%p) Refcount now %u\n", This, ref);
> if(!ref){
> - if(This->timer){
> - HANDLE event;
> - DWORD wait;
> - event = CreateEventW(NULL, TRUE, FALSE, NULL);
> - wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event);
> - wait = wait && GetLastError() == ERROR_IO_PENDING;
> - if(event && wait)
> - WaitForSingleObject(event, INFINITE);
> - CloseHandle(event);
> - }
> -
> IAudioClient3_Stop(iface);
> IMMDevice_Release(This->parent);
> IUnknown_Release(This->pUnkFTMarshal);
> @@ -573,7 +570,7 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
> }
> HeapFree(GetProcessHeap(), 0, This->vols);
> if (This->stream)
> - alsa_stream_release(This->stream);
> + alsa_stream_release(This->stream, This->timer_thread);
> HeapFree(GetProcessHeap(), 0, This);
> }
> return ref;
> @@ -807,7 +804,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>
> exit:
> if(FAILED(params.result)){
> - alsa_stream_release(stream);
> + alsa_stream_release(stream, NULL);
> HeapFree(GetProcessHeap(), 0, This->vols);
> This->vols = NULL;
> }else{
> @@ -1011,187 +1008,6 @@ static snd_pcm_sframes_t alsa_write_buffer_wrap(struct alsa_stream *stream, BYTE
> return ret;
> }
>
> -static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize)
> -{
> - if(left <= right)
> - return right - left;
> - return bufsize - (left - right);
> -}
> -
> -static UINT data_not_in_alsa(struct alsa_stream *stream)
> -{
> - UINT32 diff;
> -
> - diff = buf_ptr_diff(stream->lcl_offs_frames, stream->wri_offs_frames, stream->bufsize_frames);
> - if(diff)
> - return diff;
> -
> - return stream->held_frames - stream->data_in_alsa_frames;
> -}
> -/* Here's the buffer setup:
> - *
> - * vvvvvvvv sent to HW already
> - * vvvvvvvv in ALSA buffer but rewindable
> - * [dddddddddddddddd] ALSA buffer
> - * [dddddddddddddddd--------] mmdevapi buffer
> - * ^^^^^^^^ data_in_alsa_frames
> - * ^^^^^^^^^^^^^^^^ held_frames
> - * ^ lcl_offs_frames
> - * ^ wri_offs_frames
> - *
> - * GetCurrentPadding is held_frames
> - *
> - * During period callback, we decrement held_frames, fill ALSA buffer, and move
> - * lcl_offs forward
> - *
> - * During Stop, we rewind the ALSA buffer
> - */
> -static void alsa_write_data(struct alsa_stream *stream)
> -{
> - snd_pcm_sframes_t written;
> - snd_pcm_uframes_t avail, max_copy_frames, data_frames_played;
> - int err;
> -
> - /* this call seems to be required to get an accurate snd_pcm_state() */
> - avail = snd_pcm_avail_update(stream->pcm_handle);
> -
> - if(snd_pcm_state(stream->pcm_handle) == SND_PCM_STATE_XRUN){
> - TRACE("XRun state, recovering\n");
> -
> - avail = stream->alsa_bufsize_frames;
> -
> - if((err = snd_pcm_recover(stream->pcm_handle, -EPIPE, 1)) < 0)
> - WARN("snd_pcm_recover failed: %d (%s)\n", err, snd_strerror(err));
> -
> - if((err = snd_pcm_reset(stream->pcm_handle)) < 0)
> - WARN("snd_pcm_reset failed: %d (%s)\n", err, snd_strerror(err));
> -
> - if((err = snd_pcm_prepare(stream->pcm_handle)) < 0)
> - WARN("snd_pcm_prepare failed: %d (%s)\n", err, snd_strerror(err));
> - }
> -
> - TRACE("avail: %ld\n", avail);
> -
> - /* Add a lead-in when starting with too few frames to ensure
> - * continuous rendering. Additional benefit: Force ALSA to start. */
> - if(stream->data_in_alsa_frames == 0 && stream->held_frames < stream->alsa_period_frames)
> - {
> - alsa_write_best_effort(stream, stream->silence_buf,
> - stream->alsa_period_frames - stream->held_frames);
> - stream->vol_adjusted_frames = 0;
> - }
> -
> - if(stream->started)
> - max_copy_frames = data_not_in_alsa(stream);
> - else
> - max_copy_frames = 0;
> -
> - data_frames_played = min(stream->data_in_alsa_frames, avail);
> - stream->data_in_alsa_frames -= data_frames_played;
> -
> - if(stream->held_frames > data_frames_played){
> - if(stream->started)
> - stream->held_frames -= data_frames_played;
> - }else
> - stream->held_frames = 0;
> -
> - while(avail && max_copy_frames){
> - snd_pcm_uframes_t to_write;
> -
> - to_write = min(avail, max_copy_frames);
> -
> - written = alsa_write_buffer_wrap(stream, stream->local_buffer,
> - stream->bufsize_frames, stream->lcl_offs_frames, to_write);
> - if(written <= 0)
> - break;
> -
> - avail -= written;
> - stream->lcl_offs_frames += written;
> - stream->lcl_offs_frames %= stream->bufsize_frames;
> - stream->data_in_alsa_frames += written;
> - max_copy_frames -= written;
> - }
> -
> - if(stream->event)
> - SetEvent(stream->event);
> -}
> -
> -static void alsa_read_data(struct alsa_stream *stream)
> -{
> - snd_pcm_sframes_t nread;
> - UINT32 pos = stream->wri_offs_frames, limit = stream->held_frames;
> - unsigned int i;
> -
> - if(!stream->started)
> - goto exit;
> -
> - /* FIXME: Detect overrun and signal DATA_DISCONTINUITY
> - * How to count overrun frames and report them as position increase? */
> - limit = stream->bufsize_frames - max(limit, pos);
> -
> - nread = snd_pcm_readi(stream->pcm_handle,
> - stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> - TRACE("read %ld from %u limit %u\n", nread, pos, limit);
> - if(nread < 0){
> - int ret;
> -
> - if(nread == -EAGAIN) /* no data yet */
> - return;
> -
> - WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
> -
> - ret = snd_pcm_recover(stream->pcm_handle, nread, 0);
> - if(ret < 0){
> - WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
> - return;
> - }
> -
> - nread = snd_pcm_readi(stream->pcm_handle,
> - stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> - if(nread < 0){
> - WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
> - return;
> - }
> - }
> -
> - for(i = 0; i < stream->fmt->nChannels; i++)
> - if(stream->vols[i] != 0.0f)
> - break;
> - if(i == stream->fmt->nChannels){ /* mute */
> - int err;
> - if((err = snd_pcm_format_set_silence(stream->alsa_format,
> - stream->local_buffer + pos * stream->fmt->nBlockAlign,
> - nread)) < 0)
> - WARN("Setting buffer to silence failed: %d (%s)\n", err,
> - snd_strerror(err));
> - }
> -
> - stream->wri_offs_frames += nread;
> - stream->wri_offs_frames %= stream->bufsize_frames;
> - stream->held_frames += nread;
> -
> -exit:
> - if(stream->event)
> - SetEvent(stream->event);
> -}
> -
> -static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
> -{
> - ACImpl *This = user;
> - struct alsa_stream *stream = This->stream;
> -
> - alsa_lock(stream);
> -
> - QueryPerformanceCounter(&stream->last_period_time);
> -
> - if(stream->flow == eRender)
> - alsa_write_data(stream);
> - else if(stream->flow == eCapture)
> - alsa_read_data(stream);
> -
> - alsa_unlock(stream);
> -}
> -
> static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream)
> {
> LARGE_INTEGER time_freq, current_time, time_diff;
> @@ -1291,14 +1107,9 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
> }
> }
>
> - if(!This->timer){
> - if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
> - This, 0, stream->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
> - alsa_unlock(stream);
> - LeaveCriticalSection(&g_sessions_lock);
> - WARN("Unable to create timer: %u\n", GetLastError());
> - return E_OUTOFMEMORY;
> - }
> + if(!This->timer_thread){
> + This->timer_thread = CreateThread(NULL, 0, alsa_timer_thread, This->stream, 0, NULL);
> + SetThreadPriority(This->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
> }
>
> stream->started = TRUE;
> diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
> index 3fd6d2a73ee..4acbbcbcf11 100644
> --- a/dlls/winealsa.drv/unixlib.h
> +++ b/dlls/winealsa.drv/unixlib.h
> @@ -37,7 +37,7 @@ struct alsa_stream
> int alsa_channels;
> int alsa_channel_map[32];
>
> - BOOL started;
> + BOOL started, please_quit;
> REFERENCE_TIME mmdev_period_rt;
> UINT64 written_frames, last_pos_frames;
> UINT32 bufsize_frames, held_frames, tmp_buffer_frames, mmdev_period_frames;
> @@ -87,9 +87,15 @@ struct create_stream_params
> struct release_stream_params
> {
> struct alsa_stream *stream;
> + HANDLE timer_thread;
> HRESULT result;
> };
>
> +struct timer_loop_params
> +{
> + struct alsa_stream *stream;
> +};
> +
> struct is_format_supported_params
> {
> const char *alsa_name;
> @@ -142,6 +148,7 @@ enum alsa_funcs
> alsa_get_endpoint_ids,
> alsa_create_stream,
> alsa_release_stream,
> + alsa_timer_loop,
> alsa_is_format_supported,
> alsa_get_mix_format,
> alsa_get_buffer_size,
> --
> 2.25.1
>
>
March 1, 2022