|
|
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.