2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <pulse/xmalloc.h>
31 #include <pulse/timeval.h>
33 #include <pulsecore/sink.h>
34 #include <pulsecore/source.h>
35 #include <pulsecore/module.h>
36 #include <pulsecore/modargs.h>
37 #include <pulsecore/sample-util.h>
38 #include <pulsecore/core-util.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/thread.h>
41 #include <pulsecore/thread-mq.h>
43 #include "module-waveout-symdef.h"
45 PA_MODULE_AUTHOR("Pierre Ossman");
46 PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source");
47 PA_MODULE_VERSION(PACKAGE_VERSION);
49 "sink_name=<name for the sink> "
50 "source_name=<name for the source> "
51 "device=<device number> "
52 "device_name=<name of the device> "
53 "record=<enable source?> "
54 "playback=<enable sink?> "
55 "format=<sample format> "
57 "channels=<number of channels> "
58 "channel_map=<channel map> "
59 "fragments=<number of fragments> "
60 "fragment_size=<fragment size>");
62 #define DEFAULT_SINK_NAME "wave_output"
63 #define DEFAULT_SOURCE_NAME "wave_input"
65 #define WAVEOUT_MAX_VOLUME 0xFFFF
71 pa_usec_t poll_timeout;
74 pa_thread_mq thread_mq;
77 uint32_t fragments, fragment_size;
79 uint32_t free_ofrags, free_ifrags;
84 int cur_ohdr, cur_ihdr;
85 WAVEHDR *ohdrs, *ihdrs;
91 CRITICAL_SECTION crit;
94 static const char* const valid_modargs[] = {
110 static void do_write(struct userdata *u) {
112 pa_memchunk memchunk;
120 if (!PA_SINK_IS_LINKED(u->sink->state))
123 EnterCriticalSection(&u->crit);
124 free_frags = u->free_ofrags;
125 LeaveCriticalSection(&u->crit);
127 if (!u->sink_underflow && (free_frags == u->fragments))
128 pa_log_debug("WaveOut underflow!");
131 hdr = &u->ohdrs[u->cur_ohdr];
132 if (hdr->dwFlags & WHDR_PREPARED)
133 waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
135 hdr->dwBufferLength = 0;
136 while (hdr->dwBufferLength < u->fragment_size) {
139 len = u->fragment_size - hdr->dwBufferLength;
141 pa_sink_render(u->sink, len, &memchunk);
143 pa_assert(memchunk.memblock);
144 pa_assert(memchunk.length);
146 if (memchunk.length < len)
147 len = memchunk.length;
149 p = pa_memblock_acquire(memchunk.memblock);
150 memcpy(hdr->lpData + hdr->dwBufferLength, (char*) p + memchunk.index, len);
151 pa_memblock_release(memchunk.memblock);
153 hdr->dwBufferLength += len;
155 pa_memblock_unref(memchunk.memblock);
156 memchunk.memblock = NULL;
159 /* Underflow detection */
160 if (hdr->dwBufferLength == 0) {
161 u->sink_underflow = 1;
164 u->sink_underflow = 0;
166 res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
167 if (res != MMSYSERR_NOERROR)
168 pa_log_error("Unable to prepare waveOut block: %d", res);
170 res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
171 if (res != MMSYSERR_NOERROR)
172 pa_log_error("Unable to write waveOut block: %d", res);
174 u->written_bytes += hdr->dwBufferLength;
176 EnterCriticalSection(&u->crit);
178 LeaveCriticalSection(&u->crit);
182 u->cur_ohdr %= u->fragments;
186 static void do_read(struct userdata *u) {
188 pa_memchunk memchunk;
196 if (!PA_SOURCE_IS_LINKED(u->source->state))
199 EnterCriticalSection(&u->crit);
200 free_frags = u->free_ifrags;
202 LeaveCriticalSection(&u->crit);
204 if (free_frags == u->fragments)
205 pa_log_debug("WaveIn overflow!");
208 hdr = &u->ihdrs[u->cur_ihdr];
209 if (hdr->dwFlags & WHDR_PREPARED)
210 waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
212 if (hdr->dwBytesRecorded) {
213 memchunk.memblock = pa_memblock_new(u->core->mempool, hdr->dwBytesRecorded);
214 pa_assert(memchunk.memblock);
216 p = pa_memblock_acquire(memchunk.memblock);
217 memcpy((char*) p, hdr->lpData, hdr->dwBytesRecorded);
218 pa_memblock_release(memchunk.memblock);
220 memchunk.length = hdr->dwBytesRecorded;
223 pa_source_post(u->source, &memchunk);
224 pa_memblock_unref(memchunk.memblock);
227 res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
228 if (res != MMSYSERR_NOERROR)
229 pa_log_error("Unable to prepare waveIn block: %d", res);
231 res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
232 if (res != MMSYSERR_NOERROR)
233 pa_log_error("Unable to add waveIn block: %d", res);
237 u->cur_ihdr %= u->fragments;
241 static void thread_func(void *userdata) {
242 struct userdata *u = userdata;
245 pa_assert(u->sink || u->source);
247 pa_log_debug("Thread starting up");
249 if (u->core->realtime_scheduling)
250 pa_make_realtime(u->core->realtime_priority);
252 pa_thread_mq_install(&u->thread_mq);
256 pa_bool_t need_timer = FALSE;
258 if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
259 if (u->sink->thread_info.rewind_requested)
260 pa_sink_process_rewind(u->sink, 0);
265 if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
271 pa_rtpoll_set_timer_relative(u->rtpoll, u->poll_timeout);
273 pa_rtpoll_set_timer_disabled(u->rtpoll);
275 /* Hmm, nothing to do. Let's sleep */
276 if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
284 /* If this was no regular exit from the loop we have to continue
285 * processing messages until we received PA_MESSAGE_SHUTDOWN */
286 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
287 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
290 pa_log_debug("Thread shutting down");
293 static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
294 struct userdata *u = (struct userdata*) inst;
297 pa_log_debug("WaveOut subsystem opened.");
298 if (msg == WOM_CLOSE)
299 pa_log_debug("WaveOut subsystem closed.");
303 EnterCriticalSection(&u->crit);
305 pa_assert(u->free_ofrags <= u->fragments);
306 LeaveCriticalSection(&u->crit);
309 static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
310 struct userdata *u = (struct userdata*) inst;
313 pa_log_debug("WaveIn subsystem opened.");
314 if (msg == WIM_CLOSE)
315 pa_log_debug("WaveIn subsystem closed.");
319 EnterCriticalSection(&u->crit);
321 pa_assert(u->free_ifrags <= u->fragments);
322 LeaveCriticalSection(&u->crit);
325 static pa_usec_t sink_get_latency(struct userdata *u) {
331 memset(&mmt, 0, sizeof(mmt));
332 mmt.wType = TIME_BYTES;
333 if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
334 return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &u->sink->sample_spec);
336 EnterCriticalSection(&u->crit);
337 free_frags = u->free_ofrags;
338 LeaveCriticalSection(&u->crit);
340 return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size, &u->sink->sample_spec);
344 static pa_usec_t source_get_latency(struct userdata *u) {
348 pa_assert(u->source);
350 EnterCriticalSection(&u->crit);
351 free_frags = u->free_ifrags;
352 LeaveCriticalSection(&u->crit);
354 r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &u->source->sample_spec);
359 static int process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
362 if (pa_sink_isinstance(o)) {
363 u = PA_SINK(o)->userdata;
367 case PA_SINK_MESSAGE_GET_LATENCY: {
370 r = sink_get_latency(u);
371 *((pa_usec_t*) data) = r;
377 return pa_sink_process_msg(o, code, data, offset, chunk);
380 if (pa_source_isinstance(o)) {
381 u = PA_SOURCE(o)->userdata;
385 case PA_SOURCE_MESSAGE_GET_LATENCY: {
388 r = source_get_latency(u);
389 *((pa_usec_t*) data) = r;
395 return pa_source_process_msg(o, code, data, offset, chunk);
401 static void sink_get_volume_cb(pa_sink *s) {
402 struct userdata *u = s->userdata;
405 pa_volume_t left, right;
407 if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
409 if (!(caps.dwSupport & WAVECAPS_VOLUME))
412 if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
415 left = PA_CLAMP_VOLUME((vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
416 if (caps.dwSupport & WAVECAPS_LRVOLUME)
417 right = PA_CLAMP_VOLUME(((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
421 /* Windows supports > 2 channels, except for volume control */
422 if (s->real_volume.channels > 2)
423 pa_cvolume_set(&s->real_volume, s->real_volume.channels, (left + right)/2);
425 s->real_volume.values[0] = left;
426 if (s->real_volume.channels > 1)
427 s->real_volume.values[1] = right;
430 static void sink_set_volume_cb(pa_sink *s) {
431 struct userdata *u = s->userdata;
435 if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
437 if (!(caps.dwSupport & WAVECAPS_VOLUME))
440 if (s->real_volume.channels == 2 && caps.dwSupport & WAVECAPS_LRVOLUME) {
441 vol = (s->real_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
442 | (s->real_volume.values[1] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
444 vol = (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
445 | (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
448 if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
452 static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
453 wf->wFormatTag = WAVE_FORMAT_PCM;
455 if (ss->channels > 2) {
456 pa_log_error("More than two channels not supported.");
460 wf->nChannels = ss->channels;
462 wf->nSamplesPerSec = ss->rate;
464 if (ss->format == PA_SAMPLE_U8)
465 wf->wBitsPerSample = 8;
466 else if (ss->format == PA_SAMPLE_S16NE)
467 wf->wBitsPerSample = 16;
469 pa_log_error("Unsupported sample format, only u8 and s16 are supported.");
473 wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
474 wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
481 int pa__get_n_used(pa_module *m) {
484 pa_assert(m->userdata);
485 u = (struct userdata*) m->userdata;
487 return (u->sink ? pa_sink_used_by(u->sink) : 0) +
488 (u->source ? pa_source_used_by(u->source) : 0);
491 int pa__init(pa_module *m) {
492 struct userdata *u = NULL;
493 HWAVEOUT hwo = INVALID_HANDLE_VALUE;
494 HWAVEIN hwi = INVALID_HANDLE_VALUE;
498 int nfrags, frag_size;
499 pa_bool_t record = TRUE, playback = TRUE;
503 pa_modargs *ma = NULL;
504 const char *device_name = NULL;
510 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
511 pa_log("failed to parse module arguments.");
515 if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
516 pa_log("record= and playback= expect boolean argument.");
520 if (!playback && !record) {
521 pa_log("neither playback nor record enabled for device.");
525 /* Set the device to be opened. If set device_name is used,
526 * else device if set and lastly WAVE_MAPPER is the default */
527 device = WAVE_MAPPER;
528 if (pa_modargs_get_value_u32(ma, "device", &device) < 0) {
529 pa_log("failed to parse device argument");
532 if ((device_name = pa_modargs_get_value(ma, "device_name", NULL)) != NULL) {
533 unsigned int num_devices = waveOutGetNumDevs();
534 for (i = 0; i < num_devices; i++) {
535 if (waveOutGetDevCaps(i, &pwoc, sizeof(pwoc)) == MMSYSERR_NOERROR)
536 if (_stricmp(device_name, pwoc.szPname) == 0)
542 pa_log("device not found: %s", device_name);
546 if (waveOutGetDevCaps(device, &pwoc, sizeof(pwoc)) == MMSYSERR_NOERROR)
547 device_name = pwoc.szPname;
549 device_name = "unknown";
553 if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
554 pa_log("failed to parse fragments arguments");
558 ss = m->core->default_sample_spec;
559 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) {
560 pa_log("failed to parse sample specification");
564 if (ss_to_waveformat(&ss, &wf) < 0)
567 u = pa_xmalloc(sizeof(struct userdata));
570 result = waveInOpen(&hwi, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
571 if (result != MMSYSERR_NOERROR) {
572 pa_log_warn("Sample spec not supported by WaveIn, falling back to default sample rate.");
573 ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
575 result = waveInOpen(&hwi, device, &wf, (DWORD_PTR) chunk_ready_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
576 if (result != MMSYSERR_NOERROR) {
577 char errortext[MAXERRORLENGTH];
578 pa_log("Failed to open WaveIn.");
579 if (waveInGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
580 pa_log("Error: %s", errortext);
583 if (waveInStart(hwi) != MMSYSERR_NOERROR) {
584 pa_log("failed to start waveIn");
590 result = waveOutOpen(&hwo, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
591 if (result != MMSYSERR_NOERROR) {
592 pa_log_warn("Sample spec not supported by WaveOut, falling back to default sample rate.");
593 ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
595 result = waveOutOpen(&hwo, device, &wf, (DWORD_PTR) chunk_done_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
596 if (result != MMSYSERR_NOERROR) {
597 char errortext[MAXERRORLENGTH];
598 pa_log("Failed to open WaveOut.");
599 if (waveOutGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
600 pa_log("Error: %s", errortext);
605 InitializeCriticalSection(&u->crit);
607 if (hwi != INVALID_HANDLE_VALUE) {
608 char *description = pa_sprintf_malloc("WaveIn on %s", device_name);
609 pa_source_new_data data;
610 pa_source_new_data_init(&data);
611 data.driver = __FILE__;
613 pa_source_new_data_set_sample_spec(&data, &ss);
614 pa_source_new_data_set_channel_map(&data, &map);
615 pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
616 u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
617 pa_source_new_data_done(&data);
619 pa_assert(u->source);
620 u->source->userdata = u;
621 pa_source_set_description(u->source, description);
622 u->source->parent.process_msg = process_msg;
623 pa_xfree(description);
627 if (hwo != INVALID_HANDLE_VALUE) {
628 char *description = pa_sprintf_malloc("WaveOut on %s", device_name);
629 pa_sink_new_data data;
630 pa_sink_new_data_init(&data);
631 data.driver = __FILE__;
633 pa_sink_new_data_set_sample_spec(&data, &ss);
634 pa_sink_new_data_set_channel_map(&data, &map);
635 pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
636 u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
637 pa_sink_new_data_done(&data);
640 pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
641 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
642 u->sink->userdata = u;
643 pa_sink_set_description(u->sink, description);
644 u->sink->parent.process_msg = process_msg;
645 pa_xfree(description);
649 pa_assert(u->source || u->sink);
656 u->fragments = nfrags;
657 u->free_ifrags = u->fragments;
658 u->free_ofrags = u->fragments;
659 u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
661 u->written_bytes = 0;
662 u->sink_underflow = 1;
664 u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
665 pa_log_debug("Poll timeout = %.1f ms", (double) u->poll_timeout / PA_USEC_PER_MSEC);
669 u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
671 u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
673 for (i = 0; i < u->fragments; i++) {
674 u->ihdrs[i].dwBufferLength = u->fragment_size;
675 u->ohdrs[i].dwBufferLength = u->fragment_size;
676 u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
678 u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
685 /* Read mixer settings */
687 sink_get_volume_cb(u->sink);
689 u->rtpoll = pa_rtpoll_new();
690 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
693 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
694 pa_sink_set_rtpoll(u->sink, u->rtpoll);
697 pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
698 pa_source_set_rtpoll(u->source, u->rtpoll);
701 if (!(u->thread = pa_thread_new("waveout", thread_func, u))) {
702 pa_log("Failed to create thread.");
707 pa_sink_put(u->sink);
709 pa_source_put(u->source);
722 void pa__done(pa_module *m) {
729 if (!(u = m->userdata))
733 pa_sink_unlink(u->sink);
735 pa_source_unlink(u->source);
737 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
739 pa_thread_free(u->thread);
740 pa_thread_mq_done(&u->thread_mq);
743 pa_sink_unref(u->sink);
745 pa_source_unref(u->source);
748 pa_rtpoll_free(u->rtpoll);
750 if (u->hwi != INVALID_HANDLE_VALUE) {
755 if (u->hwo != INVALID_HANDLE_VALUE) {
756 waveOutReset(u->hwo);
757 waveOutClose(u->hwo);
760 for (i = 0; i < u->fragments; i++) {
761 pa_xfree(u->ihdrs[i].lpData);
762 pa_xfree(u->ohdrs[i].lpData);
768 DeleteCriticalSection(&u->crit);