hw/arm/virt: parameter passing cleanups
[qemu.git] / audio / dsound_template.h
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 NAME2 "DirectSoundCapture"
27 #define TYPE in
28 #define IFACE IDirectSoundCaptureBuffer
29 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
30 #define FIELD dsound_capture_buffer
31 #define FIELD2 dsound_capture
32 #else
33 #define NAME "playback buffer"
34 #define NAME2 "DirectSound"
35 #define TYPE out
36 #define IFACE IDirectSoundBuffer
37 #define BUFPTR LPDIRECTSOUNDBUFFER
38 #define FIELD dsound_buffer
39 #define FIELD2 dsound
40 #endif
41
42 static int glue (dsound_unlock_, TYPE) (
43 BUFPTR buf,
44 LPVOID p1,
45 LPVOID p2,
46 DWORD blen1,
47 DWORD blen2
48 )
49 {
50 HRESULT hr;
51
52 hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
53 if (FAILED (hr)) {
54 dsound_logerr (hr, "Could not unlock " NAME "\n");
55 return -1;
56 }
57
58 return 0;
59 }
60
61 static int glue (dsound_lock_, TYPE) (
62 BUFPTR buf,
63 struct audio_pcm_info *info,
64 DWORD pos,
65 DWORD len,
66 LPVOID *p1p,
67 LPVOID *p2p,
68 DWORD *blen1p,
69 DWORD *blen2p,
70 int entire,
71 dsound *s
72 )
73 {
74 HRESULT hr;
75 LPVOID p1 = NULL, p2 = NULL;
76 DWORD blen1 = 0, blen2 = 0;
77 DWORD flag;
78
79 #ifdef DSBTYPE_IN
80 flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
81 #else
82 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
83 #endif
84 hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag);
85
86 if (FAILED (hr)) {
87 #ifndef DSBTYPE_IN
88 if (hr == DSERR_BUFFERLOST) {
89 if (glue (dsound_restore_, TYPE) (buf, s)) {
90 dsound_logerr (hr, "Could not lock " NAME "\n");
91 }
92 goto fail;
93 }
94 #endif
95 dsound_logerr (hr, "Could not lock " NAME "\n");
96 goto fail;
97 }
98
99 if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
100 dolog ("DirectSound returned misaligned buffer %ld %ld\n",
101 blen1, blen2);
102 glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
103 goto fail;
104 }
105
106 if (!p1 && blen1) {
107 dolog ("warning: !p1 && blen1=%ld\n", blen1);
108 blen1 = 0;
109 }
110
111 if (!p2 && blen2) {
112 dolog ("warning: !p2 && blen2=%ld\n", blen2);
113 blen2 = 0;
114 }
115
116 *p1p = p1;
117 *p2p = p2;
118 *blen1p = blen1;
119 *blen2p = blen2;
120 return 0;
121
122 fail:
123 *p1p = NULL - 1;
124 *p2p = NULL - 1;
125 *blen1p = -1;
126 *blen2p = -1;
127 return -1;
128 }
129
130 #ifdef DSBTYPE_IN
131 static void dsound_fini_in (HWVoiceIn *hw)
132 #else
133 static void dsound_fini_out (HWVoiceOut *hw)
134 #endif
135 {
136 HRESULT hr;
137 #ifdef DSBTYPE_IN
138 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
139 #else
140 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
141 #endif
142
143 if (ds->FIELD) {
144 hr = glue (IFACE, _Stop) (ds->FIELD);
145 if (FAILED (hr)) {
146 dsound_logerr (hr, "Could not stop " NAME "\n");
147 }
148
149 hr = glue (IFACE, _Release) (ds->FIELD);
150 if (FAILED (hr)) {
151 dsound_logerr (hr, "Could not release " NAME "\n");
152 }
153 ds->FIELD = NULL;
154 }
155 }
156
157 #ifdef DSBTYPE_IN
158 static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
159 void *drv_opaque)
160 #else
161 static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
162 void *drv_opaque)
163 #endif
164 {
165 int err;
166 HRESULT hr;
167 dsound *s = drv_opaque;
168 WAVEFORMATEX wfx;
169 struct audsettings obt_as;
170 DSoundConf *conf = &s->conf;
171 #ifdef DSBTYPE_IN
172 const char *typ = "ADC";
173 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
174 DSCBUFFERDESC bd;
175 DSCBCAPS bc;
176 #else
177 const char *typ = "DAC";
178 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
179 DSBUFFERDESC bd;
180 DSBCAPS bc;
181 #endif
182
183 if (!s->FIELD2) {
184 dolog ("Attempt to initialize voice without " NAME2 " object\n");
185 return -1;
186 }
187
188 err = waveformat_from_audio_settings (&wfx, as);
189 if (err) {
190 return -1;
191 }
192
193 memset (&bd, 0, sizeof (bd));
194 bd.dwSize = sizeof (bd);
195 bd.lpwfxFormat = &wfx;
196 #ifdef DSBTYPE_IN
197 bd.dwBufferBytes = conf->bufsize_in;
198 hr = IDirectSoundCapture_CreateCaptureBuffer (
199 s->dsound_capture,
200 &bd,
201 &ds->dsound_capture_buffer,
202 NULL
203 );
204 #else
205 bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
206 bd.dwBufferBytes = conf->bufsize_out;
207 hr = IDirectSound_CreateSoundBuffer (
208 s->dsound,
209 &bd,
210 &ds->dsound_buffer,
211 NULL
212 );
213 #endif
214
215 if (FAILED (hr)) {
216 dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
217 return -1;
218 }
219
220 hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
221 if (FAILED (hr)) {
222 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
223 goto fail0;
224 }
225
226 #ifdef DEBUG_DSOUND
227 dolog (NAME "\n");
228 print_wave_format (&wfx);
229 #endif
230
231 memset (&bc, 0, sizeof (bc));
232 bc.dwSize = sizeof (bc);
233
234 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
235 if (FAILED (hr)) {
236 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
237 goto fail0;
238 }
239
240 err = waveformat_to_audio_settings (&wfx, &obt_as);
241 if (err) {
242 goto fail0;
243 }
244
245 ds->first_time = 1;
246 obt_as.endianness = 0;
247 audio_pcm_init_info (&hw->info, &obt_as);
248
249 if (bc.dwBufferBytes & hw->info.align) {
250 dolog (
251 "GetCaps returned misaligned buffer size %ld, alignment %d\n",
252 bc.dwBufferBytes, hw->info.align + 1
253 );
254 }
255 hw->samples = bc.dwBufferBytes >> hw->info.shift;
256 ds->s = s;
257
258 #ifdef DEBUG_DSOUND
259 dolog ("caps %ld, desc %ld\n",
260 bc.dwBufferBytes, bd.dwBufferBytes);
261
262 dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
263 hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
264 #endif
265 return 0;
266
267 fail0:
268 glue (dsound_fini_, TYPE) (hw);
269 return -1;
270 }
271
272 #undef NAME
273 #undef NAME2
274 #undef TYPE
275 #undef IFACE
276 #undef BUFPTR
277 #undef FIELD
278 #undef FIELD2