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