VirtualBox

Changeset 58983 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Dec 4, 2015 2:15:30 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
104507
Message:

Audio: Added support for dynamically enabling/disabling host audio backends, more code for audio callback support (still disabled).

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

Legend:

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

    r58600 r58983  
    3333
    3434#include "VBoxDD.h"
     35
     36#include "AudioMixBuffer.h"
    3537#include "AudioMixer.h"
    3638
     
    276278    AC97BusMasterRegs       bm_regs[3];
    277279    uint8_t                 mixer_data[256];
     280#ifndef VBOX_WITH_AUDIO_CALLBACKS
    278281    /** The emulation timer for handling the attached
    279282     *  LUN drivers. */
    280283    PTMTIMERR3              pTimer;
    281284    /** Timer ticks for handling the LUN drivers. */
    282     uint64_t                uTicks;
     285    uint64_t                uTimerTicks;
     286    /** Timestamp (delta) since last timer call. */
     287    uint64_t                uTimerTS;
     288#endif
    283289#ifdef VBOX_WITH_STATISTICS
    284290# if HC_ARCH_BITS == 32
     
    365371#define GET_BM(a_idx)   ( ((a_idx) >> 4) & 3 )
    366372
     373#ifndef VBOX_WITH_AUDIO_CALLBACKS
    367374static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
     375#endif
    368376static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed);
    369377
     
    10051013    while (cbToWrite)
    10061014    {
    1007         uint32_t cbWrittenMin = UINT32_MAX;
    1008 
    10091015        cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf);
    10101016        PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */
     
    10191025            int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    10201026                                                 pThis->pvReadWriteBuf, cbToRead, &cbWritten);
    1021             AssertRCBreak(rc);
    1022             if (RT_FAILURE(rc2))
    1023                 continue;
    1024 
    1025             cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten);
    1026             LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin));
    1027         }
    1028 
    1029         LogFlowFunc(("\tcbToRead=%RU32, cbWrittenMin=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
    1030                      cbToRead, cbWrittenMin, cbToWrite, cbToWrite - cbWrittenMin));
    1031 
    1032         if (!cbWrittenMin)
    1033         {
    1034             rc = VINF_EOF;
    1035             break;
    1036         }
    1037 
    1038         Assert(cbWrittenMin != UINT32_MAX);
    1039         Assert(cbToWrite >= cbWrittenMin);
    1040         cbToWrite      -= cbWrittenMin;
    1041         addr           += cbWrittenMin;
    1042         cbWrittenTotal += cbWrittenMin;
     1027            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
     1028        }
     1029
     1030        LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
     1031                     cbToRead, cbToWrite, cbToWrite - cbWrittenTotal));
     1032
     1033        Assert(cbToWrite >= cbToRead);
     1034        cbToWrite      -= cbToRead;
     1035        addr           += cbToRead;
     1036        cbWrittenTotal += cbToRead;
    10431037    }
    10441038
     
    11631157}
    11641158
     1159#ifndef VBOX_WITH_AUDIO_CALLBACKS
     1160
    11651161static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    11661162{
     
    11781174
    11791175    uint32_t cbIn, cbOut, cSamplesLive;
     1176
     1177    uint64_t uTicksNow     = PDMDevHlpTMTimeVirtGet(pDevIns);
     1178    uint64_t uTicksElapsed = uTicksNow  - pThis->uTimerTS;
     1179    uint64_t uTicksPerSec  = PDMDevHlpTMTimeVirtGetFreq(pDevIns);
     1180
     1181    pThis->uTimerTS = uTicksNow;
     1182
    11801183    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    11811184    {
     1185        cbIn = cbOut = 0;
    11821186        rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    1183                                               &cbIn, &cbOut, &cSamplesLive);
     1187                                              &cbIn, &cbOut, NULL /* cSamplesLive */);
    11841188        if (RT_SUCCESS(rc))
    1185         {
    1186 #ifdef DEBUG_TIMER
    1187             LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    1188 #endif
    1189             if (cSamplesLive)
    1190             {
    1191                 uint32_t cSamplesPlayed;
    1192                 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed);
    1193 #ifdef DEBUG_TIMER
    1194                 if (RT_SUCCESS(rc2))
    1195                     LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n",
    1196                                  pDrv->uLUN, cSamplesLive, cSamplesPlayed));
    1197 #endif
    1198                 if (cSamplesPlayed)
    1199                 {
    1200                     rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    1201                                                           &cbIn, &cbOut, &cSamplesLive);
    1202 #ifdef DEBUG_TIMER
    1203                     if (RT_SUCCESS(rc))
    1204                         LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    1205 #endif
    1206                 }
    1207             }
    1208 
    1209             cbInMax  = RT_MAX(cbInMax, cbIn);
    1210             cbOutMin = RT_MIN(cbOutMin, cbOut);
    1211         }
     1189            rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
     1190
     1191        uint32_t cSamplesMin  = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2);
     1192        uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
     1193
     1194        LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n",
     1195                     pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin));
     1196
     1197        if (   RT_FAILURE(rc)
     1198            && cbSamplesMin > cbOut)
     1199        {
     1200            LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin));
     1201            cbOut = cbSamplesMin;
     1202        }
     1203
     1204        cbOutMin = RT_MIN(cbOutMin, cbOut);
     1205        cbInMax  = RT_MAX(cbInMax, cbIn);
    12121206    }
    12131207
     
    12341228        ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */
    12351229
    1236     TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
     1230    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
    12371231
    12381232    STAM_PROFILE_STOP(&pThis->StatTimer, a);
    12391233}
     1234
     1235#endif
    12401236
    12411237static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed)
     
    23252321    }
    23262322
     2323# ifndef VBOX_WITH_AUDIO_CALLBACKS
    23272324    if (RT_SUCCESS(rc))
    23282325    {
     
    23342331        if (RT_SUCCESS(rc))
    23352332        {
    2336             pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */
    2337             if (pThis->uTicks < 100)
    2338                 pThis->uTicks = 100;
    2339             LogFunc(("Timer ticks=%RU64\n", pThis->uTicks));
     2333            pThis->uTimerTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */
     2334            pThis->uTimerTS    = PDMDevHlpTMTimeVirtGet(pDevIns);
     2335            if (pThis->uTimerTicks < 100)
     2336                pThis->uTimerTicks = 100;
     2337            LogFunc(("Timer ticks=%RU64\n", pThis->uTimerTicks));
    23402338
    23412339            /* Fire off timer. */
    2342             TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
    2343         }
    2344     }
     2340            TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
     2341        }
     2342    }
     2343# else
     2344    if (RT_SUCCESS(rc))
     2345    {
     2346        PAC97DRIVER pDrv;
     2347        RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     2348        {
     2349            /* Only register primary driver.
     2350             * The device emulation does the output multiplexing then. */
     2351            if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
     2352                continue;
     2353
     2354            PDMAUDIOCALLBACK AudioCallbacks[2];
     2355
     2356            AC97CALLBACKCTX Ctx = { pThis, pDrv };
     2357
     2358            AudioCallbacks[0].enmType     = PDMAUDIOCALLBACKTYPE_INPUT;
     2359            AudioCallbacks[0].pfnCallback = ac97CallbackInput;
     2360            AudioCallbacks[0].pvCtx       = &Ctx;
     2361            AudioCallbacks[0].cbCtx       = sizeof(AC97CALLBACKCTX);
     2362
     2363            AudioCallbacks[1].enmType     = PDMAUDIOCALLBACKTYPE_OUTPUT;
     2364            AudioCallbacks[1].pfnCallback = ac97CallbackOutput;
     2365            AudioCallbacks[1].pvCtx       = &Ctx;
     2366            AudioCallbacks[1].cbCtx       = sizeof(AC97CALLBACKCTX);
     2367
     2368            rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
     2369            if (RT_FAILURE(rc))
     2370                break;
     2371        }
     2372    }
     2373# endif
    23452374
    23462375# ifdef VBOX_WITH_STATISTICS
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r58954 r58983  
    4242#include "VBoxDD.h"
    4343
     44#include "AudioMixBuffer.h"
    4445#include "AudioMixer.h"
    4546#include "DevIchHdaCodec.h"
     
    723724    /** Flag whether the RC part is enabled. */
    724725    bool                               fRCEnabled;
     726#ifndef VBOX_WITH_AUDIO_CALLBACKS
    725727    /** The emulation timer for handling the attached
    726728     *  LUN drivers. */
    727729    PTMTIMERR3                         pTimer;
    728730    /** Timer ticks for handling the LUN drivers. */
    729     uint64_t                           uTicks;
     731    uint64_t                           uTimerTicks;
     732    /** Timestamp (delta) since last timer call. */
     733    uint64_t                           uTimerTS;
     734#endif
    730735#ifdef VBOX_WITH_STATISTICS
    731736# ifndef VBOX_WITH_AUDIO_CALLBACKS
     
    17161721    *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns))
    17171722                                                   - pThis->u64BaseTS, 24, 1000);
     1723    LogFlowFunc(("%RU32\n", *pu32Value));
    17181724    return VINF_SUCCESS;
    17191725}
     
    20882094#ifdef IN_RING3
    20892095# ifdef VBOX_WITH_HDA_CODEC_EMU
    2090     /* No reason to reopen voice with same settings. */
     2096    /* No reason to re-open stream with same settings. */
    20912097    if (u32Value == HDA_REG_IND(pThis, iReg))
    20922098        return VINF_SUCCESS;
     
    21112117#  endif
    21122118        default:
    2113             LogFunc(("Warning: Attempt to change format on register %d\n", iReg));
     2119            LogFunc(("Warning: Attempt to change format on register %RU32\n", iReg));
    21142120            break;
    21152121    }
     
    23952401            }
    23962402        }
    2397 
    2398         Log(("HDADEBUG: cb2Copy=%RU32, CVI(len:%RU32, pos:%RU32), CBLL=%RU32, FIFOS=%RU32, Avail=%RU32\n",
    2399              cbFree, pBDLE->u32BufSize, pBDLE->State.u32BufOff, pStrmSt->u32CBL - HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8Strm), pStrmSt->u16FIFOS, 0));
    24002403    }
    24012404
     
    28152818    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    28162819    {
    2817         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
     2820        if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
     2821                         pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
    28182822        {
    28192823            rc = VERR_NO_MEMORY;
     
    28742878{
    28752879    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
    2876     AssertPtr(pThis);
     2880    AssertPtrReturnVoid(pThis);
    28772881
    28782882    STAM_PROFILE_START(&pThis->StatTimer, a);
     
    28862890
    28872891    uint32_t cbIn, cbOut, cSamplesLive;
     2892
     2893    uint64_t uTicksNow     = PDMDevHlpTMTimeVirtGet(pDevIns);
     2894    uint64_t uTicksElapsed = uTicksNow  - pThis->uTimerTS;
     2895    uint64_t uTicksPerSec  = PDMDevHlpTMTimeVirtGetFreq(pDevIns);
     2896
     2897    pThis->uTimerTS = uTicksNow;
     2898
    28882899    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    28892900    {
     2901        cbIn = cbOut = 0;
    28902902        rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    2891                                               &cbIn, &cbOut, &cSamplesLive);
     2903                                              &cbIn, &cbOut, NULL /* cSamplesLive */);
    28922904        if (RT_SUCCESS(rc))
    2893         {
    2894 #ifdef DEBUG_TIMER
    2895             LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    2896 #endif
    2897             if (cSamplesLive)
    2898             {
    2899                 uint32_t cSamplesPlayed;
    2900                 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed);
    2901                 if (RT_SUCCESS(rc2))
    2902                     LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n",
    2903                                  pDrv->uLUN, cSamplesLive, cSamplesPlayed));
    2904 
    2905                 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    2906                                                       &cbIn, &cbOut, &cSamplesLive);
    2907 #ifdef DEBUG_TIMER
    2908                 if (RT_SUCCESS(rc))
    2909                     LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    2910 #endif
    2911             }
    2912 
    2913             cbInMax  = RT_MAX(cbInMax, cbIn);
    2914             cbOutMin = RT_MIN(cbOutMin, cbOut);
    2915         }
     2905            rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
     2906
     2907        uint32_t cSamplesMin  = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2);
     2908        uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
     2909
     2910        LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n",
     2911                     pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin));
     2912
     2913        if (   RT_FAILURE(rc)
     2914            && cbSamplesMin > cbOut)
     2915        {
     2916            LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin));
     2917            cbOut = cbSamplesMin;
     2918        }
     2919
     2920        cbOutMin = RT_MIN(cbOutMin, cbOut);
     2921        cbInMax  = RT_MAX(cbInMax, cbIn);
    29162922    }
    29172923
     
    29382944        hdaTransfer(pThis, PI_INDEX, cbInMax /* cbMax */, NULL /* pcbProcessed */); /** @todo Add rc! */
    29392945
    2940     TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
     2946    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
    29412947
    29422948    STAM_PROFILE_STOP(&pThis->StatTimer, a);
     
    44244430            /** @todo Investigate why sounds is getting corrupted if the "ticks" value is too
    44254431             *        low, e.g. "PDMDevHlpTMTimeVirtGetFreq / 200". */
    4426             pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */
    4427             if (pThis->uTicks < 100)
    4428                 pThis->uTicks = 100;
    4429             LogFunc(("Timer ticks=%RU64\n", pThis->uTicks));
     4432            pThis->uTimerTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */
     4433            pThis->uTimerTS    = PDMDevHlpTMTimeVirtGet(pDevIns);
     4434            if (pThis->uTimerTicks < 100)
     4435                pThis->uTimerTicks = 100;
     4436            LogFunc(("Timer ticks=%RU64\n", pThis->uTimerTicks));
    44304437
    44314438            /* Fire off timer. */
    4432             TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
     4439            TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
    44334440        }
    44344441    }
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r58600 r58983  
    5555#include "VBoxDD.h"
    5656
     57#include "AudioMixBuffer.h"
    5758#include "AudioMixer.h"
    5859
     
    178179    /** Audio sink for PCM output. */
    179180    R3PTRTYPE(PAUDMIXSINK)         pSinkOutput;
     181#ifndef VBOX_WITH_AUDIO_CALLBACKS
    180182    /** The emulation timer for handling I/O of the attached LUN drivers. */
    181183    PTMTIMERR3                     pTimerIO;
    182184    /** Timer ticks for handling the LUN drivers. */
    183     uint64_t                       uTicksIO;
    184 
     185    uint64_t                       uTimerTicksIO;
     186    /** Timestamp (delta) since last timer call. */
     187    uint64_t                       uTimerTSIO;
     188#endif
    185189    PTMTIMER  pTimerIRQ;
    186190    PPDMIBASE pDrvBase;
     
    15201524                          uint32_t dma_len, int len)
    15211525{
    1522     uint8_t     tmpbuf[_4K]; /** @todo Have a buffer on the heap. */
    1523     uint32_t    cbToWrite = len;
    1524     uint32_t    cbWrittenTotal = 0;
     1526    uint8_t  tmpbuf[_4K]; /** @todo Have a buffer on the heap. */
     1527    uint32_t cbToWrite = len;
     1528    uint32_t cbWrittenTotal = 0;
    15251529
    15261530    while (cbToWrite)
    15271531    {
    1528         uint32_t cbWrittenMin = UINT32_MAX;
    15291532        uint32_t cbToRead;
    15301533        uint32_t cbRead;
     
    15461549            int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    15471550                                                 tmpbuf, cbToRead, &cbWritten);
    1548             AssertRCBreak(rc);
    1549             if (RT_FAILURE(rc2))
    1550                 continue;
    1551 
    1552             cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten);
    1553             LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin));
     1551            LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, rc2, cbWritten));
    15541552        }
    15551553
    1556         Assert(cbToWrite >= cbWrittenMin);
    1557         cbToWrite      -= cbWrittenMin;
    1558         dma_pos         = (dma_pos + cbWrittenMin) % dma_len;
    1559         cbWrittenTotal += cbWrittenMin;
    1560 
    1561         if (!cbRead || !cbWrittenMin)
     1554        Assert(cbToWrite >= cbToRead);
     1555        cbToWrite      -= cbToRead;
     1556        dma_pos         = (dma_pos + cbToRead) % dma_len;
     1557        cbWrittenTotal += cbToRead;
     1558
     1559        if (!cbRead)
    15621560            break;
    15631561    }
     
    16641662    PSB16DRIVER pDrv;
    16651663
    1666     uint32_t cbIn, cbOut, cSamplesLive;
     1664    uint32_t cbIn, cbOut;
     1665
     1666    uint64_t uTicksNow     = PDMDevHlpTMTimeVirtGet(pDevIns);
     1667    uint64_t uTicksElapsed = uTicksNow  - pThis->uTimerTSIO;
     1668    uint64_t uTicksPerSec  = PDMDevHlpTMTimeVirtGetFreq(pDevIns);
     1669
     1670    pThis->uTimerTSIO = uTicksNow;
     1671
    16671672    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    16681673    {
     1674        cbIn = cbOut = 0;
    16691675        rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    1670                                               &cbIn, &cbOut, &cSamplesLive);
     1676                                              &cbIn, &cbOut, NULL /* cSamplesLive */);
    16711677        if (RT_SUCCESS(rc))
    1672         {
    1673             LogFlowFunc(("\tLUN#%RU8: [1] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    1674 
    1675             if (cSamplesLive)
    1676             {
    1677                 uint32_t cSamplesPlayed;
    1678                 int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed);
    1679                 if (RT_SUCCESS(rc2))
    1680                     LogFlowFunc(("LUN#%RU8: cSamplesLive=%RU32, cSamplesPlayed=%RU32\n",
    1681                                  pDrv->uLUN, cSamplesLive, cSamplesPlayed));
    1682 
    1683                 if (cSamplesPlayed)
    1684                 {
    1685                     rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    1686                                                           &cbIn, &cbOut, &cSamplesLive);
    1687                     if (RT_SUCCESS(rc))
    1688                         LogFlowFunc(("\tLUN#%RU8: [2] cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut));
    1689                 }
    1690             }
    1691 
    1692             cbInMax  = RT_MAX(cbInMax, cbIn);
    1693             cbOutMin = RT_MIN(cbOutMin, cbOut);
     1678            rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
     1679
     1680        uint32_t cSamplesMin  = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2);
     1681        uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
     1682
     1683        LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n",
     1684                     pDrv->uLUN, rc, cbOut, cSamplesMin, cbSamplesMin));
     1685
     1686        if (   RT_FAILURE(rc)
     1687            && cbSamplesMin > cbOut)
     1688        {
     1689            LogFlowFunc(("LUN#%RU8: Adj: %RU32 -> %RU32\n", pDrv->uLUN, cbOut, cbSamplesMin));
     1690            cbOut = cbSamplesMin;
    16941691        }
    1695     }
    1696 
     1692
     1693        cbOutMin = RT_MIN(cbOutMin, cbOut);
     1694        cbInMax  = RT_MAX(cbInMax, cbIn);
     1695    }
     1696
     1697#ifdef DEBUG_TIMER
    16971698    LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin));
     1699#endif
    16981700
    16991701    if (cbOutMin == UINT32_MAX)
     
    17161718    /** @todo Implement recording. */
    17171719
    1718     TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTicksIO);
     1720    TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTimerTicksIO);
    17191721}
    17201722
     
    21682170    sb16ResetLegacy(pThis);
    21692171
    2170     PSB16DRIVER pDrv;
    2171     uLUN = 0;
    2172     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    2173     {
    2174         PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    2175         AssertPtr(pCon);
    2176 
    2177         bool fIsOK = pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut);
    2178         if (fIsOK)
    2179         {
    2180             rc = pCon->pfnEnableOut(pCon, pDrv->Out.pStrmOut, true /* fEnable */);
    2181             fIsOK = RT_SUCCESS(rc);
    2182         }
    2183 
    2184         if (!fIsOK)
    2185         {
    2186             /*
    2187              * Only primary drivers are critical for the VM to run. Everything else
    2188              * might not worth showing an own error message box in the GUI.
    2189              */
    2190             if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
    2191                 continue;
    2192 
    2193             LogRel(("SB16: Warning: Unable to enable/use output for LUN#%RU8\n", uLUN));
    2194 
    2195             pCon->pfnDestroyOut(pCon, pDrv->Out.pStrmOut);
    2196             pDrv->Out.pStrmOut = NULL;
    2197 
    2198             pThis->pDrv->pfnInitNull(pThis->pDrv);
    2199 
    2200             PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    2201                 N_("No audio devices could be opened. Selecting the NULL audio backend "
    2202                    "with the consequence that no sound is audible"));
    2203         }
    2204 
    2205         uLUN++;
    2206     }
    2207 
     2172#ifndef VBOX_WITH_AUDIO_CALLBACKS
    22082173    if (RT_SUCCESS(rc))
    22092174    {
     
    22142179        else
    22152180        {
    2216             pThis->uTicksIO = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */
    2217             if (pThis->uTicksIO < 100)
    2218                 pThis->uTicksIO = 100;
    2219             LogFunc(("I/O timer ticks=%RU64\n", pThis->uTicksIO));
     2181            pThis->uTimerTicksIO = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */
     2182            pThis->uTimerTSIO    = PDMDevHlpTMTimeVirtGet(pDevIns);
     2183            if (pThis->uTimerTicksIO < 100)
     2184                pThis->uTimerTicksIO = 100;
     2185            LogFunc(("I/O timer ticks=%RU64\n", pThis->uTimerTicksIO));
    22202186
    22212187            /* Fire off timer. */
    2222             TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTicksIO);
     2188            TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->uTimerTicksIO);
    22232189        }
    22242190    }
     2191#else
     2192    if (RT_SUCCESS(rc))
     2193    {
     2194        PSB16DRIVER pDrv;
     2195        RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     2196        {
     2197            /* Only register primary driver.
     2198             * The device emulation does the output multiplexing then. */
     2199            if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
     2200                continue;
     2201
     2202            PDMAUDIOCALLBACK AudioCallbacks[2];
     2203
     2204            SB16CALLBACKCTX Ctx = { pThis, pDrv };
     2205
     2206            AudioCallbacks[0].enmType     = PDMAUDIOCALLBACKTYPE_INPUT;
     2207            AudioCallbacks[0].pfnCallback = sb16CallbackInput;
     2208            AudioCallbacks[0].pvCtx       = &Ctx;
     2209            AudioCallbacks[0].cbCtx       = sizeof(SB16CALLBACKCTX);
     2210
     2211            AudioCallbacks[1].enmType     = PDMAUDIOCALLBACKTYPE_OUTPUT;
     2212            AudioCallbacks[1].pfnCallback = sb16CallbackOutput;
     2213            AudioCallbacks[1].pvCtx       = &Ctx;
     2214            AudioCallbacks[1].cbCtx       = sizeof(SB16CALLBACKCTX);
     2215
     2216            rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
     2217            if (RT_FAILURE(rc))
     2218                break;
     2219        }
     2220    }
     2221#endif
    22252222
    22262223    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r58744 r58983  
    10531053              pHstStrmOut->MixBuf.pszName));
    10541054
     1055    if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf))
     1056    {
     1057        if (pcbWritten)
     1058            *pcbWritten = 0;
     1059        return VINF_SUCCESS;
     1060    }
     1061
    10551062    /*
    10561063     * First, write data from the device emulation into our
     
    17521759        AssertPtr(pHstStrmOut);
    17531760
    1754         if (pGstStrmOut->State.fActive != fEnable) /* Only process real state changes. */
    1755         {
    1756             if (fEnable)
     1761        if (fEnable)
     1762        {
     1763            /* Is a pending disable outstanding? Then disable first. */
     1764            if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
    17571765            {
    1758                 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    1759                 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    1760                     rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
     1766                rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
     1767                if (RT_SUCCESS(rc))
     1768                    pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    17611769            }
    1762             else /* Disable */
     1770
     1771            if (RT_SUCCESS(rc))
     1772                rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
     1773        }
     1774        else /* Disable */
     1775        {
     1776            if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    17631777            {
    1764                 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     1778                uint32_t cGstStrmsActive = 0;
     1779
     1780                /*
     1781                 * Check if there are any active guest streams assigned
     1782                 * to this host stream which still are being marked as active.
     1783                 *
     1784                 * In that case we have to defer closing the host stream and
     1785                 * wait until all guest streams have been finished.
     1786                 */
     1787                PPDMAUDIOGSTSTRMOUT pIter;
     1788                RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node)
    17651789                {
    1766                     uint32_t cGstStrmsActive = 0;
    1767 
    1768                     /*
    1769                      * Check if there are any active guest streams assigned
    1770                      * to this host stream which still are being marked as active.
    1771                      *
    1772                      * In that case we have to defer closing the host stream and
    1773                      * wait until all guest streams have been finished.
    1774                      */
    1775                     PPDMAUDIOGSTSTRMOUT pIter;
    1776                     RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node)
     1790                    if (pIter->State.fActive)
    17771791                    {
    1778                         if (pIter->State.fActive)
    1779                         {
    1780                             cGstStrmsActive++;
    1781                             break; /* At least one assigned & active guest stream is enough. */
    1782                         }
     1792                        cGstStrmsActive++;
     1793                        break; /* At least one assigned & active guest stream is enough. */
    17831794                    }
    1784 
    1785                     /* Do we need to defer closing the host stream? */
    1786                     if (cGstStrmsActive >= 1)
    1787                         pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    1788 
    1789                     /* Can we close the host stream now instead of deferring it? */
    1790                     if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))
    1791                         rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    17921795                }
     1796
     1797                /* Do we need to defer closing the host stream? */
     1798                if (cGstStrmsActive >= 1)
     1799                    pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     1800
     1801                /* Can we close the host stream now instead of deferring it? */
     1802                if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))
     1803                    rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    17931804            }
    1794 
    1795             if (RT_SUCCESS(rc))
    1796                 pGstStrmOut->State.fActive = fEnable;
    1797 
    1798             LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
    1799                          pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));
    1800         }
     1805        }
     1806
     1807        if (RT_SUCCESS(rc))
     1808            pGstStrmOut->State.fActive = fEnable;
     1809
     1810        LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
     1811                     pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));
    18011812    }
    18021813
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r58744 r58983  
    123123    /** DirectSound configuration options. */
    124124    DSOUNDHOSTCFG       cfg;
     125    /** Whether the input currently is in an enabled (working)
     126     *  state or not. */
     127    bool                fEnabledIn;
     128    /** Whether the output currently is in an enabled (working)
     129     *  state or not. */
     130    bool                fEnabledOut;
    125131#ifdef VBOX_WITH_AUDIO_CALLBACKS
    126132    /** Pointer to the audio connector interface of the driver/device above us. */
     
    137143     *  Must not exceed VBOX_DSOUND_MAX_EVENTS. */
    138144    uint8_t             cEvents;
    139     PDSOUNDSTREAMIN     pStrmIn;
    140     PDSOUNDSTREAMOUT    pStrmOut;
     145    /** Pointer to the input stream. */
     146    PDSOUNDSTREAMIN     pDSStrmIn;
     147    /** Pointer to the output stream. */
     148    PDSOUNDSTREAMOUT    pDSStrmOut;
    141149#endif
    142150} DRVHOSTDSOUND, *PDRVHOSTDSOUND;
     
    162170    ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTDSOUND, IHostAudio)) )
    163171
     172static HRESULT directSoundPlayRestore(LPDIRECTSOUNDBUFFER8 pDSB);
     173
    164174static void dsoundDevRemove(PDSOUNDDEV pDev);
    165175#ifdef VBOX_WITH_AUDIO_CALLBACKS
     
    174184static int dsoundWaveFmtFromCfg(PPDMAUDIOSTREAMCFG pCfg, PWAVEFORMATEX pFmt)
    175185{
     186    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     187    AssertPtrReturn(pFmt, VERR_INVALID_POINTER);
     188
    176189    RT_BZERO(pFmt, sizeof(WAVEFORMATEX));
     190
    177191    pFmt->wFormatTag      = WAVE_FORMAT_PCM;
    178192    pFmt->nChannels       = pCfg->cChannels;
     
    211225}
    212226
     227static int dsoundGetStatusOut(PDSOUNDSTREAMOUT pDSoundStrmOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos)
     228{
     229    AssertPtrReturn(pDSoundStrmOut, VERR_INVALID_POINTER);
     230
     231    LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB;
     232    if (!pDSB)
     233        return VERR_INVALID_POINTER;
     234
     235    DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStrmOut->strmOut.MixBuf, pDSoundStrmOut->csPlaybackBufferSize);
     236
     237    /* Get the current play position which is used for calculating the free space in the buffer. */
     238    DWORD cbPlayPos;
     239    HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL);
     240    if (hr == DSERR_BUFFERLOST)
     241    {
     242        hr = directSoundPlayRestore(pDSB);
     243        if (SUCCEEDED(hr))
     244            hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL);
     245    }
     246
     247    if (FAILED(hr))
     248    {
     249        if (hr != DSERR_BUFFERLOST) /* Avoid log flooding if the error is still there. */
     250            DSLOGREL(("DSound: Playback: GetCurrentPosition failed with %Rhrc\n", hr));
     251        LogFlowFunc(("Failed with %Rhrc\n", hr));
     252        return VERR_NOT_AVAILABLE;
     253    }
     254
     255    if (pdwBuffer)
     256        *pdwBuffer = cbBuffer;
     257
     258    if (pdwFree)
     259        *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer);
     260
     261    if (pdwPlayPos)
     262        *pdwPlayPos = cbPlayPos;
     263
     264    return VINF_SUCCESS;
     265}
     266
    213267static char *dsoundGUIDToUtf8StrA(LPCGUID lpGUID)
    214268{
     
    429483                pThis->cEvents--;
    430484
    431             pThis->pStrmOut = NULL;
     485            pThis->pDSStrmOut = NULL;
    432486        }
    433487
     
    590644            break;
    591645
    592         pThis->pStrmOut = pDSoundStrmOut;
     646        pThis->pDSStrmOut = pDSoundStrmOut;
    593647
    594648        Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS);
     
    9951049            else
    9961050            {
     1051                DWORD fFlags = 0;
     1052#ifndef VBOX_WITH_AUDIO_CALLBACKS
     1053                fFlags |= DSCBSTART_LOOPING;
     1054#endif
    9971055                DSLOG(("DSound: Capture start\n"));
    998                 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStrmIn->pDSCB, DSCBSTART_LOOPING);
     1056                hr = IDirectSoundCaptureBuffer8_Start(pDSoundStrmIn->pDSCB, fFlags);
    9991057                if (FAILED(hr))
    10001058                    DSLOGREL(("DSound: Capture started %Rhrc\n", hr));
     
    11811239                rc = VERR_NOT_SUPPORTED;
    11821240
     1241            pThis->fEnabledOut = RT_SUCCESS(rc);
    11831242            break;
    11841243        }
     
    12181277    do /* to use 'break' */
    12191278    {
    1220         LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB;
    1221         if (!pDSB)
    1222             break;
    1223 
    1224         int cShift = pHstStrmOut->Props.cShift;
    1225         DWORD cbBuffer = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, pDSoundStrmOut->csPlaybackBufferSize);
    1226 
    1227         /* Get the current play position which is used for calculating the free space in the buffer. */
    1228         DWORD cbPlayPos;
    1229         HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL);
    1230         if (hr == DSERR_BUFFERLOST)
    1231         {
    1232             hr = directSoundPlayRestore(pDSB);
    1233             if (SUCCEEDED(hr))
    1234                 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL);
    1235         }
    1236 
    1237         if (FAILED(hr))
    1238         {
    1239             if (hr != DSERR_BUFFERLOST) /* Avoid log flooding if the error is still there. */
    1240                 DSLOGREL(("DSound: Playback GetCurrentPosition %Rhrc\n", hr));
    1241             break;
    1242         }
    1243 
    1244         DWORD cbFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer);
     1279        DWORD cbBuffer, cbFree, cbPlayPos;
     1280        rc = dsoundGetStatusOut(pDSoundStrmOut, &cbBuffer, &cbFree, &cbPlayPos);
     1281        if (RT_FAILURE(rc))
     1282        {
     1283            /* Set the output status to disabled, as we are not able to retrieve the current
     1284             * status (anymore). */
     1285            pThis->fEnabledOut = false;
     1286            break;
     1287        }
     1288
    12451289        /*
    12461290         * Check for full buffer, do not allow the cbPlayWritePos to catch cbPlayPos during playback,
     
    12661310        }
    12671311
     1312        LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB;
     1313        AssertPtr(pDSB);
     1314
    12681315        LPVOID pv1, pv2;
    12691316        DWORD cb1, cb2;
    1270         hr = directSoundPlayLock(pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,
    1271                                  &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);
     1317        HRESULT hr = directSoundPlayLock(pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,
     1318                                         &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);
    12721319        if (FAILED(hr))
    1273             break;
     1320        {
     1321            rc = VERR_ACCESS_DENIED;
     1322            break;
     1323        }
    12741324
    12751325        DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cb1);
     
    13151365        if (pDSoundStrmOut->fRestartPlayback)
    13161366        {
    1317             /* The playback has been just started.
     1367            /*
     1368             * The playback has been just started.
    13181369             * Some samples of the new sound have been copied to the buffer
    13191370             * and it can start playing.
    13201371             */
    13211372            pDSoundStrmOut->fRestartPlayback = false;
    1322             hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, DSBPLAY_LOOPING);
     1373
     1374            DWORD fFlags = 0;
     1375#ifndef VBOX_WITH_AUDIO_CALLBACKS
     1376            fFlags |= DSCBSTART_LOOPING;
     1377#endif
     1378            hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, fFlags);
    13231379            if (FAILED(hr))
    13241380            {
    1325                 DSLOGREL(("DSound: Playback start %Rhrc\n", hr));
     1381                DSLOGREL(("DSound: Playback: Unable to start playing, hr=%Rhrc\n", hr));
    13261382                rc = VERR_NOT_SUPPORTED;
     1383                break;
    13271384            }
    13281385        }
     1386
    13291387    } while (0);
    13301388
    1331     if (pcSamplesPlayed)
    1332         *pcSamplesPlayed = cReadTotal;
     1389    if (RT_SUCCESS(rc))
     1390    {
     1391        if (pcSamplesPlayed)
     1392            *pcSamplesPlayed = cReadTotal;
     1393    }
    13331394
    13341395    return rc;
     
    14211482            if (FAILED(hr))
    14221483                rc = VERR_NOT_SUPPORTED;
    1423         } break;
     1484
     1485            pThis->fEnabledIn = RT_SUCCESS(rc);
     1486            break;
     1487        }
    14241488
    14251489        case PDMAUDIOSTREAMCMD_DISABLE:
    14261490        {
    14271491            directSoundCaptureStop(pDSoundStrmIn);
    1428         } break;
     1492            break;
     1493        }
    14291494
    14301495        default:
     
    14321497            AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd));
    14331498            rc = VERR_INVALID_PARAMETER;
    1434         } break;
     1499            break;
     1500        }
    14351501    }
    14361502
     
    14471513    int rc = VINF_SUCCESS;
    14481514
    1449     if (pDSCB == NULL)
    1450     {
    1451         if (pcSamplesCaptured) /** @todo single point of return */
    1452             *pcSamplesCaptured = 0;
    1453         return VINF_SUCCESS;
    1454     }
    1455 
    1456     /* Get DirectSound capture position in bytes. */
    1457     DWORD cbReadPos;
    1458     HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &cbReadPos);
    1459     if (FAILED(hr))
    1460     {
    1461         if (hr != pDSoundStrmIn->hrLastCaptureIn)
    1462         {
    1463             DSLOGREL(("DSound: Capture GetCurrentPosition %Rhrc\n", hr));
    1464             pDSoundStrmIn->hrLastCaptureIn = hr;
    1465         }
    1466 
    1467         if (pcSamplesCaptured)
    1468             *pcSamplesCaptured = 0;
    1469         return VINF_SUCCESS;
    1470     }
    1471     pDSoundStrmIn->hrLastCaptureIn = hr;
    1472 
    1473     if (cbReadPos & pHstStrmIn->Props.uAlign)
    1474         DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pHstStrmIn->Props.uAlign));
    1475 
    1476     /* Capture position in samples. */
    1477     DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift;
    1478 
    1479     /* Number of samples available in the DirectSound capture buffer. */
    1480     DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);
    1481     if (csCaptured == 0)
    1482     {
    1483         if (pcSamplesCaptured)
    1484             *pcSamplesCaptured = 0;
    1485         return VINF_SUCCESS;
    1486     }
    1487 
    1488     /* Using as an intermediate not circular buffer. */
    1489     AudioMixBufReset(&pHstStrmIn->MixBuf);
    1490 
    1491     /* Get number of free samples in the mix buffer and check that is has free space */
    1492     uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf);
    1493     if (csMixFree == 0)
    1494     {
    1495         DSLOGF(("DSound: Capture buffer full\n"));
    1496         if (pcSamplesCaptured)
    1497             *pcSamplesCaptured = 0;
    1498         return VINF_SUCCESS;
    1499     }
    1500 
    1501     DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n",
    1502             csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured));
    1503 
    1504     /* No need to fetch more samples than mix buffer can receive. */
    1505     csCaptured = RT_MIN(csCaptured, csMixFree);
    1506 
    1507     /* Lock relevant range in the DirectSound capture buffer. */
    1508     LPVOID pv1, pv2;
    1509     DWORD cb1, cb2;
    1510     hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props,
    1511                                 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */
    1512                                 AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured),                      /* dwBytes */
    1513                                 &pv1, &pv2, &cb1, &cb2,
    1514                                 0 /* dwFlags */);
    1515     if (FAILED(hr))
    1516     {
    1517         if (pcSamplesCaptured)
    1518             *pcSamplesCaptured = 0;
    1519         return VINF_SUCCESS;
    1520     }
    1521 
    1522     DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1);
    1523     DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2);
    1524 
    1525     uint32_t csWrittenTotal = 0;
    1526     uint32_t csWritten;
    1527     if (pv1 && len1)
    1528     {
    1529         rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */,
    1530                                 pv1, cb1, &csWritten);
     1515    uint32_t cCaptured = 0;
     1516
     1517    do
     1518    {
     1519        if (pDSCB == NULL)
     1520        {
     1521            pThis->fEnabledIn = false;
     1522
     1523            rc = VERR_NOT_AVAILABLE;
     1524            break;
     1525        }
     1526
     1527        /* Get DirectSound capture position in bytes. */
     1528        DWORD cbReadPos;
     1529        HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &cbReadPos);
     1530        if (FAILED(hr))
     1531        {
     1532            if (hr != pDSoundStrmIn->hrLastCaptureIn)
     1533            {
     1534                DSLOGREL(("DSound: Capture GetCurrentPosition %Rhrc\n", hr));
     1535                pDSoundStrmIn->hrLastCaptureIn = hr;
     1536            }
     1537
     1538            rc = VERR_NOT_AVAILABLE;
     1539            break;
     1540        }
     1541
     1542        pDSoundStrmIn->hrLastCaptureIn = hr;
     1543
     1544        if (cbReadPos & pHstStrmIn->Props.uAlign)
     1545            DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pHstStrmIn->Props.uAlign));
     1546
     1547        /* Capture position in samples. */
     1548        DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift;
     1549
     1550        /* Number of samples available in the DirectSound capture buffer. */
     1551        DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);
     1552        if (csCaptured == 0)
     1553            break;
     1554
     1555        /* Using as an intermediate not circular buffer. */
     1556        AudioMixBufReset(&pHstStrmIn->MixBuf);
     1557
     1558        /* Get number of free samples in the mix buffer and check that is has free space */
     1559        uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf);
     1560        if (csMixFree == 0)
     1561        {
     1562            DSLOGF(("DSound: Capture buffer full\n"));
     1563            break;
     1564        }
     1565
     1566        DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n",
     1567                csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured));
     1568
     1569        /* No need to fetch more samples than mix buffer can receive. */
     1570        csCaptured = RT_MIN(csCaptured, csMixFree);
     1571
     1572        /* Lock relevant range in the DirectSound capture buffer. */
     1573        LPVOID pv1, pv2;
     1574        DWORD cb1, cb2;
     1575        hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props,
     1576                                    AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */
     1577                                    AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured),                      /* dwBytes */
     1578                                    &pv1, &pv2, &cb1, &cb2,
     1579                                    0 /* dwFlags */);
     1580        if (FAILED(hr))
     1581        {
     1582            rc = VERR_ACCESS_DENIED;
     1583            break;
     1584        }
     1585
     1586        DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1);
     1587        DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2);
     1588
     1589        uint32_t csWrittenTotal = 0;
     1590        uint32_t csWritten;
     1591        if (pv1 && len1)
     1592        {
     1593            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */,
     1594                                    pv1, cb1, &csWritten);
     1595            if (RT_SUCCESS(rc))
     1596                csWrittenTotal += csWritten;
     1597        }
     1598
     1599        if (   RT_SUCCESS(rc)
     1600            && csWrittenTotal == len1
     1601            && pv2 && len2)
     1602        {
     1603            rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal,
     1604                                    pv2, cb2, &csWritten);
     1605            if (RT_SUCCESS(rc))
     1606                csWrittenTotal += csWritten;
     1607        }
     1608
     1609        directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2);
     1610
     1611        if (csWrittenTotal) /* Captured something? */
     1612            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal, &cCaptured);
     1613
    15311614        if (RT_SUCCESS(rc))
    1532             csWrittenTotal += csWritten;
    1533     }
    1534 
    1535     if (   RT_SUCCESS(rc)
    1536         && csWrittenTotal == len1
    1537         && pv2 && len2)
    1538     {
    1539         rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal,
    1540                                 pv2, cb2, &csWritten);
    1541         if (RT_SUCCESS(rc))
    1542             csWrittenTotal += csWritten;
    1543     }
    1544 
    1545     directSoundCaptureUnlock(pDSCB, pv1, pv2, cb1, cb2);
    1546 
    1547     uint32_t csProcessed = 0;
    1548     if (csWrittenTotal != 0)
    1549     {
    1550         /* Captured something. */
    1551         rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal,
    1552                                     &csProcessed);
    1553     }
    1554 
    1555     if (RT_SUCCESS(rc))
    1556     {
    1557         pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + csProcessed) % pDSoundStrmIn->csCaptureBufferSize;
    1558         DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n",
    1559                 csCaptured, len1, len2, csProcessed, csWrittenTotal));
    1560     }
     1615        {
     1616            pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + cCaptured) % pDSoundStrmIn->csCaptureBufferSize;
     1617            DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n",
     1618                    csCaptured, len1, len2, cCaptured, csWrittenTotal));
     1619        }
     1620
     1621    } while (0);
    15611622
    15621623    if (pcSamplesCaptured)
    1563         *pcSamplesCaptured = csProcessed;
     1624        *pcSamplesCaptured = cCaptured;
    15641625
    15651626    return rc;
     
    15801641}
    15811642
     1643/** @todo Replace PDMAUDIODIR with a (registered? unique) channel ID to provide multi-channel input/output. */
    15821644static DECLCALLBACK(bool) drvHostDSoundIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    15831645{
    1584     NOREF(pInterface);
    1585     NOREF(enmDir);
    1586     return true; /* Always all enabled. */
     1646    AssertPtrReturn(pInterface, false);
     1647
     1648    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
     1649
     1650    if (enmDir == PDMAUDIODIR_IN)
     1651        return pThis->fEnabledIn;
     1652
     1653    return pThis->fEnabledOut;
    15871654}
    15881655
    15891656static DECLCALLBACK(int) drvHostDSoundGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    15901657{
     1658    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1659    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1660
    15911661    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1592 
    1593     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    15941662
    15951663    dsoundFreeDeviceLists(pThis);
     
    16831751    int rc = RTThreadUserSignal(hThreadSelf);
    16841752    AssertRC(rc);
    1685 
    1686     HRESULT hr;
    16871753
    16881754    do
     
    17271793                else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_OUTPUT])
    17281794                {
    1729                     DWORD cbPlayPos;
    1730                     hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pThis->pStrmOut->pDSB, NULL, &cbPlayPos);
    1731                     if (SUCCEEDED(hr))
     1795                    DWORD cbBuffer, cbFree, cbPlayPos;
     1796                    rc = dsoundGetStatusOut(pThis->pDSStrmOut, &cbBuffer, &cbFree, &cbPlayPos);
     1797                    if (   RT_SUCCESS(rc)
     1798                        && cbFree)
    17321799                    {
    1733                         LogFlowFunc(("Output: hr=%Rhrc, dwPlayPos=%ld\n", hr, cbPlayPos));
    1734 
    1735                         uint32_t cbFree = pThis->pStrmOut->csPlaybackBufferSize - pThis->pStrmOut->cbPlayWritePos;
    1736 
    1737                         AssertPtr(pThis->pUpIAudioConnector);
    1738                         pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector, PDMAUDIOCALLBACKTYPE_OUTPUT, &cbFree, sizeof(cbFree));
     1800                        PDMAUDIOCALLBACKDATAOUT Out;
     1801                        Out.cbInFree     = cbFree;
     1802                        Out.cbOutWritten = 0;
     1803
     1804                        while (!Out.cbOutWritten)
     1805                        {
     1806                            rc = pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector,
     1807                                                                        PDMAUDIOCALLBACKTYPE_OUTPUT, &Out, sizeof(Out));
     1808                            if (RT_FAILURE(rc))
     1809                                break;
     1810                            RTThreadSleep(100);
     1811                        }
     1812
     1813                        LogFlowFunc(("Output: cbBuffer=%ld, cbFree=%ld, cbPlayPos=%ld, cbWritten=%RU32, rc=%Rrc\n",
     1814                                     cbBuffer, cbFree, cbPlayPos, Out.cbOutWritten, rc));
    17391815                    }
    17401816                }
     
    19392015    RTListInit(&pThis->lstDevOutput);
    19402016
     2017    pThis->fEnabledIn  = false;
     2018    pThis->fEnabledOut = false;
    19412019#ifdef VBOX_WITH_AUDIO_CALLBACKS
    1942     pThis->fStopped  = false;
    1943     pThis->fShutdown = false;
     2020    pThis->fStopped    = false;
     2021    pThis->fShutdown   = false;
    19442022
    19452023    RT_ZERO(pThis->aEvents);
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r58378 r58983  
    164164
    165165    /* Consume as many samples as would be played at the current frequency since last call. */
    166     uint32_t csLive          = AudioMixBufAvail(&pHstStrmOut->MixBuf);;
     166    uint32_t csLive          = AudioMixBufAvail(&pHstStrmOut->MixBuf);
    167167    uint64_t u64TicksNow     = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
    168168    uint64_t u64TicksElapsed = u64TicksNow  - pNullStrmOut->u64TicksLast;
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