Statistics
| Branch: | Revision:

root / audio / dsound_template.h @ 8b7968f7

History | View | Annotate | Download (7.1 kB)

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
    )
72
{
73
    HRESULT hr;
74
    int i;
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
    for (i = 0; i < conf.lock_retries; ++i) {
85
        hr = glue (IFACE, _Lock) (
86
            buf,
87
            pos,
88
            len,
89
            &p1,
90
            &blen1,
91
            &p2,
92
            &blen2,
93
            flag
94
            );
95

    
96
        if (FAILED (hr)) {
97
#ifndef DSBTYPE_IN
98
            if (hr == DSERR_BUFFERLOST) {
99
                if (glue (dsound_restore_, TYPE) (buf)) {
100
                    dsound_logerr (hr, "Could not lock " NAME "\n");
101
                    goto fail;
102
                }
103
                continue;
104
            }
105
#endif
106
            dsound_logerr (hr, "Could not lock " NAME "\n");
107
            goto fail;
108
        }
109

    
110
        break;
111
    }
112

    
113
    if (i == conf.lock_retries) {
114
        dolog ("%d attempts to lock " NAME " failed\n", i);
115
        goto fail;
116
    }
117

    
118
    if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
119
        dolog ("DirectSound returned misaligned buffer %ld %ld\n",
120
               blen1, blen2);
121
        glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
122
        goto fail;
123
    }
124

    
125
    if (!p1 && blen1) {
126
        dolog ("warning: !p1 && blen1=%ld\n", blen1);
127
        blen1 = 0;
128
    }
129

    
130
    if (!p2 && blen2) {
131
        dolog ("warning: !p2 && blen2=%ld\n", blen2);
132
        blen2 = 0;
133
    }
134

    
135
    *p1p = p1;
136
    *p2p = p2;
137
    *blen1p = blen1;
138
    *blen2p = blen2;
139
    return 0;
140

    
141
 fail:
142
    *p1p = NULL - 1;
143
    *p2p = NULL - 1;
144
    *blen1p = -1;
145
    *blen2p = -1;
146
    return -1;
147
}
148

    
149
#ifdef DSBTYPE_IN
150
static void dsound_fini_in (HWVoiceIn *hw)
151
#else
152
static void dsound_fini_out (HWVoiceOut *hw)
153
#endif
154
{
155
    HRESULT hr;
156
#ifdef DSBTYPE_IN
157
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
158
#else
159
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
160
#endif
161

    
162
    if (ds->FIELD) {
163
        hr = glue (IFACE, _Stop) (ds->FIELD);
164
        if (FAILED (hr)) {
165
            dsound_logerr (hr, "Could not stop " NAME "\n");
166
        }
167

    
168
        hr = glue (IFACE, _Release) (ds->FIELD);
169
        if (FAILED (hr)) {
170
            dsound_logerr (hr, "Could not release " NAME "\n");
171
        }
172
        ds->FIELD = NULL;
173
    }
174
}
175

    
176
#ifdef DSBTYPE_IN
177
static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
178
#else
179
static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
180
#endif
181
{
182
    int err;
183
    HRESULT hr;
184
    dsound *s = &glob_dsound;
185
    WAVEFORMATEX wfx;
186
    struct audsettings obt_as;
187
#ifdef DSBTYPE_IN
188
    const char *typ = "ADC";
189
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
190
    DSCBUFFERDESC bd;
191
    DSCBCAPS bc;
192
#else
193
    const char *typ = "DAC";
194
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
195
    DSBUFFERDESC bd;
196
    DSBCAPS bc;
197
#endif
198

    
199
    if (!s->FIELD2) {
200
        dolog ("Attempt to initialize voice without " NAME2 " object\n");
201
        return -1;
202
    }
203

    
204
    err = waveformat_from_audio_settings (&wfx, as);
205
    if (err) {
206
        return -1;
207
    }
208

    
209
    memset (&bd, 0, sizeof (bd));
210
    bd.dwSize = sizeof (bd);
211
    bd.lpwfxFormat = &wfx;
212
#ifdef DSBTYPE_IN
213
    bd.dwBufferBytes = conf.bufsize_in;
214
    hr = IDirectSoundCapture_CreateCaptureBuffer (
215
        s->dsound_capture,
216
        &bd,
217
        &ds->dsound_capture_buffer,
218
        NULL
219
        );
220
#else
221
    bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
222
    bd.dwBufferBytes = conf.bufsize_out;
223
    hr = IDirectSound_CreateSoundBuffer (
224
        s->dsound,
225
        &bd,
226
        &ds->dsound_buffer,
227
        NULL
228
        );
229
#endif
230

    
231
    if (FAILED (hr)) {
232
        dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
233
        return -1;
234
    }
235

    
236
    hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
237
    if (FAILED (hr)) {
238
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
239
        goto fail0;
240
    }
241

    
242
#ifdef DEBUG_DSOUND
243
    dolog (NAME "\n");
244
    print_wave_format (&wfx);
245
#endif
246

    
247
    memset (&bc, 0, sizeof (bc));
248
    bc.dwSize = sizeof (bc);
249

    
250
    hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
251
    if (FAILED (hr)) {
252
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
253
        goto fail0;
254
    }
255

    
256
    err = waveformat_to_audio_settings (&wfx, &obt_as);
257
    if (err) {
258
        goto fail0;
259
    }
260

    
261
    ds->first_time = 1;
262
    obt_as.endianness = 0;
263
    audio_pcm_init_info (&hw->info, &obt_as);
264

    
265
    if (bc.dwBufferBytes & hw->info.align) {
266
        dolog (
267
            "GetCaps returned misaligned buffer size %ld, alignment %d\n",
268
            bc.dwBufferBytes, hw->info.align + 1
269
            );
270
    }
271
    hw->samples = bc.dwBufferBytes >> hw->info.shift;
272

    
273
#ifdef DEBUG_DSOUND
274
    dolog ("caps %ld, desc %ld\n",
275
           bc.dwBufferBytes, bd.dwBufferBytes);
276

    
277
    dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
278
           hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
279
#endif
280
    return 0;
281

    
282
 fail0:
283
    glue (dsound_fini_, TYPE) (hw);
284
    return -1;
285
}
286

    
287
#undef NAME
288
#undef NAME2
289
#undef TYPE
290
#undef IFACE
291
#undef BUFPTR
292
#undef FIELD
293
#undef FIELD2