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
February 2022
- 87 participants
- 926 discussions
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v2: * Introduce is_time_digit().
* Use wcstol() for converting wDayOfWeek.
dlls/wininet/internet.c | 59 ++++++++++++++++++++++++-----------
dlls/wininet/tests/internet.c | 16 +++++-----
2 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index 59fae2fbc95..b41994f5b22 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -3302,6 +3302,11 @@ static const WCHAR WININET_month[12][4] =
L"May", L"Jun", L"Jul", L"Aug",
L"Sep", L"Oct", L"Nov", L"Dec"};
+static inline BOOL is_time_digit(const WCHAR c)
+{
+ return c >= '0' && c <= '9';
+}
+
/***********************************************************************
* InternetTimeFromSystemTimeA (WININET.@)
*/
@@ -3400,54 +3405,72 @@ BOOL WINAPI InternetTimeToSystemTimeW( LPCWSTR string, SYSTEMTIME* time, DWORD r
* a SYSTEMTIME structure.
*/
- while (*s && !iswalpha( *s )) s++;
- if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
+ while (*s && !iswalpha(*s) && !is_time_digit(*s)) s++;
+ if (*s == '\0') return TRUE;
time->wDayOfWeek = 7;
- for (i = 0; i < 7; i++)
+ if (iswalpha(*s))
{
- if (!wcsnicmp( WININET_wkday[i], s, 3 ))
+ if (s[1] == '\0' || s[2] == '\0') return TRUE;
+ for (i = 0; i < 7; i++)
{
- time->wDayOfWeek = i;
- break;
+ if (!wcsnicmp(WININET_wkday[i], s, 3))
+ {
+ time->wDayOfWeek = i;
+ break;
+ }
}
}
-
+ else if (is_time_digit(*s))
+ {
+ time->wDayOfWeek = wcstol(s, &end, 10);
+ s = end;
+ }
if (time->wDayOfWeek > 6) return TRUE;
- while (*s && !iswdigit( *s )) s++;
+
+ while (*s && !is_time_digit(*s)) s++;
time->wDay = wcstol( s, &end, 10 );
s = end;
- while (*s && !iswalpha( *s )) s++;
- if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
+ while (*s && !iswalpha(*s) && !is_time_digit(*s)) s++;
+ if (*s == '\0') return TRUE;
time->wMonth = 0;
- for (i = 0; i < 12; i++)
+ if (iswalpha(*s))
{
- if (!wcsnicmp( WININET_month[i], s, 3 ))
+ if (s[1] == '\0' || s[2] == '\0') return TRUE;
+ for (i = 0; i < 12; i++)
{
- time->wMonth = i + 1;
- break;
+ if (!wcsnicmp(WININET_month[i], s, 3))
+ {
+ time->wMonth = i + 1;
+ break;
+ }
}
}
+ else if (is_time_digit(*s))
+ {
+ time->wMonth = wcstol(s, &end, 10);
+ s = end;
+ }
if (time->wMonth == 0) return TRUE;
- while (*s && !iswdigit( *s )) s++;
+ while (*s && !is_time_digit(*s)) s++;
if (*s == '\0') return TRUE;
time->wYear = wcstol( s, &end, 10 );
s = end;
- while (*s && !iswdigit( *s )) s++;
+ while (*s && !is_time_digit(*s)) s++;
if (*s == '\0') return TRUE;
time->wHour = wcstol( s, &end, 10 );
s = end;
- while (*s && !iswdigit( *s )) s++;
+ while (*s && !is_time_digit(*s)) s++;
if (*s == '\0') return TRUE;
time->wMinute = wcstol( s, &end, 10 );
s = end;
- while (*s && !iswdigit( *s )) s++;
+ while (*s && !is_time_digit(*s)) s++;
if (*s == '\0') return TRUE;
time->wSecond = wcstol( s, &end, 10 );
s = end;
diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c
index 8fc72be8431..19d6ae7e639 100644
--- a/dlls/wininet/tests/internet.c
+++ b/dlls/wininet/tests/internet.c
@@ -917,14 +917,14 @@ static void test_InternetTimeToSystemTime(void)
{
{ "Fri, 07 Jan 2005 12:06:35 GMT", &expect1, TRUE },
{ " fri, 7 jan 2005 12 06 35", &expect1, TRUE },
- { "Fri, 07-01-2005 12:06:35", &expect1, TRUE, TRUE },
- { "5, 07-01-2005 12:06:35 GMT", &expect1, TRUE, TRUE },
- { "5, 07-01-2005 12:06:35 GMT;", &expect1, TRUE, TRUE },
- { "5, 07-01-2005 12:06:35 GMT123", &expect1, TRUE, TRUE },
- { "2, 11 01 2022 11 13 05", &expect2, TRUE, TRUE },
- { "2, 11-01-2022 11#13^05", &expect2, TRUE, TRUE },
- { "2, 11*01/2022 11+13=05", &expect2, TRUE, TRUE },
- { "2, 11-Jan-2022 11:13:05", &expect2, TRUE, TRUE },
+ { "Fri, 07-01-2005 12:06:35", &expect1, TRUE },
+ { "5, 07-01-2005 12:06:35 GMT", &expect1, TRUE },
+ { "5, 07-01-2005 12:06:35 GMT;", &expect1, TRUE },
+ { "5, 07-01-2005 12:06:35 GMT123", &expect1, TRUE },
+ { "2, 11 01 2022 11 13 05", &expect2, TRUE },
+ { "2, 11-01-2022 11#13^05", &expect2, TRUE },
+ { "2, 11*01/2022 11+13=05", &expect2, TRUE },
+ { "2, 11-Jan-2022 11:13:05", &expect2, TRUE },
{ "Fr", NULL, FALSE },
};
--
2.25.1
2
1
22 Feb '22
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
programs/dllhost/dllhost.c | 217 ++++++++++++++++++++++++++++++++++++-
1 file changed, 213 insertions(+), 4 deletions(-)
diff --git a/programs/dllhost/dllhost.c b/programs/dllhost/dllhost.c
index ac1cf0e3d33..55294efc880 100644
--- a/programs/dllhost/dllhost.c
+++ b/programs/dllhost/dllhost.c
@@ -28,9 +28,193 @@
WINE_DEFAULT_DEBUG_CHANNEL(dllhost);
+struct factory
+{
+ IClassFactory IClassFactory_iface;
+ IMarshal IMarshal_iface;
+ CLSID clsid;
+ LONG ref;
+};
+
+static inline struct factory *impl_from_IClassFactory(IClassFactory *iface)
+{
+ return CONTAINING_RECORD(iface, struct factory, IClassFactory_iface);
+}
+
+static inline struct factory *impl_from_IMarshal(IMarshal *iface)
+{
+ return CONTAINING_RECORD(iface, struct factory, IMarshal_iface);
+}
+
+static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface,
+ REFIID iid, void **ppv)
+{
+ struct factory *factory = impl_from_IClassFactory(iface);
+
+ TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(iid, &IID_IUnknown) ||
+ IsEqualIID(iid, &IID_IClassFactory))
+ {
+ IClassFactory_AddRef(&factory->IClassFactory_iface);
+ *ppv = &factory->IClassFactory_iface;
+ return S_OK;
+ }
+ else if (IsEqualIID(iid, &IID_IMarshal))
+ {
+ IClassFactory_AddRef(&factory->IClassFactory_iface);
+ *ppv = &factory->IMarshal_iface;
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI factory_AddRef(IClassFactory *iface)
+{
+ struct factory *factory = impl_from_IClassFactory(iface);
+ ULONG ref = InterlockedIncrement(&factory->ref);
+
+ TRACE("(%p)->%u\n", iface, ref);
+ return ref;
+}
+
+static ULONG WINAPI factory_Release(IClassFactory *iface)
+{
+ struct factory *factory = impl_from_IClassFactory(iface);
+ ULONG ref = InterlockedDecrement(&factory->ref);
+
+ TRACE("(%p)->%u\n", iface, ref);
+
+ if (!ref)
+ HeapFree(GetProcessHeap(), 0, factory);
+
+ return ref;
+}
+
+static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface,
+ IUnknown *punkouter, REFIID iid, void **ppv)
+{
+ FIXME("(%p,%p,%s,%p): stub\n", iface, punkouter, wine_dbgstr_guid(iid), ppv);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI factory_LockServer(IClassFactory *iface, BOOL lock)
+{
+ TRACE("(%p,%d)\n", iface, lock);
+ return S_OK;
+}
+
+static const IClassFactoryVtbl ClassFactory_Vtbl =
+{
+ factory_QueryInterface,
+ factory_AddRef,
+ factory_Release,
+ factory_CreateInstance,
+ factory_LockServer
+};
+
+static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, LPVOID *ppv)
+{
+ struct factory *factory = impl_from_IMarshal(iface);
+
+ TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(iid, &IID_IUnknown) ||
+ IsEqualIID(iid, &IID_IMarshal))
+ {
+ IMarshal_AddRef(&factory->IMarshal_iface);
+ *ppv = &factory->IMarshal_iface;
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI marshal_AddRef(IMarshal *iface)
+{
+ struct factory *factory = impl_from_IMarshal(iface);
+
+ TRACE("(%p)\n", iface);
+
+ return IClassFactory_AddRef(&factory->IClassFactory_iface);
+}
+
+static ULONG WINAPI marshal_Release(IMarshal *iface)
+{
+ struct factory *factory = impl_from_IMarshal(iface);
+
+ TRACE("(%p)\n", iface);
+
+ return IClassFactory_Release(&factory->IClassFactory_iface);
+}
+
+static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *pv,
+ DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
+{
+ FIXME("(%p,%s,%p,%08lx,%p,%08lx,%p): stub\n", iface, wine_dbgstr_guid(iid), pv,
+ dwDestContext, pvDestContext, mshlflags, clsid);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *pv,
+ DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
+{
+ FIXME("(%p,%s,%p,%08lx,%p,%08lx,%p): stub\n", iface, wine_dbgstr_guid(iid), pv,
+ dwDestContext, pvDestContext, mshlflags, size);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
+ void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
+{
+ FIXME("(%p,%s,%p,%08lx,%p,%08lx): stub\n", stream, wine_dbgstr_guid(iid), pv, dwDestContext, pvDestContext, mshlflags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
+ REFIID iid, void **ppv)
+{
+ FIXME("(%p,%p,%s,%p): stub\n", iface, stream, wine_dbgstr_guid(iid), ppv);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
+{
+ TRACE("(%p,%p)\n", iface, stream);
+ return S_OK;
+}
+
+static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
+{
+ TRACE("(%p, %08lx)\n", iface, reserved);
+ return S_OK;
+}
+
+static const IMarshalVtbl Marshal_Vtbl =
+{
+ marshal_QueryInterface,
+ marshal_AddRef,
+ marshal_Release,
+ marshal_GetUnmarshalClass,
+ marshal_GetMarshalSizeMax,
+ marshal_MarshalInterface,
+ marshal_UnmarshalInterface,
+ marshal_ReleaseMarshalData,
+ marshal_DisconnectObject
+};
+
struct surrogate
{
ISurrogate ISurrogate_iface;
+ IClassFactory *factory;
+ DWORD cookie;
LONG ref;
};
@@ -74,8 +258,29 @@ static ULONG WINAPI surrogate_Release(ISurrogate *iface)
static HRESULT WINAPI surrogate_LoadDllServer(ISurrogate *iface, const CLSID *clsid)
{
- FIXME("(%p,%s): stub\n", iface, wine_dbgstr_guid(clsid));
- return E_NOTIMPL;
+ struct surrogate *surrogate = impl_from_ISurrogate(iface);
+ struct factory *factory;
+ HRESULT hr;
+
+ TRACE("(%p,%s)\n", iface, wine_dbgstr_guid(clsid));
+
+ factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
+ if (!factory)
+ return E_OUTOFMEMORY;
+
+ factory->IClassFactory_iface.lpVtbl = &ClassFactory_Vtbl;
+ factory->IMarshal_iface.lpVtbl = &Marshal_Vtbl;
+ factory->clsid = *clsid;
+ factory->ref = 1;
+
+ hr = CoRegisterClassObject(clsid, (IUnknown *)&factory->IClassFactory_iface,
+ CLSCTX_LOCAL_SERVER, REGCLS_SURROGATE, &surrogate->cookie);
+ if (hr != S_OK)
+ IClassFactory_Release(&factory->IClassFactory_iface);
+ else
+ surrogate->factory = &factory->IClassFactory_iface;
+
+ return hr;
}
static HRESULT WINAPI surrogate_FreeSurrogate(ISurrogate *iface)
@@ -93,12 +298,16 @@ static const ISurrogateVtbl Surrogate_Vtbl =
surrogate_FreeSurrogate
};
-static struct surrogate surrogate = { { &Surrogate_Vtbl }, 0 };
-
int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE previnst, LPWSTR cmdline, int showcmd)
{
HRESULT hr;
CLSID clsid;
+ struct surrogate surrogate;
+
+ surrogate.ISurrogate_iface.lpVtbl = &Surrogate_Vtbl;
+ surrogate.factory = NULL;
+ surrogate.cookie = 0;
+ surrogate.ref = 1;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
--
2.35.1
4
10
22 Feb '22
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
dlls/wiaservc/Makefile.in | 1 -
dlls/wiaservc/service.c | 6 +++---
dlls/wiaservc/wiadevmgr.c | 24 ++++++++++++------------
3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/dlls/wiaservc/Makefile.in b/dlls/wiaservc/Makefile.in
index 9d71d10423e..c2ba299c4e3 100644
--- a/dlls/wiaservc/Makefile.in
+++ b/dlls/wiaservc/Makefile.in
@@ -1,4 +1,3 @@
-EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = wiaservc.dll
IMPORTS = uuid ole32 advapi32
diff --git a/dlls/wiaservc/service.c b/dlls/wiaservc/service.c
index 524181f72a0..3d2ba148ea1 100644
--- a/dlls/wiaservc/service.c
+++ b/dlls/wiaservc/service.c
@@ -69,7 +69,7 @@ ServiceHandler(DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context)
SetEvent(stop_event);
break;
default:
- FIXME("ignoring handle service ctrl %x\n", ctrl);
+ FIXME("ignoring handle service ctrl %lx\n", ctrl);
UpdateStatus(status.dwCurrentState, NO_ERROR, 0);
break;
}
@@ -107,7 +107,7 @@ StartCount(void)
VOID WINAPI
ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
{
- TRACE("(%d, %p)\n", dwArgc, lpszArgv);
+ TRACE("(%ld, %p)\n", dwArgc, lpszArgv);
stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!stop_event) {
@@ -117,7 +117,7 @@ ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv)
status_handle = RegisterServiceCtrlHandlerExW(L"stisvc", ServiceHandler, NULL);
if (!status_handle) {
- ERR("failed to register handler: %u\n", GetLastError());
+ ERR("failed to register handler: %lu\n", GetLastError());
return;
}
diff --git a/dlls/wiaservc/wiadevmgr.c b/dlls/wiaservc/wiadevmgr.c
index 58720ef361a..e0156b7f5a2 100644
--- a/dlls/wiaservc/wiadevmgr.c
+++ b/dlls/wiaservc/wiadevmgr.c
@@ -67,7 +67,7 @@ static ULONG WINAPI enumwiadevinfo_AddRef(IEnumWIA_DEV_INFO *iface)
{
enumwiadevinfo *This = impl_from_IEnumWIA_DEV_INFO(iface);
ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%u)\n", This, ref);
+ TRACE("(%p)->(%lu)\n", This, ref);
return ref;
}
@@ -76,7 +76,7 @@ static ULONG WINAPI enumwiadevinfo_Release(IEnumWIA_DEV_INFO *iface)
enumwiadevinfo *This = impl_from_IEnumWIA_DEV_INFO(iface);
ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p)->(%u)\n", This, ref);
+ TRACE("(%p)->(%lu)\n", This, ref);
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
@@ -87,7 +87,7 @@ static HRESULT WINAPI enumwiadevinfo_Next(IEnumWIA_DEV_INFO *iface, ULONG count,
{
enumwiadevinfo *This = impl_from_IEnumWIA_DEV_INFO(iface);
- FIXME("(%p, %d, %p, %p): stub\n", This, count, elem, fetched);
+ FIXME("(%p, %ld, %p, %p): stub\n", This, count, elem, fetched);
*fetched = 0;
return E_NOTIMPL;
@@ -97,7 +97,7 @@ static HRESULT WINAPI enumwiadevinfo_Skip(IEnumWIA_DEV_INFO *iface, ULONG count)
{
enumwiadevinfo *This = impl_from_IEnumWIA_DEV_INFO(iface);
- FIXME("(%p, %u): stub\n", This, count);
+ FIXME("(%p, %lu): stub\n", This, count);
return E_NOTIMPL;
}
@@ -182,7 +182,7 @@ static HRESULT WINAPI wiadevmgr_EnumDeviceInfo(IWiaDevMgr *iface, LONG flag, IEn
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
enumwiadevinfo *enuminfo;
- TRACE("(%p)->(%x, %p)\n", This, flag, ret);
+ TRACE("(%p)->(%lx, %p)\n", This, flag, ret);
*ret = NULL;
@@ -208,7 +208,7 @@ static HRESULT WINAPI wiadevmgr_SelectDeviceDlg(IWiaDevMgr *iface, HWND hwndPare
LONG lFlags, BSTR *pbstrDeviceID, IWiaItem **ppItemRoot)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, %p, %d, 0x%x, %p, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID, ppItemRoot);
+ FIXME("(%p, %p, %ld, 0x%lx, %p, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID, ppItemRoot);
return E_NOTIMPL;
}
@@ -216,7 +216,7 @@ static HRESULT WINAPI wiadevmgr_SelectDeviceDlgID(IWiaDevMgr *iface, HWND hwndPa
LONG lFlags, BSTR *pbstrDeviceID)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, %p, %d, 0x%x, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID);
+ FIXME("(%p, %p, %ld, 0x%lx, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID);
return E_NOTIMPL;
}
@@ -225,7 +225,7 @@ static HRESULT WINAPI wiadevmgr_GetImageDlg(IWiaDevMgr *iface, HWND hwndParent,
BSTR bstrFilename, GUID *pguidFormat)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, %p, %d, 0x%x, %d, %p, %s, %s): stub\n", This, hwndParent, lDeviceType, lFlags,
+ FIXME("(%p, %p, %ld, 0x%lx, %ld, %p, %s, %s): stub\n", This, hwndParent, lDeviceType, lFlags,
lIntent, pItemRoot, debugstr_w(bstrFilename), debugstr_guid(pguidFormat));
return E_NOTIMPL;
}
@@ -235,7 +235,7 @@ static HRESULT WINAPI wiadevmgr_RegisterEventCallbackProgram(IWiaDevMgr *iface,
BSTR bstrName, BSTR bstrDescription, BSTR bstrIcon)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, 0x%x, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
+ FIXME("(%p, 0x%lx, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
debugstr_guid(pEventGUID), debugstr_w(bstrCommandline), debugstr_w(bstrName),
debugstr_w(bstrDescription), debugstr_w(bstrIcon));
return E_NOTIMPL;
@@ -246,7 +246,7 @@ static HRESULT WINAPI wiadevmgr_RegisterEventCallbackInterface(IWiaDevMgr *iface
IUnknown **pEventObject)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, 0x%x, %s, %s, %p, %p): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
+ FIXME("(%p, 0x%lx, %s, %s, %p, %p): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
debugstr_guid(pEventGUID), pIWiaEventCallback, pEventObject);
return E_NOTIMPL;
}
@@ -256,7 +256,7 @@ static HRESULT WINAPI wiadevmgr_RegisterEventCallbackCLSID(IWiaDevMgr *iface, LO
BSTR bstrDescription, BSTR bstrIcon)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, 0x%x, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
+ FIXME("(%p, 0x%lx, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
debugstr_guid(pEventGUID), debugstr_guid(pClsID), debugstr_w(bstrName),
debugstr_w(bstrDescription), debugstr_w(bstrIcon));
return E_NOTIMPL;
@@ -265,7 +265,7 @@ static HRESULT WINAPI wiadevmgr_RegisterEventCallbackCLSID(IWiaDevMgr *iface, LO
static HRESULT WINAPI wiadevmgr_AddDeviceDlg(IWiaDevMgr *iface, HWND hwndParent, LONG lFlags)
{
wiadevmgr *This = impl_from_IWiaDevMgr(iface);
- FIXME("(%p, %p, 0x%x): stub\n", This, hwndParent, lFlags);
+ FIXME("(%p, %p, 0x%lx): stub\n", This, hwndParent, lFlags);
return E_NOTIMPL;
}
3
22
This prevents -Wmisleading-indentation warnings (Mingw GCC11)
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
dlls/comctl32/tests/static.c | 4 ++--
dlls/comctl32/tests/toolbar.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 9bd22408985..0038cadd7d2 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -165,7 +165,7 @@ static void test_image(HBITMAP image, BOOL is_dib, BOOL is_premult, BOOL is_alph
ok(bm.bmBits != NULL, "bmBits is NULL\n");
memcpy(bits, bm.bmBits, 4);
if (is_premult)
-todo_wine
+ todo_wine
ok(bits[0] == 0x05 && bits[1] == 0x09 && bits[2] == 0x0e && bits[3] == 0x44,
"bits: %02x %02x %02x %02x\n", bits[0], bits[1], bits[2], bits[3]);
else if (is_alpha)
@@ -195,7 +195,7 @@ todo_wine
DeleteDC(hdc);
if (is_premult)
-todo_wine
+ todo_wine
ok(bits[0] == 0x05 && bits[1] == 0x09 && bits[2] == 0x0e && bits[3] == 0x44,
"bits: %02x %02x %02x %02x\n", bits[0], bits[1], bits[2], bits[3]);
else if (is_alpha)
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c
index cfe4f16f430..dcd95ffa4d8 100644
--- a/dlls/comctl32/tests/toolbar.c
+++ b/dlls/comctl32/tests/toolbar.c
@@ -2728,7 +2728,7 @@ static void test_BTNS_SEP(void)
memset(&button, 0, sizeof(button));
ret = SendMessageA(hwnd, TB_GETBUTTON, 0, (LPARAM)&button);
ok(ret == 1, "Unexpected return value.\n");
-todo_wine
+ todo_wine
ok(button.iBitmap == 8, "Unexpected iBitmap value %d.\n", button.iBitmap);
rebuild_toolbar(&hwnd);
@@ -2789,7 +2789,7 @@ todo_wine
memset(&button, 0, sizeof(button));
ret = SendMessageA(hwnd, TB_GETBUTTON, 0, (LPARAM)&button);
ok(ret == 1, "Unexpected return value.\n");
-todo_wine
+ todo_wine
ok(button.iBitmap == 8, "Unexpected iBitmap value %d.\n", button.iBitmap);
DestroyWindow(hwnd);
6
17
[PATCH 4/4] winealsa: Move create_stream and release_stream to the unixlib.
by Huw Davies 22 Feb '22
by Huw Davies 22 Feb '22
22 Feb '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 303 ++++++++++++++++++++++
dlls/winealsa.drv/mmdevdrv.c | 489 +++--------------------------------
dlls/winealsa.drv/unixlib.h | 21 ++
3 files changed, 360 insertions(+), 453 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index 0680383f59b..f79a655780c 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdio.h>
+#include <pthread.h>
#include <alsa/asoundlib.h>
@@ -44,6 +45,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(alsa);
+#define EXTRA_SAFE_RT 40000
+
static const WCHAR drv_keyW[] = {'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','D','r','i','v','e','r','s','\\',
'w','i','n','e','a','l','s','a','.','d','r','v'};
@@ -133,6 +136,30 @@ static WCHAR *strdupAtoW(const char *str)
return ret;
}
+/* copied from kernelbase */
+static int muldiv( int a, int b, int c )
+{
+ LONGLONG ret;
+
+ if (!c) return -1;
+
+ /* We want to deal with a positive divisor to simplify the logic. */
+ if (c < 0)
+ {
+ a = -a;
+ c = -c;
+ }
+
+ /* If the result is positive, we "add" to round. else, we subtract to round. */
+ if ((a < 0 && b < 0) || (a >= 0 && b >= 0))
+ ret = (((LONGLONG)a * b) + (c / 2)) / c;
+ else
+ ret = (((LONGLONG)a * b) - (c / 2)) / c;
+
+ if (ret > 2147483647 || ret < -2147483647) return -1;
+ return ret;
+}
+
static BOOL alsa_try_open(const char *devnode, EDataFlow flow)
{
snd_pcm_t *handle;
@@ -663,6 +690,280 @@ static HRESULT map_channels(EDataFlow flow, const WAVEFORMATEX *fmt, int *alsa_c
return need_remap ? S_OK : S_FALSE;
}
+static void silence_buffer(struct alsa_stream *stream, BYTE *buffer, UINT32 frames)
+{
+ WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)stream->fmt;
+ if((stream->fmt->wFormatTag == WAVE_FORMAT_PCM ||
+ (stream->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
+ stream->fmt->wBitsPerSample == 8)
+ memset(buffer, 128, frames * stream->fmt->nBlockAlign);
+ else
+ memset(buffer, 0, frames * stream->fmt->nBlockAlign);
+}
+
+static NTSTATUS create_stream(void *args)
+{
+ struct create_stream_params *params = args;
+ struct alsa_stream *stream;
+ snd_pcm_sw_params_t *sw_params = NULL;
+ snd_pcm_format_t format;
+ unsigned int rate, alsa_period_us, i;
+ WAVEFORMATEXTENSIBLE *fmtex;
+ int err;
+ SIZE_T size;
+
+ stream = calloc(1, sizeof(*stream));
+ if(!stream){
+ params->result = E_OUTOFMEMORY;
+ return STATUS_SUCCESS;
+ }
+
+ params->result = alsa_open_device(params->alsa_name, params->flow, &stream->pcm_handle, &stream->hw_params);
+ if(FAILED(params->result)){
+ free(stream);
+ return STATUS_SUCCESS;
+ }
+
+ stream->need_remapping = map_channels(params->flow, params->fmt, &stream->alsa_channels, stream->alsa_channel_map) == S_OK;
+
+ if((err = snd_pcm_hw_params_any(stream->pcm_handle, stream->hw_params)) < 0){
+ WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_hw_params_set_access(stream->pcm_handle, stream->hw_params,
+ SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
+ WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ format = alsa_format(params->fmt);
+ if (format == SND_PCM_FORMAT_UNKNOWN){
+ params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ goto exit;
+ }
+
+ if((err = snd_pcm_hw_params_set_format(stream->pcm_handle, stream->hw_params,
+ format)) < 0){
+ WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
+ snd_strerror(err));
+ params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ goto exit;
+ }
+
+ stream->alsa_format = format;
+ stream->flow = params->flow;
+
+ rate = params->fmt->nSamplesPerSec;
+ if((err = snd_pcm_hw_params_set_rate_near(stream->pcm_handle, stream->hw_params,
+ &rate, NULL)) < 0){
+ WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
+ snd_strerror(err));
+ params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ goto exit;
+ }
+
+ if((err = snd_pcm_hw_params_set_channels(stream->pcm_handle, stream->hw_params,
+ stream->alsa_channels)) < 0){
+ WARN("Unable to set channels to %u: %d (%s)\n", params->fmt->nChannels, err,
+ snd_strerror(err));
+ params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ goto exit;
+ }
+
+ stream->mmdev_period_rt = params->period;
+ alsa_period_us = stream->mmdev_period_rt / 10;
+ if((err = snd_pcm_hw_params_set_period_time_near(stream->pcm_handle,
+ stream->hw_params, &alsa_period_us, NULL)) < 0)
+ WARN("Unable to set period time near %u: %d (%s)\n", alsa_period_us,
+ err, snd_strerror(err));
+ /* ALSA updates the output variable alsa_period_us */
+
+ stream->mmdev_period_frames = muldiv(params->fmt->nSamplesPerSec,
+ stream->mmdev_period_rt, 10000000);
+
+ /* Buffer 4 ALSA periods if large enough, else 4 mmdevapi periods */
+ stream->alsa_bufsize_frames = stream->mmdev_period_frames * 4;
+ if(err < 0 || alsa_period_us < params->period / 10)
+ err = snd_pcm_hw_params_set_buffer_size_near(stream->pcm_handle,
+ stream->hw_params, &stream->alsa_bufsize_frames);
+ else{
+ unsigned int periods = 4;
+ err = snd_pcm_hw_params_set_periods_near(stream->pcm_handle, stream->hw_params, &periods, NULL);
+ }
+ if(err < 0)
+ WARN("Unable to set buffer size: %d (%s)\n", err, snd_strerror(err));
+
+ if((err = snd_pcm_hw_params(stream->pcm_handle, stream->hw_params)) < 0){
+ WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_hw_params_get_period_size(stream->hw_params,
+ &stream->alsa_period_frames, NULL)) < 0){
+ WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_hw_params_get_buffer_size(stream->hw_params,
+ &stream->alsa_bufsize_frames)) < 0){
+ WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ sw_params = calloc(1, snd_pcm_sw_params_sizeof());
+ if(!sw_params){
+ params->result = E_OUTOFMEMORY;
+ goto exit;
+ }
+
+ if((err = snd_pcm_sw_params_current(stream->pcm_handle, sw_params)) < 0){
+ WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_sw_params_set_start_threshold(stream->pcm_handle,
+ sw_params, 1)) < 0){
+ WARN("Unable set start threshold to 1: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_sw_params_set_stop_threshold(stream->pcm_handle,
+ sw_params, stream->alsa_bufsize_frames)) < 0){
+ WARN("Unable set stop threshold to %lu: %d (%s)\n",
+ stream->alsa_bufsize_frames, err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_sw_params(stream->pcm_handle, sw_params)) < 0){
+ WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ if((err = snd_pcm_prepare(stream->pcm_handle)) < 0){
+ WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
+ params->result = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
+ goto exit;
+ }
+
+ /* Bear in mind weird situations where
+ * ALSA period (50ms) > mmdevapi buffer (3x10ms)
+ * or surprising rounding as seen with 22050x8x1 with Pulse:
+ * ALSA period 220 vs. 221 frames in mmdevapi and
+ * buffer 883 vs. 2205 frames in mmdevapi! */
+ stream->bufsize_frames = muldiv(params->duration, params->fmt->nSamplesPerSec, 10000000);
+ if(params->share == AUDCLNT_SHAREMODE_EXCLUSIVE)
+ stream->bufsize_frames -= stream->bufsize_frames % stream->mmdev_period_frames;
+ stream->hidden_frames = stream->alsa_period_frames + stream->mmdev_period_frames +
+ muldiv(params->fmt->nSamplesPerSec, EXTRA_SAFE_RT, 10000000);
+ /* leave no less than about 1.33ms or 256 bytes of data after a rewind */
+ stream->safe_rewind_frames = max(256 / params->fmt->nBlockAlign, muldiv(133, params->fmt->nSamplesPerSec, 100000));
+
+ /* Check if the ALSA buffer is so small that it will run out before
+ * the next MMDevAPI period tick occurs. Allow a little wiggle room
+ * with 120% of the period time. */
+ if(stream->alsa_bufsize_frames < 1.2 * stream->mmdev_period_frames)
+ FIXME("ALSA buffer time is too small. Expect underruns. (%lu < %u * 1.2)\n",
+ stream->alsa_bufsize_frames, stream->mmdev_period_frames);
+
+ fmtex = clone_format(params->fmt);
+ if(!fmtex){
+ params->result = E_OUTOFMEMORY;
+ goto exit;
+ }
+ stream->fmt = &fmtex->Format;
+
+ size = stream->bufsize_frames * params->fmt->nBlockAlign;
+ if(NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, 0, &size,
+ MEM_COMMIT, PAGE_READWRITE)){
+ params->result = E_OUTOFMEMORY;
+ goto exit;
+ }
+ silence_buffer(stream, stream->local_buffer, stream->bufsize_frames);
+
+ stream->silence_buf = malloc(stream->alsa_period_frames * stream->fmt->nBlockAlign);
+ if(!stream->silence_buf){
+ params->result = E_OUTOFMEMORY;
+ goto exit;
+ }
+ silence_buffer(stream, stream->silence_buf, stream->alsa_period_frames);
+
+ stream->vols = malloc(params->fmt->nChannels * sizeof(float));
+ if(!stream->vols){
+ params->result = E_OUTOFMEMORY;
+ goto exit;
+ }
+ for(i = 0; i < params->fmt->nChannels; ++i)
+ stream->vols[i] = 1.f;
+
+ stream->share = params->share;
+ stream->flags = params->flags;
+
+ pthread_mutex_init(&stream->lock, NULL);
+
+ TRACE("ALSA period: %lu frames\n", stream->alsa_period_frames);
+ TRACE("ALSA buffer: %lu frames\n", stream->alsa_bufsize_frames);
+ TRACE("MMDevice period: %u frames\n", stream->mmdev_period_frames);
+ TRACE("MMDevice buffer: %u frames\n", stream->bufsize_frames);
+
+exit:
+ free(sw_params);
+ if(FAILED(params->result)){
+ snd_pcm_close(stream->pcm_handle);
+ if(stream->local_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
+ }
+ free(stream->silence_buf);
+ free(stream->hw_params);
+ free(stream->fmt);
+ free(stream->vols);
+ free(stream);
+ }else{
+ *params->stream = stream;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS release_stream(void *args)
+{
+ struct release_stream_params *params = args;
+ struct alsa_stream *stream = params->stream;
+ SIZE_T size;
+
+ snd_pcm_drop(stream->pcm_handle);
+ snd_pcm_close(stream->pcm_handle);
+ if(stream->local_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
+ }
+ if(stream->tmp_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, &size, MEM_RELEASE);
+ }
+ /* free(stream->remapping_buf); */
+ free(stream->silence_buf);
+ free(stream->hw_params);
+ free(stream->fmt);
+ free(stream->vols);
+ pthread_mutex_destroy(&stream->lock);
+ free(stream);
+
+ params->result = S_OK;
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS is_format_supported(void *args)
{
struct is_format_supported_params *params = args;
@@ -922,6 +1223,8 @@ exit:
unixlib_entry_t __wine_unix_call_funcs[] =
{
get_endpoint_ids,
+ create_stream,
+ release_stream,
is_format_supported,
get_mix_format,
};
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index d89ae4ee9ec..a1477dbe850 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -62,7 +62,6 @@ unixlib_handle_t alsa_handle = 0;
static const REFERENCE_TIME DefaultPeriod = 100000;
static const REFERENCE_TIME MinimumPeriod = 50000;
-#define EXTRA_SAFE_RT 40000
struct ACImpl;
typedef struct ACImpl ACImpl;
@@ -253,6 +252,20 @@ static void alsa_unlock(struct alsa_stream *stream)
pthread_mutex_unlock(&stream->lock);
}
+static HRESULT alsa_stream_release(struct alsa_stream *stream)
+{
+ struct release_stream_params params;
+
+ /* FIXME: to be moved with remap_channels() */
+ HeapFree(GetProcessHeap(), 0, stream->remapping_buf);
+
+ params.stream = stream;
+
+ ALSA_CALL(release_stream, ¶ms);
+
+ return params.result;
+}
+
static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
GUID *guid)
{
@@ -325,11 +338,6 @@ static void get_device_guid(EDataFlow flow, const char *device, GUID *guid)
RegCloseKey(key);
}
-static snd_pcm_stream_t alsa_get_direction(EDataFlow flow)
-{
- return (flow == eRender) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE;
-}
-
static void set_stream_volumes(ACImpl *This)
{
struct alsa_stream *stream = This->stream;
@@ -459,34 +467,6 @@ static BOOL get_alsa_name_by_guid(GUID *guid, char *name, DWORD name_size, EData
return FALSE;
}
-static HRESULT alsa_open_device(const char *alsa_name, EDataFlow flow, snd_pcm_t **pcm_handle,
- snd_pcm_hw_params_t **hw_params)
-{
- int err;
-
- if(flow != eRender && flow != eCapture)
- return E_UNEXPECTED;
-
- err = snd_pcm_open(pcm_handle, alsa_name, alsa_get_direction(flow), SND_PCM_NONBLOCK);
- if(err < 0){
- WARN("Unable to open PCM \"%s\": %d (%s)\n", alsa_name, err, snd_strerror(err));
- switch(err){
- case -EBUSY:
- return AUDCLNT_E_DEVICE_IN_USE;
- default:
- return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- }
- }
-
- *hw_params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_hw_params_sizeof());
- if(!*hw_params){
- snd_pcm_close(*pcm_handle);
- return E_OUTOFMEMORY;
- }
-
- return S_OK;
-}
-
HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient **out)
{
ACImpl *This;
@@ -570,7 +550,6 @@ static ULONG WINAPI AudioClient_AddRef(IAudioClient3 *iface)
static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
{
ACImpl *This = impl_from_IAudioClient3(iface);
- struct alsa_stream *stream = This->stream;
ULONG ref;
ref = InterlockedDecrement(&This->ref);
@@ -596,26 +575,8 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
LeaveCriticalSection(&g_sessions_lock);
}
HeapFree(GetProcessHeap(), 0, This->vols);
- if (stream){
- SIZE_T size;
- snd_pcm_drop(stream->pcm_handle);
- snd_pcm_close(stream->pcm_handle);
- if(stream->local_buffer){
- size = 0;
- NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
- }
- if(stream->tmp_buffer){
- size = 0;
- NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, &size, MEM_RELEASE);
- }
- HeapFree(GetProcessHeap(), 0, stream->remapping_buf);
- HeapFree(GetProcessHeap(), 0, stream->silence_buf);
- HeapFree(GetProcessHeap(), 0, stream->hw_params);
- CoTaskMemFree(stream->fmt);
- HeapFree(GetProcessHeap(), 0, stream->vols);
- pthread_mutex_destroy(&stream->lock);
- HeapFree(GetProcessHeap(), 0, stream);
- }
+ if (This->stream)
+ alsa_stream_release(This->stream);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
@@ -655,66 +616,6 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
}
}
-static WAVEFORMATEX *clone_format(const WAVEFORMATEX *fmt)
-{
- WAVEFORMATEX *ret;
- size_t size;
-
- if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
- size = sizeof(WAVEFORMATEXTENSIBLE);
- else
- size = sizeof(WAVEFORMATEX);
-
- ret = CoTaskMemAlloc(size);
- if(!ret)
- return NULL;
-
- memcpy(ret, fmt, size);
-
- ret->cbSize = size - sizeof(WAVEFORMATEX);
-
- return ret;
-}
-
-static snd_pcm_format_t alsa_format(const WAVEFORMATEX *fmt)
-{
- snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
- const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
-
- if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
- (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
- if(fmt->wBitsPerSample == 8)
- format = SND_PCM_FORMAT_U8;
- else if(fmt->wBitsPerSample == 16)
- format = SND_PCM_FORMAT_S16_LE;
- else if(fmt->wBitsPerSample == 24)
- format = SND_PCM_FORMAT_S24_3LE;
- else if(fmt->wBitsPerSample == 32)
- format = SND_PCM_FORMAT_S32_LE;
- else
- WARN("Unsupported bit depth: %u\n", fmt->wBitsPerSample);
- if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- fmt->wBitsPerSample != fmtex->Samples.wValidBitsPerSample){
- if(fmtex->Samples.wValidBitsPerSample == 20 && fmt->wBitsPerSample == 24)
- format = SND_PCM_FORMAT_S20_3LE;
- else
- WARN("Unsupported ValidBits: %u\n", fmtex->Samples.wValidBitsPerSample);
- }
- }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
- (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
- if(fmt->wBitsPerSample == 32)
- format = SND_PCM_FORMAT_FLOAT_LE;
- else if(fmt->wBitsPerSample == 64)
- format = SND_PCM_FORMAT_FLOAT64_LE;
- else
- WARN("Unsupported float size: %u\n", fmt->wBitsPerSample);
- }else
- WARN("Unknown wave format: %04x\n", fmt->wFormatTag);
- return format;
-}
-
static void session_init_vols(AudioSession *session, UINT channels)
{
if(session->channel_count < channels){
@@ -794,123 +695,6 @@ static HRESULT get_audio_session(const GUID *sessionguid,
return S_OK;
}
-static int alsa_channel_index(DWORD flag)
-{
- switch(flag){
- case SPEAKER_FRONT_LEFT:
- return 0;
- case SPEAKER_FRONT_RIGHT:
- return 1;
- case SPEAKER_BACK_LEFT:
- return 2;
- case SPEAKER_BACK_RIGHT:
- return 3;
- case SPEAKER_FRONT_CENTER:
- return 4;
- case SPEAKER_LOW_FREQUENCY:
- return 5;
- case SPEAKER_SIDE_LEFT:
- return 6;
- case SPEAKER_SIDE_RIGHT:
- return 7;
- }
- return -1;
-}
-
-static BOOL need_remapping(ACImpl *This, const WAVEFORMATEX *fmt, int *map)
-{
- unsigned int i;
- for(i = 0; i < fmt->nChannels; ++i){
- if(map[i] != i)
- return TRUE;
- }
- return FALSE;
-}
-
-static DWORD get_channel_mask(unsigned int channels)
-{
- switch(channels){
- case 0:
- return 0;
- case 1:
- return KSAUDIO_SPEAKER_MONO;
- case 2:
- return KSAUDIO_SPEAKER_STEREO;
- case 3:
- return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
- case 4:
- return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
- case 5:
- return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
- case 6:
- return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
- case 7:
- return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
- case 8:
- return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
- }
- FIXME("Unknown speaker configuration: %u\n", channels);
- return 0;
-}
-
-static HRESULT map_channels(ACImpl *This, const WAVEFORMATEX *fmt, int *alsa_channels, int *map)
-{
- BOOL need_remap;
-
- if(This->dataflow != eCapture && (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE || fmt->nChannels > 2) ){
- WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt;
- DWORD mask, flag = SPEAKER_FRONT_LEFT;
- UINT i = 0;
-
- if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- fmtex->dwChannelMask != 0)
- mask = fmtex->dwChannelMask;
- else
- mask = get_channel_mask(fmt->nChannels);
-
- *alsa_channels = 0;
-
- while(i < fmt->nChannels && !(flag & SPEAKER_RESERVED)){
- if(mask & flag){
- map[i] = alsa_channel_index(flag);
- TRACE("Mapping mmdevapi channel %u (0x%x) to ALSA channel %d\n",
- i, flag, map[i]);
- if(map[i] >= *alsa_channels)
- *alsa_channels = map[i] + 1;
- ++i;
- }
- flag <<= 1;
- }
-
- while(i < fmt->nChannels){
- map[i] = *alsa_channels;
- TRACE("Mapping mmdevapi channel %u to ALSA channel %d\n",
- i, map[i]);
- ++*alsa_channels;
- ++i;
- }
-
- for(i = 0; i < fmt->nChannels; ++i){
- if(map[i] == -1){
- map[i] = *alsa_channels;
- ++*alsa_channels;
- TRACE("Remapping mmdevapi channel %u to ALSA channel %d\n",
- i, map[i]);
- }
- }
-
- need_remap = need_remapping(This, fmt, map);
- }else{
- *alsa_channels = fmt->nChannels;
-
- need_remap = FALSE;
- }
-
- TRACE("need_remapping: %u, alsa_channels: %d\n", need_remap, *alsa_channels);
-
- return need_remap ? S_OK : S_FALSE;
-}
-
static void silence_buffer(struct alsa_stream *stream, BYTE *buffer, UINT32 frames)
{
WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)stream->fmt;
@@ -929,13 +713,9 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
const GUID *sessionguid)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ struct create_stream_params params;
struct alsa_stream *stream;
- snd_pcm_sw_params_t *sw_params = NULL;
- snd_pcm_format_t format;
- unsigned int rate, alsa_period_us;
- int err, i;
- HRESULT hr = S_OK;
- SIZE_T size;
+ unsigned int 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));
@@ -997,237 +777,40 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
dump_fmt(fmt);
- stream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->stream));
- if(!stream){
- LeaveCriticalSection(&g_sessions_lock);
- return E_OUTOFMEMORY;
- }
+ params.alsa_name = This->alsa_name;
+ params.flow = This->dataflow;
+ params.share = mode;
+ params.flags = flags;
+ params.duration = duration;
+ params.period = period;
+ params.fmt = fmt;
+ params.stream = &stream;
- hr = alsa_open_device(This->alsa_name, This->dataflow, &stream->pcm_handle, &stream->hw_params);
- if(FAILED(hr)){
+ ALSA_CALL(create_stream, ¶ms);
+ if(FAILED(params.result)){
LeaveCriticalSection(&g_sessions_lock);
- return hr;
- }
-
- stream->need_remapping = map_channels(This, fmt, &stream->alsa_channels, stream->alsa_channel_map) == S_OK;
-
- if((err = snd_pcm_hw_params_any(stream->pcm_handle, stream->hw_params)) < 0){
- WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_hw_params_set_access(stream->pcm_handle, stream->hw_params,
- SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
- WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- format = alsa_format(fmt);
- if (format == SND_PCM_FORMAT_UNKNOWN){
- hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
- goto exit;
- }
-
- if((err = snd_pcm_hw_params_set_format(stream->pcm_handle, stream->hw_params,
- format)) < 0){
- WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
- snd_strerror(err));
- hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
- goto exit;
- }
-
- stream->alsa_format = format;
- stream->flow = This->dataflow;
-
- rate = fmt->nSamplesPerSec;
- if((err = snd_pcm_hw_params_set_rate_near(stream->pcm_handle, stream->hw_params,
- &rate, NULL)) < 0){
- WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
- snd_strerror(err));
- hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
- goto exit;
- }
-
- if((err = snd_pcm_hw_params_set_channels(stream->pcm_handle, stream->hw_params,
- stream->alsa_channels)) < 0){
- WARN("Unable to set channels to %u: %d (%s)\n", fmt->nChannels, err,
- snd_strerror(err));
- hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
- goto exit;
- }
-
- stream->mmdev_period_rt = period;
- alsa_period_us = stream->mmdev_period_rt / 10;
- if((err = snd_pcm_hw_params_set_period_time_near(stream->pcm_handle,
- stream->hw_params, &alsa_period_us, NULL)) < 0)
- WARN("Unable to set period time near %u: %d (%s)\n", alsa_period_us,
- err, snd_strerror(err));
- /* ALSA updates the output variable alsa_period_us */
-
- stream->mmdev_period_frames = MulDiv(fmt->nSamplesPerSec,
- stream->mmdev_period_rt, 10000000);
-
- /* Buffer 4 ALSA periods if large enough, else 4 mmdevapi periods */
- stream->alsa_bufsize_frames = stream->mmdev_period_frames * 4;
- if(err < 0 || alsa_period_us < period / 10)
- err = snd_pcm_hw_params_set_buffer_size_near(stream->pcm_handle,
- stream->hw_params, &stream->alsa_bufsize_frames);
- else{
- unsigned int periods = 4;
- err = snd_pcm_hw_params_set_periods_near(stream->pcm_handle, stream->hw_params, &periods, NULL);
- }
- if(err < 0)
- WARN("Unable to set buffer size: %d (%s)\n", err, snd_strerror(err));
-
- if((err = snd_pcm_hw_params(stream->pcm_handle, stream->hw_params)) < 0){
- WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
+ return params.result;
}
- if((err = snd_pcm_hw_params_get_period_size(stream->hw_params,
- &stream->alsa_period_frames, NULL)) < 0){
- WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_hw_params_get_buffer_size(stream->hw_params,
- &stream->alsa_bufsize_frames)) < 0){
- WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- sw_params = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_sw_params_sizeof());
- if(!sw_params){
- hr = E_OUTOFMEMORY;
- goto exit;
- }
-
- if((err = snd_pcm_sw_params_current(stream->pcm_handle, sw_params)) < 0){
- WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_sw_params_set_start_threshold(stream->pcm_handle,
- sw_params, 1)) < 0){
- WARN("Unable set start threshold to 1: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_sw_params_set_stop_threshold(stream->pcm_handle,
- sw_params, stream->alsa_bufsize_frames)) < 0){
- WARN("Unable set stop threshold to %lu: %d (%s)\n",
- stream->alsa_bufsize_frames, err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_sw_params(stream->pcm_handle, sw_params)) < 0){
- WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- if((err = snd_pcm_prepare(stream->pcm_handle)) < 0){
- WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
- hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
- goto exit;
- }
-
- /* Bear in mind weird situations where
- * ALSA period (50ms) > mmdevapi buffer (3x10ms)
- * or surprising rounding as seen with 22050x8x1 with Pulse:
- * ALSA period 220 vs. 221 frames in mmdevapi and
- * buffer 883 vs. 2205 frames in mmdevapi! */
- stream->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
- if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- stream->bufsize_frames -= stream->bufsize_frames % stream->mmdev_period_frames;
- stream->hidden_frames = stream->alsa_period_frames + stream->mmdev_period_frames +
- MulDiv(fmt->nSamplesPerSec, EXTRA_SAFE_RT, 10000000);
- /* leave no less than about 1.33ms or 256 bytes of data after a rewind */
- stream->safe_rewind_frames = max(256 / fmt->nBlockAlign, MulDiv(133, fmt->nSamplesPerSec, 100000));
-
- /* Check if the ALSA buffer is so small that it will run out before
- * the next MMDevAPI period tick occurs. Allow a little wiggle room
- * with 120% of the period time. */
- if(stream->alsa_bufsize_frames < 1.2 * stream->mmdev_period_frames)
- FIXME("ALSA buffer time is too small. Expect underruns. (%lu < %u * 1.2)\n",
- stream->alsa_bufsize_frames, stream->mmdev_period_frames);
-
- stream->fmt = clone_format(fmt);
- if(!stream->fmt){
- hr = E_OUTOFMEMORY;
- goto exit;
- }
-
- size = stream->bufsize_frames * fmt->nBlockAlign;
- if(NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, 0, &size,
- MEM_COMMIT, PAGE_READWRITE)){
- hr = E_OUTOFMEMORY;
- goto exit;
- }
- silence_buffer(stream, stream->local_buffer, stream->bufsize_frames);
-
- stream->silence_buf = HeapAlloc(GetProcessHeap(), 0,
- stream->alsa_period_frames * stream->fmt->nBlockAlign);
- if(!stream->silence_buf){
- hr = E_OUTOFMEMORY;
- goto exit;
- }
- pthread_mutex_init(&stream->lock, NULL);
- silence_buffer(stream, stream->silence_buf, stream->alsa_period_frames);
-
This->channel_count = fmt->nChannels;
This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
if(!This->vols){
- hr = E_OUTOFMEMORY;
+ params.result = E_OUTOFMEMORY;
goto exit;
}
-
for(i = 0; i < This->channel_count; ++i)
This->vols[i] = 1.f;
- stream->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
- if(!stream->vols){
- hr = E_OUTOFMEMORY;
- goto exit;
- }
- for(i = 0; i < fmt->nChannels; ++i)
- stream->vols[i] = 1.f;
-
- stream->share = mode;
- stream->flags = flags;
-
- hr = get_audio_session(sessionguid, This->parent, This->channel_count,
- &This->session);
- if(FAILED(hr))
+ params.result = get_audio_session(sessionguid, This->parent, This->channel_count,
+ &This->session);
+ if(FAILED(params.result))
goto exit;
list_add_tail(&This->session->clients, &This->entry);
- TRACE("ALSA period: %lu frames\n", stream->alsa_period_frames);
- TRACE("ALSA buffer: %lu frames\n", stream->alsa_bufsize_frames);
- TRACE("MMDevice period: %u frames\n", stream->mmdev_period_frames);
- TRACE("MMDevice buffer: %u frames\n", stream->bufsize_frames);
-
exit:
- HeapFree(GetProcessHeap(), 0, sw_params);
- if(FAILED(hr)){
- snd_pcm_close(stream->pcm_handle);
- if(stream->local_buffer){
- size = 0;
- NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
- }
- CoTaskMemFree(stream->fmt);
- stream->fmt = NULL;
- HeapFree(GetProcessHeap(), 0, stream->vols);
- HeapFree(GetProcessHeap(), 0, stream);
+ if(FAILED(params.result)){
+ alsa_stream_release(stream);
HeapFree(GetProcessHeap(), 0, This->vols);
This->vols = NULL;
}else{
@@ -1237,7 +820,7 @@ exit:
LeaveCriticalSection(&g_sessions_lock);
- return hr;
+ return params.result;
}
static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 615eb47c7a5..771f189bca4 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -71,6 +71,25 @@ struct get_endpoint_ids_params
unsigned int default_idx;
};
+struct create_stream_params
+{
+ const char *alsa_name;
+ EDataFlow flow;
+ AUDCLNT_SHAREMODE share;
+ DWORD flags;
+ REFERENCE_TIME duration;
+ REFERENCE_TIME period;
+ const WAVEFORMATEX *fmt;
+ HRESULT result;
+ struct alsa_stream **stream;
+};
+
+struct release_stream_params
+{
+ struct alsa_stream *stream;
+ HRESULT result;
+};
+
struct is_format_supported_params
{
const char *alsa_name;
@@ -92,6 +111,8 @@ struct get_mix_format_params
enum alsa_funcs
{
alsa_get_endpoint_ids,
+ alsa_create_stream,
+ alsa_release_stream,
alsa_is_format_supported,
alsa_get_mix_format,
};
--
2.25.1
2
1
[PATCH 3/4] winealsa: Use NtAllocateVirtualMemory() to alloc the buffers returned to the user.
by Huw Davies 22 Feb '22
by Huw Davies 22 Feb '22
22 Feb '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/mmdevdrv.c | 52 +++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 15 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 23a420c8ac7..d89ae4ee9ec 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -597,12 +597,19 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
}
HeapFree(GetProcessHeap(), 0, This->vols);
if (stream){
+ SIZE_T size;
snd_pcm_drop(stream->pcm_handle);
snd_pcm_close(stream->pcm_handle);
- HeapFree(GetProcessHeap(), 0, stream->local_buffer);
+ if(stream->local_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
+ }
+ if(stream->tmp_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, &size, MEM_RELEASE);
+ }
HeapFree(GetProcessHeap(), 0, stream->remapping_buf);
HeapFree(GetProcessHeap(), 0, stream->silence_buf);
- HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
HeapFree(GetProcessHeap(), 0, stream->hw_params);
CoTaskMemFree(stream->fmt);
HeapFree(GetProcessHeap(), 0, stream->vols);
@@ -928,6 +935,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
unsigned int rate, alsa_period_us;
int err, i;
HRESULT hr = S_OK;
+ SIZE_T size;
TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
@@ -1158,9 +1166,9 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
goto exit;
}
- stream->local_buffer = HeapAlloc(GetProcessHeap(), 0,
- stream->bufsize_frames * fmt->nBlockAlign);
- if(!stream->local_buffer){
+ size = stream->bufsize_frames * fmt->nBlockAlign;
+ if(NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, 0, &size,
+ MEM_COMMIT, PAGE_READWRITE)){
hr = E_OUTOFMEMORY;
goto exit;
}
@@ -1212,8 +1220,10 @@ exit:
HeapFree(GetProcessHeap(), 0, sw_params);
if(FAILED(hr)){
snd_pcm_close(stream->pcm_handle);
- HeapFree(GetProcessHeap(), 0, stream->local_buffer);
- stream->local_buffer = NULL;
+ if(stream->local_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE);
+ }
CoTaskMemFree(stream->fmt);
stream->fmt = NULL;
HeapFree(GetProcessHeap(), 0, stream->vols);
@@ -2297,6 +2307,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
ACImpl *This = impl_from_IAudioRenderClient(iface);
struct alsa_stream *stream = This->stream;
UINT32 write_pos;
+ SIZE_T size;
TRACE("(%p)->(%u, %p)\n", This, frames, data);
@@ -2325,10 +2336,15 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
write_pos = stream->wri_offs_frames;
if(write_pos + frames > stream->bufsize_frames){
if(stream->tmp_buffer_frames < frames){
- HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
- stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
- frames * stream->fmt->nBlockAlign);
- if(!stream->tmp_buffer){
+ if(stream->tmp_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, &size, MEM_RELEASE);
+ stream->tmp_buffer = NULL;
+ }
+ size = frames * stream->fmt->nBlockAlign;
+ if(NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, 0, &size,
+ MEM_COMMIT, PAGE_READWRITE)){
+ stream->tmp_buffer_frames = 0;
alsa_unlock(stream);
return E_OUTOFMEMORY;
}
@@ -2465,6 +2481,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
{
ACImpl *This = impl_from_IAudioCaptureClient(iface);
struct alsa_stream *stream = This->stream;
+ SIZE_T size;
TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
devpos, qpcpos);
@@ -2495,10 +2512,15 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
if(stream->lcl_offs_frames + *frames > stream->bufsize_frames){
UINT32 chunk_bytes, offs_bytes, frames_bytes;
if(stream->tmp_buffer_frames < *frames){
- HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
- stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
- *frames * stream->fmt->nBlockAlign);
- if(!stream->tmp_buffer){
+ if(stream->tmp_buffer){
+ size = 0;
+ NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, &size, MEM_RELEASE);
+ stream->tmp_buffer = NULL;
+ }
+ size = *frames * stream->fmt->nBlockAlign;
+ if(NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer, 0, &size,
+ MEM_COMMIT, PAGE_READWRITE)){
+ stream->tmp_buffer_frames = 0;
alsa_unlock(stream);
return E_OUTOFMEMORY;
}
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/mmdevdrv.c | 162 +++++++++++++++++------------------
dlls/winealsa.drv/unixlib.h | 2 +
2 files changed, 80 insertions(+), 84 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 4d38240a853..23a420c8ac7 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
+#include <pthread.h>
#include "windef.h"
#include "winbase.h"
@@ -111,8 +112,6 @@ struct ACImpl {
HANDLE timer;
- CRITICAL_SECTION lock;
-
AudioSession *session;
AudioSessionWrapper *session_wrapper;
@@ -244,6 +243,16 @@ int WINAPI AUDDRV_GetPriority(void)
return Priority_Neutral;
}
+static void alsa_lock(struct alsa_stream *stream)
+{
+ pthread_mutex_lock(&stream->lock);
+}
+
+static void alsa_unlock(struct alsa_stream *stream)
+{
+ pthread_mutex_unlock(&stream->lock);
+}
+
static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
GUID *guid)
{
@@ -515,9 +524,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
This->dataflow = dataflow;
memcpy(This->alsa_name, alsa_name, len + 1);
- InitializeCriticalSection(&This->lock);
- This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ACImpl.lock");
-
This->parent = dev;
IMMDevice_AddRef(This->parent);
@@ -584,8 +590,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
IAudioClient3_Stop(iface);
IMMDevice_Release(This->parent);
IUnknown_Release(This->pUnkFTMarshal);
- This->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->lock);
if(This->session){
EnterCriticalSection(&g_sessions_lock);
list_remove(&This->entry);
@@ -602,6 +606,7 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
HeapFree(GetProcessHeap(), 0, stream->hw_params);
CoTaskMemFree(stream->fmt);
HeapFree(GetProcessHeap(), 0, stream->vols);
+ pthread_mutex_destroy(&stream->lock);
HeapFree(GetProcessHeap(), 0, stream);
}
HeapFree(GetProcessHeap(), 0, This);
@@ -1167,6 +1172,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
hr = E_OUTOFMEMORY;
goto exit;
}
+ pthread_mutex_init(&stream->lock, NULL);
silence_buffer(stream, stream->silence_buf, stream->alsa_period_frames);
This->channel_count = fmt->nChannels;
@@ -1235,16 +1241,14 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
if(!out)
return E_POINTER;
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
*out = stream->bufsize_frames;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -1260,12 +1264,10 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
if(!latency)
return E_POINTER;
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
/* Hide some frames in the ALSA buffer. Allows us to return GetCurrentPadding=0
* yet have enough data left to play (as if it were in native's mixer). Add:
@@ -1278,7 +1280,7 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
*latency = MulDiv(stream->alsa_period_frames, 10000000, stream->fmt->nSamplesPerSec)
+ stream->mmdev_period_rt;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -1294,17 +1296,15 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
if(!out)
return E_POINTER;
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
/* padding is solely updated at callback time in shared mode */
*out = stream->held_frames;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
TRACE("pad: %u\n", *out);
@@ -1818,7 +1818,7 @@ static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
ACImpl *This = user;
struct alsa_stream *stream = This->stream;
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
QueryPerformanceCounter(&stream->last_period_time);
@@ -1827,7 +1827,7 @@ static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
else if(stream->flow == eCapture)
alsa_read_data(stream);
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
}
static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream)
@@ -1880,22 +1880,22 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
TRACE("(%p)\n", This);
EnterCriticalSection(&g_sessions_lock);
- EnterCriticalSection(&This->lock);
if(!This->stream){
- LeaveCriticalSection(&This->lock);
LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
+ alsa_lock(stream);
+
if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_EVENTHANDLE_NOT_SET;
}
if(stream->started){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_NOT_STOPPED;
}
@@ -1932,7 +1932,7 @@ 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)){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
LeaveCriticalSection(&g_sessions_lock);
WARN("Unable to create timer: %u\n", GetLastError());
return E_OUTOFMEMORY;
@@ -1941,7 +1941,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
stream->started = TRUE;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
LeaveCriticalSection(&g_sessions_lock);
return S_OK;
@@ -1954,15 +1954,13 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
TRACE("(%p)\n", This);
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
if(!stream->started){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_FALSE;
}
@@ -1971,7 +1969,7 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
stream->started = FALSE;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -1983,20 +1981,18 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
TRACE("(%p)\n", This);
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
if(stream->started){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_NOT_STOPPED;
}
if(stream->getbuf_last){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_BUFFER_OPERATION_PENDING;
}
@@ -2019,7 +2015,7 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
stream->lcl_offs_frames = 0;
stream->wri_offs_frames = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2035,27 +2031,25 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
if(!event)
return E_INVALIDARG;
- EnterCriticalSection(&This->lock);
-
- if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ if(!This->stream)
return AUDCLNT_E_NOT_INITIALIZED;
- }
+
+ alsa_lock(stream);
if(!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
}
if (stream->event){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
FIXME("called twice\n");
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
}
stream->event = event;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2310,21 +2304,21 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
return E_POINTER;
*data = NULL;
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
if(stream->getbuf_last){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_OUT_OF_ORDER;
}
if(!frames){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
/* held_frames == GetCurrentPadding_nolock(); */
if(stream->held_frames + frames > stream->bufsize_frames){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_BUFFER_TOO_LARGE;
}
@@ -2335,7 +2329,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
frames * stream->fmt->nBlockAlign);
if(!stream->tmp_buffer){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return E_OUTOFMEMORY;
}
stream->tmp_buffer_frames = frames;
@@ -2349,7 +2343,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
silence_buffer(stream, *data, frames);
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2380,21 +2374,21 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
if(!written_frames){
stream->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
if(!stream->getbuf_last){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_OUT_OF_ORDER;
}
if(written_frames > (stream->getbuf_last >= 0 ? stream->getbuf_last : -stream->getbuf_last)){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_INVALID_SIZE;
}
@@ -2415,7 +2409,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
stream->written_frames += written_frames;
stream->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2483,17 +2477,17 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
if(!frames || !flags)
return E_POINTER;
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
if(stream->getbuf_last){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_OUT_OF_ORDER;
}
/* hr = GetNextPacketSize(iface, frames); */
if(stream->held_frames < stream->mmdev_period_frames){
*frames = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_S_BUFFER_EMPTY;
}
*frames = stream->mmdev_period_frames;
@@ -2505,7 +2499,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
*frames * stream->fmt->nBlockAlign);
if(!stream->tmp_buffer){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return E_OUTOFMEMORY;
}
stream->tmp_buffer_frames = *frames;
@@ -2535,7 +2529,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
*qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
}
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
}
@@ -2548,21 +2542,21 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
TRACE("(%p)->(%u)\n", This, done);
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
if(!done){
stream->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
if(!stream->getbuf_last){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_OUT_OF_ORDER;
}
if(stream->getbuf_last != done){
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return AUDCLNT_E_INVALID_SIZE;
}
@@ -2572,7 +2566,7 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
stream->lcl_offs_frames %= stream->bufsize_frames;
stream->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2588,11 +2582,11 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
if(!frames)
return E_POINTER;
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
*frames = stream->held_frames < stream->mmdev_period_frames ? 0 : stream->mmdev_period_frames;
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
return S_OK;
}
@@ -2671,7 +2665,7 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
if(!pos)
return E_POINTER;
- EnterCriticalSection(&This->lock);
+ alsa_lock(stream);
/* avail_update required to get accurate snd_pcm_state() */
snd_pcm_avail_update(stream->pcm_handle);
@@ -2702,7 +2696,7 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
(UINT32)(stream->written_frames%1000000000), stream->held_frames,
alsa_state, (UINT32)(position%1000000000));
- LeaveCriticalSection(&This->lock);
+ alsa_unlock(stream);
if(stream->share == AUDCLNT_SHAREMODE_SHARED)
*pos = position * stream->fmt->nBlockAlign;
@@ -2874,14 +2868,14 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
}
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
- EnterCriticalSection(&client->lock);
+ alsa_lock(client->stream);
if(client->stream->started){
*state = AudioSessionStateActive;
- LeaveCriticalSection(&client->lock);
+ alsa_unlock(client->stream);
LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
- LeaveCriticalSection(&client->lock);
+ alsa_unlock(client->stream);
}
LeaveCriticalSection(&g_sessions_lock);
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index c0dc625e27f..615eb47c7a5 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -51,6 +51,8 @@ struct alsa_stream
BYTE *local_buffer, *tmp_buffer, *remapping_buf, *silence_buf;
LONG32 getbuf_last; /* <0 when using tmp_buffer */
float *vols;
+
+ pthread_mutex_t lock;
};
struct endpoint
--
2.25.1
2
1
22 Feb '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/mmdevdrv.c | 45 ++++++++++++++++++------------------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 5bb3bdbcc73..4d38240a853 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -976,10 +976,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
EnterCriticalSection(&g_sessions_lock);
- EnterCriticalSection(&This->lock);
if(This->stream){
- LeaveCriticalSection(&This->lock);
LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_ALREADY_INITIALIZED;
}
@@ -988,14 +986,12 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
stream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->stream));
if(!stream){
- LeaveCriticalSection(&This->lock);
LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
hr = alsa_open_device(This->alsa_name, This->dataflow, &stream->pcm_handle, &stream->hw_params);
if(FAILED(hr)){
- LeaveCriticalSection(&This->lock);
LeaveCriticalSection(&g_sessions_lock);
return hr;
}
@@ -1223,7 +1219,6 @@ exit:
set_stream_volumes(This);
}
- LeaveCriticalSection(&This->lock);
LeaveCriticalSection(&g_sessions_lock);
return hr;
@@ -1884,20 +1879,24 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
TRACE("(%p)\n", This);
+ EnterCriticalSection(&g_sessions_lock);
EnterCriticalSection(&This->lock);
if(!This->stream){
LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event){
LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_EVENTHANDLE_NOT_SET;
}
if(stream->started){
LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_NOT_STOPPED;
}
@@ -1934,6 +1933,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
This, 0, stream->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
WARN("Unable to create timer: %u\n", GetLastError());
return E_OUTOFMEMORY;
}
@@ -1942,6 +1942,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
stream->started = TRUE;
LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -2070,23 +2071,23 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
return E_POINTER;
*ppv = NULL;
- EnterCriticalSection(&This->lock);
+ EnterCriticalSection(&g_sessions_lock);
if(!This->stream){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_NOT_INITIALIZED;
}
if(IsEqualIID(riid, &IID_IAudioRenderClient)){
if(This->dataflow != eRender){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_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){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
}
IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
@@ -2101,7 +2102,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
}else
@@ -2112,7 +2113,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
}else
@@ -2123,7 +2124,7 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
if(!This->session_wrapper){
This->session_wrapper = AudioSessionWrapper_Create(This);
if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return E_OUTOFMEMORY;
}
}else
@@ -2133,11 +2134,11 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
}
if(*ppv){
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
FIXME("stub %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
@@ -2843,9 +2844,9 @@ static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
TRACE("(%p) Refcount now %u\n", This, ref);
if(!ref){
if(This->client){
- EnterCriticalSection(&This->client->lock);
+ EnterCriticalSection(&g_sessions_lock);
This->client->session_wrapper = NULL;
- LeaveCriticalSection(&This->client->lock);
+ LeaveCriticalSection(&g_sessions_lock);
AudioClient_Release(&This->client->IAudioClient3_iface);
}
HeapFree(GetProcessHeap(), 0, This);
@@ -3238,12 +3239,12 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
TRACE("ALSA does not support volume control\n");
- EnterCriticalSection(&This->lock);
+ EnterCriticalSection(&g_sessions_lock);
This->vols[index] = level;
set_stream_volumes(This);
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3282,13 +3283,13 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
TRACE("ALSA does not support volume control\n");
- EnterCriticalSection(&This->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
This->vols[i] = levels[i];
set_stream_volumes(This);
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3307,12 +3308,12 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(count != This->channel_count)
return E_INVALIDARG;
- EnterCriticalSection(&This->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
levels[i] = This->vols[i];
- LeaveCriticalSection(&This->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
--
2.25.1
2
1
22 Feb '22
Wine's test infrastructure allows to call ./wine <test>.exe without
test name when only a single test is available in <test>.exe.
Unfortunately, a lots of tests also rely on winetest_argv[1] to be
the name of current test
(esp. when respawning themselves to run sub processes).
So, ensure wintest_argv is correctly populated in the case of a <test>
containing a single test file and called without any argument on
command line.
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
include/wine/test.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/wine/test.h b/include/wine/test.h
index 599234b3519..fc96bfa9877 100644
--- a/include/wine/test.h
+++ b/include/wine/test.h
@@ -691,7 +691,11 @@ int main( int argc, char **argv )
if (!argv[1])
{
if (winetest_testlist[0].name && !winetest_testlist[1].name) /* only one test */
+ {
+ static char* fake_argv[3] = {argv[0], winetest_testlist[0].name, NULL};
+ winetest_argv = fake_argv;
return run_test( winetest_testlist[0].name );
+ }
usage( argv[0] );
}
if (!strcmp( argv[1], "--list" ))
2
1
22 Feb '22
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/cursoricon.c | 241 ++---------------------------------
dlls/user32/driver.c | 7 +-
dlls/user32/user_main.c | 6 +
dlls/win32u/cursoricon.c | 217 +++++++++++++++++++++++++++++++
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 2 +
dlls/win32u/ntuser_private.h | 34 +++++
dlls/win32u/syscall.c | 1 +
dlls/win32u/sysparams.c | 2 +
dlls/win32u/win32u.spec | 6 +-
dlls/win32u/win32u_private.h | 4 +
dlls/win32u/window.c | 9 ++
dlls/win32u/wrappers.c | 13 ++
dlls/wow64win/syscall.h | 1 +
dlls/wow64win/user.c | 15 +++
include/ntuser.h | 18 +++
16 files changed, 339 insertions(+), 238 deletions(-)
2
1