build-system: move x11 and jack modules into subdirectories
[profile/ivi/pulseaudio-panda.git] / 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.1 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 }