qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

dsound_template.h (7212B)


      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 NAME2 "DirectSoundCapture"
     27 #define TYPE in
     28 #define IFACE IDirectSoundCaptureBuffer
     29 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
     30 #define FIELD dsound_capture_buffer
     31 #define FIELD2 dsound_capture
     32 #define HWVOICE HWVoiceIn
     33 #define DSOUNDVOICE DSoundVoiceIn
     34 #else
     35 #define NAME "playback buffer"
     36 #define NAME2 "DirectSound"
     37 #define TYPE out
     38 #define IFACE IDirectSoundBuffer
     39 #define BUFPTR LPDIRECTSOUNDBUFFER
     40 #define FIELD dsound_buffer
     41 #define FIELD2 dsound
     42 #define HWVOICE HWVoiceOut
     43 #define DSOUNDVOICE DSoundVoiceOut
     44 #endif
     45 
     46 static 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)) {
     58         dsound_logerr (hr, "Could not unlock " NAME "\n");
     59         return -1;
     60     }
     61 
     62     return 0;
     63 }
     64 
     65 static 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,
     74     int entire,
     75     dsound *s
     76     )
     77 {
     78     HRESULT hr;
     79     DWORD flag;
     80 
     81 #ifdef DSBTYPE_IN
     82     flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
     83 #else
     84     flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
     85 #endif
     86     hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
     87 
     88     if (FAILED (hr)) {
     89 #ifndef DSBTYPE_IN
     90         if (hr == DSERR_BUFFERLOST) {
     91             if (glue (dsound_restore_, TYPE) (buf, s)) {
     92                 dsound_logerr (hr, "Could not lock " NAME "\n");
     93             }
     94             goto fail;
     95         }
     96 #endif
     97         dsound_logerr (hr, "Could not lock " NAME "\n");
     98         goto fail;
     99     }
    100 
    101     if ((p1p && *p1p && (*blen1p % info->bytes_per_frame)) ||
    102         (p2p && *p2p && (*blen2p % info->bytes_per_frame))) {
    103         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);
    107         goto fail;
    108     }
    109 
    110     if (p1p && !*p1p && *blen1p) {
    111         dolog("warning: !p1 && blen1=%ld\n", *blen1p);
    112         *blen1p = 0;
    113     }
    114 
    115     if (p2p && !*p2p && *blen2p) {
    116         dolog("warning: !p2 && blen2=%ld\n", *blen2p);
    117         *blen2p = 0;
    118     }
    119 
    120     return 0;
    121 
    122  fail:
    123     *p1p = NULL - 1;
    124     *blen1p = -1;
    125     if (p2p) {
    126         *p2p = NULL - 1;
    127         *blen2p = -1;
    128     }
    129     return -1;
    130 }
    131 
    132 #ifdef DSBTYPE_IN
    133 static void dsound_fini_in (HWVoiceIn *hw)
    134 #else
    135 static 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)) {
    148             dsound_logerr (hr, "Could not stop " NAME "\n");
    149         }
    150 
    151         hr = glue (IFACE, _Release) (ds->FIELD);
    152         if (FAILED (hr)) {
    153             dsound_logerr (hr, "Could not release " NAME "\n");
    154         }
    155         ds->FIELD = NULL;
    156     }
    157 }
    158 
    159 #ifdef DSBTYPE_IN
    160 static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
    161                           void *drv_opaque)
    162 #else
    163 static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
    164                            void *drv_opaque)
    165 #endif
    166 {
    167     int err;
    168     HRESULT hr;
    169     dsound *s = drv_opaque;
    170     WAVEFORMATEX wfx;
    171     struct audsettings obt_as;
    172 #ifdef DSBTYPE_IN
    173     const char *typ = "ADC";
    174     DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
    175     DSCBUFFERDESC bd;
    176     DSCBCAPS bc;
    177     AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
    178 #else
    179     const char *typ = "DAC";
    180     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
    181     DSBUFFERDESC bd;
    182     DSBCAPS bc;
    183     AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
    184 #endif
    185 
    186     if (!s->FIELD2) {
    187         dolog ("Attempt to initialize voice without " NAME2 " object\n");
    188         return -1;
    189     }
    190 
    191     err = waveformat_from_audio_settings (&wfx, as);
    192     if (err) {
    193         return -1;
    194     }
    195 
    196     memset (&bd, 0, sizeof (bd));
    197     bd.dwSize = sizeof (bd);
    198     bd.lpwfxFormat = &wfx;
    199     bd.dwBufferBytes = audio_buffer_bytes(pdo, as, 92880);
    200 #ifdef DSBTYPE_IN
    201     hr = IDirectSoundCapture_CreateCaptureBuffer (
    202         s->dsound_capture,
    203         &bd,
    204         &ds->dsound_capture_buffer,
    205         NULL
    206         );
    207 #else
    208     bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
    209     hr = IDirectSound_CreateSoundBuffer (
    210         s->dsound,
    211         &bd,
    212         &ds->dsound_buffer,
    213         NULL
    214         );
    215 #endif
    216 
    217     if (FAILED (hr)) {
    218         dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
    219         return -1;
    220     }
    221 
    222     hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
    223     if (FAILED (hr)) {
    224         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
    225         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)) {
    238         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
    239         goto fail0;
    240     }
    241 
    242     err = waveformat_to_audio_settings (&wfx, &obt_as);
    243     if (err) {
    244         goto fail0;
    245     }
    246 
    247     ds->first_time = true;
    248     obt_as.endianness = 0;
    249     audio_pcm_init_info (&hw->info, &obt_as);
    250 
    251     if (bc.dwBufferBytes % hw->info.bytes_per_frame) {
    252         dolog (
    253             "GetCaps returned misaligned buffer size %ld, alignment %d\n",
    254             bc.dwBufferBytes, hw->info.bytes_per_frame
    255             );
    256     }
    257     hw->size_emul = bc.dwBufferBytes;
    258     hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
    259     ds->s = s;
    260 
    261 #ifdef DEBUG_DSOUND
    262     dolog ("caps %ld, desc %ld\n",
    263            bc.dwBufferBytes, bd.dwBufferBytes);
    264 #endif
    265     return 0;
    266 
    267  fail0:
    268     glue (dsound_fini_, TYPE) (hw);
    269     return -1;
    270 }
    271 
    272 #undef NAME
    273 #undef NAME2
    274 #undef TYPE
    275 #undef IFACE
    276 #undef BUFPTR
    277 #undef FIELD
    278 #undef FIELD2
    279 #undef HWVOICE
    280 #undef DSOUNDVOICE