d3dx9: Unify calling parse_mesh helper functions.
[wine.git] / dlls / winepulse.drv / pulse.c
blob62658fc98e63166a366abd11b7b69970d66860b2
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 const REFERENCE_TIME MinimumPeriod = 30000;
117 static const REFERENCE_TIME DefaultPeriod = 100000;
119 static pthread_mutex_t pulse_mutex;
120 static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
122 static ULONG_PTR zero_bits = 0;
124 static NTSTATUS pulse_not_implemented(void *args)
126 return STATUS_SUCCESS;
129 static void pulse_lock(void)
131 pthread_mutex_lock(&pulse_mutex);
134 static void pulse_unlock(void)
136 pthread_mutex_unlock(&pulse_mutex);
139 static int pulse_cond_wait(void)
141 return pthread_cond_wait(&pulse_cond, &pulse_mutex);
144 static void pulse_broadcast(void)
146 pthread_cond_broadcast(&pulse_cond);
149 static struct pulse_stream *handle_get_stream(stream_handle h)
151 return (struct pulse_stream *)(UINT_PTR)h;
154 static void dump_attr(const pa_buffer_attr *attr)
156 TRACE("maxlength: %u\n", attr->maxlength);
157 TRACE("minreq: %u\n", attr->minreq);
158 TRACE("fragsize: %u\n", attr->fragsize);
159 TRACE("tlength: %u\n", attr->tlength);
160 TRACE("prebuf: %u\n", attr->prebuf);
163 static void free_phys_device_lists(void)
165 static struct list *const lists[] = { &g_phys_speakers, &g_phys_sources, NULL };
166 struct list *const *list = lists;
167 PhysDevice *dev, *dev_next;
169 do {
170 LIST_FOR_EACH_ENTRY_SAFE(dev, dev_next, *list, PhysDevice, entry) {
171 free(dev->name);
172 free(dev);
174 } while (*(++list));
177 /* copied from kernelbase */
178 static int muldiv(int a, int b, int c)
180 LONGLONG ret;
182 if (!c) return -1;
184 /* We want to deal with a positive divisor to simplify the logic. */
185 if (c < 0)
187 a = -a;
188 c = -c;
191 /* If the result is positive, we "add" to round. else, we subtract to round. */
192 if ((a < 0 && b < 0) || (a >= 0 && b >= 0))
193 ret = (((LONGLONG)a * b) + (c / 2)) / c;
194 else
195 ret = (((LONGLONG)a * b) - (c / 2)) / c;
197 if (ret > 2147483647 || ret < -2147483647) return -1;
198 return ret;
201 static char *wstr_to_str(const WCHAR *wstr)
203 const int len = wcslen(wstr);
204 char *str = malloc(len * 3 + 1);
205 ntdll_wcstoumbs(wstr, len + 1, str, len * 3 + 1, FALSE);
206 return str;
209 /* Following pulseaudio design here, mainloop has the lock taken whenever
210 * it is handling something for pulse, and the lock is required whenever
211 * doing any pa_* call that can affect the state in any way
213 * pa_cond_wait is used when waiting on results, because the mainloop needs
214 * the same lock taken to affect the state
216 * This is basically the same as the pa_threaded_mainloop implementation,
217 * but that cannot be used because it uses pthread_create directly
219 * pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock
220 * pa_threaded_mainloop_signal -> pthread_cond_broadcast
221 * pa_threaded_mainloop_wait -> pthread_cond_wait
223 static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata)
225 int r;
226 pulse_unlock();
227 r = poll(ufds, nfds, timeout);
228 pulse_lock();
229 return r;
232 static NTSTATUS pulse_process_attach(void *args)
234 pthread_mutexattr_t attr;
236 pthread_mutexattr_init(&attr);
237 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
239 if (pthread_mutex_init(&pulse_mutex, &attr) != 0)
240 pthread_mutex_init(&pulse_mutex, NULL);
242 #ifdef _WIN64
243 if (NtCurrentTeb()->WowTebOffset)
245 SYSTEM_BASIC_INFORMATION info;
247 NtQuerySystemInformation(SystemEmulationBasicInformation, &info, sizeof(info), NULL);
248 zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff;
250 #endif
252 return STATUS_SUCCESS;
255 static NTSTATUS pulse_process_detach(void *args)
257 free_phys_device_lists();
258 if (pulse_ctx)
260 pa_context_disconnect(pulse_ctx);
261 pa_context_unref(pulse_ctx);
263 if (pulse_ml)
264 pa_mainloop_quit(pulse_ml, 0);
266 return STATUS_SUCCESS;
269 static NTSTATUS pulse_main_loop(void *args)
271 struct main_loop_params *params = args;
272 int ret;
273 pulse_lock();
274 pulse_ml = pa_mainloop_new();
275 pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
276 NtSetEvent(params->event, NULL);
277 pa_mainloop_run(pulse_ml, &ret);
278 pa_mainloop_free(pulse_ml);
279 pulse_unlock();
280 return STATUS_SUCCESS;
283 static NTSTATUS pulse_get_endpoint_ids(void *args)
285 struct get_endpoint_ids_params *params = args;
286 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
287 struct endpoint *endpoint = params->endpoints;
288 size_t len, name_len, needed;
289 unsigned int offset;
290 PhysDevice *dev;
292 params->num = list_count(list);
293 offset = needed = params->num * sizeof(*params->endpoints);
295 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
296 name_len = lstrlenW(dev->name) + 1;
297 len = strlen(dev->pulse_name) + 1;
298 needed += name_len * sizeof(WCHAR) + ((len + 1) & ~1);
300 if (needed <= params->size) {
301 endpoint->name = offset;
302 memcpy((char *)params->endpoints + offset, dev->name, name_len * sizeof(WCHAR));
303 offset += name_len * sizeof(WCHAR);
304 endpoint->device = offset;
305 memcpy((char *)params->endpoints + offset, dev->pulse_name, len);
306 offset += (len + 1) & ~1;
307 endpoint++;
310 params->default_idx = 0;
312 if (needed > params->size) {
313 params->size = needed;
314 params->result = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
315 } else
316 params->result = S_OK;
317 return STATUS_SUCCESS;
320 static void pulse_contextcallback(pa_context *c, void *userdata)
322 switch (pa_context_get_state(c)) {
323 default:
324 FIXME("Unhandled state: %i\n", pa_context_get_state(c));
325 return;
327 case PA_CONTEXT_CONNECTING:
328 case PA_CONTEXT_UNCONNECTED:
329 case PA_CONTEXT_AUTHORIZING:
330 case PA_CONTEXT_SETTING_NAME:
331 case PA_CONTEXT_TERMINATED:
332 TRACE("State change to %i\n", pa_context_get_state(c));
333 return;
335 case PA_CONTEXT_READY:
336 TRACE("Ready\n");
337 break;
339 case PA_CONTEXT_FAILED:
340 WARN("Context failed: %s\n", pa_strerror(pa_context_errno(c)));
341 break;
343 pulse_broadcast();
346 static void pulse_stream_state(pa_stream *s, void *user)
348 pa_stream_state_t state = pa_stream_get_state(s);
349 TRACE("Stream state changed to %i\n", state);
350 pulse_broadcast();
353 static void pulse_attr_update(pa_stream *s, void *user) {
354 const pa_buffer_attr *attr = pa_stream_get_buffer_attr(s);
355 TRACE("New attributes or device moved:\n");
356 dump_attr(attr);
359 static void pulse_underflow_callback(pa_stream *s, void *userdata)
361 struct pulse_stream *stream = userdata;
362 WARN("%p: Underflow\n", userdata);
363 stream->just_underran = TRUE;
366 static void pulse_started_callback(pa_stream *s, void *userdata)
368 TRACE("%p: (Re)started playing\n", userdata);
371 static void pulse_op_cb(pa_stream *s, int success, void *user)
373 TRACE("Success: %i\n", success);
374 *(int*)user = success;
375 pulse_broadcast();
378 static void silence_buffer(pa_sample_format_t format, BYTE *buffer, UINT32 bytes)
380 memset(buffer, format == PA_SAMPLE_U8 ? 0x80 : 0, bytes);
383 static BOOL pulse_stream_valid(struct pulse_stream *stream)
385 return pa_stream_get_state(stream->stream) == PA_STREAM_READY;
388 static HRESULT pulse_connect(const char *name)
390 pa_context_state_t state;
392 if (pulse_ctx && PA_CONTEXT_IS_GOOD(pa_context_get_state(pulse_ctx)))
393 return S_OK;
394 if (pulse_ctx)
395 pa_context_unref(pulse_ctx);
397 pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), name);
398 if (!pulse_ctx) {
399 ERR("Failed to create context\n");
400 return E_FAIL;
403 pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL);
405 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION);
406 if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0)
407 goto fail;
409 /* Wait for connection */
410 while ((state = pa_context_get_state(pulse_ctx)) != PA_CONTEXT_READY &&
411 state != PA_CONTEXT_FAILED && state != PA_CONTEXT_TERMINATED)
412 pulse_cond_wait();
414 if (state != PA_CONTEXT_READY)
415 goto fail;
417 TRACE("Connected to server %s with protocol version: %i.\n",
418 pa_context_get_server(pulse_ctx),
419 pa_context_get_server_protocol_version(pulse_ctx));
420 return S_OK;
422 fail:
423 pa_context_unref(pulse_ctx);
424 pulse_ctx = NULL;
425 return E_FAIL;
428 static UINT pulse_channel_map_to_channel_mask(const pa_channel_map *map)
430 int i;
431 UINT mask = 0;
433 for (i = 0; i < map->channels; ++i) {
434 switch (map->map[i]) {
435 default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map->map[i])); break;
436 case PA_CHANNEL_POSITION_FRONT_LEFT: mask |= SPEAKER_FRONT_LEFT; break;
437 case PA_CHANNEL_POSITION_MONO:
438 case PA_CHANNEL_POSITION_FRONT_CENTER: mask |= SPEAKER_FRONT_CENTER; break;
439 case PA_CHANNEL_POSITION_FRONT_RIGHT: mask |= SPEAKER_FRONT_RIGHT; break;
440 case PA_CHANNEL_POSITION_REAR_LEFT: mask |= SPEAKER_BACK_LEFT; break;
441 case PA_CHANNEL_POSITION_REAR_CENTER: mask |= SPEAKER_BACK_CENTER; break;
442 case PA_CHANNEL_POSITION_REAR_RIGHT: mask |= SPEAKER_BACK_RIGHT; break;
443 case PA_CHANNEL_POSITION_LFE: mask |= SPEAKER_LOW_FREQUENCY; break;
444 case PA_CHANNEL_POSITION_SIDE_LEFT: mask |= SPEAKER_SIDE_LEFT; break;
445 case PA_CHANNEL_POSITION_SIDE_RIGHT: mask |= SPEAKER_SIDE_RIGHT; break;
446 case PA_CHANNEL_POSITION_TOP_CENTER: mask |= SPEAKER_TOP_CENTER; break;
447 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: mask |= SPEAKER_TOP_FRONT_LEFT; break;
448 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: mask |= SPEAKER_TOP_FRONT_CENTER; break;
449 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: mask |= SPEAKER_TOP_FRONT_RIGHT; break;
450 case PA_CHANNEL_POSITION_TOP_REAR_LEFT: mask |= SPEAKER_TOP_BACK_LEFT; break;
451 case PA_CHANNEL_POSITION_TOP_REAR_CENTER: mask |= SPEAKER_TOP_BACK_CENTER; break;
452 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: mask |= SPEAKER_TOP_BACK_RIGHT; break;
453 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: mask |= SPEAKER_FRONT_LEFT_OF_CENTER; break;
454 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: mask |= SPEAKER_FRONT_RIGHT_OF_CENTER; break;
458 return mask;
461 #define MAX_DEVICE_NAME_LEN 62
463 static WCHAR *get_device_name(const char *desc, pa_proplist *proplist)
466 Some broken apps (e.g. Split/Second with fmodex) can't handle names that
467 are too long and crash even on native. If the device desc is too long,
468 we'll attempt to incrementally build it to try to stay under the limit.
469 ( + 1 is to check against truncated buffer after ntdll_umbstowcs )
471 WCHAR buf[MAX_DEVICE_NAME_LEN + 1];
473 /* For monitors of sinks; this does not seem to be localized in PA either */
474 static const WCHAR monitor_of[] = {'M','o','n','i','t','o','r',' ','o','f',' '};
476 size_t len = strlen(desc);
477 WCHAR *name, *tmp;
479 if (!(name = malloc((len + 1) * sizeof(WCHAR))))
480 return NULL;
481 if (!(len = ntdll_umbstowcs(desc, len, name, len))) {
482 free(name);
483 return NULL;
486 if (len > MAX_DEVICE_NAME_LEN && proplist) {
487 const char *prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_CLASS);
488 unsigned prop_len, rem = ARRAY_SIZE(buf);
489 BOOL monitor = FALSE;
491 if (prop && !strcmp(prop, "monitor")) {
492 rem -= ARRAY_SIZE(monitor_of);
493 monitor = TRUE;
496 prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_PRODUCT_NAME);
497 if (!prop || !prop[0] ||
498 !(prop_len = ntdll_umbstowcs(prop, strlen(prop), buf, rem)) || prop_len == rem) {
499 prop = pa_proplist_gets(proplist, "alsa.card_name");
500 if (!prop || !prop[0] ||
501 !(prop_len = ntdll_umbstowcs(prop, strlen(prop), buf, rem)) || prop_len == rem)
502 prop = NULL;
505 if (prop) {
506 /* We know we have a name that fits within the limit now */
507 WCHAR *p = name;
509 if (monitor) {
510 memcpy(p, monitor_of, sizeof(monitor_of));
511 p += ARRAY_SIZE(monitor_of);
513 len = ntdll_umbstowcs(prop, strlen(prop), p, rem);
514 rem -= len;
515 p += len;
517 if (rem > 2) {
518 rem--; /* space */
520 prop = pa_proplist_gets(proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
521 if (prop && prop[0] && (len = ntdll_umbstowcs(prop, strlen(prop), p + 1, rem)) && len != rem) {
522 *p++ = ' ';
523 p += len;
526 len = p - name;
529 name[len] = '\0';
531 if ((tmp = realloc(name, (len + 1) * sizeof(WCHAR))))
532 name = tmp;
533 return name;
536 static void fill_device_info(PhysDevice *dev, pa_proplist *p)
538 const char *buffer;
540 dev->bus_type = phys_device_bus_invalid;
541 dev->vendor_id = 0;
542 dev->product_id = 0;
544 if (!p)
545 return;
547 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
548 if (!strcmp(buffer, "usb"))
549 dev->bus_type = phys_device_bus_usb;
550 else if (!strcmp(buffer, "pci"))
551 dev->bus_type = phys_device_bus_pci;
554 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID)))
555 dev->vendor_id = strtol(buffer, NULL, 16);
557 if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID)))
558 dev->product_id = strtol(buffer, NULL, 16);
561 static void pulse_add_device(struct list *list, pa_proplist *proplist, int index, EndpointFormFactor form,
562 UINT channel_mask, const char *pulse_name, const char *desc)
564 size_t len = strlen(pulse_name);
565 PhysDevice *dev = malloc(FIELD_OFFSET(PhysDevice, pulse_name[len + 1]));
567 if (!dev)
568 return;
570 if (!(dev->name = get_device_name(desc, proplist))) {
571 free(dev);
572 return;
574 dev->form = form;
575 dev->index = index;
576 dev->channel_mask = channel_mask;
577 dev->def_period = 0;
578 dev->min_period = 0;
579 fill_device_info(dev, proplist);
580 memcpy(dev->pulse_name, pulse_name, len + 1);
582 list_add_tail(list, &dev->entry);
584 TRACE("%s\n", debugstr_w(dev->name));
587 static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
589 struct list *speaker;
590 UINT channel_mask;
592 if (!i || !i->name || !i->name[0])
593 return;
594 channel_mask = pulse_channel_map_to_channel_mask(&i->channel_map);
596 /* For default PulseAudio render device, OR together all of the
597 * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
598 speaker = list_head(&g_phys_speakers);
599 if (speaker)
600 LIST_ENTRY(speaker, PhysDevice, entry)->channel_mask |= channel_mask;
602 pulse_add_device(&g_phys_speakers, i->proplist, i->index, Speakers, channel_mask, i->name, i->description);
605 static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
607 if (!i || !i->name || !i->name[0])
608 return;
609 pulse_add_device(&g_phys_sources, i->proplist, i->index,
610 (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel, 0, i->name, i->description);
613 /* For most hardware on Windows, users must choose a configuration with an even
614 * number of channels (stereo, quad, 5.1, 7.1). Users can then disable
615 * channels, but those channels are still reported to applications from
616 * GetMixFormat! Some applications behave badly if given an odd number of
617 * channels (e.g. 2.1). Here, we find the nearest configuration that Windows
618 * would report for a given channel layout. */
619 static void convert_channel_map(const pa_channel_map *pa_map, WAVEFORMATEXTENSIBLE *fmt)
621 UINT pa_mask = pulse_channel_map_to_channel_mask(pa_map);
623 TRACE("got mask for PA: 0x%x\n", pa_mask);
625 if (pa_map->channels == 1)
627 fmt->Format.nChannels = 1;
628 fmt->dwChannelMask = pa_mask;
629 return;
632 /* compare against known configurations and find smallest configuration
633 * which is a superset of the given speakers */
635 if (pa_map->channels <= 2 &&
636 (pa_mask & ~KSAUDIO_SPEAKER_STEREO) == 0)
638 fmt->Format.nChannels = 2;
639 fmt->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
640 return;
643 if (pa_map->channels <= 4 &&
644 (pa_mask & ~KSAUDIO_SPEAKER_QUAD) == 0)
646 fmt->Format.nChannels = 4;
647 fmt->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
648 return;
651 if (pa_map->channels <= 4 &&
652 (pa_mask & ~KSAUDIO_SPEAKER_SURROUND) == 0)
654 fmt->Format.nChannels = 4;
655 fmt->dwChannelMask = KSAUDIO_SPEAKER_SURROUND;
656 return;
659 if (pa_map->channels <= 6 &&
660 (pa_mask & ~KSAUDIO_SPEAKER_5POINT1) == 0)
662 fmt->Format.nChannels = 6;
663 fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
664 return;
667 if (pa_map->channels <= 6 &&
668 (pa_mask & ~KSAUDIO_SPEAKER_5POINT1_SURROUND) == 0)
670 fmt->Format.nChannels = 6;
671 fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND;
672 return;
675 if (pa_map->channels <= 8 &&
676 (pa_mask & ~KSAUDIO_SPEAKER_7POINT1) == 0)
678 fmt->Format.nChannels = 8;
679 fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1;
680 return;
683 if (pa_map->channels <= 8 &&
684 (pa_mask & ~KSAUDIO_SPEAKER_7POINT1_SURROUND) == 0)
686 fmt->Format.nChannels = 8;
687 fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND;
688 return;
691 /* oddball format, report truthfully */
692 fmt->Format.nChannels = pa_map->channels;
693 fmt->dwChannelMask = pa_mask;
696 static void pulse_probe_settings(int render, const char *pulse_name, WAVEFORMATEXTENSIBLE *fmt, REFERENCE_TIME *def_period, REFERENCE_TIME *min_period)
698 WAVEFORMATEX *wfx = &fmt->Format;
699 pa_stream *stream;
700 pa_channel_map map;
701 pa_sample_spec ss;
702 pa_buffer_attr attr;
703 int ret;
704 unsigned int length = 0;
706 if (pulse_name && !pulse_name[0])
707 pulse_name = NULL;
709 pa_channel_map_init_auto(&map, 2, PA_CHANNEL_MAP_ALSA);
710 ss.rate = 48000;
711 ss.format = PA_SAMPLE_FLOAT32LE;
712 ss.channels = map.channels;
714 attr.maxlength = -1;
715 attr.tlength = -1;
716 attr.minreq = attr.fragsize = pa_frame_size(&ss);
717 attr.prebuf = 0;
719 stream = pa_stream_new(pulse_ctx, "format test stream", &ss, &map);
720 if (stream)
721 pa_stream_set_state_callback(stream, pulse_stream_state, NULL);
722 if (!stream)
723 ret = -1;
724 else if (render)
725 ret = pa_stream_connect_playback(stream, pulse_name, &attr,
726 PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS, NULL, NULL);
727 else
728 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);
729 if (ret >= 0) {
730 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
731 pa_stream_get_state(stream) == PA_STREAM_CREATING)
733 if (pa_stream_get_state(stream) == PA_STREAM_READY) {
734 ss = *pa_stream_get_sample_spec(stream);
735 map = *pa_stream_get_channel_map(stream);
736 if (render)
737 length = pa_stream_get_buffer_attr(stream)->minreq;
738 else
739 length = pa_stream_get_buffer_attr(stream)->fragsize;
740 pa_stream_disconnect(stream);
741 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
742 pa_stream_get_state(stream) == PA_STREAM_READY)
747 if (stream)
748 pa_stream_unref(stream);
750 if (length)
751 *def_period = *min_period = pa_bytes_to_usec(10 * length, &ss);
753 if (*min_period < MinimumPeriod)
754 *min_period = MinimumPeriod;
756 if (*def_period < DefaultPeriod)
757 *def_period = DefaultPeriod;
759 wfx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
760 wfx->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
762 convert_channel_map(&map, fmt);
764 wfx->wBitsPerSample = 8 * pa_sample_size_of_format(ss.format);
765 wfx->nSamplesPerSec = ss.rate;
766 wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8;
767 wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign;
768 if (ss.format != PA_SAMPLE_S24_32LE)
769 fmt->Samples.wValidBitsPerSample = wfx->wBitsPerSample;
770 else
771 fmt->Samples.wValidBitsPerSample = 24;
772 if (ss.format == PA_SAMPLE_FLOAT32LE)
773 fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
774 else
775 fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
778 /* some poorly-behaved applications call audio functions during DllMain, so we
779 * have to do as much as possible without creating a new thread. this function
780 * sets up a synchronous connection to verify the server is running and query
781 * static data. */
782 static NTSTATUS pulse_test_connect(void *args)
784 struct test_connect_params *params = args;
785 PhysDevice *dev;
786 pa_operation *o;
787 int ret;
788 char *name = wstr_to_str(params->name);
790 pulse_lock();
791 pulse_ml = pa_mainloop_new();
793 pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
795 pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), name);
797 free(name);
799 if (!pulse_ctx) {
800 ERR("Failed to create context\n");
801 pa_mainloop_free(pulse_ml);
802 pulse_ml = NULL;
803 pulse_unlock();
804 params->priority = Priority_Unavailable;
805 return STATUS_SUCCESS;
808 pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL);
810 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION);
811 if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0)
812 goto fail;
814 /* Wait for connection */
815 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0) {
816 pa_context_state_t state = pa_context_get_state(pulse_ctx);
818 if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
819 goto fail;
821 if (state == PA_CONTEXT_READY)
822 break;
825 if (pa_context_get_state(pulse_ctx) != PA_CONTEXT_READY)
826 goto fail;
828 TRACE("Test-connected to server %s with protocol version: %i.\n",
829 pa_context_get_server(pulse_ctx),
830 pa_context_get_server_protocol_version(pulse_ctx));
832 free_phys_device_lists();
833 list_init(&g_phys_speakers);
834 list_init(&g_phys_sources);
836 /* Burnout Paradise Remastered expects device name to have a space. */
837 pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, 0, "", "PulseAudio Output");
838 pulse_add_device(&g_phys_sources, NULL, 0, Microphone, 0, "", "PulseAudio Input");
840 o = pa_context_get_sink_info_list(pulse_ctx, &pulse_phys_speakers_cb, NULL);
841 if (o) {
842 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
843 pa_operation_get_state(o) == PA_OPERATION_RUNNING)
845 pa_operation_unref(o);
848 o = pa_context_get_source_info_list(pulse_ctx, &pulse_phys_sources_cb, NULL);
849 if (o) {
850 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
851 pa_operation_get_state(o) == PA_OPERATION_RUNNING)
853 pa_operation_unref(o);
856 LIST_FOR_EACH_ENTRY(dev, &g_phys_speakers, PhysDevice, entry) {
857 pulse_probe_settings(1, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
860 LIST_FOR_EACH_ENTRY(dev, &g_phys_sources, PhysDevice, entry) {
861 pulse_probe_settings(0, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
864 pa_context_unref(pulse_ctx);
865 pulse_ctx = NULL;
866 pa_mainloop_free(pulse_ml);
867 pulse_ml = NULL;
869 pulse_unlock();
871 params->priority = Priority_Preferred;
872 return STATUS_SUCCESS;
874 fail:
875 pa_context_unref(pulse_ctx);
876 pulse_ctx = NULL;
877 pa_mainloop_free(pulse_ml);
878 pulse_ml = NULL;
879 pulse_unlock();
880 params->priority = Priority_Unavailable;
881 return STATUS_SUCCESS;
884 static UINT get_channel_mask(unsigned int channels)
886 switch(channels) {
887 case 0:
888 return 0;
889 case 1:
890 return KSAUDIO_SPEAKER_MONO;
891 case 2:
892 return KSAUDIO_SPEAKER_STEREO;
893 case 3:
894 return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
895 case 4:
896 return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
897 case 5:
898 return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
899 case 6:
900 return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
901 case 7:
902 return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
903 case 8:
904 return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
906 FIXME("Unknown speaker configuration: %u\n", channels);
907 return 0;
910 static const enum pa_channel_position pulse_pos_from_wfx[] = {
911 PA_CHANNEL_POSITION_FRONT_LEFT,
912 PA_CHANNEL_POSITION_FRONT_RIGHT,
913 PA_CHANNEL_POSITION_FRONT_CENTER,
914 PA_CHANNEL_POSITION_LFE,
915 PA_CHANNEL_POSITION_REAR_LEFT,
916 PA_CHANNEL_POSITION_REAR_RIGHT,
917 PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
918 PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
919 PA_CHANNEL_POSITION_REAR_CENTER,
920 PA_CHANNEL_POSITION_SIDE_LEFT,
921 PA_CHANNEL_POSITION_SIDE_RIGHT,
922 PA_CHANNEL_POSITION_TOP_CENTER,
923 PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
924 PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
925 PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
926 PA_CHANNEL_POSITION_TOP_REAR_LEFT,
927 PA_CHANNEL_POSITION_TOP_REAR_CENTER,
928 PA_CHANNEL_POSITION_TOP_REAR_RIGHT
931 static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAVEFORMATEX *fmt)
933 pa_channel_map_init(&stream->map);
934 stream->ss.rate = fmt->nSamplesPerSec;
935 stream->ss.format = PA_SAMPLE_INVALID;
937 switch(fmt->wFormatTag) {
938 case WAVE_FORMAT_IEEE_FLOAT:
939 if (!fmt->nChannels || fmt->nChannels > 2 || fmt->wBitsPerSample != 32)
940 break;
941 stream->ss.format = PA_SAMPLE_FLOAT32LE;
942 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
943 break;
944 case WAVE_FORMAT_PCM:
945 if (!fmt->nChannels || fmt->nChannels > 2)
946 break;
947 if (fmt->wBitsPerSample == 8)
948 stream->ss.format = PA_SAMPLE_U8;
949 else if (fmt->wBitsPerSample == 16)
950 stream->ss.format = PA_SAMPLE_S16LE;
951 else
952 return AUDCLNT_E_UNSUPPORTED_FORMAT;
953 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
954 break;
955 case WAVE_FORMAT_EXTENSIBLE: {
956 WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE*)fmt;
957 UINT mask = wfe->dwChannelMask;
958 unsigned i = 0, j;
959 if (fmt->cbSize != (sizeof(*wfe) - sizeof(*fmt)) && fmt->cbSize != sizeof(*wfe))
960 break;
961 if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
962 (!wfe->Samples.wValidBitsPerSample || wfe->Samples.wValidBitsPerSample == 32) &&
963 fmt->wBitsPerSample == 32)
964 stream->ss.format = PA_SAMPLE_FLOAT32LE;
965 else if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
966 DWORD valid = wfe->Samples.wValidBitsPerSample;
967 if (!valid)
968 valid = fmt->wBitsPerSample;
969 if (!valid || valid > fmt->wBitsPerSample)
970 break;
971 switch (fmt->wBitsPerSample) {
972 case 8:
973 if (valid == 8)
974 stream->ss.format = PA_SAMPLE_U8;
975 break;
976 case 16:
977 if (valid == 16)
978 stream->ss.format = PA_SAMPLE_S16LE;
979 break;
980 case 24:
981 if (valid == 24)
982 stream->ss.format = PA_SAMPLE_S24LE;
983 break;
984 case 32:
985 if (valid == 24)
986 stream->ss.format = PA_SAMPLE_S24_32LE;
987 else if (valid == 32)
988 stream->ss.format = PA_SAMPLE_S32LE;
989 break;
990 default:
991 return AUDCLNT_E_UNSUPPORTED_FORMAT;
994 stream->map.channels = fmt->nChannels;
995 if (!mask || (mask & (SPEAKER_ALL|SPEAKER_RESERVED)))
996 mask = get_channel_mask(fmt->nChannels);
997 for (j = 0; j < ARRAY_SIZE(pulse_pos_from_wfx) && i < fmt->nChannels; ++j) {
998 if (mask & (1 << j))
999 stream->map.map[i++] = pulse_pos_from_wfx[j];
1002 /* Special case for mono since pulse appears to map it differently */
1003 if (mask == SPEAKER_FRONT_CENTER)
1004 stream->map.map[0] = PA_CHANNEL_POSITION_MONO;
1006 if (i < fmt->nChannels || (mask & SPEAKER_RESERVED)) {
1007 stream->map.channels = 0;
1008 ERR("Invalid channel mask: %i/%i and %x(%x)\n", i, fmt->nChannels, mask, (unsigned)wfe->dwChannelMask);
1009 break;
1011 break;
1013 case WAVE_FORMAT_ALAW:
1014 case WAVE_FORMAT_MULAW:
1015 if (fmt->wBitsPerSample != 8) {
1016 FIXME("Unsupported bpp %u for LAW\n", fmt->wBitsPerSample);
1017 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1019 if (fmt->nChannels != 1 && fmt->nChannels != 2) {
1020 FIXME("Unsupported channels %u for LAW\n", fmt->nChannels);
1021 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1023 stream->ss.format = fmt->wFormatTag == WAVE_FORMAT_MULAW ? PA_SAMPLE_ULAW : PA_SAMPLE_ALAW;
1024 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
1025 break;
1026 default:
1027 WARN("Unhandled tag %x\n", fmt->wFormatTag);
1028 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1030 stream->ss.channels = stream->map.channels;
1031 if (!pa_channel_map_valid(&stream->map) || stream->ss.format == PA_SAMPLE_INVALID) {
1032 ERR("Invalid format! Channel spec valid: %i, format: %i\n",
1033 pa_channel_map_valid(&stream->map), stream->ss.format);
1034 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1036 return S_OK;
1039 static HRESULT pulse_stream_connect(struct pulse_stream *stream, const char *pulse_name, UINT32 period_bytes)
1041 pa_stream_flags_t flags = PA_STREAM_START_CORKED | PA_STREAM_START_UNMUTED | PA_STREAM_ADJUST_LATENCY;
1042 int ret;
1043 char buffer[64];
1044 static LONG number;
1045 pa_buffer_attr attr;
1047 ret = InterlockedIncrement(&number);
1048 sprintf(buffer, "audio stream #%i", ret);
1049 stream->stream = pa_stream_new(pulse_ctx, buffer, &stream->ss, &stream->map);
1051 if (!stream->stream) {
1052 WARN("pa_stream_new returned error %i\n", pa_context_errno(pulse_ctx));
1053 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1056 pa_stream_set_state_callback(stream->stream, pulse_stream_state, stream);
1057 pa_stream_set_buffer_attr_callback(stream->stream, pulse_attr_update, stream);
1058 pa_stream_set_moved_callback(stream->stream, pulse_attr_update, stream);
1060 /* PulseAudio will fill in correct values */
1061 attr.minreq = attr.fragsize = period_bytes;
1062 attr.tlength = period_bytes * 3;
1063 attr.maxlength = stream->bufsize_frames * pa_frame_size(&stream->ss);
1064 attr.prebuf = pa_frame_size(&stream->ss);
1065 dump_attr(&attr);
1067 /* If specific device was requested, use it exactly */
1068 if (pulse_name[0])
1069 flags |= PA_STREAM_DONT_MOVE;
1070 else
1071 pulse_name = NULL; /* use default */
1073 if (stream->dataflow == eRender)
1074 ret = pa_stream_connect_playback(stream->stream, pulse_name, &attr, flags, NULL, NULL);
1075 else
1076 ret = pa_stream_connect_record(stream->stream, pulse_name, &attr, flags);
1077 if (ret < 0) {
1078 WARN("Returns %i\n", ret);
1079 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1081 while (pa_stream_get_state(stream->stream) == PA_STREAM_CREATING)
1082 pulse_cond_wait();
1083 if (pa_stream_get_state(stream->stream) != PA_STREAM_READY)
1084 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1086 if (stream->dataflow == eRender) {
1087 pa_stream_set_underflow_callback(stream->stream, pulse_underflow_callback, stream);
1088 pa_stream_set_started_callback(stream->stream, pulse_started_callback, stream);
1090 return S_OK;
1093 static HRESULT get_device_period_helper(EDataFlow flow, const char *pulse_name, REFERENCE_TIME *def, REFERENCE_TIME *min)
1095 struct list *list = (flow == eRender) ? &g_phys_speakers : &g_phys_sources;
1096 PhysDevice *dev;
1098 if (!def && !min) {
1099 return E_POINTER;
1102 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
1103 if (strcmp(pulse_name, dev->pulse_name))
1104 continue;
1106 if (def)
1107 *def = dev->def_period;
1108 if (min)
1109 *min = dev->min_period;
1110 return S_OK;
1113 return E_FAIL;
1116 static NTSTATUS pulse_create_stream(void *args)
1118 struct create_stream_params *params = args;
1119 REFERENCE_TIME period, duration = params->duration;
1120 struct pulse_stream *stream;
1121 unsigned int i, bufsize_bytes;
1122 HRESULT hr;
1123 char *name;
1125 if (params->share == AUDCLNT_SHAREMODE_EXCLUSIVE) {
1126 params->result = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
1127 return STATUS_SUCCESS;
1130 pulse_lock();
1132 name = wstr_to_str(params->name);
1133 params->result = pulse_connect(name);
1134 free(name);
1136 if (FAILED(params->result))
1138 pulse_unlock();
1139 return STATUS_SUCCESS;
1142 if (!(stream = calloc(1, sizeof(*stream))))
1144 pulse_unlock();
1145 params->result = E_OUTOFMEMORY;
1146 return STATUS_SUCCESS;
1149 stream->dataflow = params->flow;
1150 for (i = 0; i < ARRAY_SIZE(stream->vol); ++i)
1151 stream->vol[i] = 1.f;
1153 hr = pulse_spec_from_waveformat(stream, params->fmt);
1154 TRACE("Obtaining format returns %08x\n", (unsigned)hr);
1156 if (FAILED(hr))
1157 goto exit;
1159 period = 0;
1160 hr = get_device_period_helper(params->flow, params->device, &period, NULL);
1161 if (FAILED(hr))
1162 goto exit;
1164 if (duration < 3 * period)
1165 duration = 3 * period;
1167 stream->def_period = period;
1169 stream->period_bytes = pa_frame_size(&stream->ss) * muldiv(period, stream->ss.rate, 10000000);
1171 stream->bufsize_frames = ceil((duration / 10000000.) * params->fmt->nSamplesPerSec);
1172 bufsize_bytes = stream->bufsize_frames * pa_frame_size(&stream->ss);
1173 stream->mmdev_period_usec = period / 10;
1175 stream->share = params->share;
1176 stream->flags = params->flags;
1177 hr = pulse_stream_connect(stream, params->device, stream->period_bytes);
1178 if (SUCCEEDED(hr)) {
1179 UINT32 unalign;
1180 const pa_buffer_attr *attr = pa_stream_get_buffer_attr(stream->stream);
1181 SIZE_T size;
1183 stream->attr = *attr;
1184 /* Update frames according to new size */
1185 dump_attr(attr);
1186 if (stream->dataflow == eRender) {
1187 size = stream->real_bufsize_bytes =
1188 stream->bufsize_frames * 2 * pa_frame_size(&stream->ss);
1189 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1190 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1191 hr = E_OUTOFMEMORY;
1192 } else {
1193 UINT32 i, capture_packets;
1195 if ((unalign = bufsize_bytes % stream->period_bytes))
1196 bufsize_bytes += stream->period_bytes - unalign;
1197 stream->bufsize_frames = bufsize_bytes / pa_frame_size(&stream->ss);
1198 stream->real_bufsize_bytes = bufsize_bytes;
1200 capture_packets = stream->real_bufsize_bytes / stream->period_bytes;
1202 size = stream->real_bufsize_bytes + capture_packets * sizeof(ACPacket);
1203 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1204 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1205 hr = E_OUTOFMEMORY;
1206 else {
1207 ACPacket *cur_packet = (ACPacket*)((char*)stream->local_buffer + stream->real_bufsize_bytes);
1208 BYTE *data = stream->local_buffer;
1209 silence_buffer(stream->ss.format, stream->local_buffer, stream->real_bufsize_bytes);
1210 list_init(&stream->packet_free_head);
1211 list_init(&stream->packet_filled_head);
1212 for (i = 0; i < capture_packets; ++i, ++cur_packet) {
1213 list_add_tail(&stream->packet_free_head, &cur_packet->entry);
1214 cur_packet->data = data;
1215 data += stream->period_bytes;
1221 *params->channel_count = stream->ss.channels;
1222 *params->stream = (stream_handle)(UINT_PTR)stream;
1224 exit:
1225 if (FAILED(params->result = hr)) {
1226 free(stream->local_buffer);
1227 if (stream->stream) {
1228 pa_stream_disconnect(stream->stream);
1229 pa_stream_unref(stream->stream);
1231 free(stream);
1234 pulse_unlock();
1235 return STATUS_SUCCESS;
1238 static NTSTATUS pulse_release_stream(void *args)
1240 struct release_stream_params *params = args;
1241 struct pulse_stream *stream = handle_get_stream(params->stream);
1242 SIZE_T size;
1244 if(params->timer_thread) {
1245 stream->please_quit = TRUE;
1246 NtWaitForSingleObject(params->timer_thread, FALSE, NULL);
1247 NtClose(params->timer_thread);
1250 pulse_lock();
1251 if (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream))) {
1252 pa_stream_disconnect(stream->stream);
1253 while (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream)))
1254 pulse_cond_wait();
1256 pa_stream_unref(stream->stream);
1257 pulse_unlock();
1259 if (stream->tmp_buffer) {
1260 size = 0;
1261 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1262 &size, MEM_RELEASE);
1264 if (stream->local_buffer) {
1265 size = 0;
1266 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1267 &size, MEM_RELEASE);
1269 free(stream->peek_buffer);
1270 free(stream);
1271 return STATUS_SUCCESS;
1274 static int write_buffer(const struct pulse_stream *stream, BYTE *buffer, UINT32 bytes)
1276 const float *vol = stream->vol;
1277 UINT32 i, channels, mute = 0;
1278 BOOL adjust = FALSE;
1279 BYTE *end;
1281 if (!bytes) return 0;
1283 /* Adjust the buffer based on the volume for each channel */
1284 channels = stream->ss.channels;
1285 for (i = 0; i < channels; i++)
1287 adjust |= vol[i] != 1.0f;
1288 if (vol[i] == 0.0f)
1289 mute++;
1291 if (mute == channels)
1293 silence_buffer(stream->ss.format, buffer, bytes);
1294 goto write;
1296 if (!adjust) goto write;
1298 end = buffer + bytes;
1299 switch (stream->ss.format)
1301 #ifndef WORDS_BIGENDIAN
1302 #define PROCESS_BUFFER(type) do \
1304 type *p = (type*)buffer; \
1305 do \
1307 for (i = 0; i < channels; i++) \
1308 p[i] = p[i] * vol[i]; \
1309 p += i; \
1310 } while ((BYTE*)p != end); \
1311 } while (0)
1312 case PA_SAMPLE_S16LE:
1313 PROCESS_BUFFER(INT16);
1314 break;
1315 case PA_SAMPLE_S32LE:
1316 PROCESS_BUFFER(INT32);
1317 break;
1318 case PA_SAMPLE_FLOAT32LE:
1319 PROCESS_BUFFER(float);
1320 break;
1321 #undef PROCESS_BUFFER
1322 case PA_SAMPLE_S24_32LE:
1324 UINT32 *p = (UINT32*)buffer;
1327 for (i = 0; i < channels; i++)
1329 p[i] = (INT32)((INT32)(p[i] << 8) * vol[i]);
1330 p[i] >>= 8;
1332 p += i;
1333 } while ((BYTE*)p != end);
1334 break;
1336 case PA_SAMPLE_S24LE:
1338 /* do it 12 bytes at a time until it is no longer possible */
1339 UINT32 *q = (UINT32*)buffer;
1340 BYTE *p;
1342 i = 0;
1343 while (end - (BYTE*)q >= 12)
1345 UINT32 v[4], k;
1346 v[0] = q[0] << 8;
1347 v[1] = q[1] << 16 | (q[0] >> 16 & ~0xff);
1348 v[2] = q[2] << 24 | (q[1] >> 8 & ~0xff);
1349 v[3] = q[2] & ~0xff;
1350 for (k = 0; k < 4; k++)
1352 v[k] = (INT32)((INT32)v[k] * vol[i]);
1353 if (++i == channels) i = 0;
1355 *q++ = v[0] >> 8 | (v[1] & ~0xff) << 16;
1356 *q++ = v[1] >> 16 | (v[2] & ~0xff) << 8;
1357 *q++ = v[2] >> 24 | (v[3] & ~0xff);
1359 p = (BYTE*)q;
1360 while (p != end)
1362 UINT32 v = (INT32)((INT32)(p[0] << 8 | p[1] << 16 | p[2] << 24) * vol[i]);
1363 *p++ = v >> 8 & 0xff;
1364 *p++ = v >> 16 & 0xff;
1365 *p++ = v >> 24;
1366 if (++i == channels) i = 0;
1368 break;
1370 #endif
1371 case PA_SAMPLE_U8:
1373 UINT8 *p = (UINT8*)buffer;
1376 for (i = 0; i < channels; i++)
1377 p[i] = (int)((p[i] - 128) * vol[i]) + 128;
1378 p += i;
1379 } while ((BYTE*)p != end);
1380 break;
1382 case PA_SAMPLE_ALAW:
1384 UINT8 *p = (UINT8*)buffer;
1387 for (i = 0; i < channels; i++)
1388 p[i] = mult_alaw_sample(p[i], vol[i]);
1389 p += i;
1390 } while ((BYTE*)p != end);
1391 break;
1393 case PA_SAMPLE_ULAW:
1395 UINT8 *p = (UINT8*)buffer;
1398 for (i = 0; i < channels; i++)
1399 p[i] = mult_ulaw_sample(p[i], vol[i]);
1400 p += i;
1401 } while ((BYTE*)p != end);
1402 break;
1404 default:
1405 TRACE("Unhandled format %i, not adjusting volume.\n", stream->ss.format);
1406 break;
1409 write:
1410 return pa_stream_write(stream->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
1413 static void pulse_write(struct pulse_stream *stream)
1415 /* write as much data to PA as we can */
1416 UINT32 to_write;
1417 BYTE *buf = stream->local_buffer + stream->pa_offs_bytes;
1418 UINT32 bytes = pa_stream_writable_size(stream->stream);
1420 if (stream->just_underran)
1422 /* prebuffer with silence if needed */
1423 if(stream->pa_held_bytes < bytes){
1424 to_write = bytes - stream->pa_held_bytes;
1425 TRACE("prebuffering %u frames of silence\n",
1426 (int)(to_write / pa_frame_size(&stream->ss)));
1427 buf = calloc(1, to_write);
1428 pa_stream_write(stream->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
1429 free(buf);
1432 stream->just_underran = FALSE;
1435 buf = stream->local_buffer + stream->pa_offs_bytes;
1436 TRACE("held: %lu, avail: %u\n", stream->pa_held_bytes, bytes);
1437 bytes = min(stream->pa_held_bytes, bytes);
1439 if (stream->pa_offs_bytes + bytes > stream->real_bufsize_bytes)
1441 to_write = stream->real_bufsize_bytes - stream->pa_offs_bytes;
1442 TRACE("writing small chunk of %u bytes\n", to_write);
1443 write_buffer(stream, buf, to_write);
1444 stream->pa_held_bytes -= to_write;
1445 to_write = bytes - to_write;
1446 stream->pa_offs_bytes = 0;
1447 buf = stream->local_buffer;
1449 else
1450 to_write = bytes;
1452 TRACE("writing main chunk of %u bytes\n", to_write);
1453 write_buffer(stream, buf, to_write);
1454 stream->pa_offs_bytes += to_write;
1455 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1456 stream->pa_held_bytes -= to_write;
1459 static void pulse_read(struct pulse_stream *stream)
1461 size_t bytes = pa_stream_readable_size(stream->stream);
1463 TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(stream->stream)->fragsize);
1465 bytes += stream->peek_len - stream->peek_ofs;
1467 while (bytes >= stream->period_bytes)
1469 BYTE *dst = NULL, *src;
1470 size_t src_len, copy, rem = stream->period_bytes;
1472 if (stream->started)
1474 LARGE_INTEGER stamp, freq;
1475 ACPacket *p, *next;
1477 if (!(p = (ACPacket*)list_head(&stream->packet_free_head)))
1479 p = (ACPacket*)list_head(&stream->packet_filled_head);
1480 if (!p) return;
1481 if (!p->discont) {
1482 next = (ACPacket*)p->entry.next;
1483 next->discont = 1;
1484 } else
1485 p = (ACPacket*)list_tail(&stream->packet_filled_head);
1487 else
1489 stream->held_bytes += stream->period_bytes;
1491 NtQueryPerformanceCounter(&stamp, &freq);
1492 p->qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
1493 p->discont = 0;
1494 list_remove(&p->entry);
1495 list_add_tail(&stream->packet_filled_head, &p->entry);
1497 dst = p->data;
1500 while (rem)
1502 if (stream->peek_len)
1504 copy = min(rem, stream->peek_len - stream->peek_ofs);
1506 if (dst)
1508 memcpy(dst, stream->peek_buffer + stream->peek_ofs, copy);
1509 dst += copy;
1512 rem -= copy;
1513 stream->peek_ofs += copy;
1514 if(stream->peek_len == stream->peek_ofs)
1515 stream->peek_len = stream->peek_ofs = 0;
1518 else if (pa_stream_peek(stream->stream, (const void**)&src, &src_len) == 0 && src_len)
1520 copy = min(rem, src_len);
1522 if (dst) {
1523 if(src)
1524 memcpy(dst, src, copy);
1525 else
1526 silence_buffer(stream->ss.format, dst, copy);
1528 dst += copy;
1531 rem -= copy;
1533 if (copy < src_len)
1535 if (src_len > stream->peek_buffer_len)
1537 free(stream->peek_buffer);
1538 stream->peek_buffer = malloc(src_len);
1539 stream->peek_buffer_len = src_len;
1542 if(src)
1543 memcpy(stream->peek_buffer, src + copy, src_len - copy);
1544 else
1545 silence_buffer(stream->ss.format, stream->peek_buffer, src_len - copy);
1547 stream->peek_len = src_len - copy;
1548 stream->peek_ofs = 0;
1551 pa_stream_drop(stream->stream);
1555 bytes -= stream->period_bytes;
1559 static NTSTATUS pulse_timer_loop(void *args)
1561 struct timer_loop_params *params = args;
1562 struct pulse_stream *stream = handle_get_stream(params->stream);
1563 LARGE_INTEGER delay;
1564 pa_usec_t last_time;
1565 UINT32 adv_bytes;
1566 int success;
1567 pa_operation *o;
1569 pulse_lock();
1570 delay.QuadPart = -stream->mmdev_period_usec * 10;
1571 pa_stream_get_time(stream->stream, &last_time);
1572 pulse_unlock();
1574 while (!stream->please_quit)
1576 pa_usec_t now, adv_usec = 0;
1577 int err;
1579 NtDelayExecution(FALSE, &delay);
1581 pulse_lock();
1583 delay.QuadPart = -stream->mmdev_period_usec * 10;
1585 o = pa_stream_update_timing_info(stream->stream, pulse_op_cb, &success);
1586 if (o)
1588 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1589 pulse_cond_wait();
1590 pa_operation_unref(o);
1592 err = pa_stream_get_time(stream->stream, &now);
1593 if (err == 0)
1595 TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(last_time));
1596 if (stream->started && (stream->dataflow == eCapture || stream->held_bytes))
1598 if(stream->just_underran)
1600 last_time = now;
1601 stream->just_started = TRUE;
1604 if (stream->just_started)
1606 /* let it play out a period to absorb some latency and get accurate timing */
1607 pa_usec_t diff = now - last_time;
1609 if (diff > stream->mmdev_period_usec)
1611 stream->just_started = FALSE;
1612 last_time = now;
1615 else
1617 INT32 adjust = last_time + stream->mmdev_period_usec - now;
1619 adv_usec = now - last_time;
1621 if(adjust > ((INT32)(stream->mmdev_period_usec / 2)))
1622 adjust = stream->mmdev_period_usec / 2;
1623 else if(adjust < -((INT32)(stream->mmdev_period_usec / 2)))
1624 adjust = -1 * stream->mmdev_period_usec / 2;
1626 delay.QuadPart = -(stream->mmdev_period_usec + adjust) * 10;
1628 last_time += stream->mmdev_period_usec;
1631 if (stream->dataflow == eRender)
1633 pulse_write(stream);
1635 /* regardless of what PA does, advance one period */
1636 adv_bytes = min(stream->period_bytes, stream->held_bytes);
1637 stream->lcl_offs_bytes += adv_bytes;
1638 stream->lcl_offs_bytes %= stream->real_bufsize_bytes;
1639 stream->held_bytes -= adv_bytes;
1641 else if(stream->dataflow == eCapture)
1643 pulse_read(stream);
1646 else
1648 last_time = now;
1649 delay.QuadPart = -stream->mmdev_period_usec * 10;
1653 if (stream->event)
1654 NtSetEvent(stream->event, NULL);
1656 TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n",
1657 stream, (int)adv_usec,
1658 (int)(stream->held_bytes/ pa_frame_size(&stream->ss)),
1659 (unsigned int)(-delay.QuadPart / 10));
1661 pulse_unlock();
1664 return STATUS_SUCCESS;
1667 static NTSTATUS pulse_start(void *args)
1669 struct start_params *params = args;
1670 struct pulse_stream *stream = handle_get_stream(params->stream);
1671 int success;
1672 pa_operation *o;
1674 params->result = S_OK;
1675 pulse_lock();
1676 if (!pulse_stream_valid(stream))
1678 pulse_unlock();
1679 params->result = S_OK;
1680 return STATUS_SUCCESS;
1683 if ((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event)
1685 pulse_unlock();
1686 params->result = AUDCLNT_E_EVENTHANDLE_NOT_SET;
1687 return STATUS_SUCCESS;
1690 if (stream->started)
1692 pulse_unlock();
1693 params->result = AUDCLNT_E_NOT_STOPPED;
1694 return STATUS_SUCCESS;
1697 pulse_write(stream);
1699 if (pa_stream_is_corked(stream->stream))
1701 o = pa_stream_cork(stream->stream, 0, pulse_op_cb, &success);
1702 if (o)
1704 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1705 pulse_cond_wait();
1706 pa_operation_unref(o);
1708 else
1709 success = 0;
1710 if (!success)
1711 params->result = E_FAIL;
1714 if (SUCCEEDED(params->result))
1716 stream->started = TRUE;
1717 stream->just_started = TRUE;
1719 pulse_unlock();
1720 return STATUS_SUCCESS;
1723 static NTSTATUS pulse_stop(void *args)
1725 struct stop_params *params = args;
1726 struct pulse_stream *stream = handle_get_stream(params->stream);
1727 pa_operation *o;
1728 int success;
1730 pulse_lock();
1731 if (!pulse_stream_valid(stream))
1733 pulse_unlock();
1734 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1735 return STATUS_SUCCESS;
1738 if (!stream->started)
1740 pulse_unlock();
1741 params->result = S_FALSE;
1742 return STATUS_SUCCESS;
1745 params->result = S_OK;
1746 if (stream->dataflow == eRender)
1748 o = pa_stream_cork(stream->stream, 1, pulse_op_cb, &success);
1749 if (o)
1751 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1752 pulse_cond_wait();
1753 pa_operation_unref(o);
1755 else
1756 success = 0;
1757 if (!success)
1758 params->result = E_FAIL;
1760 if (SUCCEEDED(params->result))
1761 stream->started = FALSE;
1762 pulse_unlock();
1763 return STATUS_SUCCESS;
1766 static NTSTATUS pulse_reset(void *args)
1768 struct reset_params *params = args;
1769 struct pulse_stream *stream = handle_get_stream(params->stream);
1771 pulse_lock();
1772 if (!pulse_stream_valid(stream))
1774 pulse_unlock();
1775 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1776 return STATUS_SUCCESS;
1779 if (stream->started)
1781 pulse_unlock();
1782 params->result = AUDCLNT_E_NOT_STOPPED;
1783 return STATUS_SUCCESS;
1786 if (stream->locked)
1788 pulse_unlock();
1789 params->result = AUDCLNT_E_BUFFER_OPERATION_PENDING;
1790 return STATUS_SUCCESS;
1793 if (stream->dataflow == eRender)
1795 /* If there is still data in the render buffer it needs to be removed from the server */
1796 int success = 0;
1797 if (stream->held_bytes)
1799 pa_operation *o = pa_stream_flush(stream->stream, pulse_op_cb, &success);
1800 if (o)
1802 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1803 pulse_cond_wait();
1804 pa_operation_unref(o);
1807 if (success || !stream->held_bytes)
1809 stream->clock_lastpos = stream->clock_written = 0;
1810 stream->pa_offs_bytes = stream->lcl_offs_bytes = 0;
1811 stream->held_bytes = stream->pa_held_bytes = 0;
1814 else
1816 ACPacket *p;
1817 stream->clock_written += stream->held_bytes;
1818 stream->held_bytes = 0;
1820 if ((p = stream->locked_ptr))
1822 stream->locked_ptr = NULL;
1823 list_add_tail(&stream->packet_free_head, &p->entry);
1825 list_move_tail(&stream->packet_free_head, &stream->packet_filled_head);
1827 pulse_unlock();
1828 params->result = S_OK;
1829 return STATUS_SUCCESS;
1832 static BOOL alloc_tmp_buffer(struct pulse_stream *stream, SIZE_T bytes)
1834 SIZE_T size;
1836 if (stream->tmp_buffer_bytes >= bytes)
1837 return TRUE;
1839 if (stream->tmp_buffer)
1841 size = 0;
1842 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1843 &size, MEM_RELEASE);
1844 stream->tmp_buffer = NULL;
1845 stream->tmp_buffer_bytes = 0;
1847 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1848 zero_bits, &bytes, MEM_COMMIT, PAGE_READWRITE))
1849 return FALSE;
1851 stream->tmp_buffer_bytes = bytes;
1852 return TRUE;
1855 static UINT32 pulse_render_padding(struct pulse_stream *stream)
1857 return stream->held_bytes / pa_frame_size(&stream->ss);
1860 static UINT32 pulse_capture_padding(struct pulse_stream *stream)
1862 ACPacket *packet = stream->locked_ptr;
1863 if (!packet && !list_empty(&stream->packet_filled_head))
1865 packet = (ACPacket*)list_head(&stream->packet_filled_head);
1866 stream->locked_ptr = packet;
1867 list_remove(&packet->entry);
1869 return stream->held_bytes / pa_frame_size(&stream->ss);
1872 static NTSTATUS pulse_get_render_buffer(void *args)
1874 struct get_render_buffer_params *params = args;
1875 struct pulse_stream *stream = handle_get_stream(params->stream);
1876 size_t bytes;
1877 UINT32 wri_offs_bytes;
1879 pulse_lock();
1880 if (!pulse_stream_valid(stream))
1882 pulse_unlock();
1883 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1884 return STATUS_SUCCESS;
1887 if (stream->locked)
1889 pulse_unlock();
1890 params->result = AUDCLNT_E_OUT_OF_ORDER;
1891 return STATUS_SUCCESS;
1894 if (!params->frames)
1896 pulse_unlock();
1897 *params->data = NULL;
1898 params->result = S_OK;
1899 return STATUS_SUCCESS;
1902 if (stream->held_bytes / pa_frame_size(&stream->ss) + params->frames > stream->bufsize_frames)
1904 pulse_unlock();
1905 params->result = AUDCLNT_E_BUFFER_TOO_LARGE;
1906 return STATUS_SUCCESS;
1909 bytes = params->frames * pa_frame_size(&stream->ss);
1910 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1911 if (wri_offs_bytes + bytes > stream->real_bufsize_bytes)
1913 if (!alloc_tmp_buffer(stream, bytes))
1915 pulse_unlock();
1916 params->result = E_OUTOFMEMORY;
1917 return STATUS_SUCCESS;
1919 *params->data = stream->tmp_buffer;
1920 stream->locked = -bytes;
1922 else
1924 *params->data = stream->local_buffer + wri_offs_bytes;
1925 stream->locked = bytes;
1928 silence_buffer(stream->ss.format, *params->data, bytes);
1930 pulse_unlock();
1931 params->result = S_OK;
1932 return STATUS_SUCCESS;
1935 static void pulse_wrap_buffer(struct pulse_stream *stream, BYTE *buffer, UINT32 written_bytes)
1937 UINT32 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1938 UINT32 chunk_bytes = stream->real_bufsize_bytes - wri_offs_bytes;
1940 if (written_bytes <= chunk_bytes)
1942 memcpy(stream->local_buffer + wri_offs_bytes, buffer, written_bytes);
1944 else
1946 memcpy(stream->local_buffer + wri_offs_bytes, buffer, chunk_bytes);
1947 memcpy(stream->local_buffer, buffer + chunk_bytes, written_bytes - chunk_bytes);
1951 static NTSTATUS pulse_release_render_buffer(void *args)
1953 struct release_render_buffer_params *params = args;
1954 struct pulse_stream *stream = handle_get_stream(params->stream);
1955 UINT32 written_bytes;
1956 BYTE *buffer;
1958 pulse_lock();
1959 if (!stream->locked || !params->written_frames)
1961 stream->locked = 0;
1962 pulse_unlock();
1963 params->result = params->written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1964 return STATUS_SUCCESS;
1967 if (params->written_frames * pa_frame_size(&stream->ss) >
1968 (stream->locked >= 0 ? stream->locked : -stream->locked))
1970 pulse_unlock();
1971 params->result = AUDCLNT_E_INVALID_SIZE;
1972 return STATUS_SUCCESS;
1975 if (stream->locked >= 0)
1976 buffer = stream->local_buffer + (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1977 else
1978 buffer = stream->tmp_buffer;
1980 written_bytes = params->written_frames * pa_frame_size(&stream->ss);
1981 if (params->flags & AUDCLNT_BUFFERFLAGS_SILENT)
1982 silence_buffer(stream->ss.format, buffer, written_bytes);
1984 if (stream->locked < 0)
1985 pulse_wrap_buffer(stream, buffer, written_bytes);
1987 stream->held_bytes += written_bytes;
1988 stream->pa_held_bytes += written_bytes;
1989 if (stream->pa_held_bytes > stream->real_bufsize_bytes)
1991 stream->pa_offs_bytes += stream->pa_held_bytes - stream->real_bufsize_bytes;
1992 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1993 stream->pa_held_bytes = stream->real_bufsize_bytes;
1995 stream->clock_written += written_bytes;
1996 stream->locked = 0;
1998 /* push as much data as we can to pulseaudio too */
1999 pulse_write(stream);
2001 TRACE("Released %u, held %lu\n", params->written_frames, stream->held_bytes / pa_frame_size(&stream->ss));
2003 pulse_unlock();
2004 params->result = S_OK;
2005 return STATUS_SUCCESS;
2008 static NTSTATUS pulse_get_capture_buffer(void *args)
2010 struct get_capture_buffer_params *params = args;
2011 struct pulse_stream *stream = handle_get_stream(params->stream);
2012 ACPacket *packet;
2014 pulse_lock();
2015 if (!pulse_stream_valid(stream))
2017 pulse_unlock();
2018 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2019 return STATUS_SUCCESS;
2021 if (stream->locked)
2023 pulse_unlock();
2024 params->result = AUDCLNT_E_OUT_OF_ORDER;
2025 return STATUS_SUCCESS;
2028 pulse_capture_padding(stream);
2029 if ((packet = stream->locked_ptr))
2031 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2032 *params->flags = 0;
2033 if (packet->discont)
2034 *params->flags |= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY;
2035 if (params->devpos)
2037 if (packet->discont)
2038 *params->devpos = (stream->clock_written + stream->period_bytes) / pa_frame_size(&stream->ss);
2039 else
2040 *params->devpos = stream->clock_written / pa_frame_size(&stream->ss);
2042 if (params->qpcpos)
2043 *params->qpcpos = packet->qpcpos;
2044 *params->data = packet->data;
2046 else
2047 *params->frames = 0;
2048 stream->locked = *params->frames;
2049 pulse_unlock();
2050 params->result = *params->frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2051 return STATUS_SUCCESS;
2054 static NTSTATUS pulse_release_capture_buffer(void *args)
2056 struct release_capture_buffer_params *params = args;
2057 struct pulse_stream *stream = handle_get_stream(params->stream);
2059 pulse_lock();
2060 if (!stream->locked && params->done)
2062 pulse_unlock();
2063 params->result = AUDCLNT_E_OUT_OF_ORDER;
2064 return STATUS_SUCCESS;
2066 if (params->done && stream->locked != params->done)
2068 pulse_unlock();
2069 params->result = AUDCLNT_E_INVALID_SIZE;
2070 return STATUS_SUCCESS;
2072 if (params->done)
2074 ACPacket *packet = stream->locked_ptr;
2075 stream->locked_ptr = NULL;
2076 stream->held_bytes -= stream->period_bytes;
2077 if (packet->discont)
2078 stream->clock_written += 2 * stream->period_bytes;
2079 else
2080 stream->clock_written += stream->period_bytes;
2081 list_add_tail(&stream->packet_free_head, &packet->entry);
2083 stream->locked = 0;
2084 pulse_unlock();
2085 params->result = S_OK;
2086 return STATUS_SUCCESS;
2089 static NTSTATUS pulse_is_format_supported(void *args)
2091 struct is_format_supported_params *params = args;
2092 WAVEFORMATEXTENSIBLE in;
2093 WAVEFORMATEXTENSIBLE *out;
2094 const WAVEFORMATEX *fmt = &in.Format;
2095 const BOOLEAN exclusive = params->share == AUDCLNT_SHAREMODE_EXCLUSIVE;
2097 params->result = S_OK;
2099 if (!params->fmt_in || (params->share == AUDCLNT_SHAREMODE_SHARED && !params->fmt_out))
2100 params->result = E_POINTER;
2101 else if (params->share != AUDCLNT_SHAREMODE_SHARED && params->share != AUDCLNT_SHAREMODE_EXCLUSIVE)
2102 params->result = E_INVALIDARG;
2103 else {
2104 memcpy(&in, params->fmt_in, params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2105 sizeof(in) : sizeof(in.Format));
2107 if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
2108 if (fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
2109 params->result = E_INVALIDARG;
2110 else if (fmt->nAvgBytesPerSec == 0 || fmt->nBlockAlign == 0 ||
2111 (in.Samples.wValidBitsPerSample > fmt->wBitsPerSample))
2112 params->result = E_INVALIDARG;
2113 else if (fmt->nChannels == 0)
2114 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2118 if (FAILED(params->result))
2119 return STATUS_SUCCESS;
2121 if (exclusive)
2122 out = &in;
2123 else {
2124 out = params->fmt_out;
2125 memcpy(out, fmt, fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2126 sizeof(*out) : sizeof((*out).Format));
2129 switch (fmt->wFormatTag) {
2130 case WAVE_FORMAT_EXTENSIBLE: {
2131 if ((fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) &&
2132 fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE)) ||
2133 fmt->nBlockAlign != fmt->wBitsPerSample / 8 * fmt->nChannels ||
2134 in.Samples.wValidBitsPerSample > fmt->wBitsPerSample ||
2135 fmt->nAvgBytesPerSec != fmt->nBlockAlign * fmt->nSamplesPerSec) {
2136 params->result = E_INVALIDARG;
2137 break;
2140 if (exclusive) {
2141 UINT32 mask = 0, i, channels = 0;
2143 if (!(in.dwChannelMask & (SPEAKER_ALL | SPEAKER_RESERVED))) {
2144 for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) {
2145 if (i & in.dwChannelMask) {
2146 mask |= i;
2147 ++channels;
2151 if (channels != fmt->nChannels || (in.dwChannelMask & ~mask)) {
2152 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2153 break;
2155 } else {
2156 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2157 break;
2161 if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
2162 if (fmt->wBitsPerSample != 32) {
2163 params->result = E_INVALIDARG;
2164 break;
2167 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample) {
2168 params->result = S_FALSE;
2169 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2171 } else if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
2172 if (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8) {
2173 params->result = E_INVALIDARG;
2174 break;
2177 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample &&
2178 !(fmt->wBitsPerSample == 32 &&
2179 in.Samples.wValidBitsPerSample == 24)) {
2180 params->result = S_FALSE;
2181 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2182 break;
2184 } else {
2185 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2186 break;
2189 break;
2191 case WAVE_FORMAT_ALAW:
2192 case WAVE_FORMAT_MULAW:
2193 if (fmt->wBitsPerSample != 8) {
2194 params->result = E_INVALIDARG;
2195 break;
2197 /* Fall-through */
2198 case WAVE_FORMAT_IEEE_FLOAT:
2199 if (fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT && fmt->wBitsPerSample != 32) {
2200 params->result = E_INVALIDARG;
2201 break;
2203 /* Fall-through */
2204 case WAVE_FORMAT_PCM: {
2205 if (fmt->wFormatTag == WAVE_FORMAT_PCM &&
2206 (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8)) {
2207 params->result = E_INVALIDARG;
2208 break;
2211 if (fmt->nChannels > 2) {
2212 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2213 break;
2216 /* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
2217 * ignored, invalid values are happily accepted. */
2218 break;
2220 default:
2221 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2222 break;
2225 if (exclusive) { /* This driver does not support exclusive mode. */
2226 if (params->result == S_OK)
2227 params->result = params->flow == eCapture ?
2228 AUDCLNT_E_UNSUPPORTED_FORMAT :
2229 AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
2230 else if (params->result == S_FALSE)
2231 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2234 return STATUS_SUCCESS;
2237 static NTSTATUS pulse_get_mix_format(void *args)
2239 struct get_mix_format_params *params = args;
2240 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2241 PhysDevice *dev;
2243 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2244 if (strcmp(params->device, dev->pulse_name))
2245 continue;
2247 *params->fmt = dev->fmt;
2248 params->result = S_OK;
2250 return STATUS_SUCCESS;
2253 params->result = E_FAIL;
2254 return STATUS_SUCCESS;
2257 static NTSTATUS pulse_get_device_period(void *args)
2259 struct get_device_period_params *params = args;
2261 params->result = get_device_period_helper(params->flow, params->device, params->def_period, params->min_period);
2262 return STATUS_SUCCESS;
2265 static NTSTATUS pulse_get_buffer_size(void *args)
2267 struct get_buffer_size_params *params = args;
2268 struct pulse_stream *stream = handle_get_stream(params->stream);
2270 params->result = S_OK;
2272 pulse_lock();
2273 if (!pulse_stream_valid(stream))
2274 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2275 else
2276 *params->frames = stream->bufsize_frames;
2277 pulse_unlock();
2279 return STATUS_SUCCESS;
2282 static NTSTATUS pulse_get_latency(void *args)
2284 struct get_latency_params *params = args;
2285 struct pulse_stream *stream = handle_get_stream(params->stream);
2286 const pa_buffer_attr *attr;
2287 REFERENCE_TIME lat;
2289 pulse_lock();
2290 if (!pulse_stream_valid(stream)) {
2291 pulse_unlock();
2292 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2293 return STATUS_SUCCESS;
2295 attr = pa_stream_get_buffer_attr(stream->stream);
2296 if (stream->dataflow == eRender)
2297 lat = attr->minreq / pa_frame_size(&stream->ss);
2298 else
2299 lat = attr->fragsize / pa_frame_size(&stream->ss);
2300 *params->latency = (lat * 10000000) / stream->ss.rate + stream->def_period;
2301 pulse_unlock();
2302 TRACE("Latency: %u ms\n", (unsigned)(*params->latency / 10000));
2303 params->result = S_OK;
2304 return STATUS_SUCCESS;
2307 static NTSTATUS pulse_get_current_padding(void *args)
2309 struct get_current_padding_params *params = args;
2310 struct pulse_stream *stream = handle_get_stream(params->stream);
2312 pulse_lock();
2313 if (!pulse_stream_valid(stream))
2315 pulse_unlock();
2316 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2317 return STATUS_SUCCESS;
2320 if (stream->dataflow == eRender)
2321 *params->padding = pulse_render_padding(stream);
2322 else
2323 *params->padding = pulse_capture_padding(stream);
2324 pulse_unlock();
2326 TRACE("%p Pad: %u ms (%u)\n", stream, muldiv(*params->padding, 1000, stream->ss.rate),
2327 *params->padding);
2328 params->result = S_OK;
2329 return STATUS_SUCCESS;
2332 static NTSTATUS pulse_get_next_packet_size(void *args)
2334 struct get_next_packet_size_params *params = args;
2335 struct pulse_stream *stream = handle_get_stream(params->stream);
2337 pulse_lock();
2338 pulse_capture_padding(stream);
2339 if (stream->locked_ptr)
2340 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2341 else
2342 *params->frames = 0;
2343 pulse_unlock();
2344 params->result = S_OK;
2346 return STATUS_SUCCESS;
2349 static NTSTATUS pulse_get_frequency(void *args)
2351 struct get_frequency_params *params = args;
2352 struct pulse_stream *stream = handle_get_stream(params->stream);
2354 pulse_lock();
2355 if (!pulse_stream_valid(stream))
2357 pulse_unlock();
2358 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2359 return STATUS_SUCCESS;
2362 *params->freq = stream->ss.rate;
2363 if (stream->share == AUDCLNT_SHAREMODE_SHARED)
2364 *params->freq *= pa_frame_size(&stream->ss);
2365 pulse_unlock();
2366 params->result = S_OK;
2367 return STATUS_SUCCESS;
2370 static NTSTATUS pulse_get_position(void *args)
2372 struct get_position_params *params = args;
2373 struct pulse_stream *stream = handle_get_stream(params->stream);
2375 pulse_lock();
2376 if (!pulse_stream_valid(stream))
2378 pulse_unlock();
2379 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2380 return STATUS_SUCCESS;
2383 *params->pos = stream->clock_written - stream->held_bytes;
2385 if (stream->share == AUDCLNT_SHAREMODE_EXCLUSIVE || params->device)
2386 *params->pos /= pa_frame_size(&stream->ss);
2388 /* Make time never go backwards */
2389 if (*params->pos < stream->clock_lastpos)
2390 *params->pos = stream->clock_lastpos;
2391 else
2392 stream->clock_lastpos = *params->pos;
2393 pulse_unlock();
2395 TRACE("%p Position: %u\n", stream, (unsigned)*params->pos);
2397 if (params->qpctime)
2399 LARGE_INTEGER stamp, freq;
2400 NtQueryPerformanceCounter(&stamp, &freq);
2401 *params->qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2404 params->result = S_OK;
2405 return STATUS_SUCCESS;
2408 static NTSTATUS pulse_set_volumes(void *args)
2410 struct set_volumes_params *params = args;
2411 struct pulse_stream *stream = handle_get_stream(params->stream);
2412 unsigned int i;
2414 for (i = 0; i < stream->ss.channels; i++)
2415 stream->vol[i] = params->volumes[i] * params->master_volume * params->session_volumes[i];
2417 return STATUS_SUCCESS;
2420 static NTSTATUS pulse_set_event_handle(void *args)
2422 struct set_event_handle_params *params = args;
2423 struct pulse_stream *stream = handle_get_stream(params->stream);
2424 HRESULT hr = S_OK;
2426 pulse_lock();
2427 if (!pulse_stream_valid(stream))
2428 hr = AUDCLNT_E_DEVICE_INVALIDATED;
2429 else if (!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
2430 hr = AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
2431 else if (stream->event)
2432 hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
2433 else
2434 stream->event = params->event;
2435 pulse_unlock();
2437 params->result = hr;
2438 return STATUS_SUCCESS;
2441 static NTSTATUS pulse_is_started(void *args)
2443 struct is_started_params *params = args;
2444 struct pulse_stream *stream = handle_get_stream(params->stream);
2446 pulse_lock();
2447 params->result = pulse_stream_valid(stream) && stream->started ? S_OK : S_FALSE;
2448 pulse_unlock();
2450 return STATUS_SUCCESS;
2453 static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *params)
2455 const GUID *guid = params->guid;
2456 PROPVARIANT *out = params->value;
2457 UINT serial_number;
2458 char path[128];
2459 int len;
2461 /* As hardly any audio devices have serial numbers, Windows instead
2462 appears to use a persistent random number. We emulate this here
2463 by instead using the last 8 hex digits of the GUID. */
2464 serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
2466 switch (dev->bus_type) {
2467 case phys_device_bus_pci:
2468 len = sprintf(path, "{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2469 break;
2470 case phys_device_bus_usb:
2471 len = sprintf(path, "{1}.USB\\VID_%04X&PID_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2472 break;
2473 default:
2474 len = sprintf(path, "{1}.ROOT\\MEDIA\\%04u", dev->index);
2475 break;
2478 if (*params->buffer_size < ++len * sizeof(WCHAR)) {
2479 params->result = E_NOT_SUFFICIENT_BUFFER;
2480 *params->buffer_size = len * sizeof(WCHAR);
2481 return FALSE;
2484 out->vt = VT_LPWSTR;
2485 out->pwszVal = params->buffer;
2487 ntdll_umbstowcs(path, len, out->pwszVal, len);
2489 params->result = S_OK;
2491 return TRUE;
2494 static NTSTATUS pulse_get_prop_value(void *args)
2496 static const GUID PKEY_AudioEndpoint_GUID = {
2497 0x1da5d803, 0xd492, 0x4edd, {0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e}
2499 static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
2500 {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
2502 struct get_prop_value_params *params = args;
2503 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2504 PhysDevice *dev;
2506 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2507 if (strcmp(params->device, dev->pulse_name))
2508 continue;
2509 if (IsEqualPropertyKey(*params->prop, devicepath_key)) {
2510 get_device_path(dev, params);
2511 return STATUS_SUCCESS;
2512 } else if (IsEqualGUID(&params->prop->fmtid, &PKEY_AudioEndpoint_GUID)) {
2513 switch (params->prop->pid) {
2514 case 0: /* FormFactor */
2515 params->value->vt = VT_UI4;
2516 params->value->ulVal = dev->form;
2517 params->result = S_OK;
2518 return STATUS_SUCCESS;
2519 case 3: /* PhysicalSpeakers */
2520 if (!dev->channel_mask)
2521 goto fail;
2522 params->value->vt = VT_UI4;
2523 params->value->ulVal = dev->channel_mask;
2524 params->result = S_OK;
2525 return STATUS_SUCCESS;
2529 params->result = E_NOTIMPL;
2530 return STATUS_SUCCESS;
2533 fail:
2534 params->result = E_FAIL;
2535 return STATUS_SUCCESS;
2538 const unixlib_entry_t __wine_unix_call_funcs[] =
2540 pulse_process_attach,
2541 pulse_process_detach,
2542 pulse_main_loop,
2543 pulse_get_endpoint_ids,
2544 pulse_create_stream,
2545 pulse_release_stream,
2546 pulse_start,
2547 pulse_stop,
2548 pulse_reset,
2549 pulse_timer_loop,
2550 pulse_get_render_buffer,
2551 pulse_release_render_buffer,
2552 pulse_get_capture_buffer,
2553 pulse_release_capture_buffer,
2554 pulse_is_format_supported,
2555 pulse_get_mix_format,
2556 pulse_get_device_period,
2557 pulse_get_buffer_size,
2558 pulse_get_latency,
2559 pulse_get_current_padding,
2560 pulse_get_next_packet_size,
2561 pulse_get_frequency,
2562 pulse_get_position,
2563 pulse_set_volumes,
2564 pulse_set_event_handle,
2565 pulse_test_connect,
2566 pulse_is_started,
2567 pulse_get_prop_value,
2568 pulse_not_implemented,
2569 pulse_not_implemented,
2570 pulse_not_implemented,
2571 pulse_not_implemented,
2572 pulse_not_implemented,
2573 pulse_not_implemented,
2576 C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == funcs_count);
2578 #ifdef _WIN64
2580 typedef UINT PTR32;
2582 static NTSTATUS pulse_wow64_main_loop(void *args)
2584 struct
2586 PTR32 event;
2587 } *params32 = args;
2588 struct main_loop_params params =
2590 .event = ULongToHandle(params32->event)
2592 return pulse_main_loop(&params);
2595 static NTSTATUS pulse_wow64_get_endpoint_ids(void *args)
2597 struct
2599 EDataFlow flow;
2600 PTR32 endpoints;
2601 unsigned int size;
2602 HRESULT result;
2603 unsigned int num;
2604 unsigned int default_idx;
2605 } *params32 = args;
2606 struct get_endpoint_ids_params params =
2608 .flow = params32->flow,
2609 .endpoints = ULongToPtr(params32->endpoints),
2610 .size = params32->size
2612 pulse_get_endpoint_ids(&params);
2613 params32->size = params.size;
2614 params32->result = params.result;
2615 params32->num = params.num;
2616 params32->default_idx = params.default_idx;
2617 return STATUS_SUCCESS;
2620 static NTSTATUS pulse_wow64_create_stream(void *args)
2622 struct
2624 PTR32 name;
2625 PTR32 device;
2626 EDataFlow flow;
2627 AUDCLNT_SHAREMODE share;
2628 DWORD flags;
2629 REFERENCE_TIME duration;
2630 REFERENCE_TIME period;
2631 PTR32 fmt;
2632 HRESULT result;
2633 PTR32 channel_count;
2634 PTR32 stream;
2635 } *params32 = args;
2636 struct create_stream_params params =
2638 .name = ULongToPtr(params32->name),
2639 .device = ULongToPtr(params32->device),
2640 .flow = params32->flow,
2641 .share = params32->share,
2642 .flags = params32->flags,
2643 .duration = params32->duration,
2644 .period = params32->period,
2645 .fmt = ULongToPtr(params32->fmt),
2646 .channel_count = ULongToPtr(params32->channel_count),
2647 .stream = ULongToPtr(params32->stream)
2649 pulse_create_stream(&params);
2650 params32->result = params.result;
2651 return STATUS_SUCCESS;
2654 static NTSTATUS pulse_wow64_release_stream(void *args)
2656 struct
2658 stream_handle stream;
2659 PTR32 timer_thread;
2660 HRESULT result;
2661 } *params32 = args;
2662 struct release_stream_params params =
2664 .stream = params32->stream,
2665 .timer_thread = ULongToHandle(params32->timer_thread)
2667 pulse_release_stream(&params);
2668 params32->result = params.result;
2669 return STATUS_SUCCESS;
2672 static NTSTATUS pulse_wow64_get_render_buffer(void *args)
2674 struct
2676 stream_handle stream;
2677 UINT32 frames;
2678 HRESULT result;
2679 PTR32 data;
2680 } *params32 = args;
2681 BYTE *data = NULL;
2682 struct get_render_buffer_params params =
2684 .stream = params32->stream,
2685 .frames = params32->frames,
2686 .data = &data
2688 pulse_get_render_buffer(&params);
2689 params32->result = params.result;
2690 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2691 return STATUS_SUCCESS;
2694 static NTSTATUS pulse_wow64_get_capture_buffer(void *args)
2696 struct
2698 stream_handle stream;
2699 HRESULT result;
2700 PTR32 data;
2701 PTR32 frames;
2702 PTR32 flags;
2703 PTR32 devpos;
2704 PTR32 qpcpos;
2705 } *params32 = args;
2706 BYTE *data = NULL;
2707 struct get_capture_buffer_params params =
2709 .stream = params32->stream,
2710 .data = &data,
2711 .frames = ULongToPtr(params32->frames),
2712 .flags = ULongToPtr(params32->flags),
2713 .devpos = ULongToPtr(params32->devpos),
2714 .qpcpos = ULongToPtr(params32->qpcpos)
2716 pulse_get_capture_buffer(&params);
2717 params32->result = params.result;
2718 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2719 return STATUS_SUCCESS;
2722 static NTSTATUS pulse_wow64_is_format_supported(void *args)
2724 struct
2726 PTR32 device;
2727 EDataFlow flow;
2728 AUDCLNT_SHAREMODE share;
2729 PTR32 fmt_in;
2730 PTR32 fmt_out;
2731 HRESULT result;
2732 } *params32 = args;
2733 struct is_format_supported_params params =
2735 .device = ULongToPtr(params32->device),
2736 .flow = params32->flow,
2737 .share = params32->share,
2738 .fmt_in = ULongToPtr(params32->fmt_in),
2739 .fmt_out = ULongToPtr(params32->fmt_out)
2741 pulse_is_format_supported(&params);
2742 params32->result = params.result;
2743 return STATUS_SUCCESS;
2746 static NTSTATUS pulse_wow64_get_mix_format(void *args)
2748 struct
2750 PTR32 device;
2751 EDataFlow flow;
2752 PTR32 fmt;
2753 HRESULT result;
2754 } *params32 = args;
2755 struct get_mix_format_params params =
2757 .device = ULongToPtr(params32->device),
2758 .flow = params32->flow,
2759 .fmt = ULongToPtr(params32->fmt),
2761 pulse_get_mix_format(&params);
2762 params32->result = params.result;
2763 return STATUS_SUCCESS;
2766 static NTSTATUS pulse_wow64_get_device_period(void *args)
2768 struct
2770 PTR32 device;
2771 EDataFlow flow;
2772 HRESULT result;
2773 PTR32 def_period;
2774 PTR32 min_period;
2775 } *params32 = args;
2776 struct get_device_period_params params =
2778 .device = ULongToPtr(params32->device),
2779 .flow = params32->flow,
2780 .def_period = ULongToPtr(params32->def_period),
2781 .min_period = ULongToPtr(params32->min_period),
2783 pulse_get_device_period(&params);
2784 params32->result = params.result;
2785 return STATUS_SUCCESS;
2788 static NTSTATUS pulse_wow64_get_buffer_size(void *args)
2790 struct
2792 stream_handle stream;
2793 HRESULT result;
2794 PTR32 frames;
2795 } *params32 = args;
2796 struct get_buffer_size_params params =
2798 .stream = params32->stream,
2799 .frames = ULongToPtr(params32->frames)
2801 pulse_get_buffer_size(&params);
2802 params32->result = params.result;
2803 return STATUS_SUCCESS;
2806 static NTSTATUS pulse_wow64_get_latency(void *args)
2808 struct
2810 stream_handle stream;
2811 HRESULT result;
2812 PTR32 latency;
2813 } *params32 = args;
2814 struct get_latency_params params =
2816 .stream = params32->stream,
2817 .latency = ULongToPtr(params32->latency)
2819 pulse_get_latency(&params);
2820 params32->result = params.result;
2821 return STATUS_SUCCESS;
2824 static NTSTATUS pulse_wow64_get_current_padding(void *args)
2826 struct
2828 stream_handle stream;
2829 HRESULT result;
2830 PTR32 padding;
2831 } *params32 = args;
2832 struct get_current_padding_params params =
2834 .stream = params32->stream,
2835 .padding = ULongToPtr(params32->padding)
2837 pulse_get_current_padding(&params);
2838 params32->result = params.result;
2839 return STATUS_SUCCESS;
2842 static NTSTATUS pulse_wow64_get_next_packet_size(void *args)
2844 struct
2846 stream_handle stream;
2847 HRESULT result;
2848 PTR32 frames;
2849 } *params32 = args;
2850 struct get_next_packet_size_params params =
2852 .stream = params32->stream,
2853 .frames = ULongToPtr(params32->frames)
2855 pulse_get_next_packet_size(&params);
2856 params32->result = params.result;
2857 return STATUS_SUCCESS;
2860 static NTSTATUS pulse_wow64_get_frequency(void *args)
2862 struct
2864 stream_handle stream;
2865 HRESULT result;
2866 PTR32 freq;
2867 } *params32 = args;
2868 struct get_frequency_params params =
2870 .stream = params32->stream,
2871 .freq = ULongToPtr(params32->freq)
2873 pulse_get_frequency(&params);
2874 params32->result = params.result;
2875 return STATUS_SUCCESS;
2878 static NTSTATUS pulse_wow64_get_position(void *args)
2880 struct
2882 stream_handle stream;
2883 BOOL device;
2884 HRESULT result;
2885 PTR32 pos;
2886 PTR32 qpctime;
2887 } *params32 = args;
2888 struct get_position_params params =
2890 .stream = params32->stream,
2891 .device = params32->device,
2892 .pos = ULongToPtr(params32->pos),
2893 .qpctime = ULongToPtr(params32->qpctime)
2895 pulse_get_position(&params);
2896 params32->result = params.result;
2897 return STATUS_SUCCESS;
2900 static NTSTATUS pulse_wow64_set_volumes(void *args)
2902 struct
2904 stream_handle stream;
2905 float master_volume;
2906 PTR32 volumes;
2907 PTR32 session_volumes;
2908 } *params32 = args;
2909 struct set_volumes_params params =
2911 .stream = params32->stream,
2912 .master_volume = params32->master_volume,
2913 .volumes = ULongToPtr(params32->volumes),
2914 .session_volumes = ULongToPtr(params32->session_volumes),
2916 return pulse_set_volumes(&params);
2919 static NTSTATUS pulse_wow64_set_event_handle(void *args)
2921 struct
2923 stream_handle stream;
2924 PTR32 event;
2925 HRESULT result;
2926 } *params32 = args;
2927 struct set_event_handle_params params =
2929 .stream = params32->stream,
2930 .event = ULongToHandle(params32->event)
2932 pulse_set_event_handle(&params);
2933 params32->result = params.result;
2934 return STATUS_SUCCESS;
2937 static NTSTATUS pulse_wow64_test_connect(void *args)
2939 struct
2941 PTR32 name;
2942 enum driver_priority priority;
2943 } *params32 = args;
2944 struct test_connect_params params =
2946 .name = ULongToPtr(params32->name),
2948 pulse_test_connect(&params);
2949 params32->priority = params.priority;
2950 return STATUS_SUCCESS;
2953 static NTSTATUS pulse_wow64_get_prop_value(void *args)
2955 struct propvariant32
2957 WORD vt;
2958 WORD pad1, pad2, pad3;
2959 union
2961 ULONG ulVal;
2962 PTR32 ptr;
2963 ULARGE_INTEGER uhVal;
2965 } *value32;
2966 struct
2968 PTR32 device;
2969 EDataFlow flow;
2970 PTR32 guid;
2971 PTR32 prop;
2972 HRESULT result;
2973 PTR32 value;
2974 PTR32 buffer; /* caller allocated buffer to hold value's strings */
2975 PTR32 buffer_size;
2976 } *params32 = args;
2977 PROPVARIANT value;
2978 struct get_prop_value_params params =
2980 .device = ULongToPtr(params32->device),
2981 .flow = params32->flow,
2982 .guid = ULongToPtr(params32->guid),
2983 .prop = ULongToPtr(params32->prop),
2984 .value = &value,
2985 .buffer = ULongToPtr(params32->buffer),
2986 .buffer_size = ULongToPtr(params32->buffer_size)
2988 pulse_get_prop_value(&params);
2989 params32->result = params.result;
2990 if (SUCCEEDED(params.result))
2992 value32 = UlongToPtr(params32->value);
2993 value32->vt = value.vt;
2994 switch (value.vt)
2996 case VT_UI4:
2997 value32->ulVal = value.ulVal;
2998 break;
2999 case VT_LPWSTR:
3000 value32->ptr = params32->buffer;
3001 break;
3002 default:
3003 FIXME("Unhandled vt %04x\n", value.vt);
3006 return STATUS_SUCCESS;
3009 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
3011 pulse_process_attach,
3012 pulse_process_detach,
3013 pulse_wow64_main_loop,
3014 pulse_wow64_get_endpoint_ids,
3015 pulse_wow64_create_stream,
3016 pulse_wow64_release_stream,
3017 pulse_start,
3018 pulse_stop,
3019 pulse_reset,
3020 pulse_timer_loop,
3021 pulse_wow64_get_render_buffer,
3022 pulse_release_render_buffer,
3023 pulse_wow64_get_capture_buffer,
3024 pulse_release_capture_buffer,
3025 pulse_wow64_is_format_supported,
3026 pulse_wow64_get_mix_format,
3027 pulse_wow64_get_device_period,
3028 pulse_wow64_get_buffer_size,
3029 pulse_wow64_get_latency,
3030 pulse_wow64_get_current_padding,
3031 pulse_wow64_get_next_packet_size,
3032 pulse_wow64_get_frequency,
3033 pulse_wow64_get_position,
3034 pulse_wow64_set_volumes,
3035 pulse_wow64_set_event_handle,
3036 pulse_wow64_test_connect,
3037 pulse_is_started,
3038 pulse_wow64_get_prop_value,
3039 pulse_not_implemented,
3040 pulse_not_implemented,
3041 pulse_not_implemented,
3042 pulse_not_implemented,
3043 pulse_not_implemented,
3044 pulse_not_implemented,
3047 C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == funcs_count);
3049 #endif /* _WIN64 */