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