3 #include "qemu-common.h"
7 #define AUDIO_CAP "winwave"
13 #include "audio_win_int.h"
33 CRITICAL_SECTION crit_sect
;
36 static void winwave_log_mmresult (MMRESULT mr
)
38 const char *str
= "BUG";
41 case MMSYSERR_NOERROR
:
45 case MMSYSERR_INVALHANDLE
:
46 str
= "Specified device handle is invalid";
49 case MMSYSERR_BADDEVICEID
:
50 str
= "Specified device id is out of range";
53 case MMSYSERR_NODRIVER
:
54 str
= "No device driver is present";
58 str
= "Unable to allocate or locl memory";
62 str
= "Device is synchronous but waveOutOpen was called "
63 "without using the WINWAVE_ALLOWSYNC flag";
66 case WAVERR_UNPREPARED
:
67 str
= "The data block pointed to by the pwh parameter "
68 "hasn't been prepared";
71 case WAVERR_STILLPLAYING
:
72 str
= "There are still buffers in the queue";
76 AUD_log (AUDIO_CAP
, "Reason: Unknown (MMRESULT %#x)\n", mr
);
80 AUD_log (AUDIO_CAP
, "Reason: %s\n", str
);
83 static void GCC_FMT_ATTR (2, 3) winwave_logerr (
92 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
95 AUD_log (NULL
, " failed\n");
96 winwave_log_mmresult (mr
);
99 static void winwave_anal_close_out (WaveVoiceOut
*wave
)
103 mr
= waveOutClose (wave
->hwo
);
104 if (mr
!= MMSYSERR_NOERROR
) {
105 winwave_logerr (mr
, "waveOutClose");
110 static void CALLBACK
winwave_callback (
113 DWORD_PTR dwInstance
,
118 WaveVoiceOut
*wave
= (WaveVoiceOut
*) dwInstance
;
123 WAVEHDR
*h
= (WAVEHDR
*) dwParam1
;
126 EnterCriticalSection (&wave
->crit_sect
);
128 wave
->avail
+= conf
.dac_samples
;
130 LeaveCriticalSection (&wave
->crit_sect
);
131 if (wave
->hw
.poll_mode
) {
132 if (!SetEvent (wave
->event
)) {
133 AUD_log (AUDIO_CAP
, "SetEvent failed %lx\n",
146 AUD_log (AUDIO_CAP
, "unknown wave callback msg %x\n", msg
);
150 static int winwave_init_out (HWVoiceOut
*hw
, struct audsettings
*as
)
158 wave
= (WaveVoiceOut
*) hw
;
160 InitializeCriticalSection (&wave
->crit_sect
);
162 err
= waveformat_from_audio_settings (&wfx
, as
);
167 mr
= waveOutOpen (&wave
->hwo
, WAVE_MAPPER
, &wfx
,
168 (DWORD_PTR
) winwave_callback
,
169 (DWORD_PTR
) wave
, CALLBACK_FUNCTION
);
170 if (mr
!= MMSYSERR_NOERROR
) {
171 winwave_logerr (mr
, "waveOutOpen");
175 wave
->hdrs
= audio_calloc (AUDIO_FUNC
, conf
.dac_headers
,
176 sizeof (*wave
->hdrs
));
181 audio_pcm_init_info (&hw
->info
, as
);
182 hw
->samples
= conf
.dac_samples
* conf
.dac_headers
;
183 wave
->avail
= hw
->samples
;
185 wave
->pcm_buf
= audio_calloc (AUDIO_FUNC
, conf
.dac_samples
,
186 conf
.dac_headers
<< hw
->info
.shift
);
187 if (!wave
->pcm_buf
) {
191 for (i
= 0; i
< conf
.dac_headers
; ++i
) {
192 WAVEHDR
*h
= &wave
->hdrs
[i
];
195 h
->dwBufferLength
= conf
.dac_samples
<< hw
->info
.shift
;
196 h
->lpData
= advance (wave
->pcm_buf
, i
* h
->dwBufferLength
);
199 mr
= waveOutPrepareHeader (wave
->hwo
, h
, sizeof (*h
));
200 if (mr
!= MMSYSERR_NOERROR
) {
201 winwave_logerr (mr
, "waveOutPrepareHeader(%d)", wave
->curhdr
);
209 qemu_free (wave
->pcm_buf
);
211 qemu_free (wave
->hdrs
);
213 winwave_anal_close_out (wave
);
219 static int winwave_write (SWVoiceOut
*sw
, void *buf
, int len
)
221 return audio_pcm_sw_write (sw
, buf
, len
);
224 static int winwave_run_out (HWVoiceOut
*hw
, int live
)
226 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
230 EnterCriticalSection (&wave
->crit_sect
);
232 decr
= audio_MIN (live
, wave
->avail
);
233 decr
= audio_pcm_hw_clip_out (hw
, wave
->pcm_buf
, decr
, wave
->pending
);
234 wave
->pending
+= decr
;
237 LeaveCriticalSection (&wave
->crit_sect
);
239 doreset
= hw
->poll_mode
&& (wave
->pending
>= conf
.dac_samples
);
240 if (doreset
&& !ResetEvent (wave
->event
)) {
241 AUD_log (AUDIO_CAP
, "ResetEvent failed %lx\n", GetLastError ());
244 while (wave
->pending
>= conf
.dac_samples
) {
246 WAVEHDR
*h
= &wave
->hdrs
[wave
->curhdr
];
249 mr
= waveOutWrite (wave
->hwo
, h
, sizeof (*h
));
250 if (mr
!= MMSYSERR_NOERROR
) {
251 winwave_logerr (mr
, "waveOutWrite(%d)", wave
->curhdr
);
255 wave
->pending
-= conf
.dac_samples
;
256 wave
->curhdr
= (wave
->curhdr
+ 1) % conf
.dac_headers
;
262 static void winwave_poll_out (void *opaque
)
265 audio_run ("winwave_poll_out");
268 static void winwave_fini_out (HWVoiceOut
*hw
)
272 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
274 mr
= waveOutReset (wave
->hwo
);
275 if (mr
!= MMSYSERR_NOERROR
) {
276 winwave_logerr (mr
, "waveOutReset");
279 for (i
= 0; i
< conf
.dac_headers
; ++i
) {
280 mr
= waveOutUnprepareHeader (wave
->hwo
, &wave
->hdrs
[i
],
281 sizeof (wave
->hdrs
[i
]));
282 if (mr
!= MMSYSERR_NOERROR
) {
283 winwave_logerr (mr
, "waveOutUnprepareHeader(%d)", i
);
287 winwave_anal_close_out (wave
);
290 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
291 if (!CloseHandle (wave
->event
)) {
292 AUD_log (AUDIO_CAP
, "CloseHandle failed %lx\n", GetLastError ());
297 qemu_free (wave
->pcm_buf
);
298 wave
->pcm_buf
= NULL
;
300 qemu_free (wave
->hdrs
);
304 static int winwave_ctl_out (HWVoiceOut
*hw
, int cmd
, ...)
307 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
316 poll_mode
= va_arg (ap
, int);
319 if (poll_mode
&& !wave
->event
) {
320 wave
->event
= CreateEvent (NULL
, TRUE
, TRUE
, NULL
);
323 "CreateEvent: %lx, poll mode will be disabled\n",
331 ret
= qemu_add_wait_object (wave
->event
, winwave_poll_out
,
333 hw
->poll_mode
= (ret
== 0);
339 mr
= waveOutRestart (wave
->hwo
);
340 if (mr
!= MMSYSERR_NOERROR
) {
341 winwave_logerr (mr
, "waveOutRestart");
350 mr
= waveOutPause (wave
->hwo
);
351 if (mr
!= MMSYSERR_NOERROR
) {
352 winwave_logerr (mr
, "waveOutPause");
359 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
366 static void *winwave_audio_init (void)
371 static void winwave_audio_fini (void *opaque
)
376 static struct audio_option winwave_options
[] = {
378 .name
= "DAC_HEADERS",
380 .valp
= &conf
.dac_headers
,
381 .descr
= "DAC number of headers",
384 .name
= "DAC_SAMPLES",
386 .valp
= &conf
.dac_samples
,
387 .descr
= "DAC number of samples per header",
389 { /* End of list */ }
392 static struct audio_pcm_ops winwave_pcm_ops
= {
393 .init_out
= winwave_init_out
,
394 .fini_out
= winwave_fini_out
,
395 .run_out
= winwave_run_out
,
396 .write
= winwave_write
,
397 .ctl_out
= winwave_ctl_out
400 struct audio_driver winwave_audio_driver
= {
402 .descr
= "Windows Waveform Audio http://msdn.microsoft.com",
403 .options
= winwave_options
,
404 .init
= winwave_audio_init
,
405 .fini
= winwave_audio_fini
,
406 .pcm_ops
= &winwave_pcm_ops
,
408 .max_voices_out
= INT_MAX
,
410 .voice_size_out
= sizeof (WaveVoiceOut
),