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