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";
72 AUD_log (AUDIO_CAP
, "Reason: Unknown (MMRESULT %#x)\n", mr
);
76 AUD_log (AUDIO_CAP
, "Reason: %s\n", str
);
79 static void GCC_FMT_ATTR (2, 3) winwave_logerr (
88 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
91 winwave_log_mmresult (mr
);
94 static void winwave_anal_close_out (WaveVoiceOut
*wave
)
98 mr
= waveOutClose (wave
->hwo
);
99 if (mr
!= MMSYSERR_NOERROR
) {
100 winwave_logerr (mr
, "waveOutClose\n");
105 static void CALLBACK
winwave_callback (
108 DWORD_PTR dwInstance
,
113 WaveVoiceOut
*wave
= (WaveVoiceOut
*) dwInstance
;
118 WAVEHDR
*h
= (WAVEHDR
*) dwParam1
;
121 EnterCriticalSection (&wave
->crit_sect
);
123 wave
->avail
+= conf
.dac_samples
;
125 LeaveCriticalSection (&wave
->crit_sect
);
126 if (wave
->hw
.poll_mode
) {
127 if (!SetEvent (wave
->event
)) {
128 AUD_log (AUDIO_CAP
, "SetEvent failed %lx\n",
141 AUD_log (AUDIO_CAP
, "unknown wave callback msg %x\n", msg
);
145 static int winwave_init_out (HWVoiceOut
*hw
, struct audsettings
*as
)
153 wave
= (WaveVoiceOut
*) hw
;
155 InitializeCriticalSection (&wave
->crit_sect
);
157 err
= waveformat_from_audio_settings (&wfx
, as
);
162 mr
= waveOutOpen (&wave
->hwo
, WAVE_MAPPER
, &wfx
,
163 (DWORD_PTR
) winwave_callback
,
164 (DWORD_PTR
) wave
, CALLBACK_FUNCTION
);
165 if (mr
!= MMSYSERR_NOERROR
) {
166 winwave_logerr (mr
, "waveOutOpen\n");
170 wave
->hdrs
= audio_calloc (AUDIO_FUNC
, conf
.dac_headers
,
171 sizeof (*wave
->hdrs
));
176 audio_pcm_init_info (&hw
->info
, as
);
177 hw
->samples
= conf
.dac_samples
* conf
.dac_headers
;
178 wave
->avail
= hw
->samples
;
180 wave
->pcm_buf
= audio_calloc (AUDIO_FUNC
, conf
.dac_samples
,
181 conf
.dac_headers
<< hw
->info
.shift
);
182 if (!wave
->pcm_buf
) {
186 for (i
= 0; i
< conf
.dac_headers
; ++i
) {
187 WAVEHDR
*h
= &wave
->hdrs
[i
];
190 h
->dwBufferLength
= conf
.dac_samples
<< hw
->info
.shift
;
191 h
->lpData
= advance (wave
->pcm_buf
, i
* h
->dwBufferLength
);
194 mr
= waveOutPrepareHeader (wave
->hwo
, h
, sizeof (*h
));
195 if (mr
!= MMSYSERR_NOERROR
) {
196 winwave_logerr (mr
, "waveOutPrepareHeader(%d)\n", wave
->curhdr
);
204 qemu_free (wave
->pcm_buf
);
206 qemu_free (wave
->hdrs
);
208 winwave_anal_close_out (wave
);
214 static int winwave_write (SWVoiceOut
*sw
, void *buf
, int len
)
216 return audio_pcm_sw_write (sw
, buf
, len
);
219 static int winwave_run_out (HWVoiceOut
*hw
, int live
)
221 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
225 EnterCriticalSection (&wave
->crit_sect
);
227 decr
= audio_MIN (live
, wave
->avail
);
228 decr
= audio_pcm_hw_clip_out (hw
, wave
->pcm_buf
, decr
, wave
->pending
);
229 wave
->pending
+= decr
;
232 LeaveCriticalSection (&wave
->crit_sect
);
234 doreset
= hw
->poll_mode
&& (wave
->pending
>= conf
.dac_samples
);
235 if (doreset
&& !ResetEvent (wave
->event
)) {
236 AUD_log (AUDIO_CAP
, "ResetEvent failed %lx\n", GetLastError ());
239 while (wave
->pending
>= conf
.dac_samples
) {
241 WAVEHDR
*h
= &wave
->hdrs
[wave
->curhdr
];
244 mr
= waveOutWrite (wave
->hwo
, h
, sizeof (*h
));
245 if (mr
!= MMSYSERR_NOERROR
) {
246 winwave_logerr (mr
, "waveOutWrite(%d)\n", wave
->curhdr
);
250 wave
->pending
-= conf
.dac_samples
;
251 wave
->curhdr
= (wave
->curhdr
+ 1) % conf
.dac_headers
;
257 static void winwave_poll_out (void *opaque
)
260 audio_run ("winwave_poll_out");
263 static void winwave_fini_out (HWVoiceOut
*hw
)
265 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
267 winwave_anal_close_out (wave
);
270 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
271 if (!CloseHandle (wave
->event
)) {
272 AUD_log (AUDIO_CAP
, "CloseHandle failed %lx\n", GetLastError ());
277 qemu_free (wave
->pcm_buf
);
278 wave
->pcm_buf
= NULL
;
280 qemu_free (wave
->hdrs
);
284 static int winwave_ctl_out (HWVoiceOut
*hw
, int cmd
, ...)
287 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
296 poll_mode
= va_arg (ap
, int);
299 if (poll_mode
&& !wave
->event
) {
300 wave
->event
= CreateEvent (NULL
, TRUE
, TRUE
, NULL
);
303 "CreateEvent: %lx, poll mode will be disabled\n",
311 ret
= qemu_add_wait_object (wave
->event
, winwave_poll_out
,
313 hw
->poll_mode
= (ret
== 0);
319 mr
= waveOutRestart (wave
->hwo
);
320 if (mr
!= MMSYSERR_NOERROR
) {
321 winwave_logerr (mr
, "waveOutRestart");
330 mr
= waveOutPause (wave
->hwo
);
331 if (mr
!= MMSYSERR_NOERROR
) {
332 winwave_logerr (mr
, "waveOutPause");
339 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
346 static void *winwave_audio_init (void)
351 static void winwave_audio_fini (void *opaque
)
356 static struct audio_option winwave_options
[] = {
358 .name
= "DAC_HEADERS",
360 .valp
= &conf
.dac_headers
,
361 .descr
= "DAC number of headers",
364 .name
= "DAC_SAMPLES",
366 .valp
= &conf
.dac_samples
,
367 .descr
= "DAC number of samples per header",
369 { /* End of list */ }
372 static struct audio_pcm_ops winwave_pcm_ops
= {
373 .init_out
= winwave_init_out
,
374 .fini_out
= winwave_fini_out
,
375 .run_out
= winwave_run_out
,
376 .write
= winwave_write
,
377 .ctl_out
= winwave_ctl_out
380 struct audio_driver winwave_audio_driver
= {
382 .descr
= "Windows Waveform Audio http://msdn.microsoft.com",
383 .options
= winwave_options
,
384 .init
= winwave_audio_init
,
385 .fini
= winwave_audio_fini
,
386 .pcm_ops
= &winwave_pcm_ops
,
388 .max_voices_out
= INT_MAX
,
390 .voice_size_out
= sizeof (WaveVoiceOut
),