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
32 #include <pulse/pulseaudio.h>
35 #define WIN32_NO_STATUS
38 #include "mmdeviceapi.h"
40 #include "audioclient.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(pulse
);
58 AUDCLNT_SHAREMODE share
;
60 float vol
[PA_CHANNELS_MAX
];
65 SIZE_T bufsize_frames
, alloc_size
, real_bufsize_bytes
, period_bytes
;
66 SIZE_T peek_ofs
, read_offs_bytes
, lcl_offs_bytes
, pa_offs_bytes
;
67 SIZE_T tmp_buffer_bytes
, held_bytes
, peek_len
, peek_buffer_len
, pa_held_bytes
;
68 BYTE
*local_buffer
, *tmp_buffer
, *peek_buffer
;
70 BOOL please_quit
, just_started
, just_underran
;
71 pa_usec_t last_time
, mmdev_period_usec
;
73 INT64 clock_lastpos
, clock_written
;
75 struct list packet_free_head
;
76 struct list packet_filled_head
;
79 typedef struct _ACPacket
87 static pa_context
*pulse_ctx
;
88 static pa_mainloop
*pulse_ml
;
90 /* Mixer format + period times */
91 static WAVEFORMATEXTENSIBLE pulse_fmt
[2];
92 static REFERENCE_TIME pulse_min_period
[2], pulse_def_period
[2];
94 static UINT g_phys_speakers_mask
= 0;
96 static const REFERENCE_TIME MinimumPeriod
= 30000;
97 static const REFERENCE_TIME DefaultPeriod
= 100000;
99 static pthread_mutex_t pulse_mutex
;
100 static pthread_cond_t pulse_cond
= PTHREAD_COND_INITIALIZER
;
102 UINT8
mult_alaw_sample(UINT8
, float);
103 UINT8
mult_ulaw_sample(UINT8
, float);
105 static void pulse_lock(void)
107 pthread_mutex_lock(&pulse_mutex
);
110 static void pulse_unlock(void)
112 pthread_mutex_unlock(&pulse_mutex
);
115 static int pulse_cond_wait(void)
117 return pthread_cond_wait(&pulse_cond
, &pulse_mutex
);
120 static void pulse_broadcast(void)
122 pthread_cond_broadcast(&pulse_cond
);
125 static void dump_attr(const pa_buffer_attr
*attr
)
127 TRACE("maxlength: %u\n", attr
->maxlength
);
128 TRACE("minreq: %u\n", attr
->minreq
);
129 TRACE("fragsize: %u\n", attr
->fragsize
);
130 TRACE("tlength: %u\n", attr
->tlength
);
131 TRACE("prebuf: %u\n", attr
->prebuf
);
134 /* copied from kernelbase */
135 static int muldiv(int a
, int b
, int c
)
141 /* We want to deal with a positive divisor to simplify the logic. */
148 /* If the result is positive, we "add" to round. else, we subtract to round. */
149 if ((a
< 0 && b
< 0) || (a
>= 0 && b
>= 0))
150 ret
= (((LONGLONG
)a
* b
) + (c
/ 2)) / c
;
152 ret
= (((LONGLONG
)a
* b
) - (c
/ 2)) / c
;
154 if (ret
> 2147483647 || ret
< -2147483647) return -1;
158 /* Following pulseaudio design here, mainloop has the lock taken whenever
159 * it is handling something for pulse, and the lock is required whenever
160 * doing any pa_* call that can affect the state in any way
162 * pa_cond_wait is used when waiting on results, because the mainloop needs
163 * the same lock taken to affect the state
165 * This is basically the same as the pa_threaded_mainloop implementation,
166 * but that cannot be used because it uses pthread_create directly
168 * pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock
169 * pa_threaded_mainloop_signal -> pthread_cond_broadcast
170 * pa_threaded_mainloop_wait -> pthread_cond_wait
172 static int pulse_poll_func(struct pollfd
*ufds
, unsigned long nfds
, int timeout
, void *userdata
)
176 r
= poll(ufds
, nfds
, timeout
);
181 static NTSTATUS
pulse_process_attach(void *args
)
183 pthread_mutexattr_t attr
;
185 pthread_mutexattr_init(&attr
);
186 pthread_mutexattr_setprotocol(&attr
, PTHREAD_PRIO_INHERIT
);
188 if (pthread_mutex_init(&pulse_mutex
, &attr
) != 0)
189 pthread_mutex_init(&pulse_mutex
, NULL
);
191 return STATUS_SUCCESS
;
194 static NTSTATUS
pulse_process_detach(void *args
)
198 pa_context_disconnect(pulse_ctx
);
199 pa_context_unref(pulse_ctx
);
202 pa_mainloop_quit(pulse_ml
, 0);
204 return STATUS_SUCCESS
;
207 static NTSTATUS
pulse_main_loop(void *args
)
209 struct main_loop_params
*params
= args
;
212 pulse_ml
= pa_mainloop_new();
213 pa_mainloop_set_poll_func(pulse_ml
, pulse_poll_func
, NULL
);
214 NtSetEvent(params
->event
, NULL
);
215 pa_mainloop_run(pulse_ml
, &ret
);
216 pa_mainloop_free(pulse_ml
);
218 return STATUS_SUCCESS
;
221 static void pulse_contextcallback(pa_context
*c
, void *userdata
)
223 switch (pa_context_get_state(c
)) {
225 FIXME("Unhandled state: %i\n", pa_context_get_state(c
));
228 case PA_CONTEXT_CONNECTING
:
229 case PA_CONTEXT_UNCONNECTED
:
230 case PA_CONTEXT_AUTHORIZING
:
231 case PA_CONTEXT_SETTING_NAME
:
232 case PA_CONTEXT_TERMINATED
:
233 TRACE("State change to %i\n", pa_context_get_state(c
));
236 case PA_CONTEXT_READY
:
240 case PA_CONTEXT_FAILED
:
241 WARN("Context failed: %s\n", pa_strerror(pa_context_errno(c
)));
247 static void pulse_stream_state(pa_stream
*s
, void *user
)
249 pa_stream_state_t state
= pa_stream_get_state(s
);
250 TRACE("Stream state changed to %i\n", state
);
254 static void pulse_attr_update(pa_stream
*s
, void *user
) {
255 const pa_buffer_attr
*attr
= pa_stream_get_buffer_attr(s
);
256 TRACE("New attributes or device moved:\n");
260 static void pulse_underflow_callback(pa_stream
*s
, void *userdata
)
262 struct pulse_stream
*stream
= userdata
;
263 WARN("%p: Underflow\n", userdata
);
264 stream
->just_underran
= TRUE
;
266 stream
->pa_offs_bytes
= stream
->lcl_offs_bytes
;
267 stream
->pa_held_bytes
= stream
->held_bytes
;
270 static void pulse_started_callback(pa_stream
*s
, void *userdata
)
272 TRACE("%p: (Re)started playing\n", userdata
);
275 static void pulse_op_cb(pa_stream
*s
, int success
, void *user
)
277 TRACE("Success: %i\n", success
);
278 *(int*)user
= success
;
282 static void silence_buffer(pa_sample_format_t format
, BYTE
*buffer
, UINT32 bytes
)
284 memset(buffer
, format
== PA_SAMPLE_U8
? 0x80 : 0, bytes
);
287 static BOOL
pulse_stream_valid(struct pulse_stream
*stream
)
289 return pa_stream_get_state(stream
->stream
) == PA_STREAM_READY
;
292 static HRESULT
pulse_connect(const char *name
)
294 if (pulse_ctx
&& PA_CONTEXT_IS_GOOD(pa_context_get_state(pulse_ctx
)))
297 pa_context_unref(pulse_ctx
);
299 pulse_ctx
= pa_context_new(pa_mainloop_get_api(pulse_ml
), name
);
301 ERR("Failed to create context\n");
305 pa_context_set_state_callback(pulse_ctx
, pulse_contextcallback
, NULL
);
307 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx
), PA_API_VERSION
);
308 if (pa_context_connect(pulse_ctx
, NULL
, 0, NULL
) < 0)
311 /* Wait for connection */
312 while (pulse_cond_wait()) {
313 pa_context_state_t state
= pa_context_get_state(pulse_ctx
);
315 if (state
== PA_CONTEXT_FAILED
|| state
== PA_CONTEXT_TERMINATED
)
318 if (state
== PA_CONTEXT_READY
)
322 TRACE("Connected to server %s with protocol version: %i.\n",
323 pa_context_get_server(pulse_ctx
),
324 pa_context_get_server_protocol_version(pulse_ctx
));
328 pa_context_unref(pulse_ctx
);
333 static DWORD
pulse_channel_map_to_channel_mask(const pa_channel_map
*map
)
338 for (i
= 0; i
< map
->channels
; ++i
) {
339 switch (map
->map
[i
]) {
340 default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map
->map
[i
])); break;
341 case PA_CHANNEL_POSITION_FRONT_LEFT
: mask
|= SPEAKER_FRONT_LEFT
; break;
342 case PA_CHANNEL_POSITION_MONO
:
343 case PA_CHANNEL_POSITION_FRONT_CENTER
: mask
|= SPEAKER_FRONT_CENTER
; break;
344 case PA_CHANNEL_POSITION_FRONT_RIGHT
: mask
|= SPEAKER_FRONT_RIGHT
; break;
345 case PA_CHANNEL_POSITION_REAR_LEFT
: mask
|= SPEAKER_BACK_LEFT
; break;
346 case PA_CHANNEL_POSITION_REAR_CENTER
: mask
|= SPEAKER_BACK_CENTER
; break;
347 case PA_CHANNEL_POSITION_REAR_RIGHT
: mask
|= SPEAKER_BACK_RIGHT
; break;
348 case PA_CHANNEL_POSITION_LFE
: mask
|= SPEAKER_LOW_FREQUENCY
; break;
349 case PA_CHANNEL_POSITION_SIDE_LEFT
: mask
|= SPEAKER_SIDE_LEFT
; break;
350 case PA_CHANNEL_POSITION_SIDE_RIGHT
: mask
|= SPEAKER_SIDE_RIGHT
; break;
351 case PA_CHANNEL_POSITION_TOP_CENTER
: mask
|= SPEAKER_TOP_CENTER
; break;
352 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT
: mask
|= SPEAKER_TOP_FRONT_LEFT
; break;
353 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER
: mask
|= SPEAKER_TOP_FRONT_CENTER
; break;
354 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
: mask
|= SPEAKER_TOP_FRONT_RIGHT
; break;
355 case PA_CHANNEL_POSITION_TOP_REAR_LEFT
: mask
|= SPEAKER_TOP_BACK_LEFT
; break;
356 case PA_CHANNEL_POSITION_TOP_REAR_CENTER
: mask
|= SPEAKER_TOP_BACK_CENTER
; break;
357 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT
: mask
|= SPEAKER_TOP_BACK_RIGHT
; break;
358 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
: mask
|= SPEAKER_FRONT_LEFT_OF_CENTER
; break;
359 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
: mask
|= SPEAKER_FRONT_RIGHT_OF_CENTER
; break;
366 /* For default PulseAudio render device, OR together all of the
367 * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
368 static void pulse_phys_speakers_cb(pa_context
*c
, const pa_sink_info
*i
, int eol
, void *userdata
)
371 g_phys_speakers_mask
|= pulse_channel_map_to_channel_mask(&i
->channel_map
);
374 /* For most hardware on Windows, users must choose a configuration with an even
375 * number of channels (stereo, quad, 5.1, 7.1). Users can then disable
376 * channels, but those channels are still reported to applications from
377 * GetMixFormat! Some applications behave badly if given an odd number of
378 * channels (e.g. 2.1). Here, we find the nearest configuration that Windows
379 * would report for a given channel layout. */
380 static void convert_channel_map(const pa_channel_map
*pa_map
, WAVEFORMATEXTENSIBLE
*fmt
)
382 DWORD pa_mask
= pulse_channel_map_to_channel_mask(pa_map
);
384 TRACE("got mask for PA: 0x%x\n", pa_mask
);
386 if (pa_map
->channels
== 1)
388 fmt
->Format
.nChannels
= 1;
389 fmt
->dwChannelMask
= pa_mask
;
393 /* compare against known configurations and find smallest configuration
394 * which is a superset of the given speakers */
396 if (pa_map
->channels
<= 2 &&
397 (pa_mask
& ~KSAUDIO_SPEAKER_STEREO
) == 0)
399 fmt
->Format
.nChannels
= 2;
400 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_STEREO
;
404 if (pa_map
->channels
<= 4 &&
405 (pa_mask
& ~KSAUDIO_SPEAKER_QUAD
) == 0)
407 fmt
->Format
.nChannels
= 4;
408 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_QUAD
;
412 if (pa_map
->channels
<= 4 &&
413 (pa_mask
& ~KSAUDIO_SPEAKER_SURROUND
) == 0)
415 fmt
->Format
.nChannels
= 4;
416 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_SURROUND
;
420 if (pa_map
->channels
<= 6 &&
421 (pa_mask
& ~KSAUDIO_SPEAKER_5POINT1
) == 0)
423 fmt
->Format
.nChannels
= 6;
424 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_5POINT1
;
428 if (pa_map
->channels
<= 6 &&
429 (pa_mask
& ~KSAUDIO_SPEAKER_5POINT1_SURROUND
) == 0)
431 fmt
->Format
.nChannels
= 6;
432 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_5POINT1_SURROUND
;
436 if (pa_map
->channels
<= 8 &&
437 (pa_mask
& ~KSAUDIO_SPEAKER_7POINT1
) == 0)
439 fmt
->Format
.nChannels
= 8;
440 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_7POINT1
;
444 if (pa_map
->channels
<= 8 &&
445 (pa_mask
& ~KSAUDIO_SPEAKER_7POINT1_SURROUND
) == 0)
447 fmt
->Format
.nChannels
= 8;
448 fmt
->dwChannelMask
= KSAUDIO_SPEAKER_7POINT1_SURROUND
;
452 /* oddball format, report truthfully */
453 fmt
->Format
.nChannels
= pa_map
->channels
;
454 fmt
->dwChannelMask
= pa_mask
;
457 static void pulse_probe_settings(int render
, WAVEFORMATEXTENSIBLE
*fmt
) {
458 WAVEFORMATEX
*wfx
= &fmt
->Format
;
464 unsigned int length
= 0;
466 pa_channel_map_init_auto(&map
, 2, PA_CHANNEL_MAP_ALSA
);
468 ss
.format
= PA_SAMPLE_FLOAT32LE
;
469 ss
.channels
= map
.channels
;
473 attr
.minreq
= attr
.fragsize
= pa_frame_size(&ss
);
476 stream
= pa_stream_new(pulse_ctx
, "format test stream", &ss
, &map
);
478 pa_stream_set_state_callback(stream
, pulse_stream_state
, NULL
);
482 ret
= pa_stream_connect_playback(stream
, NULL
, &attr
,
483 PA_STREAM_START_CORKED
|PA_STREAM_FIX_RATE
|PA_STREAM_FIX_CHANNELS
|PA_STREAM_EARLY_REQUESTS
, NULL
, NULL
);
485 ret
= pa_stream_connect_record(stream
, NULL
, &attr
, PA_STREAM_START_CORKED
|PA_STREAM_FIX_RATE
|PA_STREAM_FIX_CHANNELS
|PA_STREAM_EARLY_REQUESTS
);
487 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
488 pa_stream_get_state(stream
) == PA_STREAM_CREATING
)
490 if (pa_stream_get_state(stream
) == PA_STREAM_READY
) {
491 ss
= *pa_stream_get_sample_spec(stream
);
492 map
= *pa_stream_get_channel_map(stream
);
494 length
= pa_stream_get_buffer_attr(stream
)->minreq
;
496 length
= pa_stream_get_buffer_attr(stream
)->fragsize
;
497 pa_stream_disconnect(stream
);
498 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
499 pa_stream_get_state(stream
) == PA_STREAM_READY
)
505 pa_stream_unref(stream
);
508 pulse_def_period
[!render
] = pulse_min_period
[!render
] = pa_bytes_to_usec(10 * length
, &ss
);
510 if (pulse_min_period
[!render
] < MinimumPeriod
)
511 pulse_min_period
[!render
] = MinimumPeriod
;
513 if (pulse_def_period
[!render
] < DefaultPeriod
)
514 pulse_def_period
[!render
] = DefaultPeriod
;
516 wfx
->wFormatTag
= WAVE_FORMAT_EXTENSIBLE
;
517 wfx
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
519 convert_channel_map(&map
, fmt
);
521 wfx
->wBitsPerSample
= 8 * pa_sample_size_of_format(ss
.format
);
522 wfx
->nSamplesPerSec
= ss
.rate
;
523 wfx
->nBlockAlign
= wfx
->nChannels
* wfx
->wBitsPerSample
/ 8;
524 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
525 if (ss
.format
!= PA_SAMPLE_S24_32LE
)
526 fmt
->Samples
.wValidBitsPerSample
= wfx
->wBitsPerSample
;
528 fmt
->Samples
.wValidBitsPerSample
= 24;
529 if (ss
.format
== PA_SAMPLE_FLOAT32LE
)
530 fmt
->SubFormat
= KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
;
532 fmt
->SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
535 /* some poorly-behaved applications call audio functions during DllMain, so we
536 * have to do as much as possible without creating a new thread. this function
537 * sets up a synchronous connection to verify the server is running and query
539 static NTSTATUS
pulse_test_connect(void *args
)
541 struct test_connect_params
*params
= args
;
542 struct pulse_config
*config
= params
->config
;
547 pulse_ml
= pa_mainloop_new();
549 pa_mainloop_set_poll_func(pulse_ml
, pulse_poll_func
, NULL
);
551 pulse_ctx
= pa_context_new(pa_mainloop_get_api(pulse_ml
), params
->name
);
553 ERR("Failed to create context\n");
554 pa_mainloop_free(pulse_ml
);
557 params
->result
= E_FAIL
;
558 return STATUS_SUCCESS
;
561 pa_context_set_state_callback(pulse_ctx
, pulse_contextcallback
, NULL
);
563 TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx
), PA_API_VERSION
);
564 if (pa_context_connect(pulse_ctx
, NULL
, 0, NULL
) < 0)
567 /* Wait for connection */
568 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0) {
569 pa_context_state_t state
= pa_context_get_state(pulse_ctx
);
571 if (state
== PA_CONTEXT_FAILED
|| state
== PA_CONTEXT_TERMINATED
)
574 if (state
== PA_CONTEXT_READY
)
578 if (pa_context_get_state(pulse_ctx
) != PA_CONTEXT_READY
)
581 TRACE("Test-connected to server %s with protocol version: %i.\n",
582 pa_context_get_server(pulse_ctx
),
583 pa_context_get_server_protocol_version(pulse_ctx
));
585 pulse_probe_settings(1, &pulse_fmt
[0]);
586 pulse_probe_settings(0, &pulse_fmt
[1]);
588 g_phys_speakers_mask
= 0;
589 o
= pa_context_get_sink_info_list(pulse_ctx
, &pulse_phys_speakers_cb
, NULL
);
591 while (pa_mainloop_iterate(pulse_ml
, 1, &ret
) >= 0 &&
592 pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
594 pa_operation_unref(o
);
597 pa_context_unref(pulse_ctx
);
599 pa_mainloop_free(pulse_ml
);
602 config
->speakers_mask
= g_phys_speakers_mask
;
603 config
->modes
[0].format
= pulse_fmt
[0];
604 config
->modes
[0].def_period
= pulse_def_period
[0];
605 config
->modes
[0].min_period
= pulse_min_period
[0];
606 config
->modes
[1].format
= pulse_fmt
[1];
607 config
->modes
[1].def_period
= pulse_def_period
[1];
608 config
->modes
[1].min_period
= pulse_min_period
[1];
612 params
->result
= S_OK
;
613 return STATUS_SUCCESS
;
616 pa_context_unref(pulse_ctx
);
618 pa_mainloop_free(pulse_ml
);
621 params
->result
= E_FAIL
;
622 return STATUS_SUCCESS
;
625 static DWORD
get_channel_mask(unsigned int channels
)
631 return KSAUDIO_SPEAKER_MONO
;
633 return KSAUDIO_SPEAKER_STEREO
;
635 return KSAUDIO_SPEAKER_STEREO
| SPEAKER_LOW_FREQUENCY
;
637 return KSAUDIO_SPEAKER_QUAD
; /* not _SURROUND */
639 return KSAUDIO_SPEAKER_QUAD
| SPEAKER_LOW_FREQUENCY
;
641 return KSAUDIO_SPEAKER_5POINT1
; /* not 5POINT1_SURROUND */
643 return KSAUDIO_SPEAKER_5POINT1
| SPEAKER_BACK_CENTER
;
645 return KSAUDIO_SPEAKER_7POINT1_SURROUND
; /* Vista deprecates 7POINT1 */
647 FIXME("Unknown speaker configuration: %u\n", channels
);
651 static const enum pa_channel_position pulse_pos_from_wfx
[] = {
652 PA_CHANNEL_POSITION_FRONT_LEFT
,
653 PA_CHANNEL_POSITION_FRONT_RIGHT
,
654 PA_CHANNEL_POSITION_FRONT_CENTER
,
655 PA_CHANNEL_POSITION_LFE
,
656 PA_CHANNEL_POSITION_REAR_LEFT
,
657 PA_CHANNEL_POSITION_REAR_RIGHT
,
658 PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
,
659 PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
,
660 PA_CHANNEL_POSITION_REAR_CENTER
,
661 PA_CHANNEL_POSITION_SIDE_LEFT
,
662 PA_CHANNEL_POSITION_SIDE_RIGHT
,
663 PA_CHANNEL_POSITION_TOP_CENTER
,
664 PA_CHANNEL_POSITION_TOP_FRONT_LEFT
,
665 PA_CHANNEL_POSITION_TOP_FRONT_CENTER
,
666 PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
,
667 PA_CHANNEL_POSITION_TOP_REAR_LEFT
,
668 PA_CHANNEL_POSITION_TOP_REAR_CENTER
,
669 PA_CHANNEL_POSITION_TOP_REAR_RIGHT
672 static HRESULT
pulse_spec_from_waveformat(struct pulse_stream
*stream
, const WAVEFORMATEX
*fmt
)
674 pa_channel_map_init(&stream
->map
);
675 stream
->ss
.rate
= fmt
->nSamplesPerSec
;
676 stream
->ss
.format
= PA_SAMPLE_INVALID
;
678 switch(fmt
->wFormatTag
) {
679 case WAVE_FORMAT_IEEE_FLOAT
:
680 if (!fmt
->nChannels
|| fmt
->nChannels
> 2 || fmt
->wBitsPerSample
!= 32)
682 stream
->ss
.format
= PA_SAMPLE_FLOAT32LE
;
683 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
685 case WAVE_FORMAT_PCM
:
686 if (!fmt
->nChannels
|| fmt
->nChannels
> 2)
688 if (fmt
->wBitsPerSample
== 8)
689 stream
->ss
.format
= PA_SAMPLE_U8
;
690 else if (fmt
->wBitsPerSample
== 16)
691 stream
->ss
.format
= PA_SAMPLE_S16LE
;
693 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
694 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
696 case WAVE_FORMAT_EXTENSIBLE
: {
697 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)fmt
;
698 DWORD mask
= wfe
->dwChannelMask
;
700 if (fmt
->cbSize
!= (sizeof(*wfe
) - sizeof(*fmt
)) && fmt
->cbSize
!= sizeof(*wfe
))
702 if (IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
703 (!wfe
->Samples
.wValidBitsPerSample
|| wfe
->Samples
.wValidBitsPerSample
== 32) &&
704 fmt
->wBitsPerSample
== 32)
705 stream
->ss
.format
= PA_SAMPLE_FLOAT32LE
;
706 else if (IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) {
707 DWORD valid
= wfe
->Samples
.wValidBitsPerSample
;
709 valid
= fmt
->wBitsPerSample
;
710 if (!valid
|| valid
> fmt
->wBitsPerSample
)
712 switch (fmt
->wBitsPerSample
) {
715 stream
->ss
.format
= PA_SAMPLE_U8
;
719 stream
->ss
.format
= PA_SAMPLE_S16LE
;
723 stream
->ss
.format
= PA_SAMPLE_S24LE
;
727 stream
->ss
.format
= PA_SAMPLE_S24_32LE
;
728 else if (valid
== 32)
729 stream
->ss
.format
= PA_SAMPLE_S32LE
;
732 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
735 stream
->map
.channels
= fmt
->nChannels
;
736 if (!mask
|| (mask
& (SPEAKER_ALL
|SPEAKER_RESERVED
)))
737 mask
= get_channel_mask(fmt
->nChannels
);
738 for (j
= 0; j
< ARRAY_SIZE(pulse_pos_from_wfx
) && i
< fmt
->nChannels
; ++j
) {
740 stream
->map
.map
[i
++] = pulse_pos_from_wfx
[j
];
743 /* Special case for mono since pulse appears to map it differently */
744 if (mask
== SPEAKER_FRONT_CENTER
)
745 stream
->map
.map
[0] = PA_CHANNEL_POSITION_MONO
;
747 if (i
< fmt
->nChannels
|| (mask
& SPEAKER_RESERVED
)) {
748 stream
->map
.channels
= 0;
749 ERR("Invalid channel mask: %i/%i and %x(%x)\n", i
, fmt
->nChannels
, mask
, wfe
->dwChannelMask
);
754 case WAVE_FORMAT_ALAW
:
755 case WAVE_FORMAT_MULAW
:
756 if (fmt
->wBitsPerSample
!= 8) {
757 FIXME("Unsupported bpp %u for LAW\n", fmt
->wBitsPerSample
);
758 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
760 if (fmt
->nChannels
!= 1 && fmt
->nChannels
!= 2) {
761 FIXME("Unsupported channels %u for LAW\n", fmt
->nChannels
);
762 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
764 stream
->ss
.format
= fmt
->wFormatTag
== WAVE_FORMAT_MULAW
? PA_SAMPLE_ULAW
: PA_SAMPLE_ALAW
;
765 pa_channel_map_init_auto(&stream
->map
, fmt
->nChannels
, PA_CHANNEL_MAP_ALSA
);
768 WARN("Unhandled tag %x\n", fmt
->wFormatTag
);
769 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
771 stream
->ss
.channels
= stream
->map
.channels
;
772 if (!pa_channel_map_valid(&stream
->map
) || stream
->ss
.format
== PA_SAMPLE_INVALID
) {
773 ERR("Invalid format! Channel spec valid: %i, format: %i\n",
774 pa_channel_map_valid(&stream
->map
), stream
->ss
.format
);
775 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
780 static HRESULT
pulse_stream_connect(struct pulse_stream
*stream
, UINT32 period_bytes
)
787 ret
= InterlockedIncrement(&number
);
788 sprintf(buffer
, "audio stream #%i", ret
);
789 stream
->stream
= pa_stream_new(pulse_ctx
, buffer
, &stream
->ss
, &stream
->map
);
791 if (!stream
->stream
) {
792 WARN("pa_stream_new returned error %i\n", pa_context_errno(pulse_ctx
));
793 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
796 pa_stream_set_state_callback(stream
->stream
, pulse_stream_state
, stream
);
797 pa_stream_set_buffer_attr_callback(stream
->stream
, pulse_attr_update
, stream
);
798 pa_stream_set_moved_callback(stream
->stream
, pulse_attr_update
, stream
);
800 /* PulseAudio will fill in correct values */
801 attr
.minreq
= attr
.fragsize
= period_bytes
;
802 attr
.tlength
= period_bytes
* 3;
803 attr
.maxlength
= stream
->bufsize_frames
* pa_frame_size(&stream
->ss
);
804 attr
.prebuf
= pa_frame_size(&stream
->ss
);
806 if (stream
->dataflow
== eRender
)
807 ret
= pa_stream_connect_playback(stream
->stream
, NULL
, &attr
,
808 PA_STREAM_START_CORKED
|PA_STREAM_START_UNMUTED
|PA_STREAM_ADJUST_LATENCY
, NULL
, NULL
);
810 ret
= pa_stream_connect_record(stream
->stream
, NULL
, &attr
,
811 PA_STREAM_START_CORKED
|PA_STREAM_START_UNMUTED
|PA_STREAM_ADJUST_LATENCY
);
813 WARN("Returns %i\n", ret
);
814 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
816 while (pa_stream_get_state(stream
->stream
) == PA_STREAM_CREATING
)
818 if (pa_stream_get_state(stream
->stream
) != PA_STREAM_READY
)
819 return AUDCLNT_E_ENDPOINT_CREATE_FAILED
;
821 if (stream
->dataflow
== eRender
) {
822 pa_stream_set_underflow_callback(stream
->stream
, pulse_underflow_callback
, stream
);
823 pa_stream_set_started_callback(stream
->stream
, pulse_started_callback
, stream
);
828 static NTSTATUS
pulse_create_stream(void *args
)
830 struct create_stream_params
*params
= args
;
831 REFERENCE_TIME period
, duration
= params
->duration
;
832 struct pulse_stream
*stream
;
833 unsigned int i
, bufsize_bytes
;
838 if (FAILED(params
->result
= pulse_connect(params
->name
)))
841 return STATUS_SUCCESS
;
844 if (!(stream
= calloc(1, sizeof(*stream
))))
847 params
->result
= E_OUTOFMEMORY
;
848 return STATUS_SUCCESS
;
851 stream
->dataflow
= params
->dataflow
;
852 for (i
= 0; i
< ARRAY_SIZE(stream
->vol
); ++i
)
853 stream
->vol
[i
] = 1.f
;
855 hr
= pulse_spec_from_waveformat(stream
, params
->fmt
);
856 TRACE("Obtaining format returns %08x\n", hr
);
861 period
= pulse_def_period
[stream
->dataflow
== eCapture
];
862 if (duration
< 3 * period
)
863 duration
= 3 * period
;
865 stream
->period_bytes
= pa_frame_size(&stream
->ss
) * muldiv(period
, stream
->ss
.rate
, 10000000);
867 stream
->bufsize_frames
= ceil((duration
/ 10000000.) * params
->fmt
->nSamplesPerSec
);
868 bufsize_bytes
= stream
->bufsize_frames
* pa_frame_size(&stream
->ss
);
869 stream
->mmdev_period_usec
= period
/ 10;
871 stream
->share
= params
->mode
;
872 stream
->flags
= params
->flags
;
873 hr
= pulse_stream_connect(stream
, stream
->period_bytes
);
876 const pa_buffer_attr
*attr
= pa_stream_get_buffer_attr(stream
->stream
);
877 stream
->attr
= *attr
;
878 /* Update frames according to new size */
880 if (stream
->dataflow
== eRender
) {
881 stream
->alloc_size
= stream
->real_bufsize_bytes
=
882 stream
->bufsize_frames
* 2 * pa_frame_size(&stream
->ss
);
883 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
884 0, &stream
->real_bufsize_bytes
, MEM_COMMIT
, PAGE_READWRITE
))
887 UINT32 i
, capture_packets
;
889 if ((unalign
= bufsize_bytes
% stream
->period_bytes
))
890 bufsize_bytes
+= stream
->period_bytes
- unalign
;
891 stream
->bufsize_frames
= bufsize_bytes
/ pa_frame_size(&stream
->ss
);
892 stream
->real_bufsize_bytes
= bufsize_bytes
;
894 capture_packets
= stream
->real_bufsize_bytes
/ stream
->period_bytes
;
896 stream
->alloc_size
= stream
->real_bufsize_bytes
+ capture_packets
* sizeof(ACPacket
);
897 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
898 0, &stream
->alloc_size
, MEM_COMMIT
, PAGE_READWRITE
))
901 ACPacket
*cur_packet
= (ACPacket
*)((char*)stream
->local_buffer
+ stream
->real_bufsize_bytes
);
902 BYTE
*data
= stream
->local_buffer
;
903 silence_buffer(stream
->ss
.format
, stream
->local_buffer
, stream
->real_bufsize_bytes
);
904 list_init(&stream
->packet_free_head
);
905 list_init(&stream
->packet_filled_head
);
906 for (i
= 0; i
< capture_packets
; ++i
, ++cur_packet
) {
907 list_add_tail(&stream
->packet_free_head
, &cur_packet
->entry
);
908 cur_packet
->data
= data
;
909 data
+= stream
->period_bytes
;
915 *params
->channel_count
= stream
->ss
.channels
;
916 *params
->stream
= stream
;
919 if (FAILED(params
->result
= hr
)) {
920 free(stream
->local_buffer
);
921 if (stream
->stream
) {
922 pa_stream_disconnect(stream
->stream
);
923 pa_stream_unref(stream
->stream
);
929 return STATUS_SUCCESS
;
932 static NTSTATUS
pulse_release_stream(void *args
)
934 struct release_stream_params
*params
= args
;
935 struct pulse_stream
*stream
= params
->stream
;
938 stream
->please_quit
= TRUE
;
939 NtWaitForSingleObject(params
->timer
, FALSE
, NULL
);
940 NtClose(params
->timer
);
944 if (PA_STREAM_IS_GOOD(pa_stream_get_state(stream
->stream
))) {
945 pa_stream_disconnect(stream
->stream
);
946 while (PA_STREAM_IS_GOOD(pa_stream_get_state(stream
->stream
)))
949 pa_stream_unref(stream
->stream
);
952 if (stream
->tmp_buffer
)
953 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
954 &stream
->tmp_buffer_bytes
, MEM_RELEASE
);
955 if (stream
->local_buffer
)
956 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->local_buffer
,
957 &stream
->alloc_size
, MEM_RELEASE
);
958 free(stream
->peek_buffer
);
960 return STATUS_SUCCESS
;
963 static int write_buffer(const struct pulse_stream
*stream
, BYTE
*buffer
, UINT32 bytes
)
965 const float *vol
= stream
->vol
;
966 UINT32 i
, channels
, mute
= 0;
970 if (!bytes
) return 0;
972 /* Adjust the buffer based on the volume for each channel */
973 channels
= stream
->ss
.channels
;
974 for (i
= 0; i
< channels
; i
++)
976 adjust
|= vol
[i
] != 1.0f
;
980 if (mute
== channels
)
982 silence_buffer(stream
->ss
.format
, buffer
, bytes
);
985 if (!adjust
) goto write
;
987 end
= buffer
+ bytes
;
988 switch (stream
->ss
.format
)
990 #ifndef WORDS_BIGENDIAN
991 #define PROCESS_BUFFER(type) do \
993 type *p = (type*)buffer; \
996 for (i = 0; i < channels; i++) \
997 p[i] = p[i] * vol[i]; \
999 } while ((BYTE*)p != end); \
1001 case PA_SAMPLE_S16LE
:
1002 PROCESS_BUFFER(INT16
);
1004 case PA_SAMPLE_S32LE
:
1005 PROCESS_BUFFER(INT32
);
1007 case PA_SAMPLE_FLOAT32LE
:
1008 PROCESS_BUFFER(float);
1010 #undef PROCESS_BUFFER
1011 case PA_SAMPLE_S24_32LE
:
1013 UINT32
*p
= (UINT32
*)buffer
;
1016 for (i
= 0; i
< channels
; i
++)
1018 p
[i
] = (INT32
)((INT32
)(p
[i
] << 8) * vol
[i
]);
1022 } while ((BYTE
*)p
!= end
);
1025 case PA_SAMPLE_S24LE
:
1027 /* do it 12 bytes at a time until it is no longer possible */
1028 UINT32
*q
= (UINT32
*)buffer
;
1032 while (end
- (BYTE
*)q
>= 12)
1036 v
[1] = q
[1] << 16 | (q
[0] >> 16 & ~0xff);
1037 v
[2] = q
[2] << 24 | (q
[1] >> 8 & ~0xff);
1038 v
[3] = q
[2] & ~0xff;
1039 for (k
= 0; k
< 4; k
++)
1041 v
[k
] = (INT32
)((INT32
)v
[k
] * vol
[i
]);
1042 if (++i
== channels
) i
= 0;
1044 *q
++ = v
[0] >> 8 | (v
[1] & ~0xff) << 16;
1045 *q
++ = v
[1] >> 16 | (v
[2] & ~0xff) << 8;
1046 *q
++ = v
[2] >> 24 | (v
[3] & ~0xff);
1051 UINT32 v
= (INT32
)((INT32
)(p
[0] << 8 | p
[1] << 16 | p
[2] << 24) * vol
[i
]);
1052 *p
++ = v
>> 8 & 0xff;
1053 *p
++ = v
>> 16 & 0xff;
1055 if (++i
== channels
) i
= 0;
1062 UINT8
*p
= (UINT8
*)buffer
;
1065 for (i
= 0; i
< channels
; i
++)
1066 p
[i
] = (int)((p
[i
] - 128) * vol
[i
]) + 128;
1068 } while ((BYTE
*)p
!= end
);
1071 case PA_SAMPLE_ALAW
:
1073 UINT8
*p
= (UINT8
*)buffer
;
1076 for (i
= 0; i
< channels
; i
++)
1077 p
[i
] = mult_alaw_sample(p
[i
], vol
[i
]);
1079 } while ((BYTE
*)p
!= end
);
1082 case PA_SAMPLE_ULAW
:
1084 UINT8
*p
= (UINT8
*)buffer
;
1087 for (i
= 0; i
< channels
; i
++)
1088 p
[i
] = mult_ulaw_sample(p
[i
], vol
[i
]);
1090 } while ((BYTE
*)p
!= end
);
1094 TRACE("Unhandled format %i, not adjusting volume.\n", stream
->ss
.format
);
1099 return pa_stream_write(stream
->stream
, buffer
, bytes
, NULL
, 0, PA_SEEK_RELATIVE
);
1102 static void pulse_write(struct pulse_stream
*stream
)
1104 /* write as much data to PA as we can */
1106 BYTE
*buf
= stream
->local_buffer
+ stream
->pa_offs_bytes
;
1107 UINT32 bytes
= pa_stream_writable_size(stream
->stream
);
1109 if (stream
->just_underran
)
1111 /* prebuffer with silence if needed */
1112 if(stream
->pa_held_bytes
< bytes
){
1113 to_write
= bytes
- stream
->pa_held_bytes
;
1114 TRACE("prebuffering %u frames of silence\n",
1115 (int)(to_write
/ pa_frame_size(&stream
->ss
)));
1116 buf
= calloc(1, to_write
);
1117 pa_stream_write(stream
->stream
, buf
, to_write
, NULL
, 0, PA_SEEK_RELATIVE
);
1121 stream
->just_underran
= FALSE
;
1124 buf
= stream
->local_buffer
+ stream
->pa_offs_bytes
;
1125 TRACE("held: %lu, avail: %u\n", stream
->pa_held_bytes
, bytes
);
1126 bytes
= min(stream
->pa_held_bytes
, bytes
);
1128 if (stream
->pa_offs_bytes
+ bytes
> stream
->real_bufsize_bytes
)
1130 to_write
= stream
->real_bufsize_bytes
- stream
->pa_offs_bytes
;
1131 TRACE("writing small chunk of %u bytes\n", to_write
);
1132 write_buffer(stream
, buf
, to_write
);
1133 stream
->pa_held_bytes
-= to_write
;
1134 to_write
= bytes
- to_write
;
1135 stream
->pa_offs_bytes
= 0;
1136 buf
= stream
->local_buffer
;
1141 TRACE("writing main chunk of %u bytes\n", to_write
);
1142 write_buffer(stream
, buf
, to_write
);
1143 stream
->pa_offs_bytes
+= to_write
;
1144 stream
->pa_offs_bytes
%= stream
->real_bufsize_bytes
;
1145 stream
->pa_held_bytes
-= to_write
;
1148 static void pulse_read(struct pulse_stream
*stream
)
1150 size_t bytes
= pa_stream_readable_size(stream
->stream
);
1152 TRACE("Readable total: %zu, fragsize: %u\n", bytes
, pa_stream_get_buffer_attr(stream
->stream
)->fragsize
);
1154 bytes
+= stream
->peek_len
- stream
->peek_ofs
;
1156 while (bytes
>= stream
->period_bytes
)
1158 BYTE
*dst
= NULL
, *src
;
1159 size_t src_len
, copy
, rem
= stream
->period_bytes
;
1161 if (stream
->started
)
1163 LARGE_INTEGER stamp
, freq
;
1166 if (!(p
= (ACPacket
*)list_head(&stream
->packet_free_head
)))
1168 p
= (ACPacket
*)list_head(&stream
->packet_filled_head
);
1171 next
= (ACPacket
*)p
->entry
.next
;
1174 p
= (ACPacket
*)list_tail(&stream
->packet_filled_head
);
1178 stream
->held_bytes
+= stream
->period_bytes
;
1180 NtQueryPerformanceCounter(&stamp
, &freq
);
1181 p
->qpcpos
= (stamp
.QuadPart
* (INT64
)10000000) / freq
.QuadPart
;
1183 list_remove(&p
->entry
);
1184 list_add_tail(&stream
->packet_filled_head
, &p
->entry
);
1191 if (stream
->peek_len
)
1193 copy
= min(rem
, stream
->peek_len
- stream
->peek_ofs
);
1197 memcpy(dst
, stream
->peek_buffer
+ stream
->peek_ofs
, copy
);
1202 stream
->peek_ofs
+= copy
;
1203 if(stream
->peek_len
== stream
->peek_ofs
)
1204 stream
->peek_len
= stream
->peek_ofs
= 0;
1207 else if (pa_stream_peek(stream
->stream
, (const void**)&src
, &src_len
) == 0 && src_len
)
1209 copy
= min(rem
, src_len
);
1213 memcpy(dst
, src
, copy
);
1215 silence_buffer(stream
->ss
.format
, dst
, copy
);
1224 if (src_len
> stream
->peek_buffer_len
)
1226 free(stream
->peek_buffer
);
1227 stream
->peek_buffer
= malloc(src_len
);
1228 stream
->peek_buffer_len
= src_len
;
1232 memcpy(stream
->peek_buffer
, src
+ copy
, src_len
- copy
);
1234 silence_buffer(stream
->ss
.format
, stream
->peek_buffer
, src_len
- copy
);
1236 stream
->peek_len
= src_len
- copy
;
1237 stream
->peek_ofs
= 0;
1240 pa_stream_drop(stream
->stream
);
1244 bytes
-= stream
->period_bytes
;
1248 static NTSTATUS
pulse_timer_loop(void *args
)
1250 struct timer_loop_params
*params
= args
;
1251 struct pulse_stream
*stream
= params
->stream
;
1252 LARGE_INTEGER delay
;
1258 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1259 pa_stream_get_time(stream
->stream
, &stream
->last_time
);
1262 while (!stream
->please_quit
)
1264 pa_usec_t now
, adv_usec
= 0;
1267 NtDelayExecution(FALSE
, &delay
);
1271 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1273 o
= pa_stream_update_timing_info(stream
->stream
, pulse_op_cb
, &success
);
1276 while (pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1278 pa_operation_unref(o
);
1280 err
= pa_stream_get_time(stream
->stream
, &now
);
1283 TRACE("got now: %s, last time: %s\n", wine_dbgstr_longlong(now
), wine_dbgstr_longlong(stream
->last_time
));
1284 if (stream
->started
&& (stream
->dataflow
== eCapture
|| stream
->held_bytes
))
1286 if(stream
->just_underran
)
1288 stream
->last_time
= now
;
1289 stream
->just_started
= TRUE
;
1292 if (stream
->just_started
)
1294 /* let it play out a period to absorb some latency and get accurate timing */
1295 pa_usec_t diff
= now
- stream
->last_time
;
1297 if (diff
> stream
->mmdev_period_usec
)
1299 stream
->just_started
= FALSE
;
1300 stream
->last_time
= now
;
1305 INT32 adjust
= stream
->last_time
+ stream
->mmdev_period_usec
- now
;
1307 adv_usec
= now
- stream
->last_time
;
1309 if(adjust
> ((INT32
)(stream
->mmdev_period_usec
/ 2)))
1310 adjust
= stream
->mmdev_period_usec
/ 2;
1311 else if(adjust
< -((INT32
)(stream
->mmdev_period_usec
/ 2)))
1312 adjust
= -1 * stream
->mmdev_period_usec
/ 2;
1314 delay
.QuadPart
= -(stream
->mmdev_period_usec
+ adjust
) * 10;
1316 stream
->last_time
+= stream
->mmdev_period_usec
;
1319 if (stream
->dataflow
== eRender
)
1321 pulse_write(stream
);
1323 /* regardless of what PA does, advance one period */
1324 adv_bytes
= min(stream
->period_bytes
, stream
->held_bytes
);
1325 stream
->lcl_offs_bytes
+= adv_bytes
;
1326 stream
->lcl_offs_bytes
%= stream
->real_bufsize_bytes
;
1327 stream
->held_bytes
-= adv_bytes
;
1329 else if(stream
->dataflow
== eCapture
)
1336 stream
->last_time
= now
;
1337 delay
.QuadPart
= -stream
->mmdev_period_usec
* 10;
1342 NtSetEvent(stream
->event
, NULL
);
1344 TRACE("%p after update, adv usec: %d, held: %u, delay usec: %u\n",
1345 stream
, (int)adv_usec
,
1346 (int)(stream
->held_bytes
/ pa_frame_size(&stream
->ss
)),
1347 (unsigned int)(-delay
.QuadPart
/ 10));
1352 return STATUS_SUCCESS
;
1355 static NTSTATUS
pulse_start(void *args
)
1357 struct start_params
*params
= args
;
1358 struct pulse_stream
*stream
= params
->stream
;
1362 params
->result
= S_OK
;
1364 if (!pulse_stream_valid(stream
))
1367 params
->result
= S_OK
;
1368 return STATUS_SUCCESS
;
1371 if ((stream
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
) && !stream
->event
)
1374 params
->result
= AUDCLNT_E_EVENTHANDLE_NOT_SET
;
1375 return STATUS_SUCCESS
;
1378 if (stream
->started
)
1381 params
->result
= AUDCLNT_E_NOT_STOPPED
;
1382 return STATUS_SUCCESS
;
1385 pulse_write(stream
);
1387 if (pa_stream_is_corked(stream
->stream
))
1389 o
= pa_stream_cork(stream
->stream
, 0, pulse_op_cb
, &success
);
1392 while(pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1394 pa_operation_unref(o
);
1399 params
->result
= E_FAIL
;
1402 if (SUCCEEDED(params
->result
))
1404 stream
->started
= TRUE
;
1405 stream
->just_started
= TRUE
;
1408 return STATUS_SUCCESS
;
1411 static NTSTATUS
pulse_stop(void *args
)
1413 struct stop_params
*params
= args
;
1414 struct pulse_stream
*stream
= params
->stream
;
1419 if (!pulse_stream_valid(stream
))
1422 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1423 return STATUS_SUCCESS
;
1426 if (!stream
->started
)
1429 params
->result
= S_FALSE
;
1430 return STATUS_SUCCESS
;
1433 params
->result
= S_OK
;
1434 if (stream
->dataflow
== eRender
)
1436 o
= pa_stream_cork(stream
->stream
, 1, pulse_op_cb
, &success
);
1439 while(pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1441 pa_operation_unref(o
);
1446 params
->result
= E_FAIL
;
1448 if (SUCCEEDED(params
->result
))
1449 stream
->started
= FALSE
;
1451 return STATUS_SUCCESS
;
1454 static NTSTATUS
pulse_reset(void *args
)
1456 struct reset_params
*params
= args
;
1457 struct pulse_stream
*stream
= params
->stream
;
1460 if (!pulse_stream_valid(stream
))
1463 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1464 return STATUS_SUCCESS
;
1467 if (stream
->started
)
1470 params
->result
= AUDCLNT_E_NOT_STOPPED
;
1471 return STATUS_SUCCESS
;
1477 params
->result
= AUDCLNT_E_BUFFER_OPERATION_PENDING
;
1478 return STATUS_SUCCESS
;
1481 if (stream
->dataflow
== eRender
)
1483 /* If there is still data in the render buffer it needs to be removed from the server */
1485 if (stream
->held_bytes
)
1487 pa_operation
*o
= pa_stream_flush(stream
->stream
, pulse_op_cb
, &success
);
1490 while (pa_operation_get_state(o
) == PA_OPERATION_RUNNING
)
1492 pa_operation_unref(o
);
1495 if (success
|| !stream
->held_bytes
)
1497 stream
->clock_lastpos
= stream
->clock_written
= 0;
1498 stream
->pa_offs_bytes
= stream
->lcl_offs_bytes
= 0;
1499 stream
->held_bytes
= stream
->pa_held_bytes
= 0;
1505 stream
->clock_written
+= stream
->held_bytes
;
1506 stream
->held_bytes
= 0;
1508 if ((p
= stream
->locked_ptr
))
1510 stream
->locked_ptr
= NULL
;
1511 list_add_tail(&stream
->packet_free_head
, &p
->entry
);
1513 list_move_tail(&stream
->packet_free_head
, &stream
->packet_filled_head
);
1516 params
->result
= S_OK
;
1517 return STATUS_SUCCESS
;
1520 static BOOL
alloc_tmp_buffer(struct pulse_stream
*stream
, SIZE_T bytes
)
1522 if (stream
->tmp_buffer_bytes
>= bytes
)
1525 if (stream
->tmp_buffer
)
1527 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
1528 &stream
->tmp_buffer_bytes
, MEM_RELEASE
);
1529 stream
->tmp_buffer
= NULL
;
1530 stream
->tmp_buffer_bytes
= 0;
1532 if (NtAllocateVirtualMemory(GetCurrentProcess(), (void **)&stream
->tmp_buffer
,
1533 0, &bytes
, MEM_COMMIT
, PAGE_READWRITE
))
1536 stream
->tmp_buffer_bytes
= bytes
;
1540 static UINT32
pulse_render_padding(struct pulse_stream
*stream
)
1542 return stream
->held_bytes
/ pa_frame_size(&stream
->ss
);
1545 static UINT32
pulse_capture_padding(struct pulse_stream
*stream
)
1547 ACPacket
*packet
= stream
->locked_ptr
;
1548 if (!packet
&& !list_empty(&stream
->packet_filled_head
))
1550 packet
= (ACPacket
*)list_head(&stream
->packet_filled_head
);
1551 stream
->locked_ptr
= packet
;
1552 list_remove(&packet
->entry
);
1554 return stream
->held_bytes
/ pa_frame_size(&stream
->ss
);
1557 static NTSTATUS
pulse_get_render_buffer(void *args
)
1559 struct get_render_buffer_params
*params
= args
;
1560 struct pulse_stream
*stream
= params
->stream
;
1562 UINT32 wri_offs_bytes
;
1565 if (!pulse_stream_valid(stream
))
1568 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1569 return STATUS_SUCCESS
;
1575 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1576 return STATUS_SUCCESS
;
1579 if (!params
->frames
)
1582 *params
->data
= NULL
;
1583 params
->result
= S_OK
;
1584 return STATUS_SUCCESS
;
1587 if (stream
->held_bytes
/ pa_frame_size(&stream
->ss
) + params
->frames
> stream
->bufsize_frames
)
1590 params
->result
= AUDCLNT_E_BUFFER_TOO_LARGE
;
1591 return STATUS_SUCCESS
;
1594 bytes
= params
->frames
* pa_frame_size(&stream
->ss
);
1595 wri_offs_bytes
= (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1596 if (wri_offs_bytes
+ bytes
> stream
->real_bufsize_bytes
)
1598 if (!alloc_tmp_buffer(stream
, bytes
))
1601 params
->result
= E_OUTOFMEMORY
;
1602 return STATUS_SUCCESS
;
1604 *params
->data
= stream
->tmp_buffer
;
1605 stream
->locked
= -bytes
;
1609 *params
->data
= stream
->local_buffer
+ wri_offs_bytes
;
1610 stream
->locked
= bytes
;
1613 silence_buffer(stream
->ss
.format
, *params
->data
, bytes
);
1616 params
->result
= S_OK
;
1617 return STATUS_SUCCESS
;
1620 static void pulse_wrap_buffer(struct pulse_stream
*stream
, BYTE
*buffer
, UINT32 written_bytes
)
1622 UINT32 wri_offs_bytes
= (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1623 UINT32 chunk_bytes
= stream
->real_bufsize_bytes
- wri_offs_bytes
;
1625 if (written_bytes
<= chunk_bytes
)
1627 memcpy(stream
->local_buffer
+ wri_offs_bytes
, buffer
, written_bytes
);
1631 memcpy(stream
->local_buffer
+ wri_offs_bytes
, buffer
, chunk_bytes
);
1632 memcpy(stream
->local_buffer
, buffer
+ chunk_bytes
, written_bytes
- chunk_bytes
);
1636 static NTSTATUS
pulse_release_render_buffer(void *args
)
1638 struct release_render_buffer_params
*params
= args
;
1639 struct pulse_stream
*stream
= params
->stream
;
1640 UINT32 written_bytes
;
1644 if (!stream
->locked
|| !params
->written_frames
)
1648 params
->result
= params
->written_frames
? AUDCLNT_E_OUT_OF_ORDER
: S_OK
;
1649 return STATUS_SUCCESS
;
1652 if (params
->written_frames
* pa_frame_size(&stream
->ss
) >
1653 (stream
->locked
>= 0 ? stream
->locked
: -stream
->locked
))
1656 params
->result
= AUDCLNT_E_INVALID_SIZE
;
1657 return STATUS_SUCCESS
;
1660 if (stream
->locked
>= 0)
1661 buffer
= stream
->local_buffer
+ (stream
->lcl_offs_bytes
+ stream
->held_bytes
) % stream
->real_bufsize_bytes
;
1663 buffer
= stream
->tmp_buffer
;
1665 written_bytes
= params
->written_frames
* pa_frame_size(&stream
->ss
);
1666 if (params
->flags
& AUDCLNT_BUFFERFLAGS_SILENT
)
1667 silence_buffer(stream
->ss
.format
, buffer
, written_bytes
);
1669 if (stream
->locked
< 0)
1670 pulse_wrap_buffer(stream
, buffer
, written_bytes
);
1672 stream
->held_bytes
+= written_bytes
;
1673 stream
->pa_held_bytes
+= written_bytes
;
1674 if (stream
->pa_held_bytes
> stream
->real_bufsize_bytes
)
1676 stream
->pa_offs_bytes
+= stream
->pa_held_bytes
- stream
->real_bufsize_bytes
;
1677 stream
->pa_offs_bytes
%= stream
->real_bufsize_bytes
;
1678 stream
->pa_held_bytes
= stream
->real_bufsize_bytes
;
1680 stream
->clock_written
+= written_bytes
;
1683 TRACE("Released %u, held %lu\n", params
->written_frames
, stream
->held_bytes
/ pa_frame_size(&stream
->ss
));
1686 params
->result
= S_OK
;
1687 return STATUS_SUCCESS
;
1690 static NTSTATUS
pulse_get_capture_buffer(void *args
)
1692 struct get_capture_buffer_params
*params
= args
;
1693 struct pulse_stream
*stream
= params
->stream
;
1697 if (!pulse_stream_valid(stream
))
1700 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1701 return STATUS_SUCCESS
;
1706 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1707 return STATUS_SUCCESS
;
1710 pulse_capture_padding(stream
);
1711 if ((packet
= stream
->locked_ptr
))
1713 *params
->frames
= stream
->period_bytes
/ pa_frame_size(&stream
->ss
);
1715 if (packet
->discont
)
1716 *params
->flags
|= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
;
1719 if (packet
->discont
)
1720 *params
->devpos
= (stream
->clock_written
+ stream
->period_bytes
) / pa_frame_size(&stream
->ss
);
1722 *params
->devpos
= stream
->clock_written
/ pa_frame_size(&stream
->ss
);
1725 *params
->qpcpos
= packet
->qpcpos
;
1726 *params
->data
= packet
->data
;
1729 *params
->frames
= 0;
1730 stream
->locked
= *params
->frames
;
1732 params
->result
= *params
->frames
? S_OK
: AUDCLNT_S_BUFFER_EMPTY
;
1733 return STATUS_SUCCESS
;
1736 static NTSTATUS
pulse_release_capture_buffer(void *args
)
1738 struct release_capture_buffer_params
*params
= args
;
1739 struct pulse_stream
*stream
= params
->stream
;
1742 if (!stream
->locked
&& params
->done
)
1745 params
->result
= AUDCLNT_E_OUT_OF_ORDER
;
1746 return STATUS_SUCCESS
;
1748 if (params
->done
&& stream
->locked
!= params
->done
)
1751 params
->result
= AUDCLNT_E_INVALID_SIZE
;
1752 return STATUS_SUCCESS
;
1756 ACPacket
*packet
= stream
->locked_ptr
;
1757 stream
->locked_ptr
= NULL
;
1758 stream
->held_bytes
-= stream
->period_bytes
;
1759 if (packet
->discont
)
1760 stream
->clock_written
+= 2 * stream
->period_bytes
;
1762 stream
->clock_written
+= stream
->period_bytes
;
1763 list_add_tail(&stream
->packet_free_head
, &packet
->entry
);
1767 params
->result
= S_OK
;
1768 return STATUS_SUCCESS
;
1771 static NTSTATUS
pulse_get_buffer_size(void *args
)
1773 struct get_buffer_size_params
*params
= args
;
1775 params
->result
= S_OK
;
1778 if (!pulse_stream_valid(params
->stream
))
1779 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1781 *params
->size
= params
->stream
->bufsize_frames
;
1784 return STATUS_SUCCESS
;
1787 static NTSTATUS
pulse_get_latency(void *args
)
1789 struct get_latency_params
*params
= args
;
1790 struct pulse_stream
*stream
= params
->stream
;
1791 const pa_buffer_attr
*attr
;
1795 if (!pulse_stream_valid(stream
)) {
1797 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1798 return STATUS_SUCCESS
;
1800 attr
= pa_stream_get_buffer_attr(stream
->stream
);
1801 if (stream
->dataflow
== eRender
)
1802 lat
= attr
->minreq
/ pa_frame_size(&stream
->ss
);
1804 lat
= attr
->fragsize
/ pa_frame_size(&stream
->ss
);
1805 *params
->latency
= (lat
* 10000000) / stream
->ss
.rate
+ pulse_def_period
[0];
1807 TRACE("Latency: %u ms\n", (DWORD
)(*params
->latency
/ 10000));
1808 params
->result
= S_OK
;
1809 return STATUS_SUCCESS
;
1812 static NTSTATUS
pulse_get_current_padding(void *args
)
1814 struct get_current_padding_params
*params
= args
;
1815 struct pulse_stream
*stream
= params
->stream
;
1818 if (!pulse_stream_valid(stream
))
1821 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1822 return STATUS_SUCCESS
;
1825 if (stream
->dataflow
== eRender
)
1826 *params
->padding
= pulse_render_padding(stream
);
1828 *params
->padding
= pulse_capture_padding(stream
);
1831 TRACE("%p Pad: %u ms (%u)\n", stream
, muldiv(*params
->padding
, 1000, stream
->ss
.rate
),
1833 params
->result
= S_OK
;
1834 return STATUS_SUCCESS
;
1837 static NTSTATUS
pulse_get_next_packet_size(void *args
)
1839 struct get_next_packet_size_params
*params
= args
;
1840 struct pulse_stream
*stream
= params
->stream
;
1843 pulse_capture_padding(stream
);
1844 if (stream
->locked_ptr
)
1845 *params
->frames
= stream
->period_bytes
/ pa_frame_size(&stream
->ss
);
1847 *params
->frames
= 0;
1849 params
->result
= S_OK
;
1851 return STATUS_SUCCESS
;
1854 static NTSTATUS
pulse_get_frequency(void *args
)
1856 struct get_frequency_params
*params
= args
;
1857 struct pulse_stream
*stream
= params
->stream
;
1860 if (!pulse_stream_valid(stream
))
1863 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1864 return STATUS_SUCCESS
;
1867 *params
->freq
= stream
->ss
.rate
;
1868 if (stream
->share
== AUDCLNT_SHAREMODE_SHARED
)
1869 *params
->freq
*= pa_frame_size(&stream
->ss
);
1871 params
->result
= S_OK
;
1872 return STATUS_SUCCESS
;
1875 static NTSTATUS
pulse_get_position(void *args
)
1877 struct get_position_params
*params
= args
;
1878 struct pulse_stream
*stream
= params
->stream
;
1881 if (!pulse_stream_valid(stream
))
1884 params
->result
= AUDCLNT_E_DEVICE_INVALIDATED
;
1885 return STATUS_SUCCESS
;
1888 *params
->pos
= stream
->clock_written
- stream
->held_bytes
;
1890 if (stream
->share
== AUDCLNT_SHAREMODE_EXCLUSIVE
|| params
->device
)
1891 *params
->pos
/= pa_frame_size(&stream
->ss
);
1893 /* Make time never go backwards */
1894 if (*params
->pos
< stream
->clock_lastpos
)
1895 *params
->pos
= stream
->clock_lastpos
;
1897 stream
->clock_lastpos
= *params
->pos
;
1900 TRACE("%p Position: %u\n", stream
, (unsigned)*params
->pos
);
1902 if (params
->qpctime
)
1904 LARGE_INTEGER stamp
, freq
;
1905 NtQueryPerformanceCounter(&stamp
, &freq
);
1906 *params
->qpctime
= (stamp
.QuadPart
* (INT64
)10000000) / freq
.QuadPart
;
1909 params
->result
= S_OK
;
1910 return STATUS_SUCCESS
;
1913 static NTSTATUS
pulse_set_volumes(void *args
)
1915 struct set_volumes_params
*params
= args
;
1916 struct pulse_stream
*stream
= params
->stream
;
1919 for (i
= 0; i
< stream
->ss
.channels
; i
++)
1920 stream
->vol
[i
] = params
->volumes
[i
] * params
->master_volume
* params
->session_volumes
[i
];
1922 return STATUS_SUCCESS
;
1925 static NTSTATUS
pulse_set_event_handle(void *args
)
1927 struct set_event_handle_params
*params
= args
;
1928 struct pulse_stream
*stream
= params
->stream
;
1932 if (!pulse_stream_valid(stream
))
1933 hr
= AUDCLNT_E_DEVICE_INVALIDATED
;
1934 else if (!(stream
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
))
1935 hr
= AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED
;
1936 else if (stream
->event
)
1937 hr
= HRESULT_FROM_WIN32(ERROR_INVALID_NAME
);
1939 stream
->event
= params
->event
;
1942 params
->result
= hr
;
1943 return STATUS_SUCCESS
;
1946 static NTSTATUS
pulse_is_started(void *args
)
1948 struct is_started_params
*params
= args
;
1949 struct pulse_stream
*stream
= params
->stream
;
1952 params
->started
= pulse_stream_valid(stream
) && stream
->started
;
1955 return STATUS_SUCCESS
;
1958 const unixlib_entry_t __wine_unix_call_funcs
[] =
1960 pulse_process_attach
,
1961 pulse_process_detach
,
1963 pulse_create_stream
,
1964 pulse_release_stream
,
1969 pulse_get_render_buffer
,
1970 pulse_release_render_buffer
,
1971 pulse_get_capture_buffer
,
1972 pulse_release_capture_buffer
,
1973 pulse_get_buffer_size
,
1975 pulse_get_current_padding
,
1976 pulse_get_next_packet_size
,
1977 pulse_get_frequency
,
1980 pulse_set_event_handle
,