Update PA_MODULE_USAGE to be in line with actual implementation
[pulseaudio-mirror.git] / src / modules / module-waveout.c
blob1a3a6e182ab6ce363ce1652357a8b0c4dc9ddeb6
1 /***
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
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <windows.h>
28 #include <mmsystem.h>
30 #include <pulse/mainloop-api.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/rtclock.h>
36 #include <pulsecore/sink.h>
37 #include <pulsecore/source.h>
38 #include <pulsecore/module.h>
39 #include <pulsecore/modargs.h>
40 #include <pulsecore/sample-util.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/thread.h>
44 #include <pulsecore/thread-mq.h>
46 #include "module-waveout-symdef.h"
48 PA_MODULE_AUTHOR("Pierre Ossman");
49 PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source");
50 PA_MODULE_VERSION(PACKAGE_VERSION);
51 PA_MODULE_USAGE(
52 "sink_name=<name for the sink> "
53 "source_name=<name for the source> "
54 "device=<device number> "
55 "record=<enable source?> "
56 "playback=<enable sink?> "
57 "format=<sample format> "
58 "rate=<sample rate> "
59 "channels=<number of channels> "
60 "channel_map=<channel map> "
61 "fragments=<number of fragments> "
62 "fragment_size=<fragment size>");
64 #define DEFAULT_SINK_NAME "wave_output"
65 #define DEFAULT_SOURCE_NAME "wave_input"
67 #define WAVEOUT_MAX_VOLUME 0xFFFF
69 struct userdata {
70 pa_sink *sink;
71 pa_source *source;
72 pa_core *core;
73 pa_usec_t poll_timeout;
75 pa_thread *thread;
76 pa_thread_mq thread_mq;
77 pa_rtpoll *rtpoll;
79 uint32_t fragments, fragment_size;
81 uint32_t free_ofrags, free_ifrags;
83 DWORD written_bytes;
84 int sink_underflow;
86 int cur_ohdr, cur_ihdr;
87 WAVEHDR *ohdrs, *ihdrs;
89 HWAVEOUT hwo;
90 HWAVEIN hwi;
91 pa_module *module;
93 CRITICAL_SECTION crit;
96 static const char* const valid_modargs[] = {
97 "sink_name",
98 "source_name",
99 "device",
100 "record",
101 "playback",
102 "fragments",
103 "fragment_size",
104 "format",
105 "rate",
106 "channels",
107 "channel_map",
108 NULL
111 static void do_write(struct userdata *u) {
112 uint32_t free_frags;
113 pa_memchunk memchunk;
114 WAVEHDR *hdr;
115 MMRESULT res;
116 void *p;
118 if (!u->sink)
119 return;
121 if (!PA_SINK_IS_LINKED(u->sink->state))
122 return;
124 EnterCriticalSection(&u->crit);
125 free_frags = u->free_ofrags;
126 LeaveCriticalSection(&u->crit);
128 if (!u->sink_underflow && (free_frags == u->fragments))
129 pa_log_debug("WaveOut underflow!");
131 while (free_frags) {
132 hdr = &u->ohdrs[u->cur_ohdr];
133 if (hdr->dwFlags & WHDR_PREPARED)
134 waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
136 hdr->dwBufferLength = 0;
137 while (hdr->dwBufferLength < u->fragment_size) {
138 size_t len;
140 len = u->fragment_size - hdr->dwBufferLength;
142 pa_sink_render(u->sink, len, &memchunk);
144 pa_assert(memchunk.memblock);
145 pa_assert(memchunk.length);
147 if (memchunk.length < len)
148 len = memchunk.length;
150 p = pa_memblock_acquire(memchunk.memblock);
151 memcpy(hdr->lpData + hdr->dwBufferLength, (char*) p + memchunk.index, len);
152 pa_memblock_release(memchunk.memblock);
154 hdr->dwBufferLength += len;
156 pa_memblock_unref(memchunk.memblock);
157 memchunk.memblock = NULL;
160 /* Insufficient data in sink buffer? */
161 if (hdr->dwBufferLength == 0) {
162 u->sink_underflow = 1;
163 break;
166 u->sink_underflow = 0;
168 res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
169 if (res != MMSYSERR_NOERROR)
170 pa_log_error("Unable to prepare waveOut block: %d", res);
172 res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
173 if (res != MMSYSERR_NOERROR)
174 pa_log_error("Unable to write waveOut block: %d", res);
176 u->written_bytes += hdr->dwBufferLength;
178 EnterCriticalSection(&u->crit);
179 u->free_ofrags--;
180 LeaveCriticalSection(&u->crit);
182 free_frags--;
183 u->cur_ohdr++;
184 u->cur_ohdr %= u->fragments;
188 static void do_read(struct userdata *u) {
189 uint32_t free_frags;
190 pa_memchunk memchunk;
191 WAVEHDR *hdr;
192 MMRESULT res;
193 void *p;
195 if (!u->source)
196 return;
198 if (!PA_SOURCE_IS_LINKED(u->source->state))
199 return;
201 EnterCriticalSection(&u->crit);
202 free_frags = u->free_ifrags;
203 u->free_ifrags = 0;
204 LeaveCriticalSection(&u->crit);
206 if (free_frags == u->fragments)
207 pa_log_debug("WaveIn overflow!");
209 while (free_frags) {
210 hdr = &u->ihdrs[u->cur_ihdr];
211 if (hdr->dwFlags & WHDR_PREPARED)
212 waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
214 if (hdr->dwBytesRecorded) {
215 memchunk.memblock = pa_memblock_new(u->core->mempool, hdr->dwBytesRecorded);
216 pa_assert(memchunk.memblock);
218 p = pa_memblock_acquire(memchunk.memblock);
219 memcpy((char*) p, hdr->lpData, hdr->dwBytesRecorded);
220 pa_memblock_release(memchunk.memblock);
222 memchunk.length = hdr->dwBytesRecorded;
223 memchunk.index = 0;
225 pa_source_post(u->source, &memchunk);
226 pa_memblock_unref(memchunk.memblock);
229 res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
230 if (res != MMSYSERR_NOERROR)
231 pa_log_error("Unable to prepare waveIn block: %d", res);
233 res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
234 if (res != MMSYSERR_NOERROR)
235 pa_log_error("Unable to add waveIn block: %d", res);
237 free_frags--;
238 u->cur_ihdr++;
239 u->cur_ihdr %= u->fragments;
243 static void thread_func(void *userdata) {
244 struct userdata *u = userdata;
246 pa_assert(u);
247 pa_assert(u->sink || u->source);
249 pa_log_debug("Thread starting up");
251 if (u->core->realtime_scheduling)
252 pa_make_realtime(u->core->realtime_priority);
254 pa_thread_mq_install(&u->thread_mq);
256 for (;;) {
257 int ret;
259 if (PA_SINK_IS_OPENED(u->sink->thread_info.state) ||
260 PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
262 if (u->sink->thread_info.rewind_requested)
263 pa_sink_process_rewind(u->sink, 0);
265 if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
266 do_write(u);
267 if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
268 do_read(u);
270 pa_rtpoll_set_timer_relative(u->rtpoll, u->poll_timeout);
271 } else
272 pa_rtpoll_set_timer_disabled(u->rtpoll);
274 /* Hmm, nothing to do. Let's sleep */
275 if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
276 goto fail;
278 if (ret == 0)
279 goto finish;
282 fail:
283 /* If this was no regular exit from the loop we have to continue
284 * processing messages until we received PA_MESSAGE_SHUTDOWN */
285 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
286 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
288 finish:
289 pa_log_debug("Thread shutting down");
292 static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
293 struct userdata *u = (struct userdata *)inst;
295 if (msg != WOM_DONE)
296 return;
298 EnterCriticalSection(&u->crit);
299 u->free_ofrags++;
300 pa_assert(u->free_ofrags <= u->fragments);
301 LeaveCriticalSection(&u->crit);
304 static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
305 struct userdata *u = (struct userdata *)inst;
307 if (msg != WIM_DATA)
308 return;
310 EnterCriticalSection(&u->crit);
311 u->free_ifrags++;
312 pa_assert(u->free_ifrags <= u->fragments);
313 LeaveCriticalSection(&u->crit);
316 static pa_usec_t sink_get_latency(struct userdata *u) {
317 uint32_t free_frags;
318 MMTIME mmt;
319 pa_assert(u);
320 pa_assert(u->sink);
322 memset(&mmt, 0, sizeof(mmt));
323 mmt.wType = TIME_BYTES;
324 if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
325 return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &u->sink->sample_spec);
326 else {
327 EnterCriticalSection(&u->crit);
328 free_frags = u->free_ofrags;
329 LeaveCriticalSection(&u->crit);
331 return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size, &u->sink->sample_spec);
335 static pa_usec_t source_get_latency(struct userdata *u) {
336 pa_usec_t r = 0;
337 uint32_t free_frags;
338 pa_assert(u);
339 pa_assert(u->source);
341 EnterCriticalSection(&u->crit);
342 free_frags = u->free_ifrags;
343 LeaveCriticalSection(&u->crit);
345 r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &u->source->sample_spec);
347 return r;
350 static int process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
351 struct userdata *u;
353 if (pa_sink_isinstance(o)) {
354 u = PA_SINK(o)->userdata;
356 switch (code) {
358 case PA_SINK_MESSAGE_GET_LATENCY: {
359 pa_usec_t r = 0;
360 if (u->hwo)
361 r = sink_get_latency(u);
362 *((pa_usec_t*) data) = r;
363 return 0;
368 return pa_sink_process_msg(o, code, data, offset, chunk);
371 if (pa_source_isinstance(o)) {
372 u = PA_SOURCE(o)->userdata;
374 switch (code) {
376 case PA_SOURCE_MESSAGE_GET_LATENCY: {
377 pa_usec_t r = 0;
378 if (u->hwi)
379 r = source_get_latency(u);
380 *((pa_usec_t*) data) = r;
381 return 0;
386 return pa_source_process_msg(o, code, data, offset, chunk);
389 return -1;
392 static void sink_get_volume_cb(pa_sink *s) {
393 struct userdata *u = s->userdata;
394 DWORD vol;
395 pa_volume_t left, right;
397 if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
398 return;
400 left = PA_CLAMP_VOLUME((vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
401 right = PA_CLAMP_VOLUME(((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
403 /* Windows supports > 2 channels, except for volume control */
404 if (s->real_volume.channels > 2)
405 pa_cvolume_set(&s->real_volume, s->real_volume.channels, (left + right)/2);
407 s->real_volume.values[0] = left;
408 if (s->real_volume.channels > 1)
409 s->real_volume.values[1] = right;
412 static void sink_set_volume_cb(pa_sink *s) {
413 struct userdata *u = s->userdata;
414 DWORD vol;
416 vol = s->real_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM;
417 if (s->real_volume.channels > 1)
418 vol |= (s->real_volume.values[1] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
420 if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
421 return;
424 static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
425 wf->wFormatTag = WAVE_FORMAT_PCM;
427 if (ss->channels > 2) {
428 pa_log_error("More than two channels not supported.");
429 return -1;
432 wf->nChannels = ss->channels;
434 switch (ss->rate) {
435 case 8000:
436 case 11025:
437 case 22005:
438 case 44100:
439 break;
440 default:
441 pa_log_error("Unsupported sample rate.");
442 return -1;
445 wf->nSamplesPerSec = ss->rate;
447 if (ss->format == PA_SAMPLE_U8)
448 wf->wBitsPerSample = 8;
449 else if (ss->format == PA_SAMPLE_S16NE)
450 wf->wBitsPerSample = 16;
451 else {
452 pa_log_error("Unsupported sample format.");
453 return -1;
456 wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
457 wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
459 wf->cbSize = 0;
461 return 0;
464 int pa__get_n_used(pa_module *m) {
465 struct userdata *u;
466 pa_assert(m);
467 pa_assert(m->userdata);
468 u = (struct userdata *)m->userdata;
470 return (u->sink ? pa_sink_used_by(u->sink) : 0) +
471 (u->source ? pa_source_used_by(u->source) : 0);
474 int pa__init(pa_module *m) {
475 struct userdata *u = NULL;
476 HWAVEOUT hwo = INVALID_HANDLE_VALUE;
477 HWAVEIN hwi = INVALID_HANDLE_VALUE;
478 WAVEFORMATEX wf;
479 int nfrags, frag_size;
480 pa_bool_t record = TRUE, playback = TRUE;
481 unsigned int device;
482 pa_sample_spec ss;
483 pa_channel_map map;
484 pa_modargs *ma = NULL;
485 unsigned int i;
487 pa_assert(m);
488 pa_assert(m->core);
490 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
491 pa_log("failed to parse module arguments.");
492 goto fail;
495 if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
496 pa_log("record= and playback= expect boolean argument.");
497 goto fail;
500 if (!playback && !record) {
501 pa_log("neither playback nor record enabled for device.");
502 goto fail;
505 device = WAVE_MAPPER;
506 if (pa_modargs_get_value_u32(ma, "device", &device) < 0) {
507 pa_log("failed to parse device argument");
508 goto fail;
511 nfrags = 5;
512 frag_size = 8192;
513 if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
514 pa_log("failed to parse fragments arguments");
515 goto fail;
518 ss = m->core->default_sample_spec;
519 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) {
520 pa_log("failed to parse sample specification");
521 goto fail;
524 if (ss_to_waveformat(&ss, &wf) < 0)
525 goto fail;
527 u = pa_xmalloc(sizeof(struct userdata));
529 if (record) {
530 if (waveInOpen(&hwi, device, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
531 pa_log("failed to open waveIn");
532 goto fail;
534 if (waveInStart(hwi) != MMSYSERR_NOERROR) {
535 pa_log("failed to start waveIn");
536 goto fail;
538 pa_log_debug("Opened waveIn subsystem.");
541 if (playback) {
542 if (waveOutOpen(&hwo, device, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
543 pa_log("failed to open waveOut");
544 goto fail;
546 pa_log_debug("Opened waveOut subsystem.");
549 InitializeCriticalSection(&u->crit);
551 if (hwi != INVALID_HANDLE_VALUE) {
552 pa_source_new_data data;
553 pa_source_new_data_init(&data);
554 data.driver = __FILE__;
555 data.module = m;
556 pa_source_new_data_set_sample_spec(&data, &ss);
557 pa_source_new_data_set_channel_map(&data, &map);
558 pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
559 u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
560 pa_source_new_data_done(&data);
562 pa_assert(u->source);
563 u->source->userdata = u;
564 pa_source_set_description(u->source, "Windows waveIn PCM");
565 u->source->parent.process_msg = process_msg;
566 } else
567 u->source = NULL;
569 if (hwo != INVALID_HANDLE_VALUE) {
570 pa_sink_new_data data;
571 pa_sink_new_data_init(&data);
572 data.driver = __FILE__;
573 data.module = m;
574 pa_sink_new_data_set_sample_spec(&data, &ss);
575 pa_sink_new_data_set_channel_map(&data, &map);
576 pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
577 u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
578 pa_sink_new_data_done(&data);
580 pa_assert(u->sink);
581 u->sink->get_volume = sink_get_volume_cb;
582 u->sink->set_volume = sink_set_volume_cb;
583 u->sink->userdata = u;
584 pa_sink_set_description(u->sink, "Windows waveOut PCM");
585 u->sink->parent.process_msg = process_msg;
586 } else
587 u->sink = NULL;
589 pa_assert(u->source || u->sink);
590 pa_modargs_free(ma);
592 u->core = m->core;
593 u->hwi = hwi;
594 u->hwo = hwo;
596 u->fragments = nfrags;
597 u->free_ifrags = u->fragments;
598 u->free_ofrags = u->fragments;
599 u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
601 u->written_bytes = 0;
602 u->sink_underflow = 1;
604 u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
606 u->cur_ihdr = 0;
607 u->cur_ohdr = 0;
608 u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
609 pa_assert(u->ihdrs);
610 u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
611 pa_assert(u->ohdrs);
612 for (i = 0;i < u->fragments;i++) {
613 u->ihdrs[i].dwBufferLength = u->fragment_size;
614 u->ohdrs[i].dwBufferLength = u->fragment_size;
615 u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
616 pa_assert(u->ihdrs);
617 u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
618 pa_assert(u->ohdrs);
621 u->module = m;
622 m->userdata = u;
624 /* Read mixer settings */
625 if (u->sink)
626 sink_get_volume_cb(u->sink);
628 u->rtpoll = pa_rtpoll_new();
629 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
630 if (!(u->thread = pa_thread_new("waveout-source", thread_func, u))) {
631 pa_log("Failed to create thread.");
632 goto fail;
635 if (u->sink) {
636 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
637 pa_sink_set_rtpoll(u->sink, u->rtpoll);
638 pa_sink_put(u->sink);
640 if (u->source) {
641 pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
642 pa_source_set_rtpoll(u->source, u->rtpoll);
643 pa_source_put(u->source);
646 return 0;
648 fail:
649 if (ma)
650 pa_modargs_free(ma);
652 pa__done(m);
654 return -1;
657 void pa__done(pa_module *m) {
658 struct userdata *u;
659 unsigned int i;
661 pa_assert(m);
662 pa_assert(m->core);
664 if (!(u = m->userdata))
665 return;
667 if (u->sink)
668 pa_sink_unlink(u->sink);
669 if (u->source)
670 pa_source_unlink(u->source);
672 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
673 if (u->thread)
674 pa_thread_free(u->thread);
675 pa_thread_mq_done(&u->thread_mq);
677 if (u->sink)
678 pa_sink_unref(u->sink);
679 if (u->source)
680 pa_source_unref(u->source);
682 if (u->rtpoll)
683 pa_rtpoll_free(u->rtpoll);
685 if (u->hwi != INVALID_HANDLE_VALUE) {
686 waveInReset(u->hwi);
687 waveInClose(u->hwi);
690 if (u->hwo != INVALID_HANDLE_VALUE) {
691 waveOutReset(u->hwo);
692 waveOutClose(u->hwo);
695 for (i = 0;i < u->fragments;i++) {
696 pa_xfree(u->ihdrs[i].lpData);
697 pa_xfree(u->ohdrs[i].lpData);
700 pa_xfree(u->ihdrs);
701 pa_xfree(u->ohdrs);
703 DeleteCriticalSection(&u->crit);
705 pa_xfree(u);