Statistics
| Branch: | Revision:

root / audio / dsound_template.h @ c09015dd

History | View | Annotate | Download (7.1 kB)

1 1d14ffa9 bellard
/*
2 1d14ffa9 bellard
 * QEMU DirectSound audio driver header
3 1d14ffa9 bellard
 *
4 1d14ffa9 bellard
 * Copyright (c) 2005 Vassili Karpov (malc)
5 1d14ffa9 bellard
 *
6 1d14ffa9 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 1d14ffa9 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 1d14ffa9 bellard
 * in the Software without restriction, including without limitation the rights
9 1d14ffa9 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 1d14ffa9 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 1d14ffa9 bellard
 * furnished to do so, subject to the following conditions:
12 1d14ffa9 bellard
 *
13 1d14ffa9 bellard
 * The above copyright notice and this permission notice shall be included in
14 1d14ffa9 bellard
 * all copies or substantial portions of the Software.
15 1d14ffa9 bellard
 *
16 1d14ffa9 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 1d14ffa9 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 1d14ffa9 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 1d14ffa9 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 1d14ffa9 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 1d14ffa9 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 1d14ffa9 bellard
 * THE SOFTWARE.
23 1d14ffa9 bellard
 */
24 1d14ffa9 bellard
#ifdef DSBTYPE_IN
25 1d14ffa9 bellard
#define NAME "capture buffer"
26 ca9cc28c balrog
#define NAME2 "DirectSoundCapture"
27 1d14ffa9 bellard
#define TYPE in
28 1d14ffa9 bellard
#define IFACE IDirectSoundCaptureBuffer
29 1d14ffa9 bellard
#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
30 1d14ffa9 bellard
#define FIELD dsound_capture_buffer
31 ca9cc28c balrog
#define FIELD2 dsound_capture
32 1d14ffa9 bellard
#else
33 1d14ffa9 bellard
#define NAME "playback buffer"
34 ca9cc28c balrog
#define NAME2 "DirectSound"
35 1d14ffa9 bellard
#define TYPE out
36 1d14ffa9 bellard
#define IFACE IDirectSoundBuffer
37 1d14ffa9 bellard
#define BUFPTR LPDIRECTSOUNDBUFFER
38 1d14ffa9 bellard
#define FIELD dsound_buffer
39 ca9cc28c balrog
#define FIELD2 dsound
40 1d14ffa9 bellard
#endif
41 1d14ffa9 bellard
42 1d14ffa9 bellard
static int glue (dsound_unlock_, TYPE) (
43 1d14ffa9 bellard
    BUFPTR buf,
44 1d14ffa9 bellard
    LPVOID p1,
45 1d14ffa9 bellard
    LPVOID p2,
46 1d14ffa9 bellard
    DWORD blen1,
47 1d14ffa9 bellard
    DWORD blen2
48 1d14ffa9 bellard
    )
49 1d14ffa9 bellard
{
50 1d14ffa9 bellard
    HRESULT hr;
51 1d14ffa9 bellard
52 1d14ffa9 bellard
    hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
53 1d14ffa9 bellard
    if (FAILED (hr)) {
54 c0fe3827 bellard
        dsound_logerr (hr, "Could not unlock " NAME "\n");
55 1d14ffa9 bellard
        return -1;
56 1d14ffa9 bellard
    }
57 1d14ffa9 bellard
58 1d14ffa9 bellard
    return 0;
59 1d14ffa9 bellard
}
60 1d14ffa9 bellard
61 1d14ffa9 bellard
static int glue (dsound_lock_, TYPE) (
62 1d14ffa9 bellard
    BUFPTR buf,
63 1d14ffa9 bellard
    struct audio_pcm_info *info,
64 1d14ffa9 bellard
    DWORD pos,
65 1d14ffa9 bellard
    DWORD len,
66 1d14ffa9 bellard
    LPVOID *p1p,
67 1d14ffa9 bellard
    LPVOID *p2p,
68 1d14ffa9 bellard
    DWORD *blen1p,
69 1d14ffa9 bellard
    DWORD *blen2p,
70 1d14ffa9 bellard
    int entire
71 1d14ffa9 bellard
    )
