VirtualBox

Changeset 53417 in vbox for trunk/src


Ignore:
Timestamp:
Dec 1, 2014 1:27:17 PM (10 years ago)
Author:
vboxsync
Message:

Devices/Audio: handle host audio output device disconnect in the DirectSound backend.

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/dsound_template.h

    r53393 r53417  
    169169static void dsound_fini_out (HWVoiceOut *hw)
    170170{
    171     HRESULT hr;
    172171    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
    173 
    174     if (ds->FIELD) {
    175         hr = glue (IFACE, _Stop) (ds->FIELD);
    176         if (FAILED (hr)) {
    177             dsound_logerr (hr, "Could not stop " NAME "\n");
    178         }
    179 
    180         hr = glue (IFACE, _Release) (ds->FIELD);
    181         if (FAILED (hr)) {
    182             dsound_logerr (hr, "Could not release " NAME "\n");
    183         }
    184         ds->FIELD = NULL;
    185     }
     172    dsoundPlayClose (ds);
     173    ds->old_pos = 0;
     174    ds->first_time = 1;
     175    ds->playback_buffer_size = 0;
     176    memset (&ds->as, 0, sizeof(ds->as));
    186177}
    187178#endif
     
    194185    ds->last_read_pos = 0;
    195186    ds->capture_buffer_size = 0;
     187    ds->dsound_capture = NULL;
    196188    ds->dsound_capture_buffer = NULL;
    197189    ds->as = *as;
     
    209201static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
    210202{
    211     int err;
    212     HRESULT hr;
    213     dsound *s = &glob_dsound;
    214     WAVEFORMATEX wfx;
    215     audsettings_t obt_as;
    216     const char *typ = "DAC";
    217203    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
    218     DSBUFFERDESC bd;
    219     DSBCAPS bc;
    220 
    221     err = waveformat_from_audio_settings (&wfx, as);
    222     if (err) {
    223         return -1;
    224     }
    225 
    226     memset (&bd, 0, sizeof (bd));
    227     bd.dwSize = sizeof (bd);
    228     bd.lpwfxFormat = &wfx;
    229     bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
    230     bd.dwBufferBytes = conf.bufsize_out;
    231     hr = IDirectSound_CreateSoundBuffer (
    232         s->dsound,
    233         &bd,
    234         &ds->dsound_buffer,
    235         NULL
    236         );
    237 
    238     if (FAILED (hr)) {
    239         dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
    240         return -1;
    241     }
    242 
    243     hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
    244     if (FAILED (hr)) {
    245         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
    246         goto fail0;
    247     }
    248 
    249 #ifdef DEBUG_DSOUND
    250     dolog (NAME "\n");
    251     print_wave_format (&wfx);
    252 #endif
    253 
    254     memset (&bc, 0, sizeof (bc));
    255     bc.dwSize = sizeof (bc);
    256 
    257     hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
    258     if (FAILED (hr)) {
    259         dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
    260         goto fail0;
    261     }
    262 
    263     err = waveformat_to_audio_settings (&wfx, &obt_as);
    264     if (err) {
    265         goto fail0;
    266     }
    267 
     204
     205    ds->dsound = NULL;
     206    ds->dsound_buffer = NULL;
     207    ds->old_pos = 0;
    268208    ds->first_time = 1;
    269     obt_as.endianness = 0;
    270     audio_pcm_init_info (&hw->info, &obt_as);
    271 
    272     if (bc.dwBufferBytes & hw->info.align) {
    273         dolog (
    274             "GetCaps returned misaligned buffer size %ld, alignment %d\n",
    275             bc.dwBufferBytes, hw->info.align + 1
    276             );
    277     }
    278     hw->samples = bc.dwBufferBytes >> hw->info.shift;
    279 
    280 #ifdef DEBUG_DSOUND
    281     dolog ("caps %ld, desc %ld\n",
    282            bc.dwBufferBytes, bd.dwBufferBytes);
    283 
    284     dolog ("bufsize %d, freq %d, chan %d, bits %d, sign %d\n",
    285            hw->samples << hw->info.shift,
    286            hw->info.freq,
    287            hw->info.nchannels,
    288            hw->info.bits,
    289            hw->info.sign);
    290 #endif
    291     return 0;
    292 
    293  fail0:
    294     glue (dsound_fini_, TYPE) (hw);
    295     return -1;
     209    ds->playback_buffer_size = 0;
     210    ds->as = *as;
     211
     212    /* Init default settings. */
     213    audio_pcm_init_info (&hw->info, &ds->as);
     214    hw->samples = conf.bufsize_out >> hw->info.shift;
     215
     216    /* Try to open playback in case the device is already there. */
     217    dsoundPlayOpen (ds);
     218
     219    return 0;
    296220}
    297221#endif
  • trunk/src/VBox/Devices/Audio/dsoundaudio.c

    r53395 r53417  
    6060#include "audio_int.h"
    6161
    62 /* #define DEBUG_DSOUND */
    63 
    6462#define DSLOGF(a) do { LogRel2(a); } while(0)
    6563#define DSLOGREL(a)                 \
     
    7977    int restore_retries;
    8078    int getstatus_retries;
    81     int set_primary;
    8279    int bufsize_in;
    8380    int bufsize_out;
    84     audsettings_t settings;
    8581    int latency_millis;
    8682    char *device_guid_out;
     
    9086    1,
    9187    1,
    92     0,
    9388    16384,
    9489    16384,
    95     {
    96         44100,
    97         2,
    98         AUD_FMT_S16
    99     },
    10090    10,
    10191    NULL,
     
    10494
    10595typedef struct {
    106     LPDIRECTSOUND dsound;
    107     LPDIRECTSOUNDCAPTURE dsound_capture;
    108     LPDIRECTSOUNDBUFFER dsound_primary_buffer;
    109     audsettings_t settings;
     96    RTUUID devguid_play;
     97    LPCGUID devguidp_play;
    11098    RTUUID devguid_capture;
    11199    LPCGUID devguidp_capture;
     
    116104typedef struct {
    117105    HWVoiceOut hw;
     106    LPDIRECTSOUND dsound;
    118107    LPDIRECTSOUNDBUFFER dsound_buffer;
    119108    DWORD old_pos;
    120109    int first_time;
    121 #ifdef DEBUG_DSOUND
    122     DWORD old_ppos;
    123     DWORD played;
    124     DWORD mixed;
    125 #endif
     110    int playback_buffer_size;
     111    audsettings_t as;
    126112} DSoundVoiceOut;
    127113
     
    130116    int last_read_pos;
    131117    int capture_buffer_size;
     118    LPDIRECTSOUNDCAPTURE dsound_capture;
    132119    LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
    133120    audsettings_t as;
    134121    HRESULT hr_last_run_in;
    135122} DSoundVoiceIn;
     123
     124static void dsound_clear_sample (DSoundVoiceOut *ds);
    136125
    137126static void dsound_log_hresult (HRESULT hr)
     
    313302}
    314303
    315 #ifdef DEBUG_DSOUND
    316 static void print_wave_format (WAVEFORMATEX *wfx)
    317 {
    318     dolog ("tag             = %d\n", wfx->wFormatTag);
    319     dolog ("nChannels       = %d\n", wfx->nChannels);
    320     dolog ("nSamplesPerSec  = %ld\n", wfx->nSamplesPerSec);
    321     dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
    322     dolog ("nBlockAlign     = %d\n", wfx->nBlockAlign);
    323     dolog ("wBitsPerSample  = %d\n", wfx->wBitsPerSample);
    324     dolog ("cbSize          = %d\n", wfx->cbSize);
    325 }
    326 #endif
    327 
    328304static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
    329305{
     
    342318
    343319        default:
    344             dsound_logerr (hr, "Could not restore playback buffer\n");
     320            DSLOGREL(("DSound: restore playback buffer %Rhrc\n", hr));
    345321            return -1;
    346322        }
    347323    }
    348324
    349     dolog ("%d attempts to restore playback buffer failed\n", i);
     325    DSLOGF(("DSound: %d attempts to restore playback buffer failed\n", i));
    350326    return -1;
    351327}
     
    444420}
    445421
    446 static void dsoundCaptureInterfaceRelease (dsound *s)
    447 {
    448     if (s->dsound_capture) {
    449         HRESULT hr = IDirectSoundCapture_Release (s->dsound_capture);
     422/*
     423 * DirectSound playback
     424 */
     425
     426static void dsoundPlayInterfaceRelease (DSoundVoiceOut *ds)
     427{
     428    if (ds->dsound) {
     429        IDirectSound_Release (ds->dsound);
     430        ds->dsound = NULL;
     431    }
     432}
     433
     434static int dsoundPlayInterfaceCreate (DSoundVoiceOut *ds)
     435{
     436    dsound *s = &glob_dsound;
     437
     438    HRESULT hr;
     439
     440    if (ds->dsound != NULL) {
     441        DSLOGF(("DSound: DirectSound instance already exists\n"));
     442        return 0;
     443    }
     444
     445    hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL,
     446                           &IID_IDirectSound, (void **) &ds->dsound);
     447    if (FAILED (hr)) {
     448        DSLOGREL(("DSound: DirectSound create instance %Rhrc\n", hr));
     449    }
     450    else {
     451        hr = IDirectSound_Initialize (ds->dsound, s->devguidp_play);
     452        if (SUCCEEDED(hr)) {
     453            HWND hwnd = GetDesktopWindow ();
     454            hr = IDirectSound_SetCooperativeLevel (ds->dsound, hwnd, DSSCL_PRIORITY);
     455            if (FAILED (hr)) {
     456                DSLOGREL(("DSound: set cooperative level for window %p %Rhrc\n", hwnd, hr));
     457            }
     458        }
    450459        if (FAILED (hr)) {
    451             DSLOGF(("DSound: DirectSoundCapture release %Rhrc\n", hr));
    452         }
    453         s->dsound_capture = NULL;
    454     }
    455 }
    456 
    457 static int dsoundCaptureInterfaceCreate (dsound *s)
    458 {
     460            if (hr == DSERR_NODRIVER) {
     461                DSLOGREL(("DSound: DirectSound playback is currently unavailable\n"));
     462            }
     463            else {
     464                DSLOGREL(("DSound: DirectSound initialize %Rhrc\n", hr));
     465            }
     466            dsoundPlayInterfaceRelease (ds);
     467        }
     468    }
     469
     470    return SUCCEEDED (hr)? 0: -1;
     471}
     472
     473static void dsoundPlayClose (DSoundVoiceOut *ds)
     474{
     475    dsound *s = &glob_dsound;
     476
    459477    HRESULT hr;
    460478
    461     if (s->dsound_capture != NULL) {
     479    DSLOGF(("DSound: playback close %p buffer %p\n", ds, ds->dsound_buffer));
     480
     481    if (ds->dsound_buffer) {
     482        hr = IDirectSoundBuffer_Stop (ds->dsound_buffer);
     483        if (FAILED (hr)) {
     484            DSLOGREL(("DSound: playback close Stop %Rhrc\n", hr));
     485        }
     486
     487        IDirectSoundBuffer_Release (ds->dsound_buffer);
     488        ds->dsound_buffer = NULL;
     489    }
     490
     491    dsoundPlayInterfaceRelease (ds);
     492}
     493
     494static int dsoundPlayOpen (DSoundVoiceOut *ds)
     495{
     496    dsound *s = &glob_dsound;
     497
     498    int err;
     499    HRESULT hr;
     500    WAVEFORMATEX wfx;
     501    DSBUFFERDESC bd;
     502    DSBCAPS bc;
     503
     504    DSLOGF(("DSound: playback open %p size %d samples, freq %d, chan %d, bits %d, sign %d\n",
     505            ds,
     506            ds->hw.samples,
     507            ds->hw.info.freq,
     508            ds->hw.info.nchannels,
     509            ds->hw.info.bits,
     510            ds->hw.info.sign));
     511
     512    if (ds->dsound_buffer != NULL) {
     513        /* Should not happen but be forgiving. */
     514        DSLOGREL(("DSound: DirectSoundBuffer already exists\n"));
     515        dsoundPlayClose (ds);
     516    }
     517
     518    err = waveformat_from_audio_settings (&wfx, &ds->as);
     519    if (err) {
     520        return err;
     521    }
     522
     523    err = dsoundPlayInterfaceCreate (ds);
     524    if (err) {
     525        return err;
     526    }
     527
     528    memset (&bd, 0, sizeof (bd));
     529    bd.dwSize = sizeof (bd);
     530    bd.lpwfxFormat = &wfx;
     531    bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
     532    bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift;
     533    hr = IDirectSound_CreateSoundBuffer (ds->dsound,
     534                                         &bd, &ds->dsound_buffer, NULL);
     535    if (FAILED (hr)) {
     536        DSLOGREL(("DSound: playback CreateSoundBuffer %Rhrc\n", hr));
     537        goto fail0;
     538    }
     539
     540    /* Query the actual parameters. */
     541
     542    hr = IDirectSoundBuffer_GetFormat (ds->dsound_buffer, &wfx, sizeof (wfx), NULL);
     543    if (FAILED (hr)) {
     544        DSLOGREL(("DSound: playback GetFormat %Rhrc\n", hr));
     545        goto fail0;
     546    }
     547
     548    memset (&bc, 0, sizeof (bc));
     549    bc.dwSize = sizeof (bc);
     550    hr = IDirectSoundBuffer_GetCaps (ds->dsound_buffer, &bc);
     551    if (FAILED (hr)) {
     552        DSLOGREL(("DSound: playback GetCaps %Rhrc\n", hr));
     553        goto fail0;
     554    }
     555
     556    DSLOGF(("DSound: playback format: size %d bytes\n"
     557            "  tag             = %d\n"
     558            "  nChannels       = %d\n"
     559            "  nSamplesPerSec  = %d\n"
     560            "  nAvgBytesPerSec = %d\n"
     561            "  nBlockAlign     = %d\n"
     562            "  wBitsPerSample  = %d\n"
     563            "  cbSize          = %d\n",
     564            bc.dwBufferBytes,
     565            wfx.wFormatTag,
     566            wfx.nChannels,
     567            wfx.nSamplesPerSec,
     568            wfx.nAvgBytesPerSec,
     569            wfx.nBlockAlign,
     570            wfx.wBitsPerSample,
     571            wfx.cbSize));
     572
     573    if (bc.dwBufferBytes & ds->hw.info.align) {
     574        DSLOGREL(("DSound: playback GetCaps returned misaligned buffer size %ld, alignment %d\n",
     575                  bc.dwBufferBytes, ds->hw.info.align + 1));
     576    }
     577
     578    if (ds->hw.samples != 0 && ds->hw.samples != (bc.dwBufferBytes >> ds->hw.info.shift)) {
     579        DSLOGREL(("DSound: playback buffer size mismatch dsound %d, hw %d bytes\n",
     580                  bc.dwBufferBytes, ds->hw.samples << ds->hw.info.shift));
     581    }
     582
     583    /* Initial state.
     584     * dsoundPlayStart initializes part of it to make sure that Stop/Start continues with a correct
     585     * playback buffer position.
     586     */
     587    ds->playback_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift;
     588    DSLOGF(("DSound: playback open playback_buffer_size %d\n", ds->playback_buffer_size));
     589
     590    return 0;
     591
     592 fail0:
     593    dsoundPlayClose (ds);
     594    return -1;
     595}
     596
     597static int dsoundPlayGetStatus (DSoundVoiceOut *ds, DWORD *statusp)
     598{
     599    HRESULT hr;
     600    DWORD status;
     601    int i;
     602
     603    if (ds->dsound_buffer != NULL) {
     604        for (i = 0; i < RT_MAX(conf.getstatus_retries, 1); ++i) {
     605            hr = IDirectSoundBuffer_GetStatus (ds->dsound_buffer, &status);
     606            if (FAILED (hr)) {
     607                DSLOGF(("DSound: playback start GetStatus %Rhrc\n", hr));
     608                break;
     609            }
     610
     611            if ((status & DSBSTATUS_BUFFERLOST) == 0) {
     612                break;
     613            }
     614
     615            if (dsound_restore_out (ds->dsound_buffer)) {
     616                hr = E_FAIL;
     617                break;
     618            }
     619        }
     620    }
     621    else
     622    {
     623        hr = E_FAIL;
     624    }
     625
     626    if (SUCCEEDED (hr)) {
     627        *statusp = status;
     628        return 0;
     629    }
     630    return -1;
     631}
     632
     633static void dsoundPlayStop (DSoundVoiceOut *ds)
     634{
     635    HRESULT hr;
     636    DWORD status;
     637
     638    if (ds->dsound_buffer != NULL) {
     639        /* This performs some restore, so call it anyway and ignore result. */
     640        dsoundPlayGetStatus (ds, &status);
     641
     642        hr = IDirectSoundBuffer_Stop (ds->dsound_buffer);
     643        if (FAILED (hr)) {
     644            DSLOGF(("DSound: stop playback buffer %Rhrc\n", hr));
     645        }
     646    }
     647}
     648
     649static int dsoundPlayStart (DSoundVoiceOut *ds)
     650{
     651    HRESULT hr;
     652    DWORD status;
     653
     654    if (ds->dsound_buffer != NULL) {
     655        if (dsoundPlayGetStatus (ds, &status)) {
     656            DSLOGF(("DSound: playback start GetStatus failed\n"));
     657            hr = E_FAIL;
     658        }
     659        else {
     660            if (status & DSBSTATUS_PLAYING) {
     661                DSLOGF(("DSound: already playing\n"));
     662            }
     663            else {
     664                dsound_clear_sample (ds);
     665
     666                /* Reinit the playback buffer position. */
     667                ds->first_time = 1;
     668
     669                DSLOGF(("DSound: playback start\n"));
     670
     671                hr = IDirectSoundBuffer_Play (ds->dsound_buffer, 0, 0, DSBPLAY_LOOPING);
     672                if (FAILED (hr)) {
     673                    DSLOGREL(("DSound: playback start %Rhrc\n", hr));
     674                }
     675            }
     676        }
     677    }
     678    else {
     679        hr = E_FAIL;
     680    }
     681
     682    return SUCCEEDED (hr)? 0: -1;
     683}
     684
     685/*
     686 * DirectSoundCapture
     687 */
     688
     689static void dsoundCaptureInterfaceRelease (DSoundVoiceIn *ds)
     690{
     691    if (ds->dsound_capture) {
     692        IDirectSoundCapture_Release (ds->dsound_capture);
     693        ds->dsound_capture = NULL;
     694    }
     695}
     696
     697static int dsoundCaptureInterfaceCreate (DSoundVoiceIn *ds)
     698{
     699    dsound *s = &glob_dsound;
     700
     701    HRESULT hr;
     702
     703    if (ds->dsound_capture != NULL) {
    462704        DSLOGF(("DSound: DirectSoundCapture instance already exists\n"));
    463         return -1;
     705        return 0;
    464706    }
    465707
    466708    hr = CoCreateInstance (&CLSID_DirectSoundCapture, NULL, CLSCTX_ALL,
    467                            &IID_IDirectSoundCapture, (void **) &s->dsound_capture);
     709                           &IID_IDirectSoundCapture, (void **) &ds->dsound_capture);
    468710    if (FAILED (hr)) {
    469711        DSLOGREL(("DSound: DirectSoundCapture create instance %Rhrc\n", hr));
    470712    }
    471713    else {
    472         hr = IDirectSoundCapture_Initialize (s->dsound_capture, s->devguidp_capture);
     714        hr = IDirectSoundCapture_Initialize (ds->dsound_capture, s->devguidp_capture);
    473715        if (FAILED (hr)) {
    474716            if (hr == DSERR_NODRIVER) {
    475                 DSLOGREL(("DSound: DirectSoundCapture not available\n"));
     717                DSLOGREL(("DSound: DirectSound capture is currently unavailable\n"));
    476718            }
    477719            else {
    478720                DSLOGREL(("DSound: DirectSoundCapture initialize %Rhrc\n", hr));
    479721            }
    480             dsoundCaptureInterfaceRelease (s);
     722            dsoundCaptureInterfaceRelease (ds);
    481723        }
    482724    }
     
    497739        }
    498740
    499         hr = IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer);
    500         if (FAILED (hr)) {
    501             DSLOGF(("DSound: close capture buffer release %Rhrc\n", hr));
    502         }
     741        IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer);
    503742        ds->dsound_capture_buffer = NULL;
    504743    }
    505744
    506     dsoundCaptureInterfaceRelease (s);
     745    dsoundCaptureInterfaceRelease (ds);
    507746}
    508747
     
    537776    }
    538777
    539     err = dsoundCaptureInterfaceCreate (s);
     778    err = dsoundCaptureInterfaceCreate (ds);
    540779    if (err) {
    541780        return err;
     
    546785    bd.lpwfxFormat = &wfx;
    547786    bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift;
    548     hr = IDirectSoundCapture_CreateCaptureBuffer (s->dsound_capture,
     787    hr = IDirectSoundCapture_CreateCaptureBuffer (ds->dsound_capture,
    549788                                                  &bd, &ds->dsound_capture_buffer, NULL);
    550789
     
    609848    ds->last_read_pos = cpos >> ds->hw.info.shift;
    610849    ds->capture_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift;
    611     DSLOGF(("DSound: open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size));
     850    DSLOGF(("DSound: capture open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size));
    612851
    613852    ds->hr_last_run_in = S_OK;
     
    645884            }
    646885            else {
     886                /** @todo Fill the capture beffer with silence here. */
     887
     888                DSLOGF(("DSound: capture start\n"));
    647889                hr = IDirectSoundCaptureBuffer_Start (ds->dsound_capture_buffer, DSCBSTART_LOOPING);
    648890                if (FAILED (hr)) {
     
    664906#undef DSBTYPE_IN
    665907
    666 static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)
    667 {
    668     HRESULT hr;
    669     int i;
    670 
    671     for (i = 0; i < conf.getstatus_retries; ++i) {
    672         hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
    673         if (FAILED (hr)) {
    674             dsound_logerr (hr, "Could not get playback buffer status\n");
    675             return -1;
    676         }
    677 
    678         if (*statusp & DSERR_BUFFERLOST) {
    679             if (dsound_restore_out (dsb)) {
    680                 return -1;
    681             }
    682             continue;
    683         }
    684         break;
    685     }
    686 
    687     return 0;
    688 }
    689 
    690 static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,
    691                                  DWORD *statusp)
    692 {
    693     HRESULT hr;
    694 
    695     hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);
    696     if (FAILED (hr)) {
    697         dsound_logerr (hr, "Could not get capture buffer status\n");
    698         return -1;
    699     }
    700 
    701     return 0;
    702 }
    703 
    704908static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
    705909{
     
    719923    if (src_len1) {
    720924        hw->clip (dst, src1, src_len1);
    721 //        mixeng_sniff_and_clear (hw, src1, dst, src_len1);
    722925    }
    723926
     
    725928        dst = advance (dst, src_len1 << hw->info.shift);
    726929        hw->clip (dst, src2, src_len2);
    727 //        mixeng_sniff_and_clear (hw, src2, dst, src_len2);
    728930    }
    729931
     
    731933}
    732934
    733 static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
     935static void dsound_clear_sample (DSoundVoiceOut *ds)
    734936{
    735937    int err;
     
    738940
    739941    err = dsound_lock_out (
    740         dsb,
    741         &hw->info,
     942        ds->dsound_buffer,
     943        &ds->hw.info,
    742944        0,
    743         hw->samples << hw->info.shift,
     945        ds->playback_buffer_size << ds->hw.info.shift,
    744946        &p1, &p2,
    745947        &blen1, &blen2,
     
    750952    }
    751953
    752     len1 = blen1 >> hw->info.shift;
    753     len2 = blen2 >> hw->info.shift;
    754 
    755 #ifdef DEBUG_DSOUND
    756     dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",
    757            p1, blen1, len1,
    758            p2, blen2, len2);
    759 #endif
     954    len1 = blen1 >> ds->hw.info.shift;
     955    len2 = blen2 >> ds->hw.info.shift;
    760956
    761957    if (p1 && len1) {
    762         audio_pcm_info_clear_buf (&hw->info, p1, len1);
     958        audio_pcm_info_clear_buf (&ds->hw.info, p1, len1);
    763959    }
    764960
    765961    if (p2 && len2) {
    766         audio_pcm_info_clear_buf (&hw->info, p2, len2);
    767     }
    768 
    769     dsound_unlock_out (dsb, p1, p2, blen1, blen2);
    770 }
    771 
    772 static void dsound_close (dsound *s)
    773 {
    774     HRESULT hr;
    775 
    776     if (s->dsound_primary_buffer) {
    777         hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);
    778         if (FAILED (hr)) {
    779             dsound_logerr (hr, "Could not release primary buffer\n");
    780         }
    781         s->dsound_primary_buffer = NULL;
    782     }
    783 }
    784 
    785 static int dsound_open (dsound *s)
    786 {
    787     int err;
    788     HRESULT hr;
    789     WAVEFORMATEX wfx;
    790     DSBUFFERDESC dsbd;
    791     HWND hwnd;
    792 
    793     hwnd = GetDesktopWindow ();
    794     hr = IDirectSound_SetCooperativeLevel (
    795         s->dsound,
    796         hwnd,
    797         DSSCL_PRIORITY
    798         );
    799 
    800     if (FAILED (hr)) {
    801 #ifndef VBOX
    802         dsound_logerr (hr, "Could not set cooperative level for window %p\n",
    803                        hwnd);
    804 #else
    805         LogRel(("DSound: Could not set cooperative level for window %p\n", hwnd));
    806         dsound_log_hresult(hr);
    807 #endif
    808         return -1;
    809     }
    810 
    811     if (!conf.set_primary) {
    812         return 0;
    813     }
    814 
    815     err = waveformat_from_audio_settings (&wfx, &conf.settings);
    816     if (err) {
    817         return -1;
    818     }
    819 
    820     memset (&dsbd, 0, sizeof (dsbd));
    821     dsbd.dwSize = sizeof (dsbd);
    822     dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
    823     dsbd.dwBufferBytes = 0;
    824     dsbd.lpwfxFormat = NULL;
    825 
    826     hr = IDirectSound_CreateSoundBuffer (
    827         s->dsound,
    828         &dsbd,
    829         &s->dsound_primary_buffer,
    830         NULL
    831         );
    832     if (FAILED (hr)) {
    833 #ifndef VBOX
    834         dsound_logerr (hr, "Could not create primary playback buffer\n");
    835 #else
    836         LogRel(("DSound: Could not create primary playback buffer\n"));
    837         dsound_log_hresult(hr);
    838 #endif
    839         return -1;
    840     }
    841 
    842     hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx);
    843     if (FAILED (hr)) {
    844 #ifndef VBOX
    845         dsound_logerr (hr, "Could not set primary playback buffer format\n");
    846 #else
    847         LogRel(("DSound: Could not set primary playback buffer format\n"));
    848         dsound_log_hresult(hr);
    849 #endif
    850     }
    851 
    852     hr = IDirectSoundBuffer_GetFormat (
    853         s->dsound_primary_buffer,
    854         &wfx,
    855         sizeof (wfx),
    856         NULL
    857         );
    858     if (FAILED (hr)) {
    859 #ifndef VBOX
    860         dsound_logerr (hr, "Could not get primary playback buffer format\n");
    861 #else
    862         LogRel(("DSound: Could not get primary playback buffer format\n"));
    863         dsound_log_hresult(hr);
    864 #endif
    865         goto fail0;
    866     }
    867 
    868 #ifdef DEBUG_DSOUND
    869     dolog ("Primary\n");
    870     print_wave_format (&wfx);
    871 #endif
    872 
    873     err = waveformat_to_audio_settings (&wfx, &s->settings);
    874     if (err) {
    875         goto fail0;
    876     }
    877 
    878     return 0;
    879 
    880  fail0:
    881     dsound_close (s);
    882     return -1;
     962        audio_pcm_info_clear_buf (&ds->hw.info, p2, len2);
     963    }
     964
     965    dsound_unlock_out (ds->dsound_buffer, p1, p2, blen1, blen2);
    883966}
    884967
    885968static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
    886969{
    887     HRESULT hr;
    888     DWORD status;
    889970    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
    890     LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
    891 
    892     if (!dsb) {
    893         dolog ("Attempt to control voice without a buffer\n");
    894         return 0;
    895     }
    896971
    897972    switch (cmd) {
    898973    case VOICE_ENABLE:
    899         if (dsound_get_status_out (dsb, &status)) {
    900             return -1;
    901         }
    902 
    903         if (status & DSBSTATUS_PLAYING) {
    904             dolog ("warning: Voice is already playing\n");
    905             return 0;
    906         }
    907 
    908         dsound_clear_sample (hw, dsb);
    909 
    910         hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
    911         if (FAILED (hr)) {
    912             dsound_logerr (hr, "Could not start playing buffer\n");
    913             return -1;
    914         }
    915         break;
    916 
    917     case VOICE_DISABLE:
    918         if (dsound_get_status_out (dsb, &status)) {
    919             return -1;
    920         }
    921 
    922         if (status & DSBSTATUS_PLAYING) {
    923             hr = IDirectSoundBuffer_Stop (dsb);
    924             if (FAILED (hr)) {
    925                 dsound_logerr (hr, "Could not stop playing buffer\n");
     974        /* Try to start playback. If it fails, then reopen and try again. */
     975        if (dsoundPlayStart (ds)) {
     976            dsoundPlayClose (ds);
     977            dsoundPlayOpen (ds);
     978
     979            if (dsoundPlayStart (ds)) {
    926980                return -1;
    927981            }
    928982        }
    929         else {
    930             dolog ("warning: Voice is not playing\n");
    931         }
     983        break;
     984
     985    case VOICE_DISABLE:
     986        dsoundPlayStop (ds);
    932987        break;
    933988    }
     
    9551010
    9561011    if (!dsb) {
    957         dolog ("Attempt to run empty with playback buffer\n");
     1012        DSLOGF(("DSound: run_out no playback buffer\n"));
    9581013        return 0;
    9591014    }
    9601015
    9611016    hwshift = hw->info.shift;
    962     bufsize = hw->samples << hwshift;
     1017    bufsize = ds->playback_buffer_size << hwshift;
    9631018
    9641019    live = audio_pcm_hw_get_live_out (hw);
     
    9671022        dsb,
    9681023        &ppos,
    969         ds->first_time ? &wpos : NULL
     1024        &wpos
    9701025        );
    9711026    if (hr == DSERR_BUFFERLOST) {
    9721027        if (dsound_restore_out(dsb))
    9731028            return 0;
    974         hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, ds->first_time ? &wpos : NULL);
     1029        hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, &wpos);
    9751030        if (hr == DSERR_BUFFERLOST)
    9761031            return 0;   // Avoid log flooding if the error is still there.
    9771032    }
    9781033    if (FAILED (hr)) {
    979         dsound_logerr (hr, "Could not get playback buffer position\n");
     1034        DSLOGF(("DSound: get playback buffer position %Rhrc\n", hr));
    9801035        return 0;
    9811036    }
     
    9861041        if (conf.latency_millis) {
    9871042            DWORD cur_blat;
    988 
     1043            DWORD conf_blat;
     1044
     1045            conf_blat = millis_to_bytes (&hw->info, conf.latency_millis);
    9891046            cur_blat = audio_ring_dist (wpos, ppos, bufsize);
    990             ds->first_time = 0;
    9911047            old_pos = wpos;
    992             old_pos +=
    993                 millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat;
     1048            if (conf_blat > cur_blat) /* Do not write before wpos. */
     1049               old_pos += conf_blat - cur_blat;
    9941050            old_pos %= bufsize;
    9951051            old_pos &= ~hw->info.align;
     
    9981054            old_pos = wpos;
    9991055        }
    1000 #ifdef DEBUG_DSOUND
    1001         ds->played = 0;
    1002         ds->mixed = 0;
    1003 #endif
     1056        ds->first_time = 0;
    10041057    }
    10051058    else {
    10061059        if (ds->old_pos == ppos) {
    1007 #ifdef DEBUG_DSOUND
    1008             dolog ("old_pos == ppos\n");
    1009 #endif
     1060            /* Full buffer. */
    10101061            return 0;
    10111062        }
    10121063
    1013 #ifdef DEBUG_DSOUND
    1014         ds->played += audio_ring_dist (ds->old_pos, ppos, bufsize);
    1015 #endif
    10161064        old_pos = ds->old_pos;
    10171065    }
     
    10271075
    10281076    if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) {
    1029         dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
    1030                len, bufsize, old_pos, ppos);
     1077        DSLOGF(("DSound: error len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
     1078               len, bufsize, old_pos, ppos));
    10311079        return 0;
    10321080    }
     
    10371085    }
    10381086
    1039 #ifdef DEBUG_DSOUND
    1040     ds->old_ppos = ppos;
    1041 #endif
    10421087    err = dsound_lock_out (
    10431088        dsb,
     
    10681113    ds->old_pos = (old_pos + (decr << hwshift)) % bufsize;
    10691114
    1070 #ifdef DEBUG_DSOUND
    1071     ds->mixed += decr << hwshift;
    1072 
    1073     dolog ("played %lu mixed %lu diff %ld sec %f\n",
    1074            ds->played,
    1075            ds->mixed,
    1076            ds->mixed - ds->played,
    1077            abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);
    1078 #endif
    10791115    return decr;
    10801116}
     
    12061242}
    12071243
     1244static int dsoundIsAvailable (void)
     1245{
     1246    LPDIRECTSOUND dsound;
     1247    HRESULT hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL,
     1248                                   &IID_IDirectSound, (void **) &dsound);
     1249    if (SUCCEEDED(hr)) {
     1250        IDirectSound_Release (dsound);
     1251        return 1;
     1252    }
     1253
     1254    DSLOGREL(("DSound: is unavailable %Rhrc\n", hr));
     1255    return 0;
     1256}
     1257
    12081258static void dsound_audio_fini (void *opaque)
    12091259{
    1210     HRESULT hr;
    12111260    dsound *s = opaque;
    1212 
    1213     if (!s->dsound) {
    1214         goto dsound_audio_fini_exit;
    1215     }
    1216 
    1217     hr = IDirectSound_Release (s->dsound);
    1218     if (FAILED (hr)) {
    1219         dsound_logerr (hr, "Could not release DirectSound\n");
    1220     }
    1221     s->dsound = NULL;
    1222 
    1223     if (!s->dsound_capture) {
    1224         goto dsound_audio_fini_exit;
    1225     }
    1226 
    1227     hr = IDirectSoundCapture_Release (s->dsound_capture);
    1228     if (FAILED (hr)) {
    1229         dsound_logerr (hr, "Could not release DirectSoundCapture\n");
    1230     }
    1231     s->dsound_capture = NULL;
    1232 
    1233 dsound_audio_fini_exit:
     1261    NOREF(s);
    12341262    CoUninitialize();
    12351263}
     
    12371265static void *dsound_audio_init (void)
    12381266{
    1239     int err;
    12401267    HRESULT hr;
    12411268    dsound *s = &glob_dsound;
    1242     RTUUID devguid;
    1243     LPCGUID devguidp;
    12441269
    12451270    hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
    12461271    if (FAILED (hr)) {
    1247 #ifndef VBOX
    1248         dsound_logerr (hr, "Could not initialize COM\n");
    1249 #else
    1250         LogRel(("DSound: Could not initialize COM\n"));
    1251         dsound_log_hresult(hr);
    1252 #endif
     1272        DSLOGREL(("DSound: COM initialize %Rhrc\n", hr));
    12531273        return NULL;
    12541274    }
    12551275
    1256     hr = CoCreateInstance (
    1257         &CLSID_DirectSound,
    1258         NULL,
    1259         CLSCTX_ALL,
    1260         &IID_IDirectSound,
    1261         (void **) &s->dsound
    1262         );
    1263     if (FAILED (hr)) {
    1264 #ifndef VBOX
    1265         dsound_logerr (hr, "Could not create DirectSound instance\n");
    1266 #else
    1267         LogRel(("DSound: Could not create DirectSound instance\n"));
    1268         dsound_log_hresult(hr);
    1269 #endif
    1270         CoUninitialize();
    1271         return NULL;
    1272     }
    1273 
    12741276    if (conf.device_guid_out) {
    1275         hr = RTUuidFromStr(&devguid, conf.device_guid_out);
    1276         if (FAILED (hr)) {
     1277        int rc = RTUuidFromStr(&s->devguid_play, conf.device_guid_out);
     1278        if (FAILED (rc)) {
    12771279            LogRel(("DSound: Could not parse DirectSound output device GUID\n"));
    12781280        }
    1279         devguidp = (LPCGUID)&devguid;
     1281        s->devguidp_play = (LPCGUID)&s->devguid_play;
    12801282    } else {
    1281         devguidp = NULL;
    1282     }
    1283     hr = IDirectSound_Initialize (s->dsound, devguidp);
    1284     if (FAILED (hr)) {
    1285 #ifndef VBOX
    1286         dsound_logerr (hr, "Could not initialize DirectSound\n");
    1287 #else
    1288         LogRel(("DSound: Could not initialize DirectSound\n"));
    1289         dsound_log_hresult(hr);
    1290 #endif
    1291 
    1292         hr = IDirectSound_Release (s->dsound);
    1293         if (FAILED (hr)) {
    1294             dsound_logerr (hr, "Could not release DirectSound\n");
    1295         }
    1296         s->dsound = NULL;
    1297         CoUninitialize();
    1298         return NULL;
     1283        s->devguidp_play = NULL;
    12991284    }
    13001285
     
    13091294    }
    13101295
    1311     err = dsound_open (s);
    1312     if (err) {
    1313         dsound_audio_fini (s);
    1314         return NULL;
    1315     }
    1316 
    1317     return s;
     1296    /* Check that DSound interface is available. */
     1297    if (dsoundIsAvailable ())
     1298        return s;
     1299
     1300    dsound_audio_fini (s);
     1301    return NULL;
    13181302}
    13191303
     
    13251309    {"GetStatusRetries", AUD_OPT_INT, &conf.getstatus_retries,
    13261310     "Number of times to attempt getting status of the buffer", NULL, 0},
    1327     {"SetPrimary", AUD_OPT_BOOL, &conf.set_primary,
    1328      "Set the parameters of primary buffer", NULL, 0},
    13291311    {"LatencyMillis", AUD_OPT_INT, &conf.latency_millis,
    13301312     "(undocumented)", NULL, 0},
    1331     {"PrimaryFreq", AUD_OPT_INT, &conf.settings.freq,
    1332      "Primary buffer frequency", NULL, 0},
    1333     {"PrimaryChannels", AUD_OPT_INT, &conf.settings.nchannels,
    1334      "Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0},
    1335     {"PrimaryFmt", AUD_OPT_FMT, &conf.settings.fmt,
    1336      "Primary buffer format", NULL, 0},
    13371313    {"BufsizeOut", AUD_OPT_INT, &conf.bufsize_out,
    13381314     "(undocumented)", NULL, 0},
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette