3 #include "qemu-common.h"
4 #include "sysemu/sysemu.h"
7 #define AUDIO_CAP "winwave"
13 #include "audio_win_int.h"
37 CRITICAL_SECTION crit_sect;
50 CRITICAL_SECTION crit_sect;
53 static void winwave_log_mmresult (MMRESULT mr)
55 const char *str = "BUG";
58 case MMSYSERR_NOERROR:
62 case MMSYSERR_INVALHANDLE:
63 str = "Specified device handle is invalid";
66 case MMSYSERR_BADDEVICEID:
67 str = "Specified device id is out of range";
70 case MMSYSERR_NODRIVER:
71 str = "No device driver is present";
75 str = "Unable to allocate or lock memory";
79 str = "Device is synchronous but waveOutOpen was called "
80 "without using the WINWAVE_ALLOWSYNC flag";
83 case WAVERR_UNPREPARED:
84 str = "The data block pointed to by the pwh parameter "
85 "hasn't been prepared";
88 case WAVERR_STILLPLAYING:
89 str = "There are still buffers in the queue";
93 dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
97 dolog ("Reason: %s\n", str);
100 static void GCC_FMT_ATTR (2, 3) winwave_logerr (
109 AUD_vlog (AUDIO_CAP, fmt, ap);
112 AUD_log (NULL, " failed\n");
113 winwave_log_mmresult (mr);
116 static void winwave_anal_close_out (WaveVoiceOut *wave)
120 mr = waveOutClose (wave->hwo);
121 if (mr != MMSYSERR_NOERROR) {
122 winwave_logerr (mr, "waveOutClose");
127 static void CALLBACK winwave_callback_out (
130 DWORD_PTR dwInstance,
135 WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance;
140 WAVEHDR *h = (WAVEHDR *) dwParam1;
143 EnterCriticalSection (&wave->crit_sect);
145 wave->avail += conf.dac_samples;
147 LeaveCriticalSection (&wave->crit_sect);
148 if (wave->hw.poll_mode) {
149 if (!SetEvent (wave->event)) {
150 dolog ("DAC SetEvent failed %lx\n", GetLastError ());
162 dolog ("unknown wave out callback msg %x\n", msg);
166 static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
174 wave = (WaveVoiceOut *) hw;
176 InitializeCriticalSection (&wave->crit_sect);
178 err = waveformat_from_audio_settings (&wfx, as);
183 mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx,
184 (DWORD_PTR) winwave_callback_out,
185 (DWORD_PTR) wave, CALLBACK_FUNCTION);
186 if (mr != MMSYSERR_NOERROR) {
187 winwave_logerr (mr, "waveOutOpen");
191 wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
192 sizeof (*wave->hdrs));
197 audio_pcm_init_info (&hw->info, as);
198 hw->samples = conf.dac_samples * conf.dac_headers;
199 wave->avail = hw->samples;
201 wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples,
202 conf.dac_headers << hw->info.shift);
203 if (!wave->pcm_buf) {
207 for (i = 0; i < conf.dac_headers; ++i) {
208 WAVEHDR *h = &wave->hdrs[i];
211 h->dwBufferLength = conf.dac_samples << hw->info.shift;
212 h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
215 mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
216 if (mr != MMSYSERR_NOERROR) {
217 winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
225 g_free (wave->pcm_buf);
229 winwave_anal_close_out (wave);
235 static int winwave_write (SWVoiceOut *sw, void *buf, int len)
237 return audio_pcm_sw_write (sw, buf, len);
240 static int winwave_run_out (HWVoiceOut *hw, int live)
242 WaveVoiceOut *wave = (WaveVoiceOut *) hw;
246 EnterCriticalSection (&wave->crit_sect);
248 decr = audio_MIN (live, wave->avail);
249 decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending);
250 wave->pending += decr;
253 LeaveCriticalSection (&wave->crit_sect);
255 doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
256 if (doreset && !ResetEvent (wave->event)) {
257 dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
260 while (wave->pending >= conf.dac_samples) {
262 WAVEHDR *h = &wave->hdrs[wave->curhdr];
265 mr = waveOutWrite (wave->hwo, h, sizeof (*h));
266 if (mr != MMSYSERR_NOERROR) {
267 winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr);
271 wave->pending -= conf.dac_samples;
272 wave->curhdr = (wave->curhdr + 1) % conf.dac_headers;
278 static void winwave_poll (void *opaque)
281 audio_run ("winwave_poll");
284 static void winwave_fini_out (HWVoiceOut *hw)
288 WaveVoiceOut *wave = (WaveVoiceOut *) hw;
290 mr = waveOutReset (wave->hwo);
291 if (mr != MMSYSERR_NOERROR) {
292 winwave_logerr (mr, "waveOutReset");
295 for (i = 0; i < conf.dac_headers; ++i) {
296 mr = waveOutUnprepareHeader (wave->hwo, &wave->hdrs[i],
297 sizeof (wave->hdrs[i]));
298 if (mr != MMSYSERR_NOERROR) {
299 winwave_logerr (mr, "waveOutUnprepareHeader(%d)", i);
303 winwave_anal_close_out (wave);
306 qemu_del_wait_object (wave->event, winwave_poll, wave);
307 if (!CloseHandle (wave->event)) {
308 dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
313 g_free (wave->pcm_buf);
314 wave->pcm_buf = NULL;
320 static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
323 WaveVoiceOut *wave = (WaveVoiceOut *) hw;
332 poll_mode = va_arg (ap, int);
335 if (poll_mode && !wave->event) {
336 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
338 dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
346 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
347 hw->poll_mode = (ret == 0);
358 mr = waveOutReset (wave->hwo);
359 if (mr != MMSYSERR_NOERROR) {
360 winwave_logerr (mr, "waveOutReset");
367 qemu_del_wait_object (wave->event, winwave_poll, wave);
374 static void winwave_anal_close_in (WaveVoiceIn *wave)
378 mr = waveInClose (wave->hwi);
379 if (mr != MMSYSERR_NOERROR) {
380 winwave_logerr (mr, "waveInClose");
385 static void CALLBACK winwave_callback_in (
388 DWORD_PTR dwInstance,
393 WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance;
398 WAVEHDR *h = (WAVEHDR *) dwParam1;
401 EnterCriticalSection (&wave->crit_sect);
403 wave->avail += conf.adc_samples;
405 LeaveCriticalSection (&wave->crit_sect);
406 if (wave->hw.poll_mode) {
407 if (!SetEvent (wave->event)) {
408 dolog ("ADC SetEvent failed %lx\n", GetLastError ());
420 dolog ("unknown wave in callback msg %x\n", msg);
424 static void winwave_add_buffers (WaveVoiceIn *wave, int samples)
428 doreset = wave->hw.poll_mode && (samples >= conf.adc_samples);
429 if (doreset && !ResetEvent (wave->event)) {
430 dolog ("ADC ResetEvent failed %lx\n", GetLastError ());
433 while (samples >= conf.adc_samples) {
435 WAVEHDR *h = &wave->hdrs[wave->curhdr];
438 mr = waveInAddBuffer (wave->hwi, h, sizeof (*h));
439 if (mr != MMSYSERR_NOERROR) {
440 winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr);
442 wave->curhdr = (wave->curhdr + 1) % conf.adc_headers;
443 samples -= conf.adc_samples;
447 static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as)
455 wave = (WaveVoiceIn *) hw;
457 InitializeCriticalSection (&wave->crit_sect);
459 err = waveformat_from_audio_settings (&wfx, as);
464 mr = waveInOpen (&wave->hwi, WAVE_MAPPER, &wfx,
465 (DWORD_PTR) winwave_callback_in,
466 (DWORD_PTR) wave, CALLBACK_FUNCTION);
467 if (mr != MMSYSERR_NOERROR) {
468 winwave_logerr (mr, "waveInOpen");
472 wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
473 sizeof (*wave->hdrs));
478 audio_pcm_init_info (&hw->info, as);
479 hw->samples = conf.adc_samples * conf.adc_headers;
482 wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples,
483 conf.adc_headers << hw->info.shift);
484 if (!wave->pcm_buf) {
488 for (i = 0; i < conf.adc_headers; ++i) {
489 WAVEHDR *h = &wave->hdrs[i];
492 h->dwBufferLength = conf.adc_samples << hw->info.shift;
493 h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
496 mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h));
497 if (mr != MMSYSERR_NOERROR) {
498 winwave_logerr (mr, "waveInPrepareHeader(%d)", i);
504 winwave_add_buffers (wave, hw->samples);
508 g_free (wave->pcm_buf);
512 winwave_anal_close_in (wave);
518 static void winwave_fini_in (HWVoiceIn *hw)
522 WaveVoiceIn *wave = (WaveVoiceIn *) hw;
524 mr = waveInReset (wave->hwi);
525 if (mr != MMSYSERR_NOERROR) {
526 winwave_logerr (mr, "waveInReset");
529 for (i = 0; i < conf.adc_headers; ++i) {
530 mr = waveInUnprepareHeader (wave->hwi, &wave->hdrs[i],
531 sizeof (wave->hdrs[i]));
532 if (mr != MMSYSERR_NOERROR) {
533 winwave_logerr (mr, "waveInUnprepareHeader(%d)", i);
537 winwave_anal_close_in (wave);
540 qemu_del_wait_object (wave->event, winwave_poll, wave);
541 if (!CloseHandle (wave->event)) {
542 dolog ("ADC CloseHandle failed %lx\n", GetLastError ());
547 g_free (wave->pcm_buf);
548 wave->pcm_buf = NULL;
554 static int winwave_run_in (HWVoiceIn *hw)
556 WaveVoiceIn *wave = (WaveVoiceIn *) hw;
557 int live = audio_pcm_hw_get_live_in (hw);
558 int dead = hw->samples - live;
565 EnterCriticalSection (&wave->crit_sect);
567 decr = audio_MIN (dead, wave->avail);
570 LeaveCriticalSection (&wave->crit_sect);
574 int left = hw->samples - hw->wpos;
575 int conv = audio_MIN (left, decr);
576 hw->conv (hw->conv_buf + hw->wpos,
577 advance (wave->pcm_buf, wave->rpos << hw->info.shift),
580 wave->rpos = (wave->rpos + conv) % hw->samples;
581 hw->wpos = (hw->wpos + conv) % hw->samples;
585 winwave_add_buffers (wave, ret);
589 static int winwave_read (SWVoiceIn *sw, void *buf, int size)
591 return audio_pcm_sw_read (sw, buf, size);
594 static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
597 WaveVoiceIn *wave = (WaveVoiceIn *) hw;
606 poll_mode = va_arg (ap, int);
609 if (poll_mode && !wave->event) {
610 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
612 dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
620 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
621 hw->poll_mode = (ret == 0);
627 mr = waveInStart (wave->hwi);
628 if (mr != MMSYSERR_NOERROR) {
629 winwave_logerr (mr, "waveInStart");
638 mr = waveInStop (wave->hwi);
639 if (mr != MMSYSERR_NOERROR) {
640 winwave_logerr (mr, "waveInStop");
647 qemu_del_wait_object (wave->event, winwave_poll, wave);
654 static void *winwave_audio_init (void)
659 static void winwave_audio_fini (void *opaque)
664 static struct audio_option winwave_options[] = {
666 .name = "DAC_HEADERS",
668 .valp = &conf.dac_headers,
669 .descr = "DAC number of headers",
672 .name = "DAC_SAMPLES",
674 .valp = &conf.dac_samples,
675 .descr = "DAC number of samples per header",
678 .name = "ADC_HEADERS",
680 .valp = &conf.adc_headers,
681 .descr = "ADC number of headers",
684 .name = "ADC_SAMPLES",
686 .valp = &conf.adc_samples,
687 .descr = "ADC number of samples per header",
689 { /* End of list */ }
692 static struct audio_pcm_ops winwave_pcm_ops = {
693 .init_out = winwave_init_out,
694 .fini_out = winwave_fini_out,
695 .run_out = winwave_run_out,
696 .write = winwave_write,
697 .ctl_out = winwave_ctl_out,
698 .init_in = winwave_init_in,
699 .fini_in = winwave_fini_in,
700 .run_in = winwave_run_in,
701 .read = winwave_read,
702 .ctl_in = winwave_ctl_in
705 struct audio_driver winwave_audio_driver = {
707 .descr = "Windows Waveform Audio http://msdn.microsoft.com",
708 .options = winwave_options,
709 .init = winwave_audio_init,
710 .fini = winwave_audio_fini,
711 .pcm_ops = &winwave_pcm_ops,
713 .max_voices_out = INT_MAX,
714 .max_voices_in = INT_MAX,
715 .voice_size_out = sizeof (WaveVoiceOut),
716 .voice_size_in = sizeof (WaveVoiceIn)