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
44PA_MODULE_AUTHOR("Pierre Ossman");
45PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source");
46PA_MODULE_VERSION(PACKAGE_VERSION);
47PA_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
70struct 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
97static 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
117static 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
193static 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
248static 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
293fail:
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
299finish:
300    pa_log_debug("Thread shutting down");
301}
302
303static 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
319static 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
335static 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
354static 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
369static 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
411static 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
440static 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
462static 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
514static 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
556int 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
566int 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
824fail:
825    if (ma)
826        pa_modargs_free(ma);
827
828    pa__done(m);
829
830    return -1;
831}
832
833void 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