|
|
1.1 root 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"
1.1.1.3 ! root 26: #define NAME2 "DirectSoundCapture"
1.1 root 27: #define TYPE in
28: #define IFACE IDirectSoundCaptureBuffer
29: #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
30: #define FIELD dsound_capture_buffer
1.1.1.3 ! root 31: #define FIELD2 dsound_capture
1.1 root 32: #else
33: #define NAME "playback buffer"
1.1.1.3 ! root 34: #define NAME2 "DirectSound"
1.1 root 35: #define TYPE out
36: #define IFACE IDirectSoundBuffer
37: #define BUFPTR LPDIRECTSOUNDBUFFER
38: #define FIELD dsound_buffer
1.1.1.3 ! root 39: #define FIELD2 dsound
1.1 root 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;
1.1.1.2 root 77: DWORD flag;
1.1 root 78:
1.1.1.2 root 79: #ifdef DSBTYPE_IN
80: flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
81: #else
82: flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
83: #endif
1.1 root 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,
1.1.1.2 root 93: flag
1.1 root 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
1.1.1.3 ! root 177: static int dsound_init_in (HWVoiceIn *hw, struct audsettings *as)
1.1 root 178: #else
1.1.1.3 ! root 179: static int dsound_init_out (HWVoiceOut *hw, struct audsettings *as)
1.1 root 180: #endif
181: {
182: int err;
183: HRESULT hr;
184: dsound *s = &glob_dsound;
185: WAVEFORMATEX wfx;
1.1.1.3 ! root 186: struct audsettings obt_as;
1.1 root 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:
1.1.1.3 ! root 199: if (!s->FIELD2) {
! 200: dolog ("Attempt to initialize voice without " NAME2 " object\n");
! 201: return -1;
! 202: }
! 203:
1.1 root 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;
1.1.1.2 root 262: obt_as.endianness = 0;
263: audio_pcm_init_info (&hw->info, &obt_as);
1.1 root 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
1.1.1.3 ! root 288: #undef NAME2
1.1 root 289: #undef TYPE
290: #undef IFACE
291: #undef BUFPTR
292: #undef FIELD
1.1.1.3 ! root 293: #undef FIELD2
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.