mountmgr.sys: Ensure unixlib function tables and enum stay in sync.
[wine.git] / dlls / winepulse.drv / pulse.c
blob370c361b02fea7d579e6662f9bd2cfe5fbd7ee5d
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 pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, 0, "", "PulseAudio");
837 pulse_add_device(&g_phys_sources, NULL, 0, Microphone, 0, "", "PulseAudio");
839 o = pa_context_get_sink_info_list(pulse_ctx, &pulse_phys_speakers_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 o = pa_context_get_source_info_list(pulse_ctx, &pulse_phys_sources_cb, NULL);
848 if (o) {
849 while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
850 pa_operation_get_state(o) == PA_OPERATION_RUNNING)
852 pa_operation_unref(o);
855 LIST_FOR_EACH_ENTRY(dev, &g_phys_speakers, PhysDevice, entry) {
856 pulse_probe_settings(1, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
859 LIST_FOR_EACH_ENTRY(dev, &g_phys_sources, PhysDevice, entry) {
860 pulse_probe_settings(0, dev->pulse_name, &dev->fmt, &dev->def_period, &dev->min_period);
863 pa_context_unref(pulse_ctx);
864 pulse_ctx = NULL;
865 pa_mainloop_free(pulse_ml);
866 pulse_ml = NULL;
868 pulse_unlock();
870 params->priority = Priority_Preferred;
871 return STATUS_SUCCESS;
873 fail:
874 pa_context_unref(pulse_ctx);
875 pulse_ctx = NULL;
876 pa_mainloop_free(pulse_ml);
877 pulse_ml = NULL;
878 pulse_unlock();
879 params->priority = Priority_Unavailable;
880 return STATUS_SUCCESS;
883 static UINT get_channel_mask(unsigned int channels)
885 switch(channels) {
886 case 0:
887 return 0;
888 case 1:
889 return KSAUDIO_SPEAKER_MONO;
890 case 2:
891 return KSAUDIO_SPEAKER_STEREO;
892 case 3:
893 return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
894 case 4:
895 return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
896 case 5:
897 return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
898 case 6:
899 return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
900 case 7:
901 return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
902 case 8:
903 return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
905 FIXME("Unknown speaker configuration: %u\n", channels);
906 return 0;
909 static const enum pa_channel_position pulse_pos_from_wfx[] = {
910 PA_CHANNEL_POSITION_FRONT_LEFT,
911 PA_CHANNEL_POSITION_FRONT_RIGHT,
912 PA_CHANNEL_POSITION_FRONT_CENTER,
913 PA_CHANNEL_POSITION_LFE,
914 PA_CHANNEL_POSITION_REAR_LEFT,
915 PA_CHANNEL_POSITION_REAR_RIGHT,
916 PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
917 PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
918 PA_CHANNEL_POSITION_REAR_CENTER,
919 PA_CHANNEL_POSITION_SIDE_LEFT,
920 PA_CHANNEL_POSITION_SIDE_RIGHT,
921 PA_CHANNEL_POSITION_TOP_CENTER,
922 PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
923 PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
924 PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
925 PA_CHANNEL_POSITION_TOP_REAR_LEFT,
926 PA_CHANNEL_POSITION_TOP_REAR_CENTER,
927 PA_CHANNEL_POSITION_TOP_REAR_RIGHT
930 static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAVEFORMATEX *fmt)
932 pa_channel_map_init(&stream->map);
933 stream->ss.rate = fmt->nSamplesPerSec;
934 stream->ss.format = PA_SAMPLE_INVALID;
936 switch(fmt->wFormatTag) {
937 case WAVE_FORMAT_IEEE_FLOAT:
938 if (!fmt->nChannels || fmt->nChannels > 2 || fmt->wBitsPerSample != 32)
939 break;
940 stream->ss.format = PA_SAMPLE_FLOAT32LE;
941 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
942 break;
943 case WAVE_FORMAT_PCM:
944 if (!fmt->nChannels || fmt->nChannels > 2)
945 break;
946 if (fmt->wBitsPerSample == 8)
947 stream->ss.format = PA_SAMPLE_U8;
948 else if (fmt->wBitsPerSample == 16)
949 stream->ss.format = PA_SAMPLE_S16LE;
950 else
951 return AUDCLNT_E_UNSUPPORTED_FORMAT;
952 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
953 break;
954 case WAVE_FORMAT_EXTENSIBLE: {
955 WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE*)fmt;
956 UINT mask = wfe->dwChannelMask;
957 unsigned i = 0, j;
958 if (fmt->cbSize != (sizeof(*wfe) - sizeof(*fmt)) && fmt->cbSize != sizeof(*wfe))
959 break;
960 if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
961 (!wfe->Samples.wValidBitsPerSample || wfe->Samples.wValidBitsPerSample == 32) &&
962 fmt->wBitsPerSample == 32)
963 stream->ss.format = PA_SAMPLE_FLOAT32LE;
964 else if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
965 DWORD valid = wfe->Samples.wValidBitsPerSample;
966 if (!valid)
967 valid = fmt->wBitsPerSample;
968 if (!valid || valid > fmt->wBitsPerSample)
969 break;
970 switch (fmt->wBitsPerSample) {
971 case 8:
972 if (valid == 8)
973 stream->ss.format = PA_SAMPLE_U8;
974 break;
975 case 16:
976 if (valid == 16)
977 stream->ss.format = PA_SAMPLE_S16LE;
978 break;
979 case 24:
980 if (valid == 24)
981 stream->ss.format = PA_SAMPLE_S24LE;
982 break;
983 case 32:
984 if (valid == 24)
985 stream->ss.format = PA_SAMPLE_S24_32LE;
986 else if (valid == 32)
987 stream->ss.format = PA_SAMPLE_S32LE;
988 break;
989 default:
990 return AUDCLNT_E_UNSUPPORTED_FORMAT;
993 stream->map.channels = fmt->nChannels;
994 if (!mask || (mask & (SPEAKER_ALL|SPEAKER_RESERVED)))
995 mask = get_channel_mask(fmt->nChannels);
996 for (j = 0; j < ARRAY_SIZE(pulse_pos_from_wfx) && i < fmt->nChannels; ++j) {
997 if (mask & (1 << j))
998 stream->map.map[i++] = pulse_pos_from_wfx[j];
1001 /* Special case for mono since pulse appears to map it differently */
1002 if (mask == SPEAKER_FRONT_CENTER)
1003 stream->map.map[0] = PA_CHANNEL_POSITION_MONO;
1005 if (i < fmt->nChannels || (mask & SPEAKER_RESERVED)) {
1006 stream->map.channels = 0;
1007 ERR("Invalid channel mask: %i/%i and %x(%x)\n", i, fmt->nChannels, mask, (unsigned)wfe->dwChannelMask);
1008 break;
1010 break;
1012 case WAVE_FORMAT_ALAW:
1013 case WAVE_FORMAT_MULAW:
1014 if (fmt->wBitsPerSample != 8) {
1015 FIXME("Unsupported bpp %u for LAW\n", fmt->wBitsPerSample);
1016 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1018 if (fmt->nChannels != 1 && fmt->nChannels != 2) {
1019 FIXME("Unsupported channels %u for LAW\n", fmt->nChannels);
1020 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1022 stream->ss.format = fmt->wFormatTag == WAVE_FORMAT_MULAW ? PA_SAMPLE_ULAW : PA_SAMPLE_ALAW;
1023 pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA);
1024 break;
1025 default:
1026 WARN("Unhandled tag %x\n", fmt->wFormatTag);
1027 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1029 stream->ss.channels = stream->map.channels;
1030 if (!pa_channel_map_valid(&stream->map) || stream->ss.format == PA_SAMPLE_INVALID) {
1031 ERR("Invalid format! Channel spec valid: %i, format: %i\n",
1032 pa_channel_map_valid(&stream->map), stream->ss.format);
1033 return AUDCLNT_E_UNSUPPORTED_FORMAT;
1035 return S_OK;
1038 static HRESULT pulse_stream_connect(struct pulse_stream *stream, const char *pulse_name, UINT32 period_bytes)
1040 pa_stream_flags_t flags = PA_STREAM_START_CORKED | PA_STREAM_START_UNMUTED | PA_STREAM_ADJUST_LATENCY;
1041 int ret;
1042 char buffer[64];
1043 static LONG number;
1044 pa_buffer_attr attr;
1046 ret = InterlockedIncrement(&number);
1047 sprintf(buffer, "audio stream #%i", ret);
1048 stream->stream = pa_stream_new(pulse_ctx, buffer, &stream->ss, &stream->map);
1050 if (!stream->stream) {
1051 WARN("pa_stream_new returned error %i\n", pa_context_errno(pulse_ctx));
1052 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1055 pa_stream_set_state_callback(stream->stream, pulse_stream_state, stream);
1056 pa_stream_set_buffer_attr_callback(stream->stream, pulse_attr_update, stream);
1057 pa_stream_set_moved_callback(stream->stream, pulse_attr_update, stream);
1059 /* PulseAudio will fill in correct values */
1060 attr.minreq = attr.fragsize = period_bytes;
1061 attr.tlength = period_bytes * 3;
1062 attr.maxlength = stream->bufsize_frames * pa_frame_size(&stream->ss);
1063 attr.prebuf = pa_frame_size(&stream->ss);
1064 dump_attr(&attr);
1066 /* If specific device was requested, use it exactly */
1067 if (pulse_name[0])
1068 flags |= PA_STREAM_DONT_MOVE;
1069 else
1070 pulse_name = NULL; /* use default */
1072 if (stream->dataflow == eRender)
1073 ret = pa_stream_connect_playback(stream->stream, pulse_name, &attr, flags, NULL, NULL);
1074 else
1075 ret = pa_stream_connect_record(stream->stream, pulse_name, &attr, flags);
1076 if (ret < 0) {
1077 WARN("Returns %i\n", ret);
1078 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1080 while (pa_stream_get_state(stream->stream) == PA_STREAM_CREATING)
1081 pulse_cond_wait();
1082 if (pa_stream_get_state(stream->stream) != PA_STREAM_READY)
1083 return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
1085 if (stream->dataflow == eRender) {
1086 pa_stream_set_underflow_callback(stream->stream, pulse_underflow_callback, stream);
1087 pa_stream_set_started_callback(stream->stream, pulse_started_callback, stream);
1089 return S_OK;
1092 static HRESULT get_device_period_helper(EDataFlow flow, const char *pulse_name, REFERENCE_TIME *def, REFERENCE_TIME *min)
1094 struct list *list = (flow == eRender) ? &g_phys_speakers : &g_phys_sources;
1095 PhysDevice *dev;
1097 if (!def && !min) {
1098 return E_POINTER;
1101 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
1102 if (strcmp(pulse_name, dev->pulse_name))
1103 continue;
1105 if (def)
1106 *def = dev->def_period;
1107 if (min)
1108 *min = dev->min_period;
1109 return S_OK;
1112 return E_FAIL;
1115 static NTSTATUS pulse_create_stream(void *args)
1117 struct create_stream_params *params = args;
1118 REFERENCE_TIME period, duration = params->duration;
1119 struct pulse_stream *stream;
1120 unsigned int i, bufsize_bytes;
1121 HRESULT hr;
1122 char *name;
1124 if (params->share == AUDCLNT_SHAREMODE_EXCLUSIVE) {
1125 params->result = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
1126 return STATUS_SUCCESS;
1129 pulse_lock();
1131 name = wstr_to_str(params->name);
1132 params->result = pulse_connect(name);
1133 free(name);
1135 if (FAILED(params->result))
1137 pulse_unlock();
1138 return STATUS_SUCCESS;
1141 if (!(stream = calloc(1, sizeof(*stream))))
1143 pulse_unlock();
1144 params->result = E_OUTOFMEMORY;
1145 return STATUS_SUCCESS;
1148 stream->dataflow = params->flow;
1149 for (i = 0; i < ARRAY_SIZE(stream->vol); ++i)
1150 stream->vol[i] = 1.f;
1152 hr = pulse_spec_from_waveformat(stream, params->fmt);
1153 TRACE("Obtaining format returns %08x\n", (unsigned)hr);
1155 if (FAILED(hr))
1156 goto exit;
1158 period = 0;
1159 hr = get_device_period_helper(params->flow, params->device, &period, NULL);
1160 if (FAILED(hr))
1161 goto exit;
1163 if (duration < 3 * period)
1164 duration = 3 * period;
1166 stream->def_period = period;
1168 stream->period_bytes = pa_frame_size(&stream->ss) * muldiv(period, stream->ss.rate, 10000000);
1170 stream->bufsize_frames = ceil((duration / 10000000.) * params->fmt->nSamplesPerSec);
1171 bufsize_bytes = stream->bufsize_frames * pa_frame_size(&stream->ss);
1172 stream->mmdev_period_usec = period / 10;
1174 stream->share = params->share;
1175 stream->flags = params->flags;
1176 hr = pulse_stream_connect(stream, params->device, stream->period_bytes);
1177 if (SUCCEEDED(hr)) {
1178 UINT32 unalign;
1179 const pa_buffer_attr *attr = pa_stream_get_buffer_attr(stream->stream);
1180 SIZE_T size;
1182 stream->attr = *attr;
1183 /* Update frames according to new size */
1184 dump_attr(attr);
1185 if (stream->dataflow == eRender) {
1186 size = stream->real_bufsize_bytes =
1187 stream->bufsize_frames * 2 * pa_frame_size(&stream->ss);
1188 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1189 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1190 hr = E_OUTOFMEMORY;
1191 } else {
1192 UINT32 i, capture_packets;
1194 if ((unalign = bufsize_bytes % stream->period_bytes))
1195 bufsize_bytes += stream->period_bytes - unalign;
1196 stream->bufsize_frames = bufsize_bytes / pa_frame_size(&stream->ss);
1197 stream->real_bufsize_bytes = bufsize_bytes;
1199 capture_packets = stream->real_bufsize_bytes / stream->period_bytes;
1201 size = stream->real_bufsize_bytes + capture_packets * sizeof(ACPacket);
1202 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1203 zero_bits, &size, MEM_COMMIT, PAGE_READWRITE))
1204 hr = E_OUTOFMEMORY;
1205 else {
1206 ACPacket *cur_packet = (ACPacket*)((char*)stream->local_buffer + stream->real_bufsize_bytes);
1207 BYTE *data = stream->local_buffer;
1208 silence_buffer(stream->ss.format, stream->local_buffer, stream->real_bufsize_bytes);
1209 list_init(&stream->packet_free_head);
1210 list_init(&stream->packet_filled_head);
1211 for (i = 0; i < capture_packets; ++i, ++cur_packet) {
1212 list_add_tail(&stream->packet_free_head, &cur_packet->entry);
1213 cur_packet->data = data;
1214 data += stream->period_bytes;
1220 *params->channel_count = stream->ss.channels;
1221 *params->stream = (stream_handle)(UINT_PTR)stream;
1223 exit:
1224 if (FAILED(params->result = hr)) {
1225 free(stream->local_buffer);
1226 if (stream->stream) {
1227 pa_stream_disconnect(stream->stream);
1228 pa_stream_unref(stream->stream);
1230 free(stream);
1233 pulse_unlock();
1234 return STATUS_SUCCESS;
1237 static NTSTATUS pulse_release_stream(void *args)
1239 struct release_stream_params *params = args;
1240 struct pulse_stream *stream = handle_get_stream(params->stream);
1241 SIZE_T size;
1243 if(params->timer_thread) {
1244 stream->please_quit = TRUE;
1245 NtWaitForSingleObject(params->timer_thread, FALSE, NULL);
1246 NtClose(params->timer_thread);
1249 pulse_lock();
1250 if (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream))) {
1251 pa_stream_disconnect(stream->stream);
1252 while (PA_STREAM_IS_GOOD(pa_stream_get_state(stream->stream)))
1253 pulse_cond_wait();
1255 pa_stream_unref(stream->stream);
1256 pulse_unlock();
1258 if (stream->tmp_buffer) {
1259 size = 0;
1260 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1261 &size, MEM_RELEASE);
1263 if (stream->local_buffer) {
1264 size = 0;
1265 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer,
1266 &size, MEM_RELEASE);
1268 free(stream->peek_buffer);
1269 free(stream);
1270 return STATUS_SUCCESS;
1273 static int write_buffer(const struct pulse_stream *stream, BYTE *buffer, UINT32 bytes)
1275 const float *vol = stream->vol;
1276 UINT32 i, channels, mute = 0;
1277 BOOL adjust = FALSE;
1278 BYTE *end;
1280 if (!bytes) return 0;
1282 /* Adjust the buffer based on the volume for each channel */
1283 channels = stream->ss.channels;
1284 for (i = 0; i < channels; i++)
1286 adjust |= vol[i] != 1.0f;
1287 if (vol[i] == 0.0f)
1288 mute++;
1290 if (mute == channels)
1292 silence_buffer(stream->ss.format, buffer, bytes);
1293 goto write;
1295 if (!adjust) goto write;
1297 end = buffer + bytes;
1298 switch (stream->ss.format)
1300 #ifndef WORDS_BIGENDIAN
1301 #define PROCESS_BUFFER(type) do \
1303 type *p = (type*)buffer; \
1304 do \
1306 for (i = 0; i < channels; i++) \
1307 p[i] = p[i] * vol[i]; \
1308 p += i; \
1309 } while ((BYTE*)p != end); \
1310 } while (0)
1311 case PA_SAMPLE_S16LE:
1312 PROCESS_BUFFER(INT16);
1313 break;
1314 case PA_SAMPLE_S32LE:
1315 PROCESS_BUFFER(INT32);
1316 break;
1317 case PA_SAMPLE_FLOAT32LE:
1318 PROCESS_BUFFER(float);
1319 break;
1320 #undef PROCESS_BUFFER
1321 case PA_SAMPLE_S24_32LE:
1323 UINT32 *p = (UINT32*)buffer;
1326 for (i = 0; i < channels; i++)
1328 p[i] = (INT32)((INT32)(p[i] << 8) * vol[i]);
1329 p[i] >>= 8;
1331 p += i;
1332 } while ((BYTE*)p != end);
1333 break;
1335 case PA_SAMPLE_S24LE:
1337 /* do it 12 bytes at a time until it is no longer possible */
1338 UINT32 *q = (UINT32*)buffer;
1339 BYTE *p;
1341 i = 0;
1342 while (end - (BYTE*)q >= 12)
1344 UINT32 v[4], k;
1345 v[0] = q[0] << 8;
1346 v[1] = q[1] << 16 | (q[0] >> 16 & ~0xff);
1347 v[2] = q[2] << 24 | (q[1] >> 8 & ~0xff);
1348 v[3] = q[2] & ~0xff;
1349 for (k = 0; k < 4; k++)
1351 v[k] = (INT32)((INT32)v[k] * vol[i]);
1352 if (++i == channels) i = 0;
1354 *q++ = v[0] >> 8 | (v[1] & ~0xff) << 16;
1355 *q++ = v[1] >> 16 | (v[2] & ~0xff) << 8;
1356 *q++ = v[2] >> 24 | (v[3] & ~0xff);
1358 p = (BYTE*)q;
1359 while (p != end)
1361 UINT32 v = (INT32)((INT32)(p[0] << 8 | p[1] << 16 | p[2] << 24) * vol[i]);
1362 *p++ = v >> 8 & 0xff;
1363 *p++ = v >> 16 & 0xff;
1364 *p++ = v >> 24;
1365 if (++i == channels) i = 0;
1367 break;
1369 #endif
1370 case PA_SAMPLE_U8:
1372 UINT8 *p = (UINT8*)buffer;
1375 for (i = 0; i < channels; i++)
1376 p[i] = (int)((p[i] - 128) * vol[i]) + 128;
1377 p += i;
1378 } while ((BYTE*)p != end);
1379 break;
1381 case PA_SAMPLE_ALAW:
1383 UINT8 *p = (UINT8*)buffer;
1386 for (i = 0; i < channels; i++)
1387 p[i] = mult_alaw_sample(p[i], vol[i]);
1388 p += i;
1389 } while ((BYTE*)p != end);
1390 break;
1392 case PA_SAMPLE_ULAW:
1394 UINT8 *p = (UINT8*)buffer;
1397 for (i = 0; i < channels; i++)
1398 p[i] = mult_ulaw_sample(p[i], vol[i]);
1399 p += i;
1400 } while ((BYTE*)p != end);
1401 break;
1403 default:
1404 TRACE("Unhandled format %i, not adjusting volume.\n", stream->ss.format);
1405 break;
1408 write:
1409 return pa_stream_write(stream->stream, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE);
1412 static void pulse_write(struct pulse_stream *stream)
1414 /* write as much data to PA as we can */
1415 UINT32 to_write;
1416 BYTE *buf = stream->local_buffer + stream->pa_offs_bytes;
1417 UINT32 bytes = pa_stream_writable_size(stream->stream);
1419 if (stream->just_underran)
1421 /* prebuffer with silence if needed */
1422 if(stream->pa_held_bytes < bytes){
1423 to_write = bytes - stream->pa_held_bytes;
1424 TRACE("prebuffering %u frames of silence\n",
1425 (int)(to_write / pa_frame_size(&stream->ss)));
1426 buf = calloc(1, to_write);
1427 pa_stream_write(stream->stream, buf, to_write, NULL, 0, PA_SEEK_RELATIVE);
1428 free(buf);
1431 stream->just_underran = FALSE;
1434 buf = stream->local_buffer + stream->pa_offs_bytes;
1435 TRACE("held: %lu, avail: %u\n", stream->pa_held_bytes, bytes);
1436 bytes = min(stream->pa_held_bytes, bytes);
1438 if (stream->pa_offs_bytes + bytes > stream->real_bufsize_bytes)
1440 to_write = stream->real_bufsize_bytes - stream->pa_offs_bytes;
1441 TRACE("writing small chunk of %u bytes\n", to_write);
1442 write_buffer(stream, buf, to_write);
1443 stream->pa_held_bytes -= to_write;
1444 to_write = bytes - to_write;
1445 stream->pa_offs_bytes = 0;
1446 buf = stream->local_buffer;
1448 else
1449 to_write = bytes;
1451 TRACE("writing main chunk of %u bytes\n", to_write);
1452 write_buffer(stream, buf, to_write);
1453 stream->pa_offs_bytes += to_write;
1454 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1455 stream->pa_held_bytes -= to_write;
1458 static void pulse_read(struct pulse_stream *stream)
1460 size_t bytes = pa_stream_readable_size(stream->stream);
1462 TRACE("Readable total: %zu, fragsize: %u\n", bytes, pa_stream_get_buffer_attr(stream->stream)->fragsize);
1464 bytes += stream->peek_len - stream->peek_ofs;
1466 while (bytes >= stream->period_bytes)
1468 BYTE *dst = NULL, *src;
1469 size_t src_len, copy, rem = stream->period_bytes;
1471 if (stream->started)
1473 LARGE_INTEGER stamp, freq;
1474 ACPacket *p, *next;
1476 if (!(p = (ACPacket*)list_head(&stream->packet_free_head)))
1478 p = (ACPacket*)list_head(&stream->packet_filled_head);
1479 if (!p) return;
1480 if (!p->discont) {
1481 next = (ACPacket*)p->entry.next;
1482 next->discont = 1;
1483 } else
1484 p = (ACPacket*)list_tail(&stream->packet_filled_head);
1486 else
1488 stream->held_bytes += stream->period_bytes;
1490 NtQueryPerformanceCounter(&stamp, &freq);
1491 p->qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
1492 p->discont = 0;
1493 list_remove(&p->entry);
1494 list_add_tail(&stream->packet_filled_head, &p->entry);
1496 dst = p->data;
1499 while (rem)
1501 if (stream->peek_len)
1503 copy = min(rem, stream->peek_len - stream->peek_ofs);
1505 if (dst)
1507 memcpy(dst, stream->peek_buffer + stream->peek_ofs, copy);
1508 dst += copy;
1511 rem -= copy;
1512 stream->peek_ofs += copy;
1513 if(stream->peek_len == stream->peek_ofs)
1514 stream->peek_len = stream->peek_ofs = 0;
1517 else if (pa_stream_peek(stream->stream, (const void**)&src, &src_len) == 0 && src_len)
1519 copy = min(rem, src_len);
1521 if (dst) {
1522 if(src)
1523 memcpy(dst, src, copy);
1524 else
1525 silence_buffer(stream->ss.format, dst, copy);
1527 dst += copy;
1530 rem -= copy;
1532 if (copy < src_len)
1534 if (src_len > stream->peek_buffer_len)
1536 free(stream->peek_buffer);
1537 stream->peek_buffer = malloc(src_len);
1538 stream->peek_buffer_len = src_len;
1541 if(src)
1542 memcpy(stream->peek_buffer, src + copy, src_len - copy);
1543 else
1544 silence_buffer(stream->ss.format, stream->peek_buffer, src_len - copy);
1546 stream->peek_len = src_len - copy;
1547 stream->peek_ofs = 0;
1550 pa_stream_drop(stream->stream);
1554 bytes -= stream->period_bytes;
1558 static NTSTATUS pulse_timer_loop(void *args)
1560 struct timer_loop_params *params = args;
1561 struct pulse_stream *stream = handle_get_stream(params->stream);
1562 LARGE_INTEGER delay;
1563 pa_usec_t last_time;
1564 UINT32 adv_bytes;
1565 int success;
1566 pa_operation *o;
1568 pulse_lock();
1569 delay.QuadPart = -stream->mmdev_period_usec * 10;
1570 pa_stream_get_time(stream->stream, &last_time);
1571 pulse_unlock();
1573 while (!stream->please_quit)
1575 pa_usec_t now, adv_usec = 0;
1576 int err;
1578 NtDelayExecution(FALSE, &delay);
1580 pulse_lock();
1582 delay.QuadPart = -stream->mmdev_period_usec * 10;
1584 o = pa_stream_update_timing_info(stream->stream, pulse_op_cb, &success);
1585 if (o)
1587 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1588 pulse_cond_wait();
1589 pa_operation_unref(o);
1591 err = pa_stream_get_time(stream->stream, &now);
1592 if (err == 0)
1594 TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now), wine_dbgstr_longlong(last_time));
1595 if (stream->started && (stream->dataflow == eCapture || stream->held_bytes))
1597 if(stream->just_underran)
1599 last_time = now;
1600 stream->just_started = TRUE;
1603 if (stream->just_started)
1605 /* let it play out a period to absorb some latency and get accurate timing */
1606 pa_usec_t diff = now - last_time;
1608 if (diff > stream->mmdev_period_usec)
1610 stream->just_started = FALSE;
1611 last_time = now;
1614 else
1616 INT32 adjust = last_time + stream->mmdev_period_usec - now;
1618 adv_usec = now - last_time;
1620 if(adjust > ((INT32)(stream->mmdev_period_usec / 2)))
1621 adjust = stream->mmdev_period_usec / 2;
1622 else if(adjust < -((INT32)(stream->mmdev_period_usec / 2)))
1623 adjust = -1 * stream->mmdev_period_usec / 2;
1625 delay.QuadPart = -(stream->mmdev_period_usec + adjust) * 10;
1627 last_time += stream->mmdev_period_usec;
1630 if (stream->dataflow == eRender)
1632 pulse_write(stream);
1634 /* regardless of what PA does, advance one period */
1635 adv_bytes = min(stream->period_bytes, stream->held_bytes);
1636 stream->lcl_offs_bytes += adv_bytes;
1637 stream->lcl_offs_bytes %= stream->real_bufsize_bytes;
1638 stream->held_bytes -= adv_bytes;
1640 else if(stream->dataflow == eCapture)
1642 pulse_read(stream);
1645 else
1647 last_time = now;
1648 delay.QuadPart = -stream->mmdev_period_usec * 10;
1652 if (stream->event)
1653 NtSetEvent(stream->event, NULL);
1655 TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n",
1656 stream, (int)adv_usec,
1657 (int)(stream->held_bytes/ pa_frame_size(&stream->ss)),
1658 (unsigned int)(-delay.QuadPart / 10));
1660 pulse_unlock();
1663 return STATUS_SUCCESS;
1666 static NTSTATUS pulse_start(void *args)
1668 struct start_params *params = args;
1669 struct pulse_stream *stream = handle_get_stream(params->stream);
1670 int success;
1671 pa_operation *o;
1673 params->result = S_OK;
1674 pulse_lock();
1675 if (!pulse_stream_valid(stream))
1677 pulse_unlock();
1678 params->result = S_OK;
1679 return STATUS_SUCCESS;
1682 if ((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event)
1684 pulse_unlock();
1685 params->result = AUDCLNT_E_EVENTHANDLE_NOT_SET;
1686 return STATUS_SUCCESS;
1689 if (stream->started)
1691 pulse_unlock();
1692 params->result = AUDCLNT_E_NOT_STOPPED;
1693 return STATUS_SUCCESS;
1696 pulse_write(stream);
1698 if (pa_stream_is_corked(stream->stream))
1700 o = pa_stream_cork(stream->stream, 0, pulse_op_cb, &success);
1701 if (o)
1703 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1704 pulse_cond_wait();
1705 pa_operation_unref(o);
1707 else
1708 success = 0;
1709 if (!success)
1710 params->result = E_FAIL;
1713 if (SUCCEEDED(params->result))
1715 stream->started = TRUE;
1716 stream->just_started = TRUE;
1718 pulse_unlock();
1719 return STATUS_SUCCESS;
1722 static NTSTATUS pulse_stop(void *args)
1724 struct stop_params *params = args;
1725 struct pulse_stream *stream = handle_get_stream(params->stream);
1726 pa_operation *o;
1727 int success;
1729 pulse_lock();
1730 if (!pulse_stream_valid(stream))
1732 pulse_unlock();
1733 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1734 return STATUS_SUCCESS;
1737 if (!stream->started)
1739 pulse_unlock();
1740 params->result = S_FALSE;
1741 return STATUS_SUCCESS;
1744 params->result = S_OK;
1745 if (stream->dataflow == eRender)
1747 o = pa_stream_cork(stream->stream, 1, pulse_op_cb, &success);
1748 if (o)
1750 while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1751 pulse_cond_wait();
1752 pa_operation_unref(o);
1754 else
1755 success = 0;
1756 if (!success)
1757 params->result = E_FAIL;
1759 if (SUCCEEDED(params->result))
1760 stream->started = FALSE;
1761 pulse_unlock();
1762 return STATUS_SUCCESS;
1765 static NTSTATUS pulse_reset(void *args)
1767 struct reset_params *params = args;
1768 struct pulse_stream *stream = handle_get_stream(params->stream);
1770 pulse_lock();
1771 if (!pulse_stream_valid(stream))
1773 pulse_unlock();
1774 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1775 return STATUS_SUCCESS;
1778 if (stream->started)
1780 pulse_unlock();
1781 params->result = AUDCLNT_E_NOT_STOPPED;
1782 return STATUS_SUCCESS;
1785 if (stream->locked)
1787 pulse_unlock();
1788 params->result = AUDCLNT_E_BUFFER_OPERATION_PENDING;
1789 return STATUS_SUCCESS;
1792 if (stream->dataflow == eRender)
1794 /* If there is still data in the render buffer it needs to be removed from the server */
1795 int success = 0;
1796 if (stream->held_bytes)
1798 pa_operation *o = pa_stream_flush(stream->stream, pulse_op_cb, &success);
1799 if (o)
1801 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
1802 pulse_cond_wait();
1803 pa_operation_unref(o);
1806 if (success || !stream->held_bytes)
1808 stream->clock_lastpos = stream->clock_written = 0;
1809 stream->pa_offs_bytes = stream->lcl_offs_bytes = 0;
1810 stream->held_bytes = stream->pa_held_bytes = 0;
1813 else
1815 ACPacket *p;
1816 stream->clock_written += stream->held_bytes;
1817 stream->held_bytes = 0;
1819 if ((p = stream->locked_ptr))
1821 stream->locked_ptr = NULL;
1822 list_add_tail(&stream->packet_free_head, &p->entry);
1824 list_move_tail(&stream->packet_free_head, &stream->packet_filled_head);
1826 pulse_unlock();
1827 params->result = S_OK;
1828 return STATUS_SUCCESS;
1831 static BOOL alloc_tmp_buffer(struct pulse_stream *stream, SIZE_T bytes)
1833 SIZE_T size;
1835 if (stream->tmp_buffer_bytes >= bytes)
1836 return TRUE;
1838 if (stream->tmp_buffer)
1840 size = 0;
1841 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1842 &size, MEM_RELEASE);
1843 stream->tmp_buffer = NULL;
1844 stream->tmp_buffer_bytes = 0;
1846 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream->tmp_buffer,
1847 zero_bits, &bytes, MEM_COMMIT, PAGE_READWRITE))
1848 return FALSE;
1850 stream->tmp_buffer_bytes = bytes;
1851 return TRUE;
1854 static UINT32 pulse_render_padding(struct pulse_stream *stream)
1856 return stream->held_bytes / pa_frame_size(&stream->ss);
1859 static UINT32 pulse_capture_padding(struct pulse_stream *stream)
1861 ACPacket *packet = stream->locked_ptr;
1862 if (!packet && !list_empty(&stream->packet_filled_head))
1864 packet = (ACPacket*)list_head(&stream->packet_filled_head);
1865 stream->locked_ptr = packet;
1866 list_remove(&packet->entry);
1868 return stream->held_bytes / pa_frame_size(&stream->ss);
1871 static NTSTATUS pulse_get_render_buffer(void *args)
1873 struct get_render_buffer_params *params = args;
1874 struct pulse_stream *stream = handle_get_stream(params->stream);
1875 size_t bytes;
1876 UINT32 wri_offs_bytes;
1878 pulse_lock();
1879 if (!pulse_stream_valid(stream))
1881 pulse_unlock();
1882 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
1883 return STATUS_SUCCESS;
1886 if (stream->locked)
1888 pulse_unlock();
1889 params->result = AUDCLNT_E_OUT_OF_ORDER;
1890 return STATUS_SUCCESS;
1893 if (!params->frames)
1895 pulse_unlock();
1896 *params->data = NULL;
1897 params->result = S_OK;
1898 return STATUS_SUCCESS;
1901 if (stream->held_bytes / pa_frame_size(&stream->ss) + params->frames > stream->bufsize_frames)
1903 pulse_unlock();
1904 params->result = AUDCLNT_E_BUFFER_TOO_LARGE;
1905 return STATUS_SUCCESS;
1908 bytes = params->frames * pa_frame_size(&stream->ss);
1909 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1910 if (wri_offs_bytes + bytes > stream->real_bufsize_bytes)
1912 if (!alloc_tmp_buffer(stream, bytes))
1914 pulse_unlock();
1915 params->result = E_OUTOFMEMORY;
1916 return STATUS_SUCCESS;
1918 *params->data = stream->tmp_buffer;
1919 stream->locked = -bytes;
1921 else
1923 *params->data = stream->local_buffer + wri_offs_bytes;
1924 stream->locked = bytes;
1927 silence_buffer(stream->ss.format, *params->data, bytes);
1929 pulse_unlock();
1930 params->result = S_OK;
1931 return STATUS_SUCCESS;
1934 static void pulse_wrap_buffer(struct pulse_stream *stream, BYTE *buffer, UINT32 written_bytes)
1936 UINT32 wri_offs_bytes = (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1937 UINT32 chunk_bytes = stream->real_bufsize_bytes - wri_offs_bytes;
1939 if (written_bytes <= chunk_bytes)
1941 memcpy(stream->local_buffer + wri_offs_bytes, buffer, written_bytes);
1943 else
1945 memcpy(stream->local_buffer + wri_offs_bytes, buffer, chunk_bytes);
1946 memcpy(stream->local_buffer, buffer + chunk_bytes, written_bytes - chunk_bytes);
1950 static NTSTATUS pulse_release_render_buffer(void *args)
1952 struct release_render_buffer_params *params = args;
1953 struct pulse_stream *stream = handle_get_stream(params->stream);
1954 UINT32 written_bytes;
1955 BYTE *buffer;
1957 pulse_lock();
1958 if (!stream->locked || !params->written_frames)
1960 stream->locked = 0;
1961 pulse_unlock();
1962 params->result = params->written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1963 return STATUS_SUCCESS;
1966 if (params->written_frames * pa_frame_size(&stream->ss) >
1967 (stream->locked >= 0 ? stream->locked : -stream->locked))
1969 pulse_unlock();
1970 params->result = AUDCLNT_E_INVALID_SIZE;
1971 return STATUS_SUCCESS;
1974 if (stream->locked >= 0)
1975 buffer = stream->local_buffer + (stream->lcl_offs_bytes + stream->held_bytes) % stream->real_bufsize_bytes;
1976 else
1977 buffer = stream->tmp_buffer;
1979 written_bytes = params->written_frames * pa_frame_size(&stream->ss);
1980 if (params->flags & AUDCLNT_BUFFERFLAGS_SILENT)
1981 silence_buffer(stream->ss.format, buffer, written_bytes);
1983 if (stream->locked < 0)
1984 pulse_wrap_buffer(stream, buffer, written_bytes);
1986 stream->held_bytes += written_bytes;
1987 stream->pa_held_bytes += written_bytes;
1988 if (stream->pa_held_bytes > stream->real_bufsize_bytes)
1990 stream->pa_offs_bytes += stream->pa_held_bytes - stream->real_bufsize_bytes;
1991 stream->pa_offs_bytes %= stream->real_bufsize_bytes;
1992 stream->pa_held_bytes = stream->real_bufsize_bytes;
1994 stream->clock_written += written_bytes;
1995 stream->locked = 0;
1997 /* push as much data as we can to pulseaudio too */
1998 pulse_write(stream);
2000 TRACE("Released %u, held %lu\n", params->written_frames, stream->held_bytes / pa_frame_size(&stream->ss));
2002 pulse_unlock();
2003 params->result = S_OK;
2004 return STATUS_SUCCESS;
2007 static NTSTATUS pulse_get_capture_buffer(void *args)
2009 struct get_capture_buffer_params *params = args;
2010 struct pulse_stream *stream = handle_get_stream(params->stream);
2011 ACPacket *packet;
2013 pulse_lock();
2014 if (!pulse_stream_valid(stream))
2016 pulse_unlock();
2017 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2018 return STATUS_SUCCESS;
2020 if (stream->locked)
2022 pulse_unlock();
2023 params->result = AUDCLNT_E_OUT_OF_ORDER;
2024 return STATUS_SUCCESS;
2027 pulse_capture_padding(stream);
2028 if ((packet = stream->locked_ptr))
2030 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2031 *params->flags = 0;
2032 if (packet->discont)
2033 *params->flags |= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY;
2034 if (params->devpos)
2036 if (packet->discont)
2037 *params->devpos = (stream->clock_written + stream->period_bytes) / pa_frame_size(&stream->ss);
2038 else
2039 *params->devpos = stream->clock_written / pa_frame_size(&stream->ss);
2041 if (params->qpcpos)
2042 *params->qpcpos = packet->qpcpos;
2043 *params->data = packet->data;
2045 else
2046 *params->frames = 0;
2047 stream->locked = *params->frames;
2048 pulse_unlock();
2049 params->result = *params->frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2050 return STATUS_SUCCESS;
2053 static NTSTATUS pulse_release_capture_buffer(void *args)
2055 struct release_capture_buffer_params *params = args;
2056 struct pulse_stream *stream = handle_get_stream(params->stream);
2058 pulse_lock();
2059 if (!stream->locked && params->done)
2061 pulse_unlock();
2062 params->result = AUDCLNT_E_OUT_OF_ORDER;
2063 return STATUS_SUCCESS;
2065 if (params->done && stream->locked != params->done)
2067 pulse_unlock();
2068 params->result = AUDCLNT_E_INVALID_SIZE;
2069 return STATUS_SUCCESS;
2071 if (params->done)
2073 ACPacket *packet = stream->locked_ptr;
2074 stream->locked_ptr = NULL;
2075 stream->held_bytes -= stream->period_bytes;
2076 if (packet->discont)
2077 stream->clock_written += 2 * stream->period_bytes;
2078 else
2079 stream->clock_written += stream->period_bytes;
2080 list_add_tail(&stream->packet_free_head, &packet->entry);
2082 stream->locked = 0;
2083 pulse_unlock();
2084 params->result = S_OK;
2085 return STATUS_SUCCESS;
2088 static NTSTATUS pulse_is_format_supported(void *args)
2090 struct is_format_supported_params *params = args;
2091 WAVEFORMATEXTENSIBLE in;
2092 WAVEFORMATEXTENSIBLE *out;
2093 const WAVEFORMATEX *fmt = &in.Format;
2094 const BOOLEAN exclusive = params->share == AUDCLNT_SHAREMODE_EXCLUSIVE;
2096 params->result = S_OK;
2098 if (!params->fmt_in || (params->share == AUDCLNT_SHAREMODE_SHARED && !params->fmt_out))
2099 params->result = E_POINTER;
2100 else if (params->share != AUDCLNT_SHAREMODE_SHARED && params->share != AUDCLNT_SHAREMODE_EXCLUSIVE)
2101 params->result = E_INVALIDARG;
2102 else {
2103 memcpy(&in, params->fmt_in, params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2104 sizeof(in) : sizeof(in.Format));
2106 if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
2107 if (fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
2108 params->result = E_INVALIDARG;
2109 else if (fmt->nAvgBytesPerSec == 0 || fmt->nBlockAlign == 0 ||
2110 (in.Samples.wValidBitsPerSample > fmt->wBitsPerSample))
2111 params->result = E_INVALIDARG;
2112 else if (fmt->nChannels == 0)
2113 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2117 if (FAILED(params->result))
2118 return STATUS_SUCCESS;
2120 if (exclusive)
2121 out = &in;
2122 else {
2123 out = params->fmt_out;
2124 memcpy(out, fmt, fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE ?
2125 sizeof(*out) : sizeof((*out).Format));
2128 switch (fmt->wFormatTag) {
2129 case WAVE_FORMAT_EXTENSIBLE: {
2130 if ((fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) &&
2131 fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE)) ||
2132 fmt->nBlockAlign != fmt->wBitsPerSample / 8 * fmt->nChannels ||
2133 in.Samples.wValidBitsPerSample > fmt->wBitsPerSample ||
2134 fmt->nAvgBytesPerSec != fmt->nBlockAlign * fmt->nSamplesPerSec) {
2135 params->result = E_INVALIDARG;
2136 break;
2139 if (exclusive) {
2140 UINT32 mask = 0, i, channels = 0;
2142 if (!(in.dwChannelMask & (SPEAKER_ALL | SPEAKER_RESERVED))) {
2143 for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) {
2144 if (i & in.dwChannelMask) {
2145 mask |= i;
2146 ++channels;
2150 if (channels != fmt->nChannels || (in.dwChannelMask & ~mask)) {
2151 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2152 break;
2154 } else {
2155 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2156 break;
2160 if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
2161 if (fmt->wBitsPerSample != 32) {
2162 params->result = E_INVALIDARG;
2163 break;
2166 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample) {
2167 params->result = S_FALSE;
2168 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2170 } else if (IsEqualGUID(&in.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
2171 if (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8) {
2172 params->result = E_INVALIDARG;
2173 break;
2176 if (in.Samples.wValidBitsPerSample != fmt->wBitsPerSample &&
2177 !(fmt->wBitsPerSample == 32 &&
2178 in.Samples.wValidBitsPerSample == 24)) {
2179 params->result = S_FALSE;
2180 out->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
2181 break;
2183 } else {
2184 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2185 break;
2188 break;
2190 case WAVE_FORMAT_ALAW:
2191 case WAVE_FORMAT_MULAW:
2192 if (fmt->wBitsPerSample != 8) {
2193 params->result = E_INVALIDARG;
2194 break;
2196 /* Fall-through */
2197 case WAVE_FORMAT_IEEE_FLOAT:
2198 if (fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT && fmt->wBitsPerSample != 32) {
2199 params->result = E_INVALIDARG;
2200 break;
2202 /* Fall-through */
2203 case WAVE_FORMAT_PCM: {
2204 if (fmt->wFormatTag == WAVE_FORMAT_PCM &&
2205 (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8)) {
2206 params->result = E_INVALIDARG;
2207 break;
2210 if (fmt->nChannels > 2) {
2211 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2212 break;
2215 /* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
2216 * ignored, invalid values are happily accepted. */
2217 break;
2219 default:
2220 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2221 break;
2224 if (exclusive) { /* This driver does not support exclusive mode. */
2225 if (params->result == S_OK)
2226 params->result = params->flow == eCapture ?
2227 AUDCLNT_E_UNSUPPORTED_FORMAT :
2228 AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
2229 else if (params->result == S_FALSE)
2230 params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
2233 return STATUS_SUCCESS;
2236 static NTSTATUS pulse_get_mix_format(void *args)
2238 struct get_mix_format_params *params = args;
2239 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2240 PhysDevice *dev;
2242 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2243 if (strcmp(params->device, dev->pulse_name))
2244 continue;
2246 *params->fmt = dev->fmt;
2247 params->result = S_OK;
2249 return STATUS_SUCCESS;
2252 params->result = E_FAIL;
2253 return STATUS_SUCCESS;
2256 static NTSTATUS pulse_get_device_period(void *args)
2258 struct get_device_period_params *params = args;
2260 params->result = get_device_period_helper(params->flow, params->device, params->def_period, params->min_period);
2261 return STATUS_SUCCESS;
2264 static NTSTATUS pulse_get_buffer_size(void *args)
2266 struct get_buffer_size_params *params = args;
2267 struct pulse_stream *stream = handle_get_stream(params->stream);
2269 params->result = S_OK;
2271 pulse_lock();
2272 if (!pulse_stream_valid(stream))
2273 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2274 else
2275 *params->frames = stream->bufsize_frames;
2276 pulse_unlock();
2278 return STATUS_SUCCESS;
2281 static NTSTATUS pulse_get_latency(void *args)
2283 struct get_latency_params *params = args;
2284 struct pulse_stream *stream = handle_get_stream(params->stream);
2285 const pa_buffer_attr *attr;
2286 REFERENCE_TIME lat;
2288 pulse_lock();
2289 if (!pulse_stream_valid(stream)) {
2290 pulse_unlock();
2291 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2292 return STATUS_SUCCESS;
2294 attr = pa_stream_get_buffer_attr(stream->stream);
2295 if (stream->dataflow == eRender)
2296 lat = attr->minreq / pa_frame_size(&stream->ss);
2297 else
2298 lat = attr->fragsize / pa_frame_size(&stream->ss);
2299 *params->latency = (lat * 10000000) / stream->ss.rate + stream->def_period;
2300 pulse_unlock();
2301 TRACE("Latency: %u ms\n", (unsigned)(*params->latency / 10000));
2302 params->result = S_OK;
2303 return STATUS_SUCCESS;
2306 static NTSTATUS pulse_get_current_padding(void *args)
2308 struct get_current_padding_params *params = args;
2309 struct pulse_stream *stream = handle_get_stream(params->stream);
2311 pulse_lock();
2312 if (!pulse_stream_valid(stream))
2314 pulse_unlock();
2315 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2316 return STATUS_SUCCESS;
2319 if (stream->dataflow == eRender)
2320 *params->padding = pulse_render_padding(stream);
2321 else
2322 *params->padding = pulse_capture_padding(stream);
2323 pulse_unlock();
2325 TRACE("%p Pad: %u ms (%u)\n", stream, muldiv(*params->padding, 1000, stream->ss.rate),
2326 *params->padding);
2327 params->result = S_OK;
2328 return STATUS_SUCCESS;
2331 static NTSTATUS pulse_get_next_packet_size(void *args)
2333 struct get_next_packet_size_params *params = args;
2334 struct pulse_stream *stream = handle_get_stream(params->stream);
2336 pulse_lock();
2337 pulse_capture_padding(stream);
2338 if (stream->locked_ptr)
2339 *params->frames = stream->period_bytes / pa_frame_size(&stream->ss);
2340 else
2341 *params->frames = 0;
2342 pulse_unlock();
2343 params->result = S_OK;
2345 return STATUS_SUCCESS;
2348 static NTSTATUS pulse_get_frequency(void *args)
2350 struct get_frequency_params *params = args;
2351 struct pulse_stream *stream = handle_get_stream(params->stream);
2353 pulse_lock();
2354 if (!pulse_stream_valid(stream))
2356 pulse_unlock();
2357 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2358 return STATUS_SUCCESS;
2361 *params->freq = stream->ss.rate;
2362 if (stream->share == AUDCLNT_SHAREMODE_SHARED)
2363 *params->freq *= pa_frame_size(&stream->ss);
2364 pulse_unlock();
2365 params->result = S_OK;
2366 return STATUS_SUCCESS;
2369 static NTSTATUS pulse_get_position(void *args)
2371 struct get_position_params *params = args;
2372 struct pulse_stream *stream = handle_get_stream(params->stream);
2374 pulse_lock();
2375 if (!pulse_stream_valid(stream))
2377 pulse_unlock();
2378 params->result = AUDCLNT_E_DEVICE_INVALIDATED;
2379 return STATUS_SUCCESS;
2382 *params->pos = stream->clock_written - stream->held_bytes;
2384 if (stream->share == AUDCLNT_SHAREMODE_EXCLUSIVE || params->device)
2385 *params->pos /= pa_frame_size(&stream->ss);
2387 /* Make time never go backwards */
2388 if (*params->pos < stream->clock_lastpos)
2389 *params->pos = stream->clock_lastpos;
2390 else
2391 stream->clock_lastpos = *params->pos;
2392 pulse_unlock();
2394 TRACE("%p Position: %u\n", stream, (unsigned)*params->pos);
2396 if (params->qpctime)
2398 LARGE_INTEGER stamp, freq;
2399 NtQueryPerformanceCounter(&stamp, &freq);
2400 *params->qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2403 params->result = S_OK;
2404 return STATUS_SUCCESS;
2407 static NTSTATUS pulse_set_volumes(void *args)
2409 struct set_volumes_params *params = args;
2410 struct pulse_stream *stream = handle_get_stream(params->stream);
2411 unsigned int i;
2413 for (i = 0; i < stream->ss.channels; i++)
2414 stream->vol[i] = params->volumes[i] * params->master_volume * params->session_volumes[i];
2416 return STATUS_SUCCESS;
2419 static NTSTATUS pulse_set_event_handle(void *args)
2421 struct set_event_handle_params *params = args;
2422 struct pulse_stream *stream = handle_get_stream(params->stream);
2423 HRESULT hr = S_OK;
2425 pulse_lock();
2426 if (!pulse_stream_valid(stream))
2427 hr = AUDCLNT_E_DEVICE_INVALIDATED;
2428 else if (!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
2429 hr = AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
2430 else if (stream->event)
2431 hr = HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
2432 else
2433 stream->event = params->event;
2434 pulse_unlock();
2436 params->result = hr;
2437 return STATUS_SUCCESS;
2440 static NTSTATUS pulse_is_started(void *args)
2442 struct is_started_params *params = args;
2443 struct pulse_stream *stream = handle_get_stream(params->stream);
2445 pulse_lock();
2446 params->result = pulse_stream_valid(stream) && stream->started ? S_OK : S_FALSE;
2447 pulse_unlock();
2449 return STATUS_SUCCESS;
2452 static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *params)
2454 const GUID *guid = params->guid;
2455 PROPVARIANT *out = params->value;
2456 UINT serial_number;
2457 char path[128];
2458 int len;
2460 /* As hardly any audio devices have serial numbers, Windows instead
2461 appears to use a persistent random number. We emulate this here
2462 by instead using the last 8 hex digits of the GUID. */
2463 serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
2465 switch (dev->bus_type) {
2466 case phys_device_bus_pci:
2467 len = sprintf(path, "{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2468 break;
2469 case phys_device_bus_usb:
2470 len = sprintf(path, "{1}.USB\\VID_%04X&PID_%04X\\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number);
2471 break;
2472 default:
2473 len = sprintf(path, "{1}.ROOT\\MEDIA\\%04u", dev->index);
2474 break;
2477 if (*params->buffer_size < ++len * sizeof(WCHAR)) {
2478 params->result = E_NOT_SUFFICIENT_BUFFER;
2479 *params->buffer_size = len * sizeof(WCHAR);
2480 return FALSE;
2483 out->vt = VT_LPWSTR;
2484 out->pwszVal = params->buffer;
2486 ntdll_umbstowcs(path, len, out->pwszVal, len);
2488 params->result = S_OK;
2490 return TRUE;
2493 static NTSTATUS pulse_get_prop_value(void *args)
2495 static const GUID PKEY_AudioEndpoint_GUID = {
2496 0x1da5d803, 0xd492, 0x4edd, {0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e}
2498 static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
2499 {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
2501 struct get_prop_value_params *params = args;
2502 struct list *list = (params->flow == eRender) ? &g_phys_speakers : &g_phys_sources;
2503 PhysDevice *dev;
2505 LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
2506 if (strcmp(params->device, dev->pulse_name))
2507 continue;
2508 if (IsEqualPropertyKey(*params->prop, devicepath_key)) {
2509 get_device_path(dev, params);
2510 return STATUS_SUCCESS;
2511 } else if (IsEqualGUID(&params->prop->fmtid, &PKEY_AudioEndpoint_GUID)) {
2512 switch (params->prop->pid) {
2513 case 0: /* FormFactor */
2514 params->value->vt = VT_UI4;
2515 params->value->ulVal = dev->form;
2516 params->result = S_OK;
2517 return STATUS_SUCCESS;
2518 case 3: /* PhysicalSpeakers */
2519 if (!dev->channel_mask)
2520 goto fail;
2521 params->value->vt = VT_UI4;
2522 params->value->ulVal = dev->channel_mask;
2523 params->result = S_OK;
2524 return STATUS_SUCCESS;
2528 params->result = E_NOTIMPL;
2529 return STATUS_SUCCESS;
2532 fail:
2533 params->result = E_FAIL;
2534 return STATUS_SUCCESS;
2537 const unixlib_entry_t __wine_unix_call_funcs[] =
2539 pulse_process_attach,
2540 pulse_process_detach,
2541 pulse_main_loop,
2542 pulse_get_endpoint_ids,
2543 pulse_create_stream,
2544 pulse_release_stream,
2545 pulse_start,
2546 pulse_stop,
2547 pulse_reset,
2548 pulse_timer_loop,
2549 pulse_get_render_buffer,
2550 pulse_release_render_buffer,
2551 pulse_get_capture_buffer,
2552 pulse_release_capture_buffer,
2553 pulse_is_format_supported,
2554 pulse_get_mix_format,
2555 pulse_get_device_period,
2556 pulse_get_buffer_size,
2557 pulse_get_latency,
2558 pulse_get_current_padding,
2559 pulse_get_next_packet_size,
2560 pulse_get_frequency,
2561 pulse_get_position,
2562 pulse_set_volumes,
2563 pulse_set_event_handle,
2564 pulse_test_connect,
2565 pulse_is_started,
2566 pulse_get_prop_value,
2567 pulse_not_implemented,
2568 pulse_not_implemented,
2569 pulse_not_implemented,
2570 pulse_not_implemented,
2571 pulse_not_implemented,
2572 pulse_not_implemented,
2575 #ifdef _WIN64
2577 typedef UINT PTR32;
2579 static NTSTATUS pulse_wow64_main_loop(void *args)
2581 struct
2583 PTR32 event;
2584 } *params32 = args;
2585 struct main_loop_params params =
2587 .event = ULongToHandle(params32->event)
2589 return pulse_main_loop(&params);
2592 static NTSTATUS pulse_wow64_get_endpoint_ids(void *args)
2594 struct
2596 EDataFlow flow;
2597 PTR32 endpoints;
2598 unsigned int size;
2599 HRESULT result;
2600 unsigned int num;
2601 unsigned int default_idx;
2602 } *params32 = args;
2603 struct get_endpoint_ids_params params =
2605 .flow = params32->flow,
2606 .endpoints = ULongToPtr(params32->endpoints),
2607 .size = params32->size
2609 pulse_get_endpoint_ids(&params);
2610 params32->size = params.size;
2611 params32->result = params.result;
2612 params32->num = params.num;
2613 params32->default_idx = params.default_idx;
2614 return STATUS_SUCCESS;
2617 static NTSTATUS pulse_wow64_create_stream(void *args)
2619 struct
2621 PTR32 name;
2622 PTR32 device;
2623 EDataFlow flow;
2624 AUDCLNT_SHAREMODE share;
2625 DWORD flags;
2626 REFERENCE_TIME duration;
2627 REFERENCE_TIME period;
2628 PTR32 fmt;
2629 HRESULT result;
2630 PTR32 channel_count;
2631 PTR32 stream;
2632 } *params32 = args;
2633 struct create_stream_params params =
2635 .name = ULongToPtr(params32->name),
2636 .device = ULongToPtr(params32->device),
2637 .flow = params32->flow,
2638 .share = params32->share,
2639 .flags = params32->flags,
2640 .duration = params32->duration,
2641 .period = params32->period,
2642 .fmt = ULongToPtr(params32->fmt),
2643 .channel_count = ULongToPtr(params32->channel_count),
2644 .stream = ULongToPtr(params32->stream)
2646 pulse_create_stream(&params);
2647 params32->result = params.result;
2648 return STATUS_SUCCESS;
2651 static NTSTATUS pulse_wow64_release_stream(void *args)
2653 struct
2655 stream_handle stream;
2656 PTR32 timer_thread;
2657 HRESULT result;
2658 } *params32 = args;
2659 struct release_stream_params params =
2661 .stream = params32->stream,
2662 .timer_thread = ULongToHandle(params32->timer_thread)
2664 pulse_release_stream(&params);
2665 params32->result = params.result;
2666 return STATUS_SUCCESS;
2669 static NTSTATUS pulse_wow64_get_render_buffer(void *args)
2671 struct
2673 stream_handle stream;
2674 UINT32 frames;
2675 HRESULT result;
2676 PTR32 data;
2677 } *params32 = args;
2678 BYTE *data = NULL;
2679 struct get_render_buffer_params params =
2681 .stream = params32->stream,
2682 .frames = params32->frames,
2683 .data = &data
2685 pulse_get_render_buffer(&params);
2686 params32->result = params.result;
2687 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2688 return STATUS_SUCCESS;
2691 static NTSTATUS pulse_wow64_get_capture_buffer(void *args)
2693 struct
2695 stream_handle stream;
2696 HRESULT result;
2697 PTR32 data;
2698 PTR32 frames;
2699 PTR32 flags;
2700 PTR32 devpos;
2701 PTR32 qpcpos;
2702 } *params32 = args;
2703 BYTE *data = NULL;
2704 struct get_capture_buffer_params params =
2706 .stream = params32->stream,
2707 .data = &data,
2708 .frames = ULongToPtr(params32->frames),
2709 .flags = ULongToPtr(params32->flags),
2710 .devpos = ULongToPtr(params32->devpos),
2711 .qpcpos = ULongToPtr(params32->qpcpos)
2713 pulse_get_capture_buffer(&params);
2714 params32->result = params.result;
2715 *(unsigned int *)ULongToPtr(params32->data) = PtrToUlong(data);
2716 return STATUS_SUCCESS;
2719 static NTSTATUS pulse_wow64_is_format_supported(void *args)
2721 struct
2723 PTR32 device;
2724 EDataFlow flow;
2725 AUDCLNT_SHAREMODE share;
2726 PTR32 fmt_in;
2727 PTR32 fmt_out;
2728 HRESULT result;
2729 } *params32 = args;
2730 struct is_format_supported_params params =
2732 .device = ULongToPtr(params32->device),
2733 .flow = params32->flow,
2734 .share = params32->share,
2735 .fmt_in = ULongToPtr(params32->fmt_in),
2736 .fmt_out = ULongToPtr(params32->fmt_out)
2738 pulse_is_format_supported(&params);
2739 params32->result = params.result;
2740 return STATUS_SUCCESS;
2743 static NTSTATUS pulse_wow64_get_mix_format(void *args)
2745 struct
2747 PTR32 device;
2748 EDataFlow flow;
2749 PTR32 fmt;
2750 HRESULT result;
2751 } *params32 = args;
2752 struct get_mix_format_params params =
2754 .device = ULongToPtr(params32->device),
2755 .flow = params32->flow,
2756 .fmt = ULongToPtr(params32->fmt),
2758 pulse_get_mix_format(&params);
2759 params32->result = params.result;
2760 return STATUS_SUCCESS;
2763 static NTSTATUS pulse_wow64_get_device_period(void *args)
2765 struct
2767 PTR32 device;
2768 EDataFlow flow;
2769 HRESULT result;
2770 PTR32 def_period;
2771 PTR32 min_period;
2772 } *params32 = args;
2773 struct get_device_period_params params =
2775 .device = ULongToPtr(params32->device),
2776 .flow = params32->flow,
2777 .def_period = ULongToPtr(params32->def_period),
2778 .min_period = ULongToPtr(params32->min_period),
2780 pulse_get_device_period(&params);
2781 params32->result = params.result;
2782 return STATUS_SUCCESS;
2785 static NTSTATUS pulse_wow64_get_buffer_size(void *args)
2787 struct
2789 stream_handle stream;
2790 HRESULT result;
2791 PTR32 frames;
2792 } *params32 = args;
2793 struct get_buffer_size_params params =
2795 .stream = params32->stream,
2796 .frames = ULongToPtr(params32->frames)
2798 pulse_get_buffer_size(&params);
2799 params32->result = params.result;
2800 return STATUS_SUCCESS;
2803 static NTSTATUS pulse_wow64_get_latency(void *args)
2805 struct
2807 stream_handle stream;
2808 HRESULT result;
2809 PTR32 latency;
2810 } *params32 = args;
2811 struct get_latency_params params =
2813 .stream = params32->stream,
2814 .latency = ULongToPtr(params32->latency)
2816 pulse_get_latency(&params);
2817 params32->result = params.result;
2818 return STATUS_SUCCESS;
2821 static NTSTATUS pulse_wow64_get_current_padding(void *args)
2823 struct
2825 stream_handle stream;
2826 HRESULT result;
2827 PTR32 padding;
2828 } *params32 = args;
2829 struct get_current_padding_params params =
2831 .stream = params32->stream,
2832 .padding = ULongToPtr(params32->padding)
2834 pulse_get_current_padding(&params);
2835 params32->result = params.result;
2836 return STATUS_SUCCESS;
2839 static NTSTATUS pulse_wow64_get_next_packet_size(void *args)
2841 struct
2843 stream_handle stream;
2844 HRESULT result;
2845 PTR32 frames;
2846 } *params32 = args;
2847 struct get_next_packet_size_params params =
2849 .stream = params32->stream,
2850 .frames = ULongToPtr(params32->frames)
2852 pulse_get_next_packet_size(&params);
2853 params32->result = params.result;
2854 return STATUS_SUCCESS;
2857 static NTSTATUS pulse_wow64_get_frequency(void *args)
2859 struct
2861 stream_handle stream;
2862 HRESULT result;
2863 PTR32 freq;
2864 } *params32 = args;
2865 struct get_frequency_params params =
2867 .stream = params32->stream,
2868 .freq = ULongToPtr(params32->freq)
2870 pulse_get_frequency(&params);
2871 params32->result = params.result;
2872 return STATUS_SUCCESS;
2875 static NTSTATUS pulse_wow64_get_position(void *args)
2877 struct
2879 stream_handle stream;
2880 BOOL device;
2881 HRESULT result;
2882 PTR32 pos;
2883 PTR32 qpctime;
2884 } *params32 = args;
2885 struct get_position_params params =
2887 .stream = params32->stream,
2888 .device = params32->device,
2889 .pos = ULongToPtr(params32->pos),
2890 .qpctime = ULongToPtr(params32->qpctime)
2892 pulse_get_position(&params);
2893 params32->result = params.result;
2894 return STATUS_SUCCESS;
2897 static NTSTATUS pulse_wow64_set_volumes(void *args)
2899 struct
2901 stream_handle stream;
2902 float master_volume;
2903 PTR32 volumes;
2904 PTR32 session_volumes;
2905 } *params32 = args;
2906 struct set_volumes_params params =
2908 .stream = params32->stream,
2909 .master_volume = params32->master_volume,
2910 .volumes = ULongToPtr(params32->volumes),
2911 .session_volumes = ULongToPtr(params32->session_volumes),
2913 return pulse_set_volumes(&params);
2916 static NTSTATUS pulse_wow64_set_event_handle(void *args)
2918 struct
2920 stream_handle stream;
2921 PTR32 event;
2922 HRESULT result;
2923 } *params32 = args;
2924 struct set_event_handle_params params =
2926 .stream = params32->stream,
2927 .event = ULongToHandle(params32->event)
2929 pulse_set_event_handle(&params);
2930 params32->result = params.result;
2931 return STATUS_SUCCESS;
2934 static NTSTATUS pulse_wow64_test_connect(void *args)
2936 struct
2938 PTR32 name;
2939 enum driver_priority priority;
2940 } *params32 = args;
2941 struct test_connect_params params =
2943 .name = ULongToPtr(params32->name),
2945 pulse_test_connect(&params);
2946 params32->priority = params.priority;
2947 return STATUS_SUCCESS;
2950 static NTSTATUS pulse_wow64_get_prop_value(void *args)
2952 struct propvariant32
2954 WORD vt;
2955 WORD pad1, pad2, pad3;
2956 union
2958 ULONG ulVal;
2959 PTR32 ptr;
2960 ULARGE_INTEGER uhVal;
2962 } *value32;
2963 struct
2965 PTR32 device;
2966 EDataFlow flow;
2967 PTR32 guid;
2968 PTR32 prop;
2969 HRESULT result;
2970 PTR32 value;
2971 PTR32 buffer; /* caller allocated buffer to hold value's strings */
2972 PTR32 buffer_size;
2973 } *params32 = args;
2974 PROPVARIANT value;
2975 struct get_prop_value_params params =
2977 .device = ULongToPtr(params32->device),
2978 .flow = params32->flow,
2979 .guid = ULongToPtr(params32->guid),
2980 .prop = ULongToPtr(params32->prop),
2981 .value = &value,
2982 .buffer = ULongToPtr(params32->buffer),
2983 .buffer_size = ULongToPtr(params32->buffer_size)
2985 pulse_get_prop_value(&params);
2986 params32->result = params.result;
2987 if (SUCCEEDED(params.result))
2989 value32 = UlongToPtr(params32->value);
2990 value32->vt = value.vt;
2991 switch (value.vt)
2993 case VT_UI4:
2994 value32->ulVal = value.ulVal;
2995 break;
2996 case VT_LPWSTR:
2997 value32->ptr = params32->buffer;
2998 break;
2999 default:
3000 FIXME("Unhandled vt %04x\n", value.vt);
3003 return STATUS_SUCCESS;
3006 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
3008 pulse_process_attach,
3009 pulse_process_detach,
3010 pulse_wow64_main_loop,
3011 pulse_wow64_get_endpoint_ids,
3012 pulse_wow64_create_stream,
3013 pulse_wow64_release_stream,
3014 pulse_start,
3015 pulse_stop,
3016 pulse_reset,
3017 pulse_timer_loop,
3018 pulse_wow64_get_render_buffer,
3019 pulse_release_render_buffer,
3020 pulse_wow64_get_capture_buffer,
3021 pulse_release_capture_buffer,
3022 pulse_wow64_is_format_supported,
3023 pulse_wow64_get_mix_format,
3024 pulse_wow64_get_device_period,
3025 pulse_wow64_get_buffer_size,
3026 pulse_wow64_get_latency,
3027 pulse_wow64_get_current_padding,
3028 pulse_wow64_get_next_packet_size,
3029 pulse_wow64_get_frequency,
3030 pulse_wow64_get_position,
3031 pulse_wow64_set_volumes,
3032 pulse_wow64_set_event_handle,
3033 pulse_wow64_test_connect,
3034 pulse_is_started,
3035 pulse_wow64_get_prop_value,
3036 pulse_not_implemented,
3037 pulse_not_implemented,
3038 pulse_not_implemented,
3039 pulse_not_implemented,
3040 pulse_not_implemented,
3041 pulse_not_implemented,
3044 #endif /* _WIN64 */