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