Wine-devel
Threads by month
- ----- 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
November 2021
- 83 participants
- 756 discussions
[PATCH v2 01/12] mshtml: Clear the string dprop associated with the builtin attribute when removing it.
by Gabriel Ivăncescu 17 Nov '21
by Gabriel Ivăncescu 17 Nov '21
17 Nov '21
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/mshtml/dispex.c | 13 ++++---
dlls/mshtml/tests/documentmode.js | 56 +++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 96a776d..4605fda 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -1463,13 +1463,18 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
*success = VARIANT_TRUE;
return S_OK;
}
+ *success = VARIANT_TRUE;
V_VT(&var) = VT_EMPTY;
hres = builtin_propput(This, func, &dp, NULL);
- if(FAILED(hres))
- return hres;
-
- *success = VARIANT_TRUE;
+ if(FAILED(hres)) {
+ VARIANT *ref;
+ hres = dispex_get_dprop_ref(This, func->name, FALSE, &ref);
+ if(FAILED(hres) || V_VT(ref) != VT_BSTR)
+ *success = VARIANT_FALSE;
+ else
+ VariantClear(ref);
+ }
return S_OK;
}
default:
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index d566223..9db1b4f 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -1087,6 +1087,62 @@ sync_test("elem_attr", function() {
ok(r === "cls2", "class attr = " + r);
r = elem.getAttribute("className");
ok(r === "cls3", "className attr = " + r);
+
+ var func = function() { };
+ elem.onclick = func;
+ ok(elem.onclick === func, "onclick = " + elem.onclick);
+ r = elem.getAttribute("onclick");
+ ok(r === (v < 8 ? func : null), "onclick attr = " + r);
+ r = elem.removeAttribute("onclick");
+ todo_wine_if(v === 8).
+ ok(r === (v < 9 ? false : undefined), "removeAttribute returned " + r);
+ todo_wine_if(v === 8).
+ ok(elem.onclick === (v != 8 ? func : null), "removed onclick = " + elem.onclick);
+
+ elem.onclick_test = func;
+ ok(elem.onclick_test === func, "onclick_test = " + elem.onclick_test);
+ r = elem.getAttribute("onclick_test");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? func : (v < 9 ? func.toString() : null)), "onclick_test attr = " + r);
+
+ elem.setAttribute("onclick", "test");
+ r = elem.getAttribute("onclick");
+ ok(r === "test", "onclick attr after setAttribute = " + r);
+ r = elem.removeAttribute("onclick");
+ ok(r === (v < 9 ? true : undefined), "removeAttribute after setAttribute returned " + r);
+
+ /* IE11 returns an empty function, which we can't check directly */
+ todo_wine_if(v >= 8).
+ ok((v < 11) ? (elem.onclick === null) : (elem.onclick !== func), "removed onclick after setAttribute = " + elem.onclick);
+
+ r = Object.prototype.toString.call(elem.onclick);
+ todo_wine_if(v >= 8 && v < 11).
+ ok(r === (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]")),
+ "removed onclick after setAttribute Object.toString returned " + r);
+
+ elem.setAttribute("onclick", "string");
+ r = elem.getAttribute("onclick");
+ ok(r === "string", "onclick attr after setAttribute = " + r);
+ elem.onclick = func;
+ ok(elem.onclick === func, "onclick = " + elem.onclick);
+ r = elem.getAttribute("onclick");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? func : (v < 9 ? null : "string")), "onclick attr = " + r);
+ elem.onclick = "test";
+ r = elem.getAttribute("onclick");
+ todo_wine_if(v === 8).
+ ok(r === (v < 9 ? "test" : "string"), "onclick attr = " + r);
+ r = elem.removeAttribute("onclick");
+ ok(r === (v < 9 ? true : undefined), "removeAttribute returned " + r);
+ todo_wine_if(v >= 8).
+ ok(elem.onclick === null, "removed onclick = " + elem.onclick);
+
+ elem.setAttribute("ondblclick", "string");
+ r = elem.getAttribute("ondblclick");
+ ok(r === "string", "ondblclick string = " + r);
+ r = elem.removeAttribute("ondblclick");
+ ok(r === (v < 9 ? true : undefined), "ondblclick string removeAttribute returned " + r);
+ ok(elem.ondblclick === null, "removed ondblclick string = " + elem.ondblclick);
});
sync_test("__proto__", function() {
--
2.31.1
3
23
Signed-off-by: André Zwing <nerv(a)dawncrow.de>
---
dlls/avicap32/v4l.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/avicap32/v4l.c b/dlls/avicap32/v4l.c
index ef41b7e281b..4b285d94c3c 100644
--- a/dlls/avicap32/v4l.c
+++ b/dlls/avicap32/v4l.c
@@ -143,4 +143,4 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
#endif /* _WIN64 */
-#endif /* HAVE_LINUX_VIDEODEV_2 */
+#endif /* HAVE_LINUX_VIDEODEV2_H */
--
2.25.1
1
0
Signed-off-by: André Zwing <nerv(a)dawncrow.de>
---
dlls/avicap32/v4l.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/avicap32/v4l.c b/dlls/avicap32/v4l.c
index ef41b7e281b..4b285d94c3c 100644
--- a/dlls/avicap32/v4l.c
+++ b/dlls/avicap32/v4l.c
@@ -143,4 +143,4 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
#endif /* _WIN64 */
-#endif /* HAVE_LINUX_VIDEODEV_2 */
+#endif /* HAVE_LINUX_VIDEODEV2_H */
--
2.25.1
2
1
17 Nov '21
Signed-off-by: Floris Renaud <jkfloris(a)dds.nl>
---
programs/winecfg/winecfg.man.in | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/programs/winecfg/winecfg.man.in b/programs/winecfg/winecfg.man.in
index 522d2a0e812..fc624504388 100644
--- a/programs/winecfg/winecfg.man.in
+++ b/programs/winecfg/winecfg.man.in
@@ -1,14 +1,32 @@
-.TH WINECFG 1 "November 2010" "@PACKAGE_STRING@" "Wine Programs"
+.TH WINECFG 1 "November 2021" "@PACKAGE_STRING@" "Wine Programs"
.SH NAME
winecfg \- Wine Configuration Editor
.SH SYNOPSIS
-.BR "winecfg"
+.B winecfg
+.RI [ options ]
.SH DESCRIPTION
.B winecfg
is the Wine configuration editor. It allows you to change several settings, such as DLL load order
(native versus builtin), enable a virtual desktop, setup disk drives, and change the Wine audio driver,
among others. Many of these settings can be made on a per application basis, for example, preferring native
riched20.dll for wordpad.exe, but not for notepad.exe.
+
+If no option is given launch the graphical version of
+.BR winecfg .
+.SH OPTIONS
+.TP
+\fB\-v \fR[\fIversion\fR], \fB/v \fR[\fB\fIversion\fR]
+Set global Windows version to
+.I version
+and exit.
+If
+.I version
+is not specified, display the current global Windows version and exit.
+.TP
+.BR \-? ", " /?
+Display help, valid versions for
+.I version
+and exit.
.SH BUGS
Bugs can be reported on the
.UR https://bugs.winehq.org
--
2.33.1
1
0
[PATCH v2] dsound: Correctly report hardware audio buffers as unsupported.
by Eduard Permyakov 17 Nov '21
by Eduard Permyakov 17 Nov '21
17 Nov '21
Signed-off-by: Eduard Permyakov <epermyakov(a)codeweavers.com>
---
dlls/dsound/dsound.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 3085d86e5b5..bcff0d8642a 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -373,12 +373,12 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU
device->drvcaps.dwPrimaryBuffers = 1;
device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
- device->drvcaps.dwMaxHwMixingAllBuffers = 16;
+ device->drvcaps.dwMaxHwMixingAllBuffers = 1;
device->drvcaps.dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
device->drvcaps.dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
- device->drvcaps.dwFreeHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
- device->drvcaps.dwFreeHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
- device->drvcaps.dwFreeHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
+ device->drvcaps.dwFreeHwMixingAllBuffers = 0;
+ device->drvcaps.dwFreeHwMixingStaticBuffers = 0;
+ device->drvcaps.dwFreeHwMixingStreamingBuffers = 0;
ZeroMemory(&device->volpan, sizeof(device->volpan));
@@ -435,11 +435,10 @@ static HRESULT DirectSoundDevice_CreateSoundBuffer(
}
if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) &&
- dsbd->dwFlags & DSBCAPS_LOCHARDWARE &&
- device->drvcaps.dwFreeHwMixingAllBuffers == 0)
+ dsbd->dwFlags & DSBCAPS_LOCHARDWARE)
{
- WARN("ran out of emulated hardware buffers\n");
- return DSERR_ALLOCATED;
+ WARN("unable to create hardware buffer\n");
+ return DSERR_UNSUPPORTED;
}
if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
--
2.25.1
3
2
[PATCH v2 6/6] winecoreaudio: Store the channel count and period_ms directly in the audio client.
by Andrew Eikum 17 Nov '21
by Andrew Eikum 17 Nov '21
17 Nov '21
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 41 +++++++++++++++++--------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index ebab18df75b..1e37a2a9026 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -124,6 +124,7 @@ struct ACImpl {
IUnknown *pUnkFTMarshal;
EDataFlow dataflow;
+ UINT32 channel_count, period_ms;
DWORD flags;
HANDLE event;
float *vols;
@@ -1179,7 +1180,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
ACImpl *This = impl_from_IAudioClient3(iface);
HRESULT hr;
OSStatus sc;
- int i;
+ UINT32 i;
TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
@@ -1342,20 +1343,22 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
This->stream->cap_buffer = HeapAlloc(GetProcessHeap(), 0, This->stream->cap_bufsize_frames * This->stream->fmt->nBlockAlign);
}
- This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
- if(!This->vols){
- CoTaskMemFree(This->stream->fmt);
- This->stream->fmt = NULL;
- OSSpinLockUnlock(&This->stream->lock);
- LeaveCriticalSection(&g_sessions_lock);
- return E_OUTOFMEMORY;
- }
-
- for(i = 0; i < fmt->nChannels; ++i)
- This->vols[i] = 1.f;
-
This->stream->share = mode;
This->flags = flags;
+ This->channel_count = fmt->nChannels;
+ This->period_ms = period / 10000;
+
+ This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
+ if(!This->vols){
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
+ return E_OUTOFMEMORY;
+ }
+
+ for(i = 0; i < This->channel_count; ++i)
+ This->vols[i] = 1.f;
hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
&This->session);
@@ -1906,7 +1909,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
if(This->event && !This->timer)
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb,
- This, 0, This->stream->period_ms, WT_EXECUTEINTIMERTHREAD)){
+ This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){
This->timer = NULL;
OSSpinLockUnlock(&This->stream->lock);
WARN("Unable to create timer: %u\n", GetLastError());
@@ -3173,7 +3176,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
if(!out)
return E_POINTER;
- *out = This->stream->fmt->nChannels;
+ *out = This->channel_count;
return S_OK;
}
@@ -3189,7 +3192,7 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(level < 0.f || level > 1.f)
return E_INVALIDARG;
- if(index >= This->stream->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
@@ -3214,7 +3217,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
if(!level)
return E_POINTER;
- if(index >= This->stream->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
*level = This->vols[index];
@@ -3234,7 +3237,7 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->stream->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
@@ -3260,7 +3263,7 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->stream->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&g_sessions_lock);
--
2.33.1
1
0
[PATCH v2 5/6] winecoreaudio: Use the global lock to protect the audio client.
by Andrew Eikum 17 Nov '21
by Andrew Eikum 17 Nov '21
17 Nov '21
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 115 +++++++++++++++---------------
1 file changed, 59 insertions(+), 56 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index e82962db1ba..ebab18df75b 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -1234,16 +1234,19 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
}
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
if(This->initted){
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_ALREADY_INITIALIZED;
}
+ OSSpinLockLock(&This->stream->lock);
+
This->stream->fmt = clone_format(fmt);
if(!This->stream->fmt){
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
@@ -1259,6 +1262,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return hr;
}
@@ -1278,6 +1282,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
}else{
@@ -1294,6 +1299,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
}
@@ -1308,6 +1314,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
@@ -1323,6 +1330,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return osstatus_to_hresult(sc);
}
@@ -1339,6 +1347,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
@@ -1348,29 +1357,26 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
This->stream->share = mode;
This->flags = flags;
- EnterCriticalSection(&g_sessions_lock);
-
hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
&This->session);
if(FAILED(hr)){
- LeaveCriticalSection(&g_sessions_lock);
CoTaskMemFree(This->stream->fmt);
This->stream->fmt = NULL;
HeapFree(GetProcessHeap(), 0, This->vols);
This->vols = NULL;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_INVALIDARG;
}
list_add_tail(&This->session->clients, &This->entry);
- LeaveCriticalSection(&g_sessions_lock);
-
ca_setvol(This, -1);
This->initted = TRUE;
OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -1983,41 +1989,35 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
HANDLE event)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ HRESULT hr = S_OK;
TRACE("(%p)->(%p)\n", This, event);
if(!event)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
- if(!This->initted){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
- }
-
- if (This->event){
- OSSpinLockUnlock(&This->stream->lock);
+ if(!This->initted)
+ hr = AUDCLNT_E_NOT_INITIALIZED;
+ else if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
+ hr = AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
+ else if(This->event){
FIXME("called twice\n");
- return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
- }
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
+ }else
+ This->event = event;
- This->event = event;
+ LeaveCriticalSection(&g_sessions_lock);
- OSSpinLockUnlock(&This->stream->lock);
-
- return S_OK;
+ return hr;
}
static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
void **ppv)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ HRESULT hr;
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
@@ -2025,24 +2025,24 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
return E_POINTER;
*ppv = NULL;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
if(!This->initted){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
+ hr = AUDCLNT_E_NOT_INITIALIZED;
+ goto end;
}
if(IsEqualIID(riid, &IID_IAudioRenderClient)){
if(This->dataflow != eRender){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ goto end;
}
IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
*ppv = &This->IAudioRenderClient_iface;
}else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
if(This->dataflow != eCapture){
- OSSpinLockUnlock(&This->stream->lock);
- return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE;
+ goto end;
}
IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
*ppv = &This->IAudioCaptureClient_iface;
@@ -2056,8 +2056,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
@@ -2067,8 +2067,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
@@ -2078,8 +2078,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->stream->lock);
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto end;
}
}else
ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
@@ -2087,15 +2087,15 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
*ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
}
- if(*ppv){
- OSSpinLockUnlock(&This->stream->lock);
- return S_OK;
+ if(*ppv) hr = S_OK;
+ else{
+ return E_NOINTERFACE;
+ FIXME("stub %s\n", debugstr_guid(riid));
}
- OSSpinLockUnlock(&This->stream->lock);
-
- FIXME("stub %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
+end:
+ LeaveCriticalSection(&g_sessions_lock);
+ return hr;
}
static HRESULT WINAPI AudioClient_IsOffloadCapable(IAudioClient3 *iface,
@@ -2749,17 +2749,20 @@ static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
{
AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
ULONG ref;
+
+ EnterCriticalSection(&g_sessions_lock);
+
ref = InterlockedDecrement(&This->ref);
TRACE("(%p) Refcount now %u\n", This, ref);
if(!ref){
if(This->client){
- OSSpinLockLock(&This->client->stream->lock);
This->client->session_wrapper = NULL;
- OSSpinLockUnlock(&This->client->stream->lock);
AudioClient_Release(&This->client->IAudioClient3_iface);
}
HeapFree(GetProcessHeap(), 0, This);
}
+
+ LeaveCriticalSection(&g_sessions_lock);
return ref;
}
@@ -3189,14 +3192,14 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(index >= This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
This->vols[index] = level;
WARN("CoreAudio doesn't support per-channel volume control\n");
ret = ca_setvol(This, index);
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3223,7 +3226,7 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
IAudioStreamVolume *iface, UINT32 count, const float *levels)
{
ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
+ UINT32 i;
HRESULT ret;
TRACE("(%p)->(%d, %p)\n", This, count, levels);
@@ -3234,14 +3237,14 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
This->vols[i] = levels[i];
ret = ca_setvol(This, -1);
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3250,7 +3253,7 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
IAudioStreamVolume *iface, UINT32 count, float *levels)
{
ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
+ UINT32 i;
TRACE("(%p)->(%d, %p)\n", This, count, levels);
@@ -3260,12 +3263,12 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->stream->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
levels[i] = This->vols[i];
- OSSpinLockUnlock(&This->stream->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
--
2.33.1
1
0
17 Nov '21
From: Huw Davies <huw(a)codeweavers.com>
Mainly just for simplicity.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index 11be188d110..e82962db1ba 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -96,8 +96,6 @@ typedef struct _AudioSession {
float *channel_vols;
BOOL mute;
- CRITICAL_SECTION lock;
-
struct list entry;
} AudioSession;
@@ -827,9 +825,6 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
list_add_head(&g_sessions, &ret->entry);
- InitializeCriticalSection(&ret->lock);
- ret->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AudioSession.lock");
-
session_init_vols(ret, num_channels);
ret->master_vol = 1.f;
@@ -3056,13 +3051,13 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->master_vol = level;
ret = ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3094,13 +3089,13 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->mute = mute;
ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3356,14 +3351,14 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->channel_vols[index] = level;
WARN("CoreAudio doesn't support per-channel volume control\n");
ret = ca_session_setvol(session, index);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
@@ -3408,14 +3403,14 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
if(context)
FIXME("Notifications not supported yet\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
session->channel_vols[i] = levels[i];
ret = ca_session_setvol(session, -1);
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return ret;
}
--
2.33.1
1
0
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/winecoreaudio.drv/mmdevdrv.c | 633 +++++++++++++++---------------
dlls/winecoreaudio.drv/unixlib.h | 23 ++
2 files changed, 337 insertions(+), 319 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index f8b538971f2..11be188d110 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -125,35 +125,21 @@ struct ACImpl {
IMMDevice *parent;
IUnknown *pUnkFTMarshal;
- WAVEFORMATEX *fmt;
-
EDataFlow dataflow;
DWORD flags;
- AUDCLNT_SHAREMODE share;
HANDLE event;
float *vols;
BOOL initted;
AudioDeviceID adevid;
AudioObjectPropertyScope scope;
- AudioConverterRef converter;
- AudioComponentInstance unit;
- AudioStreamBasicDescription dev_desc; /* audio unit format, not necessarily the same as fmt */
HANDLE timer;
- UINT32 period_ms, bufsize_frames, period_frames;
- UINT64 written_frames;
- UINT32 lcl_offs_frames, wri_offs_frames, held_frames, tmp_buffer_frames;
- UINT32 cap_bufsize_frames, cap_offs_frames, cap_held_frames, wrap_bufsize_frames, resamp_bufsize_frames;
- INT32 getbuf_last;
- BOOL playing;
- BYTE *cap_buffer, *wrap_buffer, *resamp_buffer, *local_buffer, *tmp_buffer;
AudioSession *session;
AudioSessionWrapper *session_wrapper;
+ struct coreaudio_stream *stream;
struct list entry;
-
- OSSpinLock lock;
};
static const IAudioClient3Vtbl AudioClient3_Vtbl;
@@ -556,6 +542,11 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
if(!This)
return E_OUTOFMEMORY;
+ This->stream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->stream));
+ if(!This->stream){
+ HeapFree(GetProcessHeap(), 0, This);
+ return E_OUTOFMEMORY;
+ }
This->IAudioClient3_iface.lpVtbl = &AudioClient3_Vtbl;
This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
@@ -571,14 +562,16 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
else if(dataflow == eCapture)
This->scope = kAudioDevicePropertyScopeInput;
else{
+ HeapFree(GetProcessHeap(), 0, This->stream);
HeapFree(GetProcessHeap(), 0, This);
return E_INVALIDARG;
}
- This->lock = 0;
+ This->stream->lock = 0;
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&This->IAudioClient3_iface, &This->pUnkFTMarshal);
if (FAILED(hr)) {
+ HeapFree(GetProcessHeap(), 0, This->stream);
HeapFree(GetProcessHeap(), 0, This);
return hr;
}
@@ -588,7 +581,8 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
This->adevid = adevid;
- if(!(This->unit = get_audiounit(This->dataflow, This->adevid))){
+ if(!(This->stream->unit = get_audiounit(This->dataflow, This->adevid))){
+ HeapFree(GetProcessHeap(), 0, This->stream);
HeapFree(GetProcessHeap(), 0, This);
return AUDCLNT_E_DEVICE_INVALIDATED;
}
@@ -650,24 +644,25 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
- AudioOutputUnitStop(This->unit);
- AudioComponentInstanceDispose(This->unit);
- if(This->converter)
- AudioConverterDispose(This->converter);
+ AudioOutputUnitStop(This->stream->unit);
+ AudioComponentInstanceDispose(This->stream->unit);
+ if(This->stream->converter)
+ AudioConverterDispose(This->stream->converter);
if(This->session){
EnterCriticalSection(&g_sessions_lock);
list_remove(&This->entry);
LeaveCriticalSection(&g_sessions_lock);
}
HeapFree(GetProcessHeap(), 0, This->vols);
- HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
- HeapFree(GetProcessHeap(), 0, This->cap_buffer);
- HeapFree(GetProcessHeap(), 0, This->local_buffer);
- free(This->wrap_buffer);
- HeapFree(GetProcessHeap(), 0, This->resamp_buffer);
- CoTaskMemFree(This->fmt);
+ HeapFree(GetProcessHeap(), 0, This->stream->tmp_buffer);
+ HeapFree(GetProcessHeap(), 0, This->stream->cap_buffer);
+ HeapFree(GetProcessHeap(), 0, This->stream->local_buffer);
+ free(This->stream->wrap_buffer);
+ HeapFree(GetProcessHeap(), 0, This->stream->resamp_buffer);
+ CoTaskMemFree(This->stream->fmt);
IMMDevice_Release(This->parent);
IUnknown_Release(This->pUnkFTMarshal);
+ HeapFree(GetProcessHeap(), 0, This->stream);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
@@ -890,14 +885,14 @@ static void ca_wrap_buffer(BYTE *dst, UINT32 dst_offs, UINT32 dst_bytes,
static void silence_buffer(ACImpl *This, BYTE *buffer, UINT32 frames)
{
- WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
- if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
- (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->stream->fmt;
+ if((This->stream->fmt->wFormatTag == WAVE_FORMAT_PCM ||
+ (This->stream->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
- This->fmt->wBitsPerSample == 8)
- memset(buffer, 128, frames * This->fmt->nBlockAlign);
+ This->stream->fmt->wBitsPerSample == 8)
+ memset(buffer, 128, frames * This->stream->fmt->nBlockAlign);
else
- memset(buffer, 0, frames * This->fmt->nBlockAlign);
+ memset(buffer, 0, frames * This->stream->fmt->nBlockAlign);
}
/* CA is pulling data from us */
@@ -908,31 +903,31 @@ static OSStatus ca_render_cb(void *user, AudioUnitRenderActionFlags *flags,
ACImpl *This = user;
UINT32 to_copy_bytes, to_copy_frames, chunk_bytes, lcl_offs_bytes;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
- if(This->playing){
- lcl_offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
- to_copy_frames = min(nframes, This->held_frames);
- to_copy_bytes = to_copy_frames * This->fmt->nBlockAlign;
+ if(This->stream->playing){
+ lcl_offs_bytes = This->stream->lcl_offs_frames * This->stream->fmt->nBlockAlign;
+ to_copy_frames = min(nframes, This->stream->held_frames);
+ to_copy_bytes = to_copy_frames * This->stream->fmt->nBlockAlign;
- chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) * This->fmt->nBlockAlign;
+ chunk_bytes = (This->stream->bufsize_frames - This->stream->lcl_offs_frames) * This->stream->fmt->nBlockAlign;
if(to_copy_bytes > chunk_bytes){
- memcpy(data->mBuffers[0].mData, This->local_buffer + lcl_offs_bytes, chunk_bytes);
- memcpy(((BYTE *)data->mBuffers[0].mData) + chunk_bytes, This->local_buffer, to_copy_bytes - chunk_bytes);
+ memcpy(data->mBuffers[0].mData, This->stream->local_buffer + lcl_offs_bytes, chunk_bytes);
+ memcpy(((BYTE *)data->mBuffers[0].mData) + chunk_bytes, This->stream->local_buffer, to_copy_bytes - chunk_bytes);
}else
- memcpy(data->mBuffers[0].mData, This->local_buffer + lcl_offs_bytes, to_copy_bytes);
+ memcpy(data->mBuffers[0].mData, This->stream->local_buffer + lcl_offs_bytes, to_copy_bytes);
- This->lcl_offs_frames += to_copy_frames;
- This->lcl_offs_frames %= This->bufsize_frames;
- This->held_frames -= to_copy_frames;
+ This->stream->lcl_offs_frames += to_copy_frames;
+ This->stream->lcl_offs_frames %= This->stream->bufsize_frames;
+ This->stream->held_frames -= to_copy_frames;
}else
to_copy_bytes = to_copy_frames = 0;
if(nframes > to_copy_frames)
silence_buffer(This, ((BYTE *)data->mBuffers[0].mData) + to_copy_bytes, nframes - to_copy_frames);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return noErr;
}
@@ -950,38 +945,38 @@ static OSStatus feed_cb(AudioConverterRef converter, UInt32 *nframes, AudioBuffe
{
ACImpl *This = user;
- *nframes = min(*nframes, This->cap_held_frames);
+ *nframes = min(*nframes, This->stream->cap_held_frames);
if(!*nframes){
data->mBuffers[0].mData = NULL;
data->mBuffers[0].mDataByteSize = 0;
- data->mBuffers[0].mNumberChannels = This->fmt->nChannels;
+ data->mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
return noErr;
}
- data->mBuffers[0].mDataByteSize = *nframes * This->fmt->nBlockAlign;
- data->mBuffers[0].mNumberChannels = This->fmt->nChannels;
+ data->mBuffers[0].mDataByteSize = *nframes * This->stream->fmt->nBlockAlign;
+ data->mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
- if(This->cap_offs_frames + *nframes > This->cap_bufsize_frames){
- UINT32 chunk_frames = This->cap_bufsize_frames - This->cap_offs_frames;
+ if(This->stream->cap_offs_frames + *nframes > This->stream->cap_bufsize_frames){
+ UINT32 chunk_frames = This->stream->cap_bufsize_frames - This->stream->cap_offs_frames;
- if(This->wrap_bufsize_frames < *nframes){
- free(This->wrap_buffer);
- This->wrap_buffer = malloc(data->mBuffers[0].mDataByteSize);
- This->wrap_bufsize_frames = *nframes;
+ if(This->stream->wrap_bufsize_frames < *nframes){
+ free(This->stream->wrap_buffer);
+ This->stream->wrap_buffer = malloc(data->mBuffers[0].mDataByteSize);
+ This->stream->wrap_bufsize_frames = *nframes;
}
- memcpy(This->wrap_buffer, This->cap_buffer + This->cap_offs_frames * This->fmt->nBlockAlign,
- chunk_frames * This->fmt->nBlockAlign);
- memcpy(This->wrap_buffer + chunk_frames * This->fmt->nBlockAlign, This->cap_buffer,
- (*nframes - chunk_frames) * This->fmt->nBlockAlign);
+ memcpy(This->stream->wrap_buffer, This->stream->cap_buffer + This->stream->cap_offs_frames * This->stream->fmt->nBlockAlign,
+ chunk_frames * This->stream->fmt->nBlockAlign);
+ memcpy(This->stream->wrap_buffer + chunk_frames * This->stream->fmt->nBlockAlign, This->stream->cap_buffer,
+ (*nframes - chunk_frames) * This->stream->fmt->nBlockAlign);
- data->mBuffers[0].mData = This->wrap_buffer;
+ data->mBuffers[0].mData = This->stream->wrap_buffer;
}else
- data->mBuffers[0].mData = This->cap_buffer + This->cap_offs_frames * This->fmt->nBlockAlign;
+ data->mBuffers[0].mData = This->stream->cap_buffer + This->stream->cap_offs_frames * This->stream->fmt->nBlockAlign;
- This->cap_offs_frames += *nframes;
- This->cap_offs_frames %= This->cap_bufsize_frames;
- This->cap_held_frames -= *nframes;
+ This->stream->cap_offs_frames += *nframes;
+ This->stream->cap_offs_frames %= This->stream->cap_bufsize_frames;
+ This->stream->cap_held_frames -= *nframes;
if(packets)
*packets = NULL;
@@ -991,48 +986,48 @@ static OSStatus feed_cb(AudioConverterRef converter, UInt32 *nframes, AudioBuffe
static void capture_resample(ACImpl *This)
{
- UINT32 resamp_period_frames = MulDiv(This->period_frames, This->dev_desc.mSampleRate, This->fmt->nSamplesPerSec);
+ UINT32 resamp_period_frames = MulDiv(This->stream->period_frames, This->stream->dev_desc.mSampleRate, This->stream->fmt->nSamplesPerSec);
OSStatus sc;
/* the resampling process often needs more source frames than we'd
* guess from a straight conversion using the sample rate ratio. so
* only convert if we have extra source data. */
- while(This->cap_held_frames > resamp_period_frames * 2){
+ while(This->stream->cap_held_frames > resamp_period_frames * 2){
AudioBufferList converted_list;
- UInt32 wanted_frames = This->period_frames;
+ UInt32 wanted_frames = This->stream->period_frames;
converted_list.mNumberBuffers = 1;
- converted_list.mBuffers[0].mNumberChannels = This->fmt->nChannels;
- converted_list.mBuffers[0].mDataByteSize = wanted_frames * This->fmt->nBlockAlign;
+ converted_list.mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
+ converted_list.mBuffers[0].mDataByteSize = wanted_frames * This->stream->fmt->nBlockAlign;
- if(This->resamp_bufsize_frames < wanted_frames){
- HeapFree(GetProcessHeap(), 0, This->resamp_buffer);
- This->resamp_buffer = HeapAlloc(GetProcessHeap(), 0, converted_list.mBuffers[0].mDataByteSize);
- This->resamp_bufsize_frames = wanted_frames;
+ if(This->stream->resamp_bufsize_frames < wanted_frames){
+ HeapFree(GetProcessHeap(), 0, This->stream->resamp_buffer);
+ This->stream->resamp_buffer = HeapAlloc(GetProcessHeap(), 0, converted_list.mBuffers[0].mDataByteSize);
+ This->stream->resamp_bufsize_frames = wanted_frames;
}
- converted_list.mBuffers[0].mData = This->resamp_buffer;
+ converted_list.mBuffers[0].mData = This->stream->resamp_buffer;
- sc = AudioConverterFillComplexBuffer(This->converter, feed_cb,
+ sc = AudioConverterFillComplexBuffer(This->stream->converter, feed_cb,
This, &wanted_frames, &converted_list, NULL);
if(sc != noErr){
WARN("AudioConverterFillComplexBuffer failed: %x\n", (int)sc);
break;
}
- ca_wrap_buffer(This->local_buffer,
- This->wri_offs_frames * This->fmt->nBlockAlign,
- This->bufsize_frames * This->fmt->nBlockAlign,
- This->resamp_buffer, wanted_frames * This->fmt->nBlockAlign);
+ ca_wrap_buffer(This->stream->local_buffer,
+ This->stream->wri_offs_frames * This->stream->fmt->nBlockAlign,
+ This->stream->bufsize_frames * This->stream->fmt->nBlockAlign,
+ This->stream->resamp_buffer, wanted_frames * This->stream->fmt->nBlockAlign);
- This->wri_offs_frames += wanted_frames;
- This->wri_offs_frames %= This->bufsize_frames;
- if(This->held_frames + wanted_frames > This->bufsize_frames){
- This->lcl_offs_frames += buf_ptr_diff(This->lcl_offs_frames,
- This->wri_offs_frames, This->bufsize_frames);
- This->held_frames = This->bufsize_frames;
+ This->stream->wri_offs_frames += wanted_frames;
+ This->stream->wri_offs_frames %= This->stream->bufsize_frames;
+ if(This->stream->held_frames + wanted_frames > This->stream->bufsize_frames){
+ This->stream->lcl_offs_frames += buf_ptr_diff(This->stream->lcl_offs_frames,
+ This->stream->wri_offs_frames, This->stream->bufsize_frames);
+ This->stream->held_frames = This->stream->bufsize_frames;
}else
- This->held_frames += wanted_frames;
+ This->stream->held_frames += wanted_frames;
}
}
@@ -1052,48 +1047,48 @@ static OSStatus ca_capture_cb(void *user, AudioUnitRenderActionFlags *flags,
OSStatus sc;
UINT32 cap_wri_offs_frames;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
- cap_wri_offs_frames = (This->cap_offs_frames + This->cap_held_frames) % This->cap_bufsize_frames;
+ cap_wri_offs_frames = (This->stream->cap_offs_frames + This->stream->cap_held_frames) % This->stream->cap_bufsize_frames;
list.mNumberBuffers = 1;
- list.mBuffers[0].mNumberChannels = This->fmt->nChannels;
- list.mBuffers[0].mDataByteSize = nframes * This->fmt->nBlockAlign;
+ list.mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
+ list.mBuffers[0].mDataByteSize = nframes * This->stream->fmt->nBlockAlign;
- if(!This->playing || cap_wri_offs_frames + nframes > This->cap_bufsize_frames){
- if(This->wrap_bufsize_frames < nframes){
- free(This->wrap_buffer);
- This->wrap_buffer = malloc(list.mBuffers[0].mDataByteSize);
- This->wrap_bufsize_frames = nframes;
+ if(!This->stream->playing || cap_wri_offs_frames + nframes > This->stream->cap_bufsize_frames){
+ if(This->stream->wrap_bufsize_frames < nframes){
+ free(This->stream->wrap_buffer);
+ This->stream->wrap_buffer = malloc(list.mBuffers[0].mDataByteSize);
+ This->stream->wrap_bufsize_frames = nframes;
}
- list.mBuffers[0].mData = This->wrap_buffer;
+ list.mBuffers[0].mData = This->stream->wrap_buffer;
}else
- list.mBuffers[0].mData = This->cap_buffer + cap_wri_offs_frames * This->fmt->nBlockAlign;
+ list.mBuffers[0].mData = This->stream->cap_buffer + cap_wri_offs_frames * This->stream->fmt->nBlockAlign;
- sc = AudioUnitRender(This->unit, flags, ts, bus, nframes, &list);
+ sc = AudioUnitRender(This->stream->unit, flags, ts, bus, nframes, &list);
if(sc != noErr){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return sc;
}
- if(This->playing){
- if(list.mBuffers[0].mData == This->wrap_buffer){
- ca_wrap_buffer(This->cap_buffer,
- cap_wri_offs_frames * This->fmt->nBlockAlign,
- This->cap_bufsize_frames * This->fmt->nBlockAlign,
- This->wrap_buffer, list.mBuffers[0].mDataByteSize);
+ if(This->stream->playing){
+ if(list.mBuffers[0].mData == This->stream->wrap_buffer){
+ ca_wrap_buffer(This->stream->cap_buffer,
+ cap_wri_offs_frames * This->stream->fmt->nBlockAlign,
+ This->stream->cap_bufsize_frames * This->stream->fmt->nBlockAlign,
+ This->stream->wrap_buffer, list.mBuffers[0].mDataByteSize);
}
- This->cap_held_frames += list.mBuffers[0].mDataByteSize / This->fmt->nBlockAlign;
- if(This->cap_held_frames > This->cap_bufsize_frames){
- This->cap_offs_frames += This->cap_held_frames % This->cap_bufsize_frames;
- This->cap_offs_frames %= This->cap_bufsize_frames;
- This->cap_held_frames = This->cap_bufsize_frames;
+ This->stream->cap_held_frames += list.mBuffers[0].mDataByteSize / This->stream->fmt->nBlockAlign;
+ if(This->stream->cap_held_frames > This->stream->cap_bufsize_frames){
+ This->stream->cap_offs_frames += This->stream->cap_held_frames % This->stream->cap_bufsize_frames;
+ This->stream->cap_offs_frames %= This->stream->cap_bufsize_frames;
+ This->stream->cap_held_frames = This->stream->cap_bufsize_frames;
}
}
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return noErr;
}
@@ -1244,31 +1239,31 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
}
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_ALREADY_INITIALIZED;
}
- This->fmt = clone_format(fmt);
- if(!This->fmt){
- OSSpinLockUnlock(&This->lock);
+ This->stream->fmt = clone_format(fmt);
+ if(!This->stream->fmt){
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
- This->period_ms = period / 10000;
- This->period_frames = MulDiv(period, This->fmt->nSamplesPerSec, 10000000);
+ This->stream->period_ms = period / 10000;
+ This->stream->period_frames = MulDiv(period, This->stream->fmt->nSamplesPerSec, 10000000);
- This->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
+ This->stream->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- This->bufsize_frames -= This->bufsize_frames % This->period_frames;
+ This->stream->bufsize_frames -= This->stream->bufsize_frames % This->stream->period_frames;
- hr = ca_setup_audiounit(This->dataflow, This->unit, This->fmt, &This->dev_desc, &This->converter);
+ hr = ca_setup_audiounit(This->dataflow, This->stream->unit, This->stream->fmt, &This->stream->dev_desc, &This->stream->converter);
if(FAILED(hr)){
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return hr;
}
@@ -1279,15 +1274,15 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
input.inputProc = &ca_capture_cb;
input.inputProcRefCon = This;
- sc = AudioUnitSetProperty(This->unit, kAudioOutputUnitProperty_SetInputCallback,
+ sc = AudioUnitSetProperty(This->stream->unit, kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Output, 1, &input, sizeof(input));
if(sc != noErr){
WARN("Couldn't set callback: %x\n", (int)sc);
- AudioConverterDispose(This->converter);
- This->converter = NULL;
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ AudioConverterDispose(This->stream->converter);
+ This->stream->converter = NULL;
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return osstatus_to_hresult(sc);
}
}else{
@@ -1297,65 +1292,65 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
input.inputProc = &ca_render_cb;
input.inputProcRefCon = This;
- sc = AudioUnitSetProperty(This->unit, kAudioUnitProperty_SetRenderCallback,
+ sc = AudioUnitSetProperty(This->stream->unit, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &input, sizeof(input));
if(sc != noErr){
WARN("Couldn't set callback: %x\n", (int)sc);
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return osstatus_to_hresult(sc);
}
}
- sc = AudioUnitInitialize(This->unit);
+ sc = AudioUnitInitialize(This->stream->unit);
if(sc != noErr){
WARN("Couldn't initialize: %x\n", (int)sc);
- if(This->converter){
- AudioConverterDispose(This->converter);
- This->converter = NULL;
+ if(This->stream->converter){
+ AudioConverterDispose(This->stream->converter);
+ This->stream->converter = NULL;
}
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return osstatus_to_hresult(sc);
}
/* we play audio continuously because AudioOutputUnitStart sometimes takes
* a while to return */
- sc = AudioOutputUnitStart(This->unit);
+ sc = AudioOutputUnitStart(This->stream->unit);
if(sc != noErr){
WARN("Unit failed to start: %x\n", (int)sc);
- if(This->converter){
- AudioConverterDispose(This->converter);
- This->converter = NULL;
+ if(This->stream->converter){
+ AudioConverterDispose(This->stream->converter);
+ This->stream->converter = NULL;
}
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return osstatus_to_hresult(sc);
}
- This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->bufsize_frames * fmt->nBlockAlign);
- silence_buffer(This, This->local_buffer, This->bufsize_frames);
+ This->stream->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->stream->bufsize_frames * fmt->nBlockAlign);
+ silence_buffer(This, This->stream->local_buffer, This->stream->bufsize_frames);
if(This->dataflow == eCapture){
- This->cap_bufsize_frames = MulDiv(duration, This->dev_desc.mSampleRate, 10000000);
- This->cap_buffer = HeapAlloc(GetProcessHeap(), 0, This->cap_bufsize_frames * This->fmt->nBlockAlign);
+ This->stream->cap_bufsize_frames = MulDiv(duration, This->stream->dev_desc.mSampleRate, 10000000);
+ This->stream->cap_buffer = HeapAlloc(GetProcessHeap(), 0, This->stream->cap_bufsize_frames * This->stream->fmt->nBlockAlign);
}
This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
if(!This->vols){
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- OSSpinLockUnlock(&This->lock);
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
for(i = 0; i < fmt->nChannels; ++i)
This->vols[i] = 1.f;
- This->share = mode;
+ This->stream->share = mode;
This->flags = flags;
EnterCriticalSection(&g_sessions_lock);
@@ -1364,11 +1359,11 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
&This->session);
if(FAILED(hr)){
LeaveCriticalSection(&g_sessions_lock);
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
+ CoTaskMemFree(This->stream->fmt);
+ This->stream->fmt = NULL;
HeapFree(GetProcessHeap(), 0, This->vols);
This->vols = NULL;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return E_INVALIDARG;
}
@@ -1380,7 +1375,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
This->initted = TRUE;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1395,16 +1390,16 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
if(!frames)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
- *frames = This->bufsize_frames;
+ *frames = This->stream->bufsize_frames;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1477,10 +1472,10 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
if(!out)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
@@ -1493,23 +1488,23 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
&size, &latency);
if(sc != noErr){
WARN("Couldn't get _Latency property: %x\n", (int)sc);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return osstatus_to_hresult(sc);
}
hr = ca_get_max_stream_latency(This, &stream_latency);
if(FAILED(hr)){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return hr;
}
latency += stream_latency;
/* pretend we process audio in Period chunks, so max latency includes
* the period time */
- *out = MulDiv(latency, 10000000, This->fmt->nSamplesPerSec)
- + This->period_ms * 10000;
+ *out = MulDiv(latency, 10000000, This->stream->fmt->nSamplesPerSec)
+ + This->stream->period_ms * 10000;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1523,7 +1518,7 @@ static HRESULT AudioClient_GetCurrentPadding_nolock(ACImpl *This,
if(This->dataflow == eCapture)
capture_resample(This);
- *numpad = This->held_frames;
+ *numpad = This->stream->held_frames;
return S_OK;
}
@@ -1539,11 +1534,11 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
if(!numpad)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
hr = AudioClient_GetCurrentPadding_nolock(This, numpad);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return hr;
}
@@ -1891,35 +1886,35 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
TRACE("(%p)\n", This);
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
- if(This->playing){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->playing){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_STOPPED;
}
if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_EVENTHANDLE_NOT_SET;
}
if(This->event && !This->timer)
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb,
- This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){
+ This, 0, This->stream->period_ms, WT_EXECUTEINTIMERTHREAD)){
This->timer = NULL;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
WARN("Unable to create timer: %u\n", GetLastError());
return E_OUTOFMEMORY;
}
- This->playing = TRUE;
+ This->stream->playing = TRUE;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1930,21 +1925,21 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
TRACE("(%p)\n", This);
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
- if(!This->playing){
- OSSpinLockUnlock(&This->lock);
+ if(!This->stream->playing){
+ OSSpinLockUnlock(&This->stream->lock);
return S_FALSE;
}
- This->playing = FALSE;
+ This->stream->playing = FALSE;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1955,36 +1950,36 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
TRACE("(%p)\n", This);
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
- if(This->playing){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->playing){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_STOPPED;
}
- if(This->getbuf_last){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->getbuf_last){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_BUFFER_OPERATION_PENDING;
}
if(This->dataflow == eRender){
- This->written_frames = 0;
+ This->stream->written_frames = 0;
}else{
- This->written_frames += This->held_frames;
+ This->stream->written_frames += This->stream->held_frames;
}
- This->held_frames = 0;
- This->lcl_offs_frames = 0;
- This->wri_offs_frames = 0;
- This->cap_offs_frames = 0;
- This->cap_held_frames = 0;
+ This->stream->held_frames = 0;
+ This->stream->lcl_offs_frames = 0;
+ This->stream->wri_offs_frames = 0;
+ This->stream->cap_offs_frames = 0;
+ This->stream->cap_held_frames = 0;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -1999,27 +1994,27 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
if(!event)
return E_INVALIDARG;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
}
if (This->event){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
FIXME("called twice\n");
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
}
This->event = event;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2035,23 +2030,23 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
return E_POINTER;
*ppv = NULL;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!This->initted){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
if(IsEqualIID(riid, &IID_IAudioRenderClient)){
if(This->dataflow != eRender){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
}
IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
*ppv = &This->IAudioRenderClient_iface;
}else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
if(This->dataflow != eCapture){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
}
IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
@@ -2066,7 +2061,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
}else
@@ -2077,7 +2072,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
}else
@@ -2088,7 +2083,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
}else
@@ -2098,11 +2093,11 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
}
if(*ppv){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
FIXME("stub %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
@@ -2274,49 +2269,49 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
return E_POINTER;
*data = NULL;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
- if(This->getbuf_last){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->getbuf_last){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_OUT_OF_ORDER;
}
if(!frames){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
hr = AudioClient_GetCurrentPadding_nolock(This, &pad);
if(FAILED(hr)){
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return hr;
}
- if(pad + frames > This->bufsize_frames){
- OSSpinLockUnlock(&This->lock);
+ if(pad + frames > This->stream->bufsize_frames){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_BUFFER_TOO_LARGE;
}
- if(This->wri_offs_frames + frames > This->bufsize_frames){
- if(This->tmp_buffer_frames < frames){
- HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
- This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, frames * This->fmt->nBlockAlign);
- if(!This->tmp_buffer){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->wri_offs_frames + frames > This->stream->bufsize_frames){
+ if(This->stream->tmp_buffer_frames < frames){
+ HeapFree(GetProcessHeap(), 0, This->stream->tmp_buffer);
+ This->stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, frames * This->stream->fmt->nBlockAlign);
+ if(!This->stream->tmp_buffer){
+ OSSpinLockUnlock(&This->stream->lock);
return E_OUTOFMEMORY;
}
- This->tmp_buffer_frames = frames;
+ This->stream->tmp_buffer_frames = frames;
}
- *data = This->tmp_buffer;
- This->getbuf_last = -frames;
+ *data = This->stream->tmp_buffer;
+ This->stream->getbuf_last = -frames;
}else{
- *data = This->local_buffer + This->wri_offs_frames * This->fmt->nBlockAlign;
- This->getbuf_last = frames;
+ *data = This->stream->local_buffer + This->stream->wri_offs_frames * This->stream->fmt->nBlockAlign;
+ This->stream->getbuf_last = frames;
}
silence_buffer(This, *data, frames);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2329,46 +2324,46 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
TRACE("(%p)->(%u, %x)\n", This, frames, flags);
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!frames){
- This->getbuf_last = 0;
- OSSpinLockUnlock(&This->lock);
+ This->stream->getbuf_last = 0;
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
- if(!This->getbuf_last){
- OSSpinLockUnlock(&This->lock);
+ if(!This->stream->getbuf_last){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_OUT_OF_ORDER;
}
- if(frames > (This->getbuf_last >= 0 ? This->getbuf_last : -This->getbuf_last)){
- OSSpinLockUnlock(&This->lock);
+ if(frames > (This->stream->getbuf_last >= 0 ? This->stream->getbuf_last : -This->stream->getbuf_last)){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_INVALID_SIZE;
}
- if(This->getbuf_last >= 0)
- buffer = This->local_buffer + This->wri_offs_frames * This->fmt->nBlockAlign;
+ if(This->stream->getbuf_last >= 0)
+ buffer = This->stream->local_buffer + This->stream->wri_offs_frames * This->stream->fmt->nBlockAlign;
else
- buffer = This->tmp_buffer;
+ buffer = This->stream->tmp_buffer;
if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
silence_buffer(This, buffer, frames);
- if(This->getbuf_last < 0)
- ca_wrap_buffer(This->local_buffer,
- This->wri_offs_frames * This->fmt->nBlockAlign,
- This->bufsize_frames * This->fmt->nBlockAlign,
- buffer, frames * This->fmt->nBlockAlign);
+ if(This->stream->getbuf_last < 0)
+ ca_wrap_buffer(This->stream->local_buffer,
+ This->stream->wri_offs_frames * This->stream->fmt->nBlockAlign,
+ This->stream->bufsize_frames * This->stream->fmt->nBlockAlign,
+ buffer, frames * This->stream->fmt->nBlockAlign);
- This->wri_offs_frames += frames;
- This->wri_offs_frames %= This->bufsize_frames;
- This->held_frames += frames;
- This->written_frames += frames;
- This->getbuf_last = 0;
+ This->stream->wri_offs_frames += frames;
+ This->stream->wri_offs_frames %= This->stream->bufsize_frames;
+ This->stream->held_frames += frames;
+ This->stream->written_frames += frames;
+ This->stream->getbuf_last = 0;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2436,38 +2431,38 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
if(!frames || !flags)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
- if(This->getbuf_last){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->getbuf_last){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_OUT_OF_ORDER;
}
capture_resample(This);
- if(This->held_frames < This->period_frames){
+ if(This->stream->held_frames < This->stream->period_frames){
*frames = 0;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_S_BUFFER_EMPTY;
}
*flags = 0;
- chunk_frames = This->bufsize_frames - This->lcl_offs_frames;
- if(chunk_frames < This->period_frames){
- chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
- if(!This->tmp_buffer)
- This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, This->period_frames * This->fmt->nBlockAlign);
- *data = This->tmp_buffer;
- memcpy(*data, This->local_buffer + This->lcl_offs_frames * This->fmt->nBlockAlign, chunk_bytes);
- memcpy((*data) + chunk_bytes, This->local_buffer, This->period_frames * This->fmt->nBlockAlign - chunk_bytes);
+ chunk_frames = This->stream->bufsize_frames - This->stream->lcl_offs_frames;
+ if(chunk_frames < This->stream->period_frames){
+ chunk_bytes = chunk_frames * This->stream->fmt->nBlockAlign;
+ if(!This->stream->tmp_buffer)
+ This->stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, This->stream->period_frames * This->stream->fmt->nBlockAlign);
+ *data = This->stream->tmp_buffer;
+ memcpy(*data, This->stream->local_buffer + This->stream->lcl_offs_frames * This->stream->fmt->nBlockAlign, chunk_bytes);
+ memcpy((*data) + chunk_bytes, This->stream->local_buffer, This->stream->period_frames * This->stream->fmt->nBlockAlign - chunk_bytes);
}else
- *data = This->local_buffer + This->lcl_offs_frames * This->fmt->nBlockAlign;
+ *data = This->stream->local_buffer + This->stream->lcl_offs_frames * This->stream->fmt->nBlockAlign;
- This->getbuf_last = *frames = This->period_frames;
+ This->stream->getbuf_last = *frames = This->stream->period_frames;
if(devpos)
- *devpos = This->written_frames;
+ *devpos = This->stream->written_frames;
if(qpcpos){ /* fixme: qpc of recording time */
LARGE_INTEGER stamp, freq;
QueryPerformanceCounter(&stamp);
@@ -2475,7 +2470,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
*qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
}
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2487,31 +2482,31 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
TRACE("(%p)->(%u)\n", This, done);
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
if(!done){
- This->getbuf_last = 0;
- OSSpinLockUnlock(&This->lock);
+ This->stream->getbuf_last = 0;
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
- if(!This->getbuf_last){
- OSSpinLockUnlock(&This->lock);
+ if(!This->stream->getbuf_last){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_OUT_OF_ORDER;
}
- if(This->getbuf_last != done){
- OSSpinLockUnlock(&This->lock);
+ if(This->stream->getbuf_last != done){
+ OSSpinLockUnlock(&This->stream->lock);
return AUDCLNT_E_INVALID_SIZE;
}
- This->written_frames += done;
- This->held_frames -= done;
- This->lcl_offs_frames += done;
- This->lcl_offs_frames %= This->bufsize_frames;
- This->getbuf_last = 0;
+ This->stream->written_frames += done;
+ This->stream->held_frames -= done;
+ This->stream->lcl_offs_frames += done;
+ This->stream->lcl_offs_frames %= This->stream->bufsize_frames;
+ This->stream->getbuf_last = 0;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2526,16 +2521,16 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
if(!frames)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
capture_resample(This);
- if(This->held_frames >= This->period_frames)
- *frames = This->period_frames;
+ if(This->stream->held_frames >= This->stream->period_frames)
+ *frames = This->stream->period_frames;
else
*frames = 0;
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
@@ -2592,10 +2587,10 @@ static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
TRACE("(%p)->(%p)\n", This, freq);
- if(This->share == AUDCLNT_SHAREMODE_SHARED)
- *freq = (UINT64)This->fmt->nSamplesPerSec * This->fmt->nBlockAlign;
+ if(This->stream->share == AUDCLNT_SHAREMODE_SHARED)
+ *freq = (UINT64)This->stream->fmt->nSamplesPerSec * This->stream->fmt->nBlockAlign;
else
- *freq = This->fmt->nSamplesPerSec;
+ *freq = This->stream->fmt->nSamplesPerSec;
return S_OK;
}
@@ -2603,10 +2598,10 @@ static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
static HRESULT AudioClock_GetPosition_nolock(ACImpl *This,
UINT64 *pos, UINT64 *qpctime)
{
- *pos = This->written_frames - This->held_frames;
+ *pos = This->stream->written_frames - This->stream->held_frames;
- if(This->share == AUDCLNT_SHAREMODE_SHARED)
- *pos *= This->fmt->nBlockAlign;
+ if(This->stream->share == AUDCLNT_SHAREMODE_SHARED)
+ *pos *= This->stream->fmt->nBlockAlign;
if(qpctime){
LARGE_INTEGER stamp, freq;
@@ -2629,11 +2624,11 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
if(!pos)
return E_POINTER;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
hr = AudioClock_GetPosition_nolock(This, pos, qpctime);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return hr;
}
@@ -2763,9 +2758,9 @@ static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
TRACE("(%p) Refcount now %u\n", This, ref);
if(!ref){
if(This->client){
- OSSpinLockLock(&This->client->lock);
+ OSSpinLockLock(&This->client->stream->lock);
This->client->session_wrapper = NULL;
- OSSpinLockUnlock(&This->client->lock);
+ OSSpinLockUnlock(&This->client->stream->lock);
AudioClient_Release(&This->client->IAudioClient3_iface);
}
HeapFree(GetProcessHeap(), 0, This);
@@ -2793,14 +2788,14 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
}
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
- OSSpinLockLock(&client->lock);
- if(client->playing){
+ OSSpinLockLock(&client->stream->lock);
+ if(client->stream->playing){
*state = AudioSessionStateActive;
- OSSpinLockUnlock(&client->lock);
+ OSSpinLockUnlock(&client->stream->lock);
LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
- OSSpinLockUnlock(&client->lock);
+ OSSpinLockUnlock(&client->stream->lock);
}
LeaveCriticalSection(&g_sessions_lock);
@@ -2979,7 +2974,7 @@ static HRESULT ca_setvol(ACImpl *This, UINT32 index)
if(index == (UINT32)-1){
UINT32 i;
level = 1.;
- for(i = 0; i < This->fmt->nChannels; ++i){
+ for(i = 0; i < This->stream->fmt->nChannels; ++i){
Float32 tmp;
tmp = This->session->master_vol *
This->session->channel_vols[i] * This->vols[i];
@@ -2990,7 +2985,7 @@ static HRESULT ca_setvol(ACImpl *This, UINT32 index)
This->session->channel_vols[index] * This->vols[index];
}
- sc = AudioUnitSetParameter(This->unit, kHALOutputParam_Volume,
+ sc = AudioUnitSetParameter(This->stream->unit, kHALOutputParam_Volume,
kAudioUnitScope_Global, 0, level, 0);
if(sc != noErr)
WARN("Couldn't set volume: %x\n", (int)sc);
@@ -3180,7 +3175,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
if(!out)
return E_POINTER;
- *out = This->fmt->nChannels;
+ *out = This->stream->fmt->nChannels;
return S_OK;
}
@@ -3196,17 +3191,17 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(level < 0.f || level > 1.f)
return E_INVALIDARG;
- if(index >= This->fmt->nChannels)
+ if(index >= This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
This->vols[index] = level;
WARN("CoreAudio doesn't support per-channel volume control\n");
ret = ca_setvol(This, index);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return ret;
}
@@ -3221,7 +3216,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
if(!level)
return E_POINTER;
- if(index >= This->fmt->nChannels)
+ if(index >= This->stream->fmt->nChannels)
return E_INVALIDARG;
*level = This->vols[index];
@@ -3241,17 +3236,17 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->fmt->nChannels)
+ if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
for(i = 0; i < count; ++i)
This->vols[i] = levels[i];
ret = ca_setvol(This, -1);
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return ret;
}
@@ -3267,15 +3262,15 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->fmt->nChannels)
+ if(count != This->stream->fmt->nChannels)
return E_INVALIDARG;
- OSSpinLockLock(&This->lock);
+ OSSpinLockLock(&This->stream->lock);
for(i = 0; i < count; ++i)
levels[i] = This->vols[i];
- OSSpinLockUnlock(&This->lock);
+ OSSpinLockUnlock(&This->stream->lock);
return S_OK;
}
diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
index 7c1200464b9..6a991f1de98 100644
--- a/dlls/winecoreaudio.drv/unixlib.h
+++ b/dlls/winecoreaudio.drv/unixlib.h
@@ -18,6 +18,29 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+struct coreaudio_stream /* To be made private */
+{
+ OSSpinLock lock;
+ AudioComponentInstance unit;
+ AudioConverterRef converter;
+ AudioStreamBasicDescription dev_desc; /* audio unit format, not necessarily the same as fmt */
+ AudioDeviceID dev_id;
+ EDataFlow flow;
+ AUDCLNT_SHAREMODE share;
+
+ BOOL playing;
+ SIZE_T local_buffer_size, tmp_buffer_size;
+ UINT32 period_ms, period_frames;
+ UINT32 bufsize_frames, resamp_bufsize_frames;
+ UINT32 lcl_offs_frames, held_frames, wri_offs_frames, tmp_buffer_frames;
+ UINT32 cap_bufsize_frames, cap_offs_frames, cap_held_frames;
+ UINT32 wrap_bufsize_frames;
+ UINT64 written_frames;
+ INT32 getbuf_last;
+ WAVEFORMATEX *fmt;
+ BYTE *local_buffer, *cap_buffer, *wrap_buffer, *resamp_buffer, *tmp_buffer;
+};
+
struct endpoint
{
WCHAR *name;
--
2.33.1
1
0
17 Nov '21
From: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/winecoreaudio.drv/Makefile.in | 1 +
dlls/winecoreaudio.drv/coreaudio.c | 229 ++++++++++++++++++++++++++++-
dlls/winecoreaudio.drv/mmdevdrv.c | 211 ++++++++------------------
dlls/winecoreaudio.drv/unixlib.h | 44 ++++++
4 files changed, 326 insertions(+), 159 deletions(-)
create mode 100644 dlls/winecoreaudio.drv/unixlib.h
diff --git a/dlls/winecoreaudio.drv/Makefile.in b/dlls/winecoreaudio.drv/Makefile.in
index afbc50c7148..b6bf5bd4587 100644
--- a/dlls/winecoreaudio.drv/Makefile.in
+++ b/dlls/winecoreaudio.drv/Makefile.in
@@ -1,4 +1,5 @@
MODULE = winecoreaudio.drv
+UNIXLIB = winecoreaudio.so
IMPORTS = uuid ole32 user32 advapi32
DELAYIMPORTS = winmm
EXTRALIBS = $(COREAUDIO_LIBS)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
index 1f222367bed..f3af24f80fb 100644
--- a/dlls/winecoreaudio.drv/coreaudio.c
+++ b/dlls/winecoreaudio.drv/coreaudio.c
@@ -1,5 +1,8 @@
/*
- * Wine Driver for CoreAudio
+ * Unixlib for winecoreaudio driver.
+ *
+ * Copyright 2011 Andrew Eikum for CodeWeavers
+ * Copyright 2021 Huw Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,16 +18,230 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
+#if 0
+#pragma makedep unix
+#endif
#include "config.h"
+#define LoadResource __carbon_LoadResource
+#define CompareString __carbon_CompareString
+#define GetCurrentThread __carbon_GetCurrentThread
+#define GetCurrentProcess __carbon_GetCurrentProcess
+
#include <stdarg.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <fenv.h>
+#include <unistd.h>
+
+#include <libkern/OSAtomic.h>
+#include <CoreAudio/CoreAudio.h>
+#include <AudioToolbox/AudioFormat.h>
+#include <AudioToolbox/AudioConverter.h>
+#include <AudioUnit/AudioUnit.h>
+
+#undef LoadResource
+#undef CompareString
+#undef GetCurrentThread
+#undef GetCurrentProcess
+#undef _CDECL
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "mmddk.h"
-#include "coreaudio.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "mmdeviceapi.h"
+#include "initguid.h"
+#include "audioclient.h"
#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/unixlib.h"
+
+#include "unixlib.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
+
+static HRESULT osstatus_to_hresult(OSStatus sc)
+{
+ switch(sc){
+ case kAudioFormatUnsupportedDataFormatError:
+ case kAudioFormatUnknownFormatError:
+ case kAudioDeviceUnsupportedFormatError:
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ case kAudioHardwareBadDeviceError:
+ return AUDCLNT_E_DEVICE_INVALIDATED;
+ }
+ return E_FAIL;
+}
+
+static AudioObjectPropertyScope get_scope(EDataFlow flow)
+{
+ return (flow == eRender) ? kAudioDevicePropertyScopeOutput : kAudioDevicePropertyScopeInput;
+}
+
+static BOOL device_has_channels(AudioDeviceID device, EDataFlow flow)
+{
+ AudioObjectPropertyAddress addr;
+ AudioBufferList *buffers;
+ BOOL ret = FALSE;
+ OSStatus sc;
+ UInt32 size;
+ int i;
+
+ addr.mSelector = kAudioDevicePropertyStreamConfiguration;
+ addr.mScope = get_scope(flow);
+ addr.mElement = 0;
+
+ sc = AudioObjectGetPropertyDataSize(device, &addr, 0, NULL, &size);
+ if(sc != noErr){
+ WARN("Unable to get _StreamConfiguration property size for device %u: %x\n",
+ (unsigned int)device, (int)sc);
+ return FALSE;
+ }
+
+ buffers = malloc(size);
+ if(!buffers) return FALSE;
+
+ sc = AudioObjectGetPropertyData(device, &addr, 0, NULL, &size, buffers);
+ if(sc != noErr){
+ WARN("Unable to get _StreamConfiguration property for device %u: %x\n",
+ (unsigned int)device, (int)sc);
+ free(buffers);
+ return FALSE;
+ }
+
+ for(i = 0; i < buffers->mNumberBuffers; i++){
+ if(buffers->mBuffers[i].mNumberChannels > 0){
+ ret = TRUE;
+ break;
+ }
+ }
+ free(buffers);
+ return ret;
+}
+
+static NTSTATUS get_endpoint_ids(void *args)
+{
+ struct get_endpoint_ids_params *params = args;
+ unsigned int num_devices, i, needed;
+ AudioDeviceID *devices, default_id;
+ AudioObjectPropertyAddress addr;
+ struct endpoint *endpoint;
+ UInt32 devsize, size;
+ struct endpoint_info
+ {
+ CFStringRef name;
+ AudioDeviceID id;
+ } *info;
+ OSStatus sc;
+ WCHAR *ptr;
+
+ params->num = 0;
+ params->default_idx = 0;
+
+ addr.mScope = kAudioObjectPropertyScopeGlobal;
+ addr.mElement = kAudioObjectPropertyElementMaster;
+ if(params->flow == eRender) addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
+ else if(params->flow == eCapture) addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
+ else{
+ params->result = E_INVALIDARG;
+ return STATUS_SUCCESS;
+ }
+
+ size = sizeof(default_id);
+ sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, &default_id);
+ if(sc != noErr){
+ WARN("Getting _DefaultInputDevice property failed: %x\n", (int)sc);
+ default_id = -1;
+ }
+
+ addr.mSelector = kAudioHardwarePropertyDevices;
+ sc = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0, NULL, &devsize);
+ if(sc != noErr){
+ WARN("Getting _Devices property size failed: %x\n", (int)sc);
+ params->result = osstatus_to_hresult(sc);
+ return STATUS_SUCCESS;
+ }
+
+ num_devices = devsize / sizeof(AudioDeviceID);
+ devices = malloc(devsize);
+ info = malloc(num_devices * sizeof(*info));
+ if(!devices || !info){
+ free(info);
+ free(devices);
+ params->result = E_OUTOFMEMORY;
+ return STATUS_SUCCESS;
+ }
+
+ sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &devsize, devices);
+ if(sc != noErr){
+ WARN("Getting _Devices property failed: %x\n", (int)sc);
+ free(info);
+ free(devices);
+ params->result = osstatus_to_hresult(sc);
+ return STATUS_SUCCESS;
+ }
+
+ addr.mSelector = kAudioObjectPropertyName;
+ addr.mScope = get_scope(params->flow);
+ addr.mElement = 0;
+
+ for(i = 0; i < num_devices; i++){
+ if(!device_has_channels(devices[i], params->flow)) continue;
+
+ size = sizeof(CFStringRef);
+ sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL, &size, &info[params->num].name);
+ if(sc != noErr){
+ WARN("Unable to get _Name property for device %u: %x\n",
+ (unsigned int)devices[i], (int)sc);
+ continue;
+ }
+ info[params->num++].id = devices[i];
+ }
+ free(devices);
+
+ needed = sizeof(*endpoint) * params->num;
+ endpoint = params->endpoints;
+ ptr = (WCHAR *)(endpoint + params->num);
+
+ for(i = 0; i < params->num; i++){
+ SIZE_T len = CFStringGetLength(info[i].name);
+ needed += (len + 1) * sizeof(WCHAR);
+
+ if(needed <= params->size){
+ endpoint->name = ptr;
+ CFStringGetCharacters(info[i].name, CFRangeMake(0, len), (UniChar*)endpoint->name);
+ ptr[len] = 0;
+ endpoint->id = info[i].id;
+ endpoint++;
+ ptr += len + 1;
+ }
+ CFRelease(info[i].name);
+ if(info[i].id == default_id) params->default_idx = i;
+ }
+ free(info);
+
+ if(needed > params->size){
+ params->size = needed;
+ params->result = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else params->result = S_OK;
+
+ return STATUS_SUCCESS;
+}
+
+unixlib_entry_t __wine_unix_call_funcs[] =
+{
+ get_endpoint_ids,
+};
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index f07f4bae5fb..f8b538971f2 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -56,8 +56,10 @@
#include "winnls.h"
#include "winreg.h"
#include "wine/debug.h"
+#include "wine/heap.h"
#include "wine/unicode.h"
#include "wine/list.h"
+#include "wine/unixlib.h"
#include "ole2.h"
#include "mmdeviceapi.h"
@@ -69,9 +71,12 @@
#include "endpointvolume.h"
#include "audioclient.h"
#include "audiopolicy.h"
+#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
+unixlib_handle_t coreaudio_handle = 0;
+
#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
static const REFERENCE_TIME DefaultPeriod = 100000;
@@ -245,6 +250,9 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
switch (reason)
{
case DLL_PROCESS_ATTACH:
+ if(NtQueryVirtualMemory(GetCurrentProcess(), dll, MemoryWineUnixFuncs,
+ &coreaudio_handle, sizeof(coreaudio_handle), NULL))
+ return FALSE;
g_timer_q = CreateTimerQueue();
if(!g_timer_q)
return FALSE;
@@ -319,7 +327,7 @@ exit:
RegCloseKey(drv_key);
}
-static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
+static void get_device_guid(EDataFlow flow, DWORD device_id, GUID *guid)
{
HKEY key = NULL, dev_key;
DWORD type, size = sizeof(*guid);
@@ -333,7 +341,7 @@ static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
key_name[0] = '0';
key_name[1] = ',';
- sprintfW(key_name + 2, key_fmt, device);
+ sprintfW(key_name + 2, key_fmt, device_id);
if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_WRITE|KEY_READ, &key) == ERROR_SUCCESS){
if(RegOpenKeyExW(key, key_name, 0, KEY_READ, &dev_key) == ERROR_SUCCESS){
@@ -359,164 +367,61 @@ static void get_device_guid(EDataFlow flow, AudioDeviceID device, GUID *guid)
RegCloseKey(key);
}
-HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids,
- GUID **guids, UINT *num, UINT *def_index)
+HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out,
+ GUID **guids_out, UINT *num, UINT *def_index)
{
- UInt32 devsize, size;
- AudioDeviceID *devices;
- AudioDeviceID default_id;
- AudioObjectPropertyAddress addr;
- OSStatus sc;
- int i, ndevices;
-
- TRACE("%d %p %p %p\n", flow, ids, num, def_index);
-
- addr.mScope = kAudioObjectPropertyScopeGlobal;
- addr.mElement = kAudioObjectPropertyElementMaster;
- if(flow == eRender)
- addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
- else if(flow == eCapture)
- addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
- else
- return E_INVALIDARG;
-
- size = sizeof(default_id);
- sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0,
- NULL, &size, &default_id);
- if(sc != noErr){
- WARN("Getting _DefaultInputDevice property failed: %x\n", (int)sc);
- default_id = -1;
- }
-
- addr.mSelector = kAudioHardwarePropertyDevices;
- sc = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0,
- NULL, &devsize);
- if(sc != noErr){
- WARN("Getting _Devices property size failed: %x\n", (int)sc);
- return osstatus_to_hresult(sc);
- }
-
- devices = HeapAlloc(GetProcessHeap(), 0, devsize);
- if(!devices)
- return E_OUTOFMEMORY;
-
- sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL,
- &devsize, devices);
- if(sc != noErr){
- WARN("Getting _Devices property failed: %x\n", (int)sc);
- HeapFree(GetProcessHeap(), 0, devices);
- return osstatus_to_hresult(sc);
+ struct get_endpoint_ids_params params;
+ unsigned int i;
+ GUID *guids;
+ WCHAR **ids;
+
+ TRACE("%d %p %p %p\n", flow, ids_out, num, def_index);
+
+ params.flow = flow;
+ params.size = 1000;
+ params.endpoints = NULL;
+ do{
+ heap_free(params.endpoints);
+ params.endpoints = heap_alloc(params.size);
+ UNIX_CALL(get_endpoint_ids, ¶ms);
+ }while(params.result == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
+
+ if(FAILED(params.result)) goto end;
+
+ ids = heap_alloc_zero(params.num * sizeof(*ids));
+ guids = heap_alloc(params.num * sizeof(*guids));
+ if(!ids || !guids){
+ params.result = E_OUTOFMEMORY;
+ goto end;
}
- ndevices = devsize / sizeof(AudioDeviceID);
-
- *ids = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(WCHAR *));
- if(!*ids){
- HeapFree(GetProcessHeap(), 0, devices);
- return E_OUTOFMEMORY;
- }
-
- *guids = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(GUID));
- if(!*guids){
- HeapFree(GetProcessHeap(), 0, *ids);
- HeapFree(GetProcessHeap(), 0, devices);
- return E_OUTOFMEMORY;
- }
-
- *num = 0;
- *def_index = (UINT)-1;
- for(i = 0; i < ndevices; ++i){
- AudioBufferList *buffers;
- CFStringRef name;
- SIZE_T len;
- int j;
-
- addr.mSelector = kAudioDevicePropertyStreamConfiguration;
- if(flow == eRender)
- addr.mScope = kAudioDevicePropertyScopeOutput;
- else
- addr.mScope = kAudioDevicePropertyScopeInput;
- addr.mElement = 0;
- sc = AudioObjectGetPropertyDataSize(devices[i], &addr, 0, NULL, &size);
- if(sc != noErr){
- WARN("Unable to get _StreamConfiguration property size for "
- "device %u: %x\n", (unsigned int)devices[i], (int)sc);
- continue;
- }
-
- buffers = HeapAlloc(GetProcessHeap(), 0, size);
- if(!buffers){
- HeapFree(GetProcessHeap(), 0, devices);
- for(j = 0; j < *num; ++j)
- HeapFree(GetProcessHeap(), 0, (*ids)[j]);
- HeapFree(GetProcessHeap(), 0, *guids);
- HeapFree(GetProcessHeap(), 0, *ids);
- return E_OUTOFMEMORY;
+ for(i = 0; i < params.num; i++){
+ int size = (strlenW(params.endpoints[i].name) + 1) * sizeof(WCHAR);
+ ids[i] = heap_alloc(size);
+ if(!ids[i]){
+ params.result = E_OUTOFMEMORY;
+ goto end;
}
-
- sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
- &size, buffers);
- if(sc != noErr){
- WARN("Unable to get _StreamConfiguration property for "
- "device %u: %x\n", (unsigned int)devices[i], (int)sc);
- HeapFree(GetProcessHeap(), 0, buffers);
- continue;
- }
-
- /* check that there's at least one channel in this device before
- * we claim it as usable */
- for(j = 0; j < buffers->mNumberBuffers; ++j)
- if(buffers->mBuffers[j].mNumberChannels > 0)
- break;
- if(j >= buffers->mNumberBuffers){
- HeapFree(GetProcessHeap(), 0, buffers);
- continue;
- }
-
- HeapFree(GetProcessHeap(), 0, buffers);
-
- size = sizeof(name);
- addr.mSelector = kAudioObjectPropertyName;
- sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
- &size, &name);
- if(sc != noErr){
- WARN("Unable to get _Name property for device %u: %x\n",
- (unsigned int)devices[i], (int)sc);
- continue;
- }
-
- len = CFStringGetLength(name) + 1;
- (*ids)[*num] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- if(!(*ids)[*num]){
- CFRelease(name);
- HeapFree(GetProcessHeap(), 0, devices);
- for(j = 0; j < *num; ++j)
- HeapFree(GetProcessHeap(), 0, (*ids)[j]);
- HeapFree(GetProcessHeap(), 0, *ids);
- HeapFree(GetProcessHeap(), 0, *guids);
- return E_OUTOFMEMORY;
+ memcpy(ids[i], params.endpoints[i].name, size);
+ get_device_guid(flow, params.endpoints[i].id, guids + i);
+ }
+ *def_index = params.default_idx;
+
+end:
+ heap_free(params.endpoints);
+ if(FAILED(params.result)){
+ heap_free(guids);
+ if(ids){
+ for(i = 0; i < params.num; i++) heap_free(ids[i]);
+ heap_free(ids);
}
- CFStringGetCharacters(name, CFRangeMake(0, len - 1), (UniChar*)(*ids)[*num]);
- ((*ids)[*num])[len - 1] = 0;
- CFRelease(name);
-
- get_device_guid(flow, devices[i], &(*guids)[*num]);
-
- if(*def_index == (UINT)-1 && devices[i] == default_id)
- *def_index = *num;
-
- TRACE("device %u: id %s key %u%s\n", *num, debugstr_w((*ids)[*num]),
- (unsigned int)devices[i], (*def_index == *num) ? " (default)" : "");
-
- (*num)++;
+ }else{
+ *ids_out = ids;
+ *guids_out = guids;
+ *num = params.num;
}
- if(*def_index == (UINT)-1)
- *def_index = 0;
-
- HeapFree(GetProcessHeap(), 0, devices);
-
- return S_OK;
+ return params.result;
}
static BOOL get_deviceid_by_guid(GUID *guid, AudioDeviceID *id, EDataFlow *flow)
diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
new file mode 100644
index 00000000000..7c1200464b9
--- /dev/null
+++ b/dlls/winecoreaudio.drv/unixlib.h
@@ -0,0 +1,44 @@
+/*
+ * Unixlib header file for winecoreaudio driver.
+ *
+ * Copyright 2021 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+struct endpoint
+{
+ WCHAR *name;
+ DWORD id;
+};
+
+struct get_endpoint_ids_params
+{
+ EDataFlow flow;
+ struct endpoint *endpoints;
+ unsigned int size;
+ HRESULT result;
+ unsigned int num;
+ unsigned int default_idx;
+};
+
+enum unix_funcs
+{
+ unix_get_endpoint_ids,
+};
+
+extern unixlib_handle_t coreaudio_handle;
+
+#define UNIX_CALL( func, params ) __wine_unix_call( coreaudio_handle, unix_ ## func, params )
--
2.33.1
1
0