72 1d14ffa9 bellard
{
73 1d14ffa9 bellard
    HRESULT hr;
74 1d14ffa9 bellard
    int i;
75 1d14ffa9 bellard
    LPVOID p1 = NULL, p2 = NULL;
76 1d14ffa9 bellard
    DWORD blen1 = 0, blen2 = 0;
77 8ead62cf bellard
    DWORD flag;
78 1d14ffa9 bellard
79 8ead62cf bellard
#ifdef DSBTYPE_IN
80 8ead62cf bellard
    flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
81 8ead62cf bellard
#else
82 8ead62cf bellard
    flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
83 8ead62cf bellard
#endif
84 1d14ffa9 bellard
    for (i = 0; i < conf.lock_retries; ++i) {
85 1d14ffa9 bellard
        hr = glue (IFACE, _Lock) (
86 1d14ffa9 bellard
            buf,
87 1d14ffa9 bellard
            pos,
88 1d14ffa9 bellard
            len,
89 1d14ffa9 bellard
            &p1,
90 1d14ffa9 bellard
            &blen1,
91 1d14ffa9 bellard
            &p2,
92 1d14ffa9 bellard
            &blen2,
93 8ead62cf bellard
            flag
94 1d14ffa9 bellard
            );
95 1d14ffa9 bellard
96 1d14ffa9 bellard
        if (FAILED (hr)) {
97 1d14ffa9 bellard
#ifndef DSBTYPE_IN
98 1d14ffa9 bellard
            if (hr == DSERR_BUFFERLOST) {
99 1d14ffa9 bellard
                if (glue (dsound_restore_, TYPE) (buf)) {
100 c0fe3827 bellard
                    dsound_logerr (hr, "Could not lock " NAME "\n");
101 1d14ffa9 bellard
                    goto fail;
102 1d14ffa9 bellard
                }
103 1d14ffa9 bellard
                continue;
104 1d14ffa9 bellard
            }
105 1d14ffa9 bellard
#endif
106 c0fe3827 bellard
            dsound_logerr (hr, "Could not lock " NAME "\n");
107 1d14ffa9 bellard
            goto fail;
108 1d14ffa9 bellard
        }
109 1d14ffa9 bellard
110 1d14ffa9 bellard
        break;
111 1d14ffa9 bellard
    }
112 1d14ffa9 bellard
113 1d14ffa9 bellard
    if (i == conf.lock_retries) {
114 1d14ffa9 bellard
        dolog ("%d attempts to lock " NAME " failed\n", i);
115 1d14ffa9 bellard
        goto fail;
116 1d14ffa9 bellard
    }
117 1d14ffa9 bellard
118 1d14ffa9 bellard
    if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
119 1d14ffa9 bellard
        dolog ("DirectSound returned misaligned buffer %ld %ld\n",
120 1d14ffa9 bellard
               blen1, blen2);
121 1d14ffa9 bellard
        glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
122 1d14ffa9 bellard
        goto fail;
123 1d14ffa9 bellard
    }
124 1d14ffa9 bellard
125 1d14ffa9 bellard
    if (!p1 && blen1) {
126 1d14ffa9 bellard
        dolog ("warning: !p1 && blen1=%ld\n", blen1);
127 1d14ffa9 bellard
        blen1 = 0;
128 1d14ffa9 bellard
    }
129 1d14ffa9 bellard
130 1d14ffa9 bellard
    if (!p2 && blen2) {
131 1d14ffa9 bellard
        dolog ("warning: !p2 && blen2=%ld\n", blen2);
132 1d14ffa9 bellard
        blen2 = 0;
133 1d14ffa9 bellard
    }
134 1d14ffa9 bellard
135 1d14ffa9 bellard
    *p1p = p1;
136 1d14ffa9 bellard
    *p2p = p2;
137 1d14ffa9 bellard
    *blen1p = blen1;
138 1d14ffa9 bellard
    *blen2p = blen2;
139 1d14ffa9 bellard
    return 0;
140 1d14ffa9 bellard
141 1d14ffa9 bellard
 fail:
142 1d14ffa9 bellard
    *p1p = NULL - 1;
143 1d14ffa9 bellard
    *p2p = NULL - 1;
144 1d14ffa9 bellard
    *blen1p = -1;
145 1d14ffa9 bellard
    *blen2p = -1;
146 1d14ffa9 bellard
    return -1;
