11d14ffa9Sbellard /* 21d14ffa9Sbellard * QEMU DirectSound audio driver header 31d14ffa9Sbellard * 41d14ffa9Sbellard * Copyright (c) 2005 Vassili Karpov (malc) 51d14ffa9Sbellard * 61d14ffa9Sbellard * Permission is hereby granted, free of charge, to any person obtaining a copy 71d14ffa9Sbellard * of this software and associated documentation files (the "Software"), to deal 81d14ffa9Sbellard * in the Software without restriction, including without limitation the rights 91d14ffa9Sbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 101d14ffa9Sbellard * copies of the Software, and to permit persons to whom the Software is 111d14ffa9Sbellard * furnished to do so, subject to the following conditions: 121d14ffa9Sbellard * 131d14ffa9Sbellard * The above copyright notice and this permission notice shall be included in 141d14ffa9Sbellard * all copies or substantial portions of the Software. 151d14ffa9Sbellard * 161d14ffa9Sbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171d14ffa9Sbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181d14ffa9Sbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 191d14ffa9Sbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201d14ffa9Sbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 211d14ffa9Sbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 221d14ffa9Sbellard * THE SOFTWARE. 231d14ffa9Sbellard */ 241d14ffa9Sbellard #ifdef DSBTYPE_IN 251d14ffa9Sbellard #define NAME "capture buffer" 26ca9cc28cSbalrog #define NAME2 "DirectSoundCapture" 271d14ffa9Sbellard #define TYPE in 281d14ffa9Sbellard #define IFACE IDirectSoundCaptureBuffer 291d14ffa9Sbellard #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER 301d14ffa9Sbellard #define FIELD dsound_capture_buffer 31ca9cc28cSbalrog #define FIELD2 dsound_capture 327fa9754aSKővágó, Zoltán #define HWVOICE HWVoiceIn 337fa9754aSKővágó, Zoltán #define DSOUNDVOICE DSoundVoiceIn 341d14ffa9Sbellard #else 351d14ffa9Sbellard #define NAME "playback buffer" 36ca9cc28cSbalrog #define NAME2 "DirectSound" 371d14ffa9Sbellard #define TYPE out 381d14ffa9Sbellard #define IFACE IDirectSoundBuffer 391d14ffa9Sbellard #define BUFPTR LPDIRECTSOUNDBUFFER 401d14ffa9Sbellard #define FIELD dsound_buffer 41ca9cc28cSbalrog #define FIELD2 dsound 427fa9754aSKővágó, Zoltán #define HWVOICE HWVoiceOut 437fa9754aSKővágó, Zoltán #define DSOUNDVOICE DSoundVoiceOut 441d14ffa9Sbellard #endif 451d14ffa9Sbellard 461d14ffa9Sbellard static int glue (dsound_unlock_, TYPE) ( 471d14ffa9Sbellard BUFPTR buf, 481d14ffa9Sbellard LPVOID p1, 491d14ffa9Sbellard LPVOID p2, 501d14ffa9Sbellard DWORD blen1, 511d14ffa9Sbellard DWORD blen2 521d14ffa9Sbellard ) 531d14ffa9Sbellard { 541d14ffa9Sbellard HRESULT hr; 551d14ffa9Sbellard 561d14ffa9Sbellard hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2); 571d14ffa9Sbellard if (FAILED (hr)) { 58c0fe3827Sbellard dsound_logerr (hr, "Could not unlock " NAME "\n"); 591d14ffa9Sbellard return -1; 601d14ffa9Sbellard } 611d14ffa9Sbellard 621d14ffa9Sbellard return 0; 631d14ffa9Sbellard } 641d14ffa9Sbellard 651d14ffa9Sbellard static int glue (dsound_lock_, TYPE) ( 661d14ffa9Sbellard BUFPTR buf, 671d14ffa9Sbellard struct audio_pcm_info *info, 681d14ffa9Sbellard DWORD pos, 691d14ffa9Sbellard DWORD len, 701d14ffa9Sbellard LPVOID *p1p, 711d14ffa9Sbellard LPVOID *p2p, 721d14ffa9Sbellard DWORD *blen1p, 731d14ffa9Sbellard DWORD *blen2p, 74191e1f0aSKővágó, Zoltán int entire, 75191e1f0aSKővágó, Zoltán dsound *s 761d14ffa9Sbellard ) 771d14ffa9Sbellard { 781d14ffa9Sbellard HRESULT hr; 798ead62cfSbellard DWORD flag; 801d14ffa9Sbellard 818ead62cfSbellard #ifdef DSBTYPE_IN 828ead62cfSbellard flag = entire ? DSCBLOCK_ENTIREBUFFER : 0; 838ead62cfSbellard #else 848ead62cfSbellard flag = entire ? DSBLOCK_ENTIREBUFFER : 0; 858ead62cfSbellard #endif 867fa9754aSKővágó, Zoltán hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag); 871d14ffa9Sbellard 881d14ffa9Sbellard if (FAILED (hr)) { 891d14ffa9Sbellard #ifndef DSBTYPE_IN 901d14ffa9Sbellard if (hr == DSERR_BUFFERLOST) { 91191e1f0aSKővágó, Zoltán if (glue (dsound_restore_, TYPE) (buf, s)) { 92c0fe3827Sbellard dsound_logerr (hr, "Could not lock " NAME "\n"); 931d14ffa9Sbellard } 942762955fSKővágó, Zoltán goto fail; 951d14ffa9Sbellard } 961d14ffa9Sbellard #endif 97c0fe3827Sbellard dsound_logerr (hr, "Could not lock " NAME "\n"); 981d14ffa9Sbellard goto fail; 991d14ffa9Sbellard } 1001d14ffa9Sbellard 101*2b9cce8cSKővágó, Zoltán if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) || 102*2b9cce8cSKővágó, Zoltán (p2p && *p2p && (*blen2p % info->bytes_per_frame))) { 1031d14ffa9Sbellard dolog("DirectSound returned misaligned buffer %ld %ld\n", 1047fa9754aSKővágó, Zoltán *blen1p, *blen2p); 1057fa9754aSKővágó, Zoltán glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p, 1067fa9754aSKővágó, Zoltán blen2p ? *blen2p : 0); 1071d14ffa9Sbellard goto fail; 1081d14ffa9Sbellard } 1091d14ffa9Sbellard 1107fa9754aSKővágó, Zoltán if (p1p && !*p1p && *blen1p) { 1117fa9754aSKővágó, Zoltán dolog("warning: !p1 && blen1=%ld\n", *blen1p); 1127fa9754aSKővágó, Zoltán *blen1p = 0; 1131d14ffa9Sbellard } 1141d14ffa9Sbellard 1157fa9754aSKővágó, Zoltán if (p2p && !*p2p && *blen2p) { 1167fa9754aSKővágó, Zoltán dolog("warning: !p2 && blen2=%ld\n", *blen2p); 1177fa9754aSKővágó, Zoltán *blen2p = 0; 1181d14ffa9Sbellard } 1191d14ffa9Sbellard 1201d14ffa9Sbellard return 0; 1211d14ffa9Sbellard 1221d14ffa9Sbellard fail: 1231d14ffa9Sbellard *p1p = NULL - 1; 1241d14ffa9Sbellard *blen1p = -1; 1257fa9754aSKővágó, Zoltán if (p2p) { 1267fa9754aSKővágó, Zoltán *p2p = NULL - 1; 1271d14ffa9Sbellard *blen2p = -1; 1287fa9754aSKővágó, Zoltán } 1291d14ffa9Sbellard return -1; 1301d14ffa9Sbellard } 1311d14ffa9Sbellard 1321d14ffa9Sbellard #ifdef DSBTYPE_IN 1331d14ffa9Sbellard static void dsound_fini_in (HWVoiceIn *hw) 1341d14ffa9Sbellard #else 1351d14ffa9Sbellard static void dsound_fini_out (HWVoiceOut *hw) 1361d14ffa9Sbellard #endif 1371d14ffa9Sbellard { 1381d14ffa9Sbellard HRESULT hr; 1391d14ffa9Sbellard #ifdef DSBTYPE_IN 1401d14ffa9Sbellard DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; 1411d14ffa9Sbellard #else 1421d14ffa9Sbellard DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 1431d14ffa9Sbellard #endif 1441d14ffa9Sbellard 1451d14ffa9Sbellard if (ds->FIELD) { 1461d14ffa9Sbellard hr = glue (IFACE, _Stop) (ds->FIELD); 1471d14ffa9Sbellard if (FAILED (hr)) { 148c0fe3827Sbellard dsound_logerr (hr, "Could not stop " NAME "\n"); 1491d14ffa9Sbellard } 1501d14ffa9Sbellard 1511d14ffa9Sbellard hr = glue (IFACE, _Release) (ds->FIELD); 1521d14ffa9Sbellard if (FAILED (hr)) { 153c0fe3827Sbellard dsound_logerr (hr, "Could not release " NAME "\n"); 1541d14ffa9Sbellard } 1551d14ffa9Sbellard ds->FIELD = NULL; 1561d14ffa9Sbellard } 1571d14ffa9Sbellard } 1581d14ffa9Sbellard 1591d14ffa9Sbellard #ifdef DSBTYPE_IN 1605706db1dSKővágó, Zoltán static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as, 1615706db1dSKővágó, Zoltán void *drv_opaque) 1621d14ffa9Sbellard #else 1635706db1dSKővágó, Zoltán static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, 1645706db1dSKővágó, Zoltán void *drv_opaque) 1651d14ffa9Sbellard #endif 1661d14ffa9Sbellard { 1671d14ffa9Sbellard int err; 1681d14ffa9Sbellard HRESULT hr; 169191e1f0aSKővágó, Zoltán dsound *s = drv_opaque; 1701d14ffa9Sbellard WAVEFORMATEX wfx; 1711ea879e5Smalc struct audsettings obt_as; 1721d14ffa9Sbellard #ifdef DSBTYPE_IN 1731d14ffa9Sbellard const char *typ = "ADC"; 1741d14ffa9Sbellard DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; 1751d14ffa9Sbellard DSCBUFFERDESC bd; 1761d14ffa9Sbellard DSCBCAPS bc; 1774a3b8b34SKővágó, Zoltán AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in; 1781d14ffa9Sbellard #else 1791d14ffa9Sbellard const char *typ = "DAC"; 1801d14ffa9Sbellard DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 1811d14ffa9Sbellard DSBUFFERDESC bd; 1821d14ffa9Sbellard DSBCAPS bc; 1834a3b8b34SKővágó, Zoltán AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out; 1841d14ffa9Sbellard #endif 1851d14ffa9Sbellard 186ca9cc28cSbalrog if (!s->FIELD2) { 18726463dbcSbalrog dolog ("Attempt to initialize voice without " NAME2 " object\n"); 188ca9cc28cSbalrog return -1; 189ca9cc28cSbalrog } 190ca9cc28cSbalrog 191c0fe3827Sbellard err = waveformat_from_audio_settings (&wfx, as); 1921d14ffa9Sbellard if (err) { 1931d14ffa9Sbellard return -1; 1941d14ffa9Sbellard } 1951d14ffa9Sbellard 1961d14ffa9Sbellard memset (&bd, 0, sizeof (bd)); 1971d14ffa9Sbellard bd.dwSize = sizeof (bd); 1981d14ffa9Sbellard bd.lpwfxFormat = &wfx; 1994a3b8b34SKővágó, Zoltán bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880); 2001d14ffa9Sbellard #ifdef DSBTYPE_IN 2011d14ffa9Sbellard hr = IDirectSoundCapture_CreateCaptureBuffer ( 2021d14ffa9Sbellard s->dsound_capture, 2031d14ffa9Sbellard &bd, 2041d14ffa9Sbellard &ds->dsound_capture_buffer, 2051d14ffa9Sbellard NULL 2061d14ffa9Sbellard ); 2071d14ffa9Sbellard #else 2081d14ffa9Sbellard bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; 2091d14ffa9Sbellard hr = IDirectSound_CreateSoundBuffer ( 2101d14ffa9Sbellard s->dsound, 2111d14ffa9Sbellard &bd, 2121d14ffa9Sbellard &ds->dsound_buffer, 2131d14ffa9Sbellard NULL 2141d14ffa9Sbellard ); 2151d14ffa9Sbellard #endif 2161d14ffa9Sbellard 2171d14ffa9Sbellard if (FAILED (hr)) { 218c0fe3827Sbellard dsound_logerr2 (hr, typ, "Could not create " NAME "\n"); 2191d14ffa9Sbellard return -1; 2201d14ffa9Sbellard } 2211d14ffa9Sbellard 222c0fe3827Sbellard hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL); 2231d14ffa9Sbellard if (FAILED (hr)) { 224c0fe3827Sbellard dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); 2251d14ffa9Sbellard goto fail0; 2261d14ffa9Sbellard } 2271d14ffa9Sbellard 2281d14ffa9Sbellard #ifdef DEBUG_DSOUND 2291d14ffa9Sbellard dolog (NAME "\n"); 2301d14ffa9Sbellard print_wave_format (&wfx); 2311d14ffa9Sbellard #endif 2321d14ffa9Sbellard 2331d14ffa9Sbellard memset (&bc, 0, sizeof (bc)); 2341d14ffa9Sbellard bc.dwSize = sizeof (bc); 2351d14ffa9Sbellard 2361d14ffa9Sbellard hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc); 2371d14ffa9Sbellard if (FAILED (hr)) { 238c0fe3827Sbellard dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); 2391d14ffa9Sbellard goto fail0; 2401d14ffa9Sbellard } 2411d14ffa9Sbellard 242c0fe3827Sbellard err = waveformat_to_audio_settings (&wfx, &obt_as); 2431d14ffa9Sbellard if (err) { 2441d14ffa9Sbellard goto fail0; 2451d14ffa9Sbellard } 2461d14ffa9Sbellard 247d929eba5Sbellard obt_as.endianness = 0; 248d929eba5Sbellard audio_pcm_init_info (&hw->info, &obt_as); 249c0fe3827Sbellard 250*2b9cce8cSKővágó, Zoltán if (bc.dwBufferBytes % hw->info.bytes_per_frame) { 251c0fe3827Sbellard dolog ( 252c0fe3827Sbellard "GetCaps returned misaligned buffer size %ld, alignment %d\n", 253*2b9cce8cSKővágó, Zoltán bc.dwBufferBytes, hw->info.bytes_per_frame 2541d14ffa9Sbellard ); 255c0fe3827Sbellard } 2567fa9754aSKővágó, Zoltán hw->size_emul = bc.dwBufferBytes; 257*2b9cce8cSKővágó, Zoltán hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame; 258191e1f0aSKővágó, Zoltán ds->s = s; 2591d14ffa9Sbellard 2601d14ffa9Sbellard #ifdef DEBUG_DSOUND 2611d14ffa9Sbellard dolog ("caps %ld, desc %ld\n", 2621d14ffa9Sbellard bc.dwBufferBytes, bd.dwBufferBytes); 2631d14ffa9Sbellard #endif 2641d14ffa9Sbellard return 0; 2651d14ffa9Sbellard 2661d14ffa9Sbellard fail0: 2671d14ffa9Sbellard glue (dsound_fini_, TYPE) (hw); 2681d14ffa9Sbellard return -1; 2691d14ffa9Sbellard } 2701d14ffa9Sbellard 2711d14ffa9Sbellard #undef NAME 272832e9079Smalc #undef NAME2 2731d14ffa9Sbellard #undef TYPE 2741d14ffa9Sbellard #undef IFACE 2751d14ffa9Sbellard #undef BUFPTR 2761d14ffa9Sbellard #undef FIELD 277832e9079Smalc #undef FIELD2 2787fa9754aSKővágó, Zoltán #undef HWVOICE 2797fa9754aSKővágó, Zoltán #undef DSOUNDVOICE 280