echo-cancel-test: Enable debug log level
[platform/upstream/pulseaudio.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/xmalloc.h>
31 #include <pulse/timeval.h>
32
33 #include <pulsecore/sink.h>
34 #include <pulsecore/source.h>
35 #include <pulsecore/module.h>
36 #include <pulsecore/modargs.h>
37 #include <pulsecore/sample-util.h>
38 #include <pulsecore/core-util.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/thread.h>
41 #include <pulsecore/thread-mq.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     "device_name=<name of the device> "
53     "record=<enable source?> "
54     "playback=<enable sink?> "
55     "format=<sample format> "
56     "rate=<sample rate> "
57     "channels=<number of channels> "
58     "channel_map=<channel map> "
59     "fragments=<number of fragments> "
60     "fragment_size=<fragment size>");
61
62 #define DEFAULT_SINK_NAME "wave_output"
63 #define DEFAULT_SOURCE_NAME "wave_input"
64
65 #define WAVEOUT_MAX_VOLUME 0xFFFF
66
67 struct userdata {
68     pa_sink *sink;
69     pa_source *source;
70     pa_core *core;
71     pa_usec_t poll_timeout;
72
73     pa_thread *thread;
74     pa_thread_mq thread_mq;
75     pa_rtpoll *rtpoll;
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     "device_name",
99     "record",
100     "playback",
101     "fragments",
102     "fragment_size",
103     "format",
104     "rate",
105     "channels",
106     "channel_map",
107     NULL
108 };
109
110 static void do_write(struct userdata *u) {
111     uint32_t free_frags;
112     pa_memchunk memchunk;
113     WAVEHDR *hdr;
114     MMRESULT res;
115     void *p;
116
117     if (!u->sink)
118         return;
119
120     if (!PA_SINK_IS_LINKED(u->sink->state))
121         return;
122
123     EnterCriticalSection(&u->crit);
124     free_frags = u->free_ofrags;
125     LeaveCriticalSection(&u->crit);
126
127     if (!u->sink_underflow && (free_frags == u->fragments))
128         pa_log_debug("WaveOut underflow!");
129
130     while (free_frags) {
131         hdr = &u->ohdrs[u->cur_ohdr];
132         if (hdr->dwFlags & WHDR_PREPARED)
133             waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
134
135         hdr->dwBufferLength = 0;
136         while (hdr->dwBufferLength < u->fragment_size) {
137             size_t len;
138
139             len = u->fragment_size - hdr->dwBufferLength;
140
141             pa_sink_render(u->sink, len, &memchunk);
142
143             pa_assert(memchunk.memblock);
144             pa_assert(memchunk.length);
145
146             if (memchunk.length < len)
147                 len = memchunk.length;
148
149             p = pa_memblock_acquire(memchunk.memblock);
150             memcpy(hdr->lpData + hdr->dwBufferLength, (char*) p + memchunk.index, len);
151             pa_memblock_release(memchunk.memblock);
152
153             hdr->dwBufferLength += len;
154
155             pa_memblock_unref(memchunk.memblock);
156             memchunk.memblock = NULL;
157         }
158
159         /* Underflow detection */
160         if (hdr->dwBufferLength == 0) {
161             u->sink_underflow = 1;
162             break;
163         }
164         u->sink_underflow = 0;
165
166         res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
167         if (res != MMSYSERR_NOERROR)
168             pa_log_error("Unable to prepare waveOut block: %d", res);
169
170         res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
171         if (res != MMSYSERR_NOERROR)
172             pa_log_error("Unable to write waveOut block: %d", res);
173
174         u->written_bytes += hdr->dwBufferLength;
175
176         EnterCriticalSection(&u->crit);
177         u->free_ofrags--;
178         LeaveCriticalSection(&u->crit);
179
180         free_frags--;
181         u->cur_ohdr++;
182         u->cur_ohdr %= u->fragments;
183     }
184 }
185
186 static void do_read(struct userdata *u) {
187     uint32_t free_frags;
188     pa_memchunk memchunk;
189     WAVEHDR *hdr;
190     MMRESULT res;
191     void *p;
192
193     if (!u->source)
194         return;
195
196     if (!PA_SOURCE_IS_LINKED(u->source->state))
197         return;
198
199     EnterCriticalSection(&u->crit);
200     free_frags = u->free_ifrags;
201     u->free_ifrags = 0;
202     LeaveCriticalSection(&u->crit);
203
204     if (free_frags == u->fragments)
205         pa_log_debug("WaveIn overflow!");
206
207     while (free_frags) {
208         hdr = &u->ihdrs[u->cur_ihdr];
209         if (hdr->dwFlags & WHDR_PREPARED)
210             waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
211
212         if (hdr->dwBytesRecorded) {
213             memchunk.memblock = pa_memblock_new(u->core->mempool, hdr->dwBytesRecorded);
214             pa_assert(memchunk.memblock);
215
216             p = pa_memblock_acquire(memchunk.memblock);
217             memcpy((char*) p, hdr->lpData, hdr->dwBytesRecorded);
218             pa_memblock_release(memchunk.memblock);
219
220             memchunk.length = hdr->dwBytesRecorded;
221             memchunk.index = 0;
222
223             pa_source_post(u->source, &memchunk);
224             pa_memblock_unref(memchunk.memblock);
225         }
226
227         res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
228         if (res != MMSYSERR_NOERROR)
229             pa_log_error("Unable to prepare waveIn block: %d", res);
230
231         res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
232         if (res != MMSYSERR_NOERROR)
233             pa_log_error("Unable to add waveIn block: %d", res);
234
235         free_frags--;
236         u->cur_ihdr++;
237         u->cur_ihdr %= u->fragments;
238     }
239 }
240
241 static void thread_func(void *userdata) {
242     struct userdata *u = userdata;
243
244     pa_assert(u);
245     pa_assert(u->sink || u->source);
246
247     pa_log_debug("Thread starting up");
248
249     if (u->core->realtime_scheduling)
250         pa_make_realtime(u->core->realtime_priority);
251
252     pa_thread_mq_install(&u->thread_mq);
253
254     for (;;) {
255         int ret;
256         pa_bool_t need_timer = FALSE;
257
258         if (u->sink) {
259             if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
260                 pa_sink_process_rewind(u->sink, 0);
261
262             if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
263                 do_write(u);
264                 need_timer = TRUE;
265             }
266         }
267
268         if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
269             do_read(u);
270             need_timer = TRUE;
271         }
272
273         if (need_timer)
274             pa_rtpoll_set_timer_relative(u->rtpoll, u->poll_timeout);
275         else
276             pa_rtpoll_set_timer_disabled(u->rtpoll);
277
278         /* Hmm, nothing to do. Let's sleep */
279         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
280             goto fail;
281
282         if (ret == 0)
283             goto finish;
284     }
285
286 fail:
287     /* If this was no regular exit from the loop we have to continue
288      * processing messages until we received PA_MESSAGE_SHUTDOWN */
289     pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
290     pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
291
292 finish:
293     pa_log_debug("Thread shutting down");
294 }
295
296 static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
297     struct userdata *u = (struct userdata*) inst;
298
299     if (msg == WOM_OPEN)
300         pa_log_debug("WaveOut subsystem opened.");
301     if (msg == WOM_CLOSE)
302         pa_log_debug("WaveOut subsystem closed.");
303     if (msg != WOM_DONE)
304         return;
305
306     EnterCriticalSection(&u->crit);
307     u->free_ofrags++;
308     pa_assert(u->free_ofrags <= u->fragments);
309     LeaveCriticalSection(&u->crit);
310 }
311
312 static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
313     struct userdata *u = (struct userdata*) inst;
314
315     if (msg == WIM_OPEN)
316         pa_log_debug("WaveIn subsystem opened.");
317     if (msg == WIM_CLOSE)
318         pa_log_debug("WaveIn subsystem closed.");
319     if (msg != WIM_DATA)
320         return;
321
322     EnterCriticalSection(&u->crit);
323     u->free_ifrags++;
324     pa_assert(u->free_ifrags <= u->fragments);
325     LeaveCriticalSection(&u->crit);
326 }
327
328 static pa_usec_t sink_get_latency(struct userdata *u) {
329     uint32_t free_frags;
330     MMTIME mmt;
331     pa_assert(u);
332     pa_assert(u->sink);
333
334     memset(&mmt, 0, sizeof(mmt));
335     mmt.wType = TIME_BYTES;
336     if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
337         return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &u->sink->sample_spec);
338     else {
339         EnterCriticalSection(&u->crit);
340         free_frags = u->free_ofrags;
341         LeaveCriticalSection(&u->crit);
342
343         return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size, &u->sink->sample_spec);
344     }
345 }
346
347 static pa_usec_t source_get_latency(struct userdata *u) {
348     pa_usec_t r = 0;
349     uint32_t free_frags;
350     pa_assert(u);
351     pa_assert(u->source);
352
353     EnterCriticalSection(&u->crit);
354     free_frags = u->free_ifrags;
355     LeaveCriticalSection(&u->crit);
356
357     r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &u->source->sample_spec);
358
359     return r;
360 }
361
362 static int process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
363     struct userdata *u;
364
365     if (pa_sink_isinstance(o)) {
366         u = PA_SINK(o)->userdata;
367
368         switch (code) {
369
370             case PA_SINK_MESSAGE_GET_LATENCY: {
371                 pa_usec_t r = 0;
372                 if (u->hwo)
373                     r = sink_get_latency(u);
374                 *((pa_usec_t*) data) = r;
375                 return 0;
376             }
377
378         }
379
380         return pa_sink_process_msg(o, code, data, offset, chunk);
381     }
382
383     if (pa_source_isinstance(o)) {
384         u = PA_SOURCE(o)->userdata;
385
386         switch (code) {
387
388             case PA_SOURCE_MESSAGE_GET_LATENCY: {
389                 pa_usec_t r = 0;
390                 if (u->hwi)
391                     r = source_get_latency(u);
392                 *((pa_usec_t*) data) = r;
393                 return 0;
394             }
395
396         }
397
398         return pa_source_process_msg(o, code, data, offset, chunk);
399     }
400
401     return -1;
402 }
403
404 static void sink_get_volume_cb(pa_sink *s) {
405     struct userdata *u = s->userdata;
406     WAVEOUTCAPS caps;
407     DWORD vol;
408     pa_volume_t left, right;
409
410     if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
411         return;
412     if (!(caps.dwSupport & WAVECAPS_VOLUME))
413         return;
414
415     if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
416         return;
417
418     left = PA_CLAMP_VOLUME((vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
419     if (caps.dwSupport & WAVECAPS_LRVOLUME)
420         right = PA_CLAMP_VOLUME(((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
421     else
422         right = left;
423
424     /* Windows supports > 2 channels, except for volume control */
425     if (s->real_volume.channels > 2)
426         pa_cvolume_set(&s->real_volume, s->real_volume.channels, (left + right)/2);
427
428     s->real_volume.values[0] = left;
429     if (s->real_volume.channels > 1)
430         s->real_volume.values[1] = right;
431 }
432
433 static void sink_set_volume_cb(pa_sink *s) {
434     struct userdata *u = s->userdata;
435     WAVEOUTCAPS caps;
436     DWORD vol;
437
438     if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
439         return;
440     if (!(caps.dwSupport & WAVECAPS_VOLUME))
441         return;
442
443     if (s->real_volume.channels == 2 && caps.dwSupport & WAVECAPS_LRVOLUME) {
444         vol = (s->real_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
445             | (s->real_volume.values[1] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
446     } else {
447         vol = (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
448             | (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
449     }
450
451     if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
452         return;
453 }
454
455 static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
456     wf->wFormatTag = WAVE_FORMAT_PCM;
457
458     if (ss->channels > 2) {
459         pa_log_error("More than two channels not supported.");
460         return -1;
461     }
462
463     wf->nChannels = ss->channels;
464
465     wf->nSamplesPerSec = ss->rate;
466
467     if (ss->format == PA_SAMPLE_U8)
468         wf->wBitsPerSample = 8;
469     else if (ss->format == PA_SAMPLE_S16NE)
470         wf->wBitsPerSample = 16;
471     else {
472         pa_log_error("Unsupported sample format, only u8 and s16 are supported.");
473         return -1;
474     }
475
476     wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
477     wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
478
479     wf->cbSize = 0;
480
481     return 0;
482 }
483
484 int pa__get_n_used(pa_module *m) {
485     struct userdata *u;
486     pa_assert(m);
487     pa_assert(m->userdata);
488     u = (struct userdata*) m->userdata;
489
490     return (u->sink ? pa_sink_used_by(u->sink) : 0) +
491            (u->source ? pa_source_used_by(u->source) : 0);
492 }
493
494 int pa__init(pa_module *m) {
495     struct userdata *u = NULL;
496     HWAVEOUT hwo = INVALID_HANDLE_VALUE;
497     HWAVEIN hwi = INVALID_HANDLE_VALUE;
498     WAVEFORMATEX wf;
499     WAVEOUTCAPS pwoc;
500     MMRESULT result;
501     int nfrags, frag_size;
502     pa_bool_t record = TRUE, playback = TRUE;
503     unsigned int device;
504     pa_sample_spec ss;
505     pa_channel_map map;
506     pa_modargs *ma = NULL;
507     const char *device_name = NULL;
508     unsigned int i;
509
510     pa_assert(m);
511     pa_assert(m->core);
512
513     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
514         pa_log("failed to parse module arguments.");
515         goto fail;
516     }
517
518     if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
519         pa_log("record= and playback= expect boolean argument.");
520         goto fail;
521     }
522
523     if (!playback && !record) {
524         pa_log("neither playback nor record enabled for device.");
525         goto fail;
526     }
527
528     /* Set the device to be opened.  If set device_name is used,
529      * else device if set and lastly WAVE_MAPPER is the default */
530     device = WAVE_MAPPER;
531     if (pa_modargs_get_value_u32(ma, "device", &device) < 0) {
532         pa_log("failed to parse device argument");
533         goto fail;
534     }
535     if ((device_name = pa_modargs_get_value(ma, "device_name", NULL)) != NULL) {
536         unsigned int num_devices = waveOutGetNumDevs();
537         for (i = 0; i < num_devices; i++) {
538             if (waveOutGetDevCaps(i, &pwoc, sizeof(pwoc)) == MMSYSERR_NOERROR)
539                 if (_stricmp(device_name, pwoc.szPname) == 0)
540                     break;
541         }
542         if (i < num_devices)
543             device = i;
544         else {
545             pa_log("device not found: %s", device_name);
546             goto fail;
547         }
548     }
549     if (waveOutGetDevCaps(device, &pwoc, sizeof(pwoc)) == MMSYSERR_NOERROR)
550         device_name = pwoc.szPname;
551     else
552         device_name = "unknown";
553
554     nfrags = 5;
555     frag_size = 8192;
556     if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
557         pa_log("failed to parse fragments arguments");
558         goto fail;
559     }
560
561     ss = m->core->default_sample_spec;
562     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) {
563         pa_log("failed to parse sample specification");
564         goto fail;
565     }
566
567     if (ss_to_waveformat(&ss, &wf) < 0)
568         goto fail;
569
570     u = pa_xmalloc(sizeof(struct userdata));
571
572     if (record) {
573         result = waveInOpen(&hwi, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
574         if (result != MMSYSERR_NOERROR) {
575             pa_log_warn("Sample spec not supported by WaveIn, falling back to default sample rate.");
576             ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
577         }
578         result = waveInOpen(&hwi, device, &wf, (DWORD_PTR) chunk_ready_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
579         if (result != MMSYSERR_NOERROR) {
580             char errortext[MAXERRORLENGTH];
581             pa_log("Failed to open WaveIn.");
582             if (waveInGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
583                 pa_log("Error: %s", errortext);
584             goto fail;
585         }
586         if (waveInStart(hwi) != MMSYSERR_NOERROR) {
587             pa_log("failed to start waveIn");
588             goto fail;
589         }
590     }
591
592     if (playback) {
593         result = waveOutOpen(&hwo, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
594         if (result != MMSYSERR_NOERROR) {
595             pa_log_warn("Sample spec not supported by WaveOut, falling back to default sample rate.");
596             ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
597         }
598         result = waveOutOpen(&hwo, device, &wf, (DWORD_PTR) chunk_done_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
599         if (result != MMSYSERR_NOERROR) {
600             char errortext[MAXERRORLENGTH];
601             pa_log("Failed to open WaveOut.");
602             if (waveOutGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
603                 pa_log("Error: %s", errortext);
604             goto fail;
605         }
606     }
607
608     InitializeCriticalSection(&u->crit);
609
610     if (hwi != INVALID_HANDLE_VALUE) {
611         char *description = pa_sprintf_malloc("WaveIn on %s", device_name);
612         pa_source_new_data data;
613         pa_source_new_data_init(&data);
614         data.driver = __FILE__;
615         data.module = m;
616         pa_source_new_data_set_sample_spec(&data, &ss);
617         pa_source_new_data_set_channel_map(&data, &map);
618         pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
619         u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
620         pa_source_new_data_done(&data);
621
622         pa_assert(u->source);
623         u->source->userdata = u;
624         pa_source_set_description(u->source, description);
625         u->source->parent.process_msg = process_msg;
626         pa_xfree(description);
627     } else
628         u->source = NULL;
629
630     if (hwo != INVALID_HANDLE_VALUE) {
631         char *description = pa_sprintf_malloc("WaveOut on %s", device_name);
632         pa_sink_new_data data;
633         pa_sink_new_data_init(&data);
634         data.driver = __FILE__;
635         data.module = m;
636         pa_sink_new_data_set_sample_spec(&data, &ss);
637         pa_sink_new_data_set_channel_map(&data, &map);
638         pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
639         u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
640         pa_sink_new_data_done(&data);
641
642         pa_assert(u->sink);
643         pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
644         pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
645         u->sink->userdata = u;
646         pa_sink_set_description(u->sink, description);
647         u->sink->parent.process_msg = process_msg;
648         pa_xfree(description);
649     } else
650         u->sink = NULL;
651
652     pa_assert(u->source || u->sink);
653     pa_modargs_free(ma);
654
655     u->core = m->core;
656     u->hwi = hwi;
657     u->hwo = hwo;
658
659     u->fragments = nfrags;
660     u->free_ifrags = u->fragments;
661     u->free_ofrags = u->fragments;
662     u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
663
664     u->written_bytes = 0;
665     u->sink_underflow = 1;
666
667     u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
668     pa_log_debug("Poll timeout = %.1f ms", (double) u->poll_timeout / PA_USEC_PER_MSEC);
669
670     u->cur_ihdr = 0;
671     u->cur_ohdr = 0;
672     u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
673     pa_assert(u->ihdrs);
674     u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
675     pa_assert(u->ohdrs);
676     for (i = 0; i < u->fragments; i++) {
677         u->ihdrs[i].dwBufferLength = u->fragment_size;
678         u->ohdrs[i].dwBufferLength = u->fragment_size;
679         u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
680         pa_assert(u->ihdrs);
681         u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
682         pa_assert(u->ohdrs);
683     }
684
685     u->module = m;
686     m->userdata = u;
687
688     /* Read mixer settings */
689     if (u->sink)
690         sink_get_volume_cb(u->sink);
691
692     u->rtpoll = pa_rtpoll_new();
693     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
694
695     if (u->sink) {
696         pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
697         pa_sink_set_rtpoll(u->sink, u->rtpoll);
698     }
699     if (u->source) {
700         pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
701         pa_source_set_rtpoll(u->source, u->rtpoll);
702     }
703
704     if (!(u->thread = pa_thread_new("waveout", thread_func, u))) {
705         pa_log("Failed to create thread.");
706         goto fail;
707     }
708
709     if (u->sink)
710         pa_sink_put(u->sink);
711     if (u->source)
712         pa_source_put(u->source);
713
714     return 0;
715
716 fail:
717     if (ma)
718         pa_modargs_free(ma);
719
720     pa__done(m);
721
722     return -1;
723 }
724
725 void pa__done(pa_module *m) {
726     struct userdata *u;
727     unsigned int i;
728
729     pa_assert(m);
730     pa_assert(m->core);
731
732     if (!(u = m->userdata))
733         return;
734
735     if (u->sink)
736         pa_sink_unlink(u->sink);
737     if (u->source)
738         pa_source_unlink(u->source);
739
740     pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
741     if (u->thread)
742         pa_thread_free(u->thread);
743     pa_thread_mq_done(&u->thread_mq);
744
745     if (u->sink)
746         pa_sink_unref(u->sink);
747     if (u->source)
748         pa_source_unref(u->source);
749
750     if (u->rtpoll)
751         pa_rtpoll_free(u->rtpoll);
752
753     if (u->hwi != INVALID_HANDLE_VALUE) {
754         waveInReset(u->hwi);
755         waveInClose(u->hwi);
756     }
757
758     if (u->hwo != INVALID_HANDLE_VALUE) {
759         waveOutReset(u->hwo);
760         waveOutClose(u->hwo);
761     }
762
763     for (i = 0; i < u->fragments; i++) {
764         pa_xfree(u->ihdrs[i].lpData);
765         pa_xfree(u->ohdrs[i].lpData);
766     }
767
768     pa_xfree(u->ihdrs);
769     pa_xfree(u->ohdrs);
770
771     DeleteCriticalSection(&u->crit);
772
773     pa_xfree(u);
774 }