Statistics
| Branch: | Revision:

root / audio / dsound_template.h @ d929eba5

History | View | Annotate | Download (6.8 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 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

    
38
static 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, "Could not unlock " NAME "\n");
51
        return -1;
52
    }
53

    
54
    return 0;
55
}
56

    
57
static 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
    DWORD flag;
74

    
75
#ifdef DSBTYPE_IN
76
    flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
77
#else
78
    flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
79
#endif
80
    for (i = 0; i < conf.lock_retries; ++i) {
81
        hr = glue (IFACE, _Lock) (
82
            buf,
83
            pos,
84
            len,
85
            &p1,
86
            &blen1,
87
            &p2,
88
            &blen2,
89
            flag
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, "Could not lock " NAME "\n");
97
                    goto fail;
98
                }
99
                continue;
100
            }
101
#endif
102
            dsound_logerr (hr, "Could 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
146
static void dsound_fini_in (HWVoiceIn *hw)
147
#else
148
static 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, "Could not stop " NAME "\n");
162
        }
163

    
164
        hr = glue (IFACE, _Release) (ds->FIELD);
165
        if (FAILED (hr)) {
166
            dsound_logerr (hr, "Could not release " NAME "\n");
167
        }
168
        ds->FIELD = NULL;
169
    }
170
}
171

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

    
195
    err = waveformat_from_audio_settings (&wfx, as);
196
    if (err) {
197
        return -1;
198
    }
199

    
200
    memset (&bd, 0, sizeof (bd));
201
    bd.dwSize = sizeof (bd);
202
    bd.lpwfxFormat = &wfx;
203
#ifdef DSBTYPE_IN
204
    bd.dwBufferBytes = conf.bufsize_in;
205
    hr = IDirectSoundCapture_CreateCaptureBuffer (
206
        s->dsound_capture,
207
        &bd,
208
        &ds->dsound_capture_buffer,
209
        NULL
210
        );
211
#else
212
    bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
213
    bd.dwBufferBytes = conf.bufsize_out;
214
    hr = IDirectSound_CreateSoundBuffer (
215
        s->dsound,
216
        &bd,
217
        &ds->dsound_buffer,
218
        NULL
219
        );
220
#endif
221

    
222
    if (FAILED (hr)) {
223
        dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
224
        return -1;
225
    }
226

    
227
    hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
228
    if (FAILED (hr)) {
229
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
230
        goto fail0;
231
    }
232

    
233
#ifdef DEBUG_DSOUND
234
    dolog (NAME "\n");
235
    print_wave_format (&wfx);
236
#endif
237

    
238
    memset (&bc, 0, sizeof (bc));
239
    bc.dwSize = sizeof (bc);
240

    
241
    hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
242
    if (FAILED (hr)) {
243
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
244
        goto fail0;
245
    }
246

    
247
    err = waveformat_to_audio_settings (&wfx, &obt_as);
248
    if (err) {
249
        goto fail0;
250
    }
251

    
252
    ds->first_time = 1;
253
    obt_as.endianness = 0;
254
    audio_pcm_init_info (&hw->info, &obt_as);
255

    
256
    if (bc.dwBufferBytes & hw->info.align) {
257
        dolog (
258
            "GetCaps returned misaligned buffer size %ld, alignment %d\n",
259
            bc.dwBufferBytes, hw->info.align + 1
260
            );
261
    }
262
    hw->samples = bc.dwBufferBytes >> hw->info.shift;
263

    
264
#ifdef DEBUG_DSOUND
265
    dolog ("caps %ld, desc %ld\n",
266
           bc.dwBufferBytes, bd.dwBufferBytes);
267

    
268
    dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
269
           hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
270
#endif
271
    return 0;
272

    
273
 fail0:
274
    glue (dsound_fini_, TYPE) (hw);
275
    return -1;
276
}
277

    
278
#undef NAME
279
#undef TYPE
280
#undef IFACE
281
#undef BUFPTR
282
#undef FIELD