|
|
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"
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:
74: for (i = 0; i < conf.lock_retries; ++i) {
75: hr = glue (IFACE, _Lock) (
76: buf,
77: pos,
78: len,
79: &p1,
80: &blen1,
81: &p2,
82: &blen2,
83: (entire
84: #ifdef DSBTYPE_IN
85: ? DSCBLOCK_ENTIREBUFFER
86: #else
87: ? DSBLOCK_ENTIREBUFFER
88: #endif
89: : 0)
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:
254: audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0));
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.