This MR removes Android audio driver. It was considered not worth the effort. If we ever need it, we may restore that from git history (maybe on top of future audio drivers interface unification).
For the rest of the rest of driver, the conversion is rather straightforward, so I went ahead and just did it. The tricky part is that I could only build test it... Luckily, most of changes are sed or copy&paste.
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/wineandroid.drv/keyboard.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c index 20c6879de87..00a55c697c6 100644 --- a/dlls/wineandroid.drv/keyboard.c +++ b/dlls/wineandroid.drv/keyboard.c @@ -755,9 +755,10 @@ jboolean keyboard_event( JNIEnv *env, jobject obj, jint win, jint action, jint k */ INT ANDROID_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) { - int scancode, vkey, len; + int scancode, vkey; const char *name; char key[2]; + DWORD len;
scancode = (lparam >> 16) & 0x1FF; vkey = scancode_to_vkey( scancode ); @@ -795,7 +796,8 @@ INT ANDROID_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) name = vkey_to_name( vkey ); }
- len = MultiByteToWideChar( CP_UTF8, 0, name, -1, buffer, size ); + RtlUTF8ToUnicodeN( buffer, size * sizeof(WCHAR), &len, name, strlen( name ) + 1 ); + len /= sizeof(WCHAR); if (len) len--;
if (!len)
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/wineandroid.drv/android.h | 7 +++++++ dlls/wineandroid.drv/keyboard.c | 9 +++++---- 2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 93e3c2201bf..a7581d1b67f 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -187,4 +187,11 @@ extern JavaVM **p_java_vm; extern jobject *p_java_object; extern unsigned short *p_java_gdt_sel;
+/* string helpers */ + +static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) +{ + while (len--) *dst++ = (unsigned char)*src++; +} + #endif /* __WINE_ANDROID_H */ diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c index 00a55c697c6..e92079c0f59 100644 --- a/dlls/wineandroid.drv/keyboard.c +++ b/dlls/wineandroid.drv/keyboard.c @@ -32,7 +32,6 @@ #include "config.h"
#include "android.h" -#include "wine/unicode.h" #include "wine/server.h" #include "wine/debug.h"
@@ -802,9 +801,11 @@ INT ANDROID_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
if (!len) { - static const WCHAR format[] = {'K','e','y',' ','0','x','%','0','2','x',0}; - snprintfW( buffer, size, format, vkey ); - len = strlenW( buffer ); + char name[16]; + len = sprintf( name, "Key 0x%02x", vkey ); + len = min( len + 1, size ); + ascii_to_unicode( buffer, name, len ); + if (len) buffer[--len] = 0; }
TRACE( "lparam 0x%08x -> %s\n", lparam, debugstr_w( buffer ));
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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
Shouldn't the reference to the android driver also be removed from init_driver() in mmdevapi?
On 6/6/22 20:37, Zebediah Figura wrote:
Shouldn't the reference to the android driver also be removed from init_driver() in mmdevapi?
Right, I created a follow-up MR194 for that.
Thanks,
Jacek
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 ); } }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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; }
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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) {
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
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@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 ); }
Looks ok to me, although I haven't built or tested it.
This merge request was approved by Huw Davies.