]> code.delx.au - pulseaudio/blob - src/modules/module-waveout.c
ce9ea84d800bb64699b27b1a952cc499951c7595
[pulseaudio] / src / modules / module-waveout.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <mmsystem.h>
28 #include <assert.h>
29
30 #include <polyp/mainloop-api.h>
31
32 #include <polyp/xmalloc.h>
33
34 #include <polypcore/sink.h>
35 #include <polypcore/source.h>
36 #include <polypcore/module.h>
37 #include <polypcore/modargs.h>
38 #include <polypcore/sample-util.h>
39 #include <polypcore/core-util.h>
40 #include <polypcore/log.h>
41
42 #include "module-waveout-symdef.h"
43
44 PA_MODULE_AUTHOR("Pierre Ossman")
45 PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source")
46 PA_MODULE_VERSION(PACKAGE_VERSION)
47 PA_MODULE_USAGE(
48 "sink_name=<name for the sink> "
49 "source_name=<name for the source>"
50 "record=<enable source?> "
51 "playback=<enable sink?> "
52 "format=<sample format> "
53 "channels=<number of channels> "
54 "rate=<sample rate> "
55 "fragments=<number of fragments> "
56 "fragment_size=<fragment size> "
57 "channel_map=<channel map>")
58
59 #define DEFAULT_SINK_NAME "wave_output"
60 #define DEFAULT_SOURCE_NAME "wave_input"
61
62 #define WAVEOUT_MAX_VOLUME 0xFFFF
63
64 struct userdata {
65 pa_sink *sink;
66 pa_source *source;
67 pa_core *core;
68 pa_time_event *event;
69 pa_defer_event *defer;
70 pa_usec_t poll_timeout;
71
72 uint32_t fragments, fragment_size;
73
74 uint32_t free_ofrags, free_ifrags;
75
76 DWORD written_bytes;
77
78 int cur_ohdr, cur_ihdr;
79 unsigned int oremain;
80 WAVEHDR *ohdrs, *ihdrs;
81 pa_memchunk silence;
82
83 HWAVEOUT hwo;
84 HWAVEIN hwi;
85 pa_module *module;
86
87 CRITICAL_SECTION crit;
88 };
89
90 static const char* const valid_modargs[] = {
91 "sink_name",
92 "source_name",
93 "record",
94 "playback",
95 "fragments",
96 "fragment_size",
97 "format",
98 "rate",
99 "channels",
100 "channel_map",
101 NULL
102 };
103
104 static void update_usage(struct userdata *u) {
105 pa_module_set_used(u->module,
106 (u->sink ? pa_idxset_size(u->sink->inputs) : 0) +
107 (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) +
108 (u->source ? pa_idxset_size(u->source->outputs) : 0));
109 }
110
111 static void do_write(struct userdata *u)
112 {
113 uint32_t free_frags, remain;
114 pa_memchunk memchunk, *cur_chunk;
115 WAVEHDR *hdr;
116 MMRESULT res;
117
118 if (!u->sink)
119 return;
120
121 EnterCriticalSection(&u->crit);
122
123 free_frags = u->free_ofrags;
124 u->free_ofrags = 0;
125
126 LeaveCriticalSection(&u->crit);
127
128 if (free_frags == u->fragments)
129 pa_log_debug(__FILE__": WaveOut underflow!");
130
131 while (free_frags) {
132 hdr = &u->ohdrs[u->cur_ohdr];
133 if (hdr->dwFlags & WHDR_PREPARED)
134 waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
135
136 remain = u->oremain;
137 while (remain) {
138 cur_chunk = &memchunk;
139
140 if (pa_sink_render(u->sink, remain, cur_chunk) < 0) {
141 /*
142 * Don't fill with silence unless we're getting close to
143 * underflowing.
144 */
145 if (free_frags > u->fragments/2)
146 cur_chunk = &u->silence;
147 else {
148 EnterCriticalSection(&u->crit);
149
150 u->free_ofrags += free_frags;
151
152 LeaveCriticalSection(&u->crit);
153
154 u->oremain = remain;
155 return;
156 }
157 }
158
159 assert(cur_chunk->memblock);
160 assert(cur_chunk->memblock->data);
161 assert(cur_chunk->length);
162
163 memcpy(hdr->lpData + u->fragment_size - remain,
164 (char*)cur_chunk->memblock->data + cur_chunk->index,
165 (cur_chunk->length < remain)?cur_chunk->length:remain);
166
167 remain -= (cur_chunk->length < remain)?cur_chunk->length:remain;
168
169 if (cur_chunk != &u->silence) {
170 pa_memblock_unref(cur_chunk->memblock);
171 cur_chunk->memblock = NULL;
172 }
173 }
174
175 res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
176 if (res != MMSYSERR_NOERROR) {
177 pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d",
178 res);
179 }
180 res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
181 if (res != MMSYSERR_NOERROR) {
182 pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d",
183 res);
184 }
185
186 u->written_bytes += u->fragment_size;
187
188 free_frags--;
189 u->cur_ohdr++;
190 u->cur_ohdr %= u->fragments;
191 u->oremain = u->fragment_size;
192 }
193 }
194
195 static void do_read(struct userdata *u)
196 {
197 uint32_t free_frags;
198 pa_memchunk memchunk;
199 WAVEHDR *hdr;
200 MMRESULT res;
201
202 if (!u->source)
203 return;
204
205 EnterCriticalSection(&u->crit);
206
207 free_frags = u->free_ifrags;
208 u->free_ifrags = 0;
209
210 LeaveCriticalSection(&u->crit);
211
212 if (free_frags == u->fragments)
213 pa_log_debug(__FILE__": WaveIn overflow!");
214
215 while (free_frags) {
216 hdr = &u->ihdrs[u->cur_ihdr];
217 if (hdr->dwFlags & WHDR_PREPARED)
218 waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
219
220 if (hdr->dwBytesRecorded) {
221 memchunk.memblock = pa_memblock_new(hdr->dwBytesRecorded, u->core->memblock_stat);
222 assert(memchunk.memblock);
223
224 memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded);
225
226 memchunk.length = memchunk.memblock->length = hdr->dwBytesRecorded;
227 memchunk.index = 0;
228
229 pa_source_post(u->source, &memchunk);
230 pa_memblock_unref(memchunk.memblock);
231 }
232
233 res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
234 if (res != MMSYSERR_NOERROR) {
235 pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d",
236 res);
237 }
238 res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
239 if (res != MMSYSERR_NOERROR) {
240 pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d",
241 res);
242 }
243
244 free_frags--;
245 u->cur_ihdr++;
246 u->cur_ihdr %= u->fragments;
247 }
248 }
249
250 static void poll_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
251 struct userdata *u = userdata;
252 struct timeval ntv;
253
254 assert(u);
255
256 update_usage(u);
257
258 do_write(u);
259 do_read(u);
260
261 pa_gettimeofday(&ntv);
262 pa_timeval_add(&ntv, u->poll_timeout);
263
264 a->time_restart(e, &ntv);
265 }
266
267 static void defer_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
268 struct userdata *u = userdata;
269
270 assert(u);
271
272 a->defer_enable(e, 0);
273
274 do_write(u);
275 do_read(u);
276 }
277
278 static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
279 struct userdata *u = (struct userdata *)inst;
280
281 if (msg != WOM_DONE)
282 return;
283
284 EnterCriticalSection(&u->crit);
285
286 u->free_ofrags++;
287 assert(u->free_ofrags <= u->fragments);
288
289 LeaveCriticalSection(&u->crit);
290 }
291
292 static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
293 struct userdata *u = (struct userdata *)inst;
294
295 if (msg != WIM_DATA)
296 return;
297
298 EnterCriticalSection(&u->crit);
299
300 u->free_ifrags++;
301 assert(u->free_ifrags <= u->fragments);
302
303 LeaveCriticalSection(&u->crit);
304 }
305
306 static pa_usec_t sink_get_latency_cb(pa_sink *s) {
307 struct userdata *u = s->userdata;
308 uint32_t free_frags;
309 MMTIME mmt;
310 assert(s && u && u->sink);
311
312 memset(&mmt, 0, sizeof(mmt));
313 mmt.wType = TIME_BYTES;
314 if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
315 return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &s->sample_spec);
316 else {
317 EnterCriticalSection(&u->crit);
318
319 free_frags = u->free_ofrags;
320
321 LeaveCriticalSection(&u->crit);
322
323 return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size,
324 &s->sample_spec);
325 }
326 }
327
328 static pa_usec_t source_get_latency_cb(pa_source *s) {
329 pa_usec_t r = 0;
330 struct userdata *u = s->userdata;
331 uint32_t free_frags;
332 assert(s && u && u->sink);
333
334 EnterCriticalSection(&u->crit);
335
336 free_frags = u->free_ifrags;
337
338 LeaveCriticalSection(&u->crit);
339
340 r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec);
341
342 return r;
343 }
344
345 static void notify_sink_cb(pa_sink *s) {
346 struct userdata *u = s->userdata;
347 assert(u);
348
349 u->core->mainloop->defer_enable(u->defer, 1);
350 }
351
352 static void notify_source_cb(pa_source *s) {
353 struct userdata *u = s->userdata;
354 assert(u);
355
356 u->core->mainloop->defer_enable(u->defer, 1);
357 }
358
359 static int sink_get_hw_volume_cb(pa_sink *s) {
360 struct userdata *u = s->userdata;
361 DWORD vol;
362 pa_volume_t left, right;
363
364 if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
365 return -1;
366
367 left = (vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME;
368 right = ((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME;
369
370 /* Windows supports > 2 channels, except for volume control */
371 if (s->hw_volume.channels > 2)
372 pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, (left + right)/2);
373
374 s->hw_volume.values[0] = left;
375 if (s->hw_volume.channels > 1)
376 s->hw_volume.values[1] = right;
377
378 return 0;
379 }
380
381 static int sink_set_hw_volume_cb(pa_sink *s) {
382 struct userdata *u = s->userdata;
383 DWORD vol;
384
385 vol = s->hw_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM;
386 if (s->hw_volume.channels > 1)
387 vol |= (s->hw_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
388
389 if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
390 return -1;
391
392 return 0;
393 }
394
395 static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
396 wf->wFormatTag = WAVE_FORMAT_PCM;
397
398 if (ss->channels > 2) {
399 pa_log_error(__FILE__": ERROR: More than two channels not supported.");
400 return -1;
401 }
402
403 wf->nChannels = ss->channels;
404
405 switch (ss->rate) {
406 case 8000:
407 case 11025:
408 case 22005:
409 case 44100:
410 break;
411 default:
412 pa_log_error(__FILE__": ERROR: Unsupported sample rate.");
413 return -1;
414 }
415
416 wf->nSamplesPerSec = ss->rate;
417
418 if (ss->format == PA_SAMPLE_U8)
419 wf->wBitsPerSample = 8;
420 else if (ss->format == PA_SAMPLE_S16NE)
421 wf->wBitsPerSample = 16;
422 else {
423 pa_log_error(__FILE__": ERROR: Unsupported sample format.");
424 return -1;
425 }
426
427 wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
428 wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
429
430 wf->cbSize = 0;
431
432 return 0;
433 }
434
435 int pa__init(pa_core *c, pa_module*m) {
436 struct userdata *u = NULL;
437 HWAVEOUT hwo = INVALID_HANDLE_VALUE;
438 HWAVEIN hwi = INVALID_HANDLE_VALUE;
439 WAVEFORMATEX wf;
440 int nfrags, frag_size;
441 int record = 1, playback = 1;
442 pa_sample_spec ss;
443 pa_channel_map map;
444 pa_modargs *ma = NULL;
445 unsigned int i;
446 struct timeval tv;
447
448 assert(c && m);
449
450 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
451 pa_log(__FILE__": failed to parse module arguments.");
452 goto fail;
453 }
454
455 if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
456 pa_log(__FILE__": record= and playback= expect boolean argument.");
457 goto fail;
458 }
459
460 if (!playback && !record) {
461 pa_log(__FILE__": neither playback nor record enabled for device.");
462 goto fail;
463 }
464
465 nfrags = 5;
466 frag_size = 8192;
467 if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
468 pa_log(__FILE__": failed to parse fragments arguments");
469 goto fail;
470 }
471
472 ss = c->default_sample_spec;
473 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) {
474 pa_log(__FILE__": failed to parse sample specification");
475 goto fail;
476 }
477
478 if (ss_to_waveformat(&ss, &wf) < 0)
479 goto fail;
480
481 u = pa_xmalloc(sizeof(struct userdata));
482
483 if (record) {
484 if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
485 goto fail;
486 if (waveInStart(hwi) != MMSYSERR_NOERROR)
487 goto fail;
488 pa_log_debug(__FILE__": Opened waveIn subsystem.");
489 }
490
491 if (playback) {
492 if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
493 goto fail;
494 pa_log_debug(__FILE__": Opened waveOut subsystem.");
495 }
496
497 InitializeCriticalSection(&u->crit);
498
499 if (hwi != INVALID_HANDLE_VALUE) {
500 u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map);
501 assert(u->source);
502 u->source->userdata = u;
503 u->source->notify = notify_source_cb;
504 u->source->get_latency = source_get_latency_cb;
505 pa_source_set_owner(u->source, m);
506 u->source->description = pa_sprintf_malloc("Windows waveIn PCM");
507 } else
508 u->source = NULL;
509
510 if (hwo != INVALID_HANDLE_VALUE) {
511 u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map);
512 assert(u->sink);
513 u->sink->notify = notify_sink_cb;
514 u->sink->get_latency = sink_get_latency_cb;
515 u->sink->get_hw_volume = sink_get_hw_volume_cb;
516 u->sink->set_hw_volume = sink_set_hw_volume_cb;
517 u->sink->userdata = u;
518 pa_sink_set_owner(u->sink, m);
519 u->sink->description = pa_sprintf_malloc("Windows waveOut PCM");
520 } else
521 u->sink = NULL;
522
523 assert(u->source || u->sink);
524
525 u->core = c;
526 u->hwi = hwi;
527 u->hwo = hwo;
528
529 u->fragments = nfrags;
530 u->free_ifrags = u->fragments;
531 u->free_ofrags = u->fragments;
532 u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
533
534 u->written_bytes = 0;
535
536 u->oremain = u->fragment_size;
537
538 u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
539
540 pa_gettimeofday(&tv);
541 pa_timeval_add(&tv, u->poll_timeout);
542
543 u->event = c->mainloop->time_new(c->mainloop, &tv, poll_cb, u);
544 assert(u->event);
545
546 u->defer = c->mainloop->defer_new(c->mainloop, defer_cb, u);
547 assert(u->defer);
548 c->mainloop->defer_enable(u->defer, 0);
549
550 u->cur_ihdr = 0;
551 u->cur_ohdr = 0;
552 u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
553 assert(u->ihdrs);
554 u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
555 assert(u->ohdrs);
556 for (i = 0;i < u->fragments;i++) {
557 u->ihdrs[i].dwBufferLength = u->fragment_size;
558 u->ohdrs[i].dwBufferLength = u->fragment_size;
559 u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
560 assert(u->ihdrs);
561 u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
562 assert(u->ohdrs);
563 }
564
565 u->silence.length = u->fragment_size;
566 u->silence.memblock = pa_memblock_new(u->silence.length, u->core->memblock_stat);
567 assert(u->silence.memblock);
568 pa_silence_memblock(u->silence.memblock, &ss);
569 u->silence.index = 0;
570
571 u->module = m;
572 m->userdata = u;
573
574 pa_modargs_free(ma);
575
576 /* Read mixer settings */
577 if (u->sink)
578 sink_get_hw_volume_cb(u->sink);
579
580 return 0;
581
582 fail:
583 if (hwi != INVALID_HANDLE_VALUE)
584 waveInClose(hwi);
585
586 if (hwo != INVALID_HANDLE_VALUE)
587 waveOutClose(hwo);
588
589 if (u)
590 pa_xfree(u);
591
592 if (ma)
593 pa_modargs_free(ma);
594
595 return -1;
596 }
597
598 void pa__done(pa_core *c, pa_module*m) {
599 struct userdata *u;
600 unsigned int i;
601
602 assert(c && m);
603
604 if (!(u = m->userdata))
605 return;
606
607 if (u->event)
608 c->mainloop->time_free(u->event);
609
610 if (u->defer)
611 c->mainloop->defer_free(u->defer);
612
613 if (u->sink) {
614 pa_sink_disconnect(u->sink);
615 pa_sink_unref(u->sink);
616 }
617
618 if (u->source) {
619 pa_source_disconnect(u->source);
620 pa_source_unref(u->source);
621 }
622
623 if (u->hwi != INVALID_HANDLE_VALUE) {
624 waveInReset(u->hwi);
625 waveInClose(u->hwi);
626 }
627
628 if (u->hwo != INVALID_HANDLE_VALUE) {
629 waveOutReset(u->hwo);
630 waveOutClose(u->hwo);
631 }
632
633 for (i = 0;i < u->fragments;i++) {
634 pa_xfree(u->ihdrs[i].lpData);
635 pa_xfree(u->ohdrs[i].lpData);
636 }
637
638 pa_xfree(u->ihdrs);
639 pa_xfree(u->ohdrs);
640
641 DeleteCriticalSection(&u->crit);
642
643 pa_xfree(u);
644 }