Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH 1/8] mshtml: Expose IE10+ XMLHttpRequest props via private interface.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/mshtml/mshtml_private.h | 1 +
dlls/mshtml/mshtml_private_iface.idl | 46 +++++
dlls/mshtml/tests/documentmode.js | 10 ++
dlls/mshtml/xmlhttprequest.c | 243 +++++++++++++++++++++++++++
4 files changed, 300 insertions(+)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index ca637e5..d8b4dde 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -282,6 +282,7 @@ typedef struct EventTarget EventTarget;
XIID(IWineHTMLElementPrivate) \
XIID(IWineHTMLWindowPrivate) \
XIID(IWineHTMLWindowCompatPrivate) \
+ XIID(IWineXMLHttpRequestPrivate) \
XIID(IWineMSHTMLConsole)
typedef enum {
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl
index a273e33..972f9b3 100644
--- a/dlls/mshtml/mshtml_private_iface.idl
+++ b/dlls/mshtml/mshtml_private_iface.idl
@@ -139,4 +139,50 @@ interface IWineDOMTokenList : IDispatch
HRESULT toString([retval, out] BSTR *String);
}
+const long DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE = 5;
+[
+ odl,
+ oleautomation,
+ dual,
+ hidden,
+ uuid(08ef0edd-5fb8-4178-a2f0-9f686e00441c)
+]
+interface IWineXMLHttpRequestPrivate : IDispatch
+{
+ [propget, id(1)]
+ HRESULT response([retval, out] VARIANT *p);
+ [propput, id(2)]
+ HRESULT responseType([in] BSTR v);
+ [propget, id(2)]
+ HRESULT responseType([retval, out] BSTR *p);
+ [propget, id(3)]
+ HRESULT upload([retval, out] IDispatch **p);
+ [propput, id(4)]
+ HRESULT withCredentials([in] VARIANT_BOOL v);
+ [propget, id(4)]
+ HRESULT withCredentials([retval, out] VARIANT_BOOL *p);
+ [id(DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE)]
+ HRESULT overrideMimeType([in] BSTR mimeType);
+ [propput, id(DISPID_EVPROP_ONERROR)]
+ HRESULT onerror([in] VARIANT v);
+ [propget, id(DISPID_EVPROP_ONERROR)]
+ HRESULT onerror([retval, out] VARIANT *p);
+ [propput, id(DISPID_EVPROP_ONABORT)]
+ HRESULT onabort([in] VARIANT v);
+ [propget, id(DISPID_EVPROP_ONABORT)]
+ HRESULT onabort([retval, out] VARIANT *p);
+ [propput, id(DISPID_EVPROP_PROGRESS)]
+ HRESULT onprogress([in] VARIANT v);
+ [propget, id(DISPID_EVPROP_PROGRESS)]
+ HRESULT onprogress([retval, out] VARIANT *p);
+ [propput, id(DISPID_EVPROP_LOADSTART)]
+ HRESULT onloadstart([in] VARIANT v);
+ [propget, id(DISPID_EVPROP_LOADSTART)]
+ HRESULT onloadstart([retval, out] VARIANT *p);
+ [propput, id(DISPID_EVPROP_LOADEND)]
+ HRESULT onloadend([in] VARIANT v);
+ [propget, id(DISPID_EVPROP_LOADEND)]
+ HRESULT onloadend([retval, out] VARIANT *p);
+}
+
} /* library MSHTML_private */
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 8503523..f2da811 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -397,8 +397,18 @@ sync_test("xhr_props", function() {
test_exposed("addEventListener", v >= 9);
test_exposed("removeEventListener", v >= 9);
test_exposed("dispatchEvent", v >= 9);
+ test_exposed("onabort", v >= 10);
+ test_exposed("onerror", v >= 10);
+ test_exposed("onloadend", v >= 10);
+ test_exposed("onloadstart", v >= 10);
+ test_exposed("onprogress", v >= 10);
test_exposed("ontimeout", true);
+ test_exposed("overrideMimeType", v >= 11);
+ test_exposed("response", v >= 10);
+ test_exposed("responseType", v >= 10);
test_exposed("timeout", true);
+ test_exposed("upload", v >= 10);
+ test_exposed("withCredentials", v >= 10);
});
sync_test("stylesheet_props", function() {
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index 966dc8d..12356f1 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -97,6 +97,7 @@ static HRESULT return_nscstr(nsresult nsres, nsACString *nscstr, BSTR *p)
static const eventid_t events[] = {
EVENTID_READYSTATECHANGE,
EVENTID_LOAD,
+ EVENTID_ERROR,
EVENTID_TIMEOUT,
};
@@ -111,6 +112,7 @@ struct HTMLXMLHttpRequest {
EventTarget event_target;
IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
IHTMLXMLHttpRequest2 IHTMLXMLHttpRequest2_iface;
+ IWineXMLHttpRequestPrivate IWineXMLHttpRequestPrivate_iface;
IProvideClassInfo2 IProvideClassInfo2_iface;
LONG ref;
nsIXMLHttpRequest *nsxhr;
@@ -240,6 +242,8 @@ static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *ifa
*ppv = &This->IHTMLXMLHttpRequest_iface;
}else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest2, riid)) {
*ppv = &This->IHTMLXMLHttpRequest2_iface;
+ }else if(IsEqualGUID(&IID_IWineXMLHttpRequestPrivate, riid)) {
+ *ppv = &This->IWineXMLHttpRequestPrivate_iface;
}else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
*ppv = &This->IProvideClassInfo2_iface;
}else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
@@ -841,6 +845,238 @@ static const IHTMLXMLHttpRequest2Vtbl HTMLXMLHttpRequest2Vtbl = {
HTMLXMLHttpRequest2_get_ontimeout
};
+static inline HTMLXMLHttpRequest *impl_from_IWineXMLHttpRequestPrivate(IWineXMLHttpRequestPrivate *iface)
+{
+ return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IWineXMLHttpRequestPrivate_iface);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_QueryInterface(IWineXMLHttpRequestPrivate *iface, REFIID riid, void **ppv)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
+}
+
+static ULONG WINAPI HTMLXMLHttpRequest_private_AddRef(IWineXMLHttpRequestPrivate *iface)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
+}
+
+static ULONG WINAPI HTMLXMLHttpRequest_private_Release(IWineXMLHttpRequestPrivate *iface)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_GetTypeInfoCount(IWineXMLHttpRequestPrivate *iface, UINT *pctinfo)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_GetTypeInfo(IWineXMLHttpRequestPrivate *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo **ppTInfo)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_GetIDsOfNames(IWineXMLHttpRequestPrivate *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
+ LCID lcid, DISPID *rgDispId)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
+ lcid, rgDispId);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_Invoke(IWineXMLHttpRequestPrivate *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+ return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
+ pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_response(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_responseType(IWineXMLHttpRequestPrivate *iface, BSTR v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_w(v));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_responseType(IWineXMLHttpRequestPrivate *iface, BSTR *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_upload(IWineXMLHttpRequestPrivate *iface, IDispatch **p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_withCredentials(IWineXMLHttpRequestPrivate *iface, VARIANT_BOOL v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%x)\n", This, v);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_withCredentials(IWineXMLHttpRequestPrivate *iface, VARIANT_BOOL *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_overrideMimeType(IWineXMLHttpRequestPrivate *iface, BSTR mimeType)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_w(mimeType));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
+
+ return set_event_handler(&This->event_target, EVENTID_ERROR, &v);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ return get_event_handler(&This->event_target, EVENTID_ERROR, p);
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT v)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
+{
+ HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
+
+ FIXME("(%p)->(%p)\n", This, p);
+
+ return E_NOTIMPL;
+}
+
+static const IWineXMLHttpRequestPrivateVtbl WineXMLHttpRequestPrivateVtbl = {
+ HTMLXMLHttpRequest_private_QueryInterface,
+ HTMLXMLHttpRequest_private_AddRef,
+ HTMLXMLHttpRequest_private_Release,
+ HTMLXMLHttpRequest_private_GetTypeInfoCount,
+ HTMLXMLHttpRequest_private_GetTypeInfo,
+ HTMLXMLHttpRequest_private_GetIDsOfNames,
+ HTMLXMLHttpRequest_private_Invoke,
+ HTMLXMLHttpRequest_private_get_response,
+ HTMLXMLHttpRequest_private_put_responseType,
+ HTMLXMLHttpRequest_private_get_responseType,
+ HTMLXMLHttpRequest_private_get_upload,
+ HTMLXMLHttpRequest_private_put_withCredentials,
+ HTMLXMLHttpRequest_private_get_withCredentials,
+ HTMLXMLHttpRequest_private_overrideMimeType,
+ HTMLXMLHttpRequest_private_put_onerror,
+ HTMLXMLHttpRequest_private_get_onerror,
+ HTMLXMLHttpRequest_private_put_onabort,
+ HTMLXMLHttpRequest_private_get_onabort,
+ HTMLXMLHttpRequest_private_put_onprogress,
+ HTMLXMLHttpRequest_private_get_onprogress,
+ HTMLXMLHttpRequest_private_put_onloadstart,
+ HTMLXMLHttpRequest_private_get_onloadstart,
+ HTMLXMLHttpRequest_private_put_onloadend,
+ HTMLXMLHttpRequest_private_get_onloadend
+};
+
static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
{
return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
@@ -987,9 +1223,15 @@ static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode
{DISPID_IHTMLXMLHTTPREQUEST_OPEN, HTMLXMLHttpRequest_open_hook},
{DISPID_UNKNOWN}
};
+ static const dispex_hook_t private_ie10_hooks[] = {
+ {DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE},
+ {DISPID_UNKNOWN}
+ };
EventTarget_init_dispex_info(info, compat_mode);
dispex_info_add_interface(info, IHTMLXMLHttpRequest_tid, compat_mode >= COMPAT_MODE_IE10 ? xhr_hooks : NULL);
+ if(compat_mode >= COMPAT_MODE_IE10)
+ dispex_info_add_interface(info, IWineXMLHttpRequestPrivate_tid, compat_mode == COMPAT_MODE_IE10 ? private_ie10_hooks : NULL);
}
static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = {
@@ -1123,6 +1365,7 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor
ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
ret->IHTMLXMLHttpRequest2_iface.lpVtbl = &HTMLXMLHttpRequest2Vtbl;
+ ret->IWineXMLHttpRequestPrivate_iface.lpVtbl = &WineXMLHttpRequestPrivateVtbl;
ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
&HTMLXMLHttpRequest_dispex, This->window->doc->document_mode);
--
2.34.1
June 6, 2022
Re: [PATCH v2 0/6] MR173: preparation for sharing code in d3dx10/d3dx11 - approved
by Matteo Bruni (@Mystral)
This merge request was approved by Matteo Bruni.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/173
June 6, 2022
Re: [PATCH 0/7] MR191: wineandroid: PE conversion preparation - approved
by Huw Davies (@huw)
This merge request was approved by Huw Davies.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022
Re: [PATCH 0/7] MR191: wineandroid: PE conversion preparation
by Huw Davies (@huw)
Looks ok to me, although I haven't built or tested it.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/191#note_1603
June 6, 2022
Re: [PATCH 6/7] wineandroid: Implement desktop window proc using driver interface.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116310
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32:
msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0135 was expected, but got msg 0x030f instead
msg.c:6881: Test failed: SetFocus(hwnd) on a button: 6: the msg 0x002b was expected, but got msg 0x001c instead
msg.c:6881: Test failed: SetFocus(hwnd) on a button: 7: the msg 0x0111 was expected, but got msg 0x0086 instead
msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0006 instead
msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0009
June 6, 2022
[PATCH 7/7] wineandroid: Directly use win32u for user calls.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/wineandroid.drv/device.c | 10 ++--
dlls/wineandroid.drv/init.c | 12 +++--
dlls/wineandroid.drv/opengl.c | 18 ++++----
dlls/wineandroid.drv/window.c | 87 ++++++++++++++++++++++-------------
4 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c
index 30bc474ae19..45009d61a79 100644
--- a/dlls/wineandroid.drv/device.c
+++ b/dlls/wineandroid.drv/device.c
@@ -312,7 +312,7 @@ static struct native_win_data *get_ioctl_native_win_data( const struct ioctl_hea
static int get_ioctl_win_parent( HWND parent )
{
- if (parent != GetDesktopWindow() && !GetAncestor( parent, GA_PARENT ))
+ if (parent != NtUserGetDesktopWindow() && !NtUserGetAncestor( parent, GA_PARENT ))
return HandleToLong( HWND_MESSAGE );
return HandleToLong( parent );
}
@@ -522,7 +522,7 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
if (!data || data->parent == win)
{
pANativeWindow_release( win );
- if (data) PostMessageW( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
+ if (data) NtUserPostMessage( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
TRACE( "%p -> %p win %p (unchanged)\n", hwnd, data, win );
return;
}
@@ -535,7 +535,7 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
win->perform( win, NATIVE_WINDOW_SET_BUFFERS_FORMAT, data->buffer_format );
win->setSwapInterval( win, data->swap_interval );
unwrap_java_call();
- PostMessageW( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
+ NtUserPostMessage( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
TRACE( "%p -> %p win %p\n", hwnd, data, win );
}
@@ -1169,7 +1169,7 @@ static DWORD CALLBACK device_thread( void *arg )
init_java_thread( java_vm );
- create_desktop_window( GetDesktopWindow() );
+ create_desktop_window( NtUserGetDesktopWindow() );
RtlInitUnicodeString( &nameW, driver_nameW );
if ((status = IoCreateDriver( &nameW, init_android_driver )))
@@ -1559,7 +1559,7 @@ struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl, float scale )
req.hdr.hwnd = HandleToLong( win->hwnd );
req.hdr.opengl = win->opengl;
- req.parent = get_ioctl_win_parent( GetAncestor( hwnd, GA_PARENT ));
+ req.parent = get_ioctl_win_parent( NtUserGetAncestor( hwnd, GA_PARENT ));
req.scale = scale;
android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL );
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c
index 694ec1bae9c..f06eb6471c5 100644
--- a/dlls/wineandroid.drv/init.c
+++ b/dlls/wineandroid.drv/init.c
@@ -62,15 +62,19 @@ static const struct user_driver_funcs android_drv_funcs;
void init_monitors( int width, int height )
{
static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
+ UNICODE_STRING name;
RECT rect;
- HWND hwnd = FindWindowW( trayW, NULL );
+ HWND hwnd;
+
+ RtlInitUnicodeString( &name, trayW );
+ hwnd = NtUserFindWindowEx( 0, 0, &name, NULL, 0 );
virtual_screen_rect.right = width;
virtual_screen_rect.bottom = height;
monitor_rc_work = virtual_screen_rect;
- if (!hwnd || !IsWindowVisible( hwnd )) return;
- if (!GetWindowRect( hwnd, &rect )) return;
+ if (!hwnd || !NtUserIsWindowVisible( hwnd )) return;
+ if (!NtUserGetWindowRect( hwnd, &rect )) return;
if (rect.top) monitor_rc_work.bottom = rect.top;
else monitor_rc_work.top = rect.bottom;
TRACE( "found tray %p %s work area %s\n", hwnd,
@@ -170,7 +174,7 @@ static void fetch_display_metrics(void)
SERVER_START_REQ( get_window_rectangles )
{
- req->handle = wine_server_user_handle( GetDesktopWindow() );
+ req->handle = wine_server_user_handle( NtUserGetDesktopWindow() );
req->relative = COORDS_CLIENT;
if (!wine_server_call( req ))
{
diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c
index 9f20e51b8da..afd1ef3f7a5 100644
--- a/dlls/wineandroid.drv/opengl.c
+++ b/dlls/wineandroid.drv/opengl.c
@@ -180,7 +180,7 @@ static BOOL refresh_context( struct wgl_context *ctx )
{
TRACE( "refreshing hwnd %p context %p surface %p\n", ctx->hwnd, ctx->context, ctx->surface );
p_eglMakeCurrent( display, ctx->surface, ctx->surface, ctx->context );
- RedrawWindow( ctx->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
+ NtUserRedrawWindow( ctx->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
}
return ret;
}
@@ -207,17 +207,17 @@ void update_gl_drawable( HWND hwnd )
}
}
release_gl_drawable( gl );
- RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
+ NtUserRedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
}
}
static BOOL set_pixel_format( HDC hdc, int format, BOOL allow_change )
{
struct gl_drawable *gl;
- HWND hwnd = WindowFromDC( hdc );
+ HWND hwnd = NtUserWindowFromDC( hdc );
int prev = 0;
- if (!hwnd || hwnd == GetDesktopWindow())
+ if (!hwnd || hwnd == NtUserGetDesktopWindow())
{
WARN( "not a proper window DC %p/%p\n", hdc, hwnd );
return FALSE;
@@ -255,7 +255,7 @@ static struct wgl_context *create_context( HDC hdc, struct wgl_context *share, c
struct gl_drawable *gl;
struct wgl_context *ctx;
- if (!(gl = get_gl_drawable( WindowFromDC( hdc ), hdc ))) return NULL;
+ if (!(gl = get_gl_drawable( NtUserWindowFromDC( hdc ), hdc ))) return NULL;
ctx = HeapAlloc( GetProcessHeap(), 0, sizeof(*ctx) );
@@ -348,10 +348,10 @@ static BOOL android_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct
return TRUE;
}
- draw_hwnd = WindowFromDC( draw_hdc );
+ draw_hwnd = NtUserWindowFromDC( draw_hdc );
if ((draw_gl = get_gl_drawable( draw_hwnd, draw_hdc )))
{
- read_gl = get_gl_drawable( WindowFromDC( read_hdc ), read_hdc );
+ read_gl = get_gl_drawable( NtUserWindowFromDC( read_hdc ), read_hdc );
draw_surface = draw_gl->surface ? draw_gl->surface : draw_gl->pbuffer;
read_surface = read_gl->surface ? read_gl->surface : read_gl->pbuffer;
TRACE( "%p/%p context %p surface %p/%p\n",
@@ -500,7 +500,7 @@ static int WINAPI android_wglGetPixelFormat( HDC hdc )
struct gl_drawable *gl;
int ret = 0;
- if ((gl = get_gl_drawable( WindowFromDC( hdc ), hdc )))
+ if ((gl = get_gl_drawable( NtUserWindowFromDC( hdc ), hdc )))
{
ret = gl->format;
/* offscreen formats can't be used with traditional WGL calls */
@@ -540,7 +540,7 @@ static BOOL WINAPI android_wglMakeCurrent( HDC hdc, struct wgl_context *ctx )
return TRUE;
}
- hwnd = WindowFromDC( hdc );
+ hwnd = NtUserWindowFromDC( hdc );
if ((gl = get_gl_drawable( hwnd, hdc )))
{
EGLSurface surface = gl->surface ? gl->surface : gl->pbuffer;
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index 4b9fe5cb3ce..6b019445805 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -99,19 +99,22 @@ static inline int get_dib_image_size( const BITMAPINFO *info )
* abs( info->bmiHeader.biHeight );
}
+static BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 )
+{
+ dst->left = max(src1->left, src2->left);
+ dst->top = max(src1->top, src2->top);
+ dst->right = min(src1->right, src2->right);
+ dst->bottom = min(src1->bottom, src2->bottom);
+ return !IsRectEmpty( dst );
+}
+
/**********************************************************************
* get_win_monitor_dpi
*/
static UINT get_win_monitor_dpi( HWND hwnd )
{
- DPI_AWARENESS_CONTEXT context;
- UINT ret;
-
- context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
- ret = GetDpiForSystem(); /* FIXME: get monitor dpi */
- SetThreadDpiAwarenessContext( context );
- return ret;
+ return NtUserGetSystemDpiForProcess( NULL ); /* FIXME: get monitor dpi */
}
@@ -126,7 +129,7 @@ static struct android_win_data *alloc_win_data( HWND hwnd )
{
data->hwnd = hwnd;
data->window = create_ioctl_window( hwnd, FALSE,
- (float)get_win_monitor_dpi( hwnd ) / GetDpiForWindow( hwnd ));
+ (float)get_win_monitor_dpi( hwnd ) / NtUserGetDpiForWindow( hwnd ));
EnterCriticalSection( &win_data_section );
win_data_context[context_idx(hwnd)] = data;
}
@@ -466,8 +469,8 @@ static int process_events( DWORD mask )
screen_width = event->data.desktop.width;
screen_height = event->data.desktop.height;
init_monitors( screen_width, screen_height );
- SetWindowPos( GetDesktopWindow(), 0, 0, 0, screen_width, screen_height,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
+ NtUserSetWindowPos( NtUserGetDesktopWindow(), 0, 0, 0, screen_width, screen_height,
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
SetThreadDpiAwarenessContext( context );
break;
@@ -728,7 +731,7 @@ static void android_surface_flush( struct window_surface *window_surface )
window_surface->funcs->lock( window_surface );
SetRect( &rect, 0, 0, surface->header.rect.right - surface->header.rect.left,
surface->header.rect.bottom - surface->header.rect.top );
- needs_flush = IntersectRect( &rect, &rect, &surface->bounds );
+ needs_flush = intersect_rect( &rect, &rect, &surface->bounds );
reset_bounds( &surface->bounds );
window_surface->funcs->unlock( window_surface );
if (!needs_flush) return;
@@ -753,7 +756,7 @@ static void android_surface_flush( struct window_surface *window_surface )
rect.top = rc.top;
rect.right = rc.right;
rect.bottom = rc.bottom;
- IntersectRect( &rect, &rect, &surface->header.rect );
+ intersect_rect( &rect, &rect, &surface->header.rect );
if (surface->region_data)
{
@@ -874,7 +877,7 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_
{
region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left,
win_data->window_rect.bottom - win_data->window_rect.top );
- if (GetWindowRgn( surface->hwnd, region ) == ERROR && !surface->region) goto done;
+ if (NtUserGetWindowRgnEx( surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done;
}
NtGdiOffsetRgn( region, offset_x, offset_y );
@@ -1222,7 +1225,7 @@ BOOL ANDROID_CreateWindow( HWND hwnd )
{
TRACE( "%p\n", hwnd );
- if (hwnd == GetDesktopWindow())
+ if (hwnd == NtUserGetDesktopWindow())
{
struct android_win_data *data;
@@ -1262,11 +1265,11 @@ static struct android_win_data *create_win_data( HWND hwnd, const RECT *window_r
struct android_win_data *data;
HWND parent;
- if (!(parent = GetAncestor( hwnd, GA_PARENT ))) return NULL; /* desktop or HWND_MESSAGE */
+ if (!(parent = NtUserGetAncestor( hwnd, GA_PARENT ))) return NULL; /* desktop or HWND_MESSAGE */
if (!(data = alloc_win_data( hwnd ))) return NULL;
- data->parent = (parent == GetDesktopWindow()) ? 0 : parent;
+ data->parent = (parent == NtUserGetDesktopWindow()) ? 0 : parent;
data->whole_rect = data->window_rect = *window_rect;
data->client_rect = *client_rect;
return data;
@@ -1275,7 +1278,7 @@ static struct android_win_data *create_win_data( HWND hwnd, const RECT *window_r
static inline BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect )
{
- if (!IntersectRect( surface_rect, visible_rect, &virtual_screen_rect )) return FALSE;
+ if (!intersect_rect( surface_rect, visible_rect, &virtual_screen_rect )) return FALSE;
OffsetRect( surface_rect, -visible_rect->left, -visible_rect->top );
surface_rect->left &= ~31;
surface_rect->top &= ~31;
@@ -1297,11 +1300,11 @@ BOOL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
DWORD flags;
COLORREF key;
BYTE alpha;
- BOOL layered = GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED;
+ BOOL layered = NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED;
TRACE( "win %p window %s client %s style %08x flags %08x\n",
hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
- GetWindowLongW( hwnd, GWL_STYLE ), swp_flags );
+ NtUserGetWindowLongW( hwnd, GWL_STYLE ), swp_flags );
if (!data && !(data = create_win_data( hwnd, window_rect, client_rect ))) return TRUE;
@@ -1325,9 +1328,10 @@ BOOL ANDROID_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags,
goto done;
}
}
- if (!(swp_flags & SWP_SHOWWINDOW) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) goto done;
+ if (!(swp_flags & SWP_SHOWWINDOW) && !(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
+ goto done;
- if (!layered || !GetLayeredWindowAttributes( hwnd, &key, &alpha, &flags )) flags = 0;
+ if (!layered || !NtUserGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags )) flags = 0;
if (!(flags & LWA_ALPHA)) alpha = 255;
if (!(flags & LWA_COLORKEY)) key = CLR_INVALID;
@@ -1349,7 +1353,7 @@ void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
struct window_surface *surface )
{
struct android_win_data *data;
- DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE );
+ DWORD new_style = NtUserGetWindowLongW( hwnd, GWL_STYLE );
HWND owner = 0;
if (!(data = get_win_data( hwnd ))) return;
@@ -1364,10 +1368,10 @@ void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
if (data->surface) window_surface_release( data->surface );
data->surface = surface;
}
- if (!data->parent) owner = GetWindow( hwnd, GW_OWNER );
+ if (!data->parent) owner = NtUserGetWindowRelative( hwnd, GW_OWNER );
release_win_data( data );
- if (!(swp_flags & SWP_NOZORDER)) insert_after = GetWindow( hwnd, GW_HWNDPREV );
+ if (!(swp_flags & SWP_NOZORDER)) insert_after = NtUserGetWindowRelative( hwnd, GW_HWNDPREV );
TRACE( "win %p window %s client %s style %08x owner %p after %p flags %08x\n", hwnd,
wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
@@ -1383,7 +1387,7 @@ void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
*/
UINT ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
{
- if (!IsIconic( hwnd )) return swp;
+ if (!(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE)) return swp;
/* always hide icons off-screen */
if (rect->left != -32000 || rect->top != -32000)
{
@@ -1406,8 +1410,8 @@ void ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent )
TRACE( "win %p parent %p -> %p\n", hwnd, old_parent, parent );
- data->parent = (parent == GetDesktopWindow()) ? 0 : parent;
- ioctl_set_window_parent( hwnd, parent, (float)get_win_monitor_dpi( hwnd ) / GetDpiForWindow( hwnd ));
+ data->parent = (parent == NtUserGetDesktopWindow()) ? 0 : parent;
+ ioctl_set_window_parent( hwnd, parent, (float)get_win_monitor_dpi( hwnd ) / NtUserGetDpiForWindow( hwnd ));
release_win_data( data );
}
@@ -1422,6 +1426,28 @@ void ANDROID_SetCapture( HWND hwnd, UINT flags )
}
+static BOOL get_icon_info( HICON handle, ICONINFOEXW *ret )
+{
+ UNICODE_STRING module, res_name;
+ ICONINFO info;
+
+ module.Buffer = ret->szModName;
+ module.MaximumLength = sizeof(ret->szModName) - sizeof(WCHAR);
+ res_name.Buffer = ret->szResName;
+ res_name.MaximumLength = sizeof(ret->szResName) - sizeof(WCHAR);
+ if (!NtUserGetIconInfo( handle, &info, &module, &res_name, NULL, 0 )) return FALSE;
+ ret->fIcon = info.fIcon;
+ ret->xHotspot = info.xHotspot;
+ ret->yHotspot = info.yHotspot;
+ ret->hbmColor = info.hbmColor;
+ ret->hbmMask = info.hbmMask;
+ ret->wResID = res_name.Length ? 0 : LOWORD(res_name.Buffer);
+ ret->szModName[module.Length] = 0;
+ ret->szResName[res_name.Length] = 0;
+ return TRUE;
+}
+
+
/***********************************************************************
* ANDROID_SetCursor
*/
@@ -1441,8 +1467,7 @@ void ANDROID_SetCursor( HCURSOR handle )
ICONINFOEXW info;
int id;
- info.cbSize = sizeof(info);
- if (!GetIconInfoExW( handle, &info )) return;
+ if (!get_icon_info( handle, &info )) return;
if (!(id = get_cursor_system_id( &info )))
{
@@ -1475,7 +1500,7 @@ void ANDROID_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style )
struct android_win_data *data;
DWORD changed = style->styleNew ^ style->styleOld;
- if (hwnd == GetDesktopWindow()) return;
+ if (hwnd == NtUserGetDesktopWindow()) return;
if (!(data = get_win_data( hwnd ))) return;
if (offset == GWL_EXSTYLE && (changed & WS_EX_LAYERED)) /* changing WS_EX_LAYERED resets attributes */
@@ -1585,7 +1610,7 @@ BOOL ANDROID_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info
if (info->prcDirty)
{
- IntersectRect( &rect, &rect, info->prcDirty );
+ intersect_rect( &rect, &rect, info->prcDirty );
memcpy( src_bits, dst_bits, bmi->bmiHeader.biSizeImage );
NtGdiPatBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS );
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022
[PATCH 6/7] wineandroid: Implement desktop window proc using driver interface.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/desktop.c | 1 +
dlls/wineandroid.drv/android.h | 1 +
dlls/wineandroid.drv/init.c | 1 +
dlls/wineandroid.drv/window.c | 9 ++-------
4 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/user32/desktop.c b/dlls/user32/desktop.c
index f2905b0efac..ca000972bc4 100644
--- a/dlls/user32/desktop.c
+++ b/dlls/user32/desktop.c
@@ -96,6 +96,7 @@ LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lP
{
case WM_NCCREATE:
case WM_NCCALCSIZE:
+ case WM_PARENTNOTIFY:
return NtUserMessageCall( hwnd, message, wParam, lParam, 0, NtUserDesktopWindowProc, FALSE );
default:
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h
index 414374c6c01..91f6dc83791 100644
--- a/dlls/wineandroid.drv/android.h
+++ b/dlls/wineandroid.drv/android.h
@@ -88,6 +88,7 @@ extern void ANDROID_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
extern NTSTATUS ANDROID_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
const LARGE_INTEGER *timeout,
DWORD mask, DWORD flags ) DECLSPEC_HIDDEN;
+extern LRESULT ANDROID_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) DECLSPEC_HIDDEN;
extern void ANDROID_SetCursor( HCURSOR handle ) DECLSPEC_HIDDEN;
extern void ANDROID_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha,
DWORD flags ) DECLSPEC_HIDDEN;
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c
index dec53657ccb..694ec1bae9c 100644
--- a/dlls/wineandroid.drv/init.c
+++ b/dlls/wineandroid.drv/init.c
@@ -343,6 +343,7 @@ static const struct user_driver_funcs android_drv_funcs =
.pEnumDisplaySettingsEx = ANDROID_EnumDisplaySettingsEx,
.pUpdateDisplayDevices = ANDROID_UpdateDisplayDevices,
.pCreateWindow = ANDROID_CreateWindow,
+ .pDesktopWindowProc = ANDROID_DesktopWindowProc,
.pDestroyWindow = ANDROID_DestroyWindow,
.pMsgWaitForMultipleObjectsEx = ANDROID_MsgWaitForMultipleObjectsEx,
.pSetCapture = ANDROID_SetCapture,
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index c738bc0527d..4b9fe5cb3ce 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -1186,9 +1186,7 @@ static int get_cursor_system_id( const ICONINFOEXW *info )
}
-static WNDPROC desktop_orig_wndproc;
-
-static LRESULT CALLBACK desktop_wndproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
+LRESULT ANDROID_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch (msg)
{
@@ -1196,7 +1194,7 @@ static LRESULT CALLBACK desktop_wndproc_wrapper( HWND hwnd, UINT msg, WPARAM wp,
if (LOWORD(wp) == WM_DESTROY) destroy_ioctl_window( (HWND)lp, FALSE );
break;
}
- return desktop_orig_wndproc( hwnd, msg, wp, lp );
+ return NtUserMessageCall( hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE );
}
@@ -1655,9 +1653,6 @@ LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
*/
BOOL CDECL ANDROID_create_desktop( UINT width, UINT height )
{
- desktop_orig_wndproc = (WNDPROC)SetWindowLongPtrW( GetDesktopWindow(), GWLP_WNDPROC,
- (LONG_PTR)desktop_wndproc_wrapper );
-
/* wait until we receive the surface changed event */
while (!screen_width)
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022
[PATCH 5/7] wineandroid: Directly use win32u for GDI functions.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/wineandroid.drv/Makefile.in | 2 +-
dlls/wineandroid.drv/android.h | 3 +-
dlls/wineandroid.drv/window.c | 65 +++++++++++++++++---------------
3 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/dlls/wineandroid.drv/Makefile.in b/dlls/wineandroid.drv/Makefile.in
index 59df461697a..3f9a16bea4f 100644
--- a/dlls/wineandroid.drv/Makefile.in
+++ b/dlls/wineandroid.drv/Makefile.in
@@ -1,6 +1,6 @@
EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = wineandroid.drv
-IMPORTS = user32 gdi32 ntoskrnl win32u
+IMPORTS = user32 ntoskrnl win32u
EXTRADLLFLAGS = -mcygwin
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h
index a7581d1b67f..414374c6c01 100644
--- a/dlls/wineandroid.drv/android.h
+++ b/dlls/wineandroid.drv/android.h
@@ -31,8 +31,7 @@
#include "windef.h"
#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
+#include "ntgdi.h"
#include "wine/gdi_driver.h"
#include "android_native.h"
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index 5143990836f..c738bc0527d 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -702,13 +702,13 @@ static void android_surface_set_region( struct window_surface *window_surface, H
window_surface->funcs->lock( window_surface );
if (!region)
{
- if (surface->region) DeleteObject( surface->region );
+ if (surface->region) NtGdiDeleteObjectApp( surface->region );
surface->region = 0;
}
else
{
- if (!surface->region) surface->region = CreateRectRgn( 0, 0, 0, 0 );
- CombineRgn( surface->region, region, 0, RGN_COPY );
+ if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ NtGdiCombineRgn( surface->region, region, 0, RGN_COPY );
}
window_surface->funcs->unlock( window_surface );
set_surface_region( &surface->header, (HRGN)1 );
@@ -809,7 +809,7 @@ static void android_surface_destroy( struct window_surface *window_surface )
surface->crit.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &surface->crit );
HeapFree( GetProcessHeap(), 0, surface->region_data );
- if (surface->region) DeleteObject( surface->region );
+ if (surface->region) NtGdiDeleteObjectApp( surface->region );
release_ioctl_window( surface->window );
HeapFree( GetProcessHeap(), 0, surface->bits );
HeapFree( GetProcessHeap(), 0, surface );
@@ -872,18 +872,18 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_
if (win_region == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */
{
- region = CreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left,
- win_data->window_rect.bottom - win_data->window_rect.top );
+ region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left,
+ win_data->window_rect.bottom - win_data->window_rect.top );
if (GetWindowRgn( surface->hwnd, region ) == ERROR && !surface->region) goto done;
}
- OffsetRgn( region, offset_x, offset_y );
- if (surface->region) CombineRgn( region, region, surface->region, RGN_AND );
+ NtGdiOffsetRgn( region, offset_x, offset_y );
+ if (surface->region) NtGdiCombineRgn( region, region, surface->region, RGN_AND );
- if (!(size = GetRegionData( region, 0, NULL ))) goto done;
+ if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done;
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) goto done;
- if (!GetRegionData( region, size, data ))
+ if (!NtGdiGetRegionData( region, size, data ))
{
HeapFree( GetProcessHeap(), 0, data );
data = NULL;
@@ -895,7 +895,7 @@ done:
surface->region_data = data;
*window_surface->funcs->get_bounds( window_surface ) = surface->header.rect;
window_surface->funcs->unlock( window_surface );
- if (region != win_region) DeleteObject( region );
+ if (region != win_region) NtGdiDeleteObjectApp( region );
}
/***********************************************************************
@@ -974,11 +974,11 @@ static unsigned int *get_mono_icon_argb( HDC hdc, HBITMAP bmp, unsigned int *wid
char *mask;
unsigned int i, j, stride, mask_size, bits_size, *bits = NULL, *ptr;
- if (!GetObjectW( bmp, sizeof(bm), &bm )) return NULL;
+ if (!NtGdiExtGetObjectW( bmp, sizeof(bm), &bm )) return NULL;
stride = ((bm.bmWidth + 15) >> 3) & ~1;
mask_size = stride * bm.bmHeight;
if (!(mask = HeapAlloc( GetProcessHeap(), 0, mask_size ))) return NULL;
- if (!GetBitmapBits( bmp, mask_size, mask )) goto done;
+ if (!NtGdiGetBitmapBits( bmp, mask_size, mask )) goto done;
bm.bmHeight /= 2;
bits_size = bm.bmWidth * bm.bmHeight * sizeof(*bits);
@@ -1025,7 +1025,7 @@ static unsigned int *get_bitmap_argb( HDC hdc, HBITMAP color, HBITMAP mask, unsi
if (!color) return get_mono_icon_argb( hdc, mask, width, height );
- if (!GetObjectW( color, sizeof(bm), &bm )) return NULL;
+ if (!NtGdiExtGetObjectW( color, sizeof(bm), &bm )) return NULL;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info->bmiHeader.biWidth = bm.bmWidth;
info->bmiHeader.biHeight = -bm.bmHeight;
@@ -1039,7 +1039,8 @@ static unsigned int *get_bitmap_argb( HDC hdc, HBITMAP color, HBITMAP mask, unsi
info->bmiHeader.biClrImportant = 0;
if (!(bits = HeapAlloc( GetProcessHeap(), 0, bm.bmWidth * bm.bmHeight * sizeof(unsigned int) )))
goto failed;
- if (!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS )) goto failed;
+ if (!NtGdiGetDIBitsInternal( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS, 0, 0 ))
+ goto failed;
*width = bm.bmWidth;
*height = bm.bmHeight;
@@ -1054,7 +1055,8 @@ static unsigned int *get_bitmap_argb( HDC hdc, HBITMAP color, HBITMAP mask, unsi
info->bmiHeader.biBitCount = 1;
info->bmiHeader.biSizeImage = width_bytes * bm.bmHeight;
if (!(mask_bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto failed;
- if (!GetDIBits( hdc, mask, 0, bm.bmHeight, mask_bits, info, DIB_RGB_COLORS )) goto failed;
+ if (!NtGdiGetDIBitsInternal( hdc, mask, 0, bm.bmHeight, mask_bits, info, DIB_RGB_COLORS, 0, 0 ))
+ goto failed;
ptr = bits;
for (i = 0; i < bm.bmHeight; i++)
for (j = 0; j < bm.bmWidth; j++, ptr++)
@@ -1446,9 +1448,9 @@ void ANDROID_SetCursor( HCURSOR handle )
if (!(id = get_cursor_system_id( &info )))
{
- HDC hdc = CreateCompatibleDC( 0 );
+ HDC hdc = NtGdiCreateCompatibleDC( 0 );
bits = get_bitmap_argb( hdc, info.hbmColor, info.hbmMask, &width, &height );
- DeleteDC( hdc );
+ NtGdiDeleteObjectApp( hdc );
/* make sure hotspot is valid */
if (info.xHotspot >= width || info.yHotspot >= height)
@@ -1459,8 +1461,8 @@ void ANDROID_SetCursor( HCURSOR handle )
}
ioctl_set_cursor( id, width, height, info.xHotspot, info.yHotspot, bits );
HeapFree( GetProcessHeap(), 0, bits );
- DeleteObject( info.hbmColor );
- DeleteObject( info.hbmMask );
+ NtGdiDeleteObjectApp( info.hbmColor );
+ NtGdiDeleteObjectApp( info.hbmMask );
}
else ioctl_set_cursor( 0, 0, 0, 0, 0, NULL );
}
@@ -1575,10 +1577,11 @@ BOOL ANDROID_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info
dst_bits = surface->funcs->get_info( surface, bmi );
- if (!(dib = CreateDIBSection( info->hdcDst, bmi, DIB_RGB_COLORS, &src_bits, NULL, 0 ))) goto done;
- if (!(hdc = CreateCompatibleDC( 0 ))) goto done;
+ if (!(dib = NtGdiCreateDIBSection( info->hdcDst, NULL, 0, bmi, DIB_RGB_COLORS, 0, 0, 0, &src_bits )))
+ goto done;
+ if (!(hdc = NtGdiCreateCompatibleDC( 0 ))) goto done;
- SelectObject( hdc, dib );
+ NtGdiSelectBitmap( hdc, dib );
surface->funcs->lock( surface );
@@ -1586,16 +1589,16 @@ BOOL ANDROID_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info
{
IntersectRect( &rect, &rect, info->prcDirty );
memcpy( src_bits, dst_bits, bmi->bmiHeader.biSizeImage );
- PatBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS );
+ NtGdiPatBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, BLACKNESS );
}
src_rect = rect;
if (info->pptSrc) OffsetRect( &src_rect, info->pptSrc->x, info->pptSrc->y );
- DPtoLP( info->hdcSrc, (POINT *)&src_rect, 2 );
+ NtGdiTransformPoints( info->hdcSrc, (POINT *)&src_rect, (POINT *)&src_rect, 2, NtGdiDPtoLP );
- ret = GdiAlphaBlend( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
- info->hdcSrc, src_rect.left, src_rect.top,
- src_rect.right - src_rect.left, src_rect.bottom - src_rect.top,
- (info->dwFlags & ULW_ALPHA) ? *info->pblend : blend );
+ ret = NtGdiAlphaBlend( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
+ info->hdcSrc, src_rect.left, src_rect.top,
+ src_rect.right - src_rect.left, src_rect.bottom - src_rect.top,
+ (info->dwFlags & ULW_ALPHA) ? *info->pblend : blend, 0 );
if (ret)
{
memcpy( dst_bits, src_bits, bmi->bmiHeader.biSizeImage );
@@ -1607,8 +1610,8 @@ BOOL ANDROID_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info
done:
window_surface_release( surface );
- if (hdc) DeleteDC( hdc );
- if (dib) DeleteObject( dib );
+ if (hdc) NtGdiDeleteObjectApp( hdc );
+ if (dib) NtGdiDeleteObjectApp( dib );
return ret;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022
[PATCH 4/7] wineandroid: Directly use ntdll for registry access.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/wineandroid.drv/Makefile.in | 2 +-
dlls/wineandroid.drv/init.c | 69 ++++++++++++++++++++++++++++++--
2 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/dlls/wineandroid.drv/Makefile.in b/dlls/wineandroid.drv/Makefile.in
index e576b1d944b..59df461697a 100644
--- a/dlls/wineandroid.drv/Makefile.in
+++ b/dlls/wineandroid.drv/Makefile.in
@@ -1,6 +1,6 @@
EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = wineandroid.drv
-IMPORTS = user32 gdi32 advapi32 ntoskrnl win32u
+IMPORTS = user32 gdi32 ntoskrnl win32u
EXTRADLLFLAGS = -mcygwin
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c
index 3daa41f28d1..dec53657ccb 100644
--- a/dlls/wineandroid.drv/init.c
+++ b/dlls/wineandroid.drv/init.c
@@ -27,6 +27,8 @@
#include <dlfcn.h>
#include <link.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
@@ -84,19 +86,78 @@ void init_monitors( int width, int height )
}
+/* wrapper for NtCreateKey that creates the key recursively if necessary */
+static HKEY reg_create_key( const WCHAR *name, ULONG name_len )
+{
+ UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+ HANDLE ret;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, 0, NULL );
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ static const WCHAR registry_rootW[] = { '\\','R','e','g','i','s','t','r','y','\\' };
+ DWORD pos = 0, i = 0, len = name_len / sizeof(WCHAR);
+
+ /* don't try to create registry root */
+ if (len > ARRAY_SIZE(registry_rootW) &&
+ !memcmp( name, registry_rootW, sizeof(registry_rootW) ))
+ i += ARRAY_SIZE(registry_rootW);
+
+ while (i < len && name[i] != '\\') i++;
+ if (i == len) return 0;
+ for (;;)
+ {
+ nameW.Buffer = (WCHAR *)name + pos;
+ nameW.Length = (i - pos) * sizeof(WCHAR);
+ status = NtCreateKey( &ret, MAXIMUM_ALLOWED, &attr, 0, NULL, 0, NULL );
+
+ if (attr.RootDirectory) NtClose( attr.RootDirectory );
+ if (status) return 0;
+ if (i == len) break;
+ attr.RootDirectory = ret;
+ while (i < len && name[i] == '\\') i++;
+ pos = i;
+ while (i < len && name[i] != '\\') i++;
+ }
+ }
+ return ret;
+}
+
+
/******************************************************************************
* set_screen_dpi
*/
void set_screen_dpi( DWORD dpi )
{
- static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s',0};
static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s',0};
+ static const WCHAR dpi_key_name[] =
+ {
+ '\\','R','e','g','i','s','t','r','y',
+ '\\','M','a','c','h','i','n','e',
+ '\\','S','y','s','t','e','m',
+ '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
+ '\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s',
+ '\\','C','u','r','r','e','n','t',
+ '\\','S','o','f','t','w','a','r','e',
+ '\\','F','o','n','t','s'
+ };
HKEY hkey;
- if (!RegCreateKeyW( HKEY_CURRENT_CONFIG, dpi_key_name, &hkey ))
+ if ((hkey = reg_create_key( dpi_key_name, sizeof(dpi_key_name ))))
{
- RegSetValueExW( hkey, dpi_value_name, 0, REG_DWORD, (void *)&dpi, sizeof(DWORD) );
- RegCloseKey( hkey );
+ UNICODE_STRING name;
+ RtlInitUnicodeString( &name, dpi_value_name );
+ NtSetValueKey( hkey, &name, 0, REG_DWORD, &dpi, sizeof(dpi) );
+ NtClose( hkey );
}
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022
[PATCH 3/7] wineandroid: Remove audio driver.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/wineandroid.drv/Makefile.in | 3 +-
dlls/wineandroid.drv/mmdevdrv.c | 3097 ---------------------
dlls/wineandroid.drv/wineandroid.drv.spec | 6 -
3 files changed, 1 insertion(+), 3105 deletions(-)
delete mode 100644 dlls/wineandroid.drv/mmdevdrv.c
diff --git a/dlls/wineandroid.drv/Makefile.in b/dlls/wineandroid.drv/Makefile.in
index 0e3a632b8fb..e576b1d944b 100644
--- a/dlls/wineandroid.drv/Makefile.in
+++ b/dlls/wineandroid.drv/Makefile.in
@@ -1,6 +1,6 @@
EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = wineandroid.drv
-IMPORTS = uuid ole32 user32 gdi32 advapi32 ntoskrnl win32u
+IMPORTS = user32 gdi32 advapi32 ntoskrnl win32u
EXTRADLLFLAGS = -mcygwin
@@ -8,7 +8,6 @@ C_SRCS = \
device.c \
init.c \
keyboard.c \
- mmdevdrv.c \
opengl.c \
window.c
diff --git a/dlls/wineandroid.drv/mmdevdrv.c b/dlls/wineandroid.drv/mmdevdrv.c
deleted file mode 100644
index d6ba1072b9c..00000000000
--- a/dlls/wineandroid.drv/mmdevdrv.c
+++ /dev/null
@@ -1,3097 +0,0 @@
-/*
- * Copyright 2015 Andrew Eikum for CodeWeavers
- *
- * 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
- */
-
-#define NONAMELESSUNION
-#define COBJMACROS
-#include "config.h"
-
-#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 <unistd.h>
-#include <math.h>
-#include <dlfcn.h>
-
-#include <SLES/OpenSLES.h>
-#include <SLES/OpenSLES_Android.h>
-
-#include "android.h"
-
-#include "windef.h"
-#include "winbase.h"
-#include "winnls.h"
-#include "winreg.h"
-#include "wine/debug.h"
-#include "wine/list.h"
-
-#include "ole2.h"
-#include "mmdeviceapi.h"
-#include "devpkey.h"
-#include "dshow.h"
-#include "dsound.h"
-
-#include "initguid.h"
-#include "endpointvolume.h"
-#include "audiopolicy.h"
-#include "audioclient.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(androidaudio);
-
-#define DECL_FUNCPTR(f) static typeof(f) * p##f
-DECL_FUNCPTR( slCreateEngine );
-DECL_FUNCPTR( SL_IID_ANDROIDSIMPLEBUFFERQUEUE );
-DECL_FUNCPTR( SL_IID_ENGINE );
-DECL_FUNCPTR( SL_IID_PLAY );
-DECL_FUNCPTR( SL_IID_PLAYBACKRATE );
-DECL_FUNCPTR( SL_IID_RECORD );
-
-#define SLCALL_N(obj, func) (*obj)->func(obj)
-#define SLCALL(obj, func, ...) (*obj)->func(obj, __VA_ARGS__)
-
-#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
-
-static const REFERENCE_TIME DefaultPeriod = 100000;
-static const REFERENCE_TIME MinimumPeriod = 50000;
-
-struct ACImpl;
-typedef struct ACImpl ACImpl;
-
-typedef struct _AudioSession {
- GUID guid;
- struct list clients;
-
- IMMDevice *device;
-
- float master_vol;
- UINT32 channel_count;
- float *channel_vols;
- BOOL mute;
-
- CRITICAL_SECTION lock;
-
- struct list entry;
-} AudioSession;
-
-typedef struct _AudioSessionWrapper {
- IAudioSessionControl2 IAudioSessionControl2_iface;
- IChannelAudioVolume IChannelAudioVolume_iface;
- ISimpleAudioVolume ISimpleAudioVolume_iface;
-
- LONG ref;
-
- ACImpl *client;
- AudioSession *session;
-} AudioSessionWrapper;
-
-struct ACImpl {
- IAudioClient3 IAudioClient3_iface;
- IAudioRenderClient IAudioRenderClient_iface;
- IAudioCaptureClient IAudioCaptureClient_iface;
- IAudioClock IAudioClock_iface;
- IAudioClock2 IAudioClock2_iface;
- IAudioStreamVolume IAudioStreamVolume_iface;
-
- LONG ref;
-
- IMMDevice *parent;
- IUnknown *pUnkFTMarshal;
-
- WAVEFORMATEX *fmt;
-
- EDataFlow dataflow;
- DWORD flags;
- AUDCLNT_SHAREMODE share;
- HANDLE event;
- float *vols;
-
- SLObjectItf player;
- SLObjectItf recorder;
- SLAndroidSimpleBufferQueueItf bufq;
- SLPlayItf playitf;
- SLRecordItf recorditf;
-
- BOOL initted, playing;
- UINT64 written_frames, last_pos_frames;
- UINT32 period_us, period_frames, bufsize_frames, held_frames, tmp_buffer_frames, wrap_buffer_frames, in_sl_frames;
- UINT32 oss_bufsize_bytes, lcl_offs_frames; /* offs into local_buffer where valid data starts */
-
- BYTE *local_buffer, *tmp_buffer, *wrap_buffer;
- LONG32 getbuf_last; /* <0 when using tmp_buffer */
- HANDLE timer;
-
- CRITICAL_SECTION lock;
-
- AudioSession *session;
- AudioSessionWrapper *session_wrapper;
-
- struct list entry;
-};
-
-typedef struct _SessionMgr {
- IAudioSessionManager2 IAudioSessionManager2_iface;
-
- LONG ref;
-
- IMMDevice *device;
-} SessionMgr;
-
-static struct list g_devices = LIST_INIT(g_devices);
-
-static HANDLE g_timer_q;
-
-static CRITICAL_SECTION g_sessions_lock;
-static CRITICAL_SECTION_DEBUG g_sessions_lock_debug =
-{
- 0, 0, &g_sessions_lock,
- { &g_sessions_lock_debug.ProcessLocksList, &g_sessions_lock_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": g_sessions_lock") }
-};
-static CRITICAL_SECTION g_sessions_lock = { &g_sessions_lock_debug, -1, 0, 0, 0, 0 };
-static struct list g_sessions = LIST_INIT(g_sessions);
-
-static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client);
-
-static const IAudioClient3Vtbl AudioClient3_Vtbl;
-static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
-static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
-static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl;
-static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl;
-static const IAudioClockVtbl AudioClock_Vtbl;
-static const IAudioClock2Vtbl AudioClock2_Vtbl;
-static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl;
-static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl;
-static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl;
-
-static inline ACImpl *impl_from_IAudioClient3(IAudioClient3 *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioClient3_iface);
-}
-
-static inline ACImpl *impl_from_IAudioRenderClient(IAudioRenderClient *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioRenderClient_iface);
-}
-
-static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface);
-}
-
-static inline AudioSessionWrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
-{
- return CONTAINING_RECORD(iface, AudioSessionWrapper, IAudioSessionControl2_iface);
-}
-
-static inline AudioSessionWrapper *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
-{
- return CONTAINING_RECORD(iface, AudioSessionWrapper, ISimpleAudioVolume_iface);
-}
-
-static inline AudioSessionWrapper *impl_from_IChannelAudioVolume(IChannelAudioVolume *iface)
-{
- return CONTAINING_RECORD(iface, AudioSessionWrapper, IChannelAudioVolume_iface);
-}
-
-static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface);
-}
-
-static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface);
-}
-
-static inline ACImpl *impl_from_IAudioStreamVolume(IAudioStreamVolume *iface)
-{
- return CONTAINING_RECORD(iface, ACImpl, IAudioStreamVolume_iface);
-}
-
-static inline SessionMgr *impl_from_IAudioSessionManager2(IAudioSessionManager2 *iface)
-{
- return CONTAINING_RECORD(iface, SessionMgr, IAudioSessionManager2_iface);
-}
-
-#define LOAD_FUNCPTR(lib, func) do { \
- if ((p##func = dlsym( lib, #func )) == NULL) \
- { ERR( "can't find symbol %s\n", #func); return FALSE; } \
- } while(0)
-
-static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-
-static BOOL WINAPI load_opensles( INIT_ONCE *once, void *param, void **context )
-{
- void *libopensles;
-
- if (!(libopensles = dlopen( "libOpenSLES.so", RTLD_GLOBAL )))
- {
- ERR( "failed to load libOpenSLES.so: %s\n", dlerror() );
- return FALSE;
- }
- LOAD_FUNCPTR( libopensles, slCreateEngine );
- LOAD_FUNCPTR( libopensles, SL_IID_ANDROIDSIMPLEBUFFERQUEUE );
- LOAD_FUNCPTR( libopensles, SL_IID_ENGINE );
- LOAD_FUNCPTR( libopensles, SL_IID_PLAY );
- LOAD_FUNCPTR( libopensles, SL_IID_PLAYBACKRATE );
- LOAD_FUNCPTR( libopensles, SL_IID_RECORD );
-
- if (!(g_timer_q = CreateTimerQueue())) return FALSE;
-
- return TRUE;
-}
-
-/* From <dlls/mmdevapi/mmdevapi.h> */
-enum DriverPriority {
- Priority_Unavailable = 0,
- Priority_Low,
- Priority_Neutral,
- Priority_Preferred
-};
-
-int WINAPI AUDDRV_GetPriority(void)
-{
- if (!InitOnceExecuteOnce( &init_once, load_opensles, NULL, NULL ))
- return Priority_Unavailable;
-
- return Priority_Preferred;
-}
-
-static SLObjectItf sl;
-static SLEngineItf engine;
-static SLObjectItf outputmix;
-
-HRESULT AUDDRV_Init(void)
-{
- static const SLEngineOption options[] = { {SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE} };
- SLresult sr;
-
- sr = pslCreateEngine(&sl, 1, options, 0, NULL, NULL);
- if(sr != SL_RESULT_SUCCESS){
- WARN("slCreateEngine failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(sl, Realize, SL_BOOLEAN_FALSE);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(sl, Destroy);
- WARN("Engine Realize failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(sl, GetInterface, *pSL_IID_ENGINE, (void*)&engine);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(sl, Destroy);
- WARN("GetInterface failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(engine, CreateOutputMix, &outputmix, 0, NULL, NULL);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(sl, Destroy);
- WARN("CreateOutputMix failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(outputmix, Realize, SL_BOOLEAN_FALSE);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(outputmix, Destroy);
- SLCALL_N(sl, Destroy);
- WARN("outputmix Realize failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- return S_OK;
-}
-
-static const GUID outGuid = {0x0a047ace, 0x22b1, 0x4342, {0x98, 0xbb, 0xf8, 0x56, 0x32, 0x26, 0x61, 0x00}};
-static const GUID inGuid = {0x0a047ace, 0x22b1, 0x4342, {0x98, 0xbb, 0xf8, 0x56, 0x32, 0x26, 0x61, 0x01}};
-
-HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, GUID **guids,
- UINT *num, UINT *def_index)
-{
- static const WCHAR outName[] = {'A','n','d','r','o','i','d',' ','A','u','d','i','o',' ','O','u','t',0};
- static const WCHAR inName[] = {'A','n','d','r','o','i','d',' ','A','u','d','i','o',' ','I','n',0};
-
- TRACE("%u %p %p %p %p\n", flow, ids, guids, num, def_index);
-
- *def_index = 0;
- *num = 1;
- *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *));
- *guids = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID));
- if(flow == eRender){
- (*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(outName));
- memcpy((*ids)[0], outName, sizeof(outName));
- memcpy(&(*guids)[0], &outGuid, sizeof(outGuid));
- }else{
- (*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(inName));
- memcpy((*ids)[0], inName, sizeof(inName));
- memcpy(&(*guids)[0], &inGuid, sizeof(inGuid));
- }
-
- return S_OK;
-}
-
-HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev,
- IAudioClient **out)
-{
- ACImpl *This;
- HRESULT hr;
- EDataFlow flow;
-
- TRACE("%s %p %p\n", debugstr_guid(guid), dev, out);
-
- if(!sl)
- AUDDRV_Init();
-
- if(IsEqualGUID(guid, &outGuid))
- flow = eRender;
- else if(IsEqualGUID(guid, &inGuid))
- flow = eCapture;
- else
- return AUDCLNT_E_DEVICE_INVALIDATED;
-
- This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
- if(!This)
- return E_OUTOFMEMORY;
-
- hr = CoCreateFreeThreadedMarshaler((IUnknown *)&This->IAudioClient3_iface, &This->pUnkFTMarshal);
- if (FAILED(hr)) {
- HeapFree(GetProcessHeap(), 0, This);
- return hr;
- }
-
- This->dataflow = flow;
-
- This->IAudioClient3_iface.lpVtbl = &AudioClient3_Vtbl;
- This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
- This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl;
- This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl;
- This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl;
- This->IAudioStreamVolume_iface.lpVtbl = &AudioStreamVolume_Vtbl;
-
- InitializeCriticalSection(&This->lock);
- This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ACImpl.lock");
-
- This->parent = dev;
- IMMDevice_AddRef(This->parent);
-
- *out = (IAudioClient *)&This->IAudioClient3_iface;
- IAudioClient3_AddRef(&This->IAudioClient3_iface);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient3 *iface,
- REFIID riid, void **ppv)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioClient) ||
- IsEqualIID(riid, &IID_IAudioClient2) ||
- IsEqualIID(riid, &IID_IAudioClient3))
- *ppv = iface;
- else if(IsEqualIID(riid, &IID_IMarshal))
- return IUnknown_QueryInterface(This->pUnkFTMarshal, riid, ppv);
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioClient_AddRef(IAudioClient3 *iface)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- ULONG ref;
- ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- return ref;
-}
-
-static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- ULONG ref;
-
- ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- if(!ref){
- if(This->timer){
- HANDLE event;
- DWORD wait;
- event = CreateEventW(NULL, TRUE, FALSE, NULL);
- wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event);
- wait = wait && GetLastError() == ERROR_IO_PENDING;
- if(event && wait)
- WaitForSingleObject(event, INFINITE);
- CloseHandle(event);
- }
-
- IAudioClient3_Stop(iface);
-
- IMMDevice_Release(This->parent);
- IUnknown_Release(This->pUnkFTMarshal);
- This->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->lock);
-
- if(This->recorder)
- SLCALL_N(This->recorder, Destroy);
- if(This->player)
- SLCALL_N(This->player, Destroy);
-
- if(This->initted){
- EnterCriticalSection(&g_sessions_lock);
- list_remove(&This->entry);
- LeaveCriticalSection(&g_sessions_lock);
- }
- HeapFree(GetProcessHeap(), 0, This->vols);
- HeapFree(GetProcessHeap(), 0, This->local_buffer);
- HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
- HeapFree(GetProcessHeap(), 0, This->wrap_buffer);
- CoTaskMemFree(This->fmt);
- HeapFree(GetProcessHeap(), 0, This);
- }
- return ref;
-}
-
-static void dump_fmt(const WAVEFORMATEX *fmt)
-{
- TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
- switch(fmt->wFormatTag){
- case WAVE_FORMAT_PCM:
- TRACE("WAVE_FORMAT_PCM");
- break;
- case WAVE_FORMAT_IEEE_FLOAT:
- TRACE("WAVE_FORMAT_IEEE_FLOAT");
- break;
- case WAVE_FORMAT_EXTENSIBLE:
- TRACE("WAVE_FORMAT_EXTENSIBLE");
- break;
- default:
- TRACE("Unknown");
- break;
- }
- TRACE(")\n");
-
- TRACE("nChannels: %u\n", fmt->nChannels);
- TRACE("nSamplesPerSec: %u\n", fmt->nSamplesPerSec);
- TRACE("nAvgBytesPerSec: %u\n", fmt->nAvgBytesPerSec);
- TRACE("nBlockAlign: %u\n", fmt->nBlockAlign);
- TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample);
- TRACE("cbSize: %u\n", fmt->cbSize);
-
- if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
- WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt;
- TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask);
- TRACE("Samples: %04x\n", fmtex->Samples.wReserved);
- TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat));
- }
-}
-
-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 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 void session_init_vols(AudioSession *session, UINT channels)
-{
- if(session->channel_count < channels){
- UINT i;
-
- if(session->channel_vols)
- session->channel_vols = HeapReAlloc(GetProcessHeap(), 0,
- session->channel_vols, sizeof(float) * channels);
- else
- session->channel_vols = HeapAlloc(GetProcessHeap(), 0,
- sizeof(float) * channels);
- if(!session->channel_vols)
- return;
-
- for(i = session->channel_count; i < channels; ++i)
- session->channel_vols[i] = 1.f;
-
- session->channel_count = channels;
- }
-}
-
-static AudioSession *create_session(const GUID *guid, IMMDevice *device,
- UINT num_channels)
-{
- AudioSession *ret;
-
- ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AudioSession));
- if(!ret)
- return NULL;
-
- memcpy(&ret->guid, guid, sizeof(GUID));
-
- ret->device = device;
-
- list_init(&ret->clients);
-
- 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;
-
- return ret;
-}
-
-/* if channels == 0, then this will return or create a session with
- * matching dataflow and GUID. otherwise, channels must also match */
-static HRESULT get_audio_session(const GUID *sessionguid,
- IMMDevice *device, UINT channels, AudioSession **out)
-{
- AudioSession *session;
-
- if(!sessionguid || IsEqualGUID(sessionguid, &GUID_NULL)){
- *out = create_session(&GUID_NULL, device, channels);
- if(!*out)
- return E_OUTOFMEMORY;
-
- return S_OK;
- }
-
- *out = NULL;
- LIST_FOR_EACH_ENTRY(session, &g_sessions, AudioSession, entry){
- if(session->device == device &&
- IsEqualGUID(sessionguid, &session->guid)){
- session_init_vols(session, channels);
- *out = session;
- break;
- }
- }
-
- if(!*out){
- *out = create_session(sessionguid, device, channels);
- if(!*out)
- return E_OUTOFMEMORY;
- }
-
- return S_OK;
-}
-
-static HRESULT waveformat_to_pcm(ACImpl *This, const WAVEFORMATEX *fmt, SLAndroidDataFormat_PCM_EX *pcm)
-{
- if(fmt->nSamplesPerSec < 8000 || fmt->nSamplesPerSec > 48000)
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
-
- pcm->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
-
- pcm->sampleRate = fmt->nSamplesPerSec * 1000; /* sampleRate is in milli-Hz */
- pcm->bitsPerSample = fmt->wBitsPerSample;
- pcm->containerSize = fmt->wBitsPerSample;
-
- if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
- (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)fmt)->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
- if(pcm->bitsPerSample == 8)
- pcm->representation = SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT;
- else if(pcm->bitsPerSample == 16)
- pcm->representation = SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT;
- else
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
- }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
- (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)fmt)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
- if(pcm->bitsPerSample == 32)
- pcm->representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
- else
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
- }else
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
-
- /* only up to stereo */
- pcm->numChannels = fmt->nChannels;
- if(pcm->numChannels == 1)
- pcm->channelMask = SL_SPEAKER_FRONT_CENTER;
- else if(This->dataflow == eRender && pcm->numChannels == 2)
- pcm->channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
- else
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
-
- pcm->endianness = SL_BYTEORDER_LITTLEENDIAN;
-
- return S_OK;
-}
-
-static HRESULT try_open_render_device(SLAndroidDataFormat_PCM_EX *pcm, unsigned int num_buffers, SLObjectItf *out)
-{
- SLresult sr;
- SLDataSource source;
- SLDataSink sink;
- SLDataLocator_OutputMix loc_outmix;
- SLboolean required[2];
- SLInterfaceID iids[2];
- SLDataLocator_AndroidSimpleBufferQueue loc_bq;
- SLObjectItf player;
-
- loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- loc_bq.numBuffers = num_buffers;
- source.pLocator = &loc_bq;
- source.pFormat = pcm;
-
- loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
- loc_outmix.outputMix = outputmix;
- sink.pLocator = &loc_outmix;
- sink.pFormat = NULL;
-
- required[0] = SL_BOOLEAN_TRUE;
- iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE;
- required[1] = SL_BOOLEAN_TRUE;
- iids[1] = *pSL_IID_PLAYBACKRATE;
-
- sr = SLCALL(engine, CreateAudioPlayer, &player, &source, &sink,
- 2, iids, required);
- if(sr != SL_RESULT_SUCCESS){
- WARN("CreateAudioPlayer failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(player, Realize, SL_BOOLEAN_FALSE);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(player, Destroy);
- WARN("Player Realize failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- if(out)
- *out = player;
- else
- SLCALL_N(player, Destroy);
-
- return S_OK;
-}
-
-static HRESULT try_open_capture_device(SLAndroidDataFormat_PCM_EX *pcm, unsigned int num_buffers, SLObjectItf *out)
-{
- SLresult sr;
- SLDataSource source;
- SLDataSink sink;
- SLDataLocator_IODevice loc_mic;
- SLboolean required[1];
- SLInterfaceID iids[1];
- SLDataLocator_AndroidSimpleBufferQueue loc_bq;
- SLObjectItf recorder;
-
- loc_mic.locatorType = SL_DATALOCATOR_IODEVICE;
- loc_mic.deviceType = SL_IODEVICE_AUDIOINPUT;
- loc_mic.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
- loc_mic.device = NULL;
- source.pLocator = &loc_mic;
- source.pFormat = NULL;
-
- loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- loc_bq.numBuffers = num_buffers;
- sink.pLocator = &loc_bq;
- sink.pFormat = pcm;
-
- required[0] = SL_BOOLEAN_TRUE;
- iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE;
-
- sr = SLCALL(engine, CreateAudioRecorder, &recorder, &source, &sink,
- 1, iids, required);
- if(sr != SL_RESULT_SUCCESS){
- WARN("CreateAudioRecorder failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- sr = SLCALL(recorder, Realize, SL_BOOLEAN_FALSE);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(recorder, Destroy);
- WARN("Recorder Realize failed: 0x%x\n", sr);
- return E_FAIL;
- }
-
- if(out)
- *out = recorder;
- else
- SLCALL_N(recorder, Destroy);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
- AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
- REFERENCE_TIME period, const WAVEFORMATEX *fmt,
- const GUID *sessionguid)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- int i, num_buffers;
- HRESULT hr;
- SLresult sr;
- SLAndroidDataFormat_PCM_EX pcm;
-
- TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
- wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
-
- if(!fmt)
- return E_POINTER;
-
- dump_fmt(fmt);
-
- if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
- return E_INVALIDARG;
-
- if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
- AUDCLNT_STREAMFLAGS_LOOPBACK |
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
- AUDCLNT_STREAMFLAGS_NOPERSIST |
- AUDCLNT_STREAMFLAGS_RATEADJUST |
- AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
- AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
- AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED |
- AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY |
- AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM)){
- FIXME("Unknown flags: %08x\n", flags);
- return E_INVALIDARG;
- }
-
- if(mode == AUDCLNT_SHAREMODE_SHARED){
- period = DefaultPeriod;
- if( duration < 3 * period)
- duration = 3 * period;
- }else{
- if(!period)
- period = DefaultPeriod; /* not minimum */
- if(period < MinimumPeriod || period > 5000000)
- return AUDCLNT_E_INVALID_DEVICE_PERIOD;
- if(duration > 20000000) /* the smaller the period, the lower this limit */
- return AUDCLNT_E_BUFFER_SIZE_ERROR;
- if(flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){
- if(duration != period)
- return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL;
- FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
- return AUDCLNT_E_DEVICE_IN_USE;
- }else{
- if( duration < 8 * period)
- duration = 8 * period; /* may grow above 2s */
- }
- }
-
- EnterCriticalSection(&This->lock);
-
- if(This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_ALREADY_INITIALIZED;
- }
-
- This->period_us = period / 10;
- This->period_frames = MulDiv(fmt->nSamplesPerSec, period, 10000000);
-
- This->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
- if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- This->bufsize_frames -= This->bufsize_frames % This->period_frames;
- else if(This->bufsize_frames % This->period_frames != 0)
- /* hack: round up to integer multiple */
- This->bufsize_frames += This->period_frames - This->bufsize_frames % This->period_frames;
-
- hr = waveformat_to_pcm(This, fmt, &pcm);
- if(FAILED(hr)){
- LeaveCriticalSection(&This->lock);
- return hr;
- }
-
- num_buffers = This->bufsize_frames / This->period_frames;
-
- if(This->dataflow == eRender){
- hr = try_open_render_device(&pcm, num_buffers, &This->player);
- if(FAILED(hr)){
- LeaveCriticalSection(&This->lock);
- return hr;
- }
-
- sr = SLCALL(This->player, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- WARN("Player GetInterface(BufferQueue) failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
-
- sr = SLCALL(This->player, GetInterface, *pSL_IID_PLAY, &This->playitf);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- WARN("Player GetInterface(Play) failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }else{
- hr = try_open_capture_device(&pcm, num_buffers, &This->recorder);
- if(FAILED(hr)){
- LeaveCriticalSection(&This->lock);
- return hr;
- }
-
- sr = SLCALL(This->recorder, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- WARN("Recorder GetInterface(BufferQueue) failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
-
- sr = SLCALL(This->recorder, GetInterface, *pSL_IID_RECORD, &This->recorditf);
- if(sr != SL_RESULT_SUCCESS){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- WARN("Recorder GetInterface(Record) failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }
-
- This->fmt = clone_format(fmt);
- if(!This->fmt){
- if(This->player){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- }
- if(This->recorder){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- }
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
-
- This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
- This->bufsize_frames * fmt->nBlockAlign);
- if(!This->local_buffer){
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- if(This->player){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- }
- if(This->recorder){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- }
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
-
- if(This->dataflow == eCapture){
- while(This->in_sl_frames < This->bufsize_frames){
- TRACE("enqueueing: %u frames from %u\n", This->period_frames, (This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames);
- sr = SLCALL(This->bufq, Enqueue,
- This->local_buffer + ((This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames) * This->fmt->nBlockAlign,
- This->period_frames * This->fmt->nBlockAlign);
- if(sr != SL_RESULT_SUCCESS)
- WARN("Enqueue failed: 0x%x\n", sr);
- This->in_sl_frames += This->period_frames;
- }
- }
-
- This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
- if(!This->vols){
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- if(This->player){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- }
- if(This->recorder){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- }
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
-
- for(i = 0; i < fmt->nChannels; ++i)
- This->vols[i] = 1.f;
-
- This->share = mode;
- This->flags = flags;
- This->oss_bufsize_bytes = 0;
-
- EnterCriticalSection(&g_sessions_lock);
-
- hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
- &This->session);
- if(FAILED(hr)){
- LeaveCriticalSection(&g_sessions_lock);
- HeapFree(GetProcessHeap(), 0, This->vols);
- This->vols = NULL;
- CoTaskMemFree(This->fmt);
- This->fmt = NULL;
- if(This->player){
- SLCALL_N(This->player, Destroy);
- This->player = NULL;
- }
- if(This->recorder){
- SLCALL_N(This->recorder, Destroy);
- This->recorder = NULL;
- }
- LeaveCriticalSection(&This->lock);
- return hr;
- }
-
- list_add_tail(&This->session->clients, &This->entry);
-
- LeaveCriticalSection(&g_sessions_lock);
-
- This->initted = TRUE;
-
- TRACE("numBuffers: %u, bufsize: %u, period: %u\n", num_buffers,
- This->bufsize_frames, This->period_frames);
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
- UINT32 *frames)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%p)\n", This, frames);
-
- if(!frames)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- *frames = This->bufsize_frames;
-
- TRACE("buffer size: %u\n", *frames);
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
- REFERENCE_TIME *latency)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%p)\n", This, latency);
-
- if(!latency)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- /* pretend we process audio in Period chunks, so max latency includes
- * the period time. Some native machines add .6666ms in shared mode. */
- *latency = This->period_us * 10 + 6666;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
- UINT32 *numpad)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%p)\n", This, numpad);
-
- if(!numpad)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- *numpad = This->held_frames;
-
- TRACE("padding: %u\n", *numpad);
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
- AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *pwfx,
- WAVEFORMATEX **outpwfx)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- SLAndroidDataFormat_PCM_EX pcm;
- HRESULT hr;
-
- TRACE("(%p)->(%x, %p, %p)\n", This, mode, pwfx, outpwfx);
-
- if(!pwfx || (mode == AUDCLNT_SHAREMODE_SHARED && !outpwfx))
- return E_POINTER;
-
- if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
- return E_INVALIDARG;
-
- if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- pwfx->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
- return E_INVALIDARG;
-
- dump_fmt(pwfx);
-
- if(outpwfx)
- *outpwfx = NULL;
-
- hr = waveformat_to_pcm(This, pwfx, &pcm);
- if(SUCCEEDED(hr)){
- if(This->dataflow == eRender){
- hr = try_open_render_device(&pcm, 10, NULL);
- }else{
- hr = try_open_capture_device(&pcm, 10, NULL);
- }
- }
-
- if(FAILED(hr)){
- if(outpwfx){
- hr = IAudioClient3_GetMixFormat(iface, outpwfx);
- if(FAILED(hr))
- return hr;
- return S_FALSE;
- }
-
- hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
- }
-
- TRACE("returning: %08x\n", hr);
-
- return hr;
-}
-
-static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
- WAVEFORMATEX **pwfx)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- WAVEFORMATEXTENSIBLE *fmt;
-
- TRACE("(%p)->(%p)\n", This, pwfx);
-
- if(!pwfx)
- return E_POINTER;
- *pwfx = NULL;
-
- fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
- if(!fmt)
- return E_OUTOFMEMORY;
-
- fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- fmt->Format.wBitsPerSample = 16;
- fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- if(This->dataflow == eRender)
- fmt->Format.nChannels = 2;
- else
- fmt->Format.nChannels = 1;
- fmt->Format.nSamplesPerSec = 48000; /* TODO: query supported? recording? */
- fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
- fmt->Format.nChannels) / 8;
- fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
- fmt->Format.nBlockAlign;
- fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
- fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
- fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
-
- *pwfx = (WAVEFORMATEX*)fmt;
- dump_fmt(*pwfx);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface,
- REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
-
- if(!defperiod && !minperiod)
- return E_POINTER;
-
- if(defperiod)
- *defperiod = DefaultPeriod;
- if(minperiod)
- *minperiod = MinimumPeriod;
-
- return S_OK;
-}
-
-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 &&
- IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
- This->fmt->wBitsPerSample == 8)
- memset(buffer, 128, frames * This->fmt->nBlockAlign);
- else
- memset(buffer, 0, frames * This->fmt->nBlockAlign);
-}
-
-static void sl_read_data(ACImpl *This)
-{
- SLAndroidSimpleBufferQueueState state;
- SLresult sr;
- SLuint32 elapsed;
-
- memset(&state, 0, sizeof(state));
-
- sr = SLCALL(This->bufq, GetState, &state);
- if(sr != SL_RESULT_SUCCESS){
- WARN("GetState failed: 0x%x\n", sr);
- return;
- }
- TRACE("got: count: %u, index: %u, held: %u, in_sl: %u\n", state.count, state.index, This->held_frames, This->in_sl_frames);
-
- elapsed = This->in_sl_frames - state.count * This->period_frames;
- This->held_frames += elapsed;
- This->in_sl_frames = state.count * This->period_frames;
-
- if(This->held_frames == This->bufsize_frames){
- /* overrun */
- TRACE("overrun??\n");
- This->lcl_offs_frames += This->period_frames;
- This->held_frames -= This->period_frames;
- }
-
- TRACE("good range: %u, %u\n", This->lcl_offs_frames, This->lcl_offs_frames + This->held_frames);
- TRACE("held: %u, in_sl: %u\n", This->held_frames, This->in_sl_frames);
- while(This->held_frames + This->in_sl_frames < This->bufsize_frames){
- TRACE("enqueueing: %u frames from %u\n", This->period_frames, (This->lcl_offs_frames + This->held_frames + This->in_sl_frames) % This->bufsize_frames);
- sr = SLCALL(This->bufq, Enqueue,
- This->local_buffer + ((This->lcl_offs_frames + This->held_frames + This->in_sl_frames) % This->bufsize_frames) * This->fmt->nBlockAlign,
- This->period_frames * This->fmt->nBlockAlign);
- if(sr != SL_RESULT_SUCCESS)
- WARN("Enqueue failed: 0x%x\n", sr);
- This->in_sl_frames += This->period_frames;
- }
-}
-
-static DWORD wrap_enqueue(ACImpl *This)
-{
- DWORD to_enqueue = min(This->held_frames, This->period_frames);
- DWORD offs = (This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames;
- BYTE *buf = This->local_buffer + offs * This->fmt->nBlockAlign;
-
- if(offs + to_enqueue > This->bufsize_frames){
- DWORD chunk = This->bufsize_frames - offs;
-
- if(This->wrap_buffer_frames < to_enqueue){
- HeapFree(GetProcessHeap(), 0, This->wrap_buffer);
- This->wrap_buffer = HeapAlloc(GetProcessHeap(), 0, to_enqueue * This->fmt->nBlockAlign);
- This->wrap_buffer_frames = to_enqueue;
- }
-
- memcpy(This->wrap_buffer, This->local_buffer + offs * This->fmt->nBlockAlign, chunk * This->fmt->nBlockAlign);
- memcpy(This->wrap_buffer + chunk * This->fmt->nBlockAlign, This->local_buffer, (to_enqueue - chunk) * This->fmt->nBlockAlign);
-
- buf = This->wrap_buffer;
- }
-
- SLCALL(This->bufq, Enqueue, buf,
- to_enqueue * This->fmt->nBlockAlign);
-
- return to_enqueue;
-}
-
-static void sl_write_data(ACImpl *This)
-{
- SLAndroidSimpleBufferQueueState state;
- SLresult sr;
- SLuint32 elapsed;
-
- memset(&state, 0, sizeof(state));
-
- sr = SLCALL(This->bufq, GetState, &state);
- if(sr != SL_RESULT_SUCCESS){
- WARN("GetState failed: 0x%x\n", sr);
- return;
- }
- TRACE("got: count: %u, index: %u\n", state.count, state.index);
-
- elapsed = This->in_sl_frames - state.count * This->period_frames;
-
- if(elapsed > This->held_frames)
- This->held_frames = 0;
- else
- This->held_frames -= elapsed;
-
- This->lcl_offs_frames += elapsed;
- This->lcl_offs_frames %= This->bufsize_frames;
-
- This->in_sl_frames = state.count * This->period_frames;
-
- while(This->held_frames >= This->in_sl_frames + This->period_frames){
- /* have at least a period to write, so write it */
- TRACE("enqueueing: %u frames from %u\n", This->period_frames, (This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames);
- This->in_sl_frames += wrap_enqueue(This);
- }
-
- if(This->held_frames && This->in_sl_frames < This->period_frames * 3){
- /* write out the last bit with a partial period */
- TRACE("enqueueing partial period: %u frames from %u\n", This->held_frames, (This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames);
- This->in_sl_frames += wrap_enqueue(This);
- }
-
- TRACE("done with enqueue, lcl_offs: %u, in_sl: %u, held: %u\n", This->lcl_offs_frames, This->in_sl_frames, This->held_frames);
-}
-
-static void CALLBACK sl_period_callback(void *user, BOOLEAN timer)
-{
- ACImpl *This = user;
-
- EnterCriticalSection(&This->lock);
-
- if(This->playing){
- if(This->dataflow == eRender)
- sl_write_data(This);
- else if(This->dataflow == eCapture)
- sl_read_data(This);
- }
-
- LeaveCriticalSection(&This->lock);
-
- if(This->event)
- SetEvent(This->event);
-}
-
-static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- SLresult sr;
-
- TRACE("(%p)\n", This);
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_EVENTHANDLE_NOT_SET;
- }
-
- if(This->playing){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_STOPPED;
- }
-
- if(This->dataflow == eRender){
- sr = SLCALL(This->playitf, SetPlayState, SL_PLAYSTATE_PLAYING);
- if(sr != SL_RESULT_SUCCESS){
- WARN("SetPlayState failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }else{
- sr = SLCALL(This->recorditf, SetRecordState, SL_RECORDSTATE_RECORDING);
- if(sr != SL_RESULT_SUCCESS){
- WARN("SetRecordState failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }
-
- if(!This->timer){
- if(!CreateTimerQueueTimer(&This->timer, g_timer_q,
- sl_period_callback, This, 0, This->period_us / 1000,
- WT_EXECUTEINTIMERTHREAD))
- WARN("Unable to create period timer: %u\n", GetLastError());
- }
-
- This->playing = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- SLresult sr;
-
- TRACE("(%p)\n", This);
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(!This->playing){
- LeaveCriticalSection(&This->lock);
- return S_FALSE;
- }
-
- if(This->dataflow == eRender){
- sr = SLCALL(This->playitf, SetPlayState, SL_PLAYSTATE_PAUSED);
- if(sr != SL_RESULT_SUCCESS){
- WARN("SetPlayState failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }else{
- sr = SLCALL(This->recorditf, SetRecordState, SL_RECORDSTATE_STOPPED);
- if(sr != SL_RESULT_SUCCESS){
- WARN("SetRecordState failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
- }
-
- This->playing = FALSE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- SLresult sr;
-
- TRACE("(%p)\n", This);
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(This->playing){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_STOPPED;
- }
-
- if(This->getbuf_last){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_BUFFER_OPERATION_PENDING;
- }
-
- sr = SLCALL_N(This->bufq, Clear);
- if(sr != SL_RESULT_SUCCESS){
- WARN("Clear failed: 0x%x\n", sr);
- LeaveCriticalSection(&This->lock);
- return E_FAIL;
- }
-
- This->lcl_offs_frames = 0;
- This->in_sl_frames = 0;
-
- if(This->dataflow == eRender){
- This->written_frames = 0;
- This->last_pos_frames = 0;
- }else{
- This->written_frames += This->held_frames;
- while(This->in_sl_frames < This->bufsize_frames){
- TRACE("enqueueing: %u frames from %u\n", This->period_frames, (This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames);
- sr = SLCALL(This->bufq, Enqueue,
- This->local_buffer + ((This->lcl_offs_frames + This->in_sl_frames) % This->bufsize_frames) * This->fmt->nBlockAlign,
- This->period_frames * This->fmt->nBlockAlign);
- if(sr != SL_RESULT_SUCCESS)
- WARN("Enqueue failed: 0x%x\n", sr);
- This->in_sl_frames += This->period_frames;
- }
- }
-
- This->held_frames = 0;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
- HANDLE event)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%p)\n", This, event);
-
- if(!event)
- return E_INVALIDARG;
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
- }
-
- if (This->event){
- LeaveCriticalSection(&This->lock);
- FIXME("called twice\n");
- return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
- }
-
- This->event = event;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid,
- void **ppv)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- EnterCriticalSection(&This->lock);
-
- if(!This->initted){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_NOT_INITIALIZED;
- }
-
- if(IsEqualIID(riid, &IID_IAudioRenderClient)){
- if(This->dataflow != eRender){
- LeaveCriticalSection(&This->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);
- return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
- }
- IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
- *ppv = &This->IAudioCaptureClient_iface;
- }else if(IsEqualIID(riid, &IID_IAudioClock)){
- IAudioClock_AddRef(&This->IAudioClock_iface);
- *ppv = &This->IAudioClock_iface;
- }else if(IsEqualIID(riid, &IID_IAudioStreamVolume)){
- IAudioStreamVolume_AddRef(&This->IAudioStreamVolume_iface);
- *ppv = &This->IAudioStreamVolume_iface;
- }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
- if(!This->session_wrapper){
- This->session_wrapper = AudioSessionWrapper_Create(This);
- if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
- }else
- IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
-
- *ppv = &This->session_wrapper->IAudioSessionControl2_iface;
- }else if(IsEqualIID(riid, &IID_IChannelAudioVolume)){
- if(!This->session_wrapper){
- This->session_wrapper = AudioSessionWrapper_Create(This);
- if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
- }else
- IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
-
- *ppv = &This->session_wrapper->IChannelAudioVolume_iface;
- }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
- if(!This->session_wrapper){
- This->session_wrapper = AudioSessionWrapper_Create(This);
- if(!This->session_wrapper){
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
- }else
- ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
-
- *ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
- }
-
- if(*ppv){
- LeaveCriticalSection(&This->lock);
- return S_OK;
- }
-
- LeaveCriticalSection(&This->lock);
-
- FIXME("stub %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static HRESULT WINAPI AudioClient_IsOffloadCapable(IAudioClient3 *iface,
- AUDIO_STREAM_CATEGORY category, BOOL *offload_capable)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- TRACE("(%p)->(0x%x, %p)\n", This, category, offload_capable);
-
- if(!offload_capable)
- return E_INVALIDARG;
-
- *offload_capable = FALSE;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
- const AudioClientProperties *prop)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
- const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
-
- TRACE("(%p)->(%p)\n", This, prop);
-
- if(!legacy_prop)
- return E_POINTER;
-
- if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- legacy_prop->bIsOffload,
- legacy_prop->eCategory,
- prop->Options);
- }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
- TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
- legacy_prop->bIsOffload,
- legacy_prop->eCategory);
- }else{
- WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
- return E_INVALIDARG;
- }
-
-
- if(legacy_prop->bIsOffload)
- return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClient_GetBufferSizeLimits(IAudioClient3 *iface,
- const WAVEFORMATEX *format, BOOL event_driven, REFERENCE_TIME *min_duration,
- REFERENCE_TIME *max_duration)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- FIXME("(%p)->(%p, %u, %p, %p)\n", This, format, event_driven, min_duration, max_duration);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioClient_GetSharedModeEnginePeriod(IAudioClient3 *iface,
- const WAVEFORMATEX *format, UINT32 *default_period_frames, UINT32 *unit_period_frames,
- UINT32 *min_period_frames, UINT32 *max_period_frames)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- FIXME("(%p)->(%p, %p, %p, %p, %p)\n", This, format, default_period_frames, unit_period_frames,
- min_period_frames, max_period_frames);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioClient_GetCurrentSharedModeEnginePeriod(IAudioClient3 *iface,
- WAVEFORMATEX **cur_format, UINT32 *cur_period_frames)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- FIXME("(%p)->(%p, %p)\n", This, cur_format, cur_period_frames);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioClient_InitializeSharedAudioStream(IAudioClient3 *iface,
- DWORD flags, UINT32 period_frames, const WAVEFORMATEX *format,
- const GUID *session_guid)
-{
- ACImpl *This = impl_from_IAudioClient3(iface);
-
- FIXME("(%p)->(0x%x, %u, %p, %s)\n", This, flags, period_frames, format, debugstr_guid(session_guid));
-
- return E_NOTIMPL;
-}
-
-static const IAudioClient3Vtbl AudioClient3_Vtbl =
-{
- AudioClient_QueryInterface,
- AudioClient_AddRef,
- AudioClient_Release,
- AudioClient_Initialize,
- AudioClient_GetBufferSize,
- AudioClient_GetStreamLatency,
- AudioClient_GetCurrentPadding,
- AudioClient_IsFormatSupported,
- AudioClient_GetMixFormat,
- AudioClient_GetDevicePeriod,
- AudioClient_Start,
- AudioClient_Stop,
- AudioClient_Reset,
- AudioClient_SetEventHandle,
- AudioClient_GetService,
- AudioClient_IsOffloadCapable,
- AudioClient_SetClientProperties,
- AudioClient_GetBufferSizeLimits,
- AudioClient_GetSharedModeEnginePeriod,
- AudioClient_GetCurrentSharedModeEnginePeriod,
- AudioClient_InitializeSharedAudioStream,
-};
-
-static HRESULT WINAPI AudioRenderClient_QueryInterface(
- IAudioRenderClient *iface, REFIID riid, void **ppv)
-{
- ACImpl *This = impl_from_IAudioRenderClient(iface);
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioRenderClient))
- *ppv = iface;
- else if(IsEqualIID(riid, &IID_IMarshal))
- return IUnknown_QueryInterface(This->pUnkFTMarshal, riid, ppv);
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
-{
- ACImpl *This = impl_from_IAudioRenderClient(iface);
- return AudioClient_AddRef(&This->IAudioClient3_iface);
-}
-
-static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
-{
- ACImpl *This = impl_from_IAudioRenderClient(iface);
- return AudioClient_Release(&This->IAudioClient3_iface);
-}
-
-static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
- UINT32 frames, BYTE **data)
-{
- ACImpl *This = impl_from_IAudioRenderClient(iface);
- UINT32 write_pos;
-
- TRACE("(%p)->(%u, %p)\n", This, frames, data);
-
- if(!data)
- return E_POINTER;
-
- *data = NULL;
-
- EnterCriticalSection(&This->lock);
-
- if(This->getbuf_last){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_OUT_OF_ORDER;
- }
-
- if(!frames){
- LeaveCriticalSection(&This->lock);
- return S_OK;
- }
-
- if(This->held_frames + frames > This->bufsize_frames){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_BUFFER_TOO_LARGE;
- }
-
- write_pos =
- (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
- if(write_pos + frames > This->bufsize_frames){
- if(This->tmp_buffer_frames < frames){
- DWORD alloc = frames < This->period_frames ? This->period_frames : frames;
- HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
- This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
- alloc * This->fmt->nBlockAlign);
- if(!This->tmp_buffer){
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
- This->tmp_buffer_frames = alloc;
- }
- *data = This->tmp_buffer;
- This->getbuf_last = -frames;
- }else{
- *data = This->local_buffer + write_pos * This->fmt->nBlockAlign;
- This->getbuf_last = frames;
- }
-
- silence_buffer(This, *data, frames);
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static void oss_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_frames)
-{
- UINT32 write_offs_frames =
- (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
- UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
- UINT32 chunk_frames = This->bufsize_frames - write_offs_frames;
- UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
- UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
-
- if(written_bytes <= chunk_bytes){
- memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
- }else{
- memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
- memcpy(This->local_buffer, buffer + chunk_bytes,
- written_bytes - chunk_bytes);
- }
-}
-
-static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
- IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
-{
- ACImpl *This = impl_from_IAudioRenderClient(iface);
- BYTE *buffer;
-
- TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
-
- EnterCriticalSection(&This->lock);
-
- if(!written_frames){
- This->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
- return S_OK;
- }
-
- if(!This->getbuf_last){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_OUT_OF_ORDER;
- }
-
- if(written_frames > (This->getbuf_last >= 0 ? This->getbuf_last : -This->getbuf_last)){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_INVALID_SIZE;
- }
-
- if(This->getbuf_last >= 0)
- buffer = This->local_buffer + This->fmt->nBlockAlign *
- ((This->lcl_offs_frames + This->held_frames) % This->bufsize_frames);
- else
- buffer = This->tmp_buffer;
-
- if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
- silence_buffer(This, buffer, written_frames);
-
- if(This->getbuf_last < 0)
- oss_wrap_buffer(This, buffer, written_frames);
-
- This->held_frames += written_frames;
- This->written_frames += written_frames;
- This->getbuf_last = 0;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
- AudioRenderClient_QueryInterface,
- AudioRenderClient_AddRef,
- AudioRenderClient_Release,
- AudioRenderClient_GetBuffer,
- AudioRenderClient_ReleaseBuffer
-};
-
-static HRESULT WINAPI AudioCaptureClient_QueryInterface(
- IAudioCaptureClient *iface, REFIID riid, void **ppv)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioCaptureClient))
- *ppv = iface;
- else if(IsEqualIID(riid, &IID_IMarshal))
- return IUnknown_QueryInterface(This->pUnkFTMarshal, riid, ppv);
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
- return IAudioClient3_AddRef(&This->IAudioClient3_iface);
-}
-
-static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
- return IAudioClient3_Release(&This->IAudioClient3_iface);
-}
-
-static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
- BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
- UINT64 *qpcpos)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
-
- TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
- devpos, qpcpos);
-
- if(!data)
- return E_POINTER;
-
- *data = NULL;
-
- if(!frames || !flags)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- if(This->getbuf_last){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_OUT_OF_ORDER;
- }
-
- if(This->held_frames < This->period_frames){
- *frames = 0;
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_S_BUFFER_EMPTY;
- }
-
- *flags = 0;
-
- *frames = This->period_frames;
-
- if(This->lcl_offs_frames + *frames > This->bufsize_frames){
- UINT32 chunk_bytes, offs_bytes, frames_bytes;
- 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){
- LeaveCriticalSection(&This->lock);
- return E_OUTOFMEMORY;
- }
- This->tmp_buffer_frames = *frames;
- }
-
- *data = This->tmp_buffer;
- chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
- This->fmt->nBlockAlign;
- offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
- frames_bytes = *frames * This->fmt->nBlockAlign;
- memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
- memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
- frames_bytes - chunk_bytes);
- }else
- *data = This->local_buffer +
- This->lcl_offs_frames * This->fmt->nBlockAlign;
- TRACE("returning %u from %u\n", This->period_frames, This->lcl_offs_frames);
-
- This->getbuf_last = *frames;
-
- if(devpos)
- *devpos = This->written_frames;
- if(qpcpos){
- LARGE_INTEGER stamp, freq;
- QueryPerformanceCounter(&stamp);
- QueryPerformanceFrequency(&freq);
- *qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
- }
-
- LeaveCriticalSection(&This->lock);
-
- return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
-}
-
-static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
- IAudioCaptureClient *iface, UINT32 done)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
-
- TRACE("(%p)->(%u)\n", This, done);
-
- EnterCriticalSection(&This->lock);
-
- if(!done){
- This->getbuf_last = 0;
- LeaveCriticalSection(&This->lock);
- return S_OK;
- }
-
- if(!This->getbuf_last){
- LeaveCriticalSection(&This->lock);
- return AUDCLNT_E_OUT_OF_ORDER;
- }
-
- if(This->getbuf_last != done){
- LeaveCriticalSection(&This->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;
- TRACE("lcl: %u, held: %u\n", This->lcl_offs_frames, This->held_frames);
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
- IAudioCaptureClient *iface, UINT32 *frames)
-{
- ACImpl *This = impl_from_IAudioCaptureClient(iface);
-
- TRACE("(%p)->(%p)\n", This, frames);
-
- if(!frames)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- *frames = This->held_frames < This->period_frames ? 0 : This->period_frames;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
-{
- AudioCaptureClient_QueryInterface,
- AudioCaptureClient_AddRef,
- AudioCaptureClient_Release,
- AudioCaptureClient_GetBuffer,
- AudioCaptureClient_ReleaseBuffer,
- AudioCaptureClient_GetNextPacketSize
-};
-
-static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
- REFIID riid, void **ppv)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
-
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
- *ppv = iface;
- else if(IsEqualIID(riid, &IID_IAudioClock2))
- *ppv = &This->IAudioClock2_iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
- return IAudioClient3_AddRef(&This->IAudioClient3_iface);
-}
-
-static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
- return IAudioClient3_Release(&This->IAudioClient3_iface);
-}
-
-static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
-
- TRACE("(%p)->(%p)\n", This, freq);
-
- if(This->share == AUDCLNT_SHAREMODE_SHARED)
- *freq = (UINT64)This->fmt->nSamplesPerSec * This->fmt->nBlockAlign;
- else
- *freq = This->fmt->nSamplesPerSec;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
- UINT64 *qpctime)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
-
- TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
-
- if(!pos)
- return E_POINTER;
-
- EnterCriticalSection(&This->lock);
-
- if(This->dataflow == eRender){
- *pos = This->written_frames - This->held_frames;
- if(*pos < This->last_pos_frames)
- *pos = This->last_pos_frames;
- }else if(This->dataflow == eCapture){
- *pos = This->written_frames - This->held_frames;
- }
-
- This->last_pos_frames = *pos;
-
- TRACE("returning: 0x%s\n", wine_dbgstr_longlong(*pos));
- if(This->share == AUDCLNT_SHAREMODE_SHARED)
- *pos *= This->fmt->nBlockAlign;
-
- LeaveCriticalSection(&This->lock);
-
- if(qpctime){
- LARGE_INTEGER stamp, freq;
- QueryPerformanceCounter(&stamp);
- QueryPerformanceFrequency(&freq);
- *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
- }
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
- DWORD *chars)
-{
- ACImpl *This = impl_from_IAudioClock(iface);
-
- TRACE("(%p)->(%p)\n", This, chars);
-
- if(!chars)
- return E_POINTER;
-
- *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
-
- return S_OK;
-}
-
-static const IAudioClockVtbl AudioClock_Vtbl =
-{
- AudioClock_QueryInterface,
- AudioClock_AddRef,
- AudioClock_Release,
- AudioClock_GetFrequency,
- AudioClock_GetPosition,
- AudioClock_GetCharacteristics
-};
-
-static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
- REFIID riid, void **ppv)
-{
- ACImpl *This = impl_from_IAudioClock2(iface);
- return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
-}
-
-static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
-{
- ACImpl *This = impl_from_IAudioClock2(iface);
- return IAudioClient3_AddRef(&This->IAudioClient3_iface);
-}
-
-static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
-{
- ACImpl *This = impl_from_IAudioClock2(iface);
- return IAudioClient3_Release(&This->IAudioClient3_iface);
-}
-
-static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
- UINT64 *pos, UINT64 *qpctime)
-{
- ACImpl *This = impl_from_IAudioClock2(iface);
-
- FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
-
- return E_NOTIMPL;
-}
-
-static const IAudioClock2Vtbl AudioClock2_Vtbl =
-{
- AudioClock2_QueryInterface,
- AudioClock2_AddRef,
- AudioClock2_Release,
- AudioClock2_GetDevicePosition
-};
-
-static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client)
-{
- AudioSessionWrapper *ret;
-
- ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(AudioSessionWrapper));
- if(!ret)
- return NULL;
-
- ret->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
- ret->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
- ret->IChannelAudioVolume_iface.lpVtbl = &ChannelAudioVolume_Vtbl;
-
- ret->ref = 1;
-
- ret->client = client;
- if(client){
- ret->session = client->session;
- AudioClient_AddRef(&client->IAudioClient3_iface);
- }
-
- return ret;
-}
-
-static HRESULT WINAPI AudioSessionControl_QueryInterface(
- IAudioSessionControl2 *iface, REFIID riid, void **ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioSessionControl) ||
- IsEqualIID(riid, &IID_IAudioSessionControl2))
- *ppv = iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
- ULONG ref;
- ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- return ref;
-}
-
-static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
- ULONG ref;
- ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- if(!ref){
- if(This->client){
- EnterCriticalSection(&This->client->lock);
- This->client->session_wrapper = NULL;
- LeaveCriticalSection(&This->client->lock);
- AudioClient_Release(&This->client->IAudioClient3_iface);
- }
- HeapFree(GetProcessHeap(), 0, This);
- }
- return ref;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
- AudioSessionState *state)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
- ACImpl *client;
-
- TRACE("(%p)->(%p)\n", This, state);
-
- if(!state)
- return NULL_PTR_ERR;
-
- EnterCriticalSection(&g_sessions_lock);
-
- if(list_empty(&This->session->clients)){
- *state = AudioSessionStateExpired;
- LeaveCriticalSection(&g_sessions_lock);
- return S_OK;
- }
-
- LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
- EnterCriticalSection(&client->lock);
- if(client->playing){
- *state = AudioSessionStateActive;
- LeaveCriticalSection(&client->lock);
- LeaveCriticalSection(&g_sessions_lock);
- return S_OK;
- }
- LeaveCriticalSection(&client->lock);
- }
-
- LeaveCriticalSection(&g_sessions_lock);
-
- *state = AudioSessionStateInactive;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetDisplayName(
- IAudioSessionControl2 *iface, WCHAR **name)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, name);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_SetDisplayName(
- IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetIconPath(
- IAudioSessionControl2 *iface, WCHAR **path)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, path);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_SetIconPath(
- IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
- IAudioSessionControl2 *iface, GUID *group)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, group);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
- IAudioSessionControl2 *iface, const GUID *group, const GUID *session)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
- debugstr_guid(session));
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
- IAudioSessionControl2 *iface, IAudioSessionEvents *events)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, events);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
- IAudioSessionControl2 *iface, IAudioSessionEvents *events)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, events);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
- IAudioSessionControl2 *iface, WCHAR **id)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, id);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
- IAudioSessionControl2 *iface, WCHAR **id)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- FIXME("(%p)->(%p) - stub\n", This, id);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionControl_GetProcessId(
- IAudioSessionControl2 *iface, DWORD *pid)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- TRACE("(%p)->(%p)\n", This, pid);
-
- if(!pid)
- return E_POINTER;
-
- *pid = GetCurrentProcessId();
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
- IAudioSessionControl2 *iface)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- TRACE("(%p)\n", This);
-
- return S_FALSE;
-}
-
-static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
- IAudioSessionControl2 *iface, BOOL optout)
-{
- AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
-
- TRACE("(%p)->(%d)\n", This, optout);
-
- return S_OK;
-}
-
-static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
-{
- AudioSessionControl_QueryInterface,
- AudioSessionControl_AddRef,
- AudioSessionControl_Release,
- AudioSessionControl_GetState,
- AudioSessionControl_GetDisplayName,
- AudioSessionControl_SetDisplayName,
- AudioSessionControl_GetIconPath,
- AudioSessionControl_SetIconPath,
- AudioSessionControl_GetGroupingParam,
- AudioSessionControl_SetGroupingParam,
- AudioSessionControl_RegisterAudioSessionNotification,
- AudioSessionControl_UnregisterAudioSessionNotification,
- AudioSessionControl_GetSessionIdentifier,
- AudioSessionControl_GetSessionInstanceIdentifier,
- AudioSessionControl_GetProcessId,
- AudioSessionControl_IsSystemSoundsSession,
- AudioSessionControl_SetDuckingPreference
-};
-
-static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
- ISimpleAudioVolume *iface, REFIID riid, void **ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_ISimpleAudioVolume))
- *ppv = iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
-}
-
-static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
-}
-
-static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
- ISimpleAudioVolume *iface, float level, const GUID *context)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
-
- if(level < 0.f || level > 1.f)
- return E_INVALIDARG;
-
- if(context)
- FIXME("Notifications not supported yet\n");
-
- EnterCriticalSection(&session->lock);
-
- session->master_vol = level;
-
- TRACE("OSS doesn't support setting volume\n");
-
- LeaveCriticalSection(&session->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
- ISimpleAudioVolume *iface, float *level)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%p)\n", session, level);
-
- if(!level)
- return NULL_PTR_ERR;
-
- *level = session->master_vol;
-
- return S_OK;
-}
-
-static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
- BOOL mute, const GUID *context)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%u, %p)\n", session, mute, context);
-
- EnterCriticalSection(&session->lock);
-
- session->mute = mute;
-
- LeaveCriticalSection(&session->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
- BOOL *mute)
-{
- AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%p)\n", session, mute);
-
- if(!mute)
- return NULL_PTR_ERR;
-
- *mute = This->session->mute;
-
- return S_OK;
-}
-
-static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =
-{
- SimpleAudioVolume_QueryInterface,
- SimpleAudioVolume_AddRef,
- SimpleAudioVolume_Release,
- SimpleAudioVolume_SetMasterVolume,
- SimpleAudioVolume_GetMasterVolume,
- SimpleAudioVolume_SetMute,
- SimpleAudioVolume_GetMute
-};
-
-static HRESULT WINAPI AudioStreamVolume_QueryInterface(
- IAudioStreamVolume *iface, REFIID riid, void **ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioStreamVolume))
- *ppv = iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioStreamVolume_AddRef(IAudioStreamVolume *iface)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
- return IAudioClient3_AddRef(&This->IAudioClient3_iface);
-}
-
-static ULONG WINAPI AudioStreamVolume_Release(IAudioStreamVolume *iface)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
- return IAudioClient3_Release(&This->IAudioClient3_iface);
-}
-
-static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
- IAudioStreamVolume *iface, UINT32 *out)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
-
- TRACE("(%p)->(%p)\n", This, out);
-
- if(!out)
- return E_POINTER;
-
- *out = This->fmt->nChannels;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
- IAudioStreamVolume *iface, UINT32 index, float level)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
-
- TRACE("(%p)->(%d, %f)\n", This, index, level);
-
- if(level < 0.f || level > 1.f)
- return E_INVALIDARG;
-
- if(index >= This->fmt->nChannels)
- return E_INVALIDARG;
-
- EnterCriticalSection(&This->lock);
-
- This->vols[index] = level;
-
- TRACE("OSS doesn't support setting volume\n");
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
- IAudioStreamVolume *iface, UINT32 index, float *level)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
-
- TRACE("(%p)->(%d, %p)\n", This, index, level);
-
- if(!level)
- return E_POINTER;
-
- if(index >= This->fmt->nChannels)
- return E_INVALIDARG;
-
- *level = This->vols[index];
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
- IAudioStreamVolume *iface, UINT32 count, const float *levels)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
-
- TRACE("(%p)->(%d, %p)\n", This, count, levels);
-
- if(!levels)
- return E_POINTER;
-
- if(count != This->fmt->nChannels)
- return E_INVALIDARG;
-
- EnterCriticalSection(&This->lock);
-
- for(i = 0; i < count; ++i)
- This->vols[i] = levels[i];
-
- TRACE("OSS doesn't support setting volume\n");
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
- IAudioStreamVolume *iface, UINT32 count, float *levels)
-{
- ACImpl *This = impl_from_IAudioStreamVolume(iface);
- int i;
-
- TRACE("(%p)->(%d, %p)\n", This, count, levels);
-
- if(!levels)
- return E_POINTER;
-
- if(count != This->fmt->nChannels)
- return E_INVALIDARG;
-
- EnterCriticalSection(&This->lock);
-
- for(i = 0; i < count; ++i)
- levels[i] = This->vols[i];
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
-{
- AudioStreamVolume_QueryInterface,
- AudioStreamVolume_AddRef,
- AudioStreamVolume_Release,
- AudioStreamVolume_GetChannelCount,
- AudioStreamVolume_SetChannelVolume,
- AudioStreamVolume_GetChannelVolume,
- AudioStreamVolume_SetAllVolumes,
- AudioStreamVolume_GetAllVolumes
-};
-
-static HRESULT WINAPI ChannelAudioVolume_QueryInterface(
- IChannelAudioVolume *iface, REFIID riid, void **ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IChannelAudioVolume))
- *ppv = iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI ChannelAudioVolume_AddRef(IChannelAudioVolume *iface)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
-}
-
-static ULONG WINAPI ChannelAudioVolume_Release(IChannelAudioVolume *iface)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
-}
-
-static HRESULT WINAPI ChannelAudioVolume_GetChannelCount(
- IChannelAudioVolume *iface, UINT32 *out)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%p)\n", session, out);
-
- if(!out)
- return NULL_PTR_ERR;
-
- *out = session->channel_count;
-
- return S_OK;
-}
-
-static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
- IChannelAudioVolume *iface, UINT32 index, float level,
- const GUID *context)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%d, %f, %s)\n", session, index, level,
- wine_dbgstr_guid(context));
-
- if(level < 0.f || level > 1.f)
- return E_INVALIDARG;
-
- if(index >= session->channel_count)
- return E_INVALIDARG;
-
- if(context)
- FIXME("Notifications not supported yet\n");
-
- EnterCriticalSection(&session->lock);
-
- session->channel_vols[index] = level;
-
- TRACE("OSS doesn't support setting volume\n");
-
- LeaveCriticalSection(&session->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI ChannelAudioVolume_GetChannelVolume(
- IChannelAudioVolume *iface, UINT32 index, float *level)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- AudioSession *session = This->session;
-
- TRACE("(%p)->(%d, %p)\n", session, index, level);
-
- if(!level)
- return NULL_PTR_ERR;
-
- if(index >= session->channel_count)
- return E_INVALIDARG;
-
- *level = session->channel_vols[index];
-
- return S_OK;
-}
-
-static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
- IChannelAudioVolume *iface, UINT32 count, const float *levels,
- const GUID *context)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- AudioSession *session = This->session;
- int i;
-
- TRACE("(%p)->(%d, %p, %s)\n", session, count, levels,
- wine_dbgstr_guid(context));
-
- if(!levels)
- return NULL_PTR_ERR;
-
- if(count != session->channel_count)
- return E_INVALIDARG;
-
- if(context)
- FIXME("Notifications not supported yet\n");
-
- EnterCriticalSection(&session->lock);
-
- for(i = 0; i < count; ++i)
- session->channel_vols[i] = levels[i];
-
- TRACE("OSS doesn't support setting volume\n");
-
- LeaveCriticalSection(&session->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI ChannelAudioVolume_GetAllVolumes(
- IChannelAudioVolume *iface, UINT32 count, float *levels)
-{
- AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
- AudioSession *session = This->session;
- int i;
-
- TRACE("(%p)->(%d, %p)\n", session, count, levels);
-
- if(!levels)
- return NULL_PTR_ERR;
-
- if(count != session->channel_count)
- return E_INVALIDARG;
-
- for(i = 0; i < count; ++i)
- levels[i] = session->channel_vols[i];
-
- return S_OK;
-}
-
-static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
-{
- ChannelAudioVolume_QueryInterface,
- ChannelAudioVolume_AddRef,
- ChannelAudioVolume_Release,
- ChannelAudioVolume_GetChannelCount,
- ChannelAudioVolume_SetChannelVolume,
- ChannelAudioVolume_GetChannelVolume,
- ChannelAudioVolume_SetAllVolumes,
- ChannelAudioVolume_GetAllVolumes
-};
-
-static HRESULT WINAPI AudioSessionManager_QueryInterface(IAudioSessionManager2 *iface,
- REFIID riid, void **ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
-
- if(!ppv)
- return E_POINTER;
- *ppv = NULL;
-
- if(IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAudioSessionManager) ||
- IsEqualIID(riid, &IID_IAudioSessionManager2))
- *ppv = iface;
- if(*ppv){
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
- }
-
- WARN("Unknown interface %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI AudioSessionManager_AddRef(IAudioSessionManager2 *iface)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- ULONG ref;
- ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- return ref;
-}
-
-static ULONG WINAPI AudioSessionManager_Release(IAudioSessionManager2 *iface)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- ULONG ref;
- ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) Refcount now %u\n", This, ref);
- if(!ref)
- HeapFree(GetProcessHeap(), 0, This);
- return ref;
-}
-
-static HRESULT WINAPI AudioSessionManager_GetAudioSessionControl(
- IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
- IAudioSessionControl **out)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- AudioSession *session;
- AudioSessionWrapper *wrapper;
- HRESULT hr;
-
- TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
- flags, out);
-
- hr = get_audio_session(session_guid, This->device, 0, &session);
- if(FAILED(hr))
- return hr;
-
- wrapper = AudioSessionWrapper_Create(NULL);
- if(!wrapper)
- return E_OUTOFMEMORY;
-
- wrapper->session = session;
-
- *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionManager_GetSimpleAudioVolume(
- IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
- ISimpleAudioVolume **out)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- AudioSession *session;
- AudioSessionWrapper *wrapper;
- HRESULT hr;
-
- TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
- flags, out);
-
- hr = get_audio_session(session_guid, This->device, 0, &session);
- if(FAILED(hr))
- return hr;
-
- wrapper = AudioSessionWrapper_Create(NULL);
- if(!wrapper)
- return E_OUTOFMEMORY;
-
- wrapper->session = session;
-
- *out = &wrapper->ISimpleAudioVolume_iface;
-
- return S_OK;
-}
-
-static HRESULT WINAPI AudioSessionManager_GetSessionEnumerator(
- IAudioSessionManager2 *iface, IAudioSessionEnumerator **out)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- FIXME("(%p)->(%p) - stub\n", This, out);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionManager_RegisterSessionNotification(
- IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- FIXME("(%p)->(%p) - stub\n", This, notification);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionManager_UnregisterSessionNotification(
- IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- FIXME("(%p)->(%p) - stub\n", This, notification);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionManager_RegisterDuckNotification(
- IAudioSessionManager2 *iface, const WCHAR *session_id,
- IAudioVolumeDuckNotification *notification)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- FIXME("(%p)->(%p) - stub\n", This, notification);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AudioSessionManager_UnregisterDuckNotification(
- IAudioSessionManager2 *iface,
- IAudioVolumeDuckNotification *notification)
-{
- SessionMgr *This = impl_from_IAudioSessionManager2(iface);
- FIXME("(%p)->(%p) - stub\n", This, notification);
- return E_NOTIMPL;
-}
-
-static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl =
-{
- AudioSessionManager_QueryInterface,
- AudioSessionManager_AddRef,
- AudioSessionManager_Release,
- AudioSessionManager_GetAudioSessionControl,
- AudioSessionManager_GetSimpleAudioVolume,
- AudioSessionManager_GetSessionEnumerator,
- AudioSessionManager_RegisterSessionNotification,
- AudioSessionManager_UnregisterSessionNotification,
- AudioSessionManager_RegisterDuckNotification,
- AudioSessionManager_UnregisterDuckNotification
-};
-
-HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
- IAudioSessionManager2 **out)
-{
- SessionMgr *This;
-
- This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SessionMgr));
- if(!This)
- return E_OUTOFMEMORY;
-
- This->IAudioSessionManager2_iface.lpVtbl = &AudioSessionManager2_Vtbl;
- This->device = device;
- This->ref = 1;
-
- *out = &This->IAudioSessionManager2_iface;
-
- return S_OK;
-}
diff --git a/dlls/wineandroid.drv/wineandroid.drv.spec b/dlls/wineandroid.drv/wineandroid.drv.spec
index 2d7e76a04e8..400f5ccb991 100644
--- a/dlls/wineandroid.drv/wineandroid.drv.spec
+++ b/dlls/wineandroid.drv/wineandroid.drv.spec
@@ -1,8 +1,2 @@
# Desktop
@ cdecl wine_create_desktop(long long) ANDROID_create_desktop
-
-# MMDevAPI driver functions
-@ stdcall -private GetPriority() AUDDRV_GetPriority
-@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs
-@ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint
-@ stdcall -private GetAudioSessionManager(ptr ptr) AUDDRV_GetAudioSessionManager
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/191
June 6, 2022