VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/dsound_template.h@ 53392

Last change on this file since 53392 was 53392, checked in by vboxsync, 10 years ago

Devices/Audio: handle host audio input device disconnect in the DirectSound backend.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/* $Id: dsound_template.h 53392 2014-11-24 19:35:57Z vboxsync $ */
2
3/*
4 * Copyright (C) 2014 Oracle Corporation
5 *
6 * This file is part of VirtualBox Open Source Edition (OSE), as
7 * available from http://www.virtualbox.org. This file is free software;
8 * you can redistribute it and/or modify it under the terms of the GNU
9 * General Public License (GPL) as published by the Free Software
10 * Foundation, in version 2 as it comes in the "COPYING" file of the
11 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
12 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13 * --------------------------------------------------------------------
14 *
15 * This code is based on: audio.h
16 *
17 * QEMU DirectSound audio driver header
18 *
19 * Copyright (c) 2005 Vassili Karpov (malc)
20 *
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 * THE SOFTWARE.
38 */
39#ifdef DSBTYPE_IN
40#define NAME "capture buffer"
41#define TYPE in
42#define IFACE IDirectSoundCaptureBuffer
43#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
44#define FIELD dsound_capture_buffer
45#else
46#define NAME "playback buffer"
47#define TYPE out
48#define IFACE IDirectSoundBuffer
49#define BUFPTR LPDIRECTSOUNDBUFFER
50#define FIELD dsound_buffer
51#endif
52
53static int glue (dsound_unlock_, TYPE) (
54 BUFPTR buf,
55 LPVOID p1,
56 LPVOID p2,
57 DWORD blen1,
58 DWORD blen2
59 )
60{
61 HRESULT hr;
62
63 hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
64 if (FAILED (hr)) {
65 dsound_logerr (hr, "Could not unlock " NAME "\n");
66 return -1;
67 }
68
69 return 0;
70}
71
72static int glue (dsound_lock_, TYPE) (
73 BUFPTR buf,
74 struct audio_pcm_info *info,
75 DWORD pos,
76 DWORD len,
77 LPVOID *p1p,
78 LPVOID *p2p,
79 DWORD *blen1p,
80 DWORD *blen2p,
81 int entire
82 )
83{
84 HRESULT hr;
85 int i;
86 LPVOID p1 = NULL, p2 = NULL;
87 DWORD blen1 = 0, blen2 = 0;
88 DWORD flag;
89
90#ifdef DSBTYPE_IN
91 flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
92#else
93 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
94#endif
95
96 for (i = 0; i < conf.lock_retries; ++i) {
97 hr = glue (IFACE, _Lock) (
98 buf,
99 pos,
100 len,
101 &p1,
102 &blen1,
103 &p2,
104 &blen2,
105 flag
106 );
107
108 if (FAILED (hr)) {
109#ifndef DSBTYPE_IN
110 if (hr == DSERR_BUFFERLOST) {
111 if (glue (dsound_restore_, TYPE) (buf)) {
112 dsound_logerr (hr, "Could not lock " NAME "\n");
113 goto fail;
114 }
115 continue;
116 }
117#endif
118 dsound_logerr (hr, "Could not lock " NAME "\n");
119 goto fail;
120 }
121
122 break;
123 }
124
125 if (i == conf.lock_retries) {
126 dolog ("%d attempts to lock " NAME " failed\n", i);
127 goto fail;
128 }
129
130 if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
131 dolog ("DirectSound returned misaligned buffer %ld %ld\n",
132 blen1, blen2);
133 glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
134 goto fail;
135 }
136
137 if (!p1 && blen1) {
138 dolog ("warning: !p1 && blen1=%ld\n", blen1);
139 blen1 = 0;
140 }
141
142 if (!p2 && blen2) {
143 dolog ("warning: !p2 && blen2=%ld\n", blen2);
144 blen2 = 0;
145 }
146
147 *p1p = p1;
148 *p2p = p2;
149 *blen1p = blen1;
150 *blen2p = blen2;
151 return 0;
152
153 fail:
154 *p1p = NULL;
155 *p2p = NULL;
156 *blen1p = -1;
157 *blen2p = -1;
158 return -1;
159}
160
161#ifdef DSBTYPE_IN
162static void dsound_fini_in (HWVoiceIn *hw)
163{
164 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
165 dsoundCaptureClose (ds);
166 ds->last_read_pos = 0;
167 ds->capture_buffer_size = 0;
168 memset (&ds->as, 0, sizeof(ds->as));
169}
170#else
171static void dsound_fini_out (HWVoiceOut *hw)
172{
173 HRESULT hr;
174 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
175
176 if (ds->FIELD) {
177 hr = glue (IFACE, _Stop) (ds->FIELD);
178 if (FAILED (hr)) {
179 dsound_logerr (hr, "Could not stop " NAME "\n");
180 }
181
182 hr = glue (IFACE, _Release) (ds->FIELD);
183 if (FAILED (hr)) {
184 dsound_logerr (hr, "Could not release " NAME "\n");
185 }
186 ds->FIELD = NULL;
187 }
188}
189#endif
190
191#ifdef DSBTYPE_IN
192static int dsound_init_in (HWVoiceIn *hw, audsettings_t *as)
193{
194 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
195
196 ds->last_read_pos = 0;
197 ds->capture_buffer_size = 0;
198 ds->dsound_capture_buffer = NULL;
199 ds->as = *as;
200
201 /* Init default settings. */
202 audio_pcm_init_info (&hw->info, &ds->as);
203 hw->samples = conf.bufsize_in >> hw->info.shift;
204
205 /* Try to open capture in case the device is already there. */
206 dsoundCaptureOpen (ds);
207
208 return 0;
209}
210#else
211static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
212{
213 int err;
214 HRESULT hr;
215 dsound *s = &glob_dsound;
216 WAVEFORMATEX wfx;
217 audsettings_t obt_as;
218 const char *typ = "DAC";
219 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
220 DSBUFFERDESC bd;
221 DSBCAPS bc;
222
223 err = waveformat_from_audio_settings (&wfx, as);
224 if (err) {
225 return -1;
226 }
227
228 memset (&bd, 0, sizeof (bd));
229 bd.dwSize = sizeof (bd);
230 bd.lpwfxFormat = &wfx;
231 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
232 bd.dwBufferBytes = conf.bufsize_out;
233 hr = IDirectSound_CreateSoundBuffer (
234 s->dsound,
235 &bd,
236 &ds->dsound_buffer,
237 NULL
238 );
239
240 if (FAILED (hr)) {
241 dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
242 return -1;
243 }
244
245 hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
246 if (FAILED (hr)) {
247 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
248 goto fail0;
249 }
250
251#ifdef DEBUG_DSOUND
252 dolog (NAME "\n");
253 print_wave_format (&wfx);
254#endif
255
256 memset (&bc, 0, sizeof (bc));
257 bc.dwSize = sizeof (bc);
258
259 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
260 if (FAILED (hr)) {
261 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
262 goto fail0;
263 }
264
265 err = waveformat_to_audio_settings (&wfx, &obt_as);
266 if (err) {
267 goto fail0;
268 }
269
270 ds->first_time = 1;
271 obt_as.endianness = 0;
272 audio_pcm_init_info (&hw->info, &obt_as);
273
274 if (bc.dwBufferBytes & hw->info.align) {
275 dolog (
276 "GetCaps returned misaligned buffer size %ld, alignment %d\n",
277 bc.dwBufferBytes, hw->info.align + 1
278 );
279 }
280 hw->samples = bc.dwBufferBytes >> hw->info.shift;
281
282#ifdef DEBUG_DSOUND
283 dolog ("caps %ld, desc %ld\n",
284 bc.dwBufferBytes, bd.dwBufferBytes);
285
286 dolog ("bufsize %d, freq %d, chan %d, bits %d, sign %d\n",
287 hw->samples << hw->info.shift,
288 hw->info.freq,
289 hw->info.nchannels,
290 hw->info.bits,
291 hw->info.sign);
292#endif
293 return 0;
294
295 fail0:
296 glue (dsound_fini_, TYPE) (hw);
297 return -1;
298}
299#endif
300
301#undef NAME
302#undef TYPE
303#undef IFACE
304#undef BUFPTR
305#undef FIELD
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette