winex11: Create a global vulkan instance for xrandr.
[wine.git] / dlls / winepulse.drv / pulse.c
blob068245f03b23783561f7ef7fc5445606da6d27a0
1 /*
2 * Copyright 2011-2012 Maarten Lankhorst
3 * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers
4 * Copyright 2011 Andrew Eikum for CodeWeavers
5 * Copyright 2022 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #if 0
23 #pragma makedep unix
24 #endif
26 #include <stdarg.h>
27 #include <pthread.h>
28 #include <math.h>
29 #include <poll.h>
31 #include <pulse/pulseaudio.h>
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "winternl.h"
37 #include "mmdeviceapi.h"
38 #include "initguid.h"
39 #include "audioclient.h"
41 #include "wine/debug.h"
42 #include "wine/list.h"
43 #include "wine/unixlib.h"
45 #include "../mmdevapi/unixlib.h"
47 #include "mult.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(pulse);
51 enum phys_device_bus_type {
52 phys_device_bus_invalid = -1,
53 phys_device_bus_pci,
54 phys_device_bus_usb
57 struct pulse_stream
59 EDataFlow dataflow;
61 pa_stream *stream;
62 pa_sample_spec ss;
63 pa_channel_map map;
64 pa_buffer_attr attr;
66 DWORD flags;
67 AUDCLNT_SHAREMODE share;
68 HANDLE event;
69 float vol[PA_CHANNELS_MAX];
71 REFERENCE_TIME def_period;
73 INT32 locked;
74 BOOL started;
75 SIZE_T bufsize_frames, real_bufsize_bytes, period_bytes;
76 SIZE_T peek_ofs, read_offs_bytes, lcl_offs_bytes, pa_offs_bytes;
77 SIZE_T tmp_buffer_bytes, held_bytes, peek_len, peek_buffer_len, pa_held_bytes;
78 BYTE *local_buffer, *tmp_buffer, *peek_buffer;
79 void *locked_ptr;
80 BOOL please_quit, just_started, just_underran;
81 pa_usec_t mmdev_period_usec;
83 INT64 clock_lastpos, clock_written;
85 struct list packet_free_head;
86 struct list packet_filled_head;
89 typedef struct _ACPacket
91 struct list entry;
92 UINT64 qpcpos;
93 BYTE *data;
94 UINT32 discont;
95 } ACPacket;
97 typedef struct _PhysDevice {
98 struct list entry;
99 WCHAR *name;
100 enum phys_device_bus_type bus_type;
101 USHORT vendor_id, product_id;
102 EndpointFormFactor form;
103 UINT channel_mask;
104 UINT index;
105 REFERENCE_TIME min_period, def_period;
106 WAVEFORMATEXTENSIBLE fmt;
107 char pulse_name[0];
108 } PhysDevice;
110 static pa_context *pulse_ctx;
111 static pa_mainloop *pulse_ml;
113 static struct list g_phys_speakers = LIST_INIT(g_phys_speakers);
114 static struct list g_phys_sources = LIST_INIT(g_phys_sources);
116 static pthread_mutex_t pulse_mutex;
117 static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
119 static ULONG_PTR zero_bits = 0;
121 static NTSTATUS pulse_not_implemented(void *args)
123 return STATUS_SUCCESS;
126 static void pulse_lock(void)
128 pthread_mutex_lock(&pulse_mutex);
131 static void pulse_unlock(void)
133 pthread_mutex_unlock(&pulse_mutex);
136 static int pulse_cond_wait(void)
138 return pthread_cond_wait(&pulse_cond, &pulse_mutex);
141 static void pulse_broadcast(void)
143 pthread_cond_broadcast(&pulse_cond);
146 static struct pulse_stream *handle_get_stream(stream_handle h)
148 return (struct pulse_stream *)(UINT_PTR)h;
151 static void dump_attr(const pa_buffer_attr *attr)
153 TRACE("maxlength: %u\n", attr->maxlength);
154 TRACE("minreq: %u\n", attr->minreq);
155 TRACE("fragsize: %u\n", attr->fragsize);
156 TRACE("tlength: %u\n", attr->tlength);
157 TRACE("prebuf: %u\n", attr->prebuf);
160 static void free_phys_device_lists(void)
162 static struct list *const lists[] = { &g_phys_speakers, &g_phys_sources, NULL };
163 struct list *const *list = lists;
164 PhysDevice *dev, *dev_next;
166 do {
167 LIST_FOR_EACH_ENTRY_SAFE(dev, dev_next, *list, PhysDevice, entry) {
168 free(dev->name);
169 free(dev);
171 } while (*(++list));
174 /* copied from kernelbase */
175 static int muldiv(int a, int b, int c)
177 LONGLONG ret;
179 if (!c) return -1;
181 /* We want to deal with a positive divisor to simplify the logic. */
182 if (c < 0)
184 a = -a;
185 c = -c;
188 /* If the result is positive, we "add" to round. else, we subtract to round. */
189 if ((a < 0 && b < 0) || (a >= 0 && b >= 0))
190 ret = (((LONGLONG)a * b) + (c / 2)) / c;
191 else
192 ret = (((LONGLONG)a * b) - (c / 2)) / c;
194 if (ret > 2147483647 || ret < -2147483647) return -1;
195 return ret;
198 static char *wstr_to_str(const WCHAR *wstr)
200 const int len = wcslen(wstr);
201 char *str = malloc(len * 3 + 1);
202 ntdll_wcstoumbs(wstr, len + 1, str, len * 3 + 1, FALSE);
203 return str;
206 /* Following pulseaudio design here, mainloop has the lock taken whenever
207 * it is handling something for pulse, and the lock is required whenever
208 * doing any pa_* call that can affect the state in any way
210 * pa_cond_wait is used when waiting on results, because the mainloop needs
211 * the same lock taken to affect the state
213 * This is basically the same as the pa_threaded_mainloop implementation,
214 * but that cannot be used because it uses pthread_create directly
216 * pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock
217 * pa_threaded_mainloop_signal -> pthread_cond_broadcast
218 * pa_threaded_mainloop_wait -> pthread_cond_wait
220 static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata)
222 int r;
223 pulse_unlock();
224 r = poll(ufds, nfds, timeout);
225 pulse_lock();
226 return r;
229 static NTSTATUS pulse_process_attach(void *args)
231 pthread_mutexattr_t attr;
233 pthread_mutexattr_init(&attr);
234 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
236 if (pthread_mutex_init(&pulse_mutex, &attr) != 0)
237 pthread_mutex_init(&pulse_mutex, NULL);
239 #ifdef _WIN64
240 if (NtCurrentTeb()->WowTebOffset)
242 SYSTEM_BASIC_INFORMATION info;
244 NtQuerySystemInformation(SystemEmulationBasicInformation, &info, sizeof(info), NULL);
245 zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff;
247 #endif
249 return STATUS_SUCCESS;
252 static NTSTATUS pulse_process_detach(void *args)
254 free_phys_device_lists();
255 if (pulse_ctx)
257 pa_context_disconnect(pulse_ctx);
258 pa_context_unref(pulse_ctx);
260 if (pulse_ml)
261 pa_mainloop_quit(pulse_ml, 0);
263 return STATUS_SUCCESS;
266 static NTSTATUS pulse_main_loop(void *args)
268 struct main_loop_params *params = args;
269 int ret;
270 pulse_lock();
271 pulse_ml = pa_mainloop_new();
272 pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
273 NtSetEvent(params->event, NULL);
274 pa_mainloop_run(pulse_ml, &ret);
275 pa_mainloop_free(pulse_ml);
276 pulse_unlock();
277 return STATUS_SUCCESS;
280 static NTSTATUS pulse_get_endpoint_ids(void *args)
282 struct get_endpoint_ids_params *params = args;
283 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
284 struct endpoint *endpoint = params->endpoints;
285 size_t len, name_len, needed;
286 unsigned int offset;
287 PhysDevice *dev;
289 params->num = list_count(list);
290 offset = needed = params->num * sizeof(*params->endpoints);
292 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
293 name_len = lstrlenW(dev->name) + 1;
294 len = strlen(dev->pulse_name) + 1;
295 needed += name_len * sizeof(WCHAR) + ((len + 1) & ~1);
297 if (needed <= params->size) {
298 endpoint->name = offset;
299 memcpy((char *)params->endpoints + offset, dev->name, name_len * sizeof(WCHAR));
300 offset += name_len * sizeof(WCHAR);
301 endpoint->device = offset;
302 memcpy((char *)params->endpoints + offset, dev->pulse_name, len);
303 offset += (len + 1) & ~1;
304 endpoint++;
307 params->default_idx = 0;
309 if (needed > params->size) {
310 params->size = needed;
311 params->result = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
312 } else
313 params->result = S_OK;
314 return STATUS_SUCCESS;
317 static void pulse_contextcallback(pa_context *c, void *userdata)
319 switch (pa_context_get_state(c)) {
320 default:
321 FIXME("Unhandled state: %i\n", pa_context_get_state(c));
322 return;
324 case PA_CONTEXT_CONNECTING:
325 case PA_CONTEXT_UNCONNECTED:
326 case PA_CONTEXT_AUTHORIZING:
327 case PA_CONTEXT_SETTING_NAME:
328 case PA_CONTEXT_TERMINATED:
329 TRACE("State change to %i\n", pa_context_get_state(c));
330 return;
332 case PA_CONTEXT_READY:
333 TRACE("Ready\n");
334 break;
336 case PA_CONTEXT_FAILED:
337 WARN("Context failed: %s\n", pa_strerror(pa_context_errno(c)));
338 break;
340 pulse_broadcast();
343 static void pulse_stream_state(pa_stream *s, void *user)
345 pa_stream_state_t state = pa_stream_get_state(s);
346 TRACE("Stream state changed to %i\n", state);
347 pulse_broadcast();
350 static void pulse_attr_update(pa_stream *s, void *user) {
351 const pa_buffer_attr *attr = pa_stream_get_buffer_attr(s);
352 TRACE("New attributes or device moved:\n");
353 dump_attr(attr);
356 static void pulse_underflow_callback(pa_stream *s, void *userdata)
358 struct pulse_stream *stream = userdata;
359 WARN("%p: Underflow\n", userdata);
360 stream->just_underran = TRUE;
363 static void pulse_started_callback(pa_stream *s, void *userdata)
365 TRACE("%p: (Re)started playing\n", userdata);
368 static void pulse_op_cb(pa_stream *s, int success, void *user)
370 TRACE("Success: %i\n", success);
371 *(int*)user = success;
372 pulse_broadcast();
375 static void silence_buffer(pa_sample_format_t format, BYTE *buffer, UINT32 bytes)
377 memset(buffer, format == PA_SAMPLE_U8 ? 0x80 : 0, bytes);
380 static BOOL pulse_stream_valid(struct pulse_stream *stream)
382 return pa_stream_get_state(stream->stream) == PA_STREAM_READY;
385 static HRESULT pulse_connect(const char *name)
387 pa_context_state_t state;
389 if (pulse_ctx && PA_CONTEXT_IS_GOOD(pa_context_get_state(pulse_ctx)))
390 return S_OK;
391 if (pulse_ctx)
392 pa_context_unref(pulse_ctx);
394 pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), name);
395 if (!pulse_ctx) {
396 ERR("Failed to create context\n");
397 return E_FAIL;
400 pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL);
402 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION);
403 if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0)
404 goto fail;
406 /* Wait for connection */
407 while ((state = pa_context_get_state(pulse_ctx)) != PA_CONTEXT_READY &&
408 state != PA_CONTEXT_FAILED && state != PA_CONTEXT_TERMINATED)
409 pulse_cond_wait();
411 if (state != PA_CONTEXT_READY)
412 goto fail;
414 TRACE("Connected to server %s with protocol version: %i.\n",
415 pa_context_get_server(pulse_ctx),
416 pa_context_get_server_protocol_version(pulse_ctx));
417 return S_OK;
419 fail:
420 pa_context_unref(pulse_ctx);
421 pulse_ctx = NULL;
422 return E_FAIL;
425 static UINT pulse_channel_map_to_channel_mask(const pa_channel_map *map)
427 int i;
428 UINT mask = 0;
430 for (i = 0; i < map->channels; ++i) {
431 switch (map->map[i]) {
432 default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map->map[i])); break;
433 case PA_CHANNEL_POSITION_FRONT_LEFT: mask |= SPEAKER_FRONT_LEFT; break;
434 case PA_CHANNEL_POSITION_MONO:
435 case PA_CHANNEL_POSITION_FRONT_CENTER: mask |= SPEAKER_FRONT_CENTER; break;
436 case PA_CHANNEL_POSITION_FRONT_RIGHT: mask |= SPEAKER_FRONT_RIGHT; break;
437 case PA_CHANNEL_POSITION_REAR_LEFT: mask |= SPEAKER_BACK_LEFT; break;
438 case PA_CHANNEL_POSITION_REAR_CENTER: mask |= SPEAKER_BACK_CENTER; break;
439 case PA_CHANNEL_POSITION_REAR_RIGHT: mask |= SPEAKER_BACK_RIGHT; break;
440 case PA_CHANNEL_POSITION_LFE: mask |= SPEAKER_LOW_FREQUENCY; break;
441 case PA_CHANNEL_POSITION_SIDE_LEFT: mask |= SPEAKER_SIDE_LEFT; break;
442 case PA_CHANNEL_POSITION_SIDE_RIGHT: mask |= SPEAKER_SIDE_RIGHT; break;
443 case PA_CHANNEL_POSITION_TOP_CENTER: mask |= SPEAKER_TOP_CENTER; break;
444 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: mask |= SPEAKER_TOP_FRONT_LEFT; break;
445 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: mask |= SPEAKER_TOP_FRONT_CENTER; break;
446 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: mask |= SPEAKER_TOP_FRONT_RIGHT; break;
447 case PA_CHANNEL_POSITION_TOP_REAR_LEFT: mask |= SPEAKER_TOP_BACK_LEFT; break;
448 case PA_CHANNEL_POSITION_TOP_REAR_CENTER: mask |= SPEAKER_TOP_BACK_CENTER; break;
449 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: mask |= SPEAKER_TOP_BACK_RIGHT; break;
450 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: mask |= SPEAKER_FRONT_LEFT_OF_CENTER; break;
451 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: mask |= SPEAKER_FRONT_RIGHT_OF_CENTER; break;
455 return mask;
458 #define MAX_DEVICE_NAME_LEN 62
460 static WCHAR *get_device_name(const char *desc, pa_proplist *proplist)
463 Some broken apps (e.g. Split/Second with fmodex) can't handle names that
464 are too long and crash even on native. If the device desc is too long,
465 we'll attempt to incrementally build it to try to stay under the limit.
466 ( + 1 is to check against truncated buffer after ntdll_umbstowcs )
468 WCHAR buf[MAX_DEVICE_NAME_LEN + 1];
470 /* For monitors of sinks; this does not seem to be localized in PA either */
471 static const WCHAR monitor_of[] = {'M','o','n','i','t','o','r',' ','o','f',' '};
473 size_t len = strlen(desc);
474 WCHAR *name, *tmp;
476 if (!(name = malloc((len + 1) * sizeof(WCHAR))))
477 return NULL;
478 if (!(len = ntdll_umbstowcs(desc, len, name, len))) {
479 free(name);
480 return NULL;
483 if (len > MAX_DEVICE_NAME_LEN && proplist) {
484 const char *prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS);
485 unsigned prop_len, rem = ARRAY_SIZE(buf);
486 BOOL monitor = FALSE;
488 if (prop && !strcmp(prop, "monitor")) {
489 rem -= ARRAY_SIZE(monitor_of);
490 monitor = TRUE;
493 prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME);
494 if (!prop || !prop[0] ||
495 !(prop_len = ntdll_umbstowcs(prop, strlen(prop), buf, rem)) || prop_len == rem) {
496 prop = pa_proplist_gets(proplist, "alsa.card_name");
497 if (!prop || !prop[0] ||
498 !(prop_len = ntdll_umbstowcs(prop, strlen(prop), buf, rem)) || prop_len == rem)
499 prop = NULL;
502 if (prop) {
503 /* We know we have a name that fits within the limit now */
504 WCHAR *p = name;
506 if (monitor) {
507 memcpy(p, monitor_of, sizeof(monitor_of));
508 p += ARRAY_SIZE(monitor_of);
510 len = ntdll_umbstowcs(prop, strlen(prop), p, rem);
511 rem -= len;
512 p += len;
514 if (rem > 2) {
515 rem--; /* space */
517 prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
518 if (prop && prop[0] && (len = ntdll_umbstowcs(prop, strlen(prop), p + 1, rem)) && len != rem) {
519 *p++ = ' ';
520 p += len;
523 len = p - name;
526 name[len] = '\0';
528 if ((tmp = realloc(name, (len + 1) * sizeof(WCHAR))))
529 name = tmp;
530 return name;
533 static void fill_device_info(PhysDevice *dev, pa_proplist *p)
535 const char *buffer;
537 dev->bus_type = phys_device_bus_invalid;
538 dev->vendor_id = 0;
539 dev->product_id = 0;
541 if (!p)
542 return;
544 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
545 if (!strcmp(buffer, "usb"))
546 dev->bus_type = phys_device_bus_usb;
547 else if (!strcmp(buffer, "pci"))
548 dev->bus_type = phys_device_bus_pci;
551 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID)))
552 dev->vendor_id = strtol(buffer, NULL, 16);
554 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID)))
555 dev->product_id = strtol(buffer, NULL, 16);
558 static void pulse_add_device(struct list *list, pa_proplist *proplist, int index, EndpointFormFactor form,
559 UINT channel_mask, const char *pulse_name, const char *desc)
561 size_t len = strlen(pulse_name);
562 PhysDevice *dev = malloc(FIELD_OFFSET(PhysDevice, pulse_name[len + 1]));
564 if (!dev)
565 return;
567 if (!(dev->name = get_device_name(desc, proplist))) {
568 free(dev);
569 return;
571 dev->form = form;
572 dev->index = index;
573 dev->channel_mask = channel_mask;
574 dev->def_period = 0;
575 dev->min_period = 0;
576 fill_device_info(dev, proplist);
577 memcpy(dev->pulse_name, pulse_name, len + 1);
579 list_add_tail(list, &dev->entry);
581 TRACE("%s\n", debugstr_w(dev->name));
584 static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
586 struct list *speaker;
587 UINT channel_mask;
589 if (!i || !i->name || !i->name[0])
590 return;
591 channel_mask = pulse_channel_map_to_channel_mask(&i->channel_map);
593 /* For default PulseAudio render device, OR together all of the
594 * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
595 speaker = list_head(&g_phys_speakers);
596 if (speaker)
597 LIST_ENTRY(speaker, PhysDevice, entry)->channel_mask |= channel_mask;
599 pulse_add_device(&g_phys_speakers, i->proplist, i->index, Speakers, channel_mask, i->name, i->description);
602 static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
604 if (!i || !i->name || !i->name[0])
605 return;
606 pulse_add_device(&g_phys_sources, i->proplist, i->index,
607 (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel, 0, i->name, i->description);
610 /* For most hardware on Windows, users must choose a configuration with an even
611 * number of channels (stereo, quad, 5.1, 7.1). Users can then disable
612 * channels, but those channels are still reported to applications from
613 * GetMixFormat! Some applications behave badly if given an odd number of
614 * channels (e.g. 2.1). Here, we find the nearest configuration that Windows
615 * would report for a given channel layout. */
616 static void convert_channel_map(const pa_channel_map *pa_map, WAVEFORMATEXTENSIBLE *fmt)
618 UINT pa_mask = pulse_channel_map_to_channel_mask(pa_map);
620 TRACE("got mask for PA: 0x%x\n", pa_mask);
622 if (pa_map->channels == 1)
624 fmt->Format.nChannels = 1;
625 fmt->dwChannelMask = pa_mask;
626 return;
629 /* compare against known configurations and find smallest configuration
630 * which is a superset of the given speakers */
632 if (pa_map->channels <= 2 &&
633 (pa_mask & ~KSAUDIO_SPEAKER_STEREO) == 0)
635 fmt->Format.nChannels = 2;
636 fmt->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
637 return;
640 if (pa_map->channels <= 4 &&
641 (pa_mask & ~KSAUDIO_SPEAKER_QUAD) == 0)
643 fmt->Format.nChannels = 4;
644 fmt->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
645 return;
648 if (pa_map->channels <= 4 &&
649 (pa_mask & ~KSAUDIO_SPEAKER_SURROUND) == 0)
651 fmt->Format.nChannels = 4;
652 fmt->dwChannelMask = KSAUDIO_SPEAKER_SURROUND;
653 return;
656 if (pa_map->channels <= 6 &&
657 (pa_mask & ~KSAUDIO_SPEAKER_5POINT1) == 0)
659 fmt->Format.nChannels = 6;
660 fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
661 return;
664 if (pa_map->channels <= 6 &&
665 (pa_mask & ~KSAUDIO_SPEAKER_5POINT1_SURROUND) == 0)
667 fmt->Format.nChannels = 6;
668 fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND;
669 return;
672 if (pa_map->channels <= 8 &&
673 (pa_mask & ~KSAUDIO_SPEAKER_7POINT1) == 0)
675 fmt->Format.nChannels = 8;
676 fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1;
677 return;
680 if (pa_map->channels <= 8 &&
681 (pa_mask & ~KSAUDIO_SPEAKER_7POINT1_SURROUND) == 0)
683 fmt->Format.nChannels = 8;
684 fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND;
685 return;
688 /* oddball format, report truthfully */
689 fmt->Format.nChannels = pa_map->channels;
690 fmt->dwChannelMask = pa_mask;
693 static void pulse_probe_settings(int render, const char *pulse_name, WAVEFORMATEXTENSIBLE *fmt, REFERENCE_TIME *def_period, REFERENCE_TIME *min_period)
695 WAVEFORMATEX *wfx = &fmt->Format;
696 pa_stream *stream;
697 pa_channel_map map;
698 pa_sample_spec ss;
699 pa_buffer_attr attr;
700 int ret;
701 unsigned int length = 0;
703 if (pulse_name && !pulse_name[0])
704 pulse_name = NULL;
706 pa_channel_map_init_auto(&map, 2, PA_CHANNEL_MAP_ALSA);
707 ss.rate = 48000;
708 ss.format = PA_SAMPLE_FLOAT32LE;
709 ss.channels = map.channels;
711 attr.maxlength = -1;
712 attr.tlength = -1;
713 attr.minreq = attr.fragsize = pa_frame_size(&ss);
714 attr.prebuf = 0;
716 stream = pa_stream_new(pulse_ctx, "format test stream", &ss, &map);
717 if (stream)
718 pa_stream_set_state_callback(stream, pulse_stream_state, NULL);
719 if (!stream)
720 ret = -1;
721 else if (render)
722 ret = pa_stream_connect_playback(stream, pulse_name, &attr,
723 PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS, NULL, NULL);
724 else
725 ret = pa_stream_connect_record(stream, pulse_name, &attr, PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS);
726 if (ret >= 0) {
727 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
728 pa_stream_get_state(stream) == PA_STREAM_CREATING)
730 if (pa_stream_get_state(stream) == PA_STREAM_READY) {
731 ss = *pa_stream_get_sample_spec(stream);
732 map = *pa_stream_get_channel_map(stream);
733 if (render)
734 length = pa_stream_get_buffer_attr(stream)->minreq;
735 else
736 length = pa_stream_get_buffer_attr(stream)->fragsize;
737 pa_stream_disconnect(stream);
738 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
739 pa_stream_get_state(stream) == PA_STREAM_READY)
744 if (stream)
745 pa_stream_unref(stream);
747 if (length)
748 *def_period = *min_period = pa_bytes_to_usec(10 * length, &ss);
750 wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
751 wfx->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
753 convert_channel_map(&map, fmt);
755 wfx->wBitsPerSample = 8 * pa_sample_size_of_format(ss.format);
756 wfx->nSamplesPerSec = ss.rate;
757 wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8;
758 wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign;
759 if (ss.format != PA_SAMPLE_S24_32LE)
760 fmt->Samples.wValidBitsPerSample = wfx->wBitsPerSample;
761 else
762 fmt->Samples.wValidBitsPerSample = 24;
763 if (ss.format == PA_SAMPLE_FLOAT32LE)
764 fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
765 else
766 fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
769 /* some poorly-behaved applications call audio functions during DllMain, so we
770 * have to do as much as possible without creating a new thread. this function
771 * sets up a synchronous connection to verify the server is running and query
772 * static data. */
773 static NTSTATUS pulse_test_connect(void *args)
775 struct test_connect_params *params = args;
776 PhysDevice *dev;
777 pa_operation *o;
778 int ret;
779 char *name = wstr_to_str(params->name);
781 pulse_lock();
782 pulse_ml = pa_mainloop_new();
784 pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
786 pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), name);
788 free(name);
790 if (!pulse_ctx) {
791 ERR("Failed to create context\n");
792 pa_mainloop_free(pulse_ml);
793 pulse_ml = NULL;
794 pulse_unlock();
795 params->priority = Priority_Unavailable;
796 return STATUS_SUCCESS;
799 pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL);
801 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION);
802 if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0)
803 goto fail;
805 /* Wait for connection */
806 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0) {
807 pa_context_state_t state = pa_context_get_state(pulse_ctx);
809 if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
810 goto fail;
812 if (state == PA_CONTEXT_READY)
813 break;
816 if (pa_context_get_state(pulse_ctx) != PA_CONTEXT_READY)
817 goto fail;
819 TRACE("Test-connected to server %s with protocol version: %i.\n",
820 pa_context_get_server(pulse_ctx),
821 pa_context_get_server_protocol_version(pulse_ctx));
823 free_phys_device_lists();
824 list_init(&g_phys_speakers);
825 list_init(&g_phys_sources);
827 /* Burnout Paradise Remastered expects device name to have a space. */
828 pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, 0, "", "PulseAudio Output");
829 pulse_add_device(&g_phys_sources, NULL, 0, Microphone, 0, "", "PulseAudio Input");
831 o = pa_context_get_sink_info_list(pulse_ctx, &pulse_phys_speakers_cb, NULL);
832 if (o) {
833 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
834 pa_operation_get_state(o) == PA_OPERATION_RUNNING)
836 pa_operation_unref(o);
839 o = pa_context_get_source_info_list(pulse_ctx, &pulse_phys_sources_cb, NULL);
840 if (o) {
841 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
842 pa_operation_get_state(o) == PA_OPERATION_RUNNING)
844 pa_operation_unref(o);
847 LIST_FOR_EACH_ENTRY(dev, &g_phys_speakers, PhysDevice, entry) {
848 pulse_probe_settings(1, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
851 LIST_FOR_EACH_ENTRY(dev, &g_phys_sources, PhysDevice, entry) {
852 pulse_probe_settings(0, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
855 pa_context_unref(pulse_ctx);
856 pulse_ctx = NULL;
857 pa_mainloop_free(pulse_ml);
858 pulse_ml = NULL;
860 pulse_unlock();
862 params->priority = Priority_Preferred;
863 return STATUS_SUCCESS;
865 fail:
866 pa_context_unref(pulse_ctx);
867 pulse_ctx = NULL;
868 pa_mainloop_free(pulse_ml);
869 pulse_ml = NULL;
870 pulse_unlock();
871 params->priority = Priority_Unavailable;
872 return STATUS_SUCCESS;
875 static UINT get_channel_mask(unsigned int channels)
877 switch(channels) {
878 case 0:
879 return 0;
880 case 1:
881 return KSAUDIO_SPEAKER_MONO;
882 case 2:
883 return KSAUDIO_SPEAKER_STEREO;
884 case 3:
885 return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
886 case 4:
887 return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
888 case 5:
889 return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
890 case 6:
891 return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
892 case 7:
893 return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
894 case 8:
895 return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
897 FIXME("Unknown speaker configuration: %u\n", channels);
898 return 0;
901 static const enum pa_channel_position pulse_pos_from_wfx[] = {
902 PA_CHANNEL_POSITION_FRONT_LEFT,
903 PA_CHANNEL_POSITION_FRONT_RIGHT,
904 PA_CHANNEL_POSITION_FRONT_CENTER,
905 PA_CHANNEL_POSITION_LFE,
906 PA_CHANNEL_POSITION_REAR_LEFT,
907 PA_CHANNEL_POSITION_REAR_RIGHT,
908 PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
909 PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
910 PA_CHANNEL_POSITION_REAR_CENTER,
911 PA_CHANNEL_POSITION_SIDE_LEFT,
912 PA_CHANNEL_POSITION_SIDE_RIGHT,
913 PA_CHANNEL_POSITION_TOP_CENTER,
914 PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
915 PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
916 PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
917 PA_CHANNEL_POSITION_TOP_REAR_LEFT,
918 PA_CHANNEL_POSITION_TOP_REAR_CENTER,
919 PA_CHANNEL_POSITION_TOP_REAR_RIGHT
922 static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAVEFORMATEX *fmt)
924 pa_channel_map_init(&stream->map);
925 stream->ss.rate = fmt->nSamplesPerSec;
926 stream->ss.format = PA_SAMPLE_INVALID;
928 switch(fmt->wFormatTag) {
929 case WAVE_FORMAT_IEEE_FLOAT:
930 if (!fmt->nChannels || fmt->nChannels > 2 || fmt->wBitsPerSample != 32)
931 break;
932 stream->ss.format = PA_SAMPLE_FLOAT32LE;
933 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
934 break;
935 case WAVE_FORMAT_PCM:
936 if (!fmt->nChannels || fmt->nChannels > 2)
937 break;
938 if (fmt->wBitsPerSample == 8)
939 stream->ss.format = PA_SAMPLE_U8;
940 else if (fmt->wBitsPerSample == 16)
941 stream->ss.format = PA_SAMPLE_S16LE;
942 else
943 return AUDCLNT_E_UNSUPPORTED_FORMAT;
944 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
945 break;
946 case WAVE_FORMAT_EXTENSIBLE: {
947 WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE*)fmt;
948 UINT mask = wfe->dwChannelMask;
949 unsigned i = 0, j;
950 if (fmt->cbSize != (sizeof(*wfe) - sizeof(*fmt)) && fmt->cbSize != sizeof(*wfe))
951 break;
952 if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
953 (!wfe->Samples.wValidBitsPerSample || wfe->Samples.wValidBitsPerSample == 32) &&
954 fmt->wBitsPerSample == 32)
955 stream->ss.format = PA_SAMPLE_FLOAT32LE;
956 else if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
957 DWORD valid = wfe->Samples.wValidBitsPerSample;
958 if (!valid)
959 valid = fmt->wBitsPerSample;
960 if (!valid || valid > fmt->wBitsPerSample)
961 break;
962 switch (fmt->wBitsPerSample) {
963 case 8:
964 if (valid == 8)
965 stream->ss.format = PA_SAMPLE_U8;
966 break;
967 case 16:
968 if (valid == 16)
969 stream->ss.format = PA_SAMPLE_S16LE;
970 break;
971 case 24:
972 if (valid == 24)
973 stream->ss.format = PA_SAMPLE_S24LE;
974 break;
975 case 32:
976 if (valid == 24)
977 stream->ss.format = PA_SAMPLE_S24_32LE;
978 else if (valid == 32)
979 stream->ss.format = PA_SAMPLE_S32LE;
980 break;
981 default:
982 return AUDCLNT_E_UNSUPPORTED_FORMAT;
985 stream->map.channels = fmt->nChannels;
986 if (!mask || (mask & (SPEAKER_ALL|SPEAKER_RESERVED)))
987 mask = get_channel_mask(fmt->nChannels);
988 for (j = 0; j < ARRAY_SIZE(pulse_pos_from_wfx) && i < fmt->nChannels; ++j) {
989 if (mask & (1 << j))
990 stream->map.map[i++] = pulse_pos_from_wfx[j];
993 /* Special case for mono since pulse appears to map it differently */
994 if (mask == SPEAKER_FRONT_CENTER)
995 stream->map.map[0] = PA_CHANNEL_POSITION_MONO;
997 if (i < fmt->nChannels || (mask & SPEAKER_RESERVED)) {
998 stream->map.channels = 0;
999 ERR("Invalid channel mask: %i/%i and %x(%x)\n", i, fmt->nChannels, mask, (unsigned)wfe->dwChannelMask);
1000 break;
1002 break;
1004 case WAVE_FORMAT_ALAW:
1005 case WAVE_FORMAT_MULAW:
1006 if (fmt->wBitsPerSample != 8) {
1007 FIXME("Unsupported bpp %u for LAW\n", fmt->wBitsPerSample);
1008 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1010 if (fmt->nChannels != 1 && fmt->nChannels != 2) {
1011 FIXME("Unsupported channels %u for LAW\n", fmt->nChannels);
1012 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1014 stream->ss.format = fmt->wFormatTag == WAVE_FORMAT_MULAW ? PA_SAMPLE_ULAW : PA_SAMPLE_ALAW;
1015 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
1016 break;
1017 default:
1018 WARN("Unhandled tag %x\n", fmt->wFormatTag);
1019 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1021 stream->ss.channels = stream->map.channels;
1022 if (!pa_channel_map_valid(&stream->map) || stream->ss.format == PA_SAMPLE_INVALID) {
1023 ERR("Invalid format! Channel spec valid: %i, format: %i\n",
1024 pa_channel_map_valid(&stream->map), stream->ss.format);
1025 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1027 return S_OK;
1030 static HRESULT pulse_stream_connect(struct pulse_stream *stream, const char *pulse_name, UINT32 period_bytes)
1032 pa_stream_flags_t flags = PA_STREAM_START_CORKED | PA_STREAM_START_UNMUTED | PA_STREAM_ADJUST_LATENCY;
1033 int ret;
1034 char buffer[64];
1035 static LONG number;
1036 pa_buffer_attr attr;
1038 ret = InterlockedIncrement(&number);
1039 sprintf(buffer, "audio stream #%i", ret);
1040 stream->stream = pa_stream_new(pulse_ctx, buffer, &stream->ss, &stream->map);
1042 if (!stream->stream) {
1043 WARN("pa_stream_new returned error %i\n", pa_context_errno(pulse_ctx));
1044 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1047 pa_stream_set_state_callback(stream->stream, pulse_stream_state, stream);
1048 pa_stream_set_buffer_attr_callback(stream->stream, pulse_attr_update, stream);
1049 pa_stream_set_moved_callback(stream->stream, pulse_attr_update, stream);
1051 /* PulseAudio will fill in correct values */
1052 attr.minreq = attr.fragsize = period_bytes;
1053 attr.tlength = period_bytes * 3;
1054 attr.maxlength = stream->bufsize_frames * pa_frame_size(&stream->ss);
1055 attr.prebuf = pa_frame_size(&stream->ss);
1056 dump_attr(&attr);
1058 /* If specific device was requested, use it exactly */
1059 if (pulse_name[0])
1060 flags |= PA_STREAM_DONT_MOVE;
1061 else
1062 pulse_name = NULL; /* use default */
1064 if (stream->dataflow == eRender)
1065 ret = pa_stream_connect_playback(stream->stream, pulse_name, &attr, flags, NULL, NULL);
1066 else
1067 ret = pa_stream_connect_record(stream->stream, pulse_name, &attr, flags);
1068 if (ret < 0) {
1069 WARN("Returns %i\n", ret);
1070 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1072 while (pa_stream_get_state(stream->stream) == PA_STREAM_CREATING)
1073 pulse_cond_wait();
1074 if (pa_stream_get_state(stream->stream) != PA_STREAM_READY)
1075 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1077 if (stream->dataflow == eRender) {
1078 pa_stream_set_underflow_callback(stream->stream, pulse_underflow_callback, stream);
1079 pa_stream_set_started_callback(stream->stream, pulse_started_callback, stream);
1081 return S_OK;
1084 static HRESULT get_device_period_helper(EDataFlow flow, const char *pulse_name, REFERENCE_TIME *def, REFERENCE_TIME *min)
1086 struct list *list = (flow == eRender) ? &g_phys_speakers : &g_phys_sources;
1087 PhysDevice *dev;
1089 if (!def && !min) {
1090 return E_POINTER;
1093 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
1094 if (strcmp(pulse_name, dev->pulse_name))
1095 continue;
1097 if (def)
1098 *def = dev->def_period;
1099 if (min)
1100 *min = dev->min_period;
1101 return S_OK;
1104 return E_FAIL;
1107 static NTSTATUS pulse_create_stream(void *args)
1109 struct create_stream_params *params = args;
1110 struct pulse_stream *stream;
1111 unsigned int i, bufsize_bytes;
1112 HRESULT hr;
1113 char *name;
1115 if (params->share == AUDCLNT_SHAREMODE_EXCLUSIVE) {
1116 params->result = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
1117 return STATUS_SUCCESS;
1120 pulse_lock();
1122 name = wstr_to_str(params->name);
1123 params->result = pulse_connect(name);
1124 free(name);
1126 if (FAILED(params->result))
1128 pulse_unlock();
1129 return STATUS_SUCCESS;
1132 if (!(stream = calloc(1, sizeof(*stream))))
1134 pulse_unlock();
1135 params->result = E_OUTOFMEMORY;
1136 return STATUS_SUCCESS;
1139 stream->dataflow = params->flow;
1140 for (i = 0; i < ARRAY_SIZE(stream->vol); ++i)
1141 stream->vol[i] = 1.f;
1143 hr = pulse_spec_from_waveformat(stream, params->fmt);
1144 TRACE("Obtaining format returns %08x\n", (unsigned)hr);
1146 if (FAILED(hr))
1147 goto exit;
1149 stream->def_period = params->period;
1151 stream->period_bytes = pa_frame_size(&stream->ss) * muldiv(params->period,
1152 stream->ss.rate,
1153 10000000);
1155 stream->bufsize_frames = ceil((params->duration / 10000000.) * params->fmt->nSamplesPerSec);
1156 bufsize_bytes = stream->bufsize_frames * pa_frame_size(&stream->ss);
1157 stream->mmdev_period_usec = params->period / 10;
1159 stream->share = params->share;
1160 stream->flags = params->flags;
1161 hr = pulse_stream_connect(stream, params->device, stream->period_bytes);
1162 if (SUCCEEDED(hr)) {
1163 UINT32 unalign;
1164 const pa_buffer_attr *attr = pa_stream_get_buffer_attr(stream->stream);
1165 SIZE_T size;
1167 stream->attr = *attr;
1168 /* Update frames according to new size */
1169 dump_attr(attr);
1170 if (stream->dataflow == eRender) {
1171 size = stream->real_bufsize_bytes =
1172 stream->bufsize_frames * 2 * pa_frame_size(&stream->ss);
1173 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1174 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1175 hr = E_OUTOFMEMORY;
1176 } else {
1177 UINT32 i, capture_packets;
1179 if ((unalign = bufsize_bytes % stream->period_bytes))
1180 bufsize_bytes += stream->period_bytes - unalign;
1181 stream->bufsize_frames = bufsize_bytes / pa_frame_size(&stream->ss);
1182 stream->real_bufsize_bytes = bufsize_bytes;
1184 capture_packets = stream->real_bufsize_bytes / stream->period_bytes;
1186 size = stream->real_bufsize_bytes + capture_packets * sizeof(ACPacket);
1187 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1188 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1189 hr = E_OUTOFMEMORY;
1190 else {
1191 ACPacket *cur_packet = (ACPacket*)((char*)stream->local_buffer + stream->real_bufsize_bytes);
1192 BYTE *data = stream->local_buffer;
1193 silence_buffer(stream->ss.format, stream->local_buffer, stream->real_bufsize_bytes);
1194 list_init(&stream->packet_free_head);
1195 list_init(&stream->packet_filled_head);
1196 for (i = 0; i < capture_packets; ++i, ++cur_packet) {
1197 list_add_tail(&stream->packet_free_head, &cur_packet->entry);
1198 cur_packet->data = data;
1199 data += stream->period_bytes;
1205 *params->channel_count = stream->ss.channels;
1206 *params->stream = (stream_handle)(UINT_PTR)stream;
1208 exit:
1209 if (FAILED(params->result = hr)) {
1210 free(stream->local_buffer);
1211 if (stream->stream) {
1212 pa_stream_disconnect(stream->stream);
1213 pa_stream_unref(stream->stream);
1215 free(stream);
1218 pulse_unlock();
1219 return STATUS_SUCCESS;
1222 static NTSTATUS pulse_release_stream(void *args)
1224 struct release_stream_params *params = args;
1225 struct pulse_stream *stream = handle_get_stream(params->stream);
1226 SIZE_T size;
1228 if(params->timer_thread) {
1229 stream->please_quit = TRUE;
1230 NtWaitForSingleObject(params->timer_thread, FALSE, NULL);
1231 NtClose(params->timer_thread);
1234 pulse_lock();
1235 if (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream))) {
1236 pa_stream_disconnect(stream->stream);
1237 while (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream)))
1238 pulse_cond_wait();
1240 pa_stream_unref(stream->stream);
1241 pulse_unlock();
1243 if (stream->tmp_buffer) {
1244 size = 0;
1245 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1246 &size, MEM_RELEASE);
1248 if (stream->local_buffer) {
1249 size = 0;
1250 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1251 &size, MEM_RELEASE);
1253 free(stream->peek_buffer);
1254 free(stream);
1255 return STATUS_SUCCESS;
1258 static int write_buffer(const struct pulse_stream *stream, BYTE *buffer, UINT32 bytes)
1260 const float *vol = stream->vol;
1261 UINT32 i, channels, mute = 0;
1262 BOOL adjust = FALSE;
1263 BYTE *end;
1265 if (!bytes) return 0;
1267 /* Adjust the buffer based on the volume for each channel */
1268 channels = stream->ss.channels;
1269 for (i = 0; i < channels; i++)
1271 adjust |= vol[i] != 1.0f;
1272 if (vol[i] == 0.0f)
1273 mute++;
1275 if (mute == channels)
1277 silence_buffer(stream->ss.format, buffer, bytes);
1278 goto write;
1280 if (!adjust) goto write;
1282 end = buffer + bytes;
1283 switch (stream->ss.format)
1285 #ifndef WORDS_BIGENDIAN
1286 #define PROCESS_BUFFER(type) do \
1288 type *p = (type*)buffer; \
1289 do \
1291 for (i = 0; i < channels; i++) \
1292 p[i] = p[i] * vol[i]; \
1293 p += i; \
1294 } while ((BYTE*)p != end); \
1295 } while (0)
1296 case PA_SAMPLE_S16LE:
1297 PROCESS_BUFFER(INT16);
1298 break;
1299 case PA_SAMPLE_S32LE:
1300 PROCESS_BUFFER(INT32);
1301 break;
1302 case PA_SAMPLE_FLOAT32LE:
1303 PROCESS_BUFFER(float);
1304 break;
1305 #undef PROCESS_BUFFER
1306 case PA_SAMPLE_S24_32LE:
1308 UINT32 *p = (UINT32*)buffer;
1311 for (i = 0; i < channels; i++)
1313 p[i] = (INT32)((INT32)(p[i] << 8) * vol[i]);
1314 p[i] >>= 8;
1316 p += i;
1317 } while ((BYTE*)p != end);
1318 break;
1320 case PA_SAMPLE_S24LE:
1322 /* do it 12 bytes at a time until it is no longer possible */
1323 UINT32 *q = (UINT32*)buffer;
1324 BYTE *p;
1326 i = 0;
1327 while (end - (BYTE*)q >= 12)
1329 UINT32 v[4], k;
1330 v[0] = q[0] << 8;
1331 v[1] = q[1] << 16 | (q[0] >> 16 & ~0xff);
1332 v[2] = q[2] << 24 | (q[1] >> 8 & ~0xff);
1333 v[3] = q[2] & ~0xff;
1334 for (k = 0; k < 4; k++)
1336 v[k] = (INT32)((INT32)v[k] * vol[i]);
1337 if (++i == channels) i = 0;
1339 *q++ = v[0] >> 8 | (v[1] & ~0xff) << 16;
1340 *q++ = v[1] >> 16 | (v[2] & ~0xff) << 8;
1341 *q++ = v[2] >> 24 | (v[3] & ~0xff);
1343 p = (BYTE*)q;
1344 while (p != end)
1346 UINT32 v = (INT32)((INT32)(p[0] << 8 | p[1] << 16 | p[2] << 24) * vol[i]);
1347 *p++ = v >> 8 & 0xff;
1348 *p++ = v >> 16 & 0xff;
1349 *p++ = v >> 24;
1350 if (++i == channels) i = 0;
1352 break;
1354 #endif
1355 case PA_SAMPLE_U8:
1357 UINT8 *p = (UINT8*)buffer;
1360 for (i = 0; i < channels; i++)
1361 p[i] = (int)((p[i] - 128) * vol[i]) + 128;
1362 p += i;
1363 } while ((BYTE*)p != end);
1364 break;
1366 case PA_SAMPLE_ALAW:
1368 UINT8 *p = (UINT8*)buffer;
1371 for (i = 0; i < channels; i++)
1372 p[i] = mult_alaw_sample(p[i], vol[i]);
1373 p += i;
1374 } while ((BYTE*)p != end);
1375 break;
1377 case PA_SAMPLE_ULAW:
1379 UINT8 *p = (UINT8*)buffer;
1382 for (i = 0; i < channels; i++)
1383 p[i] = mult_ulaw_sample(p[i], vol[i]);
1384 p += i;
1385 } while ((BYTE*)p != end);
1386 break;
1388 default:
1389 TRACE("Unhandled format %i, not adjusting volume.\n", stream->ss.format);
1390 break;
1393 write:
1394 return pa_stream_write(stream->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
1397 static void pulse_write(struct pulse_stream *stream)
1399 /* write as much data to PA as we can */
1400 UINT32 to_write;
1401 BYTE *buf = stream->local_buffer + stream->pa_offs_bytes;
1402 UINT32 bytes = pa_stream_writable_size(stream->stream);
1404 if (stream->just_underran)
1406 /* prebuffer with silence if needed */
1407 if(stream->pa_held_bytes < bytes){
1408 to_write = bytes - stream->pa_held_bytes;
1409 TRACE("prebuffering %u frames of silence\n",
1410 (int)(to_write / pa_frame_size(&stream->ss)));
1411 buf = calloc(1, to_write);
1412 pa_stream_write(stream->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
1413 free(buf);
1416 stream->just_underran = FALSE;
1419 buf = stream->local_buffer + stream->pa_offs_bytes;
1420 TRACE("held: %lu, avail: %u\n", stream->pa_held_bytes, bytes);
1421 bytes = min(stream->pa_held_bytes, bytes);
1423 if (stream->pa_offs_bytes + bytes > stream->real_bufsize_bytes)
1425 to_write = stream->real_bufsize_bytes - stream->pa_offs_bytes;
1426 TRACE("writing small chunk of %u bytes\n", to_write);
1427 write_buffer(stream, buf, to_write);
1428 stream->pa_held_bytes -= to_write;
1429 to_write = bytes - to_write;
1430 stream->pa_offs_bytes = 0;
1431 buf = stream->local_buffer;
1433 else
1434 to_write = bytes;
1436 TRACE("writing main chunk of %u bytes\n", to_write);
1437 write_buffer(stream, buf, to_write);
1438 stream->pa_offs_bytes += to_write;
1439 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1440 stream->pa_held_bytes -= to_write;
1443 static void pulse_read(struct pulse_stream *stream)
1445 size_t bytes = pa_stream_readable_size(stream->stream);
1447 TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(stream->stream)->fragsize);
1449 bytes += stream->peek_len - stream->peek_ofs;
1451 while (bytes >= stream->period_bytes)
1453 BYTE *dst = NULL, *src;
1454 size_t src_len, copy, rem = stream->period_bytes;
1456 if (stream->started)
1458 LARGE_INTEGER stamp, freq;
1459 ACPacket *p, *next;
1461 if (!(p = (ACPacket*)list_head(&stream->packet_free_head)))
1463 p = (ACPacket*)list_head(&stream->packet_filled_head);
1464 if (!p) return;
1465 if (!p->discont) {
1466 next = (ACPacket*)p->entry.next;
1467 next->discont = 1;
1468 } else
1469 p = (ACPacket*)list_tail(&stream->packet_filled_head);
1471 else
1473 stream->held_bytes += stream->period_bytes;
1475 NtQueryPerformanceCounter(&stamp, &freq);
1476 p->qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
1477 p->discont = 0;
1478 list_remove(&p->entry);
1479 list_add_tail(&stream->packet_filled_head, &p->entry);
1481 dst = p->data;
1484 while (rem)
1486 if (stream->peek_len)
1488 copy = min(rem, stream->peek_len - stream->peek_ofs);
1490 if (dst)
1492 memcpy(dst, stream->peek_buffer + stream->peek_ofs, copy);
1493 dst += copy;
1496 rem -= copy;
1497 stream->peek_ofs += copy;
1498 if(stream->peek_len == stream->peek_ofs)
1499 stream->peek_len = stream->peek_ofs = 0;
1502 else if (pa_stream_peek(stream->stream, (const void**)&src, &src_len) == 0 && src_len)
1504 copy = min(rem, src_len);
1506 if (dst) {
1507 if(src)
1508 memcpy(dst, src, copy);
1509 else
1510 silence_buffer(stream->ss.format, dst, copy);
1512 dst += copy;
1515 rem -= copy;
1517 if (copy < src_len)
1519 if (src_len > stream->peek_buffer_len)
1521 free(stream->peek_buffer);
1522 stream->peek_buffer = malloc(src_len);
1523 stream->peek_buffer_len = src_len;
1526 if(src)
1527 memcpy(stream->peek_buffer, src + copy, src_len - copy);
1528 else
1529 silence_buffer(stream->ss.format, stream->peek_buffer, src_len - copy);
1531 stream->peek_len = src_len - copy;
1532 stream->peek_ofs = 0;
1535 pa_stream_drop(stream->stream);
1539 bytes -= stream->period_bytes;
1543 static NTSTATUS pulse_timer_loop(void *args)
1545 struct timer_loop_params *params = args;
1546 struct pulse_stream *stream = handle_get_stream(params->stream);
1547 LARGE_INTEGER delay;
1548 pa_usec_t last_time;
1549 UINT32 adv_bytes;
1550 int success;
1551 pa_operation *o;
1553 pulse_lock();
1554 delay.QuadPart = -stream->mmdev_period_usec * 10;
1555 pa_stream_get_time(stream->stream, &last_time);
1556 pulse_unlock();
1558 while (!stream->please_quit)
1560 pa_usec_t now, adv_usec = 0;
1561 int err;
1563 NtDelayExecution(FALSE, &delay);
1565 pulse_lock();
1567 delay.QuadPart = -stream->mmdev_period_usec * 10;
1569 o = pa_stream_update_timing_info(stream->stream, pulse_op_cb, &success);
1570 if (o)
1572 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1573 pulse_cond_wait();
1574 pa_operation_unref(o);
1576 err = pa_stream_get_time(stream->stream, &now);
1577 if (err == 0)
1579 TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(last_time));
1580 if (stream->started && (stream->dataflow == eCapture || stream->held_bytes))
1582 if(stream->just_underran)
1584 last_time = now;
1585 stream->just_started = TRUE;
1588 if (stream->just_started)
1590 /* let it play out a period to absorb some latency and get accurate timing */
1591 pa_usec_t diff = now - last_time;
1593 if (diff > stream->mmdev_period_usec)
1595 stream->just_started = FALSE;
1596 last_time = now;
1599 else
1601 INT32 adjust = last_time + stream->mmdev_period_usec - now;
1603 adv_usec = now - last_time;
1605 if(adjust > ((INT32)(stream->mmdev_period_usec / 2)))
1606 adjust = stream->mmdev_period_usec / 2;
1607 else if(adjust < -((INT32)(stream->mmdev_period_usec / 2)))
1608 adjust = -1 * stream->mmdev_period_usec / 2;
1610 delay.QuadPart = -(stream->mmdev_period_usec + adjust) * 10;
1612 last_time += stream->mmdev_period_usec;
1615 if (stream->dataflow == eRender)
1617 pulse_write(stream);
1619 /* regardless of what PA does, advance one period */
1620 adv_bytes = min(stream->period_bytes, stream->held_bytes);
1621 stream->lcl_offs_bytes += adv_bytes;
1622 stream->lcl_offs_bytes %= stream->real_bufsize_bytes;
1623 stream->held_bytes -= adv_bytes;
1625 else if(stream->dataflow == eCapture)
1627 pulse_read(stream);
1630 else
1632 last_time = now;
1633 delay.QuadPart = -stream->mmdev_period_usec * 10;
1637 if (stream->event)
1638 NtSetEvent(stream->event, NULL);
1640 TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n",
1641 stream, (int)adv_usec,
1642 (int)(stream->held_bytes/ pa_frame_size(&stream->ss)),
1643 (unsigned int)(-delay.QuadPart / 10));
1645 pulse_unlock();
1648 return STATUS_SUCCESS;
1651 static NTSTATUS pulse_start(void *args)
1653 struct start_params *params = args;
1654 struct pulse_stream *stream = handle_get_stream(params->stream);
1655 int success;
1656 pa_operation *o;
1658 params->result = S_OK;
1659 pulse_lock();
1660 if (!pulse_stream_valid(stream))
1662 pulse_unlock();
1663 params->result = S_OK;
1664 return STATUS_SUCCESS;
1667 if ((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event)
1669 pulse_unlock();
1670 params->result = AUDCLNT_E_EVENTHANDLE_NOT_SET;
1671 return STATUS_SUCCESS;
1674 if (stream->started)
1676 pulse_unlock();
1677 params->result = AUDCLNT_E_NOT_STOPPED;
1678 return STATUS_SUCCESS;
1681 pulse_write(stream);
1683 if (pa_stream_is_corked(stream->stream))
1685 o = pa_stream_cork(stream->stream, 0, pulse_op_cb, &success);
1686 if (o)
1688 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1689 pulse_cond_wait();
1690 pa_operation_unref(o);
1692 else
1693 success = 0;
1694 if (!success)
1695 params->result = E_FAIL;
1698 if (SUCCEEDED(params->result))
1700 stream->started = TRUE;
1701 stream->just_started = TRUE;
1703 pulse_unlock();
1704 return STATUS_SUCCESS;
1707 static NTSTATUS pulse_stop(void *args)
1709 struct stop_params *params = args;
1710 struct pulse_stream *stream = handle_get_stream(params->stream);
1711 pa_operation *o;
1712 int success;
1714 pulse_lock();
1715 if (!pulse_stream_valid(stream))
1717 pulse_unlock();
1718 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1719 return STATUS_SUCCESS;
1722 if (!stream->started)
1724 pulse_unlock();
1725 params->result = S_FALSE;
1726 return STATUS_SUCCESS;
1729 params->result = S_OK;
1730 if (stream->dataflow == eRender)
1732 o = pa_stream_cork(stream->stream, 1, pulse_op_cb, &success);
1733 if (o)
1735 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1736 pulse_cond_wait();
1737 pa_operation_unref(o);
1739 else
1740 success = 0;
1741 if (!success)
1742 params->result = E_FAIL;
1744 if (SUCCEEDED(params->result))
1745 stream->started = FALSE;
1746 pulse_unlock();
1747 return STATUS_SUCCESS;
1750 static NTSTATUS pulse_reset(void *args)
1752 struct reset_params *params = args;
1753 struct pulse_stream *stream = handle_get_stream(params->stream);
1755 pulse_lock();
1756 if (!pulse_stream_valid(stream))
1758 pulse_unlock();
1759 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1760 return STATUS_SUCCESS;
1763 if (stream->started)
1765 pulse_unlock();
1766 params->result = AUDCLNT_E_NOT_STOPPED;
1767 return STATUS_SUCCESS;
1770 if (stream->locked)
1772 pulse_unlock();
1773 params->result = AUDCLNT_E_BUFFER_OPERATION_PENDING;
1774 return STATUS_SUCCESS;
1777 if (stream->dataflow == eRender)
1779 /* If there is still data in the render buffer it needs to be removed from the server */
1780 int success = 0;
1781 if (stream->held_bytes)
1783 pa_operation *o = pa_stream_flush(stream->stream, pulse_op_cb, &success);
1784 if (o)
1786 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1787 pulse_cond_wait();
1788 pa_operation_unref(o);
1791 if (success || !stream->held_bytes)
1793 stream->clock_lastpos = stream->clock_written = 0;
1794 stream->pa_offs_bytes = stream->lcl_offs_bytes = 0;
1795 stream->held_bytes = stream->pa_held_bytes = 0;
1798 else
1800 ACPacket *p;
1801 stream->clock_written += stream->held_bytes;
1802 stream->held_bytes = 0;
1804 if ((p = stream->locked_ptr))
1806 stream->locked_ptr = NULL;
1807 list_add_tail(&stream->packet_free_head, &p->entry);
1809 list_move_tail(&stream->packet_free_head, &stream->packet_filled_head);
1811 pulse_unlock();
1812 params->result = S_OK;
1813 return STATUS_SUCCESS;
1816 static BOOL alloc_tmp_buffer(struct pulse_stream *stream, SIZE_T bytes)
1818 SIZE_T size;
1820 if (stream->tmp_buffer_bytes >= bytes)
1821 return TRUE;
1823 if (stream->tmp_buffer)
1825 size = 0;
1826 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1827 &size, MEM_RELEASE);
1828 stream->tmp_buffer = NULL;
1829 stream->tmp_buffer_bytes = 0;
1831 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1832 zero_bits, &bytes, MEM_COMMIT, PAGE_READWRITE))
1833 return FALSE;
1835 stream->tmp_buffer_bytes = bytes;
1836 return TRUE;
1839 static UINT32 pulse_render_padding(struct pulse_stream *stream)
1841 return stream->held_bytes / pa_frame_size(&stream->ss);
1844 static UINT32 pulse_capture_padding(struct pulse_stream *stream)
1846 ACPacket *packet = stream->locked_ptr;
1847 if (!packet && !list_empty(&stream->packet_filled_head))
1849 packet = (ACPacket*)list_head(&stream->packet_filled_head);
1850 stream->locked_ptr = packet;
1851 list_remove(&packet->entry);
1853 return stream->held_bytes / pa_frame_size(&stream->ss);
1856 static NTSTATUS pulse_get_render_buffer(void *args)
1858 struct get_render_buffer_params *params = args;
1859 struct pulse_stream *stream = handle_get_stream(params->stream);
1860 size_t bytes;
1861 UINT32 wri_offs_bytes;
1863 pulse_lock();
1864 if (!pulse_stream_valid(stream))
1866 pulse_unlock();
1867 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1868 return STATUS_SUCCESS;
1871 if (stream->locked)
1873 pulse_unlock();
1874 params->result = AUDCLNT_E_OUT_OF_ORDER;
1875 return STATUS_SUCCESS;
1878 if (!params->frames)
1880 pulse_unlock();
1881 *params->data = NULL;
1882 params->result = S_OK;
1883 return STATUS_SUCCESS;
1886 if (stream->held_bytes / pa_frame_size(&stream->ss) + params->frames > stream->bufsize_frames)
1888 pulse_unlock();
1889 params->result = AUDCLNT_E_BUFFER_TOO_LARGE;
1890 return STATUS_SUCCESS;
1893 bytes = params->frames * pa_frame_size(&stream->ss);
1894 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1895 if (wri_offs_bytes + bytes > stream->real_bufsize_bytes)
1897 if (!alloc_tmp_buffer(stream, bytes))
1899 pulse_unlock();
1900 params->result = E_OUTOFMEMORY;
1901 return STATUS_SUCCESS;
1903 *params->data = stream->tmp_buffer;
1904 stream->locked = -bytes;
1906 else
1908 *params->data = stream->local_buffer + wri_offs_bytes;
1909 stream->locked = bytes;
1912 silence_buffer(stream->ss.format, *params->data, bytes);
1914 pulse_unlock();
1915 params->result = S_OK;
1916 return STATUS_SUCCESS;
1919 static void pulse_wrap_buffer(struct pulse_stream *stream, BYTE *buffer, UINT32 written_bytes)
1921 UINT32 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1922 UINT32 chunk_bytes = stream->real_bufsize_bytes - wri_offs_bytes;
1924 if (written_bytes <= chunk_bytes)
1926 memcpy(stream->local_buffer + wri_offs_bytes, buffer, written_bytes);
1928 else
1930 memcpy(stream->local_buffer + wri_offs_bytes, buffer, chunk_bytes);
1931 memcpy(stream->local_buffer, buffer + chunk_bytes, written_bytes - chunk_bytes);
1935 static NTSTATUS pulse_release_render_buffer(void *args)
1937 struct release_render_buffer_params *params = args;
1938 struct pulse_stream *stream = handle_get_stream(params->stream);
1939 UINT32 written_bytes;
1940 BYTE *buffer;
1942 pulse_lock();
1943 if (!stream->locked || !params->written_frames)
1945 stream->locked = 0;
1946 pulse_unlock();
1947 params->result = params->written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1948 return STATUS_SUCCESS;
1951 if (params->written_frames * pa_frame_size(&stream->ss) >
1952 (stream->locked >= 0 ? stream->locked : -stream->locked))
1954 pulse_unlock();
1955 params->result = AUDCLNT_E_INVALID_SIZE;
1956 return STATUS_SUCCESS;
1959 if (stream->locked >= 0)
1960 buffer = stream->local_buffer + (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1961 else
1962 buffer = stream->tmp_buffer;
1964 written_bytes = params->written_frames * pa_frame_size(&stream->ss);
1965 if (params->flags & AUDCLNT_BUFFERFLAGS_SILENT)
1966 silence_buffer(stream->ss.format, buffer, written_bytes);
1968 if (stream->locked < 0)
1969 pulse_wrap_buffer(stream, buffer, written_bytes);
1971 stream->held_bytes += written_bytes;
1972 stream->pa_held_bytes += written_bytes;
1973 if (stream->pa_held_bytes > stream->real_bufsize_bytes)
1975 stream->pa_offs_bytes += stream->pa_held_bytes - stream->real_bufsize_bytes;
1976 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1977 stream->pa_held_bytes = stream->real_bufsize_bytes;
1979 stream->clock_written += written_bytes;
1980 stream->locked = 0;
1982 /* push as much data as we can to pulseaudio too */
1983 pulse_write(stream);
1985 TRACE("Released %u, held %lu\n", params->written_frames, stream->held_bytes / pa_frame_size(&stream->ss));
1987 pulse_unlock();
1988 params->result = S_OK;
1989 return STATUS_SUCCESS;
1992 static NTSTATUS pulse_get_capture_buffer(void *args)
1994 struct get_capture_buffer_params *params = args;
1995 struct pulse_stream *stream = handle_get_stream(params->stream);
1996 ACPacket *packet;
1998 pulse_lock();
1999 if (!pulse_stream_valid(stream))
2001 pulse_unlock();
2002 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2003 return STATUS_SUCCESS;
2005 if (stream->locked)
2007 pulse_unlock();
2008 params->result = AUDCLNT_E_OUT_OF_ORDER;
2009 return STATUS_SUCCESS;
2012 pulse_capture_padding(stream);
2013 if ((packet = stream->locked_ptr))
2015 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2016 *params->flags = 0;
2017 if (packet->discont)
2018 *params->flags |= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY;
2019 if (params->devpos)
2021 if (packet->discont)
2022 *params->devpos = (stream->clock_written + stream->period_bytes) / pa_frame_size(&stream->ss);
2023 else
2024 *params->devpos = stream->clock_written / pa_frame_size(&stream->ss);
2026 if (params->qpcpos)
2027 *params->qpcpos = packet->qpcpos;
2028 *params->data = packet->data;
2030 else
2031 *params->frames = 0;
2032 stream->locked = *params->frames;
2033 pulse_unlock();
2034 params->result = *params->frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2035 return STATUS_SUCCESS;
2038 static NTSTATUS pulse_release_capture_buffer(void *args)
2040 struct release_capture_buffer_params *params = args;
2041 struct pulse_stream *stream = handle_get_stream(params->stream);
2043 pulse_lock();
2044 if (!stream->locked && params->done)
2046 pulse_unlock();
2047 params->result = AUDCLNT_E_OUT_OF_ORDER;
2048 return STATUS_SUCCESS;
2050 if (params->done && stream->locked != params->done)
2052 pulse_unlock();
2053 params->result = AUDCLNT_E_INVALID_SIZE;
2054 return STATUS_SUCCESS;
2056 if (params->done)
2058 ACPacket *packet = stream->locked_ptr;
2059 stream->locked_ptr = NULL;
2060 stream->held_bytes -= stream->period_bytes;
2061 if (packet->discont)
2062 stream->clock_written += 2 * stream->period_bytes;
2063 else
2064 stream->clock_written += stream->period_bytes;
2065 list_add_tail(&stream->packet_free_head, &packet->entry);
2067 stream->locked = 0;
2068 pulse_unlock();
2069 params->result = S_OK;
2070 return STATUS_SUCCESS;
2073 static NTSTATUS pulse_is_format_supported(void *args)
2075 struct is_format_supported_params *params = args;
2076 WAVEFORMATEXTENSIBLE in;
2077 WAVEFORMATEXTENSIBLE *out;
2078 const WAVEFORMATEX *fmt = &in.Format;
2079 const BOOLEAN exclusive = params->share == AUDCLNT_SHAREMODE_EXCLUSIVE;
2081 params->result = S_OK;
2083 if (!params->fmt_in || (params->share == AUDCLNT_SHAREMODE_SHARED && !params->fmt_out))
2084 params->result = E_POINTER;
2085 else if (params->share != AUDCLNT_SHAREMODE_SHARED && params->share != AUDCLNT_SHAREMODE_EXCLUSIVE)
2086 params->result = E_INVALIDARG;
2087 else {
2088 memcpy(&in, params->fmt_in, params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2089 sizeof(in) : sizeof(in.Format));
2091 if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
2092 if (fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
2093 params->result = E_INVALIDARG;
2094 else if (fmt->nAvgBytesPerSec == 0 || fmt->nBlockAlign == 0 ||
2095 (in.Samples.wValidBitsPerSample > fmt->wBitsPerSample))
2096 params->result = E_INVALIDARG;
2097 else if (fmt->nChannels == 0)
2098 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2102 if (FAILED(params->result))
2103 return STATUS_SUCCESS;
2105 if (exclusive)
2106 out = &in;
2107 else {
2108 out = params->fmt_out;
2109 memcpy(out, fmt, fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2110 sizeof(*out) : sizeof((*out).Format));
2113 switch (fmt->wFormatTag) {
2114 case WAVE_FORMAT_EXTENSIBLE: {
2115 if ((fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) &&
2116 fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE)) ||
2117 fmt->nBlockAlign != fmt->wBitsPerSample / 8 * fmt->nChannels ||
2118 in.Samples.wValidBitsPerSample > fmt->wBitsPerSample ||
2119 fmt->nAvgBytesPerSec != fmt->nBlockAlign * fmt->nSamplesPerSec) {
2120 params->result = E_INVALIDARG;
2121 break;
2124 if (exclusive) {
2125 UINT32 mask = 0, i, channels = 0;
2127 if (!(in.dwChannelMask & (SPEAKER_ALL | SPEAKER_RESERVED))) {
2128 for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) {
2129 if (i & in.dwChannelMask) {
2130 mask |= i;
2131 ++channels;
2135 if (channels != fmt->nChannels || (in.dwChannelMask & ~mask)) {
2136 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2137 break;
2139 } else {
2140 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2141 break;
2145 if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
2146 if (fmt->wBitsPerSample != 32) {
2147 params->result = E_INVALIDARG;
2148 break;
2151 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample) {
2152 params->result = S_FALSE;
2153 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2155 } else if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
2156 if (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8) {
2157 params->result = E_INVALIDARG;
2158 break;
2161 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample &&
2162 !(fmt->wBitsPerSample == 32 &&
2163 in.Samples.wValidBitsPerSample == 24)) {
2164 params->result = S_FALSE;
2165 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2166 break;
2168 } else {
2169 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2170 break;
2173 break;
2175 case WAVE_FORMAT_ALAW:
2176 case WAVE_FORMAT_MULAW:
2177 if (fmt->wBitsPerSample != 8) {
2178 params->result = E_INVALIDARG;
2179 break;
2181 /* Fall-through */
2182 case WAVE_FORMAT_IEEE_FLOAT:
2183 if (fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT && fmt->wBitsPerSample != 32) {
2184 params->result = E_INVALIDARG;
2185 break;
2187 /* Fall-through */
2188 case WAVE_FORMAT_PCM: {
2189 if (fmt->wFormatTag == WAVE_FORMAT_PCM &&
2190 (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8)) {
2191 params->result = E_INVALIDARG;
2192 break;
2195 if (fmt->nChannels > 2) {
2196 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2197 break;
2200 /* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
2201 * ignored, invalid values are happily accepted. */
2202 break;
2204 default:
2205 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2206 break;
2209 if (exclusive) { /* This driver does not support exclusive mode. */
2210 if (params->result == S_OK)
2211 params->result = params->flow == eCapture ?
2212 AUDCLNT_E_UNSUPPORTED_FORMAT :
2213 AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
2214 else if (params->result == S_FALSE)
2215 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2218 return STATUS_SUCCESS;
2221 static NTSTATUS pulse_get_mix_format(void *args)
2223 struct get_mix_format_params *params = args;
2224 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2225 PhysDevice *dev;
2227 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2228 if (strcmp(params->device, dev->pulse_name))
2229 continue;
2231 *params->fmt = dev->fmt;
2232 params->result = S_OK;
2234 return STATUS_SUCCESS;
2237 params->result = E_FAIL;
2238 return STATUS_SUCCESS;
2241 static NTSTATUS pulse_get_device_period(void *args)
2243 struct get_device_period_params *params = args;
2245 params->result = get_device_period_helper(params->flow, params->device, params->def_period, params->min_period);
2246 return STATUS_SUCCESS;
2249 static NTSTATUS pulse_get_buffer_size(void *args)
2251 struct get_buffer_size_params *params = args;
2252 struct pulse_stream *stream = handle_get_stream(params->stream);
2254 params->result = S_OK;
2256 pulse_lock();
2257 if (!pulse_stream_valid(stream))
2258 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2259 else
2260 *params->frames = stream->bufsize_frames;
2261 pulse_unlock();
2263 return STATUS_SUCCESS;
2266 static NTSTATUS pulse_get_latency(void *args)
2268 struct get_latency_params *params = args;
2269 struct pulse_stream *stream = handle_get_stream(params->stream);
2270 const pa_buffer_attr *attr;
2271 REFERENCE_TIME lat;
2273 pulse_lock();
2274 if (!pulse_stream_valid(stream)) {
2275 pulse_unlock();
2276 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2277 return STATUS_SUCCESS;
2279 attr = pa_stream_get_buffer_attr(stream->stream);
2280 if (stream->dataflow == eRender)
2281 lat = attr->minreq / pa_frame_size(&stream->ss);
2282 else
2283 lat = attr->fragsize / pa_frame_size(&stream->ss);
2284 *params->latency = (lat * 10000000) / stream->ss.rate + stream->def_period;
2285 pulse_unlock();
2286 TRACE("Latency: %u ms\n", (unsigned)(*params->latency / 10000));
2287 params->result = S_OK;
2288 return STATUS_SUCCESS;
2291 static NTSTATUS pulse_get_current_padding(void *args)
2293 struct get_current_padding_params *params = args;
2294 struct pulse_stream *stream = handle_get_stream(params->stream);
2296 pulse_lock();
2297 if (!pulse_stream_valid(stream))
2299 pulse_unlock();
2300 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2301 return STATUS_SUCCESS;
2304 if (stream->dataflow == eRender)
2305 *params->padding = pulse_render_padding(stream);
2306 else
2307 *params->padding = pulse_capture_padding(stream);
2308 pulse_unlock();
2310 TRACE("%p Pad: %u ms (%u)\n", stream, muldiv(*params->padding, 1000, stream->ss.rate),
2311 *params->padding);
2312 params->result = S_OK;
2313 return STATUS_SUCCESS;
2316 static NTSTATUS pulse_get_next_packet_size(void *args)
2318 struct get_next_packet_size_params *params = args;
2319 struct pulse_stream *stream = handle_get_stream(params->stream);
2321 pulse_lock();
2322 pulse_capture_padding(stream);
2323 if (stream->locked_ptr)
2324 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2325 else
2326 *params->frames = 0;
2327 pulse_unlock();
2328 params->result = S_OK;
2330 return STATUS_SUCCESS;
2333 static NTSTATUS pulse_get_frequency(void *args)
2335 struct get_frequency_params *params = args;
2336 struct pulse_stream *stream = handle_get_stream(params->stream);
2338 pulse_lock();
2339 if (!pulse_stream_valid(stream))
2341 pulse_unlock();
2342 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2343 return STATUS_SUCCESS;
2346 *params->freq = stream->ss.rate;
2347 if (stream->share == AUDCLNT_SHAREMODE_SHARED)
2348 *params->freq *= pa_frame_size(&stream->ss);
2349 pulse_unlock();
2350 params->result = S_OK;
2351 return STATUS_SUCCESS;
2354 static NTSTATUS pulse_get_position(void *args)
2356 struct get_position_params *params = args;
2357 struct pulse_stream *stream = handle_get_stream(params->stream);
2359 pulse_lock();
2360 if (!pulse_stream_valid(stream))
2362 pulse_unlock();
2363 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2364 return STATUS_SUCCESS;
2367 *params->pos = stream->clock_written - stream->held_bytes;
2369 if (stream->share == AUDCLNT_SHAREMODE_EXCLUSIVE || params->device)
2370 *params->pos /= pa_frame_size(&stream->ss);
2372 /* Make time never go backwards */
2373 if (*params->pos < stream->clock_lastpos)
2374 *params->pos = stream->clock_lastpos;
2375 else
2376 stream->clock_lastpos = *params->pos;
2377 pulse_unlock();
2379 TRACE("%p Position: %u\n", stream, (unsigned)*params->pos);
2381 if (params->qpctime)
2383 LARGE_INTEGER stamp, freq;
2384 NtQueryPerformanceCounter(&stamp, &freq);
2385 *params->qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2388 params->result = S_OK;
2389 return STATUS_SUCCESS;
2392 static NTSTATUS pulse_set_volumes(void *args)
2394 struct set_volumes_params *params = args;
2395 struct pulse_stream *stream = handle_get_stream(params->stream);
2396 unsigned int i;
2398 for (i = 0; i < stream->ss.channels; i++)
2399 stream->vol[i] = params->volumes[i] * params->master_volume * params->session_volumes[i];
2401 return STATUS_SUCCESS;
2404 static NTSTATUS pulse_set_event_handle(void *args)
2406 struct set_event_handle_params *params = args;
2407 struct pulse_stream *stream = handle_get_stream(params->stream);
2408 HRESULT hr = S_OK;
2410 pulse_lock();
2411 if (!pulse_stream_valid(stream))
2412 hr = AUDCLNT_E_DEVICE_INVALIDATED;
2413 else if (!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
2414 hr = AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
2415 else if (stream->event)
2416 hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
2417 else
2418 stream->event = params->event;
2419 pulse_unlock();
2421 params->result = hr;
2422 return STATUS_SUCCESS;
2425 static NTSTATUS pulse_is_started(void *args)
2427 struct is_started_params *params = args;
2428 struct pulse_stream *stream = handle_get_stream(params->stream);
2430 pulse_lock();
2431 params->result = pulse_stream_valid(stream) && stream->started ? S_OK : S_FALSE;
2432 pulse_unlock();
2434 return STATUS_SUCCESS;
2437 static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *params)
2439 const GUID *guid = params->guid;
2440 PROPVARIANT *out = params->value;
2441 UINT serial_number;
2442 char path[128];
2443 int len;
2445 /* As hardly any audio devices have serial numbers, Windows instead
2446 appears to use a persistent random number. We emulate this here
2447 by instead using the last 8 hex digits of the GUID. */
2448 serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
2450 switch (dev->bus_type) {
2451 case phys_device_bus_pci:
2452 len = sprintf(path, "{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2453 break;
2454 case phys_device_bus_usb:
2455 len = sprintf(path, "{1}.USB\\VID_%04X&PID_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2456 break;
2457 default:
2458 len = sprintf(path, "{1}.ROOT\\MEDIA\\%04u", dev->index);
2459 break;
2462 if (*params->buffer_size < ++len * sizeof(WCHAR)) {
2463 params->result = E_NOT_SUFFICIENT_BUFFER;
2464 *params->buffer_size = len * sizeof(WCHAR);
2465 return FALSE;
2468 out->vt = VT_LPWSTR;
2469 out->pwszVal = params->buffer;
2471 ntdll_umbstowcs(path, len, out->pwszVal, len);
2473 params->result = S_OK;
2475 return TRUE;
2478 static NTSTATUS pulse_get_prop_value(void *args)
2480 static const GUID PKEY_AudioEndpoint_GUID = {
2481 0x1da5d803, 0xd492, 0x4edd, {0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e}
2483 static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
2484 {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
2486 struct get_prop_value_params *params = args;
2487 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2488 PhysDevice *dev;
2490 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2491 if (strcmp(params->device, dev->pulse_name))
2492 continue;
2493 if (IsEqualPropertyKey(*params->prop, devicepath_key)) {
2494 get_device_path(dev, params);
2495 return STATUS_SUCCESS;
2496 } else if (IsEqualGUID(&params->prop->fmtid, &PKEY_AudioEndpoint_GUID)) {
2497 switch (params->prop->pid) {
2498 case 0: /* FormFactor */
2499 params->value->vt = VT_UI4;
2500 params->value->ulVal = dev->form;
2501 params->result = S_OK;
2502 return STATUS_SUCCESS;
2503 case 3: /* PhysicalSpeakers */
2504 if (!dev->channel_mask)
2505 goto fail;
2506 params->value->vt = VT_UI4;
2507 params->value->ulVal = dev->channel_mask;
2508 params->result = S_OK;
2509 return STATUS_SUCCESS;
2513 params->result = E_NOTIMPL;
2514 return STATUS_SUCCESS;
2517 fail:
2518 params->result = E_FAIL;
2519 return STATUS_SUCCESS;
2522 const unixlib_entry_t __wine_unix_call_funcs[] =
2524 pulse_process_attach,
2525 pulse_process_detach,
2526 pulse_main_loop,
2527 pulse_get_endpoint_ids,
2528 pulse_create_stream,
2529 pulse_release_stream,
2530 pulse_start,
2531 pulse_stop,
2532 pulse_reset,
2533 pulse_timer_loop,
2534 pulse_get_render_buffer,
2535 pulse_release_render_buffer,
2536 pulse_get_capture_buffer,
2537 pulse_release_capture_buffer,
2538 pulse_is_format_supported,
2539 pulse_get_mix_format,
2540 pulse_get_device_period,
2541 pulse_get_buffer_size,
2542 pulse_get_latency,
2543 pulse_get_current_padding,
2544 pulse_get_next_packet_size,
2545 pulse_get_frequency,
2546 pulse_get_position,
2547 pulse_set_volumes,
2548 pulse_set_event_handle,
2549 pulse_test_connect,
2550 pulse_is_started,
2551 pulse_get_prop_value,
2552 pulse_not_implemented,
2553 pulse_not_implemented,
2554 pulse_not_implemented,
2555 pulse_not_implemented,
2556 pulse_not_implemented,
2557 pulse_not_implemented,
2560 C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == funcs_count);
2562 #ifdef _WIN64
2564 typedef UINT PTR32;
2566 static NTSTATUS pulse_wow64_main_loop(void *args)
2568 struct
2570 PTR32 event;
2571 } *params32 = args;
2572 struct main_loop_params params =
2574 .event = ULongToHandle(params32->event)
2576 return pulse_main_loop(&params);
2579 static NTSTATUS pulse_wow64_get_endpoint_ids(void *args)
2581 struct
2583 EDataFlow flow;
2584 PTR32 endpoints;
2585 unsigned int size;
2586 HRESULT result;
2587 unsigned int num;
2588 unsigned int default_idx;
2589 } *params32 = args;
2590 struct get_endpoint_ids_params params =
2592 .flow = params32->flow,
2593 .endpoints = ULongToPtr(params32->endpoints),
2594 .size = params32->size
2596 pulse_get_endpoint_ids(&params);
2597 params32->size = params.size;
2598 params32->result = params.result;
2599 params32->num = params.num;
2600 params32->default_idx = params.default_idx;
2601 return STATUS_SUCCESS;
2604 static NTSTATUS pulse_wow64_create_stream(void *args)
2606 struct
2608 PTR32 name;
2609 PTR32 device;
2610 EDataFlow flow;
2611 AUDCLNT_SHAREMODE share;
2612 DWORD flags;
2613 REFERENCE_TIME duration;
2614 REFERENCE_TIME period;
2615 PTR32 fmt;
2616 HRESULT result;
2617 PTR32 channel_count;
2618 PTR32 stream;
2619 } *params32 = args;
2620 struct create_stream_params params =
2622 .name = ULongToPtr(params32->name),
2623 .device = ULongToPtr(params32->device),
2624 .flow = params32->flow,
2625 .share = params32->share,
2626 .flags = params32->flags,
2627 .duration = params32->duration,
2628 .period = params32->period,
2629 .fmt = ULongToPtr(params32->fmt),
2630 .channel_count = ULongToPtr(params32->channel_count),
2631 .stream = ULongToPtr(params32->stream)
2633 pulse_create_stream(&params);
2634 params32->result = params.result;
2635 return STATUS_SUCCESS;
2638 static NTSTATUS pulse_wow64_release_stream(void *args)
2640 struct
2642 stream_handle stream;
2643 PTR32 timer_thread;
2644 HRESULT result;
2645 } *params32 = args;
2646 struct release_stream_params params =
2648 .stream = params32->stream,
2649 .timer_thread = ULongToHandle(params32->timer_thread)
2651 pulse_release_stream(&params);
2652 params32->result = params.result;
2653 return STATUS_SUCCESS;
2656 static NTSTATUS pulse_wow64_get_render_buffer(void *args)
2658 struct
2660 stream_handle stream;
2661 UINT32 frames;
2662 HRESULT result;
2663 PTR32 data;
2664 } *params32 = args;
2665 BYTE *data = NULL;
2666 struct get_render_buffer_params params =
2668 .stream = params32->stream,
2669 .frames = params32->frames,
2670 .data = &data
2672 pulse_get_render_buffer(&params);
2673 params32->result = params.result;
2674 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2675 return STATUS_SUCCESS;
2678 static NTSTATUS pulse_wow64_get_capture_buffer(void *args)
2680 struct
2682 stream_handle stream;
2683 HRESULT result;
2684 PTR32 data;
2685 PTR32 frames;
2686 PTR32 flags;
2687 PTR32 devpos;
2688 PTR32 qpcpos;
2689 } *params32 = args;
2690 BYTE *data = NULL;
2691 struct get_capture_buffer_params params =
2693 .stream = params32->stream,
2694 .data = &data,
2695 .frames = ULongToPtr(params32->frames),
2696 .flags = ULongToPtr(params32->flags),
2697 .devpos = ULongToPtr(params32->devpos),
2698 .qpcpos = ULongToPtr(params32->qpcpos)
2700 pulse_get_capture_buffer(&params);
2701 params32->result = params.result;
2702 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2703 return STATUS_SUCCESS;
2706 static NTSTATUS pulse_wow64_is_format_supported(void *args)
2708 struct
2710 PTR32 device;
2711 EDataFlow flow;
2712 AUDCLNT_SHAREMODE share;
2713 PTR32 fmt_in;
2714 PTR32 fmt_out;
2715 HRESULT result;
2716 } *params32 = args;
2717 struct is_format_supported_params params =
2719 .device = ULongToPtr(params32->device),
2720 .flow = params32->flow,
2721 .share = params32->share,
2722 .fmt_in = ULongToPtr(params32->fmt_in),
2723 .fmt_out = ULongToPtr(params32->fmt_out)
2725 pulse_is_format_supported(&params);
2726 params32->result = params.result;
2727 return STATUS_SUCCESS;
2730 static NTSTATUS pulse_wow64_get_mix_format(void *args)
2732 struct
2734 PTR32 device;
2735 EDataFlow flow;
2736 PTR32 fmt;
2737 HRESULT result;
2738 } *params32 = args;
2739 struct get_mix_format_params params =
2741 .device = ULongToPtr(params32->device),
2742 .flow = params32->flow,
2743 .fmt = ULongToPtr(params32->fmt),
2745 pulse_get_mix_format(&params);
2746 params32->result = params.result;
2747 return STATUS_SUCCESS;
2750 static NTSTATUS pulse_wow64_get_device_period(void *args)
2752 struct
2754 PTR32 device;
2755 EDataFlow flow;
2756 HRESULT result;
2757 PTR32 def_period;
2758 PTR32 min_period;
2759 } *params32 = args;
2760 struct get_device_period_params params =
2762 .device = ULongToPtr(params32->device),
2763 .flow = params32->flow,
2764 .def_period = ULongToPtr(params32->def_period),
2765 .min_period = ULongToPtr(params32->min_period),
2767 pulse_get_device_period(&params);
2768 params32->result = params.result;
2769 return STATUS_SUCCESS;
2772 static NTSTATUS pulse_wow64_get_buffer_size(void *args)
2774 struct
2776 stream_handle stream;
2777 HRESULT result;
2778 PTR32 frames;
2779 } *params32 = args;
2780 struct get_buffer_size_params params =
2782 .stream = params32->stream,
2783 .frames = ULongToPtr(params32->frames)
2785 pulse_get_buffer_size(&params);
2786 params32->result = params.result;
2787 return STATUS_SUCCESS;
2790 static NTSTATUS pulse_wow64_get_latency(void *args)
2792 struct
2794 stream_handle stream;
2795 HRESULT result;
2796 PTR32 latency;
2797 } *params32 = args;
2798 struct get_latency_params params =
2800 .stream = params32->stream,
2801 .latency = ULongToPtr(params32->latency)
2803 pulse_get_latency(&params);
2804 params32->result = params.result;
2805 return STATUS_SUCCESS;
2808 static NTSTATUS pulse_wow64_get_current_padding(void *args)
2810 struct
2812 stream_handle stream;
2813 HRESULT result;
2814 PTR32 padding;
2815 } *params32 = args;
2816 struct get_current_padding_params params =
2818 .stream = params32->stream,
2819 .padding = ULongToPtr(params32->padding)
2821 pulse_get_current_padding(&params);
2822 params32->result = params.result;
2823 return STATUS_SUCCESS;
2826 static NTSTATUS pulse_wow64_get_next_packet_size(void *args)
2828 struct
2830 stream_handle stream;
2831 HRESULT result;
2832 PTR32 frames;
2833 } *params32 = args;
2834 struct get_next_packet_size_params params =
2836 .stream = params32->stream,
2837 .frames = ULongToPtr(params32->frames)
2839 pulse_get_next_packet_size(&params);
2840 params32->result = params.result;
2841 return STATUS_SUCCESS;
2844 static NTSTATUS pulse_wow64_get_frequency(void *args)
2846 struct
2848 stream_handle stream;
2849 HRESULT result;
2850 PTR32 freq;
2851 } *params32 = args;
2852 struct get_frequency_params params =
2854 .stream = params32->stream,
2855 .freq = ULongToPtr(params32->freq)
2857 pulse_get_frequency(&params);
2858 params32->result = params.result;
2859 return STATUS_SUCCESS;
2862 static NTSTATUS pulse_wow64_get_position(void *args)
2864 struct
2866 stream_handle stream;
2867 BOOL device;
2868 HRESULT result;
2869 PTR32 pos;
2870 PTR32 qpctime;
2871 } *params32 = args;
2872 struct get_position_params params =
2874 .stream = params32->stream,
2875 .device = params32->device,
2876 .pos = ULongToPtr(params32->pos),
2877 .qpctime = ULongToPtr(params32->qpctime)
2879 pulse_get_position(&params);
2880 params32->result = params.result;
2881 return STATUS_SUCCESS;
2884 static NTSTATUS pulse_wow64_set_volumes(void *args)
2886 struct
2888 stream_handle stream;
2889 float master_volume;
2890 PTR32 volumes;
2891 PTR32 session_volumes;
2892 } *params32 = args;
2893 struct set_volumes_params params =
2895 .stream = params32->stream,
2896 .master_volume = params32->master_volume,
2897 .volumes = ULongToPtr(params32->volumes),
2898 .session_volumes = ULongToPtr(params32->session_volumes),
2900 return pulse_set_volumes(&params);
2903 static NTSTATUS pulse_wow64_set_event_handle(void *args)
2905 struct
2907 stream_handle stream;
2908 PTR32 event;
2909 HRESULT result;
2910 } *params32 = args;
2911 struct set_event_handle_params params =
2913 .stream = params32->stream,
2914 .event = ULongToHandle(params32->event)
2916 pulse_set_event_handle(&params);
2917 params32->result = params.result;
2918 return STATUS_SUCCESS;
2921 static NTSTATUS pulse_wow64_test_connect(void *args)
2923 struct
2925 PTR32 name;
2926 enum driver_priority priority;
2927 } *params32 = args;
2928 struct test_connect_params params =
2930 .name = ULongToPtr(params32->name),
2932 pulse_test_connect(&params);
2933 params32->priority = params.priority;
2934 return STATUS_SUCCESS;
2937 static NTSTATUS pulse_wow64_get_prop_value(void *args)
2939 struct propvariant32
2941 WORD vt;
2942 WORD pad1, pad2, pad3;
2943 union
2945 ULONG ulVal;
2946 PTR32 ptr;
2947 ULARGE_INTEGER uhVal;
2949 } *value32;
2950 struct
2952 PTR32 device;
2953 EDataFlow flow;
2954 PTR32 guid;
2955 PTR32 prop;
2956 HRESULT result;
2957 PTR32 value;
2958 PTR32 buffer; /* caller allocated buffer to hold value's strings */
2959 PTR32 buffer_size;
2960 } *params32 = args;
2961 PROPVARIANT value;
2962 struct get_prop_value_params params =
2964 .device = ULongToPtr(params32->device),
2965 .flow = params32->flow,
2966 .guid = ULongToPtr(params32->guid),
2967 .prop = ULongToPtr(params32->prop),
2968 .value = &value,
2969 .buffer = ULongToPtr(params32->buffer),
2970 .buffer_size = ULongToPtr(params32->buffer_size)
2972 pulse_get_prop_value(&params);
2973 params32->result = params.result;
2974 if (SUCCEEDED(params.result))
2976 value32 = UlongToPtr(params32->value);
2977 value32->vt = value.vt;
2978 switch (value.vt)
2980 case VT_UI4:
2981 value32->ulVal = value.ulVal;
2982 break;
2983 case VT_LPWSTR:
2984 value32->ptr = params32->buffer;
2985 break;
2986 default:
2987 FIXME("Unhandled vt %04x\n", value.vt);
2990 return STATUS_SUCCESS;
2993 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
2995 pulse_process_attach,
2996 pulse_process_detach,
2997 pulse_wow64_main_loop,
2998 pulse_wow64_get_endpoint_ids,
2999 pulse_wow64_create_stream,
3000 pulse_wow64_release_stream,
3001 pulse_start,
3002 pulse_stop,
3003 pulse_reset,
3004 pulse_timer_loop,
3005 pulse_wow64_get_render_buffer,
3006 pulse_release_render_buffer,
3007 pulse_wow64_get_capture_buffer,
3008 pulse_release_capture_buffer,
3009 pulse_wow64_is_format_supported,
3010 pulse_wow64_get_mix_format,
3011 pulse_wow64_get_device_period,
3012 pulse_wow64_get_buffer_size,
3013 pulse_wow64_get_latency,
3014 pulse_wow64_get_current_padding,
3015 pulse_wow64_get_next_packet_size,
3016 pulse_wow64_get_frequency,
3017 pulse_wow64_get_position,
3018 pulse_wow64_set_volumes,
3019 pulse_wow64_set_event_handle,
3020 pulse_wow64_test_connect,
3021 pulse_is_started,
3022 pulse_wow64_get_prop_value,
3023 pulse_not_implemented,
3024 pulse_not_implemented,
3025 pulse_not_implemented,
3026 pulse_not_implemented,
3027 pulse_not_implemented,
3028 pulse_not_implemented,
3031 C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == funcs_count);
3033 #endif /* _WIN64 */