147 1d14ffa9 bellard
}
148 1d14ffa9 bellard
149 1d14ffa9 bellard
#ifdef DSBTYPE_IN
150 1d14ffa9 bellard
static void dsound_fini_in (HWVoiceIn *hw)
151 1d14ffa9 bellard
#else
152 1d14ffa9 bellard
static void dsound_fini_out (HWVoiceOut *hw)
153 1d14ffa9 bellard
#endif
154 1d14ffa9 bellard
{
155 1d14ffa9 bellard
    HRESULT hr;
156 1d14ffa9 bellard
#ifdef DSBTYPE_IN
157 1d14ffa9 bellard
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
158 1d14ffa9 bellard
#else
159 1d14ffa9 bellard
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
160 1d14ffa9 bellard
#endif
161 1d14ffa9 bellard
162 1d14ffa9 bellard
    if (ds->FIELD) {
163 1d14ffa9 bellard
        hr = glue (IFACE, _Stop) (ds->FIELD);
164 1d14ffa9 bellard
        if (FAILED (hr)) {
165 c0fe3827 bellard
            dsound_logerr (hr, "Could not stop " NAME "\n");
166 1d14ffa9 bellard
        }
167 1d14ffa9 bellard
168 1d14ffa9 bellard
        hr = glue (IFACE, _Release) (ds->FIELD);
169 1d14ffa9 bellard
        if (FAILED (hr)) {
170 c0fe3827 bellard
            dsound_logerr (hr, "Could not release " NAME "\n");
171 1d14ffa9 bellard
        }
172 1d14ffa9 bellard
        ds->FIELD = NULL;
173 1d14ffa9 bellard
    }
174 1d14ffa9 bellard
}
175 1d14ffa9 bellard
176 1d14ffa9 bellard
#ifdef DSBTYPE_IN
177 1ea879e5 malc
static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
178 1d14ffa9 bellard
#else
179 1ea879e5 malc
static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
180 1d14ffa9 bellard
#endif
181 1d14ffa9 bellard
{
182 1d14ffa9 bellard
    int err;
183 1d14ffa9 bellard
    HRESULT hr;
184 1d14ffa9 bellard
    dsound *s = &glob_dsound;
185 1d14ffa9 bellard
    WAVEFORMATEX wfx;
186 1ea879e5 malc
    struct audsettings obt_as;
187 1d14ffa9 bellard
#ifdef DSBTYPE_IN
188 1d14ffa9 bellard
    const char *typ = "ADC";
189 1d14ffa9 bellard
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
190 1d14ffa9 bellard
    DSCBUFFERDESC bd;
191 1d14ffa9 bellard
    DSCBCAPS bc;
192 1d14ffa9 bellard
#else
193 1d14ffa9 bellard
    const char *typ = "DAC";
194 1d14ffa9 bellard
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
195 1d14ffa9 bellard
    DSBUFFERDESC bd;
196 1d14ffa9 bellard
    DSBCAPS bc;
197 1d14ffa9 bellard
#endif
198 1d14ffa9 bellard
199 ca9cc28c balrog
    if (!s->FIELD2) {
200 26463dbc balrog
        dolog ("Attempt to initialize voice without " NAME2 " object\n");
201 ca9cc28c balrog
        return -1;
202 ca9cc28c balrog
    }
203 ca9cc28c balrog
204 c0fe3827 bellard
    err = waveformat_from_audio_settings (&wfx, as);
205 1d14ffa9 bellard
    if (err) {
206 1d14ffa9 bellard
        return -1;
207 1d14ffa9 bellard
    }
208 1d14ffa9 bellard
209 1d14ffa9 bellard
    memset (&bd, 0, sizeof (bd));
210 1d14ffa9 bellard
    bd.dwSize = sizeof (bd);
211 1d14ffa9 bellard
    bd.lpwfxFormat = &wfx;
212 1d14ffa9 bellard
#ifdef DSBTYPE_IN
213 1d14ffa9 bellard
    bd.dwBufferBytes = conf.bufsize_in;
214 1d14ffa9 bellard
    hr = IDirectSoundCapture_CreateCaptureBuffer (
215 1d14ffa9 bellard
        s->dsound_capture,
216 1d14ffa9 bellard
        &bd,
217 1d14ffa9 bellard
        &ds->dsound_capture_buffer,
218 1d14ffa9 bellard
        NULL
219 1d14ffa9 bellard
        );
220 1d14ffa9 bellard
#else
221 1d14ffa9 bellard
    bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
222 1d14ffa9 bellard
    bd.dwBufferBytes = conf.bufsize_out;
223 1d14ffa9 bellard
    hr = IDirectSound_CreateSoundBuffer (
224 1d14ffa9 bellard
        s->dsound,
225 1d14ffa9 bellard
        &bd,
226 1d14ffa9 bellard
        &ds->dsound_buffer,
227 1d14ffa9 bellard
        NULL
228 1d14ffa9 bellard
        );
229 1d14ffa9 bellard
#endif
230 1d14ffa9 bellard
231 1d14ffa9 bellard
    if (FAILED (hr)) {
232 c0fe3827 bellard
        dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
233 1d14ffa9 bellard
        return -1;
234 1d14ffa9 bellard
    }
235 1d14ffa9 bellard
236 c0fe3827 bellard
    hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
237 1d14ffa9 bellard
    if (FAILED (hr)) {
238 c0fe3827 bellard
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
239 1d14ffa9 bellard
        goto fail0;
240 1d14ffa9 bellard
    }
241 1d14ffa9 bellard
242 1d14ffa9 bellard
#ifdef DEBUG_DSOUND
243 1d14ffa9 bellard
    dolog (NAME "\n");
244 1d14ffa9 bellard
    print_wave_format (&wfx);
245 1d14ffa9 bellard
#endif
246 1d14ffa9 bellard
247 1d14ffa9 bellard
    memset (&bc, 0, sizeof (bc));
248 1d14ffa9 bellard
    bc.dwSize = sizeof (bc);
249 1d14ffa9 bellard
250 1d14ffa9 bellard
    hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
251 1d14ffa9 bellard
    if (FAILED (hr)) {
252 c0fe3827 bellard
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
253 1d14ffa9 bellard
        goto fail0;
254 1d14ffa9 bellard
    }
255 1d14ffa9 bellard
256 c0fe3827 bellard
    err = waveformat_to_audio_settings (&wfx, &obt_as);
257 1d14ffa9 bellard
    if (err) {
258 1d14ffa9 bellard
        goto fail0;
259 1d14ffa9 bellard
    }
260 1d14ffa9 bellard
261 1d14ffa9 bellard
    ds->first_time = 1;
262 d929eba5 bellard
    obt_as.endianness = 0;
263 d929eba5 bellard
    audio_pcm_init_info (&hw->info, &obt_as);
264 c0fe3827 bellard
265 c0fe3827 bellard
    if (bc.dwBufferBytes & hw->info.align) {
266 c0fe3827 bellard
        dolog (
267 c0fe3827 bellard
            "GetCaps returned misaligned buffer size %ld, alignment %d\n",
268 c0fe3827 bellard
            bc.dwBufferBytes, hw->info.align + 1
269 c0fe3827 bellard
            );
270 c0fe3827 bellard
    }
271 c0fe3827 bellard
    hw->samples = bc.dwBufferBytes >> hw->info.shift;
272 1d14ffa9 bellard
273 1d14ffa9 bellard
#ifdef DEBUG_DSOUND
274 1d14ffa9 bellard
    dolog ("caps %ld, desc %ld\n",
275 1d14ffa9 bellard
           bc.dwBufferBytes, bd.dwBufferBytes);
276 1d14ffa9 bellard
277 1d14ffa9 bellard
    dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
278 c0fe3827 bellard
           hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
279 1d14ffa9 bellard
#endif
280 1d14ffa9 bellard
    return 0;
281 1d14ffa9 bellard
282 1d14ffa9 bellard
 fail0:
283 1d14ffa9 bellard
    glue (dsound_fini_, TYPE) (hw);
284 1d14ffa9 bellard
    return -1;
285 1d14ffa9 bellard
}
286 1d14ffa9 bellard
287 1d14ffa9 bellard
#undef NAME
288 832e9079 malc
#undef NAME2
289 1d14ffa9 bellard
#undef TYPE
290 1d14ffa9 bellard
#undef IFACE
291 1d14ffa9 bellard
#undef BUFPTR
292 1d14ffa9 bellard
#undef FIELD
293 832e9079 malc
#undef FIELD2