Statistics
| Branch: | Revision:

root / audio / dsound_template.h @ cbeb0857

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