2 * QEMU DirectSound audio driver header
4 * Copyright (c) 2005 Vassili Karpov (malc)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #define NAME "capture buffer"
26 #define NAME2 "DirectSoundCapture"
28 #define IFACE IDirectSoundCaptureBuffer
29 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
30 #define FIELD dsound_capture_buffer
31 #define FIELD2 dsound_capture
32 #define HWVOICE HWVoiceIn
33 #define DSOUNDVOICE DSoundVoiceIn
35 #define NAME "playback buffer"
36 #define NAME2 "DirectSound"
38 #define IFACE IDirectSoundBuffer
39 #define BUFPTR LPDIRECTSOUNDBUFFER
40 #define FIELD dsound_buffer
42 #define HWVOICE HWVoiceOut
43 #define DSOUNDVOICE DSoundVoiceOut
46 static int glue (dsound_unlock_
, TYPE
) (
56 hr
= glue (IFACE
, _Unlock
) (buf
, p1
, blen1
, p2
, blen2
);
58 dsound_logerr (hr
, "Could not unlock " NAME
"\n");
65 static int glue (dsound_lock_
, TYPE
) (
67 struct audio_pcm_info
*info
,
82 flag
= entire
? DSCBLOCK_ENTIREBUFFER
: 0;
84 flag
= entire
? DSBLOCK_ENTIREBUFFER
: 0;
86 hr
= glue(IFACE
, _Lock
)(buf
, pos
, len
, p1p
, blen1p
, p2p
, blen2p
, flag
);
90 if (hr
== DSERR_BUFFERLOST
) {
91 if (glue (dsound_restore_
, TYPE
) (buf
, s
)) {
92 dsound_logerr (hr
, "Could not lock " NAME
"\n");
97 dsound_logerr (hr
, "Could not lock " NAME
"\n");
101 if ((p1p
&& *p1p
&& (*blen1p
% info
->bytes_per_frame
)) ||
102 (p2p
&& *p2p
&& (*blen2p
% info
->bytes_per_frame
))) {
103 dolog("DirectSound returned misaligned buffer %ld %ld\n",
105 glue(dsound_unlock_
, TYPE
)(buf
, *p1p
, p2p
? *p2p
: NULL
, *blen1p
,
106 blen2p
? *blen2p
: 0);
110 if (p1p
&& !*p1p
&& *blen1p
) {
111 dolog("warning: !p1 && blen1=%ld\n", *blen1p
);
115 if (p2p
&& !*p2p
&& *blen2p
) {
116 dolog("warning: !p2 && blen2=%ld\n", *blen2p
);
133 static void dsound_fini_in (HWVoiceIn
*hw
)
135 static void dsound_fini_out (HWVoiceOut
*hw
)
140 DSoundVoiceIn
*ds
= (DSoundVoiceIn
*) hw
;
142 DSoundVoiceOut
*ds
= (DSoundVoiceOut
*) hw
;
146 hr
= glue (IFACE
, _Stop
) (ds
->FIELD
);
148 dsound_logerr (hr
, "Could not stop " NAME
"\n");
151 hr
= glue (IFACE
, _Release
) (ds
->FIELD
);
153 dsound_logerr (hr
, "Could not release " NAME
"\n");
160 static int dsound_init_in(HWVoiceIn
*hw
, struct audsettings
*as
,
163 static int dsound_init_out(HWVoiceOut
*hw
, struct audsettings
*as
,
169 dsound
*s
= drv_opaque
;
171 struct audsettings obt_as
;
173 const char *typ
= "ADC";
174 DSoundVoiceIn
*ds
= (DSoundVoiceIn
*) hw
;
177 AudiodevPerDirectionOptions
*pdo
= s
->dev
->u
.dsound
.in
;
179 const char *typ
= "DAC";
180 DSoundVoiceOut
*ds
= (DSoundVoiceOut
*) hw
;
183 AudiodevPerDirectionOptions
*pdo
= s
->dev
->u
.dsound
.out
;
187 dolog ("Attempt to initialize voice without " NAME2
" object\n");
191 err
= waveformat_from_audio_settings (&wfx
, as
);
196 memset (&bd
, 0, sizeof (bd
));
197 bd
.dwSize
= sizeof (bd
);
198 bd
.lpwfxFormat
= &wfx
;
199 bd
.dwBufferBytes
= audio_buffer_bytes(pdo
, as
, 92880);
201 hr
= IDirectSoundCapture_CreateCaptureBuffer (
204 &ds
->dsound_capture_buffer
,
208 bd
.dwFlags
= DSBCAPS_GLOBALFOCUS
| DSBCAPS_GETCURRENTPOSITION2
;
209 hr
= IDirectSound_CreateSoundBuffer (
218 dsound_logerr2 (hr
, typ
, "Could not create " NAME
"\n");
222 hr
= glue (IFACE
, _GetFormat
) (ds
->FIELD
, &wfx
, sizeof (wfx
), NULL
);
224 dsound_logerr2 (hr
, typ
, "Could not get " NAME
" format\n");
230 print_wave_format (&wfx
);
233 memset (&bc
, 0, sizeof (bc
));
234 bc
.dwSize
= sizeof (bc
);
236 hr
= glue (IFACE
, _GetCaps
) (ds
->FIELD
, &bc
);
238 dsound_logerr2 (hr
, typ
, "Could not get " NAME
" format\n");
242 err
= waveformat_to_audio_settings (&wfx
, &obt_as
);
247 ds
->first_time
= true;
248 obt_as
.endianness
= 0;
249 audio_pcm_init_info (&hw
->info
, &obt_as
);
251 if (bc
.dwBufferBytes
% hw
->info
.bytes_per_frame
) {
253 "GetCaps returned misaligned buffer size %ld, alignment %d\n",
254 bc
.dwBufferBytes
, hw
->info
.bytes_per_frame
257 hw
->size_emul
= bc
.dwBufferBytes
;
258 hw
->samples
= bc
.dwBufferBytes
/ hw
->info
.bytes_per_frame
;
262 dolog ("caps %ld, desc %ld\n",
263 bc
.dwBufferBytes
, bd
.dwBufferBytes
);
268 glue (dsound_fini_
, TYPE
) (hw
);