3 #include "qemu-common.h"
7 #define AUDIO_CAP "winwave"
13 #include "audio_win_int.h"
32 CRITICAL_SECTION crit_sect
;
35 static void winwave_log_mmresult (MMRESULT mr
)
37 const char *str
= "BUG";
40 case MMSYSERR_NOERROR
:
44 case MMSYSERR_INVALHANDLE
:
45 str
= "Specified device handle is invalid";
48 case MMSYSERR_BADDEVICEID
:
49 str
= "Specified device id is out of range";
52 case MMSYSERR_NODRIVER
:
53 str
= "No device driver is present";
57 str
= "Unable to allocate or locl memory";
61 str
= "Device is synchronous but waveOutOpen was called "
62 "without using the WINWAVE_ALLOWSYNC flag";
65 case WAVERR_UNPREPARED
:
66 str
= "The data block pointed to by the pwh parameter "
67 "hasn't been prepared";
71 AUD_log (AUDIO_CAP
, "Reason: Unknown (MMRESULT %#x)\n", mr
);
75 AUD_log (AUDIO_CAP
, "Reason: %s\n", str
);
78 static void GCC_FMT_ATTR (2, 3) winwave_logerr (
87 AUD_vlog (AUDIO_CAP
, fmt
, ap
);
90 winwave_log_mmresult (mr
);
93 static void winwave_anal_close_out (WaveVoiceOut
*wave
)
97 mr
= waveOutClose (wave
->hwo
);
98 if (mr
!= MMSYSERR_NOERROR
) {
99 winwave_logerr (mr
, "waveOutClose\n");
104 static void CALLBACK
winwave_callback (
107 DWORD_PTR dwInstance
,
112 WaveVoiceOut
*wave
= (WaveVoiceOut
*) dwInstance
;
117 WAVEHDR
*h
= (WAVEHDR
*) dwParam1
;
120 EnterCriticalSection (&wave
->crit_sect
);
122 wave
->avail
+= conf
.dac_samples
;
124 LeaveCriticalSection (&wave
->crit_sect
);
125 if (wave
->hw
.poll_mode
) {
126 if (!SetEvent (wave
->event
)) {
127 AUD_log (AUDIO_CAP
, "SetEvent failed %lx\n",
140 AUD_log (AUDIO_CAP
, "unknown wave callback msg %x\n", msg
);
144 static int winwave_init_out (HWVoiceOut
*hw
, struct audsettings
*as
)
152 wave
= (WaveVoiceOut
*) hw
;
154 InitializeCriticalSection (&wave
->crit_sect
);
156 err
= waveformat_from_audio_settings (&wfx
, as
);
161 mr
= waveOutOpen (&wave
->hwo
, WAVE_MAPPER
, &wfx
,
162 (DWORD_PTR
) winwave_callback
,
163 (DWORD_PTR
) wave
, CALLBACK_FUNCTION
);
164 if (mr
!= MMSYSERR_NOERROR
) {
165 winwave_logerr (mr
, "waveOutOpen\n");
169 wave
->hdrs
= audio_calloc (AUDIO_FUNC
, conf
.dac_headers
,
170 sizeof (*wave
->hdrs
));
175 audio_pcm_init_info (&hw
->info
, as
);
176 hw
->samples
= conf
.dac_samples
* conf
.dac_headers
;
177 wave
->avail
= hw
->samples
;
179 wave
->pcm_buf
= audio_calloc (AUDIO_FUNC
, conf
.dac_samples
,
180 conf
.dac_headers
<< hw
->info
.shift
);
181 if (!wave
->pcm_buf
) {
185 for (i
= 0; i
< conf
.dac_headers
; ++i
) {
186 WAVEHDR
*h
= &wave
->hdrs
[i
];
189 h
->dwBufferLength
= conf
.dac_samples
<< hw
->info
.shift
;
190 h
->lpData
= advance (wave
->pcm_buf
, i
* h
->dwBufferLength
);
193 mr
= waveOutPrepareHeader (wave
->hwo
, h
, sizeof (*h
));
194 if (mr
!= MMSYSERR_NOERROR
) {
195 winwave_logerr (mr
, "waveOutPrepareHeader(%d)\n", wave
->curhdr
);
203 qemu_free (wave
->pcm_buf
);
205 qemu_free (wave
->hdrs
);
207 winwave_anal_close_out (wave
);
213 static int winwave_write (SWVoiceOut
*sw
, void *buf
, int len
)
215 return audio_pcm_sw_write (sw
, buf
, len
);
218 static int winwave_run_out (HWVoiceOut
*hw
, int live
)
220 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
224 EnterCriticalSection (&wave
->crit_sect
);
226 decr
= audio_MIN (live
, wave
->avail
);
227 decr
= audio_pcm_hw_clip_out (hw
, wave
->pcm_buf
, decr
, wave
->pending
);
228 wave
->pending
+= decr
;
231 LeaveCriticalSection (&wave
->crit_sect
);
233 doreset
= hw
->poll_mode
&& (wave
->pending
>= conf
.dac_samples
);
234 if (doreset
&& !ResetEvent (wave
->event
)) {
235 AUD_log (AUDIO_CAP
, "ResetEvent failed %lx\n", GetLastError ());
238 while (wave
->pending
>= conf
.dac_samples
) {
240 WAVEHDR
*h
= &wave
->hdrs
[wave
->curhdr
];
243 mr
= waveOutWrite (wave
->hwo
, h
, sizeof (*h
));
244 if (mr
!= MMSYSERR_NOERROR
) {
245 winwave_logerr (mr
, "waveOutWrite(%d)\n", wave
->curhdr
);
249 wave
->pending
-= conf
.dac_samples
;
250 wave
->curhdr
= (wave
->curhdr
+ 1) % conf
.dac_headers
;
256 static void winwave_poll_out (void *opaque
)
259 audio_run ("winwave_poll_out");
262 static void winwave_fini_out (HWVoiceOut
*hw
)
264 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
267 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
268 if (!CloseHandle (wave
->event
)) {
269 AUD_log (AUDIO_CAP
, "CloseHandle failed %lx\n", GetLastError ());
274 winwave_anal_close_out (wave
);
276 qemu_free (wave
->pcm_buf
);
277 wave
->pcm_buf
= NULL
;
279 qemu_free (wave
->hdrs
);
283 static int winwave_ctl_out (HWVoiceOut
*hw
, int cmd
, ...)
285 WaveVoiceOut
*wave
= (WaveVoiceOut
*) hw
;
294 poll_mode
= va_arg (ap
, int);
297 if (poll_mode
&& !wave
->event
) {
298 wave
->event
= CreateEvent (NULL
, TRUE
, TRUE
, NULL
);
301 "CreateEvent: %lx, poll mode will be disabled\n",
309 ret
= qemu_add_wait_object (wave
->event
, winwave_poll_out
,
311 hw
->poll_mode
= (ret
== 0);
321 qemu_del_wait_object (wave
->event
, winwave_poll_out
, wave
);
328 static void *winwave_audio_init (void)
333 static void winwave_audio_fini (void *opaque
)
338 static struct audio_option winwave_options
[] = {
340 .name
= "DAC_HEADERS",
342 .valp
= &conf
.dac_headers
,
343 .descr
= "DAC number of headers",
346 .name
= "DAC_SAMPLES",
348 .valp
= &conf
.dac_samples
,
349 .descr
= "DAC number of samples per header",
351 { /* End of list */ }
354 static struct audio_pcm_ops winwave_pcm_ops
= {
355 .init_out
= winwave_init_out
,
356 .fini_out
= winwave_fini_out
,
357 .run_out
= winwave_run_out
,
358 .write
= winwave_write
,
359 .ctl_out
= winwave_ctl_out
362 struct audio_driver winwave_audio_driver
= {
364 .descr
= "Windows Waveform Audio http://msdn.microsoft.com",
365 .options
= winwave_options
,
366 .init
= winwave_audio_init
,
367 .fini
= winwave_audio_fini
,
368 .pcm_ops
= &winwave_pcm_ops
,
370 .max_voices_out
= INT_MAX
,
372 .voice_size_out
= sizeof (WaveVoiceOut
),