blob: 0678f2de38beb64a4a9725d8266d5cbe49fe1e97 [file] [log] [blame]
bellard1d14ffa2005-10-30 18:58:22 +00001/*
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"
balrogca9cc282008-01-14 04:24:29 +000026#define NAME2 "DirectSoundCapture"
bellard1d14ffa2005-10-30 18:58:22 +000027#define TYPE in
28#define IFACE IDirectSoundCaptureBuffer
29#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
30#define FIELD dsound_capture_buffer
balrogca9cc282008-01-14 04:24:29 +000031#define FIELD2 dsound_capture
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +020032#define HWVOICE HWVoiceIn
33#define DSOUNDVOICE DSoundVoiceIn
bellard1d14ffa2005-10-30 18:58:22 +000034#else
35#define NAME "playback buffer"
balrogca9cc282008-01-14 04:24:29 +000036#define NAME2 "DirectSound"
bellard1d14ffa2005-10-30 18:58:22 +000037#define TYPE out
38#define IFACE IDirectSoundBuffer
39#define BUFPTR LPDIRECTSOUNDBUFFER
40#define FIELD dsound_buffer
balrogca9cc282008-01-14 04:24:29 +000041#define FIELD2 dsound
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +020042#define HWVOICE HWVoiceOut
43#define DSOUNDVOICE DSoundVoiceOut
bellard1d14ffa2005-10-30 18:58:22 +000044#endif
45
46static int glue (dsound_unlock_, TYPE) (
47 BUFPTR buf,
48 LPVOID p1,
49 LPVOID p2,
50 DWORD blen1,
51 DWORD blen2
52 )
53{
54 HRESULT hr;
55
56 hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
57 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +000058 dsound_logerr (hr, "Could not unlock " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +000059 return -1;
60 }
61
62 return 0;
63}
64
65static int glue (dsound_lock_, TYPE) (
66 BUFPTR buf,
67 struct audio_pcm_info *info,
68 DWORD pos,
69 DWORD len,
70 LPVOID *p1p,
71 LPVOID *p2p,
72 DWORD *blen1p,
73 DWORD *blen2p,
Kővágó, Zoltán191e1f02015-06-03 23:03:52 +020074 int entire,
75 dsound *s
bellard1d14ffa2005-10-30 18:58:22 +000076 )
77{
78 HRESULT hr;
bellard8ead62c2006-07-04 16:51:32 +000079 DWORD flag;
bellard1d14ffa2005-10-30 18:58:22 +000080
bellard8ead62c2006-07-04 16:51:32 +000081#ifdef DSBTYPE_IN
82 flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
83#else
84 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
85#endif
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +020086 hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
bellard1d14ffa2005-10-30 18:58:22 +000087
Kővágó, Zoltán27629552015-06-12 14:33:04 +020088 if (FAILED (hr)) {
bellard1d14ffa2005-10-30 18:58:22 +000089#ifndef DSBTYPE_IN
Kővágó, Zoltán27629552015-06-12 14:33:04 +020090 if (hr == DSERR_BUFFERLOST) {
91 if (glue (dsound_restore_, TYPE) (buf, s)) {
92 dsound_logerr (hr, "Could not lock " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +000093 }
bellard1d14ffa2005-10-30 18:58:22 +000094 goto fail;
95 }
Kővágó, Zoltán27629552015-06-12 14:33:04 +020096#endif
97 dsound_logerr (hr, "Could not lock " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +000098 goto fail;
99 }
100
Kővágó, Zoltán2b9cce82019-10-13 21:58:02 +0200101 if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) ||
102 (p2p && *p2p && (*blen2p % info->bytes_per_frame))) {
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200103 dolog("DirectSound returned misaligned buffer %ld %ld\n",
104 *blen1p, *blen2p);
105 glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
106 blen2p ? *blen2p : 0);
bellard1d14ffa2005-10-30 18:58:22 +0000107 goto fail;
108 }
109
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200110 if (p1p && !*p1p && *blen1p) {
111 dolog("warning: !p1 && blen1=%ld\n", *blen1p);
112 *blen1p = 0;
bellard1d14ffa2005-10-30 18:58:22 +0000113 }
114
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200115 if (p2p && !*p2p && *blen2p) {
116 dolog("warning: !p2 && blen2=%ld\n", *blen2p);
117 *blen2p = 0;
bellard1d14ffa2005-10-30 18:58:22 +0000118 }
119
bellard1d14ffa2005-10-30 18:58:22 +0000120 return 0;
121
122 fail:
123 *p1p = NULL - 1;
bellard1d14ffa2005-10-30 18:58:22 +0000124 *blen1p = -1;
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200125 if (p2p) {
126 *p2p = NULL - 1;
127 *blen2p = -1;
128 }
bellard1d14ffa2005-10-30 18:58:22 +0000129 return -1;
130}
131
132#ifdef DSBTYPE_IN
133static void dsound_fini_in (HWVoiceIn *hw)
134#else
135static void dsound_fini_out (HWVoiceOut *hw)
136#endif
137{
138 HRESULT hr;
139#ifdef DSBTYPE_IN
140 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
141#else
142 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
143#endif
144
145 if (ds->FIELD) {
146 hr = glue (IFACE, _Stop) (ds->FIELD);
147 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +0000148 dsound_logerr (hr, "Could not stop " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +0000149 }
150
151 hr = glue (IFACE, _Release) (ds->FIELD);
152 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +0000153 dsound_logerr (hr, "Could not release " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +0000154 }
155 ds->FIELD = NULL;
156 }
157}
158
159#ifdef DSBTYPE_IN
Kővágó, Zoltán5706db12015-06-03 23:03:47 +0200160static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
161 void *drv_opaque)
bellard1d14ffa2005-10-30 18:58:22 +0000162#else
Kővágó, Zoltán5706db12015-06-03 23:03:47 +0200163static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
164 void *drv_opaque)
bellard1d14ffa2005-10-30 18:58:22 +0000165#endif
166{
167 int err;
168 HRESULT hr;
Kővágó, Zoltán191e1f02015-06-03 23:03:52 +0200169 dsound *s = drv_opaque;
bellard1d14ffa2005-10-30 18:58:22 +0000170 WAVEFORMATEX wfx;
malc1ea879e2008-12-03 22:48:44 +0000171 struct audsettings obt_as;
bellard1d14ffa2005-10-30 18:58:22 +0000172#ifdef DSBTYPE_IN
173 const char *typ = "ADC";
174 DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
175 DSCBUFFERDESC bd;
176 DSCBCAPS bc;
Kővágó, Zoltán4a3b8b32019-03-08 23:34:18 +0100177 AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
bellard1d14ffa2005-10-30 18:58:22 +0000178#else
179 const char *typ = "DAC";
180 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
181 DSBUFFERDESC bd;
182 DSBCAPS bc;
Kővágó, Zoltán4a3b8b32019-03-08 23:34:18 +0100183 AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
bellard1d14ffa2005-10-30 18:58:22 +0000184#endif
185
balrogca9cc282008-01-14 04:24:29 +0000186 if (!s->FIELD2) {
balrog26463db2008-01-17 21:47:25 +0000187 dolog ("Attempt to initialize voice without " NAME2 " object\n");
balrogca9cc282008-01-14 04:24:29 +0000188 return -1;
189 }
190
bellardc0fe3822005-11-05 18:55:28 +0000191 err = waveformat_from_audio_settings (&wfx, as);
bellard1d14ffa2005-10-30 18:58:22 +0000192 if (err) {
193 return -1;
194 }
195
196 memset (&bd, 0, sizeof (bd));
197 bd.dwSize = sizeof (bd);
198 bd.lpwfxFormat = &wfx;
Kővágó, Zoltán4a3b8b32019-03-08 23:34:18 +0100199 bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880);
bellard1d14ffa2005-10-30 18:58:22 +0000200#ifdef DSBTYPE_IN
bellard1d14ffa2005-10-30 18:58:22 +0000201 hr = IDirectSoundCapture_CreateCaptureBuffer (
202 s->dsound_capture,
203 &bd,
204 &ds->dsound_capture_buffer,
205 NULL
206 );
207#else
Volker Rümelin401dcf02021-01-10 11:02:36 +0100208 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
bellard1d14ffa2005-10-30 18:58:22 +0000209 hr = IDirectSound_CreateSoundBuffer (
210 s->dsound,
211 &bd,
212 &ds->dsound_buffer,
213 NULL
214 );
215#endif
216
217 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +0000218 dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
bellard1d14ffa2005-10-30 18:58:22 +0000219 return -1;
220 }
221
bellardc0fe3822005-11-05 18:55:28 +0000222 hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
bellard1d14ffa2005-10-30 18:58:22 +0000223 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +0000224 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
bellard1d14ffa2005-10-30 18:58:22 +0000225 goto fail0;
226 }
227
228#ifdef DEBUG_DSOUND
229 dolog (NAME "\n");
230 print_wave_format (&wfx);
231#endif
232
233 memset (&bc, 0, sizeof (bc));
234 bc.dwSize = sizeof (bc);
235
236 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
237 if (FAILED (hr)) {
bellardc0fe3822005-11-05 18:55:28 +0000238 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
bellard1d14ffa2005-10-30 18:58:22 +0000239 goto fail0;
240 }
241
bellardc0fe3822005-11-05 18:55:28 +0000242 err = waveformat_to_audio_settings (&wfx, &obt_as);
bellard1d14ffa2005-10-30 18:58:22 +0000243 if (err) {
244 goto fail0;
245 }
246
Kővágó, Zoltánfb35c2c2020-02-03 00:02:23 +0100247 ds->first_time = true;
bellardd929eba2006-07-04 21:47:22 +0000248 obt_as.endianness = 0;
249 audio_pcm_init_info (&hw->info, &obt_as);
bellardc0fe3822005-11-05 18:55:28 +0000250
Kővágó, Zoltán2b9cce82019-10-13 21:58:02 +0200251 if (bc.dwBufferBytes % hw->info.bytes_per_frame) {
bellardc0fe3822005-11-05 18:55:28 +0000252 dolog (
253 "GetCaps returned misaligned buffer size %ld, alignment %d\n",
Kővágó, Zoltán2b9cce82019-10-13 21:58:02 +0200254 bc.dwBufferBytes, hw->info.bytes_per_frame
bellardc0fe3822005-11-05 18:55:28 +0000255 );
256 }
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200257 hw->size_emul = bc.dwBufferBytes;
Kővágó, Zoltán2b9cce82019-10-13 21:58:02 +0200258 hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
Kővágó, Zoltán191e1f02015-06-03 23:03:52 +0200259 ds->s = s;
bellard1d14ffa2005-10-30 18:58:22 +0000260
261#ifdef DEBUG_DSOUND
262 dolog ("caps %ld, desc %ld\n",
263 bc.dwBufferBytes, bd.dwBufferBytes);
bellard1d14ffa2005-10-30 18:58:22 +0000264#endif
265 return 0;
266
267 fail0:
268 glue (dsound_fini_, TYPE) (hw);
269 return -1;
270}
271
272#undef NAME
malc832e9072009-01-22 22:09:55 +0000273#undef NAME2
bellard1d14ffa2005-10-30 18:58:22 +0000274#undef TYPE
275#undef IFACE
276#undef BUFPTR
277#undef FIELD
malc832e9072009-01-22 22:09:55 +0000278#undef FIELD2
Kővágó, Zoltán7fa97542019-09-19 23:24:12 +0200279#undef HWVOICE
280#undef DSOUNDVOICE