VirtualBox

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


Ignore:
Timestamp:
May 19, 2016 3:26:50 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107316
Message:

Audio: Update.

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

Legend:

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

    r60941 r61050  
    3737#include "AudioMixer.h"
    3838#include "AudioMixBuffer.h"
     39#include "DrvAudio.h"
    3940
    4041#include <VBox/vmm/pdm.h>
     
    101102}
    102103
     104int AudioMixerCreateStream(PAUDIOMIXER pMixer,
     105                           PPDMIAUDIOCONNECTOR pConn, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream)
     106{
     107    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
     108    AssertPtrReturn(pConn,  VERR_INVALID_POINTER);
     109    AssertPtrReturn(pCfg,   VERR_INVALID_POINTER);
     110    /** @todo Validate fFlags. */
     111    /* ppStream is optional. */
     112
     113    PAUDMIXSTREAM pMixStream = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));
     114    if (!pMixStream)
     115        return VERR_NO_MEMORY;
     116
     117    pMixStream->pszName = RTStrDup(pCfg->szName);
     118    if (!pMixStream->pszName)
     119    {
     120        RTMemFree(pMixStream);
     121        return VERR_NO_MEMORY;
     122    }
     123
     124    LogFlowFunc(("[%s]: fFlags=0x%x (enmDir=%ld, %s, %RU8 channels, %RU32Hz)\n",
     125                 pMixer->pszName, fFlags, pCfg->enmDir, DrvAudioAudFmtToStr(pCfg->enmFormat), pCfg->cChannels, pCfg->uHz));
     126
     127    int rc;
     128    if (pCfg->enmDir == PDMAUDIODIR_IN)
     129    {
     130        PPDMAUDIOGSTSTRMIN pGstStrm;
     131        rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm);
     132        if (RT_SUCCESS(rc))
     133        {
     134            pMixStream->InOut.pIn = pGstStrm;
     135
     136            /* Increase the stream's reference count to let others know
     137             * we're reyling on it to be around now. */
     138            pConn->pfnAddRefIn(pConn, pGstStrm);
     139        }
     140    }
     141    else if (pCfg->enmDir == PDMAUDIODIR_OUT)
     142    {
     143        PPDMAUDIOGSTSTRMOUT pGstStrm;
     144        rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm);
     145        if (RT_SUCCESS(rc))
     146        {
     147            pMixStream->InOut.pOut = pGstStrm;
     148
     149            /* Increase the stream's reference count to let others know
     150             * we're reyling on it to be around now. */
     151            pConn->pfnAddRefOut(pConn, pGstStrm);
     152        }
     153    }
     154    else
     155    {
     156        AssertMsgFailed(("Direction not implemented\n"));
     157        rc = VERR_NOT_IMPLEMENTED;
     158    }
     159
     160    if (RT_SUCCESS(rc))
     161    {
     162        pMixStream->fFlags = fFlags;
     163        pMixStream->enmDir = pCfg->enmDir;
     164        pMixStream->pConn  = pConn;
     165
     166        if (ppStream)
     167            *ppStream = pMixStream;
     168    }
     169    else if (pMixStream)
     170    {
     171        RTStrFree(pMixStream->pszName);
     172        pMixStream->pszName = NULL;
     173
     174        RTMemFree(pMixStream);
     175        pMixStream = NULL;
     176    }
     177
     178    return rc;
     179}
     180
    103181int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer)
    104182{
     
    191269    AssertPtrReturnVoid(pMixer);
    192270
    193     LogFlowFunc(("%s: Invalidating ...\n", pMixer->pszName));
     271    LogFlowFunc(("[%s]: Invalidating ...\n", pMixer->pszName));
    194272
    195273    /* Propagate new master volume to all connected sinks. */
     
    219297    pMixer->cSinks--;
    220298
    221     LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n",
     299    LogFlowFunc(("[%s]: pSink=%s, cSinks=%RU8\n",
    222300                 pMixer->pszName, pSink->pszName, pMixer->cSinks));
    223301}
     
    248326    pMixer->VolMaster = *pVol;
    249327
    250     LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
     328    LogFlowFunc(("[%s]: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
    251329                 pMixer->pszName, pVol->uLeft, pVol->uRight,
    252330                 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));
     
    256334}
    257335
    258 /*****************************************************************************
     336/*********************************************************************************************************************************
    259337 * Mixer Sink implementation.
    260  *****************************************************************************/
     338 ********************************************************************************************************************************/
    261339
    262340int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     
    273351    pSink->cStreams++;
    274352
    275     LogFlowFunc(("%s: cStreams=%RU8\n", pSink->pszName, pSink->cStreams));
     353    LogFlowFunc(("[%s]: cStreams=%RU8\n", pSink->pszName, pSink->cStreams));
    276354
    277355    return VINF_SUCCESS;
     
    312390    }
    313391
    314     LogFlowFunc(("%s: enmCmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));
     392    LogFlowFunc(("[%s]: enmCmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));
    315393    return rc;
    316394}
     
    384462}
    385463
     464bool AudioMixerSinkHasData(PAUDMIXSINK pSink)
     465{
     466    if (!pSink)
     467        return false;
     468
     469    /* If the dirty flag is set, there is unprocessed data in the sink. */
     470    return (pSink->fFlags & AUDMIXSINK_FLAG_DIRTY);
     471}
     472
    386473int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    387474{
     
    442529    RTMemFree(pvMixBuf);
    443530
    444     Log3Func(("%s: cbRead=%RU32, rc=%Rrc\n", pSink->pszName, cbRead, rc));
     531    Log3Func(("[%s]: cbRead=%RU32, rc=%Rrc\n", pSink->pszName, cbRead, rc));
    445532    return rc;
    446533}
     
    460547                          ? pStream->InOut.pIn->MixBuf.pszName : pStream->InOut.pOut->MixBuf.pszName;
    461548
    462     LogFlowFunc(("%s: (Stream = %s), cStreams=%RU8\n",
     549    LogFlowFunc(("[%s]: (Stream = %s), cStreams=%RU8\n",
    463550                 pSink->pszName, pszStream ? pszStream : "<Unnamed>", pSink->cStreams));
    464551#endif
     
    500587    AssertPtrReturn(pPCMProps, VERR_INVALID_POINTER);
    501588
     589    if (DrvAudioPCMPropsAreEqual(&pSink->PCMProps, pPCMProps)) /* Bail out early if PCM properties are equal. */
     590        return VINF_SUCCESS;
     591
     592    if (pSink->PCMProps.uHz)
     593        LogFlowFunc(("[%s]: Old format: %RU8 bit, %RU8 channels, %RU32Hz\n",
     594                     pSink->pszName, pSink->PCMProps.cBits, pSink->PCMProps.cChannels, pSink->PCMProps.uHz));
     595
    502596    memcpy(&pSink->PCMProps, pPCMProps, sizeof(PDMPCMPROPS));
    503597
     598    LogFlowFunc(("[%s]: New format %RU8 bit, %RU8 channels, %RU32Hz\n",
     599                 pSink->pszName, pSink->PCMProps.cBits, pSink->PCMProps.cChannels, pSink->PCMProps.uHz));
     600
     601#if 0
    504602    PAUDMIXSTREAM pStream;
    505603    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     
    507605        /** @todo Invalidate mix buffers! */
    508606    }
     607#endif
    509608
    510609    return VINF_SUCCESS;
     
    524623    AssertPtr(pSink->pParent);
    525624
    526     LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));
     625    LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));
    527626
    528627    pSink->Volume = *pVol;
     
    531630}
    532631
    533 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData)
     632void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTimerTicks, uint64_t cTicksElapsed, uint32_t *pcbData)
    534633{
    535634    AssertPtrReturnVoid(pSink);
    536635    /* pcbData is optional. */
    537636
    538     uint32_t cSamplesMin  = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2);
     637    /* Note: cTimerTicks / cTicksElapsed = Hz elapsed. */
     638
     639    LogFlowFunc(("[%s]: cTimerTicks=%RU64, cTicksElapsed=%RU64\n", pSink->pszName, cTimerTicks, cTicksElapsed));
     640
     641    //uint32_t cSamplesMin  = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / 2);
     642    uint32_t cSamplesMin  = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels;
    539643    uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift;
    540644
    541     LogFlowFunc(("%s: cbSamplesMin=%RU32\n", pSink->pszName, cbSamplesMin));
     645    Assert((cbSamplesMin % 2 == 0));
     646
     647    LogFlowFunc(("[%s]: cSamplesMin=%RU32 (%RU32 bytes, %RU32Hz)\n", pSink->pszName, cSamplesMin, cbSamplesMin, pSink->PCMProps.uHz));
    542648
    543649    audioMixerSinkUpdateInternal(pSink);
     
    551657    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    552658
     659    int rc = VINF_SUCCESS;
     660
    553661    PAUDMIXSTREAM pStream;
    554662    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    555663    {
    556         uint32_t cbIn, cbOut;
    557         uint32_t cSamplesLive;
    558         int rc2 = pStream->pConn->pfnQueryStatus(pStream->pConn,
    559                                                  &cbIn, &cbOut, &cSamplesLive);
    560 #ifdef DEBUG
    561         if (   cbIn
    562             || cbOut
    563             || cSamplesLive)
    564         {
    565             Log3Func(("%s: cbIn=%RU32, cbOut=%RU32, cSamplesLive=%RU32, rc2=%Rrc\n",
    566                       pSink->pszName, cbIn, cbOut, cSamplesLive, rc2));
    567         }
    568 #endif
    569664        if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
    570665        {
    571             rc2 = pStream->pConn->pfnPlayOut(pStream->pConn, NULL /* pcSamplesPlayed */);
    572             if (RT_FAILURE(rc2))
    573                 Log3Func(("rc2=%Rrc\n", rc2));
     666            uint32_t cSamplesLive;
     667            uint32_t cSamplesPlayed = 0;
     668            rc = pStream->pConn->pfnGetDataOut(pStream->pConn, NULL /* cbOut */, &cSamplesLive);
     669            if (   RT_SUCCESS(rc)
     670                && cSamplesLive)
     671            {
     672                rc = pStream->pConn->pfnPlayOut(pStream->pConn, &cSamplesPlayed);
     673            }
     674
     675            if (RT_SUCCESS(rc))
     676            {
     677                Assert(cSamplesLive >= cSamplesPlayed);
     678                if (cSamplesLive - cSamplesPlayed) /* Some live samples left? */
     679                    pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
     680                else
     681                    pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
     682            }
     683
     684            Log3Func(("[%s]: fFlags=0x%x, cSamplesLive=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cSamplesLive, rc));
    574685        }
    575686        else if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
    576687        {
    577             //int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */);
    578             //Log3Func(("rc2=%Rrc\n", rc2));
     688            uint32_t cbIn;
     689            rc = pStream->pConn->pfnGetDataIn(pStream->pConn, &cbIn);
     690            if (   RT_SUCCESS(rc)
     691                && cbIn)
     692            {
     693                /** @todo Implement this! */
     694                // int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */);
     695                // Log3Func(("rc2=%Rrc\n", rc2));
     696            }
     697
     698            if (RT_SUCCESS(rc))
     699            {
     700                if (cbIn) /* Some inpput data available? */
     701                    pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
     702                else
     703                    pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
     704            }
     705
     706            Log3Func(("[%s]: fFlags=0x%x, cbIn=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cbIn, rc));
    579707        }
    580708        else
     709        {
     710            rc = VERR_NOT_IMPLEMENTED;
    581711            AssertMsgFailed(("Direction not implemented\n"));
    582     }
    583 
    584     return VINF_SUCCESS;
     712        }
     713    }
     714
     715    return rc;
    585716}
    586717
     
    597728    LogFlowFunc(("Master fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
    598729                  pVolMaster->fMuted, pVolMaster->uLeft, pVolMaster->uRight));
    599     LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
     730    LogFlowFunc(("[%s]: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
    600731                  pSink->pszName, pSink->Volume.fMuted, pSink->Volume.uLeft, pSink->Volume.uRight));
    601732
     
    656787}
    657788
    658 /*****************************************************************************
     789/*********************************************************************************************************************************
    659790 * Mixer Stream implementation.
    660  *****************************************************************************/
     791 ********************************************************************************************************************************/
    661792
    662793int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl)
     
    702833}
    703834
    704 int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConn, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream)
    705 {
    706     AssertPtrReturn(pConn, VERR_INVALID_POINTER);
    707     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    708     /** @todo Validate fFlags. */
    709     /* ppStream is optional. */
    710 
    711     PAUDMIXSTREAM pMixStream = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));
    712     if (!pMixStream)
    713         return VERR_NO_MEMORY;
    714 
    715     pMixStream->pszName = RTStrDup(pCfg->szName);
    716     if (!pMixStream->pszName)
    717     {
    718         RTMemFree(pMixStream);
    719         return VERR_NO_MEMORY;
    720     }
    721 
    722     int rc;
    723     if (pCfg->enmDir == PDMAUDIODIR_IN)
    724     {
    725         PPDMAUDIOGSTSTRMIN pGstStrm;
    726         rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm);
    727         if (RT_SUCCESS(rc))
    728         {
    729             pMixStream->InOut.pIn = pGstStrm;
    730 
    731             /* Increase the stream's reference count to let others know
    732              * we're reyling on it to be around now. */
    733             pConn->pfnAddRefIn(pConn, pGstStrm);
    734         }
    735     }
    736     else if (pCfg->enmDir == PDMAUDIODIR_OUT)
    737     {
    738         PPDMAUDIOGSTSTRMOUT pGstStrm;
    739         rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm);
    740         if (RT_SUCCESS(rc))
    741         {
    742             pMixStream->InOut.pOut = pGstStrm;
    743 
    744             /* Increase the stream's reference count to let others know
    745              * we're reyling on it to be around now. */
    746             pConn->pfnAddRefOut(pConn, pGstStrm);
    747         }
    748     }
    749     else
    750         rc = VERR_NOT_SUPPORTED;
    751 
    752     if (RT_SUCCESS(rc))
    753     {
    754         pMixStream->fFlags = fFlags;
    755         pMixStream->enmDir = pCfg->enmDir;
    756         pMixStream->pConn  = pConn;
    757 
    758         if (ppStream)
    759             *ppStream = pMixStream;
    760     }
    761     else if (pMixStream)
    762     {
    763         RTStrFree(pMixStream->pszName);
    764         pMixStream->pszName = NULL;
    765 
    766         RTMemFree(pMixStream);
    767         pMixStream = NULL;
    768     }
    769 
    770     return rc;
    771 }
    772 
    773835static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream)
    774836{
     
    832894        return false;
    833895
     896    bool fIsActive;
     897    switch (pStream->enmDir)
     898    {
     899        case PDMAUDIODIR_IN:
     900        {
     901            fIsActive = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn);
     902            break;
     903        }
     904
     905        case PDMAUDIODIR_OUT:
     906        {
     907            fIsActive = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut);
     908            break;
     909        }
     910
     911        default:
     912            fIsActive = false;
     913            AssertMsgFailed(("Not implemented\n"));
     914            break;
     915    }
     916
     917    return fIsActive;
     918}
     919
     920bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream)
     921{
     922    if (!pStream)
     923        return false;
     924
    834925    bool fIsValid;
    835926    switch (pStream->enmDir)
     
    837928        case PDMAUDIODIR_IN:
    838929        {
    839             fIsValid = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn);
     930            fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn);
    840931            break;
    841932        }
     
    843934        case PDMAUDIODIR_OUT:
    844935        {
    845             fIsValid = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut);
     936            fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut);
    846937            break;
    847938        }
     
    856947}
    857948
    858 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream)
    859 {
    860     if (!pStream)
    861         return false;
    862 
    863     bool fIsValid;
    864     switch (pStream->enmDir)
    865     {
    866         case PDMAUDIODIR_IN:
    867         {
    868             fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn);
    869             break;
    870         }
    871 
    872         case PDMAUDIODIR_OUT:
    873         {
    874             fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut);
    875             break;
    876         }
    877 
    878         default:
    879             fIsValid = false;
    880             AssertMsgFailed(("Not implemented\n"));
    881             break;
    882     }
    883 
    884     return fIsValid;
    885 }
    886 
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r60941 r61050  
    6969} AUDMIXSTREAM, *PAUDMIXSTREAM;
    7070
     71/** No flags specified. */
     72#define AUDMIXSINK_FLAG_NONE                  0
     73/** Dirty flag. */
     74#define AUDMIXSINK_FLAG_DIRTY                 RT_BIT(0)
     75
    7176/**
    7277 * Audio mixer sink direction.
     
    113118     *  if this sink handles input or output. */
    114119    AUDMIXSINKDIR           enmDir;
     120    /** Sink flags of type AUDMIXSINK_FLAG_. */
     121    uint32_t                fFlags;
    115122    /** The sink's PCM format. */
    116123    PDMPCMPROPS             PCMProps;
     
    145152int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer);
    146153int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink);
     154int AudioMixerCreateStream(PAUDIOMIXER pMixer, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream);
    147155void AudioMixerDestroy(PAUDIOMIXER pMixer);
    148156int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg);
     
    159167PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
    160168uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink);
     169bool AudioMixerSinkHasData(PAUDMIXSINK pSink);
    161170int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    162171void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     
    164173int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps);
    165174int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
    166 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData);
     175void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTimerTicks, uint64_t cTicksElapsed, uint32_t *pcbData);
    167176int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    168177int AudioMixerSinkUpdate(PAUDMIXSINK pSink);
    169178
    170 int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream);
    171179int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl);
    172180void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream);
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r60942 r61050  
    2727#include <iprt/assert.h>
    2828#ifdef IN_RING3
     29# ifdef DEBUG
     30#  include <iprt/file.h>
     31# endif
    2932# include <iprt/mem.h>
    3033# include <iprt/string.h>
     
    371374    uint32_t                Padding0;
    372375# endif
     376    /** Flag indicating whether the timer is active or not. */
     377    bool                    fTimerActive;
     378    uint8_t                 u8Padding1[7];
    373379    /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
    374380    uint64_t                cTimerTicks;
     
    547553    }
    548554
    549     LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8\n", pStream->u8Strm, fActive, pThis->cStreamsActive));
    550 
    551     return AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
    552                              fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     555    int rc = AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
     556                               fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     557
     558    LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8, rc=%Rrc\n",
     559                 pStream->u8Strm, fActive, pThis->cStreamsActive, rc));
     560    if (rc == VERR_AUDIO_STREAM_PENDING_DISABLE)
     561    {
     562        LogFlowFunc(("On pending disable\n"));
     563        rc = VINF_SUCCESS;
     564    }
     565
     566    return rc;
    553567}
    554568
     
    743757        pStrmIn->pMixStrm = NULL;
    744758
    745         int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStrmIn->pMixStrm);
     759        int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStrmIn->pMixStrm);
    746760        if (RT_SUCCESS(rc2))
    747761        {
     
    788802        pDrv->Out.pMixStrm = NULL;
    789803
    790         int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
     804        int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
    791805        if (RT_SUCCESS(rc2))
    792806        {
     
    876890    if (RT_SUCCESS(rc))
    877891    {
    878         pStream->State.cbFIFOW  = 256; /** @todo Make FIFOW size configurable. */
     892        pStream->State.cbFIFOW  = _4K; /** @todo Make FIFOW size configurable. */
    879893        pStream->State.offFIFOW = 0;
    880894        pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW);
     
    11581172        PDMDevHlpPhysRead(pDevIns, addr, pu8FIFOW, cbToRead); /** @todo r=andy Check rc? */
    11591173
     1174#if defined (RT_OS_LINUX) && defined(DEBUG_andy)
     1175        RTFILE fh;
     1176        RTFileOpen(&fh, "/tmp/ac97WriteAudio.pcm",
     1177                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     1178        RTFileWrite(fh, pu8FIFOW, cbToRead, NULL);
     1179        RTFileClose(fh);
     1180#endif
    11601181        /*
    11611182         * Write data to the mixer sink.
     
    13131334        return;
    13141335
     1336    /* Set timer flag. */
     1337    ASMAtomicXchgBool(&pThis->fTimerActive, true);
     1338
     1339    /* Update current time timestamp. */
     1340    pThis->uTimerTS = TMTimerGet(pThis->pTimer);
     1341
    13151342    /* Fire off timer. */
    13161343    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     
    13271354        return;
    13281355
    1329     int rc2 = TMTimerStop(pThis->pTimer);
    1330     AssertRC(rc2);
     1356    /* Set timer flag. */
     1357    ASMAtomicXchgBool(&pThis->fTimerActive, false);
    13311358}
    13321359
     
    13411368    uint64_t cTicksNow     = TMTimerGet(pTimer);
    13421369    uint64_t cTicksElapsed = cTicksNow  - pThis->uTimerTS;
    1343     uint64_t cTicksPerSec  = TMTimerGetFreq(pTimer);
    1344 
     1370
     1371    /* Update current time timestamp. */
    13451372    pThis->uTimerTS = cTicksNow;
    13461373
    13471374    uint32_t cbLineIn;
    1348     AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, cTicksPerSec, cTicksElapsed, &cbLineIn);
     1375    AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicksElapsed, &cbLineIn);
    13491376    if (cbLineIn)
    1350         ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbLineIn); /** @todo Add rc! */
     1377        ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbLineIn);
    13511378
    13521379    uint32_t cbMicIn;
    1353     AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , cTicksPerSec, cTicksElapsed, &cbMicIn);
     1380    AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicksElapsed, &cbMicIn);
     1381    if (cbMicIn)
     1382        ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbMicIn);
    13541383
    13551384    uint32_t cbOut;
    1356     AudioMixerSinkTimerUpdate(pThis->pSinkOutput, cTicksPerSec, cTicksElapsed, &cbOut);
     1385    AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicksElapsed, &cbOut);
    13571386    if (cbOut)
    1358         ichac97TransferAudio(pThis, &pThis->StreamOut, cbOut);  /** @todo Add rc! */
    1359 
    1360     /* Kick the timer again. */
    1361     uint64_t cTicks = pThis->cTimerTicks;
    1362     /** @todo adjust cTicks down by now much cbOutMin represents. */
    1363     TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     1387        ichac97TransferAudio(pThis, &pThis->StreamOut, cbOut);
     1388
     1389    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     1390        || AudioMixerSinkHasData(pThis->pSinkLineIn)
     1391        || AudioMixerSinkHasData(pThis->pSinkMicIn)
     1392        || AudioMixerSinkHasData(pThis->pSinkOutput))
     1393    {
     1394        /* Kick the timer again. */
     1395        uint64_t cTicks = pThis->cTimerTicks;
     1396        /** @todo adjust cTicks down by now much cbOutMin represents. */
     1397        TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     1398    }
    13641399
    13651400    STAM_PROFILE_STOP(&pThis->StatTimer, a);
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r60942 r61050  
    469469 * Other values not listed are not supported.
    470470 */
    471 #define HDA_SDINFIFO_120B           0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
    472 #define HDA_SDINFIFO_160B           0x9F /* 20-, 24-bit Input Streams Streams */
    473 
    474 #define HDA_SDONFIFO_16B            0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    475 #define HDA_SDONFIFO_32B            0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    476 #define HDA_SDONFIFO_64B            0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    477 #define HDA_SDONFIFO_128B           0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    478 #define HDA_SDONFIFO_192B           0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
    479 #define HDA_SDONFIFO_256B           0xFF /* 20-, 24-bit Output Streams */
     471#define HDA_SDIFIFO_120B            0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
     472#define HDA_SDIFIFO_160B            0x9F /* 20-, 24-bit Input Streams Streams */
     473
     474#define HDA_SDOFIFO_16B             0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     475#define HDA_SDOFIFO_32B             0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     476#define HDA_SDOFIFO_64B             0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     477#define HDA_SDOFIFO_128B            0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     478#define HDA_SDOFIFO_192B            0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
     479#define HDA_SDOFIFO_256B            0xFF /* 20-, 24-bit Output Streams */
    480480#define SDFIFOS(pThis, num)         HDA_REG((pThis), SD(FIFOS, num))
    481481
     
    559559    uint32_t     cbBelowFIFOW;
    560560    /** The buffer descriptor's internal DMA buffer. */
    561     uint8_t      au8FIFO[HDA_SDONFIFO_256B + 1];
     561    uint8_t      au8FIFO[HDA_SDOFIFO_256B + 1];
    562562    /** Current offset in DMA buffer (in bytes).*/
    563563    uint32_t     u32BufOff;
     
    789789    bool                               fDMAPosition;
    790790    /** Padding for alignment. */
    791     uint8_t                            u32Padding0[7];
     791    uint8_t                            u8Padding0[7];
    792792    /** Pointer to CORB buffer. */
    793793    R3PTRTYPE(uint32_t *)              pu32CorbBuf;
     
    811811    /** The timer for pumping data thru the attached LUN drivers. */
    812812    PTMTIMERR3                         pTimer;
    813     /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
     813    /** Flag indicating whether the timer is active or not. */
     814    bool                               fTimerActive;
     815    uint8_t                            u8Padding1[7];
     816    /** Timer ticks per Hz. */
    814817    uint64_t                           cTimerTicks;
    815818    /** Timestamp of the last timer callback (hdaTimer).
     
    11721175    {
    11731176        /* Input */
    1174         case HDA_SDINFIFO_120B: cb = 120; break;
    1175         case HDA_SDINFIFO_160B: cb = 160; break;
     1177        case HDA_SDIFIFO_120B: cb = 120; break;
     1178        case HDA_SDIFIFO_160B: cb = 160; break;
    11761179
    11771180        /* Output */
    1178         case HDA_SDONFIFO_16B:  cb = 16;  break;
    1179         case HDA_SDONFIFO_32B:  cb = 32;  break;
    1180         case HDA_SDONFIFO_64B:  cb = 64;  break;
    1181         case HDA_SDONFIFO_128B: cb = 128; break;
    1182         case HDA_SDONFIFO_192B: cb = 192; break;
    1183         case HDA_SDONFIFO_256B: cb = 256; break;
     1181        case HDA_SDOFIFO_16B:  cb = 16;  break;
     1182        case HDA_SDOFIFO_32B:  cb = 32;  break;
     1183        case HDA_SDOFIFO_64B:  cb = 64;  break;
     1184        case HDA_SDOFIFO_128B: cb = 128; break;
     1185        case HDA_SDOFIFO_192B: cb = 192; break;
     1186        case HDA_SDOFIFO_256B: cb = 256; break;
    11841187        default:
    11851188        {
     
    13411344         && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
    13421345
    1343     uint8_t uLevel = 0;
     1346    int iLevel = 0;
    13441347
    13451348    /** @todo Optimize IRQ handling. */
     
    13501353           || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
    13511354           || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))))
    1352         uLevel = 1;
     1355    {
     1356        iLevel = 1;
     1357    }
    13531358
    13541359    if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
     
    13611366        || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 7))
    13621367    {
    1363         uLevel = 1;
     1368        iLevel = 1;
    13641369    }
    13651370
    13661371    if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
    13671372    {
    1368         Log3Func(("Level=%d\n", uLevel));
    1369         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , uLevel);
     1373        Log3Func(("Level=%d\n", iLevel));
     1374        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , iLevel);
    13701375    }
    13711376
     
    14891494    {
    14901495        Assert((HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)));
     1496        Assert(pThis->u64CORBBase);
     1497        AssertPtr(pThis->pu32CorbBuf);
     1498        Assert(pThis->cbCorbBuf);
     1499
    14911500        rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
    14921501        if (RT_FAILURE(rc))
     
    17201729    HDA_STREAM_REG(pThis, CTL,   uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    17211730    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */
    1722     HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
     1731    HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B;
    17231732    /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
    17241733    HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
     
    20972106    }
    20982107
    2099     HDA_MARK_STREAM(0); /* SD0: Input. */
    2100     HDA_MARK_STREAM(4); /* SD4: Output. */
     2108    HDA_MARK_STREAM(0);
     2109    HDA_MARK_STREAM(1);
     2110    HDA_MARK_STREAM(2);
     2111    HDA_MARK_STREAM(3);
     2112    HDA_MARK_STREAM(4);
     2113    HDA_MARK_STREAM(5);
     2114    HDA_MARK_STREAM(6);
     2115    HDA_MARK_STREAM(7);
    21012116
    21022117#undef HDA_MARK_STREAM
    21032118
    21042119    /* "OR" bit of all interrupt status bits. */
    2105     if (v)
    2106         v |= RT_BIT(31);
     2120    v |= v ? RT_BIT(31) : 0;
    21072121
    21082122    *pu32Value = v;
     
    22402254    bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    22412255
    2242 uint32_t uVal = HDA_REG_IND(pThis, iReg);
    2243     LogFunc(("uVal=%RU32 vs u32Value=%RU32\n", uVal, u32Value));
    2244 
    22452256    if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    22462257        return VINF_SUCCESS;
     
    23462357static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    23472358{
    2348     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2349         return VINF_SUCCESS;
    2350 
    23512359    uint32_t v  = HDA_REG_IND(pThis, iReg);
    23522360             /* Clear (zero) FIFOE and DESE bits when writing 1 to it. */
     
    23962404static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    23972405{
    2398     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
     2406    uint8_t  uSD      = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
     2407    /** @todo Only allow updating FIFOS if RUN bit is 0? */
     2408    uint32_t u32FIFOW = 0;
     2409
     2410    if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_IN) /* FIFOW for input streams only. */
     2411    {
     2412        LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to stream #%RU8, ignoring\n", uSD));
    23992413        return VINF_SUCCESS;
     2414    }
    24002415
    24012416    switch (u32Value)
     
    24042419        case HDA_SDFIFOW_16B:
    24052420        case HDA_SDFIFOW_32B:
    2406             return hdaRegWriteU16(pThis, iReg, u32Value);
     2421            u32FIFOW = u32Value;
     2422            break;
    24072423        default:
    2408             LogFunc(("Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
    2409             return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
    2410     }
     2424            LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
     2425                    u32Value, uSD));
     2426            u32FIFOW = HDA_SDFIFOW_32B;
     2427            break;
     2428    }
     2429
     2430    if (u32FIFOW)
     2431    {
     2432        LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, hdaSDFIFOSToBytes(u32FIFOW)));
     2433        /** @todo Update internal stream state with new FIFOS. */
     2434
     2435        return hdaRegWriteU16(pThis, iReg, u32FIFOW);
     2436    }
     2437
    24112438    return VINF_SUCCESS; /* Never reached. */
    24122439}
     
    24182445static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    24192446{
    2420     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2421         return VINF_SUCCESS;
    2422 
    24232447    uint8_t  uSD      = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
    24242448    /** @todo Only allow updating FIFOS if RUN bit is 0? */
    24252449    uint32_t u32FIFOS = 0;
    24262450
    2427     if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) /* FIFOS for input streams is read-only. */
    2428     {
    2429         LogRel(("HDA: Warning: Guest tried to write read-only FIFOS for input stream #%RU8, skipping\n", uSD));
    2430         AssertFailed();
     2451    if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_OUT) /* FIFOS for output streams only. */
     2452    {
     2453        LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to stream #%RU8, ignoring\n", uSD));
    24312454        return VINF_SUCCESS;
    24322455    }
     
    24342457    switch(u32Value)
    24352458    {
    2436         case HDA_SDONFIFO_16B:
    2437         case HDA_SDONFIFO_32B:
    2438         case HDA_SDONFIFO_64B:
    2439         case HDA_SDONFIFO_128B:
    2440         case HDA_SDONFIFO_192B:
     2459        case HDA_SDOFIFO_16B:
     2460        case HDA_SDOFIFO_32B:
     2461        case HDA_SDOFIFO_64B:
     2462        case HDA_SDOFIFO_128B:
     2463        case HDA_SDOFIFO_192B:
    24412464            u32FIFOS = u32Value;
    24422465            break;
    24432466
    2444         case HDA_SDONFIFO_256B: /** @todo r=andy Investigate this. */
     2467        case HDA_SDOFIFO_256B: /** @todo r=andy Investigate this. */
    24452468            LogFunc(("256-bit is unsupported, HDA is switched into 192-bit mode\n"));
    24462469            /* Fall through is intentional. */
    24472470        default:
    2448             LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to input stream #%RU8, defaulting to 192 bytes\n",
     2471            LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
    24492472                    u32Value, uSD));
    2450             u32FIFOS = HDA_SDONFIFO_192B;
    2451             AssertFailed();
     2473            u32FIFOS = HDA_SDOFIFO_192B;
    24522474            break;
    24532475    }
     
    24742496    int rc = VINF_SUCCESS;
    24752497
    2476     uint32_t u32Hz     = (u32SDFMT & HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
     2498    uint32_t u32Hz     = EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
     2499                       ? 44100 : 48000;
    24772500    uint32_t u32HzMult = 1;
    24782501    uint32_t u32HzDiv  = 1;
     
    25982621    }
    25992622#else /* !VBOX_WITH_HDA_51_SURROUND */
     2623    /* Only support mono or stereo channels. */
    26002624    if (   pCfg->cChannels != 1 /* Mono */
    26012625        && pCfg->cChannels != 2 /* Stereo */)
     
    26052629#endif
    26062630
    2607     if (RT_FAILURE(rc))
     2631    if (rc == VERR_NOT_SUPPORTED)
    26082632    {
    26092633        LogRel(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->cChannels));
    26102634        pCfg->cChannels = 2;
     2635
     2636        rc = VINF_SUCCESS;
    26112637    }
    26122638
    26132639    do
    26142640    {
     2641        if (RT_FAILURE(rc))
     2642            break;
     2643
    26152644        if (fUseFront)
    26162645        {
     
    26432672            if (RT_SUCCESS(rc))
    26442673                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
    2645 
    2646             RTStrFree(pszName);
    26472674        }
    26482675
     
    26662693    } while (0);
    26672694
     2695    LogFlowFuncLeaveRC(rc);
    26682696    return rc;
    26692697}
     
    27072735    }
    27082736
     2737    LogFlowFuncLeaveRC(rc);
    27092738    return rc;
    27102739}
     
    28652894    if (fIsRunning)
    28662895    {
    2867         LogFlowFunc(("[SD%RU8]: Warning: Cannot write to register 0x%x (0x%x) when RUN bit is set (%R[sdctl])\n",
    2868                      pStream->u8SD, iReg, u32Value, u32SDCTL));
     2896        LogFunc(("[SD%RU8]: Warning: Cannot write to register 0x%x (0x%x) when RUN bit is set (%R[sdctl])\n",
     2897                 pStream->u8SD, iReg, u32Value, u32SDCTL));
     2898# ifdef DEBUG_andy
     2899        AssertFailed();
     2900# endif
    28692901        return VERR_ACCESS_DENIED;
    28702902    }
     
    31113143    Assert(u32LPIB <= pStream->u32CBL);
    31123144
    3113     uint32_t cbFree = pStream->u32CBL - u32LPIB; /** @todo Convert samples to bytes? */
     3145    uint32_t cbFree = pStream->u32CBL - u32LPIB;
    31143146    if (cbFree)
    31153147    {
     
    31183150
    31193151        /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
    3120         cbFree = RT_MIN(cbFree, pStream->u16FIFOS);
     3152     //   cbFree = RT_MIN(cbFree, uint32_t(pStream->u16FIFOS));
    31213153
    31223154        /* Make sure we only transfer as many bytes as requested. */
     
    31363168    }
    31373169
    3138     LogFlowFunc(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, cbFree=%RU32, %R[bdle]\n", pStream->u8SD,
    3139                  pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbFree, pBDLE));
     3170    LogFlowFunc(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbFree=%RU32, %R[bdle]\n", pStream->u8SD,
     3171                 pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS, cbFree, pBDLE));
    31403172    return cbFree;
    31413173}
     
    32233255    }
    32243256
    3225     if (RT_SUCCESS(rc))
    3226         rc = RTCircBufCreate(&pMapping->pCircBuf, _4K);
     3257    if (   RT_SUCCESS(rc)
     3258        /* Create circular buffer if not created yet. */
     3259        && !pMapping->pCircBuf)
     3260    {
     3261        rc = RTCircBufCreate(&pMapping->pCircBuf, _4K); /** @todo Make size configurable? */
     3262    }
    32273263
    32283264    if (RT_SUCCESS(rc))
     
    33123348    LogFlowFunc(("[SD%RU8]: cbInc=%RU32\n", pStream->u8SD, cbInc));
    33133349
    3314     Assert(cbInc <= pStream->u16FIFOS);
     3350    //Assert(cbInc <= pStream->u16FIFOS);
    33153351
    33163352    if (!cbInc) /* Nothing to do? Bail out early. */
     
    34293465        Assert(cbRead <= cbBuf);
    34303466        Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff);
    3431         Assert(cbRead <= pStream->u16FIFOS);
     3467        //Assert(cbRead <= pStream->u16FIFOS);
    34323468
    34333469        /*
     
    35033539                               pvBuf, cbBuf);
    35043540        AssertRC(rc);
    3505 #if defined (RT_OS_LINUX) && defined(DEBUG)
     3541#if defined (RT_OS_LINUX) && defined(DEBUG_andy)
    35063542        RTFILE fh;
    3507         RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm",
     3543        RTFileOpen(&fh, "/tmp/hdaWriteAudio-hda.pcm",
    35083544                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    35093545        RTFileWrite(fh, pvBuf, cbBuf, NULL);
     
    36023638    }
    36033639
    3604     Assert(cbWritten <= pStream->u16FIFOS);
     3640    //Assert(cbWritten <= pStream->u16FIFOS);
    36053641
    36063642    if (RT_SUCCESS(rc))
     
    36813717    if (RT_SUCCESS(rc))
    36823718        rc = AudioMixerSinkSetFormat(pSink->pMixSink, &PCMProps);
     3719
     3720    if (RT_FAILURE(rc))
     3721        return rc;
    36833722
    36843723    PHDADRIVER pDrv;
     
    37363775
    37373776            PAUDMIXSTREAM pMixStrm;
    3738             rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm);
     3777            rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm);
    37393778            if (RT_SUCCESS(rc2))
    37403779            {
     
    37763815    {
    37773816        rc = hdaMixerAddStream(pThis, pSink, pCfg);
     3817
     3818        AssertPtr(pSink->pMixSink);
     3819        LogFlowFunc(("Sink=%s, enmMixerCtl=%ld\n", pSink->pMixSink->pszName, enmMixerCtl));
    37783820    }
    37793821    else
    37803822        rc = VERR_NOT_FOUND;
    37813823
    3782     LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pMixSink->pszName, enmMixerCtl, rc));
     3824    LogFlowFuncLeaveRC(rc);
    37833825    return rc;
    37843826}
     
    39523994static void hdaTimerMaybeStart(PHDASTATE pThis)
    39533995{
     3996    LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
     3997
    39543998    if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
    39553999        return;
     
    39604004    LogFlowFuncEnter();
    39614005
     4006    /* Set timer flag. */
     4007    ASMAtomicXchgBool(&pThis->fTimerActive, true);
     4008
     4009    /* Update current time timestamp. */
     4010    pThis->uTimerTS = TMTimerGet(pThis->pTimer);
     4011
    39624012    /* Fire off timer. */
    39634013    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     
    39664016static void hdaTimerMaybeStop(PHDASTATE pThis)
    39674017{
     4018    LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
     4019
    39684020    if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
    39694021        return;
     
    39744026    LogFlowFuncEnter();
    39754027
    3976     int rc2 = TMTimerStop(pThis->pTimer);
    3977     AssertRC(rc2);
     4028    /* Set timer flag. */
     4029    ASMAtomicXchgBool(&pThis->fTimerActive, false);
    39784030}
    39794031
     
    39914043    uint64_t cTicksNow     = TMTimerGet(pTimer);
    39924044    uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS;
    3993     uint64_t cTicksPerSec  = TMTimerGetFreq(pTimer);
    3994 
     4045
     4046    /* Update current time timestamp. */
    39954047    pThis->uTimerTS = cTicksNow;
    39964048
     
    40004052#endif
    40014053    PHDASTREAM pStreamFront   = hdaGetStreamFromSink(pThis, &pThis->SinkFront);
     4054#ifdef VBOX_WITH_HDA_51_SURROUND
     4055    /** @todo See note below. */
     4056#endif
    40024057
    40034058    uint32_t cbLineIn;
    4004     AudioMixerSinkTimerUpdate(pThis->SinkLineIn.pMixSink, cTicksPerSec, cTicksElapsed, &cbLineIn);
     4059    AudioMixerSinkTimerUpdate(pThis->SinkLineIn.pMixSink,    pThis->cTimerTicks, cTicksElapsed, &cbLineIn);
    40054060    if (cbLineIn)
    40064061        hdaTransfer(pThis, pStreamLineIn, cbLineIn, NULL); /** @todo Add rc! */
     
    40084063#ifdef VBOX_WITH_HDA_MIC_IN
    40094064    uint32_t cbMicIn;
    4010     AudioMixerSinkTimerUpdate(pThis->SinkMicIn.pMixSink , cTicksPerSec, cTicksElapsed, &cbMicIn);
    4011 #endif
    4012 
    4013     uint32_t cbOut;
    4014     AudioMixerSinkTimerUpdate(pThis->SinkFront.pMixSink, cTicksPerSec, cTicksElapsed, &cbOut);
    4015     if (cbOut)
    4016         hdaTransfer(pThis, pStreamFront, cbOut, NULL);  /** @todo Add rc! */
    4017 
    4018     /* Kick the timer again. */
    4019     uint64_t cTicks = pThis->cTimerTicks;
    4020     /** @todo adjust cTicks down by now much cbOutMin represents. */
    4021     TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     4065    AudioMixerSinkTimerUpdate(pThis->SinkMicIn.pMixSink ,    pThis->cTimerTicks, cTicksElapsed, &cbMicIn);
     4066#endif
     4067
     4068    uint32_t cbFront;
     4069    AudioMixerSinkTimerUpdate(pThis->SinkFront.pMixSink,     pThis->cTimerTicks, cTicksElapsed, &cbFront);
     4070#ifdef VBOX_WITH_HDA_51_SURROUND
     4071    uint32_t cbCenterLFE;
     4072    AudioMixerSinkTimerUpdate(pThis->SinkCenterLFE.pMixSink, pThis->cTimerTicks, cTicksElapsed, &cbCenterLFE);
     4073    uint32_t cbRear;
     4074    AudioMixerSinkTimerUpdate(pThis->SinkRear.pMixSink,      pThis->cTimerTicks, cTicksElapsed, &cbRear);
     4075#endif
     4076
     4077    if (cbFront)
     4078        hdaTransfer(pThis, pStreamFront, cbFront, NULL);  /** @todo Add rc! */
     4079#ifdef VBOX_WITH_HDA_51_SURROUND
     4080    /*
     4081     * Only call hdaTransfer if CenterLFE and/or Rear are on different SDs,
     4082     * otherwise we have to use the interleaved streams support for getting the data
     4083     * out of the Front sink (depending on the mapping layout).
     4084     */
     4085#endif
     4086
     4087    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     4088        || AudioMixerSinkHasData(pThis->SinkFront.pMixSink)
     4089#ifdef VBOX_WITH_HDA_51_SURROUND
     4090        || AudioMixerSinkHasData(pThis->SinkCenterLFE.pMixSink)
     4091        || AudioMixerSinkHasData(pThis->SinkRear.pMixSink)
     4092#endif
     4093        || AudioMixerSinkHasData(pThis->SinkLineIn.pMixSink))
     4094    {
     4095        /* Kick the timer again. */
     4096        uint64_t cTicks = pThis->cTimerTicks;
     4097        /** @todo adjust cTicks down by now much cbOutMin represents. */
     4098        TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     4099    }
    40224100
    40234101    STAM_PROFILE_STOP(&pThis->StatTimer, a);
     
    41114189        fProceed = false;
    41124190
    4113 #if 0
    4114     Log3Func(("[SD%RU8] fProceed=%RTbool, fRun=%RTbool, cbToProcess=%RU32\n",
    4115               pStream->u8SD, fProceed, HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN),
    4116               cbToProcess));
    4117 #endif
    4118 
    41194191    if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
    41204192    {
    4121         Log3Func(("[SD%RU8]: BCIS: Skipping\n", pStream->u8SD));
     4193        Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    41224194        fProceed = false;
    41234195    }
     
    41254197    if (!fProceed)
    41264198    {
     4199        Log3Func(("[SD%RU8] Skipping\n"));
     4200
    41274201        rc = RTSemMutexRelease(pStream->State.hMtx);
    41284202        AssertRC(rc);
     
    41444218    Assert(u32LPIB <= pStream->u32CBL);
    41454219
    4146     if (u32LPIB == pStream->u32CBL)
    4147          u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0);
    4148 
    4149     uint32_t cbLeft  = pStream->u32CBL - u32LPIB;
     4220    uint32_t cbLeft  = cbToProcess;
    41504221    uint32_t cbTotal = 0;
    41514222
     
    41544225    Log3Func(("cbLeft=%RU32\n", cbLeft));
    41554226
     4227#define FOO
     4228
     4229#ifdef FOO
     4230    uint8_t u8FIFO[_16K+1];
     4231    size_t u8FIFOff = 0;
     4232#endif
     4233
     4234    /* Set the FIFORDY bit on the stream while doing the transfer. */
     4235    HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4236
    41564237    while (cbLeft)
    41574238    {
    4158     #if 1
    41594239        /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
    41604240        if (hdaStreamNeedsNextBDLE(pThis, pStream))
     
    41644244                break;
    41654245        }
    4166     #else
    4167         PHDABDLE pBDLE   = &pStream->State.BDLE;
    4168 
    4169         /* Did we reach the CBL (Cyclic Buffer List) limit? */
    4170         bool fCBLLimitReached = u32LPIB >= pStream->u32CBL;
    4171 
    4172         /* Do we need to use the next BDLE entry? Either because we reached
    4173          * the CBL limit or our internal DMA buffer is full. */
    4174         bool fNeedsNextBDLE   = (   fCBLLimitReached
    4175                                  || (pBDLE->State.u32BufOff >= pBDLE->u32BufSize));
    4176 
    4177         Assert(u32LPIB                <= pStream->u32CBL);
    4178         Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
    4179 
    4180         if (fNeedsNextBDLE)
    4181         {
    4182 
    4183 
    4184         #if 1
    4185             if (/* IOC (Interrupt On Completion) bit set? */
    4186                    pBDLE->fIntOnCompletion
    4187                 /* All data put into the DMA FIFO? */
    4188                 && pBDLE->State.cbBelowFIFOW == 0
    4189                )
    4190             {
    4191             //    fSetIRQ = true;
    4192                 /*
    4193                  * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
    4194                  * we need to generate an interrupt.
    4195                  */
    4196                // if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    4197                  //   PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
    4198             }
    4199         #endif
    4200 
    4201 
    4202         }
    4203     #endif
    4204 
    4205         /* Set the FIFORDY bit on the stream while doing the transfer. */
    4206         HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    42074246
    42084247        uint32_t cbProcessed;
     
    42104249            rc = hdaReadAudio (pThis, pStream, cbLeft, &cbProcessed);
    42114250        else
     4251        {
     4252#ifndef FOO
    42124253            rc = hdaWriteAudio(pThis, pStream, cbLeft, &cbProcessed);
    4213 
    4214         /* Remove the FIFORDY bit again. */
    4215         HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4254#else
     4255            uint32_t cbToWrite = hdaStreamGetTransferSize(pThis, pStream, cbLeft);
     4256
     4257            void    *pvBuf = u8FIFO + u8FIFOff;
     4258            int32_t cbBuf = cbToWrite;
     4259
     4260            PHDABDLE pBDLE = &pStream->State.BDLE;
     4261
     4262            rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     4263                               pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
     4264                               pvBuf, cbBuf);
     4265
     4266            hdaBDLEUpdate(pBDLE, cbToWrite, cbToWrite);
     4267
     4268            LogFlowFunc(("u8FIFOff=%zu, cbLeft=%RU32, cbToWrite=%RU32\n", u8FIFOff, cbLeft, cbToWrite));
     4269
     4270            u8FIFOff += cbToWrite;
     4271            Assert(u8FIFOff <= sizeof(u8FIFO));
     4272
     4273            cbProcessed = cbToWrite;
     4274#endif
     4275        }
    42164276
    42174277        if (RT_FAILURE(rc))
    42184278            break;
    42194279
    4220     #if 1
    42214280        hdaStreamTransferUpdate(pThis, pStream, cbProcessed);
    42224281
     
    42324291
    42334292        if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt))
    4234         {
    4235             rc = hdaStreamGetNextBDLE(pThis, pStream);
    42364293            break;
    4237         }
    4238     #else
    4239         Assert(cbProcessedLeft >= cbProcessed);
    4240         cbProcessedLeft  -= cbProcessed;
    4241         cbProcessedTotal += cbProcessed;
    4242 
    4243 
    4244         u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, u32LPIB + cbProcessed);
    4245 
    4246         Assert(u32LPIB <= pStream->u32CBL);
    4247         if (u32LPIB == pStream->u32CBL)
    4248         {
    4249            // HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
    4250             Log3Func(("[SD%RU8]: Transfer complete\n", pStream->u8SD));
     4294    }
     4295
     4296    /* Remove the FIFORDY bit again. */
     4297    HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4298
     4299#ifdef FOO
     4300    #if defined (RT_OS_LINUX) && defined(DEBUG_andy)
     4301        RTFILE fh;
     4302        RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm",
     4303                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     4304        RTFileWrite(fh, u8FIFO, u8FIFOff, NULL);
     4305        RTFileClose(fh);
     4306    #endif
    42514307#if 1
    4252             if (/* IOC (Interrupt On Completion) bit set? */
    4253                    pBDLE->fIntOnCompletion
    4254                 /* All data put into the DMA FIFO? */
    4255                 && pBDLE->State.cbBelowFIFOW == 0
    4256                )
    4257             {
    4258                 fSetIRQ = true;
    4259                 /*
    4260                  * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
    4261                  * we need to generate an interrupt.
    4262                  */
    4263             //    if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    4264               //      PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
    4265               //  fIRQ = true;
    4266             }
    4267 #endif
    4268             fIsComplete = true;
    4269         }
    4270 
    4271         if (   fIsComplete
    4272             || pBDLE->State.u32BufOff >= pBDLE->u32BufSize)
    4273         {
    4274             Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
    4275 
    4276             Log3Func(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, %R[bdle] => Next BDLE\n",
    4277                       pStream->u8SD, u32LPIB, u32LPIB >= pStream->u32CBL, pBDLE));
    4278 
    4279             /*
    4280              * Switch to the next BDLE entry and do a wrap around
    4281              * if we reached the end of the Buffer Descriptor List (BDL).
    4282              */
    4283             pStream->State.uCurBDLE++;
    4284             if (pStream->State.uCurBDLE == pStream->u16LVI + 1)
    4285             {
    4286                 pStream->State.uCurBDLE = 0;
    4287                 u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0);
    4288             }
    4289 
    4290             hdaBDLEFetch(pThis, &pStream->State.BDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    4291 
    4292             if (/* IOC (Interrupt On Completion) bit set? */
    4293                    pBDLE->fIntOnCompletion
    4294                 /* All data put into the DMA FIFO? */
    4295                 && pBDLE->State.cbBelowFIFOW == 0
    4296                )
    4297             {
    4298                 fSetIRQ = true;
    4299             }
    4300         }
    4301 
    4302     #endif
    4303 
    4304         /*if (fIsComplete)
    4305             break;*/
    4306     }
    4307 
     4308     AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, u8FIFO, u8FIFOff,
     4309                         NULL /* pcbWritten */);
     4310#endif
     4311#endif
     4312
     4313#ifdef FOO
    43084314    if (fInterrupt)
    43094315    {
     
    43194325         */
    43204326        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
    4321         Log3Func(("[SD%RU8]: BCIS: Set (fInterrupt=%RTbool)\n", pStream->u8SD, fInterrupt));
     4327        Log3Func(("[SD%RU8]: BCIS: Set\n", pStream->u8SD));
    43224328
    43234329        hdaProcessInterrupt(pThis);
    4324     }
    4325 
    4326 #if 0
    4327     if (fSetIRQ)
    4328     {
    4329         Log3Func(("[SD%RU8]: IRQ\n", pStream->u8SD));
    4330 
    4331         /**
    4332          * Set the BCIS (Buffer Completion Interrupt Status) flag as the
    4333          * last byte of data for the current descriptor has been fetched
    4334          * from memory and put into the DMA FIFO.
    4335          *
    4336          * Speech synthesis works fine on Mac Guest if this bit isn't set
    4337          * but in general sound quality gets worse.
    4338          *
    4339          * This must be set in *any* case.
    4340          */
    4341         HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
    4342 
    4343         /*
    4344          * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
    4345          * we need to generate an interrupt.
    4346          */
    4347         if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    4348             PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
    43494330    }
    43504331#endif
     
    50064987    if (RT_SUCCESS(rc))
    50074988    {
    5008         /*
    5009          * Update sinks after the state changes.
    5010          */
    5011         AUDMIXSINKCMD enmCmdLineIn = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
    5012                                    ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    5013 #ifdef VBOX_WITH_HDA_MIC_IN
    5014         AUDMIXSINKCMD enmCmdMicIn  = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
    5015                                    ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    5016 #endif
    5017         AUDMIXSINKCMD enmCmdOut    = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
    5018                                    ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    5019 
    5020 # ifdef VBOX_WITH_HDA_MIC_IN
    5021         AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink,     enmCmdMicIn);
    5022 # endif
    5023         AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink,    enmCmdLineIn);
    5024         AudioMixerSinkCtl(pThis->SinkFront.pMixSink,     enmCmdOut);
    5025 # ifdef VBOX_WITH_HDA_51_SURROUND
    5026         AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, enmCmdOut);
    5027         AudioMixerSinkCtl(pThis->SinkRear.pMixSink,      enmCmdOut);
    5028 # endif
    5029     }
    5030 
    5031     if (RT_SUCCESS(rc))
    5032     {
    50334989        pThis->u64CORBBase  = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
    50344990        pThis->u64RIRBBase  = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
     
    50384994        pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));
    50394995    }
    5040     else
     4996
     4997    if (RT_SUCCESS(rc))
     4998    {
     4999        for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
     5000        {
     5001            PHDASTREAM pStream = hdaStreamFromSD(pThis, i);
     5002            if (pStream)
     5003            {
     5004                bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
     5005                LogFlowFunc(("[SD%RU8]: fActive=%RTbool\n", i, fActive));
     5006                int rc2 = hdaStreamSetActive(pThis, pStream, fActive);
     5007                AssertRC(rc2);
     5008            }
     5009        }
     5010    }
     5011
     5012    if (RT_FAILURE(rc))
    50415013        LogRel(("HDA: Failed loading device state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
    50425014
     
    56785650#ifndef VBOX_WITH_AUDIO_CALLBACKS
    56795651    uint16_t uTimerHz;
    5680     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */);
     5652    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
    56815653    if (RT_FAILURE(rc))
    56825654        return PDMDEV_SET_ERROR(pDevIns, rc,
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r60938 r61050  
    16851685    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    16861686    {
    1687         int rc2 = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    1688                                                    NULL /* pcbIn */, &cbOut, NULL /* pcSamplesLive */);
     1687        int rc2 = pDrv->pConnector->pfnGetDataOut(pDrv->pConnector, &cbOut, NULL /* pcSamplesLive */);
    16891688        if (RT_SUCCESS(rc2))
    16901689            cbOutMin = RT_MIN(cbOutMin, cbOut);
     
    17611760    if (!pThis->pTimerIO)
    17621761        return;
     1762
     1763    /* Update current time timestamp. */
     1764    pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO);
    17631765
    17641766    /* Fire off timer. */
     
    20522054        pDrv->Out.pMixStrm = NULL;
    20532055
    2054         int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
     2056        int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
    20552057        if (RT_SUCCESS(rc2))
    20562058        {
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r61033 r61050  
    11611161}
    11621162
    1163 static DECLCALLBACK(int) drvAudioQueryStatus(PPDMIAUDIOCONNECTOR pInterface,
    1164                                              uint32_t *pcbAvailIn, uint32_t *pcbFreeOut,
    1165                                              uint32_t *pcSamplesLive)
     1163static DECLCALLBACK(int) drvAudioGetDataIn(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbAvailIn)
    11661164{
    11671165    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    11681166    /* pcbAvailIn is optional. */
     1167
     1168    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     1169
     1170    int rc = RTCritSectEnter(&pThis->CritSect);
     1171    if (RT_FAILURE(rc))
     1172        return rc;
     1173
     1174    uint32_t cbAvailIn = 0;
     1175
     1176    PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
     1177    while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
     1178    {
     1179        /* Disabled? Skip it! */
     1180        if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     1181            continue;
     1182
     1183        /* Call the host backend to capture the audio input data. */
     1184        uint32_t cSamplesCaptured;
     1185        int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn,
     1186                                                     &cSamplesCaptured);
     1187        if (RT_FAILURE(rc2))
     1188            continue;
     1189
     1190        PPDMAUDIOGSTSTRMIN pGstStrmIn = pHstStrmIn->pGstStrmIn;
     1191        AssertPtrBreak(pGstStrmIn);
     1192
     1193        if (pGstStrmIn->State.fActive)
     1194        {
     1195            cbAvailIn = RT_MAX(cbAvailIn, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf,
     1196                                                          AudioMixBufMixed(&pHstStrmIn->MixBuf)));
     1197#ifdef DEBUG_andy
     1198            LogFlowFunc(("\t[%s] cbAvailIn=%RU32\n", pHstStrmIn->MixBuf.pszName, cbAvailIn));
     1199#endif
     1200        }
     1201    }
     1202
     1203    if (RT_SUCCESS(rc))
     1204    {
     1205        if (pcbAvailIn)
     1206            *pcbAvailIn = cbAvailIn;
     1207    }
     1208
     1209    int rc2 = RTCritSectLeave(&pThis->CritSect);
     1210    if (RT_SUCCESS(rc))
     1211        rc = rc2;
     1212
     1213    if (RT_FAILURE(rc))
     1214        LogFlowFuncLeaveRC(rc);
     1215
     1216    return rc;
     1217}
     1218
     1219static DECLCALLBACK(int) drvAudioGetDataOut(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbFreeOut, uint32_t *pcSamplesLive)
     1220{
     1221    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    11691222    /* pcbFreeOut is optional. */
    11701223    /* pcSamplesLive is optional. */
     
    12341287    }
    12351288
    1236     /*
    1237      * Recording.
    1238      */
    1239     uint32_t cbAvailIn = 0;
    1240 
    1241     PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    1242     while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
    1243     {
    1244         /* Disabled? Skip it! */
    1245         if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    1246             continue;
    1247 
    1248         /* Call the host backend to capture the audio input data. */
    1249         uint32_t cSamplesCaptured;
    1250         int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn,
    1251                                                      &cSamplesCaptured);
    1252         if (RT_FAILURE(rc2))
    1253             continue;
    1254 
    1255         PPDMAUDIOGSTSTRMIN pGstStrmIn = pHstStrmIn->pGstStrmIn;
    1256         AssertPtrBreak(pGstStrmIn);
    1257 
    1258         if (pGstStrmIn->State.fActive)
    1259         {
    1260             cbAvailIn = RT_MAX(cbAvailIn, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf,
    1261                                                           AudioMixBufMixed(&pHstStrmIn->MixBuf)));
    1262 #ifdef DEBUG_andy
    1263             LogFlowFunc(("\t[%s] cbAvailIn=%RU32\n", pHstStrmIn->MixBuf.pszName, cbAvailIn));
    1264 #endif
    1265         }
    1266     }
    1267 
    12681289    if (RT_SUCCESS(rc))
    12691290    {
    12701291        if (cbFreeOut == UINT32_MAX)
    12711292            cbFreeOut = 0;
    1272 
    1273         if (pcbAvailIn)
    1274             *pcbAvailIn = cbAvailIn;
    12751293
    12761294        if (pcbFreeOut)
     
    17131731        if (RT_SUCCESS(rc))
    17141732            rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
     1733
     1734        if (RT_SUCCESS(rc))
     1735            pGstStrmOut->State.fActive = fEnable;
    17151736    }
    17161737    else /* Disable */
     
    17181739        if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    17191740        {
    1720             uint32_t cGstStrmsActive = 0;
     1741            size_t cGstStrmsActive = 0;
    17211742
    17221743            /*
     
    17381759
    17391760            /* Do we need to defer closing the host stream? */
    1740             if (cGstStrmsActive >= 1)
     1761            if (cGstStrmsActive)
     1762            {
     1763                LogFlowFunc(("Closing stream deferred: %zu guest stream(s) active\n", cGstStrmsActive));
    17411764                pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    17421765
    1743             /* Can we close the host stream now instead of deferring it? */
    1744             if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))
     1766                rc = VERR_AUDIO_STREAM_PENDING_DISABLE;
     1767            }
     1768            else
     1769            {
    17451770                rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    1746         }
    1747     }
    1748 
    1749     if (RT_SUCCESS(rc))
    1750         pGstStrmOut->State.fActive = fEnable;
     1771                if (RT_SUCCESS(rc))
     1772                    pGstStrmOut->State.fActive = fEnable;
     1773            }
     1774        }
     1775    }
    17511776
    17521777    LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
     
    20712096    pDrvIns->IBase.pfnQueryInterface                 = drvAudioQueryInterface;
    20722097    /* IAudioConnector. */
    2073     pThis->IAudioConnector.pfnQueryStatus            = drvAudioQueryStatus;
    20742098    pThis->IAudioConnector.pfnAddRefIn               = drvAudioAddRefIn;
    20752099    pThis->IAudioConnector.pfnAddRefOut              = drvAudioAddRefOut;
     
    20792103    pThis->IAudioConnector.pfnWrite                  = drvAudioWrite;
    20802104    pThis->IAudioConnector.pfnGetConfig              = drvAudioGetConfig;
     2105    pThis->IAudioConnector.pfnGetDataIn              = drvAudioGetDataIn;
     2106    pThis->IAudioConnector.pfnGetDataOut             = drvAudioGetDataOut;
    20812107    pThis->IAudioConnector.pfnIsActiveIn             = drvAudioIsActiveIn;
    20822108    pThis->IAudioConnector.pfnIsActiveOut            = drvAudioIsActiveOut;
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r60925 r61050  
    115115const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt);
    116116void DrvAudioClearBuf(PPDMPCMPROPS pPCMInfo, void *pvBuf, size_t cbBuf, uint32_t cSamples);
     117bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2);
    117118bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pPCMInfo, PPDMAUDIOSTREAMCFG pCfg);
    118119const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSource);
  • trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp

    r60925 r61050  
    205205bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
    206206{
     207    AssertPtrReturn(pProps, VERR_INVALID_POINTER);
     208    AssertPtrReturn(pCfg,   VERR_INVALID_POINTER);
     209
    207210    int cBits = 8;
    208211    bool fSigned = false;
     
    238241                  && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
    239242    return fEqual;
     243}
     244
     245bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2)
     246{
     247    AssertPtrReturn(pProps1, VERR_INVALID_POINTER);
     248    AssertPtrReturn(pProps2, VERR_INVALID_POINTER);
     249
     250    return    pProps1->uHz         == pProps2->uHz
     251           && pProps1->cChannels   == pProps2->cChannels
     252           && pProps1->fSigned     == pProps2->fSigned
     253           && pProps1->cBits       == pProps2->cBits
     254           && pProps1->fSwapEndian == pProps2->fSwapEndian;
    240255}
    241256
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r60925 r61050  
    636636    pStrm->BufAttr.maxlength   = (pStrm->BufAttr.tlength * 3) / 2;
    637637    pStrm->BufAttr.prebuf      = -1; /* Same as tlength */
    638     pStrm->BufAttr.minreq      = -1; /* Pulse should set something sensible for minreq on it's own */
     638
     639    /* Set minreq to 0, as we want to control ourselves when to start/stop the stream. */
     640    pStrm->BufAttr.minreq      = 0;
    639641
    640642    /* Note that the struct BufAttr is updated to the obtained values after this call! */
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