Revert "pacat: Don't use any buffer attr if we don't set any latency/process time...
[pulseaudio-mirror.git] / src / modules / module-waveout.c
blobd1b9f2ffb83a2ea2f4ac1505e23a89b49a33d281
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>
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>
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)
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>")
61 #define DEFAULT_SINK_NAME "wave_output"
62 #define DEFAULT_SOURCE_NAME "wave_input"
64 #define WAVEOUT_MAX_VOLUME 0xFFFF
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;
74 uint32_t fragments, fragment_size;
76 uint32_t free_ofrags, free_ifrags;
78 DWORD written_bytes;
79 int sink_underflow;
81 int cur_ohdr, cur_ihdr;
82 WAVEHDR *ohdrs, *ihdrs;
84 HWAVEOUT hwo;
85 HWAVEIN hwi;
86 pa_module *module;
88 CRITICAL_SECTION crit;
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
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));
112 static void do_write(struct userdata *u)
114 uint32_t free_frags;
115 pa_memchunk memchunk;
116 WAVEHDR *hdr;
117 MMRESULT res;
119 if (!u->sink)
120 return;
122 EnterCriticalSection(&u->crit);
123 free_frags = u->free_ofrags;
124 LeaveCriticalSection(&u->crit);
126 if (!u->sink_underflow && (free_frags == u->fragments))
127 pa_log_debug("WaveOut underflow!");
129 while (free_frags) {
130 hdr = &u->ohdrs[u->cur_ohdr];
131 if (hdr->dwFlags & WHDR_PREPARED)
132 waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
134 hdr->dwBufferLength = 0;
135 while (hdr->dwBufferLength < u->fragment_size) {
136 size_t len;
138 len = u->fragment_size - hdr->dwBufferLength;
140 if (pa_sink_render(u->sink, len, &memchunk) < 0)
141 break;
143 assert(memchunk.memblock);
144 assert(memchunk.memblock->data);
145 assert(memchunk.length);
147 if (memchunk.length < len)
148 len = memchunk.length;
150 memcpy(hdr->lpData + hdr->dwBufferLength,
151 (char*)memchunk.memblock->data + memchunk.index, len);
153 hdr->dwBufferLength += len;
155 pa_memblock_unref(memchunk.memblock);
156 memchunk.memblock = NULL;
159 /* Insufficient data in sink buffer? */
160 if (hdr->dwBufferLength == 0) {
161 u->sink_underflow = 1;
162 break;
165 u->sink_underflow = 0;
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);
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);
178 u->written_bytes += hdr->dwBufferLength;
180 EnterCriticalSection(&u->crit);
181 u->free_ofrags--;
182 LeaveCriticalSection(&u->crit);
184 free_frags--;
185 u->cur_ohdr++;
186 u->cur_ohdr %= u->fragments;
190 static void do_read(struct userdata *u)
192 uint32_t free_frags;
193 pa_memchunk memchunk;
194 WAVEHDR *hdr;
195 MMRESULT res;
197 if (!u->source)
198 return;
200 EnterCriticalSection(&u->crit);
202 free_frags = u->free_ifrags;
203 u->free_ifrags = 0;
205 LeaveCriticalSection(&u->crit);
207 if (free_frags == u->fragments)
208 pa_log_debug("WaveIn overflow!");
210 while (free_frags) {
211 hdr = &u->ihdrs[u->cur_ihdr];
212 if (hdr->dwFlags & WHDR_PREPARED)
213 waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
215 if (hdr->dwBytesRecorded) {
216 memchunk.memblock = pa_memblock_new(u->core->mempool, hdr->dwBytesRecorded);
217 assert(memchunk.memblock);
219 memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded);
221 memchunk.length = memchunk.memblock->length = hdr->dwBytesRecorded;
222 memchunk.index = 0;
224 pa_source_post(u->source, &memchunk);
225 pa_memblock_unref(memchunk.memblock);
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);
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);
239 free_frags--;
240 u->cur_ihdr++;
241 u->cur_ihdr %= u->fragments;
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;
249 assert(u);
251 update_usage(u);
253 do_write(u);
254 do_read(u);
256 pa_gettimeofday(&ntv);
257 pa_timeval_add(&ntv, u->poll_timeout);
259 a->rtclock_time_restart(e, &ntv);
262 static void defer_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
263 struct userdata *u = userdata;
265 assert(u);
267 a->defer_enable(e, 0);
269 do_write(u);
270 do_read(u);
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;
276 if (msg != WOM_DONE)
277 return;
279 EnterCriticalSection(&u->crit);
281 u->free_ofrags++;
282 assert(u->free_ofrags <= u->fragments);
284 LeaveCriticalSection(&u->crit);
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;
290 if (msg != WIM_DATA)
291 return;
293 EnterCriticalSection(&u->crit);
295 u->free_ifrags++;
296 assert(u->free_ifrags <= u->fragments);
298 LeaveCriticalSection(&u->crit);
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);
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);
314 free_frags = u->free_ofrags;
316 LeaveCriticalSection(&u->crit);
318 return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size,
319 &s->sample_spec);
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);
329 EnterCriticalSection(&u->crit);
331 free_frags = u->free_ifrags;
333 LeaveCriticalSection(&u->crit);
335 r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec);
337 return r;
340 static void notify_sink_cb(pa_sink *s) {
341 struct userdata *u = s->userdata;
342 assert(u);
344 u->core->mainloop->defer_enable(u->defer, 1);
347 static void notify_source_cb(pa_source *s) {
348 struct userdata *u = s->userdata;
349 assert(u);
351 u->core->mainloop->defer_enable(u->defer, 1);
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;
359 if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
360 return -1;
362 left = (vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME;
363 right = ((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME;
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);
369 s->hw_volume.values[0] = left;
370 if (s->hw_volume.channels > 1)
371 s->hw_volume.values[1] = right;
373 return 0;
376 static int sink_set_hw_volume_cb(pa_sink *s) {
377 struct userdata *u = s->userdata;
378 DWORD vol;
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;
384 if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
385 return -1;
387 return 0;
390 static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
391 wf->wFormatTag = WAVE_FORMAT_PCM;
393 if (ss->channels > 2) {
394 pa_log_error("ERROR: More than two channels not supported.");
395 return -1;
398 wf->nChannels = ss->channels;
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;
411 wf->nSamplesPerSec = ss->rate;
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;
422 wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
423 wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
425 wf->cbSize = 0;
427 return 0;
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;
444 assert(c && m);
446 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
447 pa_log("failed to parse module arguments.");
448 goto fail;
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;
456 if (!playback && !record) {
457 pa_log("neither playback nor record enabled for device.");
458 goto fail;
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;
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;
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;
480 if (ss_to_waveformat(&ss, &wf) < 0)
481 goto fail;
483 u = pa_xmalloc(sizeof(struct userdata));
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;
490 if (waveInStart(hwi) != MMSYSERR_NOERROR) {
491 pa_log("failed to start waveIn");
492 goto fail;
494 pa_log_debug("Opened waveIn subsystem.");
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;
502 pa_log_debug("Opened waveOut subsystem.");
505 InitializeCriticalSection(&u->crit);
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;
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;
533 assert(u->source || u->sink);
535 u->core = c;
536 u->hwi = hwi;
537 u->hwo = hwo;
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));
544 u->written_bytes = 0;
545 u->sink_underflow = 1;
547 u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
549 pa_gettimeofday(&tv);
550 pa_timeval_add(&tv, u->poll_timeout);
552 u->event = c->mainloop->rtclock_time_new(c->mainloop, &tv, poll_cb, u);
553 assert(u->event);
555 u->defer = c->mainloop->defer_new(c->mainloop, defer_cb, u);
556 assert(u->defer);
557 c->mainloop->defer_enable(u->defer, 0);
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);
574 u->module = m;
575 m->userdata = u;
577 pa_modargs_free(ma);
579 /* Read mixer settings */
580 if (u->sink)
581 sink_get_hw_volume_cb(u->sink);
583 return 0;
585 fail:
586 if (hwi != INVALID_HANDLE_VALUE)
587 waveInClose(hwi);
589 if (hwo != INVALID_HANDLE_VALUE)
590 waveOutClose(hwo);
592 if (u)
593 pa_xfree(u);
595 if (ma)
596 pa_modargs_free(ma);
598 return -1;
601 void pa__done(pa_core *c, pa_module*m) {
602 struct userdata *u;
603 unsigned int i;
605 assert(c && m);
607 if (!(u = m->userdata))
608 return;
610 if (u->event)
611 c->mainloop->time_free(u->event);
613 if (u->defer)
614 c->mainloop->defer_free(u->defer);
616 if (u->sink) {
617 pa_sink_disconnect(u->sink);
618 pa_sink_unref(u->sink);
621 if (u->source) {
622 pa_source_disconnect(u->source);
623 pa_source_unref(u->source);
626 if (u->hwi != INVALID_HANDLE_VALUE) {
627 waveInReset(u->hwi);
628 waveInClose(u->hwi);
631 if (u->hwo != INVALID_HANDLE_VALUE) {
632 waveOutReset(u->hwo);
633 waveOutClose(u->hwo);
636 for (i = 0;i < u->fragments;i++) {
637 pa_xfree(u->ihdrs[i].lpData);
638 pa_xfree(u->ohdrs[i].lpData);
641 pa_xfree(u->ihdrs);
642 pa_xfree(u->ohdrs);
644 DeleteCriticalSection(&u->crit);
646 pa_xfree(u);