-- v2: wineoss: Use mmdevapi's AudioClient's Initialize. winecoreaudio: Use mmdevapi's AudioClient's Initialize. winealsa: Use mmdevapi's AudioClient's Initialize. winepulse: Move AudioClient's Initialize into mmdevapi. wineoss: Implement main_loop in unixlib. winecoreaudio: Implement main_loop in unixlib. winealsa: Implement main_loop in unixlib.
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winealsa.drv/alsa.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index dbf85a7947e..4930850e9dc 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -476,6 +476,13 @@ static WCHAR *alsa_get_card_name(int card) return ret; }
+static NTSTATUS alsa_main_loop(void *args) +{ + struct main_loop_params *params = args; + NtSetEvent(params->event, NULL); + return STATUS_SUCCESS; +} + static NTSTATUS alsa_get_endpoint_ids(void *args) { static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; @@ -2493,7 +2500,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = { alsa_not_implemented, alsa_not_implemented, - alsa_not_implemented, + alsa_main_loop, alsa_get_endpoint_ids, alsa_create_stream, alsa_release_stream, @@ -2531,6 +2538,19 @@ unixlib_entry_t __wine_unix_call_funcs[] =
typedef UINT PTR32;
+static NTSTATUS alsa_wow64_main_loop(void *args) +{ + struct + { + PTR32 event; + } *params32 = args; + struct main_loop_params params = + { + .event = ULongToHandle(params32->event) + }; + return alsa_main_loop(¶ms); +} + static NTSTATUS alsa_wow64_get_endpoint_ids(void *args) { struct @@ -2934,7 +2954,7 @@ unixlib_entry_t __wine_unix_call_wow64_funcs[] = { alsa_not_implemented, alsa_not_implemented, - alsa_not_implemented, + alsa_wow64_main_loop, alsa_wow64_get_endpoint_ids, alsa_wow64_create_stream, alsa_wow64_release_stream,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winecoreaudio.drv/coreaudio.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index d031b82583e..f41118e62f5 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -196,6 +196,13 @@ static BOOL device_has_channels(AudioDeviceID device, EDataFlow flow) return ret; }
+static NTSTATUS unix_main_loop(void *args) +{ + struct main_loop_params *params = args; + NtSetEvent(params->event, NULL); + return STATUS_SUCCESS; +} + static NTSTATUS unix_get_endpoint_ids(void *args) { struct get_endpoint_ids_params *params = args; @@ -1775,7 +1782,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = { unix_not_implemented, unix_not_implemented, - unix_not_implemented, + unix_main_loop, unix_get_endpoint_ids, unix_create_stream, unix_release_stream, @@ -1813,6 +1820,19 @@ unixlib_entry_t __wine_unix_call_funcs[] =
typedef UINT PTR32;
+static NTSTATUS unix_wow64_main_loop(void *args) +{ + struct + { + PTR32 event; + } *params32 = args; + struct main_loop_params params = + { + .event = ULongToHandle(params32->event) + }; + return unix_main_loop(¶ms); +} + static NTSTATUS unix_wow64_get_endpoint_ids(void *args) { struct @@ -2157,7 +2177,7 @@ unixlib_entry_t __wine_unix_call_wow64_funcs[] = { unix_not_implemented, unix_not_implemented, - unix_not_implemented, + unix_wow64_main_loop, unix_wow64_get_endpoint_ids, unix_wow64_create_stream, unix_wow64_release_stream,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/wineoss.drv/oss.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index df03d3286d9..5049c711e98 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -221,6 +221,13 @@ static void get_default_device(EDataFlow flow, char device[OSS_DEVNODE_SIZE]) return; }
+static NTSTATUS oss_main_loop(void *args) +{ + struct main_loop_params *params = args; + NtSetEvent(params->event, NULL); + return STATUS_SUCCESS; +} + static NTSTATUS oss_get_endpoint_ids(void *args) { struct get_endpoint_ids_params *params = args; @@ -1684,7 +1691,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = { oss_not_implemented, oss_not_implemented, - oss_not_implemented, + oss_main_loop, oss_get_endpoint_ids, oss_create_stream, oss_release_stream, @@ -1738,6 +1745,19 @@ static NTSTATUS oss_wow64_test_connect(void *args) return STATUS_SUCCESS; }
+static NTSTATUS oss_wow64_main_loop(void *args) +{ + struct + { + PTR32 event; + } *params32 = args; + struct main_loop_params params = + { + .event = ULongToHandle(params32->event) + }; + return oss_main_loop(¶ms); +} + static NTSTATUS oss_wow64_get_endpoint_ids(void *args) { struct @@ -2108,7 +2128,7 @@ unixlib_entry_t __wine_unix_call_wow64_funcs[] = { oss_not_implemented, oss_not_implemented, - oss_not_implemented, + oss_wow64_main_loop, oss_wow64_get_endpoint_ids, oss_wow64_create_stream, oss_wow64_release_stream,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/Makefile.in | 2 +- dlls/mmdevapi/audiosessionmanager.c | 6 + dlls/mmdevapi/client.c | 255 +++++++++++++++++++++++++ dlls/mmdevapi/main.c | 2 + dlls/mmdevapi/mmdevapi_private.h | 2 + dlls/winealsa.drv/Makefile.in | 2 +- dlls/winealsa.drv/mmdevdrv.c | 2 +- dlls/winecoreaudio.drv/Makefile.in | 2 +- dlls/winecoreaudio.drv/mmdevdrv.c | 2 +- dlls/wineoss.drv/Makefile.in | 2 +- dlls/wineoss.drv/mmdevdrv.c | 2 +- dlls/winepulse.drv/mmdevdrv.c | 277 +--------------------------- dlls/winepulse.drv/pulse.c | 9 +- 13 files changed, 283 insertions(+), 282 deletions(-)
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in index ee2848ff2de..027854ea97b 100644 --- a/dlls/mmdevapi/Makefile.in +++ b/dlls/mmdevapi/Makefile.in @@ -1,5 +1,5 @@ MODULE = mmdevapi.dll -IMPORTS = uuid ole32 oleaut32 user32 advapi32 +IMPORTS = uuid ole32 oleaut32 user32 advapi32 version
C_SRCS = \ audiosessionmanager.c \ diff --git a/dlls/mmdevapi/audiosessionmanager.c b/dlls/mmdevapi/audiosessionmanager.c index 71799590e5e..dc0c5f609b7 100644 --- a/dlls/mmdevapi/audiosessionmanager.c +++ b/dlls/mmdevapi/audiosessionmanager.c @@ -47,6 +47,12 @@ void sessions_unlock(void) LeaveCriticalSection(&g_sessions_lock); }
+HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, + struct audio_session **out) +{ + return E_NOTIMPL; +} + static inline struct session_mgr *impl_from_IAudioSessionManager2(IAudioSessionManager2 *iface) { return CONTAINING_RECORD(iface, struct session_mgr, IAudioSessionManager2_iface); diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 03bfbabd536..dd0ab48544b 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -21,6 +21,8 @@
#define COBJMACROS
+#include <wchar.h> + #include <audiopolicy.h> #include <mmdeviceapi.h> #include <winternl.h> @@ -33,11 +35,29 @@
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
+typedef struct tagLANGANDCODEPAGE +{ + WORD wLanguage; + WORD wCodePage; +} LANGANDCODEPAGE; + extern void sessions_lock(void) DECLSPEC_HIDDEN; extern void sessions_unlock(void) DECLSPEC_HIDDEN;
+extern HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, + struct audio_session **out) DECLSPEC_HIDDEN; extern struct audio_session_wrapper *session_wrapper_create(struct audio_client *client) DECLSPEC_HIDDEN;
+static HANDLE main_loop_thread; + +void stop_main_loop(void) +{ + if (main_loop_thread) { + WaitForSingleObject(main_loop_thread, INFINITE); + CloseHandle(main_loop_thread); + } +} + void set_stream_volumes(struct audio_client *This) { struct set_volumes_params params; @@ -114,6 +134,19 @@ static void dump_fmt(const WAVEFORMATEX *fmt) } }
+static DWORD CALLBACK main_loop_func(void *event) +{ + struct main_loop_params params; + + SetThreadDescription(GetCurrentThread(), L"audio_client_main"); + + params.event = event; + + WINE_UNIX_CALL(main_loop, ¶ms); + + return 0; +} + static DWORD CALLBACK timer_loop_func(void *user) { struct timer_loop_params params; @@ -128,6 +161,117 @@ static DWORD CALLBACK timer_loop_func(void *user) return 0; }
+static HRESULT stream_release(stream_handle stream, HANDLE timer_thread) +{ + struct release_stream_params params; + + params.stream = stream; + params.timer_thread = timer_thread; + + WINE_UNIX_CALL(release_stream, ¶ms); + + return params.result; +} + +static BOOL query_productname(void *data, LANGANDCODEPAGE *lang, LPVOID *buffer, UINT *len) +{ + WCHAR pn[37]; + swprintf(pn, ARRAY_SIZE(pn), L"\StringFileInfo\%04x%04x\ProductName", lang->wLanguage, lang->wCodePage); + return VerQueryValueW(data, pn, buffer, len) && *len; +} + +static WCHAR *get_application_name(void) +{ + WCHAR path[MAX_PATH], *name; + UINT translate_size, productname_size; + LANGANDCODEPAGE *translate; + LPVOID productname; + BOOLEAN found = FALSE; + void *data = NULL; + unsigned int i; + LCID locale; + DWORD size; + + GetModuleFileNameW(NULL, path, ARRAY_SIZE(path)); + + size = GetFileVersionInfoSizeW(path, NULL); + if (!size) + goto skip; + + data = malloc(size); + if (!data) + goto skip; + + if (!GetFileVersionInfoW(path, 0, size, data)) + goto skip; + + if (!VerQueryValueW(data, L"\VarFileInfo\Translation", (LPVOID *)&translate, &translate_size)) + goto skip; + + /* No translations found. */ + if (translate_size < sizeof(LANGANDCODEPAGE)) + goto skip; + + /* The following code will try to find the best translation. We first search for an + * exact match of the language, then a match of the language PRIMARYLANGID, then we + * search for a LANG_NEUTRAL match, and if that still doesn't work we pick the + * first entry which contains a proper productname. */ + locale = GetThreadLocale(); + + for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); ++i) { + if (translate[i].wLanguage == locale && + query_productname(data, &translate[i], &productname, &productname_size)) { + found = TRUE; + break; + } + } + + if (!found) { + for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); ++i) { + if (PRIMARYLANGID(translate[i].wLanguage) == PRIMARYLANGID(locale) && + query_productname(data, &translate[i], &productname, &productname_size)) { + found = TRUE; + break; + } + } + } + + if (!found) { + for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); ++i) { + if (PRIMARYLANGID(translate[i].wLanguage) == LANG_NEUTRAL && + query_productname(data, &translate[i], &productname, &productname_size)) { + found = TRUE; + break; + } + } + } + + if (!found) { + for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); ++i) { + if (query_productname(data, &translate[i], &productname, &productname_size)) { + found = TRUE; + break; + } + } + } +skip: + if (found) { + name = wcsdup(productname); + free(data); + return name; + } + + free(data); + + name = wcsrchr(path, '\'); + if (!name) + name = path; + else + ++name; + + return wcsdup(name); +} + static HRESULT WINAPI capture_QueryInterface(IAudioCaptureClient *iface, REFIID riid, void **ppv) { struct audio_client *This = impl_from_IAudioCaptureClient(iface); @@ -244,6 +388,117 @@ const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl = capture_GetNextPacketSize };
+HRESULT WINAPI client_Initialize(IAudioClient3 *iface, AUDCLNT_SHAREMODE mode, DWORD flags, + REFERENCE_TIME duration, REFERENCE_TIME period, + const WAVEFORMATEX *fmt, const GUID *sessionguid) +{ + struct audio_client *This = impl_from_IAudioClient3(iface); + struct create_stream_params params; + unsigned int i, channel_count; + stream_handle stream; + WCHAR *name; + + TRACE("(%p)->(%x, %lx, %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: %08lx\n", flags); + return E_INVALIDARG; + } + + sessions_lock(); + + if (This->stream) { + sessions_unlock(); + return AUDCLNT_E_ALREADY_INITIALIZED; + } + + if (!main_loop_thread) { + HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); + if (!(main_loop_thread = CreateThread(NULL, 0, main_loop_func, event, 0, NULL))) + { + ERR("Failed to create main loop thread.\n"); + sessions_unlock(); + CloseHandle(event); + return E_FAIL; + } + + SetThreadPriority(main_loop_thread, THREAD_PRIORITY_TIME_CRITICAL); + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } + + channel_count = fmt->nChannels; + + params.name = name = get_application_name(); + params.device = This->device_name; + params.flow = This->dataflow; + params.share = mode; + params.flags = flags; + params.duration = duration; + params.period = period; + params.fmt = fmt; + params.channel_count = &channel_count; + params.stream = &stream; + + WINE_UNIX_CALL(create_stream, ¶ms); + + free(name); + + if (FAILED(params.result)) { + sessions_unlock(); + return params.result; + } + + if (!(This->vols = malloc(channel_count * sizeof(*This->vols)))) { + params.result = E_OUTOFMEMORY; + goto fail; + } + + for (i = 0; i < channel_count; ++i) + This->vols[i] = 1.f; + + params.result = get_audio_session(sessionguid, This->parent, channel_count, &This->session); + if (FAILED(params.result)) { + free(This->vols); + This->vols = NULL; + + goto fail; + } + + This->stream = stream; + This->channel_count = channel_count; + + list_add_tail(&This->session->clients, &This->entry); + + set_stream_volumes(This); + + return S_OK; +fail: + stream_release(stream, NULL); + sessions_unlock(); + + return params.result; +} + HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out) { struct audio_client *This = impl_from_IAudioClient3(iface); diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c index d3d4ec6a905..7647cd92bbf 100644 --- a/dlls/mmdevapi/main.c +++ b/dlls/mmdevapi/main.c @@ -196,6 +196,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DisableThreadLibraryCalls(hinstDLL); break; case DLL_PROCESS_DETACH: + stop_main_loop(); + if (drvs.module_unixlib) { const NTSTATUS status = __wine_unix_call(drvs.module_unixlib, process_detach, NULL); if (status) diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index 684d303eefb..4ae7de65fb8 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -80,4 +80,6 @@ extern HRESULT SpatialAudioClient_Create(IMMDevice *device, ISpatialAudioClient extern HRESULT load_devices_from_reg(void) DECLSPEC_HIDDEN; extern HRESULT load_driver_devices(EDataFlow flow) DECLSPEC_HIDDEN;
+extern void stop_main_loop(void) DECLSPEC_HIDDEN; + extern const WCHAR drv_keyW[] DECLSPEC_HIDDEN; diff --git a/dlls/winealsa.drv/Makefile.in b/dlls/winealsa.drv/Makefile.in index 9494858c4dd..d1387520742 100644 --- a/dlls/winealsa.drv/Makefile.in +++ b/dlls/winealsa.drv/Makefile.in @@ -1,6 +1,6 @@ MODULE = winealsa.drv UNIXLIB = winealsa.so -IMPORTS = uuid ole32 advapi32 +IMPORTS = uuid ole32 advapi32 version PARENTSRC = ../mmdevapi DELAYIMPORTS = winmm UNIX_LIBS = $(ALSA_LIBS) $(PTHREAD_LIBS) diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 7c7096d584a..df465522e06 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -526,7 +526,7 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
/* 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, +HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, AudioSession **out) { AudioSession *session; diff --git a/dlls/winecoreaudio.drv/Makefile.in b/dlls/winecoreaudio.drv/Makefile.in index 01c5a3d0073..ecf85cffda4 100644 --- a/dlls/winecoreaudio.drv/Makefile.in +++ b/dlls/winecoreaudio.drv/Makefile.in @@ -1,6 +1,6 @@ MODULE = winecoreaudio.drv UNIXLIB = winecoreaudio.so -IMPORTS = uuid ole32 user32 advapi32 +IMPORTS = uuid ole32 user32 advapi32 version PARENTSRC = ../mmdevapi DELAYIMPORTS = winmm UNIX_LIBS = $(COREAUDIO_LIBS) diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index f268e9565b4..50af5409d8a 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -512,7 +512,7 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
/* 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, +HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, AudioSession **out) { AudioSession *session; diff --git a/dlls/wineoss.drv/Makefile.in b/dlls/wineoss.drv/Makefile.in index 121595a7c6c..f571397257b 100644 --- a/dlls/wineoss.drv/Makefile.in +++ b/dlls/wineoss.drv/Makefile.in @@ -1,6 +1,6 @@ MODULE = wineoss.drv UNIXLIB = wineoss.so -IMPORTS = uuid ole32 user32 advapi32 +IMPORTS = uuid ole32 user32 advapi32 version PARENTSRC = ../mmdevapi DELAYIMPORTS = winmm UNIX_LIBS = $(OSS4_LIBS) $(PTHREAD_LIBS) diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 12f10fd4377..e03600d0923 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -501,7 +501,7 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
/* 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, +HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, AudioSession **out) { AudioSession *session; diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 12e36fae827..2d11e5e544f 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -56,7 +56,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(pulse);
#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
-static HANDLE pulse_thread; static struct list g_sessions = LIST_INIT(g_sessions); static struct list g_devices_cache = LIST_INIT(g_devices_cache);
@@ -115,11 +114,6 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
LIST_FOR_EACH_ENTRY_SAFE(device, device_next, &g_devices_cache, struct device_cache, entry) free(device); - - if (pulse_thread) { - WaitForSingleObject(pulse_thread, INFINITE); - CloseHandle(pulse_thread); - } } return TRUE; } @@ -157,134 +151,6 @@ static void pulse_release_stream(stream_handle stream, HANDLE timer) pulse_call(release_stream, ¶ms); }
-static DWORD CALLBACK pulse_mainloop_thread(void *event) -{ - struct main_loop_params params; - params.event = event; - SetThreadDescription(GetCurrentThread(), L"winepulse_mainloop"); - pulse_call(main_loop, ¶ms); - return 0; -} - -typedef struct tagLANGANDCODEPAGE -{ - WORD wLanguage; - WORD wCodePage; -} LANGANDCODEPAGE; - -static BOOL query_productname(void *data, LANGANDCODEPAGE *lang, LPVOID *buffer, UINT *len) -{ - WCHAR pn[37]; - swprintf(pn, ARRAY_SIZE(pn), L"\StringFileInfo\%04x%04x\ProductName", lang->wLanguage, lang->wCodePage); - return VerQueryValueW(data, pn, buffer, len) && *len; -} - -static WCHAR *get_application_name(BOOL query_app_name) -{ - WCHAR path[MAX_PATH], *name; - - GetModuleFileNameW(NULL, path, ARRAY_SIZE(path)); - - if (query_app_name) - { - UINT translate_size, productname_size; - LANGANDCODEPAGE *translate; - LPVOID productname; - BOOL found = FALSE; - void *data = NULL; - unsigned int i; - LCID locale; - DWORD size; - - size = GetFileVersionInfoSizeW(path, NULL); - if (!size) - goto skip; - - data = malloc(size); - if (!data) - goto skip; - - if (!GetFileVersionInfoW(path, 0, size, data)) - goto skip; - - if (!VerQueryValueW(data, L"\VarFileInfo\Translation", (LPVOID *)&translate, &translate_size)) - goto skip; - - /* no translations found */ - if (translate_size < sizeof(LANGANDCODEPAGE)) - goto skip; - - /* The following code will try to find the best translation. We first search for an - * exact match of the language, then a match of the language PRIMARYLANGID, then we - * search for a LANG_NEUTRAL match, and if that still doesn't work we pick the - * first entry which contains a proper productname. */ - locale = GetThreadLocale(); - - for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) { - if (translate[i].wLanguage == locale && - query_productname(data, &translate[i], &productname, &productname_size)) { - found = TRUE; - break; - } - } - - if (!found) { - for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) { - if (PRIMARYLANGID(translate[i].wLanguage) == PRIMARYLANGID(locale) && - query_productname(data, &translate[i], &productname, &productname_size)) { - found = TRUE; - break; - } - } - } - - if (!found) { - for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) { - if (PRIMARYLANGID(translate[i].wLanguage) == LANG_NEUTRAL && - query_productname(data, &translate[i], &productname, &productname_size)) { - found = TRUE; - break; - } - } - } - - if (!found) { - for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) { - if (query_productname(data, &translate[i], &productname, &productname_size)) { - found = TRUE; - break; - } - } - } - - skip: - if (found) - { - name = wcsdup(productname); - free(data); - return name; - } - free(data); - } - - name = wcsrchr(path, '\'); - if (!name) - name = path; - else - name++; - return wcsdup(name); -} - -static void set_stream_volumes(ACImpl *This) -{ - struct set_volumes_params params; - params.stream = This->stream; - params.master_volume = This->session->mute ? 0.0f : This->session->master_vol; - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - pulse_call(set_volumes, ¶ms); -} - static void get_device_guid(HKEY drv_key, EDataFlow flow, const char *pulse_name, GUID *guid) { WCHAR key_name[MAX_PULSE_NAME_LEN + 2]; @@ -577,40 +443,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) 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: %lu\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %lu\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: %08lx\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - static void session_init_vols(AudioSession *session, UINT channels) { if (session->channel_count < channels) { @@ -658,7 +490,7 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
/* 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, +HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, AudioSession **out) { AudioSession *session; @@ -690,111 +522,10 @@ static HRESULT get_audio_session(const GUID *sessionguid, return S_OK; }
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, +extern HRESULT WINAPI client_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); - struct create_stream_params params; - unsigned int i, channel_count; - stream_handle stream; - WCHAR *name; - HRESULT hr; - - TRACE("(%p)->(%x, %lx, %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 (mode == AUDCLNT_SHAREMODE_EXCLUSIVE) - return AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED; - - 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: %08lx\n", flags); - return E_INVALIDARG; - } - - sessions_lock(); - - if (This->stream) { - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - - if (!pulse_thread) - { - HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); - if (!(pulse_thread = CreateThread(NULL, 0, pulse_mainloop_thread, event, 0, NULL))) - { - ERR("Failed to create mainloop thread.\n"); - sessions_unlock(); - CloseHandle(event); - return E_FAIL; - } - SetThreadPriority(pulse_thread, THREAD_PRIORITY_TIME_CRITICAL); - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } - - params.name = name = get_application_name(TRUE); - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.stream = &stream; - params.channel_count = &channel_count; - pulse_call(create_stream, ¶ms); - free(name); - if (FAILED(hr = params.result)) - { - sessions_unlock(); - return hr; - } - - if (!(This->vols = malloc(channel_count * sizeof(*This->vols)))) - { - pulse_release_stream(stream, NULL); - sessions_unlock(); - return E_OUTOFMEMORY; - } - for (i = 0; i < channel_count; i++) - This->vols[i] = 1.f; - - hr = get_audio_session(sessionguid, This->parent, channel_count, &This->session); - if (FAILED(hr)) - { - free(This->vols); - This->vols = NULL; - sessions_unlock(); - pulse_release_stream(stream, NULL); - return E_OUTOFMEMORY; - } - - This->stream = stream; - This->channel_count = channel_count; - list_add_tail(&This->session->clients, &This->entry); - set_stream_volumes(This); - - sessions_unlock(); - return S_OK; -} + const GUID *sessionguid);
extern HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out); @@ -853,7 +584,7 @@ static const IAudioClient3Vtbl AudioClient3_Vtbl = AudioClient_QueryInterface, AudioClient_AddRef, AudioClient_Release, - AudioClient_Initialize, + client_Initialize, client_GetBufferSize, client_GetStreamLatency, client_GetCurrentPadding, diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 5ba66a8aa1d..ed56e6a11d3 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -1116,12 +1116,17 @@ static NTSTATUS pulse_create_stream(void *args) struct pulse_stream *stream; unsigned int i, bufsize_bytes; HRESULT hr; - char *name = wstr_to_str(params->name); + char *name; + + if (params->share == AUDCLNT_SHAREMODE_EXCLUSIVE) { + params->result = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED; + return STATUS_SUCCESS; + }
pulse_lock();
+ name = wstr_to_str(params->name); params->result = pulse_connect(name); - free(name);
if (FAILED(params->result))
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winealsa.drv/mmdevdrv.c | 137 +---------------------------------- 1 file changed, 3 insertions(+), 134 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index df465522e06..ceec2537eb0 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -207,18 +207,6 @@ static void get_device_guid(EDataFlow flow, const char *device, GUID *guid) RegCloseKey(key); }
-static void set_stream_volumes(ACImpl *This) -{ - struct set_volumes_params params; - - params.stream = This->stream; - params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol); - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - - ALSA_CALL(set_volumes, ¶ms); -} - HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, GUID **guids_out, UINT *num, UINT *def_index) { @@ -445,40 +433,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) 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: %lu\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %lu\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: %08lx\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - static void session_init_vols(AudioSession *session, UINT channels) { if(session->channel_count < channels){ @@ -558,95 +512,10 @@ HRESULT get_audio_session(const GUID *sessionguid, return S_OK; }
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, +extern HRESULT WINAPI client_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); - struct create_stream_params params; - stream_handle stream; - unsigned int i; - - TRACE("(%p)->(%x, %lx, %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; - - 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: %08lx\n", flags); - return E_INVALIDARG; - } - - sessions_lock(); - - if(This->stream){ - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - - dump_fmt(fmt); - - params.name = NULL; - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.channel_count = NULL; - params.stream = &stream; - - ALSA_CALL(create_stream, ¶ms); - if(FAILED(params.result)){ - sessions_unlock(); - return params.result; - } - - This->channel_count = fmt->nChannels; - This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float)); - if(!This->vols){ - params.result = E_OUTOFMEMORY; - goto exit; - } - for(i = 0; i < This->channel_count; ++i) - This->vols[i] = 1.f; - - params.result = get_audio_session(sessionguid, This->parent, This->channel_count, - &This->session); - if(FAILED(params.result)) - goto exit; - - list_add_tail(&This->session->clients, &This->entry); - -exit: - if(FAILED(params.result)){ - alsa_stream_release(stream, NULL); - HeapFree(GetProcessHeap(), 0, This->vols); - This->vols = NULL; - }else{ - This->stream = stream; - set_stream_volumes(This); - } - - sessions_unlock(); - - return params.result; -} + const GUID *sessionguid);
extern HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out); @@ -705,7 +574,7 @@ static const IAudioClient3Vtbl AudioClient3_Vtbl = AudioClient_QueryInterface, AudioClient_AddRef, AudioClient_Release, - AudioClient_Initialize, + client_Initialize, client_GetBufferSize, client_GetStreamLatency, client_GetCurrentPadding,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winecoreaudio.drv/mmdevdrv.c | 139 +----------------------------- 1 file changed, 3 insertions(+), 136 deletions(-)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 50af5409d8a..8e712867d1b 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -192,18 +192,6 @@ static void get_device_guid(EDataFlow flow, const char *dev, GUID *guid) RegCloseKey(key); }
-static void set_stream_volumes(ACImpl *This) -{ - struct set_volumes_params params; - - params.stream = This->stream; - params.master_volume = This->session->mute ? 0.0f : This->session->master_vol; - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - - UNIX_CALL(set_volumes, ¶ms); -} - HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, GUID **guids_out, UINT *num, UINT *def_index) { @@ -431,40 +419,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) 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: %lu\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %lu\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: %08lx\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - static void session_init_vols(AudioSession *session, UINT channels) { if(session->channel_count < channels){ @@ -544,97 +498,10 @@ HRESULT get_audio_session(const GUID *sessionguid, return S_OK; }
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, +extern HRESULT WINAPI client_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); - struct release_stream_params release_params; - struct create_stream_params params; - stream_handle stream; - UINT32 i; - - TRACE("(%p)->(%x, %lx, %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: %08lx\n", flags); - return E_INVALIDARG; - } - - sessions_lock(); - - if(This->stream){ - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - - params.name = NULL; - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.channel_count = NULL; - params.stream = &stream; - - UNIX_CALL(create_stream, ¶ms); - if(FAILED(params.result)){ - sessions_unlock(); - return params.result; - } - - This->channel_count = fmt->nChannels; - - This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float)); - if(!This->vols){ - params.result = E_OUTOFMEMORY; - goto end; - } - - for(i = 0; i < This->channel_count; ++i) - This->vols[i] = 1.f; - - params.result = get_audio_session(sessionguid, This->parent, fmt->nChannels, &This->session); - if(FAILED(params.result)) goto end; - - list_add_tail(&This->session->clients, &This->entry); - -end: - if(FAILED(params.result)){ - release_params.stream = stream; - UNIX_CALL(release_stream, &release_params); - HeapFree(GetProcessHeap(), 0, This->vols); - This->vols = NULL; - }else{ - This->stream = stream; - set_stream_volumes(This); - } - - sessions_unlock(); - - return params.result; -} + const GUID *sessionguid);
extern HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *frames); @@ -693,7 +560,7 @@ static const IAudioClient3Vtbl AudioClient3_Vtbl = AudioClient_QueryInterface, AudioClient_AddRef, AudioClient_Release, - AudioClient_Initialize, + client_Initialize, client_GetBufferSize, client_GetStreamLatency, client_GetCurrentPadding,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/wineoss.drv/mmdevdrv.c | 133 +----------------------------------- 1 file changed, 3 insertions(+), 130 deletions(-)
diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index e03600d0923..4ef6248c26b 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -220,17 +220,6 @@ static void get_device_guid(EDataFlow flow, const char *device, GUID *guid) RegCloseKey(key); }
-static void set_stream_volumes(ACImpl *This) -{ - struct set_volumes_params params; - - params.stream = This->stream; - params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol); - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - OSS_CALL(set_volumes, ¶ms); -} - static const OSSDevice *get_ossdevice_from_guid(const GUID *guid) { OSSDevice *dev_item; @@ -420,40 +409,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) 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: %lu\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %lu\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: %08lx\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - static void session_init_vols(AudioSession *session, UINT channels) { if(session->channel_count < channels){ @@ -533,92 +488,10 @@ HRESULT get_audio_session(const GUID *sessionguid, return S_OK; }
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, +extern HRESULT WINAPI client_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); - struct create_stream_params params; - stream_handle stream; - unsigned int i; - - TRACE("(%p)->(%x, %lx, %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: %08lx\n", flags); - return E_INVALIDARG; - } - - sessions_lock(); - - if(This->stream){ - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - - params.name = NULL; - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.channel_count = NULL; - params.stream = &stream; - - OSS_CALL(create_stream, ¶ms); - if(FAILED(params.result)){ - sessions_unlock(); - return params.result; - } - - This->channel_count = fmt->nChannels; - This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float)); - if(!This->vols){ - params.result = E_OUTOFMEMORY; - goto exit; - } - for(i = 0; i < This->channel_count; ++i) - This->vols[i] = 1.f; - - params.result = get_audio_session(sessionguid, This->parent, This->channel_count, - &This->session); - -exit: - if(FAILED(params.result)){ - stream_release(stream, NULL); - HeapFree(GetProcessHeap(), 0, This->vols); - This->vols = NULL; - } else { - list_add_tail(&This->session->clients, &This->entry); - This->stream = stream; - set_stream_volumes(This); - } - - sessions_unlock(); - - return params.result; -} + const GUID *sessionguid);
extern HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *frames); @@ -677,7 +550,7 @@ static const IAudioClient3Vtbl AudioClient3_Vtbl = AudioClient_QueryInterface, AudioClient_AddRef, AudioClient_Release, - AudioClient_Initialize, + client_Initialize, client_GetBufferSize, client_GetStreamLatency, client_GetCurrentPadding,
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133624
Your paranoid android.
=== debian11 (32 bit report) ===
amstream: amstream: Timeout
qcap: audiorecord: Timeout
windows.media.speech: speech: Timeout
winmm: capture: Timeout mci: Timeout wave: Timeout
wmp: media: Timeout oleobj: Timeout
xaudio2_7: xaudio2: Timeout
xaudio2_8: xaudio2: Timeout
On Fri Jun 9 08:41:58 2023 +0000, Huw Davies wrote:
These failures look suspicious
We are calling `NtSetEvent()` in the main loop for all drivers though...
On Fri Jun 9 09:26:33 2023 +0000, Davide Beatrici wrote:
We are calling `NtSetEvent()` in the main loop for all drivers though...
I just realized the same failures happened in !2855.
Is perhaps `WaitForSingleObject()` not returning if the thread is already stopped? That would be very bad.
On Fri Jun 9 09:49:59 2023 +0000, Davide Beatrici wrote:
I just realized the same failures happened in !2855. Missing `sessions_unlock()` call in case of success in `Initialize()`.
I have always been running only `mmdevapi_test.exe`'s collection locally, which doesn't exhibit the issue...