123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- /*
- * QEMU DirectSound audio driver header
- *
- * Copyright (c) 2005 Vassili Karpov (malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- #ifdef DSBTYPE_IN
- #define NAME "capture buffer"
- #define NAME2 "DirectSoundCapture"
- #define TYPE in
- #define IFACE IDirectSoundCaptureBuffer
- #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
- #define FIELD dsound_capture_buffer
- #define FIELD2 dsound_capture
- #define HWVOICE HWVoiceIn
- #define DSOUNDVOICE DSoundVoiceIn
- #else
- #define NAME "playback buffer"
- #define NAME2 "DirectSound"
- #define TYPE out
- #define IFACE IDirectSoundBuffer
- #define BUFPTR LPDIRECTSOUNDBUFFER
- #define FIELD dsound_buffer
- #define FIELD2 dsound
- #define HWVOICE HWVoiceOut
- #define DSOUNDVOICE DSoundVoiceOut
- #endif
- static int glue (dsound_unlock_, TYPE) (
- BUFPTR buf,
- LPVOID p1,
- LPVOID p2,
- DWORD blen1,
- DWORD blen2
- )
- {
- HRESULT hr;
- hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not unlock " NAME "\n");
- return -1;
- }
- return 0;
- }
- static int glue (dsound_lock_, TYPE) (
- BUFPTR buf,
- struct audio_pcm_info *info,
- DWORD pos,
- DWORD len,
- LPVOID *p1p,
- LPVOID *p2p,
- DWORD *blen1p,
- DWORD *blen2p,
- int entire,
- dsound *s
- )
- {
- HRESULT hr;
- DWORD flag;
- #ifdef DSBTYPE_IN
- flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
- #else
- flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
- #endif
- hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
- if (FAILED (hr)) {
- #ifndef DSBTYPE_IN
- if (hr == DSERR_BUFFERLOST) {
- if (glue (dsound_restore_, TYPE) (buf, s)) {
- dsound_logerr (hr, "Could not lock " NAME "\n");
- }
- goto fail;
- }
- #endif
- dsound_logerr (hr, "Could not lock " NAME "\n");
- goto fail;
- }
- if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) ||
- (p2p && *p2p && (*blen2p % info->bytes_per_frame))) {
- dolog("DirectSound returned misaligned buffer %ld %ld\n",
- *blen1p, *blen2p);
- glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
- blen2p ? *blen2p : 0);
- goto fail;
- }
- if (p1p && !*p1p && *blen1p) {
- dolog("warning: !p1 && blen1=%ld\n", *blen1p);
- *blen1p = 0;
- }
- if (p2p && !*p2p && *blen2p) {
- dolog("warning: !p2 && blen2=%ld\n", *blen2p);
- *blen2p = 0;
- }
- return 0;
- fail:
- *p1p = NULL - 1;
- *blen1p = -1;
- if (p2p) {
- *p2p = NULL - 1;
- *blen2p = -1;
- }
- return -1;
- }
- #ifdef DSBTYPE_IN
- static void dsound_fini_in (HWVoiceIn *hw)
- #else
- static void dsound_fini_out (HWVoiceOut *hw)
- #endif
- {
- HRESULT hr;
- #ifdef DSBTYPE_IN
- DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
- #else
- DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
- #endif
- if (ds->FIELD) {
- hr = glue (IFACE, _Stop) (ds->FIELD);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not stop " NAME "\n");
- }
- hr = glue (IFACE, _Release) (ds->FIELD);
- if (FAILED (hr)) {
- dsound_logerr (hr, "Could not release " NAME "\n");
- }
- ds->FIELD = NULL;
- }
- }
- #ifdef DSBTYPE_IN
- static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
- void *drv_opaque)
- #else
- static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
- void *drv_opaque)
- #endif
- {
- int err;
- HRESULT hr;
- dsound *s = drv_opaque;
- WAVEFORMATEX wfx;
- struct audsettings obt_as;
- #ifdef DSBTYPE_IN
- const char *typ = "ADC";
- DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
- DSCBUFFERDESC bd;
- DSCBCAPS bc;
- AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
- #else
- const char *typ = "DAC";
- DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
- DSBUFFERDESC bd;
- DSBCAPS bc;
- AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
- #endif
- if (!s->FIELD2) {
- dolog ("Attempt to initialize voice without " NAME2 " object\n");
- return -1;
- }
- err = waveformat_from_audio_settings (&wfx, as);
- if (err) {
- return -1;
- }
- memset (&bd, 0, sizeof (bd));
- bd.dwSize = sizeof (bd);
- bd.lpwfxFormat = &wfx;
- bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880);
- #ifdef DSBTYPE_IN
- hr = IDirectSoundCapture_CreateCaptureBuffer (
- s->dsound_capture,
- &bd,
- &ds->dsound_capture_buffer,
- NULL
- );
- #else
- bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
- hr = IDirectSound_CreateSoundBuffer (
- s->dsound,
- &bd,
- &ds->dsound_buffer,
- NULL
- );
- #endif
- if (FAILED (hr)) {
- dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
- return -1;
- }
- hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
- if (FAILED (hr)) {
- dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
- goto fail0;
- }
- #ifdef DEBUG_DSOUND
- dolog (NAME "\n");
- print_wave_format (&wfx);
- #endif
- memset (&bc, 0, sizeof (bc));
- bc.dwSize = sizeof (bc);
- hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
- if (FAILED (hr)) {
- dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
- goto fail0;
- }
- err = waveformat_to_audio_settings (&wfx, &obt_as);
- if (err) {
- goto fail0;
- }
- ds->first_time = true;
- obt_as.endianness = 0;
- audio_pcm_init_info (&hw->info, &obt_as);
- if (bc.dwBufferBytes % hw->info.bytes_per_frame) {
- dolog (
- "GetCaps returned misaligned buffer size %ld, alignment %d\n",
- bc.dwBufferBytes, hw->info.bytes_per_frame
- );
- }
- hw->size_emul = bc.dwBufferBytes;
- hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
- ds->s = s;
- #ifdef DEBUG_DSOUND
- dolog ("caps %ld, desc %ld\n",
- bc.dwBufferBytes, bd.dwBufferBytes);
- #endif
- return 0;
- fail0:
- glue (dsound_fini_, TYPE) (hw);
- return -1;
- }
- #undef NAME
- #undef NAME2
- #undef TYPE
- #undef IFACE
- #undef BUFPTR
- #undef FIELD
- #undef FIELD2
- #undef HWVOICE
- #undef DSOUNDVOICE
|