2 * Copyright 2011-2012 Maarten Lankhorst
3 * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers
4 * Copyright 2011 Andrew Eikum for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include <pulse/pulseaudio.h>
33 #define WIN32_NO_STATUS
36 #include "mmdeviceapi.h"
38 #include "audioclient.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(pulse
);
56 AUDCLNT_SHAREMODE share
;
58 float vol
[PA_CHANNELS_MAX
];
63 SIZE_T bufsize_frames
, alloc_size
, real_bufsize_bytes
, period_bytes
;
64 SIZE_T peek_ofs
, read_offs_bytes
, lcl_offs_bytes
, pa_offs_bytes
;
65 SIZE_T tmp_buffer_bytes
, held_bytes
, peek_len
, peek_buffer_len
, pa_held_bytes
;
66 BYTE
*local_buffer
, *tmp_buffer
, *peek_buffer
;
68 BOOL please_quit
, just_started
, just_underran
;
69 pa_usec_t last_time
, mmdev_period_usec
;
71 INT64 clock_lastpos
, clock_written
;
73 struct list packet_free_head
;
74 struct list packet_filled_head
;
77 typedef struct _ACPacket
85 static pa_context
*pulse_ctx
;
86 static pa_mainloop
*pulse_ml
;
88 /* Mixer format + period times */
89 static WAVEFORMATEXTENSIBLE pulse_fmt
[2];
90 static REFERENCE_TIME pulse_min_period
[2], pulse_def_period
[2];
92 static UINT g_phys_speakers_mask
= 0;
94 static const REFERENCE_TIME MinimumPeriod
= 30000;
95 static const REFERENCE_TIME DefaultPeriod
= 100000;
97 static pthread_mutex_t pulse_mutex
;
98 static pthread_cond_t pulse_cond
= PTHREAD_COND_INITIALIZER
;
100 UINT8
mult_alaw_sample(UINT8
, float);
101 UINT8
mult_ulaw_sample(UINT8
, float);
103 static void pulse_lock(void)
105 pthread_mutex_lock(&pulse_mutex
);
108 static void pulse_unlock(void)
110 pthread_mutex_unlock(&pulse_mutex
);
113 static int pulse_cond_wait(void)
115 return pthread_cond_wait(&pulse_cond
, &pulse_mutex
);
118 static void pulse_broadcast(void)
120 pthread_cond_broadcast(&pulse_cond
);
123 static void dump_attr(const pa_buffer_attr
*attr
)
125 TRACE("maxlength: %u\n", attr
->maxlength
);
126 TRACE("minreq: %u\n", attr
->minreq
);
127 TRACE("fragsize: %u\n", attr
->fragsize
);
128 TRACE("tlength: %u\n", attr
->tlength
);
129 TRACE("prebuf: %u\n", attr
->prebuf
);
132 /* copied from kernelbase */
133 static int muldiv(int a
, int b
, int c
)
139 /* We want to deal with a positive divisor to simplify the logic. */
146 /* If the result is positive, we "add" to round. else, we subtract to round. */
147 if ((a
< 0 && b
< 0) || (a
>= 0 && b
>= 0))
148 ret
= (((LONGLONG
)a
* b
) + (c
/ 2)) / c
;
150 ret
= (((LONGLONG
)a
* b
) - (c
/ 2)) / c
;
152 if (ret
> 2147483647 || ret
< -2147483647) return -1;
156 /* Following pulseaudio design here, mainloop has the lock taken whenever
157 * it is handling something for pulse, and the lock is required whenever
158 * doing any pa_* call that can affect the state in any way
160 * pa_cond_wait is used when waiting on results, because the mainloop needs
161 * the same lock taken to affect the state
163 * This is basically the same as the pa_threaded_mainloop implementation,
164 * but that cannot be used because it uses pthread_create directly
166 * pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock
167 * pa_threaded_mainloop_signal -> pthread_cond_broadcast
168 * pa_threaded_mainloop_wait -> pthread_cond_wait
170 static int pulse_poll_func(struct pollfd
*ufds
, unsigned long nfds
, int timeout
, void *userdata
)
174 r
= poll(ufds
, nfds
, timeout
);
179 static void WINAPI
pulse_main_loop(struct main_loop_params
*params
)
183 pulse_ml
= pa_mainloop_new();
184 pa_mainloop_set_poll_func(pulse_ml
, pulse_poll_func
, NULL
);
185 NtSetEvent(params
->event
, NULL
);
186 pa_mainloop_run(pulse_ml
, &ret
);
187 pa_mainloop_free(pulse_ml
);
191 static void pulse_contextcallback(pa_context
*c
, void *userdata
)
193 switch (pa_context_get_state(c
)) {
195 FIXME("Unhandled state: %i\n", pa_context_get_state(c
));
198 case PA_CONTEXT_CONNECTING
:
199 case PA_CONTEXT_UNCONNECTED
:
200 case PA_CONTEXT_AUTHORIZING
:
201 case PA_CONTEXT_SETTING_NAME
:
202 case PA_CONTEXT_TERMINATED
:
203 TRACE("State change to %i\n", pa_context_get_state(c
));
206 case PA_CONTEXT_READY
:
210 case PA_CONTEXT_FAILED
:
211 WARN("Context failed: %s\n", pa_strerror(pa_context_errno(c
)));
217 static void pulse_stream_state(pa_stream
*s
, void *user
)
219 pa_stream_state_t state
= pa_stream_get_state(s
);
220 TRACE("Stream state changed to %i\n", state
);
224 static void pulse_attr_update(pa_stream
*s
, void *user
) {
225 const pa_buffer_attr
*attr
= pa_stream_get_buffer_attr(s
);
226 TRACE("New attributes or device moved:\n");
230 static void pulse_underflow_callback(pa_stream
*s
, void *userdata
)
232 struct pulse_stream
*stream
= userdata
;
233 WARN("%p: Underflow\n", userdata
);
234 stream
->just_underran
= TRUE
;
236 stream
->pa_offs_bytes
= stream
->lcl_offs_bytes
;
237 stream
->pa_held_bytes
= stream
->held_bytes
;
240 static void pulse_started_callback(pa_stream
*s
, void *userdata
)
242 TRACE("%p: (Re)started playing\n", userdata
);
245 static void pulse_op_cb(pa_stream
*s
, int success
, void *user
)
247 TRACE("Success: %i\n", success
);
248 *(int*)user
= success
;
252 static void silence_buffer(pa_sample_format_t format
, BYTE
*buffer
, UINT32 bytes
)
254 memset(buffer
, format
== PA_SAMPLE_U8
? 0x80 : 0, bytes
);
257 static BOOL
pulse_stream_valid(struct pulse_stream
*stream
)
259 return pa_stream_get_state(stream
->stream
) == PA_STREAM_READY
;
262 static HRESULT
pulse_connect(const char *name
)
264 if (pulse_ctx
&& PA_CONTEXT_IS_GOOD(pa_context_get_state(pulse_ctx
)))
267 pa_context_unref(pulse_ctx
);
269 pulse_ctx
= pa_context_new(pa_mainloop_get_api(pulse_ml
), name
);
271 ERR("Failed to create context\n");
275 pa_context_set_state_callback(pulse_ctx
, pulse_contextcallback
, NULL
);
277 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx
), PA_API_VERSION
);
278 if (pa_context_connect(pulse_ctx
, NULL
, 0, NULL
) < 0)
281 /* Wait for connection */
282 while (pulse_cond_wait()) {
283 pa_context_state_t state
= pa_context_get_state(pulse_ctx
);
285 if (state
== PA_CONTEXT_FAILED
|| state
== PA_CONTEXT_TERMINATED
)
288 if (state
== PA_CONTEXT_READY
)
292 TRACE("Connected to server %s with protocol version: %i.\n",
293 pa_context_get_server(pulse_ctx
),
294 pa_context_get_server_protocol_version(pulse_ctx
));
298 pa_context_unref(pulse_ctx
);
303 static DWORD
pulse_channel_map_to_channel_mask(const pa_channel_map
*map
)
308 for (i
= 0; i
< map
->channels
; ++i
) {
309 switch (map
->map
[i
]) {
310 default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map
->map
[i
])); break;
311 case PA_CHANNEL_POSITION_FRONT_LEFT
: mask
|= SPEAKER_FRONT_LEFT
; break;
312 case PA_CHANNEL_POSITION_MONO
:
313 case PA_CHANNEL_POSITION_FRONT_CENTER
: mask
|= SPEAKER_FRONT_CENTER
; break;
314 case PA_CHANNEL_POSITION_FRONT_RIGHT
: mask
|= SPEAKER_FRONT_RIGHT
; break;
315 case PA_CHANNEL_POSITION_REAR_LEFT
: mask
|= SPEAKER_BACK_LEFT
; break;
316 case PA_CHANNEL_POSITION_REAR_CENTER
: mask
|= SPEAKER_BACK_CENTER
; break;
317 case PA_CHANNEL_POSITION_REAR_RIGHT
: mask
|= SPEAKER_BACK_RIGHT
; break;
318 case PA_CHANNEL_POSITION_LFE
: mask
|= SPEAKER_LOW_FREQUENCY
; break;
319 case PA_CHANNEL_POSITION_SIDE_LEFT
: mask
|= SPEAKER_SIDE_LEFT
; break;
320 case PA_CHANNEL_POSITION_SIDE_RIGHT
: mask
|= SPEAKER_SIDE_RIGHT
; break;
321 case PA_CHANNEL_POSITION_TOP_CENTER
: mask
|= SPEAKER_TOP_CENTER
; break;
322 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT
: mask
|= SPEAKER_TOP_FRONT_LEFT
; break;
323 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER
: mask
|= SPEAKER_TOP_FRONT_CENTER
; break;
324 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
: mask
|= SPEAKER_TOP_FRONT_RIGHT
; break;
325 case PA_CHANNEL_POSITION_TOP_REAR_LEFT
: mask
|= SPEAKER_TOP_BACK_LEFT
; break;
326 case PA_CHANNEL_POSITION_TOP_REAR_CENTER
: mask
|= SPEAKER_TOP_BACK_CENTER
; break;
327 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT
: mask
|= SPEAKER_TOP_BACK_RIGHT
; break;
328 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
: mask
|= SPEAKER_FRONT_LEFT_OF_CENTER
; break;
329 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
: mask
|= SPEAKER_FRONT_RIGHT_OF_CENTER
; break;
336 /* For default PulseAudio render device, OR together all of the
337 * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
338 static void pulse_phys_speakers_cb(pa_context
*c
, const pa_sink_info
*i
, int eol
, void *userdata
)
341 g_phys_speakers_mask
|= pulse_channel_map_to_channel_mask(&i
->channel_map
);
344 /* For most hardware on Windows, users must choose a configuration with an even
345 * number of channels (stereo, quad, 5.1, 7.1). Users can then disable
346 * channels, but those channels are still reported to applications from
347 * GetMixFormat! Some applications behave badly if given an odd number of
348 * channels (e.g. 2.1). Here, we find the nearest configuration that Windows
349 * would report for a given channel layout. */
350 static void convert_channel_map(const pa_channel_map
*pa_map
, WAVEFORMATEXTENSIBLE
*fmt
)
352 DWORD pa_mask
= pulse_channel_map_to_channel_mask(pa_map
);
354 TRACE("got mask for PA: 0x%x\n", pa_mask
);
356 if (pa_map
->channels
== 1)
358 fmt
->Format
.nChannels
= 1;
359 fmt
->dwChannelMask
= pa_mask
;
363 /* compare against known configurations and find smallest configuration
364 * which is a superset of the given speakers */
366 if (pa_map
->channels
<= 2 &&
367 (pa_mask
& ~KSAUDIO_SPEAKER_STEREO
) == 0)
369 fmt
->Format
.nChannels
= 2;
370 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_STEREO
;
374 if (pa_map
->channels
<= 4 &&
375 (pa_mask
& ~KSAUDIO_SPEAKER_QUAD
) == 0)
377 fmt
->Format
.nChannels
= 4;
378 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_QUAD
;
382 if (pa_map
->channels
<= 4 &&
383 (pa_mask
& ~KSAUDIO_SPEAKER_SURROUND
) == 0)
385 fmt
->Format
.nChannels
= 4;
386 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_SURROUND
;
390 if (pa_map
->channels
<= 6 &&
391 (pa_mask
& ~KSAUDIO_SPEAKER_5POINT1
) == 0)
393 fmt
->Format
.nChannels
= 6;
394 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_5POINT1
;
398 if (pa_map
->channels
<= 6 &&
399 (pa_mask
& ~KSAUDIO_SPEAKER_5POINT1_SURROUND
) == 0)
401 fmt
->Format
.nChannels
= 6;
402 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_5POINT1_SURROUND
;
406 if (pa_map
->channels
<= 8 &&
407 (pa_mask
& ~KSAUDIO_SPEAKER_7POINT1
) == 0)
409 fmt
->Format
.nChannels
= 8;
410 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_7POINT1
;
414 if (pa_map
->channels
<= 8 &&
415 (pa_mask
& ~KSAUDIO_SPEAKER_7POINT1_SURROUND
) == 0)
417 fmt
->Format
.nChannels
= 8;
418 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_7POINT1_SURROUND
;
422 /* oddball format, report truthfully */
423 fmt
->Format
.nChannels
= pa_map
->channels
;
424 fmt
->dwChannelMask
= pa_mask
;
427 static void pulse_probe_settings(int render
, WAVEFORMATEXTENSIBLE
*fmt
) {
428 WAVEFORMATEX
*wfx
= &fmt
->Format
;
434 unsigned int length
= 0;
436 pa_channel_map_init_auto(&map
, 2, PA_CHANNEL_MAP_ALSA
);
438 ss
.format
= PA_SAMPLE_FLOAT32LE
;
439 ss
.channels
= map
.channels
;
443 attr
.minreq
= attr
.fragsize
= pa_frame_size(&ss
);
446 stream
= pa_stream_new(pulse_ctx
, "format test stream", &ss
, &map
);
448 pa_stream_set_state_callback(stream
, pulse_stream_state
, NULL
);
452 ret
= pa_stream_connect_playback(stream
, NULL
, &attr
,
453 PA_STREAM_START_CORKED
|PA_STREAM_FIX_RATE
|PA_STREAM_FIX_CHANNELS
|PA_STREAM_EARLY_REQUESTS
, NULL
, NULL
);
455 ret
= pa_stream_connect_record(stream
, NULL
, &attr
, PA_STREAM_START_CORKED
|PA_STREAM_FIX_RATE
|PA_STREAM_FIX_CHANNELS
|PA_STREAM_EARLY_REQUESTS
);
457 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
458 pa_stream_get_state(stream
) == PA_STREAM_CREATING
)
460 if (pa_stream_get_state(stream
) == PA_STREAM_READY
) {
461 ss
= *pa_stream_get_sample_spec(stream
);
462 map
= *pa_stream_get_channel_map(stream
);
464 length
= pa_stream_get_buffer_attr(stream
)->minreq
;
466 length
= pa_stream_get_buffer_attr(stream
)->fragsize
;
467 pa_stream_disconnect(stream
);
468 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
469 pa_stream_get_state(stream
) == PA_STREAM_READY
)
475 pa_stream_unref(stream
);
478 pulse_def_period
[!render
] = pulse_min_period
[!render
] = pa_bytes_to_usec(10 * length
, &ss
);
480 if (pulse_min_period
[!render
] < MinimumPeriod
)
481 pulse_min_period
[!render
] = MinimumPeriod
;
483 if (pulse_def_period
[!render
] < DefaultPeriod
)
484 pulse_def_period
[!render
] = DefaultPeriod
;
486 wfx
->wFormatTag
= WAVE_FORMAT_EXTENSIBLE
;
487 wfx
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
489 convert_channel_map(&map
, fmt
);
491 wfx
->wBitsPerSample
= 8 * pa_sample_size_of_format(ss
.format
);
492 wfx
->nSamplesPerSec
= ss
.rate
;
493 wfx
->nBlockAlign
= wfx
->nChannels
* wfx
->wBitsPerSample
/ 8;
494 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
495 if (ss
.format
!= PA_SAMPLE_S24_32LE
)
496 fmt
->Samples
.wValidBitsPerSample
= wfx
->wBitsPerSample
;
498 fmt
->Samples
.wValidBitsPerSample
= 24;
499 if (ss
.format
== PA_SAMPLE_FLOAT32LE
)
500 fmt
->SubFormat
= KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
;
502 fmt
->SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
505 /* some poorly-behaved applications call audio functions during DllMain, so we
506 * have to do as much as possible without creating a new thread. this function
507 * sets up a synchronous connection to verify the server is running and query
509 static void WINAPI
pulse_test_connect(struct test_connect_params
*params
)
511 struct pulse_config
*config
= params
->config
;
516 pulse_ml
= pa_mainloop_new();
518 pa_mainloop_set_poll_func(pulse_ml
, pulse_poll_func
, NULL
);
520 pulse_ctx
= pa_context_new(pa_mainloop_get_api(pulse_ml
), params
->name
);
522 ERR("Failed to create context\n");
523 pa_mainloop_free(pulse_ml
);
526 params
->result
= E_FAIL
;
530 pa_context_set_state_callback(pulse_ctx
, pulse_contextcallback
, NULL
);
532 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx
), PA_API_VERSION
);
533 if (pa_context_connect(pulse_ctx
, NULL
, 0, NULL
) < 0)
536 /* Wait for connection */
537 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0) {
538 pa_context_state_t state
= pa_context_get_state(pulse_ctx
);
540 if (state
== PA_CONTEXT_FAILED
|| state
== PA_CONTEXT_TERMINATED
)
543 if (state
== PA_CONTEXT_READY
)
547 if (pa_context_get_state(pulse_ctx
) != PA_CONTEXT_READY
)
550 TRACE("Test-connected to server %s with protocol version: %i.\n",
551 pa_context_get_server(pulse_ctx
),
552 pa_context_get_server_protocol_version(pulse_ctx
));
554 pulse_probe_settings(1, &pulse_fmt
[0]);
555 pulse_probe_settings(0, &pulse_fmt
[1]);
557 g_phys_speakers_mask
= 0;
558 o
= pa_context_get_sink_info_list(pulse_ctx
, &pulse_phys_speakers_cb
, NULL
);
560 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
561 pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
563 pa_operation_unref(o
);
566 pa_context_unref(pulse_ctx
);
568 pa_mainloop_free(pulse_ml
);
571 config
->speakers_mask
= g_phys_speakers_mask
;
572 config
->modes
[0].format
= pulse_fmt
[0];
573 config
->modes
[0].def_period
= pulse_def_period
[0];
574 config
->modes
[0].min_period
= pulse_min_period
[0];
575 config
->modes
[1].format
= pulse_fmt
[1];
576 config
->modes
[1].def_period
= pulse_def_period
[1];
577 config
->modes
[1].min_period
= pulse_min_period
[1];
581 params
->result
= S_OK
;
585 pa_context_unref(pulse_ctx
);
587 pa_mainloop_free(pulse_ml
);
590 params
->result
= E_FAIL
;
593 static DWORD
get_channel_mask(unsigned int channels
)
599 return KSAUDIO_SPEAKER_MONO
;
601 return KSAUDIO_SPEAKER_STEREO
;
603 return KSAUDIO_SPEAKER_STEREO
| SPEAKER_LOW_FREQUENCY
;
605 return KSAUDIO_SPEAKER_QUAD
; /* not _SURROUND */
607 return KSAUDIO_SPEAKER_QUAD
| SPEAKER_LOW_FREQUENCY
;
609 return KSAUDIO_SPEAKER_5POINT1
; /* not 5POINT1_SURROUND */
611 return KSAUDIO_SPEAKER_5POINT1
| SPEAKER_BACK_CENTER
;
613 return KSAUDIO_SPEAKER_7POINT1_SURROUND
; /* Vista deprecates 7POINT1 */
615 FIXME("Unknown speaker configuration: %u\n", channels
);
619 static const enum pa_channel_position pulse_pos_from_wfx
[] = {
620 PA_CHANNEL_POSITION_FRONT_LEFT
,
621 PA_CHANNEL_POSITION_FRONT_RIGHT
,
622 PA_CHANNEL_POSITION_FRONT_CENTER
,
623 PA_CHANNEL_POSITION_LFE
,
624 PA_CHANNEL_POSITION_REAR_LEFT
,
625 PA_CHANNEL_POSITION_REAR_RIGHT
,
626 PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
,
627 PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
,
628 PA_CHANNEL_POSITION_REAR_CENTER
,
629 PA_CHANNEL_POSITION_SIDE_LEFT
,
630 PA_CHANNEL_POSITION_SIDE_RIGHT
,
631 PA_CHANNEL_POSITION_TOP_CENTER
,
632 PA_CHANNEL_POSITION_TOP_FRONT_LEFT
,
633 PA_CHANNEL_POSITION_TOP_FRONT_CENTER
,
634 PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
,
635 PA_CHANNEL_POSITION_TOP_REAR_LEFT
,
636 PA_CHANNEL_POSITION_TOP_REAR_CENTER
,
637 PA_CHANNEL_POSITION_TOP_REAR_RIGHT
640 static HRESULT
pulse_spec_from_waveformat(struct pulse_stream
*stream
, const WAVEFORMATEX
*fmt
)
642 pa_channel_map_init(&stream
->map
);
643 stream
->ss
.rate
= fmt
->nSamplesPerSec
;
644 stream
->ss
.format
= PA_SAMPLE_INVALID
;
646 switch(fmt
->wFormatTag
) {
647 case WAVE_FORMAT_IEEE_FLOAT
:
648 if (!fmt
->nChannels
|| fmt
->nChannels
> 2 || fmt
->wBitsPerSample
!= 32)
650 stream
->ss
.format
= PA_SAMPLE_FLOAT32LE
;
651 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
653 case WAVE_FORMAT_PCM
:
654 if (!fmt
->nChannels
|| fmt
->nChannels
> 2)
656 if (fmt
->wBitsPerSample
== 8)
657 stream
->ss
.format
= PA_SAMPLE_U8
;
658 else if (fmt
->wBitsPerSample
== 16)
659 stream
->ss
.format
= PA_SAMPLE_S16LE
;
661 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
662 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
664 case WAVE_FORMAT_EXTENSIBLE
: {
665 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)fmt
;
666 DWORD mask
= wfe
->dwChannelMask
;
668 if (fmt
->cbSize
!= (sizeof(*wfe
) - sizeof(*fmt
)) && fmt
->cbSize
!= sizeof(*wfe
))
670 if (IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
671 (!wfe
->Samples
.wValidBitsPerSample
|| wfe
->Samples
.wValidBitsPerSample
== 32) &&
672 fmt
->wBitsPerSample
== 32)
673 stream
->ss
.format
= PA_SAMPLE_FLOAT32LE
;
674 else if (IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) {
675 DWORD valid
= wfe
->Samples
.wValidBitsPerSample
;
677 valid
= fmt
->wBitsPerSample
;
678 if (!valid
|| valid
> fmt
->wBitsPerSample
)
680 switch (fmt
->wBitsPerSample
) {
683 stream
->ss
.format
= PA_SAMPLE_U8
;
687 stream
->ss
.format
= PA_SAMPLE_S16LE
;
691 stream
->ss
.format
= PA_SAMPLE_S24LE
;
695 stream
->ss
.format
= PA_SAMPLE_S24_32LE
;
696 else if (valid
== 32)
697 stream
->ss
.format
= PA_SAMPLE_S32LE
;
700 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
703 stream
->map
.channels
= fmt
->nChannels
;
704 if (!mask
|| (mask
& (SPEAKER_ALL
|SPEAKER_RESERVED
)))
705 mask
= get_channel_mask(fmt
->nChannels
);
706 for (j
= 0; j
< ARRAY_SIZE(pulse_pos_from_wfx
) && i
< fmt
->nChannels
; ++j
) {
708 stream
->map
.map
[i
++] = pulse_pos_from_wfx
[j
];
711 /* Special case for mono since pulse appears to map it differently */
712 if (mask
== SPEAKER_FRONT_CENTER
)
713 stream
->map
.map
[0] = PA_CHANNEL_POSITION_MONO
;
715 if (i
< fmt
->nChannels
|| (mask
& SPEAKER_RESERVED
)) {
716 stream
->map
.channels
= 0;
717 ERR("Invalid channel mask: %i/%i and %x(%x)\n", i
, fmt
->nChannels
, mask
, wfe
->dwChannelMask
);
722 case WAVE_FORMAT_ALAW
:
723 case WAVE_FORMAT_MULAW
:
724 if (fmt
->wBitsPerSample
!= 8) {
725 FIXME("Unsupported bpp %u for LAW\n", fmt
->wBitsPerSample
);
726 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
728 if (fmt
->nChannels
!= 1 && fmt
->nChannels
!= 2) {
729 FIXME("Unsupported channels %u for LAW\n", fmt
->nChannels
);
730 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
732 stream
->ss
.format
= fmt
->wFormatTag
== WAVE_FORMAT_MULAW
? PA_SAMPLE_ULAW
: PA_SAMPLE_ALAW
;
733 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
736 WARN("Unhandled tag %x\n", fmt
->wFormatTag
);
737 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
739 stream
->ss
.channels
= stream
->map
.channels
;
740 if (!pa_channel_map_valid(&stream
->map
) || stream
->ss
.format
== PA_SAMPLE_INVALID
) {
741 ERR("Invalid format! Channel spec valid: %i, format: %i\n",
742 pa_channel_map_valid(&stream
->map
), stream
->ss
.format
);
743 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
748 static HRESULT
pulse_stream_connect(struct pulse_stream
*stream
, UINT32 period_bytes
)
755 ret
= InterlockedIncrement(&number
);
756 sprintf(buffer
, "audio stream #%i", ret
);
757 stream
->stream
= pa_stream_new(pulse_ctx
, buffer
, &stream
->ss
, &stream
->map
);
759 if (!stream
->stream
) {
760 WARN("pa_stream_new returned error %i\n", pa_context_errno(pulse_ctx
));
761 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
764 pa_stream_set_state_callback(stream
->stream
, pulse_stream_state
, stream
);
765 pa_stream_set_buffer_attr_callback(stream
->stream
, pulse_attr_update
, stream
);
766 pa_stream_set_moved_callback(stream
->stream
, pulse_attr_update
, stream
);
768 /* PulseAudio will fill in correct values */
769 attr
.minreq
= attr
.fragsize
= period_bytes
;
770 attr
.tlength
= period_bytes
* 3;
771 attr
.maxlength
= stream
->bufsize_frames
* pa_frame_size(&stream
->ss
);
772 attr
.prebuf
= pa_frame_size(&stream
->ss
);
774 if (stream
->dataflow
== eRender
)
775 ret
= pa_stream_connect_playback(stream
->stream
, NULL
, &attr
,
776 PA_STREAM_START_CORKED
|PA_STREAM_START_UNMUTED
|PA_STREAM_ADJUST_LATENCY
, NULL
, NULL
);
778 ret
= pa_stream_connect_record(stream
->stream
, NULL
, &attr
,
779 PA_STREAM_START_CORKED
|PA_STREAM_START_UNMUTED
|PA_STREAM_ADJUST_LATENCY
);
781 WARN("Returns %i\n", ret
);
782 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
784 while (pa_stream_get_state(stream
->stream
) == PA_STREAM_CREATING
)
786 if (pa_stream_get_state(stream
->stream
) != PA_STREAM_READY
)
787 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
789 if (stream
->dataflow
== eRender
) {
790 pa_stream_set_underflow_callback(stream
->stream
, pulse_underflow_callback
, stream
);
791 pa_stream_set_started_callback(stream
->stream
, pulse_started_callback
, stream
);
796 static void WINAPI
pulse_create_stream(struct create_stream_params
*params
)
798 REFERENCE_TIME period
, duration
= params
->duration
;
799 struct pulse_stream
*stream
;
800 unsigned int i
, bufsize_bytes
;
805 if (FAILED(params
->result
= pulse_connect(params
->name
)))
811 if (!(stream
= calloc(1, sizeof(*stream
))))
814 params
->result
= E_OUTOFMEMORY
;
818 stream
->dataflow
= params
->dataflow
;
819 for (i
= 0; i
< ARRAY_SIZE(stream
->vol
); ++i
)
820 stream
->vol
[i
] = 1.f
;
822 hr
= pulse_spec_from_waveformat(stream
, params
->fmt
);
823 TRACE("Obtaining format returns %08x\n", hr
);
828 period
= pulse_def_period
[stream
->dataflow
== eCapture
];
829 if (duration
< 3 * period
)
830 duration
= 3 * period
;
832 stream
->period_bytes
= pa_frame_size(&stream
->ss
) * muldiv(period
, stream
->ss
.rate
, 10000000);
834 stream
->bufsize_frames
= ceil((duration
/ 10000000.) * params
->fmt
->nSamplesPerSec
);
835 bufsize_bytes
= stream
->bufsize_frames
* pa_frame_size(&stream
->ss
);
836 stream
->mmdev_period_usec
= period
/ 10;
838 stream
->share
= params
->mode
;
839 stream
->flags
= params
->flags
;
840 hr
= pulse_stream_connect(stream
, stream
->period_bytes
);
843 const pa_buffer_attr
*attr
= pa_stream_get_buffer_attr(stream
->stream
);
844 stream
->attr
= *attr
;
845 /* Update frames according to new size */
847 if (stream
->dataflow
== eRender
) {
848 stream
->alloc_size
= stream
->real_bufsize_bytes
=
849 stream
->bufsize_frames
* 2 * pa_frame_size(&stream
->ss
);
850 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
851 0, &stream
->real_bufsize_bytes
, MEM_COMMIT
, PAGE_READWRITE
))
854 UINT32 i
, capture_packets
;
856 if ((unalign
= bufsize_bytes
% stream
->period_bytes
))
857 bufsize_bytes
+= stream
->period_bytes
- unalign
;
858 stream
->bufsize_frames
= bufsize_bytes
/ pa_frame_size(&stream
->ss
);
859 stream
->real_bufsize_bytes
= bufsize_bytes
;
861 capture_packets
= stream
->real_bufsize_bytes
/ stream
->period_bytes
;
863 stream
->alloc_size
= stream
->real_bufsize_bytes
+ capture_packets
* sizeof(ACPacket
);
864 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
865 0, &stream
->alloc_size
, MEM_COMMIT
, PAGE_READWRITE
))
868 ACPacket
*cur_packet
= (ACPacket
*)((char*)stream
->local_buffer
+ stream
->real_bufsize_bytes
);
869 BYTE
*data
= stream
->local_buffer
;
870 silence_buffer(stream
->ss
.format
, stream
->local_buffer
, stream
->real_bufsize_bytes
);
871 list_init(&stream
->packet_free_head
);
872 list_init(&stream
->packet_filled_head
);
873 for (i
= 0; i
< capture_packets
; ++i
, ++cur_packet
) {
874 list_add_tail(&stream
->packet_free_head
, &cur_packet
->entry
);
875 cur_packet
->data
= data
;
876 data
+= stream
->period_bytes
;
882 *params
->channel_count
= stream
->ss
.channels
;
883 *params
->stream
= stream
;
886 if (FAILED(params
->result
= hr
)) {
887 free(stream
->local_buffer
);
888 if (stream
->stream
) {
889 pa_stream_disconnect(stream
->stream
);
890 pa_stream_unref(stream
->stream
);
898 static void WINAPI
pulse_release_stream(struct release_stream_params
*params
)
900 struct pulse_stream
*stream
= params
->stream
;
903 stream
->please_quit
= TRUE
;
904 NtWaitForSingleObject(params
->timer
, FALSE
, NULL
);
905 NtClose(params
->timer
);
909 if (PA_STREAM_IS_GOOD(pa_stream_get_state(stream
->stream
))) {
910 pa_stream_disconnect(stream
->stream
);
911 while (PA_STREAM_IS_GOOD(pa_stream_get_state(stream
->stream
)))
914 pa_stream_unref(stream
->stream
);
917 if (stream
->tmp_buffer
)
918 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
919 &stream
->tmp_buffer_bytes
, MEM_RELEASE
);
920 if (stream
->local_buffer
)
921 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
922 &stream
->alloc_size
, MEM_RELEASE
);
923 free(stream
->peek_buffer
);
927 static int write_buffer(const struct pulse_stream
*stream
, BYTE
*buffer
, UINT32 bytes
)
929 const float *vol
= stream
->vol
;
930 UINT32 i
, channels
, mute
= 0;
934 if (!bytes
) return 0;
936 /* Adjust the buffer based on the volume for each channel */
937 channels
= stream
->ss
.channels
;
938 for (i
= 0; i
< channels
; i
++)
940 adjust
|= vol
[i
] != 1.0f
;
944 if (mute
== channels
)
946 silence_buffer(stream
->ss
.format
, buffer
, bytes
);
949 if (!adjust
) goto write
;
951 end
= buffer
+ bytes
;
952 switch (stream
->ss
.format
)
954 #ifndef WORDS_BIGENDIAN
955 #define PROCESS_BUFFER(type) do \
957 type *p = (type*)buffer; \
960 for (i = 0; i < channels; i++) \
961 p[i] = p[i] * vol[i]; \
963 } while ((BYTE*)p != end); \
965 case PA_SAMPLE_S16LE
:
966 PROCESS_BUFFER(INT16
);
968 case PA_SAMPLE_S32LE
:
969 PROCESS_BUFFER(INT32
);
971 case PA_SAMPLE_FLOAT32LE
:
972 PROCESS_BUFFER(float);
974 #undef PROCESS_BUFFER
975 case PA_SAMPLE_S24_32LE
:
977 UINT32
*p
= (UINT32
*)buffer
;
980 for (i
= 0; i
< channels
; i
++)
982 p
[i
] = (INT32
)((INT32
)(p
[i
] << 8) * vol
[i
]);
986 } while ((BYTE
*)p
!= end
);
989 case PA_SAMPLE_S24LE
:
991 /* do it 12 bytes at a time until it is no longer possible */
992 UINT32
*q
= (UINT32
*)buffer
;
996 while (end
- (BYTE
*)q
>= 12)
1000 v
[1] = q
[1] << 16 | (q
[0] >> 16 & ~0xff);
1001 v
[2] = q
[2] << 24 | (q
[1] >> 8 & ~0xff);
1002 v
[3] = q
[2] & ~0xff;
1003 for (k
= 0; k
< 4; k
++)
1005 v
[k
] = (INT32
)((INT32
)v
[k
] * vol
[i
]);
1006 if (++i
== channels
) i
= 0;
1008 *q
++ = v
[0] >> 8 | (v
[1] & ~0xff) << 16;
1009 *q
++ = v
[1] >> 16 | (v
[2] & ~0xff) << 8;
1010 *q
++ = v
[2] >> 24 | (v
[3] & ~0xff);
1015 UINT32 v
= (INT32
)((INT32
)(p
[0] << 8 | p
[1] << 16 | p
[2] << 24) * vol
[i
]);
1016 *p
++ = v
>> 8 & 0xff;
1017 *p
++ = v
>> 16 & 0xff;
1019 if (++i
== channels
) i
= 0;
1026 UINT8
*p
= (UINT8
*)buffer
;
1029 for (i
= 0; i
< channels
; i
++)
1030 p
[i
] = (int)((p
[i
] - 128) * vol
[i
]) + 128;
1032 } while ((BYTE
*)p
!= end
);
1035 case PA_SAMPLE_ALAW
:
1037 UINT8
*p
= (UINT8
*)buffer
;
1040 for (i
= 0; i
< channels
; i
++)
1041 p
[i
] = mult_alaw_sample(p
[i
], vol
[i
]);
1043 } while ((BYTE
*)p
!= end
);
1046 case PA_SAMPLE_ULAW
:
1048 UINT8
*p
= (UINT8
*)buffer
;
1051 for (i
= 0; i
< channels
; i
++)
1052 p
[i
] = mult_ulaw_sample(p
[i
], vol
[i
]);
1054 } while ((BYTE
*)p
!= end
);
1058 TRACE("Unhandled format %i, not adjusting volume.\n", stream
->ss
.format
);
1063 return pa_stream_write(stream
->stream
, buffer
, bytes
, NULL
, 0, PA_SEEK_RELATIVE
);
1066 static void pulse_write(struct pulse_stream
*stream
)
1068 /* write as much data to PA as we can */
1070 BYTE
*buf
= stream
->local_buffer
+ stream
->pa_offs_bytes
;
1071 UINT32 bytes
= pa_stream_writable_size(stream
->stream
);
1073 if (stream
->just_underran
)
1075 /* prebuffer with silence if needed */
1076 if(stream
->pa_held_bytes
< bytes
){
1077 to_write
= bytes
- stream
->pa_held_bytes
;
1078 TRACE("prebuffering %u frames of silence\n",
1079 (int)(to_write
/ pa_frame_size(&stream
->ss
)));
1080 buf
= calloc(1, to_write
);
1081 pa_stream_write(stream
->stream
, buf
, to_write
, NULL
, 0, PA_SEEK_RELATIVE
);
1085 stream
->just_underran
= FALSE
;
1088 buf
= stream
->local_buffer
+ stream
->pa_offs_bytes
;
1089 TRACE("held: %lu, avail: %u\n", stream
->pa_held_bytes
, bytes
);
1090 bytes
= min(stream
->pa_held_bytes
, bytes
);
1092 if (stream
->pa_offs_bytes
+ bytes
> stream
->real_bufsize_bytes
)
1094 to_write
= stream
->real_bufsize_bytes
- stream
->pa_offs_bytes
;
1095 TRACE("writing small chunk of %u bytes\n", to_write
);
1096 write_buffer(stream
, buf
, to_write
);
1097 stream
->pa_held_bytes
-= to_write
;
1098 to_write
= bytes
- to_write
;
1099 stream
->pa_offs_bytes
= 0;
1100 buf
= stream
->local_buffer
;
1105 TRACE("writing main chunk of %u bytes\n", to_write
);
1106 write_buffer(stream
, buf
, to_write
);
1107 stream
->pa_offs_bytes
+= to_write
;
1108 stream
->pa_offs_bytes
%= stream
->real_bufsize_bytes
;
1109 stream
->pa_held_bytes
-= to_write
;
1112 static void pulse_read(struct pulse_stream
*stream
)
1114 size_t bytes
= pa_stream_readable_size(stream
->stream
);
1116 TRACE("Readable total: %zu, fragsize: %u\n", bytes
, pa_stream_get_buffer_attr(stream
->stream
)->fragsize
);
1118 bytes
+= stream
->peek_len
- stream
->peek_ofs
;
1120 while (bytes
>= stream
->period_bytes
)
1122 BYTE
*dst
= NULL
, *src
;
1123 size_t src_len
, copy
, rem
= stream
->period_bytes
;
1125 if (stream
->started
)
1127 LARGE_INTEGER stamp
, freq
;
1130 if (!(p
= (ACPacket
*)list_head(&stream
->packet_free_head
)))
1132 p
= (ACPacket
*)list_head(&stream
->packet_filled_head
);
1135 next
= (ACPacket
*)p
->entry
.next
;
1138 p
= (ACPacket
*)list_tail(&stream
->packet_filled_head
);
1142 stream
->held_bytes
+= stream
->period_bytes
;
1144 NtQueryPerformanceCounter(&stamp
, &freq
);
1145 p
->qpcpos
= (stamp
.QuadPart
* (INT64
)10000000) / freq
.QuadPart
;
1147 list_remove(&p
->entry
);
1148 list_add_tail(&stream
->packet_filled_head
, &p
->entry
);
1155 if (stream
->peek_len
)
1157 copy
= min(rem
, stream
->peek_len
- stream
->peek_ofs
);
1161 memcpy(dst
, stream
->peek_buffer
+ stream
->peek_ofs
, copy
);
1166 stream
->peek_ofs
+= copy
;
1167 if(stream
->peek_len
== stream
->peek_ofs
)
1168 stream
->peek_len
= stream
->peek_ofs
= 0;
1171 else if (pa_stream_peek(stream
->stream
, (const void**)&src
, &src_len
) == 0 && src_len
)
1173 copy
= min(rem
, src_len
);
1177 memcpy(dst
, src
, copy
);
1179 silence_buffer(stream
->ss
.format
, dst
, copy
);
1188 if (src_len
> stream
->peek_buffer_len
)
1190 free(stream
->peek_buffer
);
1191 stream
->peek_buffer
= malloc(src_len
);
1192 stream
->peek_buffer_len
= src_len
;
1196 memcpy(stream
->peek_buffer
, src
+ copy
, src_len
- copy
);
1198 silence_buffer(stream
->ss
.format
, stream
->peek_buffer
, src_len
- copy
);
1200 stream
->peek_len
= src_len
- copy
;
1201 stream
->peek_ofs
= 0;
1204 pa_stream_drop(stream
->stream
);
1208 bytes
-= stream
->period_bytes
;
1212 static void WINAPI
pulse_timer_loop(struct timer_loop_params
*params
)
1214 struct pulse_stream
*stream
= params
->stream
;
1215 LARGE_INTEGER delay
;
1221 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1222 pa_stream_get_time(stream
->stream
, &stream
->last_time
);
1225 while (!stream
->please_quit
)
1227 pa_usec_t now
, adv_usec
= 0;
1230 NtDelayExecution(FALSE
, &delay
);
1234 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1236 o
= pa_stream_update_timing_info(stream
->stream
, pulse_op_cb
, &success
);
1239 while (pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1241 pa_operation_unref(o
);
1243 err
= pa_stream_get_time(stream
->stream
, &now
);
1246 TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now
), wine_dbgstr_longlong(stream
->last_time
));
1247 if (stream
->started
&& (stream
->dataflow
== eCapture
|| stream
->held_bytes
))
1249 if(stream
->just_underran
)
1251 stream
->last_time
= now
;
1252 stream
->just_started
= TRUE
;
1255 if (stream
->just_started
)
1257 /* let it play out a period to absorb some latency and get accurate timing */
1258 pa_usec_t diff
= now
- stream
->last_time
;
1260 if (diff
> stream
->mmdev_period_usec
)
1262 stream
->just_started
= FALSE
;
1263 stream
->last_time
= now
;
1268 INT32 adjust
= stream
->last_time
+ stream
->mmdev_period_usec
- now
;
1270 adv_usec
= now
- stream
->last_time
;
1272 if(adjust
> ((INT32
)(stream
->mmdev_period_usec
/ 2)))
1273 adjust
= stream
->mmdev_period_usec
/ 2;
1274 else if(adjust
< -((INT32
)(stream
->mmdev_period_usec
/ 2)))
1275 adjust
= -1 * stream
->mmdev_period_usec
/ 2;
1277 delay
.QuadPart
= -(stream
->mmdev_period_usec
+ adjust
) * 10;
1279 stream
->last_time
+= stream
->mmdev_period_usec
;
1282 if (stream
->dataflow
== eRender
)
1284 pulse_write(stream
);
1286 /* regardless of what PA does, advance one period */
1287 adv_bytes
= min(stream
->period_bytes
, stream
->held_bytes
);
1288 stream
->lcl_offs_bytes
+= adv_bytes
;
1289 stream
->lcl_offs_bytes
%= stream
->real_bufsize_bytes
;
1290 stream
->held_bytes
-= adv_bytes
;
1292 else if(stream
->dataflow
== eCapture
)
1299 stream
->last_time
= now
;
1300 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1305 NtSetEvent(stream
->event
, NULL
);
1307 TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n",
1308 stream
, (int)adv_usec
,
1309 (int)(stream
->held_bytes
/ pa_frame_size(&stream
->ss
)),
1310 (unsigned int)(-delay
.QuadPart
/ 10));
1316 static void WINAPI
pulse_start(struct start_params
*params
)
1318 struct pulse_stream
*stream
= params
->stream
;
1322 params
->result
= S_OK
;
1324 if (!pulse_stream_valid(stream
))
1327 params
->result
= S_OK
;
1331 if ((stream
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
) && !stream
->event
)
1334 params
->result
= AUDCLNT_E_EVENTHANDLE_NOT_SET
;
1338 if (stream
->started
)
1341 params
->result
= AUDCLNT_E_NOT_STOPPED
;
1345 pulse_write(stream
);
1347 if (pa_stream_is_corked(stream
->stream
))
1349 o
= pa_stream_cork(stream
->stream
, 0, pulse_op_cb
, &success
);
1352 while(pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1354 pa_operation_unref(o
);
1359 params
->result
= E_FAIL
;
1362 if (SUCCEEDED(params
->result
))
1364 stream
->started
= TRUE
;
1365 stream
->just_started
= TRUE
;
1370 static void WINAPI
pulse_stop(struct stop_params
*params
)
1372 struct pulse_stream
*stream
= params
->stream
;
1377 if (!pulse_stream_valid(stream
))
1380 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1384 if (!stream
->started
)
1387 params
->result
= S_FALSE
;
1391 params
->result
= S_OK
;
1392 if (stream
->dataflow
== eRender
)
1394 o
= pa_stream_cork(stream
->stream
, 1, pulse_op_cb
, &success
);
1397 while(pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1399 pa_operation_unref(o
);
1404 params
->result
= E_FAIL
;
1406 if (SUCCEEDED(params
->result
))
1407 stream
->started
= FALSE
;
1411 static void WINAPI
pulse_reset(struct reset_params
*params
)
1413 struct pulse_stream
*stream
= params
->stream
;
1416 if (!pulse_stream_valid(stream
))
1419 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1423 if (stream
->started
)
1426 params
->result
= AUDCLNT_E_NOT_STOPPED
;
1433 params
->result
= AUDCLNT_E_BUFFER_OPERATION_PENDING
;
1437 if (stream
->dataflow
== eRender
)
1439 /* If there is still data in the render buffer it needs to be removed from the server */
1441 if (stream
->held_bytes
)
1443 pa_operation
*o
= pa_stream_flush(stream
->stream
, pulse_op_cb
, &success
);
1446 while (pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1448 pa_operation_unref(o
);
1451 if (success
|| !stream
->held_bytes
)
1453 stream
->clock_lastpos
= stream
->clock_written
= 0;
1454 stream
->pa_offs_bytes
= stream
->lcl_offs_bytes
= 0;
1455 stream
->held_bytes
= stream
->pa_held_bytes
= 0;
1461 stream
->clock_written
+= stream
->held_bytes
;
1462 stream
->held_bytes
= 0;
1464 if ((p
= stream
->locked_ptr
))
1466 stream
->locked_ptr
= NULL
;
1467 list_add_tail(&stream
->packet_free_head
, &p
->entry
);
1469 list_move_tail(&stream
->packet_free_head
, &stream
->packet_filled_head
);
1472 params
->result
= S_OK
;
1475 static BOOL
alloc_tmp_buffer(struct pulse_stream
*stream
, SIZE_T bytes
)
1477 if (stream
->tmp_buffer_bytes
>= bytes
)
1480 if (stream
->tmp_buffer
)
1482 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
1483 &stream
->tmp_buffer_bytes
, MEM_RELEASE
);
1484 stream
->tmp_buffer
= NULL
;
1485 stream
->tmp_buffer_bytes
= 0;
1487 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
1488 0, &bytes
, MEM_COMMIT
, PAGE_READWRITE
))
1491 stream
->tmp_buffer_bytes
= bytes
;
1495 static UINT32
pulse_render_padding(struct pulse_stream
*stream
)
1497 return stream
->held_bytes
/ pa_frame_size(&stream
->ss
);
1500 static UINT32
pulse_capture_padding(struct pulse_stream
*stream
)
1502 ACPacket
*packet
= stream
->locked_ptr
;
1503 if (!packet
&& !list_empty(&stream
->packet_filled_head
))
1505 packet
= (ACPacket
*)list_head(&stream
->packet_filled_head
);
1506 stream
->locked_ptr
= packet
;
1507 list_remove(&packet
->entry
);
1509 return stream
->held_bytes
/ pa_frame_size(&stream
->ss
);
1512 static void WINAPI
pulse_get_render_buffer(struct get_render_buffer_params
*params
)
1514 struct pulse_stream
*stream
= params
->stream
;
1516 UINT32 wri_offs_bytes
;
1519 if (!pulse_stream_valid(stream
))
1522 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1529 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1533 if (!params
->frames
)
1536 *params
->data
= NULL
;
1537 params
->result
= S_OK
;
1541 if (stream
->held_bytes
/ pa_frame_size(&stream
->ss
) + params
->frames
> stream
->bufsize_frames
)
1544 params
->result
= AUDCLNT_E_BUFFER_TOO_LARGE
;
1548 bytes
= params
->frames
* pa_frame_size(&stream
->ss
);
1549 wri_offs_bytes
= (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1550 if (wri_offs_bytes
+ bytes
> stream
->real_bufsize_bytes
)
1552 if (!alloc_tmp_buffer(stream
, bytes
))
1555 params
->result
= E_OUTOFMEMORY
;
1558 *params
->data
= stream
->tmp_buffer
;
1559 stream
->locked
= -bytes
;
1563 *params
->data
= stream
->local_buffer
+ wri_offs_bytes
;
1564 stream
->locked
= bytes
;
1567 silence_buffer(stream
->ss
.format
, *params
->data
, bytes
);
1570 params
->result
= S_OK
;
1573 static void pulse_wrap_buffer(struct pulse_stream
*stream
, BYTE
*buffer
, UINT32 written_bytes
)
1575 UINT32 wri_offs_bytes
= (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1576 UINT32 chunk_bytes
= stream
->real_bufsize_bytes
- wri_offs_bytes
;
1578 if (written_bytes
<= chunk_bytes
)
1580 memcpy(stream
->local_buffer
+ wri_offs_bytes
, buffer
, written_bytes
);
1584 memcpy(stream
->local_buffer
+ wri_offs_bytes
, buffer
, chunk_bytes
);
1585 memcpy(stream
->local_buffer
, buffer
+ chunk_bytes
, written_bytes
- chunk_bytes
);
1589 static void WINAPI
pulse_release_render_buffer(struct release_render_buffer_params
*params
)
1591 struct pulse_stream
*stream
= params
->stream
;
1592 UINT32 written_bytes
;
1596 if (!stream
->locked
|| !params
->written_frames
)
1600 params
->result
= params
->written_frames
? AUDCLNT_E_OUT_OF_ORDER
: S_OK
;
1604 if (params
->written_frames
* pa_frame_size(&stream
->ss
) >
1605 (stream
->locked
>= 0 ? stream
->locked
: -stream
->locked
))
1608 params
->result
= AUDCLNT_E_INVALID_SIZE
;
1612 if (stream
->locked
>= 0)
1613 buffer
= stream
->local_buffer
+ (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1615 buffer
= stream
->tmp_buffer
;
1617 written_bytes
= params
->written_frames
* pa_frame_size(&stream
->ss
);
1618 if (params
->flags
& AUDCLNT_BUFFERFLAGS_SILENT
)
1619 silence_buffer(stream
->ss
.format
, buffer
, written_bytes
);
1621 if (stream
->locked
< 0)
1622 pulse_wrap_buffer(stream
, buffer
, written_bytes
);
1624 stream
->held_bytes
+= written_bytes
;
1625 stream
->pa_held_bytes
+= written_bytes
;
1626 if (stream
->pa_held_bytes
> stream
->real_bufsize_bytes
)
1628 stream
->pa_offs_bytes
+= stream
->pa_held_bytes
- stream
->real_bufsize_bytes
;
1629 stream
->pa_offs_bytes
%= stream
->real_bufsize_bytes
;
1630 stream
->pa_held_bytes
= stream
->real_bufsize_bytes
;
1632 stream
->clock_written
+= written_bytes
;
1635 TRACE("Released %u, held %lu\n", params
->written_frames
, stream
->held_bytes
/ pa_frame_size(&stream
->ss
));
1638 params
->result
= S_OK
;
1641 static void WINAPI
pulse_get_capture_buffer(struct get_capture_buffer_params
*params
)
1643 struct pulse_stream
*stream
= params
->stream
;
1647 if (!pulse_stream_valid(stream
))
1650 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1656 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1660 pulse_capture_padding(stream
);
1661 if ((packet
= stream
->locked_ptr
))
1663 *params
->frames
= stream
->period_bytes
/ pa_frame_size(&stream
->ss
);
1665 if (packet
->discont
)
1666 *params
->flags
|= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
;
1669 if (packet
->discont
)
1670 *params
->devpos
= (stream
->clock_written
+ stream
->period_bytes
) / pa_frame_size(&stream
->ss
);
1672 *params
->devpos
= stream
->clock_written
/ pa_frame_size(&stream
->ss
);
1675 *params
->qpcpos
= packet
->qpcpos
;
1676 *params
->data
= packet
->data
;
1679 *params
->frames
= 0;
1680 stream
->locked
= *params
->frames
;
1682 params
->result
= *params
->frames
? S_OK
: AUDCLNT_S_BUFFER_EMPTY
;
1685 static void WINAPI
pulse_release_capture_buffer(struct release_capture_buffer_params
*params
)
1687 struct pulse_stream
*stream
= params
->stream
;
1690 if (!stream
->locked
&& params
->done
)
1693 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1696 if (params
->done
&& stream
->locked
!= params
->done
)
1699 params
->result
= AUDCLNT_E_INVALID_SIZE
;
1704 ACPacket
*packet
= stream
->locked_ptr
;
1705 stream
->locked_ptr
= NULL
;
1706 stream
->held_bytes
-= stream
->period_bytes
;
1707 if (packet
->discont
)
1708 stream
->clock_written
+= 2 * stream
->period_bytes
;
1710 stream
->clock_written
+= stream
->period_bytes
;
1711 list_add_tail(&stream
->packet_free_head
, &packet
->entry
);
1715 params
->result
= S_OK
;
1718 static void WINAPI
pulse_get_buffer_size(struct get_buffer_size_params
*params
)
1720 params
->result
= S_OK
;
1723 if (!pulse_stream_valid(params
->stream
))
1724 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1726 *params
->size
= params
->stream
->bufsize_frames
;
1730 static void WINAPI
pulse_get_latency(struct get_latency_params
*params
)
1732 struct pulse_stream
*stream
= params
->stream
;
1733 const pa_buffer_attr
*attr
;
1737 if (!pulse_stream_valid(stream
)) {
1739 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1742 attr
= pa_stream_get_buffer_attr(stream
->stream
);
1743 if (stream
->dataflow
== eRender
)
1744 lat
= attr
->minreq
/ pa_frame_size(&stream
->ss
);
1746 lat
= attr
->fragsize
/ pa_frame_size(&stream
->ss
);
1747 *params
->latency
= (lat
* 10000000) / stream
->ss
.rate
+ pulse_def_period
[0];
1749 TRACE("Latency: %u ms\n", (DWORD
)(*params
->latency
/ 10000));
1750 params
->result
= S_OK
;
1753 static void WINAPI
pulse_get_current_padding(struct get_current_padding_params
*params
)
1755 struct pulse_stream
*stream
= params
->stream
;
1758 if (!pulse_stream_valid(stream
))
1761 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1765 if (stream
->dataflow
== eRender
)
1766 *params
->padding
= pulse_render_padding(stream
);
1768 *params
->padding
= pulse_capture_padding(stream
);
1771 TRACE("%p Pad: %u ms (%u)\n", stream
, muldiv(*params
->padding
, 1000, stream
->ss
.rate
),
1773 params
->result
= S_OK
;
1776 static void WINAPI
pulse_get_next_packet_size(struct get_next_packet_size_params
*params
)
1778 struct pulse_stream
*stream
= params
->stream
;
1781 pulse_capture_padding(stream
);
1782 if (stream
->locked_ptr
)
1783 *params
->frames
= stream
->period_bytes
/ pa_frame_size(&stream
->ss
);
1785 *params
->frames
= 0;
1787 params
->result
= S_OK
;
1790 static void WINAPI
pulse_get_frequency(struct get_frequency_params
*params
)
1792 struct pulse_stream
*stream
= params
->stream
;
1795 if (!pulse_stream_valid(stream
))
1798 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1802 *params
->freq
= stream
->ss
.rate
;
1803 if (stream
->share
== AUDCLNT_SHAREMODE_SHARED
)
1804 *params
->freq
*= pa_frame_size(&stream
->ss
);
1806 params
->result
= S_OK
;
1809 static void WINAPI
pulse_get_position(struct get_position_params
*params
)
1811 struct pulse_stream
*stream
= params
->stream
;
1814 if (!pulse_stream_valid(stream
))
1817 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1821 *params
->pos
= stream
->clock_written
- stream
->held_bytes
;
1823 if (stream
->share
== AUDCLNT_SHAREMODE_EXCLUSIVE
|| params
->device
)
1824 *params
->pos
/= pa_frame_size(&stream
->ss
);
1826 /* Make time never go backwards */
1827 if (*params
->pos
< stream
->clock_lastpos
)
1828 *params
->pos
= stream
->clock_lastpos
;
1830 stream
->clock_lastpos
= *params
->pos
;
1833 TRACE("%p Position: %u\n", stream
, (unsigned)*params
->pos
);
1835 if (params
->qpctime
)
1837 LARGE_INTEGER stamp
, freq
;
1838 NtQueryPerformanceCounter(&stamp
, &freq
);
1839 *params
->qpctime
= (stamp
.QuadPart
* (INT64
)10000000) / freq
.QuadPart
;
1842 params
->result
= S_OK
;
1845 static void WINAPI
pulse_set_volumes(struct set_volumes_params
*params
)
1847 struct pulse_stream
*stream
= params
->stream
;
1850 for (i
= 0; i
< stream
->ss
.channels
; i
++)
1851 stream
->vol
[i
] = params
->volumes
[i
] * params
->master_volume
* params
->session_volumes
[i
];
1854 static void WINAPI
pulse_set_event_handle(struct set_event_handle_params
*params
)
1856 struct pulse_stream
*stream
= params
->stream
;
1860 if (!pulse_stream_valid(stream
))
1861 hr
= AUDCLNT_E_DEVICE_INVALIDATED
;
1862 else if (!(stream
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
))
1863 hr
= AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED
;
1864 else if (stream
->event
)
1865 hr
= HRESULT_FROM_WIN32(ERROR_INVALID_NAME
);
1867 stream
->event
= params
->event
;
1870 params
->result
= hr
;
1873 static void WINAPI
pulse_is_started(struct is_started_params
*params
)
1875 struct pulse_stream
*stream
= params
->stream
;
1878 params
->started
= pulse_stream_valid(stream
) && stream
->started
;
1882 static const struct unix_funcs unix_funcs
=
1885 pulse_create_stream
,
1886 pulse_release_stream
,
1891 pulse_get_render_buffer
,
1892 pulse_release_render_buffer
,
1893 pulse_get_capture_buffer
,
1894 pulse_release_capture_buffer
,
1895 pulse_get_buffer_size
,
1897 pulse_get_current_padding
,
1898 pulse_get_next_packet_size
,
1899 pulse_get_frequency
,
1902 pulse_set_event_handle
,
1907 NTSTATUS CDECL
__wine_init_unix_lib(HMODULE module
, DWORD reason
, const void *ptr_in
, void *ptr_out
)
1909 pthread_mutexattr_t attr
;
1913 case DLL_PROCESS_ATTACH
:
1914 pthread_mutexattr_init(&attr
);
1915 pthread_mutexattr_setprotocol(&attr
, PTHREAD_PRIO_INHERIT
);
1917 if (pthread_mutex_init(&pulse_mutex
, &attr
) != 0)
1918 pthread_mutex_init(&pulse_mutex
, NULL
);
1920 *(const struct unix_funcs
**)ptr_out
= &unix_funcs
;
1922 case DLL_PROCESS_DETACH
:
1925 pa_context_disconnect(pulse_ctx
);
1926 pa_context_unref(pulse_ctx
);
1929 pa_mainloop_quit(pulse_ml
, 0);
1933 return STATUS_SUCCESS
;