VirtualBox

Changeset 88554 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 15, 2021 10:20:26 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143849
Message:

DrvHostAudioDSound: Refreshed the stream creation code. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostAudioDSound.cpp

    r88542 r88554  
    4747*********************************************************************************************************************************/
    4848/*
    49  * IDirectSound* interface uses HRESULT status codes and the driver callbacks use
    50  * the VBox status codes.  To minimize HRESULT->VBox conversion most internal functions
    51  * in the driver return HRESULT and conversion is done in the driver callbacks.
    52  *
    53  * Naming convention:
    54  * 'dsound*' functions return VBox status code;
    55  * 'directSound*' - return HRESULT.
    56  */
    57 
    58 /*
    5949 * Optional release logging, which a user can turn on with the
    6050 * 'VBoxManage debugvm' command.
    6151 * Debug logging still uses the common Log* macros from VBox.
    6252 * Messages which always should go to the release log use LogRel.
     53 *
     54 * @deprecated Use LogRelMax, LogRel2 and LogRel3 directly.
    6355 */
    6456/** General code behavior. */
     
    7870/** Maximum number of attempts to restore the sound buffer before giving up. */
    7971#define DRV_DSOUND_RESTORE_ATTEMPTS_MAX         3
     72#if 0 /** @todo r=bird: What are these for? Nobody is using them... */
    8073/** Default input latency (in ms). */
    8174#define DRV_DSOUND_DEFAULT_LATENCY_MS_IN        50
    8275/** Default output latency (in ms). */
    8376#define DRV_DSOUND_DEFAULT_LATENCY_MS_OUT       50
    84 
    85 /** Makes DRVHOSTDSOUND out of PDMIHOSTAUDIO. */
    86 #define PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface) \
    87     ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_UOFFSETOF(DRVHOSTDSOUND, IHostAudio)) )
     77#endif
    8878
    8979
     
    248238
    249239static int      dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable);
    250 static void     dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS);
    251240static void     dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis);
    252241
     
    407396
    408397/**
    409  * Destroys a DirectSound playback interface.
    410  *
    411  * @param   pDS                 Playback interface to destroy.
    412  */
    413 static void directSoundPlayInterfaceDestroy(LPDIRECTSOUND8 pDS)
    414 {
    415     if (pDS)
    416     {
    417         LogFlowFuncEnter();
    418 
    419         IDirectSound8_Release(pDS);
    420         pDS = NULL;
    421     }
    422 }
    423 
    424 
    425 /**
    426  * Creates a DirectSound playback interface.
     398 * Creates a DirectSound playback instance.
    427399 *
    428400 * @return  HRESULT
    429  * @param   pGUID               GUID of device to create the playback interface for.
    430  * @param   ppDS                Where to store the created interface. Optional.
    431  */
    432 static HRESULT directSoundPlayInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUND8 *ppDS)
    433 {
    434     /* pGUID can be NULL, if this is the default device. */
    435     /* ppDS is optional. */
    436 
     401 * @param   pGUID   GUID of device to create the playback interface for. NULL
     402 *                  for the default device.
     403 * @param   ppDS    Where to return the interface to the created instance.
     404 */
     405static HRESULT drvHostDSoundCreateDSPlaybackInstance(LPCGUID pGUID, LPDIRECTSOUND8 *ppDS)
     406{
    437407    LogFlowFuncEnter();
    438408
    439     LPDIRECTSOUND8 pDS;
    440     HRESULT hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL,
    441                                   IID_IDirectSound8, (void **)&pDS);
    442     if (FAILED(hr))
    443     {
    444         DSLOGREL(("DSound: Creating playback instance failed with %Rhrc\n", hr));
     409    LPDIRECTSOUND8 pDS = NULL;
     410    HRESULT        hrc = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL, IID_IDirectSound8, (void **)&pDS);
     411    if (SUCCEEDED(hrc))
     412    {
     413        hrc = IDirectSound8_Initialize(pDS, pGUID);
     414        if (SUCCEEDED(hrc))
     415        {
     416            HWND hWnd = GetDesktopWindow();
     417            hrc = IDirectSound8_SetCooperativeLevel(pDS, hWnd, DSSCL_PRIORITY);
     418            if (SUCCEEDED(hrc))
     419            {
     420                *ppDS = pDS;
     421                LogFlowFunc(("LEAVE S_OK\n"));
     422                return S_OK;
     423            }
     424            LogRelMax(64, ("DSound: Setting cooperative level for (hWnd=%p) failed: %Rhrc\n", hWnd, hrc));
     425        }
     426        else if (hrc == DSERR_NODRIVER) /* Usually means that no playback devices are attached. */
     427            LogRelMax(64, ("DSound: DirectSound playback is currently unavailable\n"));
     428        else
     429            LogRelMax(64, ("DSound: DirectSound playback initialization failed: %Rhrc\n", hrc));
     430
     431        IDirectSound8_Release(pDS);
    445432    }
    446433    else
    447     {
    448         hr = IDirectSound8_Initialize(pDS, pGUID);
    449         if (SUCCEEDED(hr))
    450         {
    451             HWND hWnd = GetDesktopWindow();
    452             hr = IDirectSound8_SetCooperativeLevel(pDS, hWnd, DSSCL_PRIORITY);
    453             if (FAILED(hr))
    454                 DSLOGREL(("DSound: Setting cooperative level for window %p failed with %Rhrc\n", hWnd, hr));
    455         }
    456 
    457         if (FAILED(hr))
    458         {
    459             if (hr == DSERR_NODRIVER) /* Usually means that no playback devices are attached. */
    460                 DSLOGREL(("DSound: DirectSound playback is currently unavailable\n"));
    461             else
    462                 DSLOGREL(("DSound: DirectSound playback initialization failed with %Rhrc\n", hr));
    463 
    464             directSoundPlayInterfaceDestroy(pDS);
    465         }
    466         else if (ppDS)
    467         {
    468             *ppDS = pDS;
    469         }
    470     }
    471 
    472     LogFlowFunc(("Returning %Rhrc\n", hr));
    473     return hr;
    474 }
    475 
    476 
     434        LogRelMax(64, ("DSound: Creating playback instance failed: %Rhrc\n", hrc));
     435
     436    LogFlowFunc(("LEAVE %Rhrc\n", hrc));
     437    return hrc;
     438}
     439
     440
     441#if 0 /* not used */
    477442static HRESULT directSoundPlayGetStatus(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB, DWORD *pdwStatus)
    478443{
     
    508473    return hr;
    509474}
     475#endif
    510476
    511477
     
    571537
    572538/**
    573  * Destroys a DirectSound capture interface.
     539 * Creates a DirectSound capture instance.
    574540 *
    575  * @param   pDSC                Capture interface to destroy.
    576  */
    577 static void directSoundCaptureInterfaceDestroy(LPDIRECTSOUNDCAPTURE8 pDSC)
    578 {
    579     if (pDSC)
    580     {
    581         LogFlowFuncEnter();
    582 
     541 * @returns HRESULT
     542 * @param   pGUID   GUID of device to create the capture interface for.  NULL
     543 *                  for default.
     544 * @param   ppDSC   Where to return the interface to the created instance.
     545 */
     546static HRESULT drvHostDSoundCreateDSCaptureInstance(LPCGUID pGUID, LPDIRECTSOUNDCAPTURE8 *ppDSC)
     547{
     548    LogFlowFuncEnter();
     549
     550    LPDIRECTSOUNDCAPTURE8 pDSC = NULL;
     551    HRESULT hrc = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL, IID_IDirectSoundCapture8, (void **)&pDSC);
     552    if (SUCCEEDED(hrc))
     553    {
     554        hrc = IDirectSoundCapture_Initialize(pDSC, pGUID);
     555        if (SUCCEEDED(hrc))
     556        {
     557            *ppDSC = pDSC;
     558            LogFlowFunc(("LEAVE S_OK\n"));
     559            return S_OK;
     560        }
     561        if (hrc == DSERR_NODRIVER) /* Usually means that no capture devices are attached. */
     562            LogRelMax(64, ("DSound: Capture device currently is unavailable\n"));
     563        else
     564            LogRelMax(64, ("DSound: Initializing capturing device failed: %Rhrc\n", hrc));
    583565        IDirectSoundCapture_Release(pDSC);
    584         pDSC = NULL;
    585     }
    586 }
    587 
    588 
    589 /**
    590  * Creates a DirectSound capture interface.
    591  *
    592  * @return  HRESULT
    593  * @param   pGUID               GUID of device to create the capture interface for.
    594  * @param   ppDSC               Where to store the created interface. Optional.
    595  */
    596 static HRESULT directSoundCaptureInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUNDCAPTURE8 *ppDSC)
    597 {
    598     /* pGUID can be NULL, if this is the default device. */
    599     /* ppDSC is optional. */
    600 
    601     LogFlowFuncEnter();
    602 
    603     LPDIRECTSOUNDCAPTURE8 pDSC;
    604     HRESULT hr = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL,
    605                                   IID_IDirectSoundCapture8, (void **)&pDSC);
    606     if (FAILED(hr))
    607     {
    608         DSLOGREL(("DSound: Creating capture instance failed with %Rhrc\n", hr));
    609566    }
    610567    else
    611     {
    612         hr = IDirectSoundCapture_Initialize(pDSC, pGUID);
    613         if (FAILED(hr))
    614         {
    615             if (hr == DSERR_NODRIVER) /* Usually means that no capture devices are attached. */
    616                 DSLOGREL(("DSound: Capture device currently is unavailable\n"));
    617             else
    618                 DSLOGREL(("DSound: Initializing capturing device failed with %Rhrc\n", hr));
    619 
    620             directSoundCaptureInterfaceDestroy(pDSC);
    621         }
    622         else if (ppDSC)
    623         {
    624             *ppDSC = pDSC;
    625         }
    626     }
    627 
    628     LogFlowFunc(("Returning %Rhrc\n", hr));
    629     return hr;
     568        LogRelMax(64, ("DSound: Creating capture instance failed: %Rhrc\n", hrc));
     569
     570    LogFlowFunc(("LEAVE %Rhrc\n", hrc));
     571    return hrc;
    630572}
    631573
     
    832774    {
    833775        LPDIRECTSOUND8 pDS;
    834         HRESULT hr = directSoundPlayInterfaceCreate(&pDev->Guid, &pDS);
     776        HRESULT hr = drvHostDSoundCreateDSPlaybackInstance(&pDev->Guid, &pDS);
    835777        if (SUCCEEDED(hr))
    836778        {
     
    879821            }
    880822
    881             directSoundPlayInterfaceDestroy(pDS);
     823            IDirectSound8_Release(pDS);
    882824        }
    883825        else
     
    887829    {
    888830        LPDIRECTSOUNDCAPTURE8 pDSC;
    889         HRESULT hr = directSoundCaptureInterfaceCreate(&pDev->Guid, &pDSC);
     831        HRESULT hr = drvHostDSoundCreateDSCaptureInstance(&pDev->Guid, &pDSC);
    890832        if (SUCCEEDED(hr))
    891833        {
     
    905847            }
    906848
    907             directSoundCaptureInterfaceDestroy(pDSC);
     849            IDirectSoundCapture_Release(pDSC);
    908850        }
    909851        else
     
    11831125static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostDSoundHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    11841126{
    1185     RT_NOREF(enmDir);
    1186     AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
    1187 
     1127    RT_NOREF(pInterface, enmDir);
    11881128    return PDMAUDIOBACKENDSTS_RUNNING;
    11891129}
    11901130
    11911131
    1192 static int dsoundWaveFmtFromCfg(PPDMAUDIOSTREAMCFG pCfg, PWAVEFORMATEX pFmt)
    1193 {
    1194     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    1195     AssertPtrReturn(pFmt, VERR_INVALID_POINTER);
    1196 
    1197     RT_BZERO(pFmt, sizeof(WAVEFORMATEX));
    1198 
     1132/**
     1133 * Converts from PDM stream config to windows WAVEFORMATEX struct.
     1134 *
     1135 * @param   pCfg    The PDM audio stream config to convert from.
     1136 * @param   pFmt    The windows structure to initialize.
     1137 */
     1138static void dsoundWaveFmtFromCfg(PCPDMAUDIOSTREAMCFG pCfg, PWAVEFORMATEX pFmt)
     1139{
     1140    RT_ZERO(*pFmt);
    11991141    pFmt->wFormatTag      = WAVE_FORMAT_PCM;
    12001142    pFmt->nChannels       = PDMAudioPropsChannels(&pCfg->Props);
     
    12041146    pFmt->nAvgBytesPerSec = PDMAudioPropsFramesToBytes(&pCfg->Props, PDMAudioPropsHz(&pCfg->Props));
    12051147    pFmt->cbSize          = 0; /* No extra data specified. */
    1206 
    1207     return VINF_SUCCESS;
    1208 }
    1209 
    1210 
    1211 /**
    1212  * Resets the state of a DirectSound stream.
     1148}
     1149
     1150
     1151/**
     1152 * Resets the state of a DirectSound stream, clearing the buffer content.
    12131153 *
    12141154 * @param   pThis               Host audio driver instance.
    12151155 * @param   pStreamDS           Stream to reset state for.
    12161156 */
    1217 static void dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1157static void drvHostDSoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    12181158{
    12191159    RT_NOREF(pThis);
    1220 
    1221     LogFunc(("Resetting %s\n",
    1222              pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN ? "capture" : "playback"));
     1160    LogFunc(("Resetting %s\n", pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN ? "capture" : "playback"));
    12231161
    12241162    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
    12251163    {
     1164        /*
     1165         * Input streams.
     1166         */
     1167        LogFunc(("Resetting capture stream '%s'\n", pStreamDS->Cfg.szName));
     1168
     1169        /* Reset the state: */
     1170/** @todo r=bird: We set the read position to zero here, but shouldn't we query it
     1171 * from the buffer instead given that there isn't any interface for repositioning
     1172 * to the start of the buffer as with playback buffers? */
    12261173        pStreamDS->In.offReadPos = 0;
    12271174        pStreamDS->In.cOverruns  = 0;
    12281175
    1229         /* Also reset the DirectSound Capture Buffer (DSCB) by clearing all data to make sure
    1230          * not stale audio data is left. */
     1176        /* Clear the buffer content: */
     1177        AssertPtr(pStreamDS->In.pDSCB);
    12311178        if (pStreamDS->In.pDSCB)
    12321179        {
    1233             PVOID pv1; PVOID pv2; DWORD cb1; DWORD cb2;
    1234             HRESULT hr = directSoundCaptureLock(pStreamDS, 0 /* Offset */, pStreamDS->cbBufSize, &pv1, &pv2, &cb1, &cb2,
    1235                                                 0 /* Flags */);
    1236             if (SUCCEEDED(hr))
     1180            PVOID   pv1 = NULL;
     1181            DWORD   cb1 = 0;
     1182            PVOID   pv2 = NULL;
     1183            DWORD   cb2 = 0;
     1184            HRESULT hrc = IDirectSoundCaptureBuffer8_Lock(pStreamDS->In.pDSCB, 0, pStreamDS->cbBufSize,
     1185                                                          &pv1, &cb1, &pv2, &cb2, 0 /*fFlags*/);
     1186            if (SUCCEEDED(hrc))
    12371187            {
    12381188                PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv1, cb1, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb1));
    12391189                if (pv2 && cb2)
    12401190                    PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv2, cb2, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb2));
    1241                 directSoundCaptureUnlock(pStreamDS->In.pDSCB, pv1, pv2, cb1, cb2);
     1191                hrc = IDirectSoundCaptureBuffer8_Unlock(pStreamDS->In.pDSCB, pv1, cb1, pv2, cb2);
     1192                if (FAILED(hrc))
     1193                    LogRelMaxFunc(64, ("DSound: Unlocking capture buffer '%s' after reset failed: %Rhrc\n",
     1194                                       pStreamDS->Cfg.szName, hrc));
    12421195            }
    1243         }
    1244     }
    1245     else if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT)
    1246     {
    1247         /* If draining was enagaged, make sure dsound has stopped playing. */
     1196            else
     1197                LogRelMaxFunc(64, ("DSound: Locking capture buffer '%s' for reset failed: %Rhrc\n",
     1198                                   pStreamDS->Cfg.szName, hrc));
     1199        }
     1200    }
     1201    else
     1202    {
     1203        /*
     1204         * Output streams.
     1205         */
     1206        Assert(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT);
     1207        LogFunc(("Resetting playback stream '%s'\n", pStreamDS->Cfg.szName));
     1208
     1209        /* If draining was enagaged, make sure dsound has stopped playing: */
    12481210        if (pStreamDS->Out.fDrain && pStreamDS->Out.pDSB)
    12491211            pStreamDS->Out.pDSB->Stop();
    12501212
    1251         pStreamDS->Out.fFirstTransfer = true;
    1252         pStreamDS->Out.fDrain         = false;
    1253         pStreamDS->Out.cUnderruns     = 0;
    1254 
    1255         pStreamDS->Out.cbLastTransferred   = 0;
    1256         pStreamDS->Out.tsLastTransferredMs = 0;
    1257 
    1258         pStreamDS->Out.cbTransferred = 0;
    1259         pStreamDS->Out.cbWritten = 0;
    1260 
    1261         pStreamDS->Out.offWritePos = 0;
     1213        /* Reset the internal state: */
     1214        pStreamDS->Out.fFirstTransfer           = true;
     1215        pStreamDS->Out.fDrain                   = false;
     1216        pStreamDS->Out.cUnderruns               = 0;
     1217        pStreamDS->Out.cbLastTransferred        = 0;
     1218        pStreamDS->Out.tsLastTransferredMs      = 0;
     1219        pStreamDS->Out.cbTransferred            = 0;
     1220        pStreamDS->Out.cbWritten                = 0;
     1221        pStreamDS->Out.offWritePos              = 0;
    12621222        pStreamDS->Out.offPlayCursorLastPending = 0;
    1263         pStreamDS->Out.offPlayCursorLastPlayed = 0;
    1264 
    1265         /* Also reset the DirectSound Buffer (DSB) by setting the position to 0 and clear all data to make sure
    1266          * not stale audio data is left. */
     1223        pStreamDS->Out.offPlayCursorLastPlayed  = 0;
     1224
     1225        /* Reset the buffer content and repositioning the buffer to the start of the buffer. */
     1226        AssertPtr(pStreamDS->Out.pDSB);
    12671227        if (pStreamDS->Out.pDSB)
    12681228        {
    1269             HRESULT hr = IDirectSoundBuffer8_SetCurrentPosition(pStreamDS->Out.pDSB, 0);
    1270             if (SUCCEEDED(hr))
     1229            HRESULT hrc = IDirectSoundBuffer8_SetCurrentPosition(pStreamDS->Out.pDSB, 0);
     1230            if (FAILED(hrc))
     1231                LogRelMaxFunc(64, ("DSound: Failed to set buffer position for '%s': %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1232
     1233            PVOID   pv1 = NULL;
     1234            DWORD   cb1 = 0;
     1235            PVOID   pv2 = NULL;
     1236            DWORD   cb2 = 0;
     1237            hrc = IDirectSoundBuffer8_Lock(pStreamDS->Out.pDSB, 0, pStreamDS->cbBufSize, &pv1, &cb1, &pv2, &cb2, 0 /*fFlags*/);
     1238            if (hrc == DSERR_BUFFERLOST)
    12711239            {
    1272                 PVOID pv1; PVOID pv2; DWORD cb1; DWORD cb2;
    1273                 hr = directSoundPlayLock(pThis, pStreamDS, 0 /* Offset */, pStreamDS->cbBufSize, &pv1, &pv2, &cb1, &cb2,
    1274                                          0 /* Flags */);
    1275                 if (SUCCEEDED(hr))
    1276                 {
    1277                     PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv1, cb1, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb1));
    1278                     if (pv2 && cb2)
    1279                         PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv2, cb2, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb2));
    1280                     directSoundPlayUnlock(pThis, pStreamDS->Out.pDSB, pv1, pv2, cb1, cb2);
    1281                 }
     1240                directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
     1241                hrc = IDirectSoundBuffer8_Lock(pStreamDS->Out.pDSB, 0, pStreamDS->cbBufSize, &pv1, &cb1, &pv2, &cb2, 0 /*fFlags*/);
    12821242            }
     1243            if (SUCCEEDED(hrc))
     1244            {
     1245                PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv1, cb1, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb1));
     1246                if (pv2 && cb2)
     1247                    PDMAudioPropsClearBuffer(&pStreamDS->Cfg.Props, pv2, cb2, PDMAUDIOPCMPROPS_B2F(&pStreamDS->Cfg.Props, cb2));
     1248
     1249                hrc = IDirectSoundBuffer8_Unlock(pStreamDS->Out.pDSB, pv1, cb1, pv2, cb2);
     1250                if (FAILED(hrc))
     1251                    LogRelMaxFunc(64, ("DSound: Unlocking playback buffer '%s' after reset failed: %Rhrc\n",
     1252                                       pStreamDS->Cfg.szName, hrc));
     1253            }
     1254            else
     1255                LogRelMaxFunc(64, ("DSound: Locking playback buffer '%s' for reset failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
    12831256        }
    12841257    }
     
    12901263
    12911264
     1265/**
     1266 * Worker for drvHostDSoundHA_StreamCreate that creates caputre stream.
     1267 *
     1268 * @returns Windows COM status code.
     1269 * @param   pThis       The DSound instance data.
     1270 * @param   pStreamDS   The stream instance data.
     1271 * @param   pCfgReq     The requested stream config (input).
     1272 * @param   pCfgAcq     Where to return the actual stream config.  This is a
     1273 *                      copy of @a *pCfgReq when called.
     1274 * @param   pWaveFmtX   On input the requested stream format.
     1275 *                      Updated to the actual stream format on successful
     1276 *                      return.
     1277 */
     1278static HRESULT drvHostDSoundStreamCreateCapture(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
     1279                                                PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq, WAVEFORMATEX *pWaveFmtX)
     1280{
     1281    Assert(pStreamDS->In.pDSCB == NULL);
     1282    HRESULT hrc;
     1283
     1284    /*
     1285     * Create, initialize and set up a IDirectSoundCapture instance the first time
     1286     * we go thru here.
     1287     */
     1288    /** @todo bird: Or should we rather just throw this away after we've gotten the
     1289     *        capture buffer?  Old code would just leak it... */
     1290    if (pThis->pDSC == NULL)
     1291    {
     1292        hrc = drvHostDSoundCreateDSCaptureInstance(pThis->Cfg.pGuidCapture, &pThis->pDSC);
     1293        if (FAILED(hrc))
     1294            return hrc; /* The worker has complained to the release log already. */
     1295    }
     1296
     1297    /*
     1298     * Create the capture buffer.
     1299     */
     1300    DSCBUFFERDESC BufferDesc =
     1301    {
     1302        /*.dwSize = */          sizeof(BufferDesc),
     1303        /*.dwFlags = */         0,
     1304        /*.dwBufferBytes =*/    PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
     1305        /*.dwReserved = */      0,
     1306        /*.lpwfxFormat = */     pWaveFmtX,
     1307        /*.dwFXCount = */       0,
     1308        /*.lpDSCFXDesc = */     NULL
     1309    };
     1310
     1311    LogRel2(("DSound: Requested capture buffer is %#x B / %u B / %RU64 ms\n", BufferDesc.dwBufferBytes, BufferDesc.dwBufferBytes,
     1312             PDMAudioPropsBytesToMilli(&pCfgReq->Props, BufferDesc.dwBufferBytes)));
     1313
     1314    LPDIRECTSOUNDCAPTUREBUFFER pLegacyDSCB = NULL;
     1315    hrc = IDirectSoundCapture_CreateCaptureBuffer(pThis->pDSC, &BufferDesc, &pLegacyDSCB, NULL);
     1316    if (FAILED(hrc))
     1317    {
     1318        LogRelMax(64, ("DSound: Creating capture buffer for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1319        return hrc;
     1320    }
     1321
     1322    /* Get the IDirectSoundCaptureBuffer8 version of the interface. */
     1323    hrc = IDirectSoundCaptureBuffer_QueryInterface(pLegacyDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pStreamDS->In.pDSCB);
     1324    IDirectSoundCaptureBuffer_Release(pLegacyDSCB);
     1325    if (FAILED(hrc))
     1326    {
     1327        LogRelMax(64, ("DSound: Querying IID_IDirectSoundCaptureBuffer8 for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1328        return hrc;
     1329    }
     1330
     1331    /*
     1332     * Query the actual stream configuration.
     1333     */
     1334#if 0 /** @todo r=bird: WTF was this for? */
     1335    DWORD offByteReadPos = 0;
     1336    hrc = IDirectSoundCaptureBuffer8_GetCurrentPosition(pStreamDS->In.pDSCB, NULL, &offByteReadPos);
     1337    if (FAILED(hrc))
     1338    {
     1339        offByteReadPos = 0;
     1340        DSLOGREL(("DSound: Getting capture position failed with %Rhrc\n", hr));
     1341    }
     1342#endif
     1343    RT_ZERO(*pWaveFmtX);
     1344    hrc = IDirectSoundCaptureBuffer8_GetFormat(pStreamDS->In.pDSCB, pWaveFmtX, sizeof(*pWaveFmtX), NULL);
     1345    if (SUCCEEDED(hrc))
     1346    {
     1347        /** @todo r=bird: We aren't converting/checking the pWaveFmtX content...   */
     1348
     1349        DSCBCAPS BufferCaps = { /*.dwSize = */ sizeof(BufferCaps), 0, 0, 0 };
     1350        hrc = IDirectSoundCaptureBuffer8_GetCaps(pStreamDS->In.pDSCB, &BufferCaps);
     1351        if (SUCCEEDED(hrc))
     1352        {
     1353            LogRel2(("DSound: Acquired capture buffer capabilities for '%s':\n"
     1354                     "DSound:   dwFlags       = %#RX32\n"
     1355                     "DSound:   dwBufferBytes = %#RX32 B / %RU32 B / %RU64 ms\n"
     1356                     "DSound:   dwReserved    = %#RX32\n",
     1357                     pCfgReq->szName, BufferCaps.dwFlags, BufferCaps.dwBufferBytes, BufferCaps.dwBufferBytes,
     1358                     PDMAudioPropsBytesToMilli(&pCfgReq->Props, BufferCaps.dwBufferBytes), BufferCaps.dwReserved ));
     1359
     1360            /* Update buffer related stuff: */
     1361            pStreamDS->In.offReadPos = 0; /** @todo shouldn't we use offBytReadPos here to "read at the initial capture position"? */
     1362            pStreamDS->cbBufSize     = BufferCaps.dwBufferBytes;
     1363            pCfgAcq->Backend.cFramesBufferSize = PDMAudioPropsBytesToFrames(&pCfgAcq->Props, BufferCaps.dwBufferBytes);
     1364
     1365            /** @todo r=bird: WTF is this for? */
     1366            pThis->pDSStrmIn = pStreamDS;
     1367
     1368#if 0 /** @todo r=bird: uAlign isn't set anywhere, so this hasn't been checking anything for a while... */
     1369            if (bc.dwBufferBytes & pStreamDS->uAlign)
     1370                DSLOGREL(("DSound: Capture GetCaps returned misaligned buffer: size %RU32, alignment %RU32\n",
     1371                          bc.dwBufferBytes, pStreamDS->uAlign + 1));
     1372#endif
     1373            LogFlow(("returns S_OK\n"));
     1374            return S_OK;
     1375        }
     1376        LogRelMax(64, ("DSound: Getting capture buffer capabilities for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1377    }
     1378    else
     1379        LogRelMax(64, ("DSound: Getting capture format for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1380
     1381    IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB);
     1382    pStreamDS->In.pDSCB = NULL;
     1383    LogFlowFunc(("returns %Rhrc\n", hrc));
     1384    return hrc;
     1385}
     1386
     1387
     1388/**
     1389 * Worker for drvHostDSoundHA_StreamCreate that creates playback stream.
     1390 *
     1391 * @returns Windows COM status code.
     1392 * @param   pThis       The DSound instance data.
     1393 * @param   pStreamDS   The stream instance data.
     1394 * @param   pCfgReq     The requested stream config (input).
     1395 * @param   pCfgAcq     Where to return the actual stream config.  This is a
     1396 *                      copy of @a *pCfgReq when called.
     1397 * @param   pWaveFmtX   On input the requested stream format.
     1398 *                      Updated to the actual stream format on successful
     1399 *                      return.
     1400 */
     1401static HRESULT drvHostDSoundStreamCreatePlayback(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
     1402                                                 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq, WAVEFORMATEX *pWaveFmtX)
     1403{
     1404    Assert(pStreamDS->Out.pDSB == NULL);
     1405    HRESULT hrc;
     1406
     1407    /*
     1408     * Create, initialize and set up a DirectSound8 instance the first time
     1409     * we go thru here.
     1410     */
     1411    /** @todo bird: Or should we rather just throw this away after we've gotten the
     1412     *        sound buffer?  Old code would just leak it... */
     1413    if (pThis->pDS == NULL)
     1414    {
     1415        hrc = drvHostDSoundCreateDSPlaybackInstance(pThis->Cfg.pGuidPlay, &pThis->pDS);
     1416        if (FAILED(hrc))
     1417            return hrc; /* The worker has complained to the release log already. */
     1418    }
     1419
     1420    /*
     1421     * As we reuse our (secondary) buffer for playing out data as it comes in,
     1422     * we're using this buffer as a so-called streaming buffer.
     1423     *
     1424     * See https://msdn.microsoft.com/en-us/library/windows/desktop/ee419014(v=vs.85).aspx
     1425     *
     1426     * However, as we do not want to use memory on the sound device directly
     1427     * (as most modern audio hardware on the host doesn't have this anyway),
     1428     * we're *not* going to use DSBCAPS_STATIC for that.
     1429     *
     1430     * Instead we're specifying DSBCAPS_LOCSOFTWARE, as this fits the bill
     1431     * of copying own buffer data to our secondary's Direct Sound buffer.
     1432     */
     1433    DSBUFFERDESC BufferDesc =
     1434    {
     1435        /*.dwSize = */          sizeof(BufferDesc),
     1436        /*.dwFlags = */         DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE,
     1437        /*.dwBufferBytes = */   PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
     1438        /*.dwReserved = */      0,
     1439        /*.lpwfxFormat = */     pWaveFmtX
     1440        /*.guid3DAlgorithm =    {0, 0, 0, {0,0,0,0, 0,0,0,0}} */
     1441    };
     1442    LogRel2(("DSound: Requested playback buffer is %#x B / %u B / %RU64 ms\n", BufferDesc.dwBufferBytes, BufferDesc.dwBufferBytes,
     1443             PDMAudioPropsBytesToMilli(&pCfgReq->Props, BufferDesc.dwBufferBytes)));
     1444
     1445    LPDIRECTSOUNDBUFFER pLegacyDSB = NULL;
     1446    hrc = IDirectSound8_CreateSoundBuffer(pThis->pDS, &BufferDesc, &pLegacyDSB, NULL);
     1447    if (FAILED(hrc))
     1448    {
     1449        LogRelMax(64, ("DSound: Creating playback sound buffer for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1450        return hrc;
     1451    }
     1452
     1453    /* Get the IDirectSoundBuffer8 version of the interface. */
     1454    hrc = IDirectSoundBuffer_QueryInterface(pLegacyDSB, IID_IDirectSoundBuffer8, (PVOID *)&pStreamDS->Out.pDSB);
     1455    IDirectSoundBuffer_Release(pLegacyDSB);
     1456    if (FAILED(hrc))
     1457    {
     1458        LogRelMax(64, ("DSound: Querying IID_IDirectSoundBuffer8 for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1459        return hrc;
     1460    }
     1461
     1462    /*
     1463     * Query the actual stream parameters, they may differ from what we requested.
     1464     */
     1465    RT_ZERO(*pWaveFmtX);
     1466    hrc = IDirectSoundBuffer8_GetFormat(pStreamDS->Out.pDSB, pWaveFmtX, sizeof(*pWaveFmtX), NULL);
     1467    if (SUCCEEDED(hrc))
     1468    {
     1469        /** @todo r=bird: We aren't converting/checking the pWaveFmtX content...   */
     1470
     1471        DSBCAPS BufferCaps = { /*.dwSize = */ sizeof(BufferCaps), 0, 0, 0, 0 };
     1472        hrc = IDirectSoundBuffer8_GetCaps(pStreamDS->Out.pDSB, &BufferCaps);
     1473        if (SUCCEEDED(hrc))
     1474        {
     1475            LogRel2(("DSound: Acquired playback buffer capabilities for '%s':\n"
     1476                     "DSound:   dwFlags              = %#RX32\n"
     1477                     "DSound:   dwBufferBytes        = %#RX32 B / %RU32 B / %RU64 ms\n"
     1478                     "DSound:   dwUnlockTransferRate = %RU32 KB/s\n"
     1479                     "DSound:   dwPlayCpuOverhead    = %RU32%%\n",
     1480                     pCfgReq->szName, BufferCaps.dwFlags, BufferCaps.dwBufferBytes, BufferCaps.dwBufferBytes,
     1481                     PDMAudioPropsBytesToMilli(&pCfgReq->Props, BufferCaps.dwBufferBytes),
     1482                     BufferCaps.dwUnlockTransferRate, BufferCaps.dwPlayCpuOverhead));
     1483
     1484            /* Update buffer related stuff: */
     1485            pStreamDS->cbBufSize = BufferCaps.dwBufferBytes;
     1486            pCfgAcq->Backend.cFramesBufferSize    = PDMAudioPropsBytesToFrames(&pCfgAcq->Props, BufferCaps.dwBufferBytes);
     1487            pCfgAcq->Backend.cFramesPeriod        = pCfgAcq->Backend.cFramesBufferSize / 4; /* total fiction */
     1488            pCfgAcq->Backend.cFramesPreBuffering  = pCfgReq->Backend.cFramesPreBuffering * pCfgAcq->Backend.cFramesBufferSize
     1489                                                  / RT_MAX(pCfgReq->Backend.cFramesBufferSize, 1);
     1490
     1491            /** @todo r=bird: WTF is this for? */
     1492            pThis->pDSStrmOut = pStreamDS;
     1493
     1494#if 0 /** @todo r=bird: uAlign isn't set anywhere, so this hasn't been checking anything for a while... */
     1495            if (bc.dwBufferBytes & pStreamDS->uAlign)
     1496                DSLOGREL(("DSound: Playback capabilities returned misaligned buffer: size %RU32, alignment %RU32\n",
     1497                          bc.dwBufferBytes, pStreamDS->uAlign + 1));
     1498#endif
     1499            LogFlow(("returns S_OK\n"));
     1500            return S_OK;
     1501        }
     1502        LogRelMax(64, ("DSound: Getting playback buffer capabilities for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1503    }
     1504    else
     1505        LogRelMax(64, ("DSound: Getting playback format for '%s' failed: %Rhrc\n", pCfgReq->szName, hrc));
     1506
     1507    IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB);
     1508    pStreamDS->Out.pDSB = NULL;
     1509    LogFlowFunc(("returns %Rhrc\n", hrc));
     1510    return hrc;
     1511}
     1512
     1513
     1514/**
     1515 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
     1516 */
     1517static DECLCALLBACK(int) drvHostDSoundHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     1518                                                      PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     1519{
     1520    PDRVHOSTDSOUND pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1521    PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
     1522    AssertPtrReturn(pStreamDS, VERR_INVALID_POINTER);
     1523    AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
     1524    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
     1525    AssertReturn(pCfgReq->enmDir == PDMAUDIODIR_IN || pCfgReq->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
     1526    Assert(PDMAudioStrmCfgEquals(pCfgReq, pCfgAcq));
     1527
     1528    const char * const pszStreamType = pCfgReq->enmDir == PDMAUDIODIR_IN ? "capture" : "playback"; RT_NOREF(pszStreamType);
     1529    LogFlowFunc(("enmSrc/Dst=%s '%s'\n",
     1530                 pCfgReq->enmDir == PDMAUDIODIR_IN ? PDMAudioRecSrcGetName(pCfgReq->u.enmSrc)
     1531                 : PDMAudioPlaybackDstGetName(pCfgReq->u.enmDst), pCfgReq->szName));
     1532
     1533    /* For whatever reason: */
     1534    dsoundUpdateStatusInternal(pThis);
     1535
     1536    /*
     1537     * DSound has different COM interfaces for working with input and output
     1538     * streams, so we'll quickly part ways here after some common format
     1539     * specification setup and logging.
     1540     */
     1541#if defined(RTLOG_REL_ENABLED) || defined(LOG_ENABLED)
     1542    char szTmp[64];
     1543#endif
     1544    LogRel2(("DSound: Opening %s stream '%s' (%s)\n", pCfgReq->szName, pszStreamType,
     1545             PDMAudioPropsToString(&pCfgReq->Props, szTmp, sizeof(szTmp))));
     1546
     1547    WAVEFORMATEX WaveFmtX;
     1548    dsoundWaveFmtFromCfg(pCfgReq, &WaveFmtX);
     1549    LogRel2(("DSound: Requested %s format for '%s':\n"
     1550             "DSound:   wFormatTag      = %RU16\n"
     1551             "DSound:   nChannels       = %RU16\n"
     1552             "DSound:   nSamplesPerSec  = %RU32\n"
     1553             "DSound:   nAvgBytesPerSec = %RU32\n"
     1554             "DSound:   nBlockAlign     = %RU16\n"
     1555             "DSound:   wBitsPerSample  = %RU16\n"
     1556             "DSound:   cbSize          = %RU16\n",
     1557             pszStreamType, pCfgReq->szName, WaveFmtX.wFormatTag, WaveFmtX.nChannels, WaveFmtX.nSamplesPerSec,
     1558             WaveFmtX.nAvgBytesPerSec, WaveFmtX.nBlockAlign, WaveFmtX.wBitsPerSample, WaveFmtX.cbSize));
     1559
     1560    HRESULT hrc;
     1561    if (pCfgReq->enmDir == PDMAUDIODIR_IN)
     1562        hrc = drvHostDSoundStreamCreateCapture(pThis, pStreamDS, pCfgReq, pCfgAcq, &WaveFmtX);
     1563    else
     1564        hrc = drvHostDSoundStreamCreatePlayback(pThis, pStreamDS, pCfgReq, pCfgAcq, &WaveFmtX);
     1565    int rc;
     1566    if (SUCCEEDED(hrc))
     1567    {
     1568        LogRel2(("DSound: Acquired %s format for '%s':\n"
     1569                 "DSound:   wFormatTag      = %RU16\n"
     1570                 "DSound:   nChannels       = %RU16\n"
     1571                 "DSound:   nSamplesPerSec  = %RU32\n"
     1572                 "DSound:   nAvgBytesPerSec = %RU32\n"
     1573                 "DSound:   nBlockAlign     = %RU16\n"
     1574                 "DSound:   wBitsPerSample  = %RU16\n"
     1575                 "DSound:   cbSize          = %RU16\n",
     1576                 pszStreamType, pCfgReq->szName, WaveFmtX.wFormatTag, WaveFmtX.nChannels, WaveFmtX.nSamplesPerSec,
     1577                 WaveFmtX.nAvgBytesPerSec, WaveFmtX.nBlockAlign, WaveFmtX.wBitsPerSample, WaveFmtX.cbSize));
     1578
     1579        /*
     1580         * Copy the acquired config and reset the stream (clears the buffer).
     1581         */
     1582        PDMAudioStrmCfgCopy(&pStreamDS->Cfg, pCfgAcq);
     1583        drvHostDSoundStreamReset(pThis, pStreamDS);
     1584        rc = VINF_SUCCESS;
     1585    }
     1586    else
     1587        rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     1588
     1589    LogFlowFunc(("returns %Rrc\n", rc));
     1590    return rc;
     1591}
     1592
     1593
     1594static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1595{
     1596    AssertPtrReturn(pThis,     E_POINTER);
     1597    AssertPtrReturn(pStreamDS, E_POINTER);
     1598
     1599    LogFlowFuncEnter();
     1600
     1601    HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
     1602    if (SUCCEEDED(hr))
     1603    {
     1604        DSLOG(("DSound: Closing playback stream\n"));
     1605        RTCritSectEnter(&pThis->CritSect);
     1606
     1607        if (pStreamDS->Out.pDSB)
     1608        {
     1609            IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB);
     1610            pStreamDS->Out.pDSB = NULL;
     1611        }
     1612
     1613        pThis->pDSStrmOut = NULL;
     1614
     1615        RTCritSectLeave(&pThis->CritSect);
     1616    }
     1617
     1618    if (FAILED(hr))
     1619        DSLOGREL(("DSound: Stopping playback stream %p failed with %Rhrc\n", pStreamDS, hr));
     1620
     1621    return hr;
     1622}
     1623
     1624
     1625static int dsoundDestroyStreamOut(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1626{
     1627    LogFlowFuncEnter();
     1628
     1629    HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
     1630    if (SUCCEEDED(hr))
     1631    {
     1632        hr = directSoundPlayClose(pThis, pStreamDS);
     1633        if (FAILED(hr))
     1634            return VERR_GENERAL_FAILURE; /** @todo Fix. */
     1635    }
     1636
     1637    return VINF_SUCCESS;
     1638}
     1639
     1640
    12921641static HRESULT directSoundCaptureClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    12931642{
     
    13151664
    13161665
    1317 static HRESULT directSoundCaptureOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
    1318                                       PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1319 {
    1320     AssertPtrReturn(pThis,     E_POINTER);
    1321     AssertPtrReturn(pStreamDS, E_POINTER);
    1322     AssertPtrReturn(pCfgReq,   E_POINTER);
    1323     AssertPtrReturn(pCfgAcq,   E_POINTER);
    1324 
    1325     /** @todo r=bird: I cannot see any code populating pCfgAcq... */
    1326 
     1666static int dsoundDestroyStreamIn(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1667{
    13271668    LogFlowFuncEnter();
    13281669
    1329     Assert(pStreamDS->In.pDSCB == NULL);
    1330 
    1331     DSLOG(("DSound: Opening capturing stream (uHz=%RU32, cChannels=%RU8, cBits=%u, fSigned=%RTbool)\n", pCfgReq->Props.uHz,
    1332            PDMAudioPropsChannels(&pCfgReq->Props), PDMAudioPropsSampleBits(&pCfgReq->Props), pCfgReq->Props.fSigned));
    1333 
    1334     WAVEFORMATEX wfx;
    1335     int rc = dsoundWaveFmtFromCfg(pCfgReq, &wfx);
    1336     if (RT_FAILURE(rc))
    1337         return E_INVALIDARG;
    1338 
    1339     /** @todo r=bird: Why is this called every time?  It triggers a device
    1340      * enumeration. Andy claimed on IRC that enumeration was only done once... */
    1341     dsoundUpdateStatusInternal(pThis);
    1342 
    1343     HRESULT hr = directSoundCaptureInterfaceCreate(pThis->Cfg.pGuidCapture, &pThis->pDSC);
    1344     if (FAILED(hr))
    1345         return hr;
    1346 
    1347     do /* For readability breaks... */
    1348     {
    1349         DSCBUFFERDESC bd;
    1350         RT_ZERO(bd);
    1351 
    1352         bd.dwSize        = sizeof(bd);
    1353         bd.lpwfxFormat   = &wfx;
    1354         bd.dwBufferBytes = PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize);
    1355 
    1356         DSLOG(("DSound: Requested capture buffer is %RU64ms (%ld bytes)\n",
    1357                PDMAudioPropsBytesToMilli(&pCfgReq->Props, bd.dwBufferBytes), bd.dwBufferBytes));
    1358 
    1359         LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
    1360         hr = IDirectSoundCapture_CreateCaptureBuffer(pThis->pDSC, &bd, &pDSCB, NULL);
    1361         if (FAILED(hr))
    1362         {
    1363             if (hr == E_ACCESSDENIED)
    1364             {
    1365                 DSLOGREL(("DSound: Capturing input from host not possible, access denied\n"));
    1366             }
    1367             else
    1368                 DSLOGREL(("DSound: Creating capture buffer failed with %Rhrc\n", hr));
    1369             break;
    1370         }
    1371 
    1372         hr = IDirectSoundCaptureBuffer_QueryInterface(pDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pStreamDS->In.pDSCB);
    1373         IDirectSoundCaptureBuffer_Release(pDSCB);
    1374         if (FAILED(hr))
    1375         {
    1376             DSLOGREL(("DSound: Querying interface for capture buffer failed with %Rhrc\n", hr));
    1377             break;
    1378         }
    1379 
    1380         /*
    1381          * Query the actual parameters.
    1382          */
    1383         DWORD offByteReadPos = 0;
    1384         hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pStreamDS->In.pDSCB, NULL, &offByteReadPos);
    1385         if (FAILED(hr))
    1386         {
    1387             offByteReadPos = 0;
    1388             DSLOGREL(("DSound: Getting capture position failed with %Rhrc\n", hr));
    1389         }
    1390 
    1391         RT_ZERO(wfx);
    1392         hr = IDirectSoundCaptureBuffer8_GetFormat(pStreamDS->In.pDSCB, &wfx, sizeof(wfx), NULL);
    1393         if (FAILED(hr))
    1394         {
    1395             DSLOGREL(("DSound: Getting capture format failed with %Rhrc\n", hr));
    1396             break;
    1397         }
    1398 
    1399         DSCBCAPS bc;
    1400         RT_ZERO(bc);
    1401         bc.dwSize = sizeof(bc);
    1402         hr = IDirectSoundCaptureBuffer8_GetCaps(pStreamDS->In.pDSCB, &bc);
    1403         if (FAILED(hr))
    1404         {
    1405             DSLOGREL(("DSound: Getting capture capabilities failed with %Rhrc\n", hr));
    1406             break;
    1407         }
    1408 
    1409         DSLOG(("DSound: Acquired capture buffer is %RU64ms (%ld bytes)\n",
    1410                PDMAudioPropsBytesToMilli(&pCfgReq->Props, bc.dwBufferBytes), bc.dwBufferBytes));
    1411 
    1412         DSLOG(("DSound: Capture format:\n"
    1413                "  dwBufferBytes   = %RI32\n"
    1414                "  dwFlags         = 0x%x\n"
    1415                "  wFormatTag      = %RI16\n"
    1416                "  nChannels       = %RI16\n"
    1417                "  nSamplesPerSec  = %RU32\n"
    1418                "  nAvgBytesPerSec = %RU32\n"
    1419                "  nBlockAlign     = %RI16\n"
    1420                "  wBitsPerSample  = %RI16\n"
    1421                "  cbSize          = %RI16\n",
    1422                bc.dwBufferBytes,
    1423                bc.dwFlags,
    1424                wfx.wFormatTag,
    1425                wfx.nChannels,
    1426                wfx.nSamplesPerSec,
    1427                wfx.nAvgBytesPerSec,
    1428                wfx.nBlockAlign,
    1429                wfx.wBitsPerSample,
    1430                wfx.cbSize));
    1431 
    1432         if (bc.dwBufferBytes & pStreamDS->uAlign)
    1433             DSLOGREL(("DSound: Capture GetCaps returned misaligned buffer: size %RU32, alignment %RU32\n",
    1434                       bc.dwBufferBytes, pStreamDS->uAlign + 1));
    1435 
    1436         /* Initial state: reading at the initial capture position, no error. */
    1437         pStreamDS->In.offReadPos = 0;
    1438         pStreamDS->cbBufSize     = bc.dwBufferBytes;
    1439 
    1440         pThis->pDSStrmIn = pStreamDS;
    1441 
    1442         pCfgAcq->Backend.cFramesBufferSize = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pStreamDS->cbBufSize);
    1443 
    1444     } while (0);
    1445 
    1446     if (FAILED(hr))
    1447         directSoundCaptureClose(pThis, pStreamDS);
    1448 
    1449     LogFlowFunc(("Returning %Rhrc\n", hr));
    1450     return hr;
    1451 }
    1452 
    1453 
    1454 static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1455 {
    1456     AssertPtrReturn(pThis,     E_POINTER);
    1457     AssertPtrReturn(pStreamDS, E_POINTER);
    1458 
    1459     LogFlowFuncEnter();
    1460 
    1461     HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
    1462     if (SUCCEEDED(hr))
    1463     {
    1464         DSLOG(("DSound: Closing playback stream\n"));
    1465         RTCritSectEnter(&pThis->CritSect);
    1466 
    1467         if (pStreamDS->Out.pDSB)
    1468         {
    1469             IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB);
    1470             pStreamDS->Out.pDSB = NULL;
    1471         }
    1472 
    1473         pThis->pDSStrmOut = NULL;
    1474 
    1475         RTCritSectLeave(&pThis->CritSect);
    1476     }
    1477 
    1478     if (FAILED(hr))
    1479         DSLOGREL(("DSound: Stopping playback stream %p failed with %Rhrc\n", pStreamDS, hr));
    1480 
    1481     return hr;
    1482 }
    1483 
    1484 
    1485 static HRESULT directSoundPlayOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
    1486                                    PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1487 {
    1488     AssertPtrReturn(pThis,     E_POINTER);
    1489     AssertPtrReturn(pStreamDS, E_POINTER);
    1490     AssertPtrReturn(pCfgReq,   E_POINTER);
    1491     AssertPtrReturn(pCfgAcq,   E_POINTER);
    1492     LogFlowFuncEnter();
    1493 
    1494     Assert(pStreamDS->Out.pDSB == NULL);
    1495 
    1496     DSLOG(("DSound: Opening playback stream (uHz=%RU32, cChannels=%RU8, cBits=%u, fSigned=%RTbool)\n", pCfgReq->Props.uHz,
    1497            PDMAudioPropsChannels(&pCfgReq->Props), PDMAudioPropsSampleBits(&pCfgReq->Props), pCfgReq->Props.fSigned));
    1498 
    1499     WAVEFORMATEX wfx;
    1500     int rc = dsoundWaveFmtFromCfg(pCfgReq, &wfx);
    1501     if (RT_FAILURE(rc))
    1502         return E_INVALIDARG;
    1503 
    1504     DSLOG(("DSound: Requested playback format:\n"
    1505            "  wFormatTag      = %RI16\n"
    1506            "  nChannels       = %RI16\n"
    1507            "  nSamplesPerSec  = %RU32\n"
    1508            "  nAvgBytesPerSec = %RU32\n"
    1509            "  nBlockAlign     = %RI16\n"
    1510            "  wBitsPerSample  = %RI16\n"
    1511            "  cbSize          = %RI16\n",
    1512            wfx.wFormatTag,
    1513            wfx.nChannels,
    1514            wfx.nSamplesPerSec,
    1515            wfx.nAvgBytesPerSec,
    1516            wfx.nBlockAlign,
    1517            wfx.wBitsPerSample,
    1518            wfx.cbSize));
    1519 
    1520     /* Waste some time: */
    1521     dsoundUpdateStatusInternal(pThis);
    1522 
    1523     HRESULT hr = directSoundPlayInterfaceCreate(pThis->Cfg.pGuidPlay, &pThis->pDS);
    1524     if (FAILED(hr))
    1525         return hr;
    1526 
    1527     do /* To use breaks. */
    1528     {
    1529         LPDIRECTSOUNDBUFFER pDSB = NULL;
    1530 
    1531         DSBUFFERDESC bd;
    1532         RT_ZERO(bd);
    1533         bd.dwSize      = sizeof(bd);
    1534         bd.lpwfxFormat = &wfx;
    1535 
    1536         /*
    1537          * As we reuse our (secondary) buffer for playing out data as it comes in,
    1538          * we're using this buffer as a so-called streaming buffer.
    1539          *
    1540          * See https://msdn.microsoft.com/en-us/library/windows/desktop/ee419014(v=vs.85).aspx
    1541          *
    1542          * However, as we do not want to use memory on the sound device directly
    1543          * (as most modern audio hardware on the host doesn't have this anyway),
    1544          * we're *not* going to use DSBCAPS_STATIC for that.
    1545          *
    1546          * Instead we're specifying DSBCAPS_LOCSOFTWARE, as this fits the bill
    1547          * of copying own buffer data to our secondary's Direct Sound buffer.
    1548          */
    1549         bd.dwFlags       = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE;
    1550         bd.dwBufferBytes = PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize);
    1551 
    1552         DSLOG(("DSound: Requested playback buffer is %RU64ms (%ld bytes)\n",
    1553                PDMAudioPropsBytesToMilli(&pCfgReq->Props, bd.dwBufferBytes), bd.dwBufferBytes));
    1554 
    1555         hr = IDirectSound8_CreateSoundBuffer(pThis->pDS, &bd, &pDSB, NULL);
    1556         if (FAILED(hr))
    1557         {
    1558             DSLOGREL(("DSound: Creating playback sound buffer failed with %Rhrc\n", hr));
    1559             break;
    1560         }
    1561 
    1562         /* "Upgrade" to IDirectSoundBuffer8 interface. */
    1563         hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (PVOID *)&pStreamDS->Out.pDSB);
    1564         IDirectSoundBuffer_Release(pDSB);
    1565         if (FAILED(hr))
    1566         {
    1567             DSLOGREL(("DSound: Querying playback sound buffer interface failed with %Rhrc\n", hr));
    1568             break;
    1569         }
    1570 
    1571         /*
    1572          * Query the actual parameters set for this stream.
    1573          * Those might be different than the initially requested parameters.
    1574          */
    1575         RT_ZERO(wfx);
    1576         hr = IDirectSoundBuffer8_GetFormat(pStreamDS->Out.pDSB, &wfx, sizeof(wfx), NULL);
    1577         if (FAILED(hr))
    1578         {
    1579             DSLOGREL(("DSound: Getting playback format failed with %Rhrc\n", hr));
    1580             break;
    1581         }
    1582 
    1583         DSBCAPS bc;
    1584         RT_ZERO(bc);
    1585         bc.dwSize = sizeof(bc);
    1586 
    1587         hr = IDirectSoundBuffer8_GetCaps(pStreamDS->Out.pDSB, &bc);
    1588         if (FAILED(hr))
    1589         {
    1590             DSLOGREL(("DSound: Getting playback capabilities failed with %Rhrc\n", hr));
    1591             break;
    1592         }
    1593 
    1594         DSLOG(("DSound: Acquired playback buffer is %RU64ms (%ld bytes)\n",
    1595                PDMAudioPropsBytesToMilli(&pCfgReq->Props, bc.dwBufferBytes), bc.dwBufferBytes));
    1596 
    1597         DSLOG(("DSound: Acquired playback format:\n"
    1598                "  dwBufferBytes   = %RI32\n"
    1599                "  dwFlags         = 0x%x\n"
    1600                "  wFormatTag      = %RI16\n"
    1601                "  nChannels       = %RI16\n"
    1602                "  nSamplesPerSec  = %RU32\n"
    1603                "  nAvgBytesPerSec = %RU32\n"
    1604                "  nBlockAlign     = %RI16\n"
    1605                "  wBitsPerSample  = %RI16\n"
    1606                "  cbSize          = %RI16\n",
    1607                bc.dwBufferBytes,
    1608                bc.dwFlags,
    1609                wfx.wFormatTag,
    1610                wfx.nChannels,
    1611                wfx.nSamplesPerSec,
    1612                wfx.nAvgBytesPerSec,
    1613                wfx.nBlockAlign,
    1614                wfx.wBitsPerSample,
    1615                wfx.cbSize));
    1616 
    1617         if (bc.dwBufferBytes & pStreamDS->uAlign)
    1618             DSLOGREL(("DSound: Playback capabilities returned misaligned buffer: size %RU32, alignment %RU32\n",
    1619                       bc.dwBufferBytes, pStreamDS->uAlign + 1));
    1620 
    1621         /*
    1622          * Initial state.
    1623          * dsoundPlayStart initializes part of it to make sure that Stop/Start continues with a correct
    1624          * playback buffer position.
    1625          */
    1626         pStreamDS->cbBufSize = bc.dwBufferBytes;
    1627 
    1628         pThis->pDSStrmOut = pStreamDS;
    1629 
    1630         const uint32_t cfBufSize = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pStreamDS->cbBufSize);
    1631 
    1632         pCfgAcq->Backend.cFramesBufferSize    = cfBufSize;
    1633         pCfgAcq->Backend.cFramesPeriod        = cfBufSize / 4;
    1634         pCfgAcq->Backend.cFramesPreBuffering  = pCfgAcq->Backend.cFramesPeriod * 2;
    1635 
    1636     } while (0);
    1637 
    1638     if (FAILED(hr))
    1639         directSoundPlayClose(pThis, pStreamDS);
    1640 
    1641     return hr;
    1642 }
    1643 
    1644 
    1645 static void dsoundPlayClearBuffer(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1646 {
    1647     AssertPtrReturnVoid(pStreamDS);
    1648 
    1649     PPDMAUDIOPCMPROPS pProps = &pStreamDS->Cfg.Props;
    1650 
    1651     HRESULT hr = IDirectSoundBuffer_SetCurrentPosition(pStreamDS->Out.pDSB, 0 /* Position */);
    1652     if (FAILED(hr))
    1653         DSLOGREL(("DSound: Setting current position to 0 when clearing buffer failed with %Rhrc\n", hr));
    1654 
    1655     PVOID pv1;
    1656     hr = directSoundPlayLock(pThis, pStreamDS,
    1657                              0 /* dwOffset */, pStreamDS->cbBufSize,
    1658                              &pv1, NULL, 0, 0, DSBLOCK_ENTIREBUFFER);
    1659     if (SUCCEEDED(hr))
    1660     {
    1661         PDMAudioPropsClearBuffer(pProps, pv1, pStreamDS->cbBufSize, PDMAUDIOPCMPROPS_B2F(pProps, pStreamDS->cbBufSize));
    1662 
    1663         directSoundPlayUnlock(pThis, pStreamDS->Out.pDSB, pv1, NULL, 0, 0);
    1664 
    1665         /* Make sure to get the last playback position and current write position from DirectSound again.
    1666          * Those positions in theory could have changed, re-fetch them to be sure. */
    1667         DWORD offPlay  = 0;
    1668         DWORD offWrite = 0;
    1669         hr = IDirectSoundBuffer_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlay, &offWrite);
    1670         if (SUCCEEDED(hr))
    1671         {
    1672             pStreamDS->Out.offPlayCursorLastPlayed = offPlay;
    1673             pStreamDS->Out.offWritePos             = offWrite;
    1674         }
    1675         else
    1676             DSLOGREL(("DSound: Re-fetching current position when clearing buffer failed with %Rhrc\n", hr));
    1677     }
    1678 }
    1679 
    1680 
    1681 static int dsoundCreateStreamOut(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
    1682                                  PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1683 {
    1684     LogFlowFunc(("pStreamDS=%p, pCfgReq=%p\n", pStreamDS, pCfgReq));
    1685 
    1686     int rc;
    1687 
    1688     /* Try to open playback in case the device is already there. */
    1689     HRESULT hr = directSoundPlayOpen(pThis, pStreamDS, pCfgReq, pCfgAcq);
    1690     if (SUCCEEDED(hr))
    1691     {
    1692         rc = PDMAudioStrmCfgCopy(&pStreamDS->Cfg, pCfgAcq);
    1693         if (RT_SUCCESS(rc))
    1694             dsoundStreamReset(pThis, pStreamDS);
    1695     }
    1696     else
    1697         rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
    1698 
    1699     LogFlowFuncLeaveRC(rc);
    1700     return rc;
    1701 }
    1702 
    1703 
    1704 static int dsoundCreateStreamIn(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS,
    1705                                 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1706 {
    1707     LogFunc(("pStreamDS=%p, pCfgReq=%p, enmRecSource=%s\n",
    1708              pStreamDS, pCfgReq, PDMAudioRecSrcGetName(pCfgReq->u.enmSrc)));
    1709 
    1710 
    1711     /* Try to open capture in case the device is already there. */
    1712     int rc;
    1713     HRESULT hr = directSoundCaptureOpen(pThis, pStreamDS, pCfgReq, pCfgAcq);
    1714     if (SUCCEEDED(hr))
    1715     {
    1716         rc = PDMAudioStrmCfgCopy(&pStreamDS->Cfg, pCfgAcq);
    1717         if (RT_SUCCESS(rc))
    1718             dsoundStreamReset(pThis, pStreamDS);
    1719     }
    1720     else
    1721         rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
    1722 
    1723     return rc;
    1724 }
    1725 
    1726 
    1727 /**
    1728  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    1729  */
    1730 static DECLCALLBACK(int) drvHostDSoundHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    1731                                                       PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1732 {
    1733     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1734     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    1735     AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
    1736     AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
    1737 
    1738     PDRVHOSTDSOUND pThis     = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
     1670    directSoundCaptureClose(pThis, pStreamDS);
     1671
     1672    return VINF_SUCCESS;
     1673}
     1674
     1675
     1676/**
     1677 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
     1678 */
     1679static DECLCALLBACK(int) drvHostDSoundHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1680{
     1681    PDRVHOSTDSOUND pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
    17391682    PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
    1740 
    1741     int rc;
    1742     if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    1743         rc = dsoundCreateStreamIn(pThis,  pStreamDS, pCfgReq, pCfgAcq);
    1744     else
    1745         rc = dsoundCreateStreamOut(pThis, pStreamDS, pCfgReq, pCfgAcq);
    1746 
    1747     if (RT_SUCCESS(rc))
    1748     {
    1749         /** @todo already copied   */
    1750         rc = PDMAudioStrmCfgCopy(&pStreamDS->Cfg, pCfgAcq);
    1751         if (RT_SUCCESS(rc))
    1752             rc = RTCritSectInit(&pStreamDS->CritSect);
    1753     }
    1754 
    1755     return rc;
    1756 }
    1757 
    1758 
    1759 static int dsoundDestroyStreamOut(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1760 {
    1761     LogFlowFuncEnter();
    1762 
    1763     HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
    1764     if (SUCCEEDED(hr))
    1765     {
    1766         hr = directSoundPlayClose(pThis, pStreamDS);
    1767         if (FAILED(hr))
    1768             return VERR_GENERAL_FAILURE; /** @todo Fix. */
    1769     }
    1770 
    1771     return VINF_SUCCESS;
    1772 }
    1773 
    1774 
    1775 static int dsoundDestroyStreamIn(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1776 {
    1777     LogFlowFuncEnter();
    1778 
    1779     directSoundCaptureClose(pThis, pStreamDS);
    1780 
    1781     return VINF_SUCCESS;
    1782 }
    1783 
    1784 
    1785 /**
    1786  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
    1787  */
    1788 static DECLCALLBACK(int) drvHostDSoundHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    1789 {
    1790     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1791     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    1792 
    1793     PDRVHOSTDSOUND pThis     = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1794     PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
     1683    AssertPtrReturn(pStreamDS, VERR_INVALID_POINTER);
    17951684
    17961685    int rc;
     
    18271716
    18281717    if (fEnable)
    1829         dsoundStreamReset(pThis, pStreamDS);
     1718        drvHostDSoundStreamReset(pThis, pStreamDS);
    18301719
    18311720    pStreamDS->fEnabled = fEnable;
     
    18851774    {
    18861775        if (fFlush)
    1887             dsoundStreamReset(pThis, pStreamDS);
     1776            drvHostDSoundStreamReset(pThis, pStreamDS);
    18881777    }
    18891778
     
    20461935    {
    20471936        if (fFlush)
    2048              dsoundStreamReset(pThis, pStreamDS);
     1937             drvHostDSoundStreamReset(pThis, pStreamDS);
    20491938    }
    20501939
     
    20771966                if (SUCCEEDED(hr))
    20781967                {
     1968/** @todo r=bird: This isn't working. CfgAcq isn't initialized! */
    20791969                    PDMAUDIOSTREAMCFG CfgAcq;
    2080                     hr = directSoundCaptureOpen(pThis, pStreamDS, &pStreamDS->Cfg /* pCfgReq */, &CfgAcq);
     1970                    WAVEFORMATEX WaveFmtX;
     1971                    dsoundWaveFmtFromCfg(&pStreamDS->Cfg, &WaveFmtX);
     1972                    hr = drvHostDSoundStreamCreateCapture(pThis, pStreamDS, &pStreamDS->Cfg, &CfgAcq, &WaveFmtX);
    20811973                    if (SUCCEEDED(hr))
    20821974                    {
    2083                         rc = PDMAudioStrmCfgCopy(&pStreamDS->Cfg, &CfgAcq);
    2084                         if (RT_FAILURE(rc))
    2085                             break;
     1975                        PDMAudioStrmCfgCopy(&pStreamDS->Cfg, &CfgAcq);
    20861976
    20871977                        /** @todo What to do if the format has changed? */
     
    21282018                                                       PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    21292019{
    2130     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    2131     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    2132 
    2133     PDRVHOSTDSOUND pThis     = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
     2020    PDRVHOSTDSOUND pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
    21342021    PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
     2022    AssertPtrReturn(pStreamDS, VERR_INVALID_POINTER);
    21352023
    21362024    int rc;
Note: See TracChangeset for help on using the changeset viewer.

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