Update version for 1.6.0-rc2
[sdk/emulator/qemu.git] / audio / winwaveaudio.c
1 /* public domain */
2
3 #include "qemu-common.h"
4 #include "sysemu/sysemu.h"
5 #include "audio.h"
6
7 #define AUDIO_CAP "winwave"
8 #include "audio_int.h"
9
10 #include <windows.h>
11 #include <mmsystem.h>
12
13 #include "audio_win_int.h"
14
15 static struct {
16     int dac_headers;
17     int dac_samples;
18     int adc_headers;
19     int adc_samples;
20 } conf = {
21     .dac_headers = 4,
22     .dac_samples = 1024,
23     .adc_headers = 4,
24     .adc_samples = 1024
25 };
26
27 typedef struct {
28     HWVoiceOut hw;
29     HWAVEOUT hwo;
30     WAVEHDR *hdrs;
31     HANDLE event;
32     void *pcm_buf;
33     int avail;
34     int pending;
35     int curhdr;
36     int paused;
37     CRITICAL_SECTION crit_sect;
38 } WaveVoiceOut;
39
40 typedef struct {
41     HWVoiceIn hw;
42     HWAVEIN hwi;
43     WAVEHDR *hdrs;
44     HANDLE event;
45     void *pcm_buf;
46     int curhdr;
47     int paused;
48     int rpos;
49     int avail;
50     CRITICAL_SECTION crit_sect;
51 } WaveVoiceIn;
52
53 static void winwave_log_mmresult (MMRESULT mr)
54 {
55     const char *str = "BUG";
56
57     switch (mr) {
58     case MMSYSERR_NOERROR:
59         str = "Success";
60         break;
61
62     case MMSYSERR_INVALHANDLE:
63         str = "Specified device handle is invalid";
64         break;
65
66     case MMSYSERR_BADDEVICEID:
67         str = "Specified device id is out of range";
68         break;
69
70     case MMSYSERR_NODRIVER:
71         str = "No device driver is present";
72         break;
73
74     case MMSYSERR_NOMEM:
75         str = "Unable to allocate or lock memory";
76         break;
77
78     case WAVERR_SYNC:
79         str = "Device is synchronous but waveOutOpen was called "
80             "without using the WINWAVE_ALLOWSYNC flag";
81         break;
82
83     case WAVERR_UNPREPARED:
84         str = "The data block pointed to by the pwh parameter "
85             "hasn't been prepared";
86         break;
87
88     case WAVERR_STILLPLAYING:
89         str = "There are still buffers in the queue";
90         break;
91
92     default:
93         dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
94         return;
95     }
96
97     dolog ("Reason: %s\n", str);
98 }
99
100 static void GCC_FMT_ATTR (2, 3) winwave_logerr (
101     MMRESULT mr,
102     const char *fmt,
103     ...
104     )
105 {
106     va_list ap;
107
108     va_start (ap, fmt);
109     AUD_vlog (AUDIO_CAP, fmt, ap);
110     va_end (ap);
111
112     AUD_log (NULL, " failed\n");
113     winwave_log_mmresult (mr);
114 }
115
116 static void winwave_anal_close_out (WaveVoiceOut *wave)
117 {
118     MMRESULT mr;
119
120     mr = waveOutClose (wave->hwo);
121     if (mr != MMSYSERR_NOERROR) {
122         winwave_logerr (mr, "waveOutClose");
123     }
124     wave->hwo = NULL;
125 }
126
127 static void CALLBACK winwave_callback_out (
128     HWAVEOUT hwo,
129     UINT msg,
130     DWORD_PTR dwInstance,
131     DWORD_PTR dwParam1,
132     DWORD_PTR dwParam2
133     )
134 {
135     WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance;
136
137     switch (msg) {
138     case WOM_DONE:
139         {
140             WAVEHDR *h = (WAVEHDR *) dwParam1;
141             if (!h->dwUser) {
142                 h->dwUser = 1;
143                 EnterCriticalSection (&wave->crit_sect);
144                 {
145                     wave->avail += conf.dac_samples;
146                 }
147                 LeaveCriticalSection (&wave->crit_sect);
148                 if (wave->hw.poll_mode) {
149                     if (!SetEvent (wave->event)) {
150                         dolog ("DAC SetEvent failed %lx\n", GetLastError ());
151                     }
152                 }
153             }
154         }
155         break;
156
157     case WOM_CLOSE:
158     case WOM_OPEN:
159         break;
160
161     default:
162         dolog ("unknown wave out callback msg %x\n", msg);
163     }
164 }
165
166 static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
167 {
168     int i;
169     int err;
170     MMRESULT mr;
171     WAVEFORMATEX wfx;
172     WaveVoiceOut *wave;
173
174     wave = (WaveVoiceOut *) hw;
175
176     InitializeCriticalSection (&wave->crit_sect);
177
178     err = waveformat_from_audio_settings (&wfx, as);
179     if (err) {
180         goto err0;
181     }
182
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");
188         goto err1;
189     }
190
191     wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
192                                sizeof (*wave->hdrs));
193     if (!wave->hdrs) {
194         goto err2;
195     }
196
197     audio_pcm_init_info (&hw->info, as);
198     hw->samples = conf.dac_samples * conf.dac_headers;
199     wave->avail = hw->samples;
200
201     wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples,
202                                   conf.dac_headers << hw->info.shift);
203     if (!wave->pcm_buf) {
204         goto err3;
205     }
206
207     for (i = 0; i < conf.dac_headers; ++i) {
208         WAVEHDR *h = &wave->hdrs[i];
209
210         h->dwUser = 0;
211         h->dwBufferLength = conf.dac_samples << hw->info.shift;
212         h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
213         h->dwFlags = 0;
214
215         mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
216         if (mr != MMSYSERR_NOERROR) {
217             winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
218             goto err4;
219         }
220     }
221
222     return 0;
223
224  err4:
225     g_free (wave->pcm_buf);
226  err3:
227     g_free (wave->hdrs);
228  err2:
229     winwave_anal_close_out (wave);
230  err1:
231  err0:
232     return -1;
233 }
234
235 static int winwave_write (SWVoiceOut *sw, void *buf, int len)
236 {
237     return audio_pcm_sw_write (sw, buf, len);
238 }
239
240 static int winwave_run_out (HWVoiceOut *hw, int live)
241 {
242     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
243     int decr;
244     int doreset;
245
246     EnterCriticalSection (&wave->crit_sect);
247     {
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;
251         wave->avail -= decr;
252     }
253     LeaveCriticalSection (&wave->crit_sect);
254
255     doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
256     if (doreset && !ResetEvent (wave->event)) {
257         dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
258     }
259
260     while (wave->pending >= conf.dac_samples) {
261         MMRESULT mr;
262         WAVEHDR *h = &wave->hdrs[wave->curhdr];
263
264         h->dwUser = 0;
265         mr = waveOutWrite (wave->hwo, h, sizeof (*h));
266         if (mr != MMSYSERR_NOERROR) {
267             winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr);
268             break;
269         }
270
271         wave->pending -= conf.dac_samples;
272         wave->curhdr = (wave->curhdr + 1) % conf.dac_headers;
273     }
274
275     return decr;
276 }
277
278 static void winwave_poll (void *opaque)
279 {
280     (void) opaque;
281     audio_run ("winwave_poll");
282 }
283
284 static void winwave_fini_out (HWVoiceOut *hw)
285 {
286     int i;
287     MMRESULT mr;
288     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
289
290     mr = waveOutReset (wave->hwo);
291     if (mr != MMSYSERR_NOERROR) {
292         winwave_logerr (mr, "waveOutReset");
293     }
294
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);
300         }
301     }
302
303     winwave_anal_close_out (wave);
304
305     if (wave->event) {
306         qemu_del_wait_object (wave->event, winwave_poll, wave);
307         if (!CloseHandle (wave->event)) {
308             dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
309         }
310         wave->event = NULL;
311     }
312
313     g_free (wave->pcm_buf);
314     wave->pcm_buf = NULL;
315
316     g_free (wave->hdrs);
317     wave->hdrs = NULL;
318 }
319
320 static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
321 {
322     MMRESULT mr;
323     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
324
325     switch (cmd) {
326     case VOICE_ENABLE:
327         {
328             va_list ap;
329             int poll_mode;
330
331             va_start (ap, cmd);
332             poll_mode = va_arg (ap, int);
333             va_end (ap);
334
335             if (poll_mode && !wave->event) {
336                 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
337                 if (!wave->event) {
338                     dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
339                            GetLastError ());
340                 }
341             }
342
343             if (wave->event) {
344                 int ret;
345
346                 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
347                 hw->poll_mode = (ret == 0);
348             }
349             else {
350                 hw->poll_mode = 0;
351             }
352             wave->paused = 0;
353         }
354         return 0;
355
356     case VOICE_DISABLE:
357         if (!wave->paused) {
358             mr = waveOutReset (wave->hwo);
359             if (mr != MMSYSERR_NOERROR) {
360                 winwave_logerr (mr, "waveOutReset");
361             }
362             else {
363                 wave->paused = 1;
364             }
365         }
366         if (wave->event) {
367             qemu_del_wait_object (wave->event, winwave_poll, wave);
368         }
369         return 0;
370     }
371     return -1;
372 }
373
374 static void winwave_anal_close_in (WaveVoiceIn *wave)
375 {
376     MMRESULT mr;
377
378     mr = waveInClose (wave->hwi);
379     if (mr != MMSYSERR_NOERROR) {
380         winwave_logerr (mr, "waveInClose");
381     }
382     wave->hwi = NULL;
383 }
384
385 static void CALLBACK winwave_callback_in (
386     HWAVEIN *hwi,
387     UINT msg,
388     DWORD_PTR dwInstance,
389     DWORD_PTR dwParam1,
390     DWORD_PTR dwParam2
391     )
392 {
393     WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance;
394
395     switch (msg) {
396     case WIM_DATA:
397         {
398             WAVEHDR *h = (WAVEHDR *) dwParam1;
399             if (!h->dwUser) {
400                 h->dwUser = 1;
401                 EnterCriticalSection (&wave->crit_sect);
402                 {
403                     wave->avail += conf.adc_samples;
404                 }
405                 LeaveCriticalSection (&wave->crit_sect);
406                 if (wave->hw.poll_mode) {
407                     if (!SetEvent (wave->event)) {
408                         dolog ("ADC SetEvent failed %lx\n", GetLastError ());
409                     }
410                 }
411             }
412         }
413         break;
414
415     case WIM_CLOSE:
416     case WIM_OPEN:
417         break;
418
419     default:
420         dolog ("unknown wave in callback msg %x\n", msg);
421     }
422 }
423
424 static void winwave_add_buffers (WaveVoiceIn *wave, int samples)
425 {
426     int doreset;
427
428     doreset = wave->hw.poll_mode && (samples >= conf.adc_samples);
429     if (doreset && !ResetEvent (wave->event)) {
430         dolog ("ADC ResetEvent failed %lx\n", GetLastError ());
431     }
432
433     while (samples >= conf.adc_samples) {
434         MMRESULT mr;
435         WAVEHDR *h = &wave->hdrs[wave->curhdr];
436
437         h->dwUser = 0;
438         mr = waveInAddBuffer (wave->hwi, h, sizeof (*h));
439         if (mr != MMSYSERR_NOERROR) {
440             winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr);
441         }
442         wave->curhdr = (wave->curhdr + 1) % conf.adc_headers;
443         samples -= conf.adc_samples;
444     }
445 }
446
447 static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as)
448 {
449     int i;
450     int err;
451     MMRESULT mr;
452     WAVEFORMATEX wfx;
453     WaveVoiceIn *wave;
454
455     wave = (WaveVoiceIn *) hw;
456
457     InitializeCriticalSection (&wave->crit_sect);
458
459     err = waveformat_from_audio_settings (&wfx, as);
460     if (err) {
461         goto err0;
462     }
463
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");
469         goto err1;
470     }
471
472     wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
473                                sizeof (*wave->hdrs));
474     if (!wave->hdrs) {
475         goto err2;
476     }
477
478     audio_pcm_init_info (&hw->info, as);
479     hw->samples = conf.adc_samples * conf.adc_headers;
480     wave->avail = 0;
481
482     wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples,
483                                   conf.adc_headers << hw->info.shift);
484     if (!wave->pcm_buf) {
485         goto err3;
486     }
487
488     for (i = 0; i < conf.adc_headers; ++i) {
489         WAVEHDR *h = &wave->hdrs[i];
490
491         h->dwUser = 0;
492         h->dwBufferLength = conf.adc_samples << hw->info.shift;
493         h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
494         h->dwFlags = 0;
495
496         mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h));
497         if (mr != MMSYSERR_NOERROR) {
498             winwave_logerr (mr, "waveInPrepareHeader(%d)", i);
499             goto err4;
500         }
501     }
502
503     wave->paused = 1;
504     winwave_add_buffers (wave, hw->samples);
505     return 0;
506
507  err4:
508     g_free (wave->pcm_buf);
509  err3:
510     g_free (wave->hdrs);
511  err2:
512     winwave_anal_close_in (wave);
513  err1:
514  err0:
515     return -1;
516 }
517
518 static void winwave_fini_in (HWVoiceIn *hw)
519 {
520     int i;
521     MMRESULT mr;
522     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
523
524     mr = waveInReset (wave->hwi);
525     if (mr != MMSYSERR_NOERROR) {
526         winwave_logerr (mr, "waveInReset");
527     }
528
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);
534         }
535     }
536
537     winwave_anal_close_in (wave);
538
539     if (wave->event) {
540         qemu_del_wait_object (wave->event, winwave_poll, wave);
541         if (!CloseHandle (wave->event)) {
542             dolog ("ADC CloseHandle failed %lx\n", GetLastError ());
543         }
544         wave->event = NULL;
545     }
546
547     g_free (wave->pcm_buf);
548     wave->pcm_buf = NULL;
549
550     g_free (wave->hdrs);
551     wave->hdrs = NULL;
552 }
553
554 static int winwave_run_in (HWVoiceIn *hw)
555 {
556     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
557     int live = audio_pcm_hw_get_live_in (hw);
558     int dead = hw->samples - live;
559     int decr, ret;
560
561     if (!dead) {
562         return 0;
563     }
564
565     EnterCriticalSection (&wave->crit_sect);
566     {
567         decr = audio_MIN (dead, wave->avail);
568         wave->avail -= decr;
569     }
570     LeaveCriticalSection (&wave->crit_sect);
571
572     ret = decr;
573     while (decr) {
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),
578                   conv);
579
580         wave->rpos = (wave->rpos + conv) % hw->samples;
581         hw->wpos = (hw->wpos + conv) % hw->samples;
582         decr -= conv;
583     }
584
585     winwave_add_buffers (wave, ret);
586     return ret;
587 }
588
589 static int winwave_read (SWVoiceIn *sw, void *buf, int size)
590 {
591     return audio_pcm_sw_read (sw, buf, size);
592 }
593
594 static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
595 {
596     MMRESULT mr;
597     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
598
599     switch (cmd) {
600     case VOICE_ENABLE:
601         {
602             va_list ap;
603             int poll_mode;
604
605             va_start (ap, cmd);
606             poll_mode = va_arg (ap, int);
607             va_end (ap);
608
609             if (poll_mode && !wave->event) {
610                 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
611                 if (!wave->event) {
612                     dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
613                            GetLastError ());
614                 }
615             }
616
617             if (wave->event) {
618                 int ret;
619
620                 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
621                 hw->poll_mode = (ret == 0);
622             }
623             else {
624                 hw->poll_mode = 0;
625             }
626             if (wave->paused) {
627                 mr = waveInStart (wave->hwi);
628                 if (mr != MMSYSERR_NOERROR) {
629                     winwave_logerr (mr, "waveInStart");
630                 }
631                 wave->paused = 0;
632             }
633         }
634         return 0;
635
636     case VOICE_DISABLE:
637         if (!wave->paused) {
638             mr = waveInStop (wave->hwi);
639             if (mr != MMSYSERR_NOERROR) {
640                 winwave_logerr (mr, "waveInStop");
641             }
642             else {
643                 wave->paused = 1;
644             }
645         }
646         if (wave->event) {
647             qemu_del_wait_object (wave->event, winwave_poll, wave);
648         }
649         return 0;
650     }
651     return 0;
652 }
653
654 static void *winwave_audio_init (void)
655 {
656     return &conf;
657 }
658
659 static void winwave_audio_fini (void *opaque)
660 {
661     (void) opaque;
662 }
663
664 static struct audio_option winwave_options[] = {
665     {
666         .name        = "DAC_HEADERS",
667         .tag         = AUD_OPT_INT,
668         .valp        = &conf.dac_headers,
669         .descr       = "DAC number of headers",
670     },
671     {
672         .name        = "DAC_SAMPLES",
673         .tag         = AUD_OPT_INT,
674         .valp        = &conf.dac_samples,
675         .descr       = "DAC number of samples per header",
676     },
677     {
678         .name        = "ADC_HEADERS",
679         .tag         = AUD_OPT_INT,
680         .valp        = &conf.adc_headers,
681         .descr       = "ADC number of headers",
682     },
683     {
684         .name        = "ADC_SAMPLES",
685         .tag         = AUD_OPT_INT,
686         .valp        = &conf.adc_samples,
687         .descr       = "ADC number of samples per header",
688     },
689     { /* End of list */ }
690 };
691
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
703 };
704
705 struct audio_driver winwave_audio_driver = {
706     .name           = "winwave",
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,
712     .can_be_default = 1,
713     .max_voices_out = INT_MAX,
714     .max_voices_in  = INT_MAX,
715     .voice_size_out = sizeof (WaveVoiceOut),
716     .voice_size_in  = sizeof (WaveVoiceIn)
717 };