]> git.proxmox.com Git - mirror_qemu.git/blame - audio/dsound_template.h
same PCI parameters as PIIX3
[mirror_qemu.git] / audio / dsound_template.h
CommitLineData
1d14ffa9
FB
1/*
2 * QEMU DirectSound audio driver header
3 *
4 * Copyright (c) 2005 Vassili Karpov (malc)
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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
22 * THE SOFTWARE.
23 */
24#ifdef DSBTYPE_IN
25#define NAME "capture buffer"
26#define TYPE in
27#define IFACE IDirectSoundCaptureBuffer
28#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
29#define FIELD dsound_capture_buffer
30#else
31#define NAME "playback buffer"
32#define TYPE out
33#define IFACE IDirectSoundBuffer
34#define BUFPTR LPDIRECTSOUNDBUFFER
35#define FIELD dsound_buffer
36#endif
37
38static int glue (dsound_unlock_, TYPE) (
39 BUFPTR buf,
40 LPVOID p1,
41 LPVOID p2,
42 DWORD blen1,
43 DWORD blen2
44 )
45{
46 HRESULT hr;
47
48 hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
49 if (FAILED (hr)) {
50 dsound_logerr (hr, "Can not unlock " NAME "\n");
51 return -1;
52 }
53
54 return 0;
55}
56
57static int glue (dsound_lock_, TYPE) (
58 BUFPTR buf,
59 struct audio_pcm_info *info,
60 DWORD pos,
61 DWORD len,
62 LPVOID *p1p,
63 LPVOID *p2p,
64 DWORD *blen1p,
65 DWORD *blen2p,
66 int entire
67 )
68{
69 HRESULT hr;
70 int i;
71 LPVOID p1 = NULL, p2 = NULL;
72 DWORD blen1 = 0, blen2 = 0;
73
74 for (i = 0; i < conf.lock_retries; ++i) {
75 hr = glue (IFACE, _Lock) (
76 buf,
77 pos,
78 len,
79 &p1,
80 &blen1,
81 &p2,
82 &blen2,
83 (entire
84#ifdef DSBTYPE_IN
85 ? DSCBLOCK_ENTIREBUFFER
86#else
87 ? DSBLOCK_ENTIREBUFFER
88#endif
89 : 0)
90 );
91
92 if (FAILED (hr)) {
93#ifndef DSBTYPE_IN
94 if (hr == DSERR_BUFFERLOST) {
95 if (glue (dsound_restore_, TYPE) (buf)) {
96 dsound_logerr (hr, "Can not lock " NAME "\n");
97 goto fail;
98 }
99 continue;
100 }
101#endif
102 dsound_logerr (hr, "Can not lock " NAME "\n");
103 goto fail;
104 }
105
106 break;
107 }
108
109 if (i == conf.lock_retries) {
110 dolog ("%d attempts to lock " NAME " failed\n", i);
111 goto fail;
112 }
113
114 if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
115 dolog ("DirectSound returned misaligned buffer %ld %ld\n",
116 blen1, blen2);
117 glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
118 goto fail;
119 }
120
121 if (!p1 && blen1) {
122 dolog ("warning: !p1 && blen1=%ld\n", blen1);
123 blen1 = 0;
124 }
125
126 if (!p2 && blen2) {
127 dolog ("warning: !p2 && blen2=%ld\n", blen2);
128 blen2 = 0;
129 }
130
131 *p1p = p1;
132 *p2p = p2;
133 *blen1p = blen1;
134 *blen2p = blen2;
135 return 0;
136
137 fail:
138 *p1p = NULL - 1;
139 *p2p = NULL - 1;
140 *blen1p = -1;
141 *blen2p = -1;
142 return -1;
143}
144
145#ifdef DSBTYPE_IN
146static void dsound_fini_in (HWVoiceIn *hw)
147#else
148static void dsound_fini_out (HWVoiceOut *hw)
149#endif
150{
151 HRESULT hr;
152#ifdef DSBTYPE_IN
153 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
154#else
155 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
156#endif
157
158 if (ds->FIELD) {
159 hr = glue (IFACE, _Stop) (ds->FIELD);
160 if (FAILED (hr)) {
161 dsound_logerr (hr, "Can not stop " NAME "\n");
162 }
163
164 hr = glue (IFACE, _Release) (ds->FIELD);
165 if (FAILED (hr)) {
166 dsound_logerr (hr, "Can not release " NAME "\n");
167 }
168 ds->FIELD = NULL;
169 }
170}
171
172#ifdef DSBTYPE_IN
173static int dsound_init_in (
174 HWVoiceIn *hw,
175 int freq,
176 int nchannels,
177 audfmt_e fmt
178 )
179#else
180static int dsound_init_out (
181 HWVoiceOut *hw,
182 int freq,
183 int nchannels,
184 audfmt_e fmt
185 )
186#endif
187{
188 int err;
189 HRESULT hr;
190 dsound *s = &glob_dsound;
191 WAVEFORMATEX wfx;
192 struct full_fmt full_fmt;
193#ifdef DSBTYPE_IN
194 const char *typ = "ADC";
195 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
196 DSCBUFFERDESC bd;
197 DSCBCAPS bc;
198#else
199 const char *typ = "DAC";
200 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
201 DSBUFFERDESC bd;
202 DSBCAPS bc;
203#endif
204
205 full_fmt.freq = freq;
206 full_fmt.nchannels = nchannels;
207 full_fmt.fmt = fmt;
208 err = waveformat_from_full_fmt (&wfx, &full_fmt);
209 if (err) {
210 return -1;
211 }
212
213 memset (&bd, 0, sizeof (bd));
214 bd.dwSize = sizeof (bd);
215 bd.lpwfxFormat = &wfx;
216#ifdef DSBTYPE_IN
217 bd.dwBufferBytes = conf.bufsize_in;
218 hr = IDirectSoundCapture_CreateCaptureBuffer (
219 s->dsound_capture,
220 &bd,
221 &ds->dsound_capture_buffer,
222 NULL
223 );
224#else
225 bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
226 bd.dwBufferBytes = conf.bufsize_out;
227 hr = IDirectSound_CreateSoundBuffer (
228 s->dsound,
229 &bd,
230 &ds->dsound_buffer,
231 NULL
232 );
233#endif
234
235 if (FAILED (hr)) {
236 dsound_logerr2 (hr, typ, "Can not create " NAME "\n");
237 return -1;
238 }
239
240 hr = glue (IFACE, _GetFormat) (
241 ds->FIELD,
242 &wfx,
243 sizeof (wfx),
244 NULL
245 );
246 if (FAILED (hr)) {
247 dsound_logerr2 (hr, typ, "Can not get " NAME " format\n");
248 goto fail0;
249 }
250
251#ifdef DEBUG_DSOUND
252 dolog (NAME "\n");
253 print_wave_format (&wfx);
254#endif
255
256 memset (&bc, 0, sizeof (bc));
257 bc.dwSize = sizeof (bc);
258
259 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
260 if (FAILED (hr)) {
261 dsound_logerr2 (hr, typ, "Can not get " NAME " format\n");
262 goto fail0;
263 }
264
265 err = waveformat_to_full_fmt (&wfx, &full_fmt);
266 if (err) {
267 goto fail0;
268 }
269
270 ds->first_time = 1;
271 hw->bufsize = bc.dwBufferBytes;
272 audio_pcm_init_info (
273 &hw->info,
274 full_fmt.freq,
275 full_fmt.nchannels,
276 full_fmt.fmt,
277 audio_need_to_swap_endian (0)
278 );
279
280#ifdef DEBUG_DSOUND
281 dolog ("caps %ld, desc %ld\n",
282 bc.dwBufferBytes, bd.dwBufferBytes);
283
284 dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
285 hw->bufsize, full_fmt.freq, full_fmt.nchannels, full_fmt.fmt);
286#endif
287 return 0;
288
289 fail0:
290 glue (dsound_fini_, TYPE) (hw);
291 return -1;
292}
293
294#undef NAME
295#undef TYPE
296#undef IFACE
297#undef BUFPTR
298#undef FIELD