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