VirtualBox

Changeset 60925 in vbox for trunk


Ignore:
Timestamp:
May 10, 2016 1:27:44 PM (9 years ago)
Author:
vboxsync
Message:

Audio: Update on infrastructure:

  • More work on HDA stream interleaving + surround support
  • The mixer can now (optionally) act as a supplemental layer between audio connector interface and device emulation (where applicable)
  • Multiple LUN streams can be bound to a certain sink, which in turn then can be treated as separate input/output channels
  • Unified more code which was duplicated between different audio device emulations
  • Tiny bit of documentation

Work in progress.

Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r60368 r60925  
    2828
    2929#include <VBox/types.h>
     30#include <iprt/circbuf.h>
    3031#include <iprt/critsect.h>
    3132#include <iprt/list.h>
     
    5253typedef enum PDMAUDIOFMT
    5354{
    54     AUD_FMT_INVALID,
    55     AUD_FMT_U8,
    56     AUD_FMT_S8,
    57     AUD_FMT_U16,
    58     AUD_FMT_S16,
    59     AUD_FMT_U32,
    60     AUD_FMT_S32,
     55    PDMAUDIOFMT_INVALID,
     56    PDMAUDIOFMT_U8,
     57    PDMAUDIOFMT_S8,
     58    PDMAUDIOFMT_U16,
     59    PDMAUDIOFMT_S16,
     60    PDMAUDIOFMT_U32,
     61    PDMAUDIOFMT_S32,
    6162    /** Hack to blow the type up to 32-bit. */
    62     AUD_FMT_32BIT_HACK = 0x7fffffff
     63    PDMAUDIOFMT_32BIT_HACK = 0x7fffffff
    6364} PDMAUDIOFMT;
    6465
     
    152153
    153154/**
     155 * Audio stream (data) layout.
     156 */
     157typedef enum PDMAUDIOSTREAMLAYOUT
     158{
     159    /** Unknown access type; do not use. */
     160    PDMAUDIOSTREAMLAYOUT_UNKNOWN = 0,
     161    /** Non-interleaved access, that is, consecutive
     162     *  access to the data. */
     163    PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED,
     164    /** Interleaved access, where the data can be
     165     *  mixed together with data of other audio streams. */
     166    PDMAUDIOSTREAMLAYOUT_INTERLEAVED
     167} PDMAUDIOSTREAMLAYOUT, *PPDMAUDIOSTREAMLAYOUT;
     168
     169/** No stream channel data flags defined. */
     170#define PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE      0
     171
     172/**
     173 * Structure for keeping a stream channel data block around.
     174 */
     175typedef struct PDMAUDIOSTREAMCHANNELDATA
     176{
     177    /** Circular buffer for the channel data. */
     178    PRTCIRCBUF pCircBuf;
     179    size_t     cbAcq;
     180    /** Channel data flags. */
     181    uint32_t   fFlags;
     182} PDMAUDIOSTREAMCHANNELDATA, *PPDMAUDIOSTREAMCHANNELDATA;
     183
     184/**
     185 * Structure for a single channel of an audio stream.
     186 * An audio stream consists of one or multiple channels,
     187 * depending on the configuration.
     188 */
     189typedef struct PDMAUDIOSTREAMCHANNEL
     190{
     191    /** Channel ID. */
     192    uint8_t                   uChannel;
     193    /** Step size (in bytes) to the channel's next frame. */
     194    size_t                    cbStep;
     195    /** Frame size (in bytes) of this channel. */
     196    size_t                    cbFrame;
     197    /** Offset (in bytes) to first sample in the data block. */
     198    size_t                    cbFirst;
     199    /** Currente offset (in bytes) in the data stream. */
     200    size_t                    cbOff;
     201    /** Associated data buffer. */
     202    PDMAUDIOSTREAMCHANNELDATA Data;
     203} PDMAUDIOSTREAMCHANNEL, *PPDMAUDIOSTREAMCHANNEL;
     204
     205/**
    154206 * Structure for keeping an audio stream configuration.
    155207 */
     
    157209{
    158210    /** Friendly name of the stream. */
    159     const char               *pszName;
     211    char                     szName[64];
    160212    /** Direction of the stream. */
    161213    PDMAUDIODIR              enmDir;
     
    169221    /** Frequency in Hertz (Hz). */
    170222    uint32_t                 uHz;
    171     /** Number of channels (2 for stereo, 1 for mono). */
     223    /** Number of audio channels (2 for stereo, 1 for mono). */
    172224    uint8_t                  cChannels;
    173225    /** Audio format. */
     
    337389     */
    338390    int64_t                iFreqRatio;
    339     /* For quickly converting samples <-> bytes and
    340      * vice versa. */
     391    /** For quickly converting samples <-> bytes and vice versa. */
    341392    uint8_t                cShift;
    342393} PDMAUDIOMIXBUF;
     
    347398/** No flags being set. */
    348399#define PDMAUDIOSTRMSTS_FLAG_NONE            0
     400/** Whether this stream has been initialized by the
     401 *  backend or not. */
     402#define PDMAUDIOSTRMSTS_FLAG_INITIALIZED     RT_BIT_32(0)
    349403/** Whether this stream is enabled or disabled. */
    350 #define PDMAUDIOSTRMSTS_FLAG_ENABLED         RT_BIT_32(0)
     404#define PDMAUDIOSTRMSTS_FLAG_ENABLED         RT_BIT_32(1)
    351405/** Whether this stream has been paused or not. This also implies
    352406 *  that this is an enabled stream! */
    353 #define PDMAUDIOSTRMSTS_FLAG_PAUSED          RT_BIT_32(1)
     407#define PDMAUDIOSTRMSTS_FLAG_PAUSED          RT_BIT_32(2)
    354408/** Whether this stream was marked as being disabled
    355409 *  but there are still associated guest output streams
    356410 *  which rely on its data. */
    357 #define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32(2)
     411#define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32(3)
    358412/** Validation mask. */
    359 #define PDMAUDIOSTRMSTS_VALID_MASK           UINT32_C(0x00000007)
     413#define PDMAUDIOSTRMSTS_VALID_MASK           UINT32_C(0x0000000F)
    360414
    361415/**
     
    418472    bool                   fEmpty;
    419473    /** Name of this stream. */
    420     char                  *pszName;
     474    char                   szName[64];
    421475    /** Number of references to this stream. Only can be
    422476     *  destroyed if the reference count is reaching 0. */
    423     uint8_t                cRefs;
     477    uint32_t               cRefs;
    424478} PDMAUDIOGSTSTRMSTATE, *PPDMAUDIOGSTSTRMSTATE;
    425479
     
    515569/**
    516570 * Audio connector interface (up).
     571 ** @todo Get rid of the separate XXXIn and XXXOut methods and unify the In/Out structs with a union,
     572 **       so that we only have one guest and one host stream ultimately.
    517573 */
    518574typedef struct PDMIAUDIOCONNECTOR
    519575{
    520576    DECLR3CALLBACKMEMBER(int, pfnQueryStatus, (PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbAvailIn, uint32_t *pcbFreeOut, uint32_t *pcSamplesLive));
     577
     578    /**
     579     * Adds a reference to the specified input stream.
     580     *
     581     * @returns New reference count.
     582     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     583     * @param   pGstStrmIn      Pointer to guest input stream adding the reference to.
     584     */
     585    DECLR3CALLBACKMEMBER(uint32_t, pfnAddRefIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn));
     586
     587    /**
     588     * Adds a reference to the specified output stream.
     589     *
     590     * @returns New reference count.
     591     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     592     * @param   pGstStrmOut     Pointer to guest output stream adding the reference to.
     593     */
     594    DECLR3CALLBACKMEMBER(uint32_t, pfnAddRefOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut));
     595
     596    /**
     597     * Releases a reference from the input specified stream.
     598     *
     599     * @returns New reference count.
     600     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     601     * @param   pGstStrmIn      Pointer to guest input stream releasing a reference from.
     602     */
     603    DECLR3CALLBACKMEMBER(uint32_t, pfnReleaseIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn));
     604
     605    /**
     606     * Releases a reference from the output specified stream.
     607     *
     608     * @returns New reference count.
     609     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     610     * @param   pGstStrmOut     Pointer to guest output stream releasing a reference from.
     611     */
     612    DECLR3CALLBACKMEMBER(uint32_t, pfnReleaseOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut));
    521613
    522614    /**
     
    552644     * @param   pCfg            Where to store the host audio backend configuration data.
    553645     */
    554     DECLR3CALLBACKMEMBER(int, pfnGetConfiguration, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));
     646    DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));
    555647
    556648    /**
     
    616708     * @param   pInterface           Pointer to the interface structure containing the called function pointer.
    617709     * @param   pszName              Friendly name of this input stream.
    618      * @param   pCfg                 Pointer to PDMAUDIOSTREAMCFG to use.
    619710     * @param   ppGstStrmIn          Pointer where to return the guest guest input stream on success.
    620711     */
    621     DECLR3CALLBACKMEMBER(int, pfnCreateIn, (PPDMIAUDIOCONNECTOR pInterface, const char *pszName,
    622                                             PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn));
     712    DECLR3CALLBACKMEMBER(int, pfnCreateIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
     713                                            PPDMAUDIOGSTSTRMIN *ppGstStrmIn));
    623714    /**
    624715     * Creates a guest output stream.
     
    626717     * @returns VBox status code.
    627718     * @param   pInterface           Pointer to the interface structure containing the called function pointer.
    628      * @param   pszName              Friendly name of this output stream.
    629719     * @param   pCfg                 Pointer to PDMAUDIOSTREAMCFG to use.
    630720     * @param   ppGstStrmOut         Pointer where to return the guest guest input stream on success.
    631721     */
    632     DECLR3CALLBACKMEMBER(int, pfnCreateOut, (PPDMIAUDIOCONNECTOR pInterface, const char *pszName,
    633                                              PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut));
    634 
     722    DECLR3CALLBACKMEMBER(int, pfnCreateOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
     723                                             PPDMAUDIOGSTSTRMOUT *ppGstStrmOut));
    635724    /**
    636725     * Destroys a guest input stream.
     
    666755
    667756/** PDMIAUDIOCONNECTOR interface ID. */
    668 #define PDMIAUDIOCONNECTOR_IID                  "f0ef4012-ae89-4528-9dad-4ef496894df8"
     757#define PDMIAUDIOCONNECTOR_IID                  "5bba362c-092a-493b-854b-5d0ad3acecc4"
    669758
    670759
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp

    r60353 r60925  
    1919#include <VBox/log.h>
    2020
    21 #if 0
     21#if 1
    2222/*
    2323 * DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
     
    230230uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf)
    231231{
    232     AssertPtrReturn(pMixBuf, true);
     232    AssertPtrReturn(pMixBuf, 0);
    233233
    234234    uint32_t cAvail;
    235     if (pMixBuf->pParent) /* Child */
     235    if (pMixBuf->pParent) /* Is this a child buffer? */
    236236        cAvail = pMixBuf->cMixed;
    237237    else
     
    975975static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSamples, uint32_t *pcProcessed)
    976976{
    977     AssertPtrReturn(pDst, VERR_INVALID_POINTER);
    978     AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
     977    AssertPtrReturn(pDst,  VERR_INVALID_POINTER);
     978    AssertPtrReturn(pSrc,  VERR_INVALID_POINTER);
    979979    AssertReturn(cSamples, VERR_INVALID_PARAMETER);
    980980    /* pcProcessed is optional. */
     
    10211021
    10221022        Assert(offWrite + cToWrite <= pDst->cSamples);
    1023         Assert(offRead + cToRead <= pSrc->cSamples);
     1023        Assert(offRead  + cToRead <= pSrc->cSamples);
    10241024
    10251025        AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt)));
     
    10461046
    10471047    pSrc->cMixed     += cWrittenTotal;
     1048
    10481049    pDst->cProcessed += cWrittenTotal;
     1050
     1051#if 0
     1052    /**
     1053     * Note: pDst->cProcessed can be bigger than pDst->cSamples if there
     1054     *       was a wrap-around. In that case samples were lost,
     1055     *       e.g. not consumed (yet).
     1056     *
     1057     *       So adjust the current read/write offset to match the current
     1058     *       position, minus the dropped samples. */
     1059    if (pDst->cProcessed > pDst->cSamples)
     1060    {
     1061        LogFlowFunc(("%s: %RU32 / %RU32\n", pDst->pszName, pDst->cProcessed, pDst->cSamples));
     1062        pSrc->cMixed       = pDst->cSamples;
     1063        pDst->offReadWrite = 0;
     1064        pDst->cProcessed   = pDst->cSamples;
     1065    }
     1066#endif
     1067
    10491068#ifdef DEBUG
    10501069    s_cSamplesMixedTotal += cWrittenTotal;
     
    11351154
    11361155    AUDMIXBUF_LOG(("********************************************\n"));
    1137     AUDMIXBUF_LOG(("[PARENT] %s: offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
    1138                    pParent->pszName,
     1156    AUDMIXBUF_LOG(("[PARENT] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
     1157                   pParent->pszName, pParent->cSamples,
    11391158                   pParent->offReadWrite, pParent->cProcessed, pParent->cMixed,
    11401159                   AUDIOMIXBUF_S2B(pParent, 1)));
    11411160
     1161    size_t cChildren = 0;
     1162
    11421163    PPDMAUDIOMIXBUF pIter;
    11431164    RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
    11441165    {
    1145         AUDMIXBUF_LOG(("\t[CHILD] %s: offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
    1146                        pIter->pszName,
     1166        AUDMIXBUF_LOG(("\t[CHILD] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
     1167                       pIter->pszName, pIter->cSamples,
    11471168                       pIter->offReadWrite, pIter->cProcessed, pIter->cMixed,
    11481169                       AUDIOMIXBUF_S2B(pIter, 1)));
    1149     }
    1150     AUDMIXBUF_LOG(("Total samples mixed: %RU64\n", s_cSamplesMixedTotal));
     1170        cChildren++;
     1171    }
     1172    AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal));
    11511173    AUDMIXBUF_LOG(("********************************************\n"));
    11521174}
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r60353 r60925  
    44 *             emulations to achieve proper multiplexing from/to attached
    55 *             devices LUNs.
     6 *
     7 * This mixer acts as a layer between the audio connector interface and
     8 * the actual device emulation, providing mechanisms for audio sources (input) and
     9 * audio sinks (output).
     10 *
     11 * As audio driver instances are handled as LUNs on the device level, this
     12 * audio mixer then can take care of e.g. mixing various inputs/outputs to/from
     13 * a specific source/sink.
     14 *
     15 * How and which audio streams are connected to sinks/sources depends on how
     16 * the audio mixer has been set up.
     17 *
     18 * A sink can connect multiple output streams together, whereas a source
     19 * does this with input streams. Each sink / source consists of one or more
     20 * so-called mixer streams, which then in turn have pointers to the actual
     21 * PDM audio input/output streams.
    622 */
    723
     
    3248#include <iprt/string.h>
    3349
    34 static int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster);
    35 
    36 
    37 int AudioMixerAddSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink)
     50static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink);
     51static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster);
     52static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     53
     54static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream);
     55static void audioMixerStreamFree(PAUDMIXSTREAM pStream);
     56
     57int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink)
    3858{
    3959    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    4060    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    41     /** ppSink is optional. */
     61    /* ppSink is optional. */
    4262
    4363    int rc = VINF_SUCCESS;
     
    80100}
    81101
    82 int AudioMixerAddStreamIn(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMIN pStream,
    83                           uint32_t uFlags, PAUDMIXSTREAM *ppStream)
    84 {
    85     AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    86     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    87     /** @todo Add flag validation. */
    88     /* ppStream is optional. */
    89 
    90     int rc;
    91 
    92     if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */
    93         return VERR_TOO_MUCH_DATA;
    94 
    95     PAUDMIXSTREAM pMixStream
    96         = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));
    97     if (pMixStream)
    98     {
    99         pMixStream->pConn = pConnector;
    100         pMixStream->pIn   = pStream;
    101         /** @todo Process flags. */
    102 
    103         RTListAppend(&pSink->lstStreams, &pMixStream->Node);
    104         pSink->cStreams++;
    105 
    106         LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",
    107                      pSink->pszName, pMixStream, pSink->cStreams));
    108 
    109         /* Increase the stream's reference count to let others know
    110          * we're reyling on it to be around now. */
    111         pStream->State.cRefs++;
    112 
    113         if (ppStream)
    114             *ppStream = pMixStream;
    115 
    116         rc = VINF_SUCCESS;
    117     }
    118     else
    119         rc = VERR_NO_MEMORY;
    120 
    121     return rc;
    122 }
    123 
    124 int AudioMixerAddStreamOut(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMOUT pStream,
    125                            uint32_t uFlags, PAUDMIXSTREAM *ppStream)
    126 {
    127     AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    128     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    129     /** @todo Add flag validation. */
    130     /* ppStream is optional. */
    131 
    132     int rc;
    133 
    134     if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */
    135         return VERR_TOO_MUCH_DATA;
    136 
    137     PAUDMIXSTREAM pMixStream
    138         = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));
    139     if (pMixStream)
    140     {
    141         pMixStream->pConn = pConnector;
    142         pMixStream->pOut  = pStream;
    143         /** @todo Process flags. */
    144 
    145         RTListAppend(&pSink->lstStreams, &pMixStream->Node);
    146         pSink->cStreams++;
    147 
    148         LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",
    149                      pSink->pszName, pMixStream, pSink->cStreams));
    150 
    151         /* Increase the stream's reference count to let others know
    152          * we're reyling on it to be around now. */
    153         pStream->State.cRefs++;
    154 
    155         if (ppStream)
    156             *ppStream = pMixStream;
    157 
    158         rc = VINF_SUCCESS;
    159     }
    160     else
    161         rc = VERR_NO_MEMORY;
    162 
    163     return rc;
    164 }
    165 
    166 int AudioMixerControlStream(PAUDIOMIXER pMixer, PAUDMIXSTREAM pHandle)
    167 {
    168     return VERR_NOT_IMPLEMENTED;
    169 }
    170 
    171102int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer)
    172103{
     
    207138}
    208139
     140void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs)
     141{
     142    PAUDMIXSINK pSink;
     143    unsigned    iSink = 0;
     144
     145    pHlp->pfnPrintf(pHlp, "[Master] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", pMixer->pszName,
     146                    pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight, pMixer->VolMaster.fMuted);
     147
     148    RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
     149    {
     150        pHlp->pfnPrintf(pHlp, "[Sink %u] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", iSink, pSink->pszName,
     151                        pSink->Volume.uLeft, pSink->Volume.uRight, pSink->Volume.fMuted);
     152        ++iSink;
     153    }
     154}
     155
    209156void AudioMixerDestroy(PAUDIOMIXER pMixer)
    210157{
     
    216163    PAUDMIXSINK pSink, pSinkNext;
    217164    RTListForEachSafe(&pMixer->lstSinks, pSink, pSinkNext, AUDMIXSINK, Node)
    218         AudioMixerRemoveSink(pMixer, pSink);
    219 
    220     Assert(pMixer->cSinks == 0);
     165        audioMixerSinkDestroyInternal(pSink);
    221166
    222167    if (pMixer->pszName)
     
    227172
    228173    RTMemFree(pMixer);
    229 }
    230 
    231 static void audioMixerDestroySink(PAUDMIXSINK pSink)
     174    pMixer = NULL;
     175}
     176
     177int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg)
     178{
     179    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
     180    AssertPtrReturn(pCfg,   VERR_INVALID_POINTER);
     181
     182    /** @todo Perform a deep copy, if needed. */
     183    *pCfg = pMixer->devFmt;
     184
     185    return VINF_SUCCESS;
     186}
     187
     188void AudioMixerInvalidate(PAUDIOMIXER pMixer)
     189{
     190    AssertPtrReturnVoid(pMixer);
     191
     192    LogFlowFunc(("%s: Invalidating ...\n", pMixer->pszName));
     193
     194    /* Propagate new master volume to all connected sinks. */
     195    PAUDMIXSINK pSink;
     196    RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
     197    {
     198        int rc2 = audioMixerSinkUpdateVolume(pSink, &pMixer->VolMaster);
     199        AssertRC(rc2);
     200    }
     201}
     202
     203void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
     204{
     205    AssertPtrReturnVoid(pMixer);
     206    if (!pSink)
     207        return;
     208
     209    /** @todo Check if pSink is part of pMixer. */
     210
     211    AudioMixerSinkRemoveAllStreams(pSink);
     212
     213    Assert(pSink->cStreams == 0);
     214
     215    RTListNodeRemove(&pSink->Node);
     216
     217    Assert(pMixer->cSinks);
     218    pMixer->cSinks--;
     219
     220    LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n",
     221                 pMixer->pszName, pSink->pszName, pMixer->cSinks));
     222}
     223
     224int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg)
     225{
     226    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
     227    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     228
     229    /** @todo Perform a deep copy, if needed. */
     230    pMixer->devFmt = *pCfg;
     231
     232    return VINF_SUCCESS;
     233}
     234
     235/**
     236 * Sets the mixer's master volume.
     237 *
     238 * @returns IPRT status code.
     239 * @param   pMixer          Mixer to set master volume for.
     240 * @param   pVol            Volume to set.
     241 */
     242int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol)
     243{
     244    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
     245    AssertPtrReturn(pVol,   VERR_INVALID_POINTER);
     246
     247    pMixer->VolMaster = *pVol;
     248
     249    LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
     250                 pMixer->pszName, pVol->uLeft, pVol->uRight,
     251                 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));
     252
     253    AudioMixerInvalidate(pMixer);
     254    return VINF_SUCCESS;
     255}
     256
     257/*****************************************************************************
     258 * Mixer Sink implementation.
     259 *****************************************************************************/
     260
     261int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     262{
     263    AssertPtrReturn(pSink,   VERR_INVALID_POINTER);
     264    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     265
     266    if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */
     267        return VERR_NO_MORE_HANDLES;
     268
     269    /** @todo Check if stream already is assigned to (another) sink. */
     270
     271    RTListAppend(&pSink->lstStreams, &pStream->Node);
     272    pSink->cStreams++;
     273
     274    LogFlowFunc(("%s: cStreams=%RU8\n", pSink->pszName, pSink->cStreams));
     275
     276    return VINF_SUCCESS;
     277}
     278
     279static PDMAUDIOSTREAMCMD audioMixerSinkToStreamCmd(AUDMIXSINKCMD enmCmd)
     280{
     281    switch (enmCmd)
     282    {
     283        case AUDMIXSINKCMD_ENABLE:   return PDMAUDIOSTREAMCMD_ENABLE;
     284        case AUDMIXSINKCMD_DISABLE:  return PDMAUDIOSTREAMCMD_DISABLE;
     285        case AUDMIXSINKCMD_PAUSE:    return PDMAUDIOSTREAMCMD_PAUSE;
     286        case AUDMIXSINKCMD_RESUME:   return PDMAUDIOSTREAMCMD_RESUME;
     287        default:                     break;
     288    }
     289
     290    AssertMsgFailed(("Unsupported sink command %ld\n", enmCmd));
     291    return PDMAUDIOSTREAMCMD_UNKNOWN;
     292}
     293
     294int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd)
     295{
     296    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     297
     298    PDMAUDIOSTREAMCMD enmCmdStream = audioMixerSinkToStreamCmd(enmCmd);
     299    if (enmCmdStream == PDMAUDIOSTREAMCMD_UNKNOWN)
     300        return VERR_NOT_SUPPORTED;
     301
     302    int rc = VINF_SUCCESS;
     303
     304    PAUDMIXSTREAM pStream;
     305    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     306    {
     307        int rc2 = AudioMixerStreamCtl(pStream, enmCmdStream, AUDMIXSTRMCTL_FLAG_NONE);
     308        if (RT_SUCCESS(rc))
     309            rc = rc2;
     310        /* Keep going. Flag? */
     311    }
     312
     313    LogFlowFunc(("Sink=%s, Cmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));
     314    return rc;
     315}
     316
     317void AudioMixerSinkDestroy(PAUDMIXSINK pSink)
     318{
     319    audioMixerSinkDestroyInternal(pSink);
     320}
     321
     322static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink)
    232323{
    233324    AssertPtrReturnVoid(pSink);
     
    235326        return;
    236327
     328    LogFunc(("%s\n", pSink->pszName));
     329
     330    PAUDMIXSTREAM pStream, pStreamNext;
     331    RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
     332    {
     333        audioMixerSinkRemoveStreamInternal(pSink, pStream);
     334        audioMixerStreamDestroyInternal(pStream);
     335    }
     336
     337    Assert(pSink->cStreams == 0);
     338
    237339    if (pSink->pszName)
    238340        RTStrFree(pSink->pszName);
     
    241343}
    242344
    243 static void audioMixerDestroyStream(PAUDMIXSTREAM pStream)
    244 {
    245     AssertPtrReturnVoid(pStream);
    246     if (!pStream)
    247         return;
    248 
    249     RTMemFree(pStream);
    250 }
    251 
    252 int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg)
    253 {
    254     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    255     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    256 
    257     /** @todo Perform a deep copy, if needed. */
    258     *pCfg = pMixer->devFmt;
    259 
    260     return VINF_SUCCESS;
    261 }
    262 
    263 uint32_t AudioMixerGetStreamCount(PAUDIOMIXER pMixer)
    264 {
    265     AssertPtrReturn(pMixer, 0);
    266 
    267     uint32_t cStreams = 0;
    268 
    269     PAUDMIXSINK pSink;
    270     RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
    271         cStreams += pSink->cStreams;
    272 
    273     return cStreams;
    274 }
    275 
    276 void AudioMixerInvalidate(PAUDIOMIXER pMixer)
    277 {
    278     AssertPtrReturnVoid(pMixer);
    279 
    280     LogFlowFunc(("%s: Invalidating ...\n", pMixer->pszName));
    281 
    282     /* Propagate new master volume to all connected sinks. */
    283     PAUDMIXSINK pSink;
    284     RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
    285     {
    286         int rc2 = audioMixerUpdateSinkVolume(pSink, &pMixer->VolMaster);
    287         AssertRC(rc2);
    288     }
    289 }
    290 
    291 int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed)
     345PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex)
     346{
     347    AssertPtrReturn(pSink, NULL);
     348    AssertMsgReturn(uIndex < pSink->cStreams,
     349                    ("Index %RU8 exceeds stream count (%RU8)", uIndex, pSink->cStreams), NULL);
     350
     351    /* Slow lookup, d'oh. */
     352    PAUDMIXSTREAM pStream = RTListGetFirst(&pSink->lstStreams, AUDMIXSTREAM, Node);
     353    while (uIndex)
     354    {
     355        pStream = RTListGetNext(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node);
     356        uIndex--;
     357    }
     358
     359    AssertPtr(pStream);
     360    return pStream;
     361}
     362
     363uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink)
     364{
     365    if (!pSink)
     366        return 0;
     367
     368    return pSink->cStreams;
     369}
     370
     371int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    292372{
    293373    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    294374    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    295     AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
    296     /* pcbProcessed is optional. */
     375    AssertReturn(cbBuf,    VERR_INVALID_PARAMETER);
     376    /* pcbRead is optional. */
    297377
    298378    /** @todo Handle mixing operation enmOp! */
     
    303383
    304384    int rc = VERR_NOT_FOUND;
    305     uint32_t cbProcessed = 0;
    306 
    307     LogFlowFunc(("%s: pvBuf=%p, cbBuf=%zu\n", pSink->pszName, pvBuf, cbBuf));
     385    uint32_t cbRead = 0;
    308386
    309387    PAUDMIXSTREAM pStream;
    310388    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    311389    {
    312         if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->pIn))
     390        if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn))
    313391            continue;
    314392
     
    318396        while (cbToRead)
    319397        {
    320             uint32_t cbRead;
     398            uint32_t cbReadStrm;
    321399            AssertPtr(pStream->pConn);
    322             rc = pStream->pConn->pfnRead(pStream->pConn, pStream->pIn,
    323                                          (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbRead);
     400            rc = pStream->pConn->pfnRead(pStream->pConn, pStream->InOut.pIn,
     401                                         (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm);
    324402            if (   RT_FAILURE(rc)
    325                 || !cbRead)
     403                || !cbReadStrm)
    326404                break;
    327405
    328406            /** @todo Right now we only handle one stream (the last one added in fact). */
    329407
    330             AssertBreakStmt(cbRead <= cbToRead, rc = VERR_BUFFER_OVERFLOW);
    331             cbToRead -= cbRead;
    332             cbTotalRead += cbRead;
     408            AssertBreakStmt(cbReadStrm <= cbToRead, rc = VERR_BUFFER_OVERFLOW);
     409            cbToRead    -= cbReadStrm;
     410            cbTotalRead += cbReadStrm;
    333411        }
    334412
     
    336414            continue;
    337415
    338         cbProcessed = RT_MAX(cbProcessed, cbTotalRead);
     416        cbRead = RT_MAX(cbRead, cbTotalRead);
    339417    }
    340418
    341419    if (RT_SUCCESS(rc))
    342420    {
    343         memcpy(pvBuf, pvMixBuf, cbProcessed); /* @todo Use an intermediate mixing buffer per sink! */
    344 
    345         if (pcbProcessed)
    346             *pcbProcessed = cbProcessed;
     421        memcpy(pvBuf, pvMixBuf, cbRead); /* @todo Use an intermediate mixing buffer per sink! */
     422
     423        if (pcbRead)
     424            *pcbRead = cbRead;
    347425    }
    348426
    349427    RTMemFree(pvMixBuf);
    350428
    351     LogFlowFunc(("cbProcessed=%RU32, rc=%Rrc\n", cbProcessed, rc));
     429    Log3Func(("%s: cbRead=%RU32, rc=%Rrc\n", pSink->pszName, cbRead, rc));
    352430    return rc;
    353431}
    354432
    355 int AudioMixerProcessSinkOut(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed)
    356 {
    357     return VERR_NOT_IMPLEMENTED;
    358 }
    359 
    360 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
    361 {
    362     AssertPtrReturnVoid(pMixer);
    363     if (!pSink)
    364         return;
    365 
    366     PAUDMIXSTREAM pStream, pStreamNext;
    367     RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
    368         AudioMixerRemoveStream(pSink, pStream);
    369 
    370     Assert(pSink->cStreams == 0);
    371 
    372     RTListNodeRemove(&pSink->Node);
    373     Assert(pMixer->cSinks);
    374     pMixer->cSinks--;
    375 
    376     LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n",
    377                  pMixer->pszName, pSink->pszName, pMixer->cSinks));
    378 
    379     audioMixerDestroySink(pSink);
    380 }
    381 
    382 void AudioMixerRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     433static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
    383434{
    384435    AssertPtrReturnVoid(pSink);
     
    386437        return;
    387438
     439    /** @todo Check if pStream is part of pSink. */
     440
    388441    Assert(pSink->cStreams);
    389     RTListNodeRemove(&pStream->Node);
    390     pSink->cStreams--;
    391442
    392443#ifdef DEBUG
    393444    const char *pszStream = pSink->enmDir == AUDMIXSINKDIR_INPUT
    394                           ? pStream->pIn->MixBuf.pszName : pStream->pOut->MixBuf.pszName;
    395 
    396     LogFlowFunc(("%s: pStream=%s, cStreams=%RU8\n",
     445                          ? pStream->InOut.pIn->MixBuf.pszName : pStream->InOut.pOut->MixBuf.pszName;
     446
     447    LogFlowFunc(("%s: (Stream = %s), cStreams=%RU8\n",
    397448                 pSink->pszName, pszStream ? pszStream : "<Unnamed>", pSink->cStreams));
    398449#endif
    399450
    400     /* Decrease the reference count again. */
    401     switch (pSink->enmDir)
    402     {
    403         case AUDMIXSINKDIR_INPUT:
    404         {
    405             Assert(pStream->pIn->State.cRefs);
    406             pStream->pIn->State.cRefs--;
    407             break;
    408         }
    409 
    410         case AUDMIXSINKDIR_OUTPUT:
    411         {
    412             Assert(pStream->pOut->State.cRefs);
    413             pStream->pOut->State.cRefs--;
    414             break;
    415         }
    416 
    417         default:
    418             AssertMsgFailed(("Not implemented\n"));
    419             break;
    420     }
    421 
    422     audioMixerDestroyStream(pStream);
    423 }
    424 
    425 int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg)
    426 {
    427     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    428     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    429 
    430     /** @todo Perform a deep copy, if needed. */
    431     pMixer->devFmt = *pCfg;
     451    /* Remove stream from sink. */
     452    RTListNodeRemove(&pStream->Node);
     453
     454    Assert(pSink->cStreams);
     455    pSink->cStreams--;
     456}
     457
     458void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     459{
     460    audioMixerSinkRemoveStreamInternal(pSink, pStream);
     461}
     462
     463/**
     464 * Removes all attached streams from a given sink.
     465 *
     466 * @param pSink         Sink to remove attached streams from.
     467 */
     468void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink)
     469{
     470    if (!pSink)
     471        return;
     472
     473    LogFunc(("%s\n", pSink->pszName));
     474
     475    PAUDMIXSTREAM pStream, pStreamNext;
     476    RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
     477        audioMixerSinkRemoveStreamInternal(pSink, pStream);
     478
     479    Assert(pSink->cStreams == 0);
     480}
     481
     482int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps)
     483{
     484    AssertPtrReturn(pSink,     VERR_INVALID_POINTER);
     485    AssertPtrReturn(pPCMProps, VERR_INVALID_POINTER);
     486
     487    memcpy(&pSink->PCMProps, pPCMProps, sizeof(PDMPCMPROPS));
     488
     489    PAUDMIXSTREAM pStream;
     490    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     491    {
     492        /** @todo Invalidate mix buffers! */
     493    }
    432494
    433495    return VINF_SUCCESS;
    434496}
    435497
    436 static int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster)
     498/**
     499 * Set the volume of an individual sink.
     500 *
     501 * @returns IPRT status code.
     502 * @param   pSink           Sink to set volume for.
     503 * @param   pVol            Volume to set.
     504 */
     505int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol)
     506{
     507    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     508    AssertPtrReturn(pVol,  VERR_INVALID_POINTER);
     509    AssertPtr(pSink->pParent);
     510
     511    LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));
     512
     513    pSink->Volume = *pVol;
     514
     515    return audioMixerSinkUpdateVolume(pSink, &pSink->pParent->VolMaster);
     516}
     517
     518int AudioMixerSinkUpdate(PAUDMIXSINK pSink)
     519{
     520    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     521
     522    PAUDMIXSTREAM pStream;
     523    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     524    {
     525        uint32_t cbIn, cbOut;
     526        uint32_t cSamplesLive;
     527        int rc2 = pStream->pConn->pfnQueryStatus(pStream->pConn,
     528                                                 &cbIn, &cbOut, &cSamplesLive);
     529#ifdef DEBUG
     530        if (   cbIn
     531            || cbOut
     532            || cSamplesLive)
     533        {
     534            Log3Func(("cbIn=%RU32, cbOut=%RU32, cSamplesLive=%RU32, rc2=%Rrc\n", cbIn, cbOut, cSamplesLive, rc2));
     535        }
     536#endif
     537        if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
     538        {
     539            rc2 = pStream->pConn->pfnPlayOut(pStream->pConn, NULL /* pcSamplesPlayed */);
     540            if (RT_FAILURE(rc2))
     541                Log3Func(("rc2=%Rrc\n", rc2));
     542        }
     543        else if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
     544        {
     545            //int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */);
     546            //Log3Func(("rc2=%Rrc\n", rc2));
     547        }
     548        else
     549            AssertMsgFailed(("Direction not implemented\n"));
     550    }
     551
     552    return VINF_SUCCESS;
     553}
     554
     555static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster)
    437556{
    438557    AssertPtrReturn(pSink,      VERR_INVALID_POINTER);
     
    461580    {
    462581        if (fOut)
    463             AudioMixBufSetVolume(&pStream->pOut->MixBuf, &volSink);
     582            AudioMixBufSetVolume(&pStream->InOut.pOut->MixBuf, &volSink);
    464583        else
    465             AudioMixBufSetVolume(&pStream->pIn->MixBuf,  &volSink);
     584            AudioMixBufSetVolume(&pStream->InOut.pIn->MixBuf,  &volSink);
    466585    }
    467586
     
    469588}
    470589
    471 /** Set the master volume of the mixer. */
    472 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol)
    473 {
    474     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    475     AssertPtrReturn(pVol,   VERR_INVALID_POINTER);
    476 
    477     pMixer->VolMaster = *pVol;
    478 
    479     LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
    480                  pMixer->pszName, pVol->uLeft, pVol->uRight,
    481                  pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));
    482 
    483     AudioMixerInvalidate(pMixer);
     590int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     591{
     592    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     593    /* pcbWritten is optional. */
     594
     595    if (!pvBuf || !cbBuf)
     596    {
     597        if (pcbWritten)
     598            *pcbWritten = 0;
     599        return VINF_SUCCESS;
     600    }
     601
     602    uint32_t cbProcessed = 0;
     603
     604    PAUDMIXSTREAM pStream;
     605    RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     606    {
     607        int rc2 = pStream->pConn->pfnWrite(pStream->pConn, pStream->InOut.pOut, pvBuf, cbBuf, &cbProcessed);
     608        if (   RT_FAILURE(rc2)
     609            || cbProcessed < cbBuf)
     610        {
     611            LogFlowFunc(("rc=%Rrc, cbBuf=%RU32, cbProcessed=%RU32\n", rc2, cbBuf, cbProcessed));
     612        }
     613    }
     614
     615    if (pcbWritten)
     616        *pcbWritten = cbBuf; /* Always report back a complete write for now. */
     617
    484618    return VINF_SUCCESS;
    485619}
    486620
    487 /** Set the volume of an individual sink. */
    488 int AudioMixerSetSinkVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol)
    489 {
    490     AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    491     AssertPtrReturn(pVol,  VERR_INVALID_POINTER);
    492     AssertPtr(pSink->pParent);
    493 
    494     LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight));
    495 
    496     pSink->Volume = *pVol;
    497 
    498     return audioMixerUpdateSinkVolume(pSink, &pSink->pParent->VolMaster);
    499 }
    500 
    501 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs)
    502 {
    503     PAUDMIXSINK pSink;
    504     unsigned    iSink = 0;
    505 
    506     pHlp->pfnPrintf(pHlp, "[Master] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", pMixer->pszName,
    507                     pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight, pMixer->VolMaster.fMuted);
    508 
    509     RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
    510     {
    511         pHlp->pfnPrintf(pHlp, "[Sink %u] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", iSink, pSink->pszName,
    512                         pSink->Volume.uLeft, pSink->Volume.uRight, pSink->Volume.fMuted);
    513         ++iSink;
    514     }
    515 }
     621/*****************************************************************************
     622 * Mixer Stream implementation.
     623 *****************************************************************************/
     624
     625int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl)
     626{
     627    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     628    /** @todo Validate fCtl. */
     629
     630    int rc;
     631    switch (pStream->enmDir)
     632    {
     633        case PDMAUDIODIR_IN:
     634        {
     635            if (   enmCmd == PDMAUDIOSTREAMCMD_ENABLE
     636                || enmCmd == PDMAUDIOSTREAMCMD_DISABLE)
     637            {
     638                rc = pStream->pConn->pfnEnableIn(pStream->pConn, pStream->InOut.pIn,
     639                                                 enmCmd == PDMAUDIOSTREAMCMD_ENABLE);
     640            }
     641            else
     642                AssertFailed();
     643            break;
     644        }
     645
     646        case PDMAUDIODIR_OUT:
     647        {
     648            if (   enmCmd == PDMAUDIOSTREAMCMD_ENABLE
     649                || enmCmd == PDMAUDIOSTREAMCMD_DISABLE)
     650            {
     651                rc = pStream->pConn->pfnEnableOut(pStream->pConn, pStream->InOut.pOut,
     652                                                  enmCmd == PDMAUDIOSTREAMCMD_ENABLE);
     653            }
     654            else
     655                AssertFailed();
     656            break;
     657        }
     658
     659        default:
     660            AssertMsgFailed(("Not implemented\n"));
     661            break;
     662    }
     663
     664    return rc;
     665}
     666
     667int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConn, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream)
     668{
     669    AssertPtrReturn(pConn, VERR_INVALID_POINTER);
     670    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
     671    /** @todo Validate fFlags. */
     672    /* ppStream is optional. */
     673
     674    PAUDMIXSTREAM pMixStream = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));
     675    if (!pMixStream)
     676        return VERR_NO_MEMORY;
     677
     678    pMixStream->pszName = RTStrDup(pCfg->szName);
     679    if (!pMixStream->pszName)
     680    {
     681        RTMemFree(pMixStream);
     682        return VERR_NO_MEMORY;
     683    }
     684
     685    int rc;
     686    if (pCfg->enmDir == PDMAUDIODIR_IN)
     687    {
     688        PPDMAUDIOGSTSTRMIN pGstStrm;
     689        rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm);
     690        if (RT_SUCCESS(rc))
     691        {
     692            pMixStream->InOut.pIn = pGstStrm;
     693
     694            /* Increase the stream's reference count to let others know
     695             * we're reyling on it to be around now. */
     696            pConn->pfnAddRefIn(pConn, pGstStrm);
     697        }
     698    }
     699    else if (pCfg->enmDir == PDMAUDIODIR_OUT)
     700    {
     701        PPDMAUDIOGSTSTRMOUT pGstStrm;
     702        rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm);
     703        if (RT_SUCCESS(rc))
     704        {
     705            pMixStream->InOut.pOut = pGstStrm;
     706
     707            /* Increase the stream's reference count to let others know
     708             * we're reyling on it to be around now. */
     709            pConn->pfnAddRefOut(pConn, pGstStrm);
     710        }
     711    }
     712    else
     713        rc = VERR_NOT_SUPPORTED;
     714
     715    if (RT_SUCCESS(rc))
     716    {
     717        pMixStream->fFlags = fFlags;
     718        pMixStream->enmDir = pCfg->enmDir;
     719        pMixStream->pConn  = pConn;
     720
     721        if (ppStream)
     722            *ppStream = pMixStream;
     723    }
     724    else if (pMixStream)
     725    {
     726        RTStrFree(pMixStream->pszName);
     727        pMixStream->pszName = NULL;
     728
     729        RTMemFree(pMixStream);
     730        pMixStream = NULL;
     731    }
     732
     733    return rc;
     734}
     735
     736static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream)
     737{
     738    if (!pStream)
     739        return;
     740
     741    LogFunc(("%s\n", pStream->pszName));
     742
     743    if (pStream->pConn) /* Stream has a connector interface present? */
     744    {
     745        if (   pStream->enmDir == PDMAUDIODIR_IN
     746            && pStream->pConn->pfnDestroyIn)
     747        {
     748            if (pStream->InOut.pIn)
     749            {
     750                pStream->pConn->pfnReleaseIn(pStream->pConn, pStream->InOut.pIn);
     751                pStream->pConn->pfnDestroyIn(pStream->pConn, pStream->InOut.pIn);
     752            }
     753        }
     754        else if (   pStream->enmDir == PDMAUDIODIR_OUT
     755                 && pStream->pConn->pfnDestroyOut)
     756        {
     757            if (pStream->InOut.pOut)
     758            {
     759                pStream->pConn->pfnReleaseOut(pStream->pConn, pStream->InOut.pOut);
     760                pStream->pConn->pfnDestroyOut(pStream->pConn, pStream->InOut.pOut);
     761            }
     762        }
     763        else
     764            AssertFailed();
     765    }
     766
     767    audioMixerStreamFree(pStream);
     768}
     769
     770void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream)
     771{
     772    audioMixerStreamDestroyInternal(pStream);
     773}
     774
     775static void audioMixerStreamFree(PAUDMIXSTREAM pStream)
     776{
     777    if (pStream)
     778    {
     779        LogFunc(("%s\n", pStream->pszName));
     780
     781        if (pStream->pszName)
     782        {
     783            RTStrFree(pStream->pszName);
     784            pStream->pszName = NULL;
     785        }
     786
     787        RTMemFree(pStream);
     788        pStream = NULL;
     789    }
     790}
     791
     792bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream)
     793{
     794    if (!pStream)
     795        return false;
     796
     797    bool fIsValid;
     798    switch (pStream->enmDir)
     799    {
     800        case PDMAUDIODIR_IN:
     801        {
     802            fIsValid = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn);
     803            break;
     804        }
     805
     806        case PDMAUDIODIR_OUT:
     807        {
     808            fIsValid = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut);
     809            break;
     810        }
     811
     812        default:
     813            fIsValid = false;
     814            AssertMsgFailed(("Not implemented\n"));
     815            break;
     816    }
     817
     818    return fIsValid;
     819}
     820
     821bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream)
     822{
     823    if (!pStream)
     824        return false;
     825
     826    bool fIsValid;
     827    switch (pStream->enmDir)
     828    {
     829        case PDMAUDIODIR_IN:
     830        {
     831            fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn);
     832            break;
     833        }
     834
     835        case PDMAUDIODIR_OUT:
     836        {
     837            fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut);
     838            break;
     839        }
     840
     841        default:
     842            fIsValid = false;
     843            AssertMsgFailed(("Not implemented\n"));
     844            break;
     845    }
     846
     847    return fIsValid;
     848}
     849
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r59275 r60925  
    2424#include <VBox/vmm/pdmaudioifs.h>
    2525
     26/**
     27 * Structure for maintaining an audio mixer instance.
     28 */
    2629typedef struct AUDIOMIXER
    2730{
     
    4043} AUDIOMIXER, *PAUDIOMIXER;
    4144
     45/** No flags specified. */
     46#define AUDMIXSTREAM_FLAG_NONE                  0
     47
     48/**
     49 * Structure for maintaining an audio mixer stream.
     50 */
    4251typedef struct AUDMIXSTREAM
    4352{
     53    /** List node. */
    4454    RTLISTNODE              Node;
     55    /** Name of this stream. */
     56    char                   *pszName;
     57    /** Stream flags of type AUDMIXSTREAM_FLAG_. */
     58    uint32_t                fFlags;
     59    /** Pointer to audio connector being used. */
    4560    PPDMIAUDIOCONNECTOR     pConn;
     61    /** Audio direction of this stream. */
     62    PDMAUDIODIR             enmDir;
     63    /** Union of PDM input/output streams for this stream. */
    4664    union
    4765    {
    4866        PPDMAUDIOGSTSTRMIN  pIn;
    4967        PPDMAUDIOGSTSTRMOUT pOut;
    50     };
     68    } InOut;
    5169} AUDMIXSTREAM, *PAUDMIXSTREAM;
    5270
     71/**
     72 * Audio mixer sink direction.
     73 */
    5374typedef enum AUDMIXSINKDIR
    5475{
     
    6081} AUDMIXSINKDIR;
    6182
     83/**
     84 * Audio mixer sink command.
     85 */
     86typedef enum AUDMIXSINKCMD
     87{
     88    /** Unknown command, do not use. */
     89    AUDMIXSINKCMD_UNKNOWN = 0,
     90    /** Enables the sink. */
     91    AUDMIXSINKCMD_ENABLE,
     92    /** Disables the sink. */
     93    AUDMIXSINKCMD_DISABLE,
     94    /** Pauses the sink. */
     95    AUDMIXSINKCMD_PAUSE,
     96    /** Resumes the sink. */
     97    AUDMIXSINKCMD_RESUME,
     98    /** Hack to blow the type up to 32-bit. */
     99    AUDMIXSINKCMD_32BIT_HACK = 0x7fffffff
     100} AUDMIXSINKCMD;
     101
     102/**
     103 * Structure for maintaining an audio mixer sink.
     104 */
    62105typedef struct AUDMIXSINK
    63106{
    64107    RTLISTNODE              Node;
     108    /** Pointer to mixer object this sink is bound to. */
     109    PAUDIOMIXER             pParent;
    65110    /** Name of this sink. */
    66111    char                   *pszName;
     
    68113     *  if this sink handles input or output. */
    69114    AUDMIXSINKDIR           enmDir;
    70     /** Pointer to mixer object this sink is bound
    71      *  to. */
    72     PAUDIOMIXER             pParent;
     115    /** The sink's PCM format. */
     116    PDMPCMPROPS             PCMProps;
    73117    /** Number of streams assigned. */
    74118    uint8_t                 cStreams;
    75119    /** List of assigned streams. */
     120    /** @todo Use something faster -- vector maybe? */
    76121    RTLISTANCHOR            lstStreams;
    77122    /** This sink's mixing buffer. */
     
    82127} AUDMIXSINK, *PAUDMIXSINK;
    83128
     129/**
     130 * Audio mixer operation.
     131 */
    84132typedef enum AUDMIXOP
    85133{
    86     AUDMIXOP_NONE = 0,
     134    /** Invalid operation, do not use. */
     135    AUDMIXOP_INVALID = 0,
    87136    AUDMIXOP_COPY,
    88137    AUDMIXOP_BLEND,
     
    91140} AUDMIXOP;
    92141
     142/** No flags specified. */
     143#define AUDMIXSTRMCTL_FLAG_NONE         0
    93144
    94 int AudioMixerAddSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink);
    95 int AudioMixerAddStreamIn(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMIN pStream, uint32_t uFlags, PAUDMIXSTREAM *ppStream);
    96 int AudioMixerAddStreamOut(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMOUT pStream, uint32_t uFlags, PAUDMIXSTREAM *ppStream);
    97 int AudioMixerControlStream(AUDMIXSTREAM pHandle); /** @todo Implement me. */
    98145int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer);
     146int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink);
    99147void AudioMixerDestroy(PAUDIOMIXER pMixer);
    100148int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg);
    101 uint32_t AudioMixerGetStreamCount(PAUDIOMIXER pMixer);
    102149void AudioMixerInvalidate(PAUDIOMIXER pMixer);
    103 int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed);
    104 int AudioMixerProcessSinkOut(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed);
    105150void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
    106 void AudioMixerRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    107151int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg);
    108152int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol);
    109 int AudioMixerSetSinkVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
    110153void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
     154
     155int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     156int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd);
     157void AudioMixerSinkDestroy(PAUDMIXSINK pSink);
     158PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
     159uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink);
     160int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
     161void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     162void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink);
     163int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps);
     164int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
     165int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
     166int AudioMixerSinkUpdate(PAUDMIXSINK pSink);
     167
     168int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream);
     169int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl);
     170void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream);
     171bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream);
     172bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream);
    111173
    112174#endif /* AUDIO_MIXER_H */
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r60361 r60925  
    5252#define AC97_SSM_VERSION 1
    5353
     54#define AC97_TIMER_HZ 200
     55
    5456#ifdef VBOX
    5557# define SOFT_VOLUME /** @todo Get rid of this crap. */
     
    5860#endif
    5961
     62/** @todo Use AC97_ prefixes! */
    6063#define SR_FIFOE RT_BIT(4)          /* rwc, FIFO error. */
    6164#define SR_BCIS  RT_BIT(3)          /* rwc, Buffer completion interrupt status. */
     
    113116/** @name Buffer Descriptor
    114117 * @{ */
    115 #define BD_IOC RT_BIT(31)          /**< Interrupt on Completion */
    116 #define BD_BUP RT_BIT(30)          /**< Buffer Underrun Policy */
     118#define BD_IOC RT_BIT(31)          /**< Interrupt on Completion. */
     119#define BD_BUP RT_BIT(30)          /**< Buffer Underrun Policy. */
     120
     121#define BD_MAX_LEN_MASK 0xFFFE
    117122/** @} */
    118123
    119 #define EACS_VRA 1
    120 #define EACS_VRM 8
     124/** @name Extended Audio Status and Control Register
     125 * @{ */
     126#define EACS_VRA 1                 /**< Variable Rate Audio (4.2.1.1). */
     127#define EACS_VRM 8                 /**< Variable Rate Mic Audio (4.2.1.1). */
     128/** @} */
    121129
    122130#define VOL_MASK 0x1f
     
    193201
    194202/** Emits registers for a specific (Native Audio Bus Master BAR) NABMBAR. */
    195 #define AC97_NABMBAR_REGS(prefix, off) \
    196     enum {                             \
    197         prefix ## _BDBAR = off,        \
    198         prefix ## _CIV   = off + 4,    \
    199         prefix ## _LVI   = off + 5,    \
    200         prefix ## _SR    = off + 6,    \
    201         prefix ## _PICB  = off + 8,    \
    202         prefix ## _PIV   = off + 10,   \
    203         prefix ## _CR    = off + 11    \
     203#define AC97_NABMBAR_REGS(prefix, off)                                    \
     204    enum {                                                                \
     205        prefix ## _BDBAR = off,      /* Buffer Descriptor Base Address */ \
     206        prefix ## _CIV   = off + 4,  /* Current Index Value */            \
     207        prefix ## _LVI   = off + 5,  /* Last Valid Index */               \
     208        prefix ## _SR    = off + 6,  /* Status Register */                \
     209        prefix ## _PICB  = off + 8,  /* Position in Current Buffer */     \
     210        prefix ## _PIV   = off + 10, /* Prefetched Index Value */         \
     211        prefix ## _CR    = off + 11  /* Control Register */               \
    204212    }
    205213
     
    264272typedef struct AC97STREAMSTATE
    265273{
    266     /* Nothing yet. */
     274    /** Temporary FIFO write buffer. */
     275    R3PTRTYPE(uint8_t *) au8FIFOW;
     276    /** Size of the temporary FIFO write buffer. */
     277    uint32_t             cbFIFOW;
     278    /** Current write offset in FIFO write buffer. */
     279    uint32_t             offFIFOW;
     280    uint8_t              Padding;
    267281} AC97STREAMSTATE, *PAC97STREAMSTATE;
    268282
     
    286300{
    287301    /** PCM line input stream. */
    288     R3PTRTYPE(PPDMAUDIOGSTSTRMIN)      pStrmIn;
     302    R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn;
    289303    /** Mixer handle for line input stream. */
    290     R3PTRTYPE(PAUDMIXSTREAM)           phStrmIn;
     304    R3PTRTYPE(PAUDMIXSTREAM)      pMixStrm;
    291305} AC97INPUTSTREAM, *PAC97INPUTSTREAM;
    292306
     
    294308{
    295309    /** PCM output stream. */
    296     R3PTRTYPE(PPDMAUDIOGSTSTRMOUT)     pStrmOut;
     310    R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut;
    297311    /** Mixer handle for output stream. */
    298     R3PTRTYPE(PAUDMIXSTREAM)           phStrmOut;
     312    R3PTRTYPE(PAUDMIXSTREAM)       pMixStrm;
    299313} AC97OUTPUTSTREAM, *PAC97OUTPUTSTREAM;
    300314
     
    335349    /** R3 Pointer to the device instance. */
    336350    PPDMDEVINSR3            pDevInsR3;
    337     /** Global Control (Bus Master Control Register) */
     351    /** Global Control (Bus Master Control Register). */
    338352    uint32_t                glob_cnt;
    339     /** Global Status (Bus Master Control Register) */
     353    /** Global Status (Bus Master Control Register). */
    340354    uint32_t                glob_sta;
    341     /** Codec Access Semaphore Register (Bus Master Control Register) */
     355    /** Codec Access Semaphore Register (Bus Master Control Register). */
    342356    uint32_t                cas;
    343357    uint32_t                last_samp;
     
    379393    /** Base port of the I/O space region. */
    380394    RTIOPORT                IOPortBase[2];
    381     /** Pointer to temporary scratch read/write buffer. */
    382     R3PTRTYPE(uint8_t *)    pvReadWriteBuf;
    383     /** Size of the temporary scratch read/write buffer. */
    384     uint32_t                cbReadWriteBuf;
    385395    /** Codec model. */
    386396    uint32_t                uCodecModel;
     
    393403#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    394404
     405static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource);
     406static void ichac97CloseOut(PAC97STATE pThis);
    395407DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
     408static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm);
    396409static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
    397410#ifndef VBOX_WITH_AUDIO_CALLBACKS
    398411static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
    399412#endif
    400 static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed);
     413static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbElapsed);
    401414
    402415static void ichac97WarmReset(PAC97STATE pThis)
     
    410423}
    411424
     425DECLINLINE(PAUDMIXSINK) ichac97IndexToSink(PAC97STATE pThis, uint8_t uIndex)
     426{
     427    AssertPtrReturn(pThis, NULL);
     428
     429    switch (uIndex)
     430    {
     431        case PI_INDEX: return pThis->pSinkLineIn; break;
     432        case PO_INDEX: return pThis->pSinkOutput; break;
     433        case MC_INDEX: return pThis->pSinkMicIn;  break;
     434        default:       break;
     435    }
     436
     437    AssertMsgFailed(("Wrong index %RU8\n", uIndex));
     438    return NULL;
     439}
     440
    412441/** Fetches the buffer descriptor at _CIV. */
    413 static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStrmSt)
     442static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStream)
    414443{
    415444    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    416     PAC97BMREGS pRegs   = &pStrmSt->Regs;
     445    PAC97BMREGS pRegs   = &pStream->Regs;
    417446
    418447    uint32_t u32[2];
     
    426455    pRegs->bd.ctl_len = RT_H2LE_U32(u32[1]);
    427456#endif
    428     pRegs->picb       = pRegs->bd.ctl_len & 0xffff;
     457    pRegs->picb       = pRegs->bd.ctl_len & BD_MAX_LEN_MASK;
    429458    LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
    430459                  pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16,
    431                   pRegs->bd.ctl_len & 0xffff, (pRegs->bd.ctl_len & 0xffff) << 1));
     460                  pRegs->bd.ctl_len & BD_MAX_LEN_MASK,
     461                 (pRegs->bd.ctl_len & BD_MAX_LEN_MASK) << 1)); /** @todo r=andy Assumes 16bit samples. */
    432462}
    433463
     
    435465 * Update the BM status register
    436466 */
    437 static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t new_sr)
     467static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStream, uint32_t new_sr)
    438468{
    439469    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    440     PAC97BMREGS pRegs   = &pStrmSt->Regs;
    441 
    442     bool fSignal   = false;
    443     bool iIrqLevel;
     470    PAC97BMREGS pRegs   = &pStream->Regs;
     471
     472    bool fSignal = false;
     473    int  iIRQL;
    444474
    445475    uint32_t new_mask = new_sr & SR_INT_MASK;
     
    453483        if (!new_mask)
    454484        {
    455             fSignal   = true;
    456             iIrqLevel = 0;
     485            fSignal = true;
     486            iIRQL  = 0;
    457487        }
    458488        else if ((new_mask & SR_LVBCI) && (pRegs->cr & CR_LVBIE))
    459489        {
    460             fSignal   = true;
    461             iIrqLevel = 1;
     490            fSignal = true;
     491            iIRQL  = 1;
    462492        }
    463493        else if ((new_mask & SR_BCIS) && (pRegs->cr & CR_IOCE))
    464494        {
    465             fSignal   = true;
    466             iIrqLevel = 1;
     495            fSignal = true;
     496            iIRQL  = 1;
    467497        }
    468498    }
     
    470500    pRegs->sr = new_sr;
    471501
    472     LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, iIrqLevel=%d\n",
    473                  pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iIrqLevel));
     502    LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, IRQL=%d\n",
     503                 pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iIRQL));
    474504
    475505    if (fSignal)
    476506    {
    477         if (iIrqLevel)
    478             pThis->glob_sta |=  masks[pStrmSt->u8Strm];
     507        if (iIRQL)
     508            pThis->glob_sta |=  masks[pStream->u8Strm];
    479509        else
    480             pThis->glob_sta &= ~masks[pStrmSt->u8Strm];
    481 
    482         LogFlowFunc(("set irq level=%d\n", !!iIrqLevel));
    483         PDMDevHlpPCISetIrq(pDevIns, 0, !!iIrqLevel);
    484     }
    485 }
    486 
    487 static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fActive)
     510            pThis->glob_sta &= ~masks[pStream->u8Strm];
     511
     512        LogFlowFunc(("Setting IRQ level=%d\n", iIRQL));
     513        PDMDevHlpPCISetIrq(pDevIns, 0, iIRQL);
     514    }
     515}
     516
     517static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStream, bool fActive)
    488518{
    489519    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    490     AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
    491 
    492     LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStrmSt->u8Strm, fActive));
    493 
    494     int rc = VINF_SUCCESS;
    495 
    496     PAC97DRIVER pDrv;
    497     switch (pStrmSt->u8Strm)
    498     {
    499         case PI_INDEX:
    500             RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    501             {
    502                 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
    503                                                         pDrv->LineIn.pStrmIn, fActive);
    504                 if (RT_SUCCESS(rc))
    505                     rc = rc2;
    506             }
    507             break;
    508 
    509         case PO_INDEX:
    510             RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    511             {
    512                 int rc2 = pDrv->pConnector->pfnEnableOut(pDrv->pConnector,
    513                                                          pDrv->Out.pStrmOut, fActive);
    514                 if (RT_SUCCESS(rc))
    515                     rc = rc2;
    516             }
    517             break;
    518 
    519         case MC_INDEX:
    520             RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    521             {
    522                 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
    523                                                         pDrv->MicIn.pStrmIn, fActive);
    524                 if (RT_SUCCESS(rc))
    525                     rc = rc2;
    526             }
    527             break;
    528 
    529         default:
    530             AssertMsgFailed(("Wrong index %RU32\n", pStrmSt->u8Strm));
    531             rc = VERR_NOT_SUPPORTED;
    532             break;
    533     }
    534 
    535     return rc;
    536 }
    537 
    538 static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStrmSt)
     520    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     521
     522    LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStream->u8Strm, fActive));
     523
     524    return AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
     525                             fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     526}
     527
     528static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStream)
    539529{
    540530    AssertPtrReturnVoid(pThis);
    541     AssertPtrReturnVoid(pStrmSt);
     531    AssertPtrReturnVoid(pStream);
    542532
    543533    LogFlowFuncEnter();
    544534
    545     PAC97BMREGS pRegs = &pStrmSt->Regs;
     535    PAC97BMREGS pRegs = &pStream->Regs;
    546536
    547537    pRegs->bdbar    = 0;
     
    549539    pRegs->lvi      = 0;
    550540
    551     ichac97StreamUpdateStatus(pThis, pStrmSt, SR_DCH); /** @todo Do we need to do that? */
     541    ichac97StreamUpdateStatus(pThis, pStream, SR_DCH); /** @todo Do we need to do that? */
    552542
    553543    pRegs->picb     = 0;
     
    556546    pRegs->bd_valid = 0;
    557547
    558     int rc = ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
     548    int rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */);
    559549    AssertRC(rc);
    560550
    561551    RT_ZERO(pThis->silence);
     552}
     553
     554static void ichac97StreamDestroy(PAC97STREAM pStream)
     555{
     556    if (pStream->State.au8FIFOW)
     557    {
     558        Assert(pStream->State.cbFIFOW);
     559        RTMemFree(pStream->State.au8FIFOW);
     560        pStream->State.au8FIFOW = NULL;
     561    }
     562
     563    pStream->State.cbFIFOW  = 0;
     564    pStream->State.offFIFOW = 0;
     565}
     566
     567static void ichac97StreamsDestroy(PAC97STATE pThis)
     568{
     569    LogFlowFuncEnter();
     570
     571    ichac97CloseIn(pThis, PDMAUDIORECSOURCE_LINE);
     572    ichac97CloseIn(pThis, PDMAUDIORECSOURCE_MIC);
     573    ichac97CloseOut(pThis);
     574
     575    ichac97StreamDestroy(&pThis->StrmStLineIn);
     576    ichac97StreamDestroy(&pThis->StrmStMicIn);
     577    ichac97StreamDestroy(&pThis->StrmStOut);
     578}
     579
     580static int ichac97StreamsInit(PAC97STATE pThis)
     581{
     582    LogFlowFuncEnter();
     583
     584    ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
     585    ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
     586    ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
     587
     588    return VINF_SUCCESS;
    562589}
    563590
     
    589616}
    590617
    591 static DECLCALLBACK(void) ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
    592 {
    593     NOREF(pThis);
    594     NOREF(enmRecSource);
     618static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
     619{
     620    AssertPtrReturnVoid(pThis);
     621
    595622    LogFlowFuncEnter();
    596 }
    597 
    598 static DECLCALLBACK(void) ichac97CloseOut(PAC97STATE pThis)
    599 {
    600     NOREF(pThis);
    601     LogFlowFuncEnter();
    602 }
    603 
    604 static int ichac97OpenIn(PAC97STATE pThis,
    605                          const char *pszName, PDMAUDIORECSOURCE enmRecSource,
    606                          PPDMAUDIOSTREAMCFG pCfg)
    607 {
    608     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    609     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    610     AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    611623
    612624    PAUDMIXSINK pSink;
     
    621633        default:
    622634            AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
    623             return VERR_NOT_SUPPORTED;
    624     }
    625 
    626     int rc = VINF_SUCCESS;
     635            return;
     636    }
    627637
    628638    PAC97DRIVER pDrv;
    629639    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    630640    {
    631         char *pszDesc;
    632         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
    633         {
    634             rc = VERR_NO_MEMORY;
    635             break;
    636         }
    637 
    638641        PAC97INPUTSTREAM pStrmIn;
    639642        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
     
    642645            pStrmIn = &pDrv->LineIn;
    643646
    644         int rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, pCfg, &pStrmIn->pStrmIn);
    645         LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2));
    646         if (RT_SUCCESS(rc2))
    647         {
    648             AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn);
    649             rc2 = AudioMixerAddStreamIn(pSink,
    650                                         pDrv->pConnector, pStrmIn->pStrmIn,
    651                                         0 /* uFlags */, &pStrmIn->phStrmIn);
    652         }
    653 
    654         if (RT_SUCCESS(rc))
    655             rc = rc2;
    656 
    657         RTStrFree(pszDesc);
    658     }
    659 
    660     LogFlowFuncLeaveRC(rc);
    661     return rc;
    662 }
    663 
    664 static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     647        AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm);
     648        AudioMixerStreamDestroy(pStrmIn->pMixStrm);
     649        pStrmIn->pMixStrm = NULL;
     650    }
     651}
     652
     653static void ichac97CloseOut(PAC97STATE pThis)
     654{
     655    AssertPtrReturnVoid(pThis);
     656
     657    LogFlowFuncEnter();
     658
     659    PAC97DRIVER pDrv;
     660    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     661    {
     662        AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     663        AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
     664        pDrv->Out.pMixStrm = NULL;
     665    }
     666}
     667
     668static int ichac97OpenIn(PAC97STATE pThis,
     669                         const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg)
    665670{
    666671    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     
    668673    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    669674
    670     int rc = VINF_SUCCESS;
    671     char *pszDesc;
     675    PAUDMIXSINK pSink;
     676    switch (enmRecSource)
     677    {
     678        case PDMAUDIORECSOURCE_MIC:
     679            pSink = pThis->pSinkMicIn;
     680            break;
     681        case PDMAUDIORECSOURCE_LINE:
     682            pSink = pThis->pSinkLineIn;
     683            break;
     684        default:
     685            AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
     686            return VERR_NOT_SUPPORTED;
     687    }
     688
     689    /* Update the sink's format. */
     690    PDMPCMPROPS PCMProps;
     691    int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps);
     692    if (RT_SUCCESS(rc))
     693        rc = AudioMixerSinkSetFormat(pSink, &PCMProps);
     694
     695    if (RT_FAILURE(rc))
     696        return rc;
    672697
    673698    PAC97DRIVER pDrv;
    674699    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    675700    {
    676         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
    677                          pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
    678         {
    679             rc = VERR_NO_MEMORY;
    680             break;
    681         }
    682 
    683         int rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
    684         LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2));
     701        if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s", pDrv->uLUN, pszName))
     702        {
     703            rc = VERR_BUFFER_OVERFLOW;
     704            break;
     705        }
     706
     707        PAC97INPUTSTREAM pStrmIn;
     708        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
     709            pStrmIn = &pDrv->MicIn;
     710        else
     711            pStrmIn = &pDrv->LineIn;
     712
     713        AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm);
     714
     715        AudioMixerStreamDestroy(pStrmIn->pMixStrm);
     716        pStrmIn->pMixStrm = NULL;
     717
     718        int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStrmIn->pMixStrm);
    685719        if (RT_SUCCESS(rc2))
    686720        {
    687             AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
    688             rc2 = AudioMixerAddStreamOut(pThis->pSinkOutput,
    689                                          pDrv->pConnector, pDrv->Out.pStrmOut,
    690                                          0 /* uFlags */, &pDrv->Out.phStrmOut);
     721            rc2 = AudioMixerSinkAddStream(pSink, pStrmIn->pMixStrm);
     722            LogFlowFunc(("LUN#%RU8: Created input \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
    691723        }
    692724
    693725        if (RT_SUCCESS(rc))
    694726            rc = rc2;
    695 
    696         RTStrFree(pszDesc);
    697727    }
    698728
     
    701731}
    702732
    703 static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
     733static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     734{
     735    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     736    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     737    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
     738
     739    /* Update the sink's format. */
     740    PDMPCMPROPS PCMProps;
     741    int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps);
     742    if (RT_SUCCESS(rc))
     743        rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps);
     744
     745    if (RT_FAILURE(rc))
     746        return rc;
     747
     748    PAC97DRIVER pDrv;
     749    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     750    {
     751        if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
     752                         pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"))
     753        {
     754            rc = VERR_BUFFER_OVERFLOW;
     755            break;
     756        }
     757
     758        AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     759
     760        AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
     761        pDrv->Out.pMixStrm = NULL;
     762
     763        int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
     764        if (RT_SUCCESS(rc2))
     765        {
     766            rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     767            LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
     768        }
     769
     770        if (RT_SUCCESS(rc))
     771            rc = rc2;
     772    }
     773
     774    LogFlowFuncLeaveRC(rc);
     775    return rc;
     776}
     777
     778static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
    704779{
    705780    AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
    706     AssertPtrReturn(pStrmSt,           VERR_INVALID_POINTER);
     781    AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
    707782    AssertReturn(u8Strm <= LAST_INDEX, VERR_INVALID_PARAMETER);
    708783    AssertPtrReturn(pCfg,              VERR_INVALID_POINTER);
    709784
    710     pStrmSt->u8Strm = u8Strm;
     785    pStream->u8Strm = u8Strm;
    711786
    712787    LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n",
    713                  pStrmSt->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
     788                 pStream->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
    714789
    715790    int rc;
    716     switch (pStrmSt->u8Strm)
     791    switch (pStream->u8Strm)
    717792    {
    718793        case PI_INDEX:
     
    733808    }
    734809
     810    if (RT_FAILURE(rc))
     811        LogRel2(("AC97: Error opening stream #%RU8, rc=%Rrc\n", pStream->u8Strm, rc));
     812
    735813    LogFlowFuncLeaveRC(rc);
    736814    return rc;
    737815}
    738816
    739 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm)
     817static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm)
    740818{
    741819    int rc = VINF_SUCCESS;
     
    769847    }
    770848
    771     if (RT_FAILURE(rc))
    772         return rc;
    773 
    774     if (streamCfg.uHz)
    775     {
    776         streamCfg.cChannels     = 2;
    777         streamCfg.enmFormat     = AUD_FMT_S16;
    778         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    779 
    780         return ichac97StreamInitEx(pThis, pStrmSt, u8Strm, &streamCfg);
    781     }
    782 
    783     /* If no frequency is given, disable the stream. */
    784     return ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
    785 }
    786 
    787 static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrmSt)
    788 {
    789     return ichac97StreamInit(pThis, pStrmSt, pStrmSt->u8Strm);
    790 }
    791 
    792 static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrmSt)
     849    if (RT_SUCCESS(rc))
     850    {
     851        pStream->State.cbFIFOW  = 256; /** @todo Make FIFOW size configurable. */
     852        pStream->State.offFIFOW = 0;
     853        pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW);
     854        if (!pStream->State.au8FIFOW)
     855            rc = VERR_NO_MEMORY;
     856    }
     857
     858    if (RT_SUCCESS(rc))
     859    {
     860        if (streamCfg.uHz)
     861        {
     862            streamCfg.cChannels     = 2; /** @todo Handle mono channels? */
     863            streamCfg.enmFormat     = PDMAUDIOFMT_S16;
     864            streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     865
     866            rc = ichac97StreamInitEx(pThis, pStream, u8Strm, &streamCfg);
     867        }
     868        else
     869        {
     870            /* If no frequency is given, disable the stream. */
     871            rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */);
     872        }
     873    }
     874
     875    LogFlowFunc(("Index=%RU8, rc=%Rrc\n", u8Strm, rc));
     876    return rc;
     877}
     878
     879static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrm)
     880{
     881    return ichac97StreamInit(pThis, pStrm, pStrm->u8Strm);
     882}
     883
     884static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrm)
    793885{
    794886    AssertPtrReturnVoid(pThis);
    795     AssertPtrReturnVoid(pStrmSt);
    796 
    797     LogFlowFunc(("uStrm=%RU8\n", pStrmSt->u8Strm));
     887    AssertPtrReturnVoid(pStrm);
     888
     889    if (pStrm->State.au8FIFOW)
     890    {
     891        Assert(pStrm->State.cbFIFOW);
     892        RT_BZERO(pStrm->State.au8FIFOW, pStrm->State.cbFIFOW);
     893    }
     894
     895    pStrm->State.offFIFOW = 0;
     896
     897    LogFlowFunc(("uStrm=%RU8\n", pStrm->u8Strm));
    798898}
    799899
     
    832932
    833933            case PDMAUDIOMIXERCTL_FRONT:
    834                 rc = AudioMixerSetSinkVolume(pThis->pSinkOutput, &vol);
     934                rc = AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol);
    835935                break;
    836936
    837937            case PDMAUDIOMIXERCTL_MIC_IN:
    838                 rc = AudioMixerSetSinkVolume(pThis->pSinkMicIn, &vol);
     938                rc = AudioMixerSinkSetVolume(pThis->pSinkMicIn, &vol);
    839939                break;
    840940
    841941            case PDMAUDIOMIXERCTL_LINE_IN:
    842                 rc = AudioMixerSetSinkVolume(pThis->pSinkLineIn, &vol);
     942                rc = AudioMixerSinkSetVolume(pThis->pSinkLineIn, &vol);
    843943                break;
    844944
     
    9911091 * @return  IPRT status code.
    9921092 * @param   pThis
    993  * @param   pStrmSt
     1093 * @param   pStream
    9941094 * @param   cbMax
    9951095 * @param   pcbWritten
    9961096 */
    997 static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbWritten)
    998 {
    999     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1000     AssertPtrReturn(pStrmSt,    VERR_INVALID_POINTER);
    1001     AssertReturn(cbMax,         VERR_INVALID_PARAMETER);
     1097static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbWritten)
     1098{
     1099    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1100    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1101    AssertReturn(cbMax,      VERR_INVALID_PARAMETER);
    10021102    /* pcbWritten is optional. */
    10031103
    10041104    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    1005     PAC97BMREGS pRegs   = &pStrmSt->Regs;
     1105    PAC97BMREGS pRegs   = &pStream->Regs;
    10061106
    10071107    uint32_t    addr           = pRegs->bd.addr;
    10081108    uint32_t    cbWrittenTotal = 0;
    1009     uint32_t    cbToRead;
    1010 
    1011     uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax);
     1109
     1110    Log3Func(("PICB=%RU16, cbMax=%RU32\n", pRegs->picb, cbMax));
     1111
     1112    uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax); /** @todo r=andy Assumes 16bit sample size. */
    10121113    if (!cbToWrite)
    10131114    {
     
    10211122    LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite));
    10221123
     1124    Assert(pStream->State.offFIFOW <= pStream->State.cbFIFOW);
     1125    uint32_t  cbFIFOW  = pStream->State.cbFIFOW - pStream->State.offFIFOW;
     1126    uint8_t  *pu8FIFOW = &pStream->State.au8FIFOW[pStream->State.offFIFOW];
     1127
     1128    uint32_t cbToRead;
    10231129    while (cbToWrite)
    10241130    {
    1025         cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf);
    1026         PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */
    1027 
     1131        cbToRead = RT_MIN(cbToWrite, cbFIFOW);
     1132        PDMDevHlpPhysRead(pDevIns, addr, pu8FIFOW, cbToRead); /** @todo r=andy Check rc? */
     1133
     1134        /*
     1135         * Write data to the mixer sink.
     1136         */
    10281137        uint32_t cbWritten;
    1029 
    1030         /* Just multiplex the output to the connected backends.
    1031          * No need to utilize the virtual mixer here (yet). */
    1032         PAC97DRIVER pDrv;
    1033         RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    1034         {
    1035             int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    1036                                                  pThis->pvReadWriteBuf, cbToRead, &cbWritten);
    1037             LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
    1038         }
    1039 
    1040         LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
    1041                      cbToRead, cbToWrite, cbToWrite - cbWrittenTotal));
    1042 
     1138        rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, pu8FIFOW, cbToRead, &cbWritten);
     1139
     1140        LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32, rc=%Rrc\n",
     1141                     cbToRead, cbToWrite, cbWritten, cbToWrite - cbWrittenTotal, rc));
     1142
     1143        if (RT_FAILURE(rc))
     1144            break;
     1145
     1146        /* Advance. */
    10431147        Assert(cbToWrite >= cbToRead);
    10441148        cbToWrite      -= cbToRead;
     
    10471151    }
    10481152
     1153    /* Set new buffer descriptor address. */
    10491154    pRegs->bd.addr = addr;
    10501155
     
    10591164            }
    10601165            else
    1061                 pThis->last_samp = *(uint32_t *)&pThis->pvReadWriteBuf[cbToRead - 4];
     1166                pThis->last_samp = *(uint32_t *)&pStream->State.au8FIFOW[pStream->State.offFIFOW + cbToRead - 4];
    10621167        }
    10631168
     
    11221227}
    11231228
    1124 static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbRead)
     1229static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbRead)
    11251230{
    11261231    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1127     AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1232    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    11281233    AssertReturn(cbMax,      VERR_INVALID_PARAMETER);
    11291234    /* pcbRead is optional. */
    11301235
    11311236    PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    1132     PAC97BMREGS pRegs  = &pStrmSt->Regs;
     1237    PAC97BMREGS pRegs  = &pStream->Regs;
    11331238
    11341239    /* Select audio sink to process. */
    1135     AssertMsg(pStrmSt->u8Strm != PO_INDEX, ("Can't read from output\n"));
    1136     PAUDMIXSINK pSink = pStrmSt->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
     1240    AssertMsg(pStream->u8Strm != PO_INDEX, ("Can't read from output\n"));
     1241    PAUDMIXSINK pSink = pStream->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
    11371242    AssertPtr(pSink);
    11381243
    11391244    uint32_t cbRead   = 0;
    1140 
    1141     uint32_t cbMixBuf = cbMax;
    1142     uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1), cbMixBuf);
     1245    uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1),
     1246                               RT_MIN(pStream->State.cbFIFOW, cbMax)); /** @todo r=andy Assumes 16bit samples. */
    11431247
    11441248    if (!cbToRead)
     
    11511255    int rc;
    11521256
    1153     uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbMixBuf);
    1154     if (pvMixBuf)
    1155     {
    1156         rc = AudioMixerProcessSinkIn(pSink, AUDMIXOP_BLEND, pvMixBuf, cbToRead, &cbRead);
    1157         if (   RT_SUCCESS(rc)
    1158             && cbRead)
    1159         {
    1160             PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, pvMixBuf, cbRead);
    1161             pRegs->bd.addr += cbRead;
    1162         }
    1163 
    1164         RTMemFree(pvMixBuf);
    1165     }
    1166     else
    1167         rc = VERR_NO_MEMORY;
     1257    rc = AudioMixerSinkRead(pSink, AUDMIXOP_BLEND, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbToRead, &cbRead);
     1258    if (   RT_SUCCESS(rc)
     1259        && cbRead)
     1260    {
     1261        PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbRead);
     1262        pRegs->bd.addr += cbRead;
     1263    }
    11681264
    11691265    if (RT_SUCCESS(rc))
    11701266    {
     1267        if (!cbRead)
     1268            rc = VINF_EOF;
     1269
    11711270        if (pcbRead)
    11721271            *pcbRead = cbRead;
     
    11891288    uint32_t cbOutMin = UINT32_MAX;
    11901289
    1191     PAC97DRIVER pDrv;
     1290//    PAC97DRIVER pDrv;
    11921291
    11931292    uint64_t cTicksNow     = TMTimerGet(pTimer);
     
    11971296    pThis->uTimerTS = cTicksNow;
    11981297
     1298#if 0
    11991299    /*
    12001300     * Calculate the mixer's (fixed) sampling rate.
     
    12771377    if (cbInMax)
    12781378        ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */
     1379#else
     1380    AudioMixerSinkUpdate(pThis->pSinkLineIn);
     1381    AudioMixerSinkUpdate(pThis->pSinkMicIn);
     1382    AudioMixerSinkUpdate(pThis->pSinkOutput);
     1383
     1384    uint32_t cMixerSamplesMin  = (int)((2 * cTicksElapsed *   pThis->pSinkOutput->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2);
     1385    uint32_t cbMixerSamplesMin = cMixerSamplesMin <<  pThis->pSinkOutput->PCMProps.cShift;
     1386
     1387    Log3Func(("cMixerSamplesMin=%RU32, cbMixerSamplesMin=%RU32, mixerHz=%RU32\n",
     1388              cMixerSamplesMin, cbMixerSamplesMin,  pThis->pSinkOutput->PCMProps.uHz));
     1389
     1390    //uint32_t cbSamplesElapsed = 5120; //((48000 / AC97_TIMER_HZ) * 20) / 8;
     1391
     1392    uint32_t cMixerSamplesMinIn  = (int)((2 * cTicksElapsed *   pThis->pSinkLineIn->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2);
     1393    uint32_t cbMixerSamplesMinIn = cMixerSamplesMinIn <<  pThis->pSinkLineIn->PCMProps.cShift;
     1394
     1395    ichac97TransferAudio(pThis, &pThis->StrmStLineIn, cMixerSamplesMinIn); /** @todo Add rc! */
     1396    ichac97TransferAudio(pThis, &pThis->StrmStOut,    cbMixerSamplesMin);  /** @todo Add rc! */
     1397#endif
    12791398
    12801399    /* Kick the timer again. */
     
    12881407#endif
    12891408
    1290 static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed)
    1291 {
    1292     LogFlowFunc(("pThis=%p, enmSrc=%RU32, cbElapsed=%RU32\n", pThis, enmSrc, cbElapsed));
    1293 
    1294     PAC97STREAM pStrmSt;
    1295     switch (enmSrc)
    1296     {
    1297         case PI_INDEX: pStrmSt = &pThis->StrmStLineIn; break;
    1298         case MC_INDEX: pStrmSt = &pThis->StrmStMicIn;  break;
    1299         case PO_INDEX: pStrmSt = &pThis->StrmStOut;    break;
    1300         default:
    1301         {
    1302             AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
    1303             return VERR_NOT_SUPPORTED;
    1304         }
    1305     }
    1306 
    1307     PAC97BMREGS pRegs = &pStrmSt->Regs;
     1409static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbElapsed)
     1410{
     1411    Log3Func(("SD=%RU8, cbElapsed=%RU32\n", pStream->u8Strm , cbElapsed));
     1412
     1413    PAC97BMREGS pRegs = &pStream->Regs;
    13081414
    13091415    if (pRegs->sr & SR_DCH) /* Controller halted? */
     
    13111417        if (pRegs->cr & CR_RPBM)
    13121418        {
    1313             switch (enmSrc)
     1419            switch (pStream->u8Strm)
    13141420            {
    13151421                case PO_INDEX:
     
    13251431    }
    13261432
     1433    /* BCIS flag still set? Skip iteration. */
     1434    if (pRegs->sr & SR_BCIS)
     1435        return VINF_SUCCESS;
     1436
    13271437    int rc = VINF_SUCCESS;
    13281438    uint32_t cbWrittenTotal = 0;
    13291439
    1330     while (cbElapsed >> 1)
     1440    while (cbElapsed >> 1) /** @todo r=andy This assumes (hardcodes) 16bit sample size.*/
    13311441    {
    13321442        if (!pRegs->bd_valid)
    13331443        {
    13341444            LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n"));
    1335             ichac97StreamFetchBDLE(pThis, pStrmSt);
     1445            ichac97StreamFetchBDLE(pThis, pStream);
    13361446        }
    13371447
     
    13511461            pRegs->sr &= ~SR_CELV;
    13521462            pRegs->civ = pRegs->piv;
    1353             pRegs->piv = (pRegs->piv + 1) % 32;
    1354 
    1355             ichac97StreamFetchBDLE(pThis, pStrmSt);
     1463            pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */
     1464
     1465            ichac97StreamFetchBDLE(pThis, pStream);
    13561466            continue;
    13571467        }
    13581468
    13591469        uint32_t cbTransferred;
    1360         switch (enmSrc)
     1470        switch (pStream->u8Strm)
    13611471        {
    13621472            case PO_INDEX:
    13631473            {
    1364                 rc = ichac97WriteAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
     1474                rc = ichac97WriteAudio(pThis, pStream, cbElapsed, &cbTransferred);
    13651475                if (   RT_SUCCESS(rc)
    13661476                    && cbTransferred)
     
    13701480                    cbElapsed      -= cbTransferred;
    13711481                    Assert((cbTransferred & 1) == 0);    /* Else the following shift won't work */
    1372                     pRegs->picb    -= (cbTransferred >> 1);
     1482                    pRegs->picb    -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
    13731483                }
    13741484                break;
     
    13781488            case MC_INDEX:
    13791489            {
    1380                 rc = ichac97ReadAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
     1490                rc = ichac97ReadAudio(pThis, pStream, cbElapsed, &cbTransferred);
    13811491                if (   RT_SUCCESS(rc)
    13821492                    && cbTransferred)
    13831493                {
    13841494                    Assert(cbElapsed >= cbTransferred);
    1385                     cbElapsed  -= cbTransferred;
     1495                    cbElapsed   -= cbTransferred;
    13861496                    Assert((cbTransferred & 1) == 0);    /* Else the following shift won't work */
    1387                     pRegs->picb -= (cbTransferred >> 1);
     1497                    pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
    13881498                }
    13891499                break;
     
    13911501
    13921502            default:
    1393                 AssertMsgFailed(("Source %RU32 not supported\n", enmSrc));
     1503                AssertMsgFailed(("Stream #%RU8 not supported\n", pStream->u8Strm));
    13941504                rc = VERR_NOT_SUPPORTED;
    13951505                break;
    13961506        }
    13971507
    1398         LogFlowFunc(("pReg->picb=%#x, cbWrittenTotal=%RU32\n", pRegs->picb, cbWrittenTotal));
     1508        Log3Func(("PICB=%RU16 (%#x), cbTransferred=%RU32 (%zu samples), cbWrittenTotal=%RU32\n",
     1509                  pRegs->picb, pRegs->picb, cbTransferred, (cbTransferred >> 1), cbWrittenTotal));
    13991510
    14001511        if (!pRegs->picb)
     
    14091520            if (pRegs->civ == pRegs->lvi)
    14101521            {
    1411                 LogFlowFunc(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi));
     1522                Log3Func(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi));
    14121523                new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
    14131524                pThis->bup_flag = (pRegs->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
     
    14181529            {
    14191530                pRegs->civ = pRegs->piv;
    1420                 pRegs->piv = (pRegs->piv + 1) % 32;
    1421                 ichac97StreamFetchBDLE(pThis, pStrmSt);
     1531                pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */
     1532                ichac97StreamFetchBDLE(pThis, pStream);
    14221533            }
    14231534
    1424             ichac97StreamUpdateStatus(pThis, pStrmSt, new_sr);
     1535            ichac97StreamUpdateStatus(pThis, pStream, new_sr);
    14251536        }
    14261537
     
    14471558    const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
    14481559
    1449     PAC97STREAM pStrmSt    = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
    1450     PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
     1560    PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
     1561    PAC97BMREGS pRegs   = pStream ? &pStream->Regs : NULL;
    14511562
    14521563    switch (cbVal)
     
    15191630                case PO_PICB:
    15201631                case MC_PICB:
    1521                     /* Position in Current Buffer Register */
     1632                    /* Position in Current Buffer */
    15221633                    *pu32Val = pRegs->picb;
    15231634                    LogFlowFunc(("PICB[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
     
    15971708    const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
    15981709
    1599     PAC97STREAM pStrmSt    = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
    1600     PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
     1710    PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
     1711    PAC97BMREGS pRegs   = pStream ? &pStream->Regs : NULL;
    16011712
    16021713    switch (cbVal)
     
    16161727                        pRegs->piv = (pRegs->piv + 1) % 32;
    16171728
    1618                         ichac97StreamFetchBDLE(pThis, pStrmSt);
     1729                        ichac97StreamFetchBDLE(pThis, pStream);
    16191730                    }
    16201731                    pRegs->lvi = u32Val % 32;
     
    16281739                    if (u32Val & CR_RR) /* Busmaster reset */
    16291740                    {
    1630                         ichac97StreamResetBMRegs(pThis, pStrmSt);
     1741                        ichac97StreamResetBMRegs(pThis, pStream);
    16311742                    }
    16321743                    else
     
    16351746                        if (!(pRegs->cr & CR_RPBM))
    16361747                        {
    1637                             ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
     1748                            ichac97StreamSetActive(pThis, pStream, false /* fActive */);
    16381749                            pRegs->sr |= SR_DCH;
    16391750                        }
     
    16431754                            pRegs->piv = (pRegs->piv + 1) % 32;
    16441755
    1645                             ichac97StreamFetchBDLE(pThis, pStrmSt);
     1756                            ichac97StreamFetchBDLE(pThis, pStream);
    16461757
    16471758                            pRegs->sr &= ~SR_DCH;
    1648                             ichac97StreamSetActive(pThis, pStrmSt, true /* fActive */);
     1759                            ichac97StreamSetActive(pThis, pStream, true /* fActive */);
    16491760                        }
    16501761                    }
     
    16571768                    /* Status Register */
    16581769                    pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
    1659                     ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
     1770                    ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
    16601771                    LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
    16611772                    break;
     
    16761787                    /* Status Register */
    16771788                    pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
    1678                     ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
     1789                    ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
    16791790                    LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
    16801791                    break;
     
    18571968                    }
    18581969                    else
    1859                         LogFlowFunc(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
     1970                        AssertMsgFailed(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
    18601971                    break;
    18611972                case AC97_MIC_ADC_Rate:
     
    18671978                    }
    18681979                    else
    1869                         LogFlowFunc(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
     1980                        AssertMsgFailed(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
    18701981                    break;
    18711982                case AC97_PCM_LR_ADC_Rate:
     
    18771988                    }
    18781989                    else
    1879                         LogFlowFunc(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
     1990                        AssertMsgFailed(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
    18801991                    break;
    18811992                default:
     
    19492060
    19502061#ifdef IN_RING3
    1951 static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
    1952 {
    1953     PAC97BMREGS pRegs = &pStrmSt->Regs;
     2062static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
     2063{
     2064    PAC97BMREGS pRegs = &pStream->Regs;
    19542065
    19552066    SSMR3PutU32(pSSM, pRegs->bdbar);
     
    20062117}
    20072118
    2008 static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
    2009 {
    2010     PAC97BMREGS pRegs = &pStrmSt->Regs;
     2119static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
     2120{
     2121    PAC97BMREGS pRegs = &pStream->Regs;
    20112122
    20122123    SSMR3GetU32(pSSM, &pRegs->bdbar);
     
    20642175                             ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
    20652176
    2066     int rc;
    2067     rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
    2068     AssertRC(rc);
    2069     rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
    2070     AssertRC(rc);
    2071     rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
     2177    int rc = ichac97StreamsInit(pThis);
    20722178    AssertRC(rc);
    20732179
     
    21012207
    21022208/**
     2209 * Powers off the device.
     2210 *
     2211 * @param   pDevIns             Device instance to power off.
     2212 */
     2213static DECLCALLBACK(void) ichac97PowerOff(PPDMDEVINS pDevIns)
     2214{
     2215    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
     2216
     2217    LogRel2(("AC97: Powering off ...\n"));
     2218
     2219    /**
     2220     * Note: Destroy the mixer while powering off and *not* in ichac97Destruct,
     2221     *       giving the mixer the chance to release any references held to
     2222     *       PDM audio streams it maintains.
     2223     */
     2224    if (pThis->pMixer)
     2225    {
     2226        AudioMixerDestroy(pThis->pMixer);
     2227        pThis->pMixer = NULL;
     2228    }
     2229}
     2230
     2231
     2232/**
    21032233 * @interface_method_impl{PDMDEVREG,pfnReset}
    21042234 *
     
    21292259     * Stop any audio currently playing.
    21302260     */
    2131     PAC97DRIVER pDrv;
    2132     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    2133     {
    2134         pDrv->pConnector->pfnEnableIn(pDrv->pConnector,  pDrv->LineIn.pStrmIn, false /* Disable */);
    2135         /* Ignore rc. */
    2136         pDrv->pConnector->pfnEnableIn(pDrv->pConnector,  pDrv->MicIn.pStrmIn,  false /* Disable */);
    2137         /* Ditto. */
    2138         pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut,   false /* Disable */);
    2139         /* Ditto. */
    2140     }
     2261    /*
     2262     * Stop any audio currently playing and/or recording.
     2263     */
     2264    AudioMixerSinkCtl(pThis->pSinkOutput, AUDMIXSINKCMD_DISABLE);
     2265    AudioMixerSinkCtl(pThis->pSinkMicIn,  AUDMIXSINKCMD_DISABLE);
     2266    AudioMixerSinkCtl(pThis->pSinkLineIn, AUDMIXSINKCMD_DISABLE);
    21412267
    21422268    /*
     
    21692295    }
    21702296
    2171     if (pThis->pMixer)
    2172     {
    2173         AudioMixerDestroy(pThis->pMixer);
    2174         pThis->pMixer = NULL;
    2175     }
    2176 
    2177     if (pThis->pvReadWriteBuf)
    2178     {
    2179         RTMemFree(pThis->pvReadWriteBuf);
    2180         pThis->pvReadWriteBuf = NULL;
    2181         pThis->cbReadWriteBuf = 0;
    2182     }
     2297    ichac97StreamsDestroy(pThis);
    21832298
    21842299    LogFlowFuncLeave();
     
    23192434#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
    23202435
    2321     int rc = VINF_SUCCESS;
     2436    int rc;
    23222437    do
    23232438    {
     
    23792494#ifndef VBOX_WITH_AUDIO_CALLBACKS
    23802495    uint16_t uTimerHz;
    2381     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
     2496    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, AC97_TIMER_HZ /* Default value, if not set. */);
    23822497    if (RT_FAILURE(rc))
    23832498        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    25002615            streamCfg.uHz           = 44100;
    25012616            streamCfg.cChannels     = 2;
    2502             streamCfg.enmFormat     = AUD_FMT_S16;
     2617            streamCfg.enmFormat     = PDMAUDIOFMT_S16;
    25032618            streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    25042619
     
    25072622
    25082623            /* Add all required audio sinks. */
    2509             rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
    2510             AssertRC(rc);
    2511 
    2512             rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
    2513             AssertRC(rc);
    2514 
    2515             rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
    2516             AssertRC(rc);
     2624            int rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
     2625            AssertRC(rc2);
     2626
     2627            rc2 = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
     2628            AssertRC(rc2);
     2629
     2630            rc2 = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
     2631            AssertRC(rc2);
    25172632        }
    25182633    }
     
    25222637    if (RT_SUCCESS(rc))
    25232638    {
    2524         rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
    2525         if (RT_FAILURE(rc))
    2526             return rc;
    2527         rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
    2528         if (RT_FAILURE(rc))
    2529             return rc;
    2530         rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
    2531         if (RT_FAILURE(rc))
    2532             return rc;
     2639        ichac97StreamsInit(pThis);
    25332640
    25342641        PAC97DRIVER pDrv;
     
    25452652            AssertPtr(pCon);
    25462653
    2547             bool fValidLineIn = pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn);
    2548             bool fValidMicIn  = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn);
    2549             bool fValidOut    = pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut);
     2654            bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
     2655            bool fValidMicIn  = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
     2656            bool fValidOut    = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
    25502657
    25512658            if (    !fValidLineIn
     
    25552662                LogRel(("AC97: Falling back to NULL backend (no sound audible)\n"));
    25562663
     2664                /* Destroy the streams before re-attaching the NULL driver. */
     2665                ichac97StreamsDestroy(pThis);
     2666
    25572667                ichac97Reset(pDevIns);
    25582668                ichac97Reattach(pThis, pDrv, pDrv->uLUN, "NullAudio");
     2669
     2670                ichac97StreamsInit(pThis);
    25592671
    25602672                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     
    25672679
    25682680                PDMAUDIOBACKENDCFG backendCfg;
    2569                 int rc2 = pCon->pfnGetConfiguration(pCon, &backendCfg);
     2681                int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
    25702682                if (RT_SUCCESS(rc2))
    25712683                {
     
    26242736            }
    26252737        }
    2626     }
    2627 
    2628     if (RT_SUCCESS(rc))
    2629     {
    2630         pThis->cbReadWriteBuf = _4K; /** @todo Make this configurable. */
    2631         pThis->pvReadWriteBuf = (uint8_t *)RTMemAllocZ(pThis->cbReadWriteBuf);
    2632         if (!pThis->pvReadWriteBuf)
    2633             rc = VERR_NO_MEMORY;
    26342738    }
    26352739
     
    27482852    NULL,
    27492853    /* pfnPowerOff */
    2750     NULL,
     2854    ichac97PowerOff,
    27512855    /* pfnSoftReset */
    27522856    NULL,
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r60353 r60925  
    8787#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
    8888
    89 /* Make sure that interleaving streams support is enabled if the 5.1 code
    90  * is being used. */
    91 #ifdef VBOX_WITH_HDA_51_SURROUND
     89/* Make sure that interleaving streams support is enabled if the 5.1 code is being used. */
     90#if defined (VBOX_WITH_HDA_51_SURROUND) && !defined(VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT)
    9291# define VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
    9392#endif
    9493
    9594/**
    96  * At the moment we support 4 input + 4 output streams (for 7.1 support) max,
    97  * which is 12 in total. Bidirectional streams are currently *not* supported.
     95 * At the moment we support 4 input + 4 output streams max, which is 8 in total.
     96 * Bidirectional streams are currently *not* supported.
    9897 *
    9998 * Note: When changing any of those values, be prepared for some saved state
     
    143142 */
    144143#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
    145     (  (((oss)   & 0xF) << 12) \
    146      | (((iss)   & 0xF) << 8)  \
    147      | (((bss)   & 0xF) << 3)  \
    148      | (((bds)   & 0x3) << 1)  \
     144    (  (((oss)   & 0xF)  << 12) \
     145     | (((iss)   & 0xF)  << 8)  \
     146     | (((bss)   & 0x1F) << 3)  \
     147     | (((bds)   & 0x3)  << 1)  \
    149148     | ((b64sup) & 1))
    150149
     
    588587
    589588/**
     589 * Structure for keeping an audio stream data mapping.
     590 */
     591typedef struct HDASTREAMMAPPING
     592{
     593    /** The stream's layout. */
     594    PDMAUDIOSTREAMLAYOUT              enmLayout;
     595    /** Number of audio channels in this stream. */
     596    uint8_t                           cChannels;
     597    /** Array audio channels. */
     598    R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels;
     599    R3PTRTYPE(PRTCIRCBUF)             pCircBuf;
     600} HDASTREAMMAPPING, *PHDASTREAMMAPPING;
     601
     602/**
    590603 * Internal state of a HDA stream.
    591604 */
     
    594607    /** Current BDLE to use. Wraps around to 0 if
    595608     *  maximum (cBDLE) is reached. */
    596     uint16_t            uCurBDLE;
     609    uint16_t                uCurBDLE;
    597610    /** Stop indicator. */
    598     volatile bool       fDoStop;
     611    volatile bool           fDoStop;
    599612    /** Flag indicating whether this stream is in an
    600613     *  active (operative) state or not. */
    601     volatile bool       fActive;
     614    volatile bool           fActive;
    602615    /** Flag indicating whether this stream currently is
    603616     *  in reset mode and therefore not acccessible by the guest. */
    604     volatile bool       fInReset;
     617    volatile bool           fInReset;
    605618    /** Unused, padding. */
    606     bool                fPadding;
     619    bool                    fPadding;
    607620    /** Mutex semaphore handle to serialize access. */
    608     RTSEMMUTEX          hMtx;
     621    RTSEMMUTEX              hMtx;
    609622    /** Event signalling that the stream's state has been changed. */
    610     RTSEMEVENT          hStateChangedEvent;
     623    RTSEMEVENT              hStateChangedEvent;
     624    /** This stream's data mapping. */
     625    HDASTREAMMAPPING        Mapping;
    611626    /** Current BDLE (Buffer Descriptor List Entry). */
    612     HDABDLE             BDLE;
     627    HDABDLE                 BDLE;
    613628} HDASTREAMSTATE, *PHDASTREAMSTATE;
    614629
     
    659674} HDATAG, *PHDATAG;
    660675
    661 typedef struct HDAINPUTSTREAM
    662 {
    663     /** Pointer to guest input stream. */
    664     R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pGstStrm;
     676/**
     677 * Structure defining an HDA mixer stream.
     678 * This is being used together with an audio mixer instance.
     679 */
     680typedef struct HDAMIXERSTREAM
     681{
     682    union
     683    {
     684        /** Desired playback destination (for an output stream). */
     685        PDMAUDIOPLAYBACKDEST           Dest;
     686        /** Desired recording source (for an input stream). */
     687        PDMAUDIORECSOURCE              Source;
     688    } DestSource;
     689    uint8_t                            Padding1[4];
    665690    /** Associated mixer handle. */
    666     R3PTRTYPE(PAUDMIXSTREAM)      pMixStrm;
    667 } HDAINPUTSTREAM, *PHDAINPUTSTREAM;
    668 
    669 typedef struct HDAOUTPUTSTREAM
    670 {
    671     /** Pointer to guest output stream. */
    672     R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pGstStrm;
    673     /** Associated mixer handle. */
    674     R3PTRTYPE(PAUDMIXSTREAM)       pMixStrm;
    675 } HDAOUTPUTSTREAM, *PHDAOUTPUTSTREAM;
     691    R3PTRTYPE(PAUDMIXSTREAM)           pMixStrm;
     692} HDAMIXERSTREAM, *PHDAMIXERSTREAM;
    676693
    677694/**
     
    701718    /** Audio connector interface to the underlying host backend. */
    702719    R3PTRTYPE(PPDMIAUDIOCONNECTOR)     pConnector;
    703     /** Stream for line input. */
    704     HDAINPUTSTREAM                     LineIn;
     720    /** Mixer stream for line input. */
     721    HDAMIXERSTREAM                     LineIn;
    705722#ifdef VBOX_WITH_HDA_MIC_IN
    706     /** Stream for mic input. */
    707     HDAINPUTSTREAM                     MicIn;
    708 #endif
    709     /** Stream for front output. */
    710     HDAOUTPUTSTREAM                    Front;
     723    /** Mixer stream for mic input. */
     724    HDAMIXERSTREAM                     MicIn;
     725#endif
     726    /** Mixer stream for front output. */
     727    HDAMIXERSTREAM                     Front;
    711728#ifdef VBOX_WITH_HDA_51_SURROUND
    712     /** Stream for center/LFE output. */
    713     HDAOUTPUTSTREAM                    CenterLFE;
    714     /** Stream for rear output. */
    715     HDAOUTPUTSTREAM                    Rear;
     729    /** Mixer stream for center/LFE output. */
     730    HDAMIXERSTREAM                     CenterLFE;
     731    /** Mixer stream for rear output. */
     732    HDAMIXERSTREAM                     Rear;
    716733#endif
    717734} HDADRIVER;
     
    807824    /** Padding for alignment. */
    808825    uint8_t                            au8Padding2[7];
    809 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
    810     /** Circular buffer for interleaving streams support.
    811      *  This is needed for extracting multiple channels out of a single HDA stream. */
    812     R3PTRTYPE(PRTCIRCBUF)              pCircBuf;
    813 #endif
    814826} HDASTATE;
    815827/** Pointer to the ICH Intel HD Audio Controller state. */
     
    853865static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    854866static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    855 static int hdaRegReadOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    856 static int hdaRegWriteOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    857 static int hdaRegReadOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    858 static int hdaRegWriteOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    859867static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    860868static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
     
    897905
    898906#ifdef IN_RING3
    899 static int       hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
    900 DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB);
     907static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg);
     908static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping);
     909static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping);
     910#endif
     911
     912#ifdef IN_RING3
     913static int           hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
     914DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB);
    901915# ifdef LOG_ENABLED
    902 static void             hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
     916static void          hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
    903917# endif
    904918#endif
     919static int           hdaProcessInterrupt(PHDASTATE pThis);
    905920
    906921
     
    936951    { offset + 0xC,  0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16, hdaRegWriteSDLVI  , HDA_REG_IDX_STRM(name, LVI)  , #name " Last Valid Index" }, \
    937952    /* Reserved: FIFO Watermark. ** @todo Document this! */ \
    938     { offset + 0xE,  0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
     953    { offset + 0xE,  0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteU16,    HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
    939954    /* Offset 0x90 (SD0) */ \
    940     { offset + 0x10, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16, hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
     955    { offset + 0x10, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16, hdaRegWriteU16,    HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
    941956    /* Offset 0x92 (SD0) */ \
    942957    { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16, hdaRegWriteSDFMT  , HDA_REG_IDX_STRM(name, FMT)  , #name " Stream Format" }, \
     
    980995    { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimpl     , HDA_REG_IDX(VMIN)         }, /* Minor Version */
    981996    { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimpl     , HDA_REG_IDX(VMAJ)         }, /* Major Version */
    982     { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadOUTPAY       , hdaRegWriteOUTPAY     , HDA_REG_IDX(OUTPAY)       }, /* Output Payload Capabilities */
     997    { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16        , HDA_REG_IDX(OUTPAY)       }, /* Output Payload Capabilities */
    983998    { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimpl     , HDA_REG_IDX(INPAY)        }, /* Input Payload Capabilities */
    984999    { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadU32          , hdaRegWriteGCTL       , HDA_REG_IDX(GCTL)         }, /* Global Control */
     
    9861001    { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8           , hdaRegWriteSTATESTS   , HDA_REG_IDX(STATESTS)     }, /* State Change Status */
    9871002    { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimpl       , hdaRegWriteUnimpl     , HDA_REG_IDX(GSTS)         }, /* Global Status */
    988     { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadOUTSTRMPAY   , hdaRegWriteOUTSTRMPAY , HDA_REG_IDX(OUTSTRMPAY)   }, /* Output Stream Payload Capability */
     1003    { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16        , HDA_REG_IDX(OUTSTRMPAY)   }, /* Output Stream Payload Capability */
    9891004    { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimpl     , HDA_REG_IDX(INSTRMPAY)    }, /* Input Stream Payload Capability */
    9901005    { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32          , hdaRegWriteU32        , HDA_REG_IDX(INTCTL)       }, /* Interrupt Control */
    9911006    { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS       , hdaRegWriteUnimpl     , HDA_REG_IDX(INTSTS)       }, /* Interrupt Status */
    9921007    { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK       , hdaRegWriteUnimpl     , HDA_REG_IDX_LOCAL(WALCLK) }, /* Wall Clock Counter */
    993     { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadSSYNC        , hdaRegWriteSSYNC      , HDA_REG_IDX(SSYNC)        }, /* Stream Synchronization */
     1008    { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32          , hdaRegWriteU32        , HDA_REG_IDX(SSYNC)        }, /* Stream Synchronization */
    9941009    { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteBase       , HDA_REG_IDX(CORBLBASE)    }, /* CORB Lower Base Address */
    9951010    { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase       , HDA_REG_IDX(CORBUBASE)    }, /* CORB Upper Base Address */
     
    10111026    { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32          , hdaRegWriteBase       , HDA_REG_IDX(DPLBASE)      }, /* DMA Position Lower Base */
    10121027    { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase       , HDA_REG_IDX(DPUBASE)      }, /* DMA Position Upper Base */
    1013     /* 4 Input Stream Descriptors (ISD). */
     1028    /* 4 Serial Data In (SDI). */
    10141029    HDA_REG_MAP_DEF_STREAM(0, SD0),
    10151030    HDA_REG_MAP_DEF_STREAM(1, SD1),
    10161031    HDA_REG_MAP_DEF_STREAM(2, SD2),
    10171032    HDA_REG_MAP_DEF_STREAM(3, SD3),
    1018     /* 4 Output Stream Descriptors (OSD). */
     1033    /* 4 Serial Data Out (SDO). */
    10191034    HDA_REG_MAP_DEF_STREAM(4, SD4),
    10201035    HDA_REG_MAP_DEF_STREAM(5, SD5),
     
    10861101
    10871102#ifdef IN_RING3
    1088 DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB)
    1089 {
    1090     AssertPtrReturnVoid(pThis);
    1091     AssertPtrReturnVoid(pStrmSt);
     1103DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB)
     1104{
     1105    AssertPtrReturn(pThis,   0);
     1106    AssertPtrReturn(pStrmSt, 0);
    10921107
    10931108    Assert(u32LPIB <= pStrmSt->u32CBL);
     
    11071122        AssertRC(rc2);
    11081123    }
     1124
     1125    return u32LPIB;
    11091126}
    11101127#endif
     
    11691186 * @return  IPRT status code.
    11701187 */
    1171 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStrmSt)
     1188DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream)
    11721189{
    11731190    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1174     AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1191    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    11751192
    11761193    NOREF(pThis);
    11771194
    1178     Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1);
     1195    Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
     1196
     1197    LogFlowFuncEnter();
    11791198
    11801199#ifdef DEBUG
    1181     uint32_t uOldBDLE = pStrmSt->State.uCurBDLE;
    1182 #endif
     1200    uint32_t uOldBDLE = pStream->State.uCurBDLE;
     1201#endif
     1202
     1203    PHDABDLE pBDLE = &pStream->State.BDLE;
    11831204
    11841205    /*
     
    11861207     * if we reached the end of the Buffer Descriptor List (BDL).
    11871208     */
    1188     pStrmSt->State.uCurBDLE++;
    1189     if (pStrmSt->State.uCurBDLE == pStrmSt->u16LVI + 1)
    1190     {
    1191         pStrmSt->State.uCurBDLE = 0;
    1192 
    1193         hdaStreamUpdateLPIB(pThis, pStrmSt, 0);
    1194     }
    1195 
    1196     Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1);
    1197 
    1198     int rc = hdaBDLEFetch(pThis, &pStrmSt->State.BDLE, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE);
     1209    pStream->State.uCurBDLE++;
     1210    if (pStream->State.uCurBDLE == pStream->u16LVI + 1)
     1211    {
     1212        pStream->State.uCurBDLE = 0;
     1213
     1214        hdaStreamUpdateLPIB(pThis, pStream, 0);
     1215    }
     1216
     1217    Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
     1218
     1219    /* Fetch the next BDLE entry. */
     1220    int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    11991221
    12001222#ifdef DEBUG
    12011223    LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",
    1202                  pStrmSt->u8SD, uOldBDLE, pStrmSt->State.uCurBDLE, pStrmSt->u16LVI, rc, &pStrmSt->State.BDLE));
    1203 #endif
     1224                 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));
     1225#endif
     1226
    12041227    return rc;
    12051228}
    12061229#endif /* IN_RING3 */
     1230
     1231/**
     1232 * Returns the audio direction of a specified stream descriptor.
     1233 *
     1234 * The register layout specifies that input streams (SDI) come first,
     1235 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
     1236 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
     1237 *
     1238 * Note: SDnFMT register does not provide that information, so we have to judge
     1239 *       for ourselves.
     1240 *
     1241 * @return  Audio direction.
     1242 */
     1243DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)
     1244{
     1245    AssertReturn(uSD <= HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
     1246
     1247    if (uSD < HDA_MAX_SDI)
     1248        return PDMAUDIODIR_IN;
     1249
     1250    return PDMAUDIODIR_OUT;
     1251}
    12071252
    12081253DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD)
     
    12391284         && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
    12401285
    1241     bool fIrq = false;
     1286    uint8_t uLevel = 0;
    12421287
    12431288    /** @todo Optimize IRQ handling. */
     
    12481293           || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
    12491294           || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))))
    1250         fIrq = true;
     1295        uLevel = 1;
    12511296
    12521297    if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
     
    12591304        || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 7))
    12601305    {
    1261         fIrq = true;
     1306        uLevel = 1;
    12621307    }
    12631308
    12641309    if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
    12651310    {
    1266         Log3Func(("%s\n", fIrq ? "Asserted" : "Deasserted"));
    1267         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , fIrq);
     1311        Log3Func(("Level=%d\n", uLevel));
     1312        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , uLevel);
    12681313    }
    12691314
     
    14421487static int hdaCORBCmdProcess(PHDASTATE pThis)
    14431488{
    1444     PFNHDACODECVERBPROCESSOR pfn = (PFNHDACODECVERBPROCESSOR)NULL;
    1445 
    14461489    int rc = hdaCmdSync(pThis, true);
    14471490    if (RT_FAILURE(rc))
     
    14531496
    14541497    Assert((corbWp != corbRp));
    1455     LogFlowFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
     1498    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
    14561499
    14571500    while (corbRp != corbWp)
    14581501    {
    1459         uint32_t cmd;
    1460         uint64_t resp;
    1461         pfn = NULL;
    1462         corbRp++;
    1463         cmd = pThis->pu32CorbBuf[corbRp];
    1464 
    1465         rc = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(cmd, 0 /* Codec index */), &pfn);
    1466         if (RT_SUCCESS(rc))
    1467         {
    1468             AssertPtr(pfn);
    1469             rc = pfn(pThis->pCodec, HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp);
    1470         }
    1471 
    1472         if (RT_FAILURE(rc))
    1473             AssertRCReturn(rc, rc);
     1502        uint64_t uResp;
     1503        uint32_t uCmd = pThis->pu32CorbBuf[++corbRp];
     1504
     1505        int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
     1506        if (RT_FAILURE(rc2))
     1507            LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2));
     1508
    14741509        (rirbWp)++;
    14751510
    1476         LogFunc(("verb:%08x->%016lx\n", cmd, resp));
    1477         if (   (resp & CODEC_RESPONSE_UNSOLICITED)
     1511        if (   (uResp & CODEC_RESPONSE_UNSOLICITED)
    14781512            && !HDA_REG_FLAG_VALUE(pThis, GCTL, UR))
    14791513        {
    1480             LogFunc(("unexpected unsolicited response.\n"));
     1514            LogFunc(("Unexpected unsolicited response\n"));
    14811515            HDA_REG(pThis, CORBRP) = corbRp;
    14821516            return rc;
    14831517        }
    14841518
    1485         pThis->pu64RirbBuf[rirbWp] = resp;
     1519        pThis->pu64RirbBuf[rirbWp] = uResp;
    14861520
    14871521        pThis->u8RespIntCnt++;
     
    14891523            break;
    14901524    }
     1525
    14911526    HDA_REG(pThis, CORBRP) = corbRp;
    14921527    HDA_REG(pThis, RIRBWP) = rirbWp;
     1528
    14931529    rc = hdaCmdSync(pThis, false);
    1494     LogFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP),
    1495          HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
     1530
     1531    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
     1532
    14961533    if (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC))
    14971534    {
     
    15011538        rc = hdaProcessInterrupt(pThis);
    15021539    }
     1540
    15031541    if (RT_FAILURE(rc))
    15041542        AssertRCReturn(rc, rc);
     
    15331571    AssertPtrReturnVoid(pStrmSt);
    15341572
    1535     LogFlowFunc(("[SD%RU8]: Destroy\n", pStrmSt->u8SD));
     1573    LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStrmSt->u8SD));
    15361574
    15371575    int rc2 = hdaStreamStop(pStrmSt);
    15381576    AssertRC(rc2);
     1577
     1578    hdaStreamMapDestroy(&pStrmSt->State.Mapping);
    15391579
    15401580    if (pStrmSt->State.hMtx != NIL_RTSEMMUTEX)
     
    15551595}
    15561596
    1557 static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8SD)
     1597static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStream, uint8_t u8SD)
    15581598{
    15591599    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1560     AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
    1561 
    1562     pStrmSt->u8SD       = u8SD;
    1563     pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrmSt->u8SD),
    1564                                       HDA_STREAM_REG(pThis, BDPU, pStrmSt->u8SD));
    1565     pStrmSt->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStrmSt->u8SD);
    1566     pStrmSt->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrmSt->u8SD);
    1567     pStrmSt->u16FIFOS   = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStrmSt->u8SD));
    1568 
    1569     RT_ZERO(pStrmSt->State.BDLE);
    1570     pStrmSt->State.uCurBDLE = 0;
     1600    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1601
     1602    pStream->u8SD       = u8SD;
     1603    pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
     1604                                      HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
     1605    pStream->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
     1606    pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
     1607    pStream->u16FIFOS   = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD));
     1608
     1609    RT_ZERO(pStream->State.BDLE);
     1610    pStream->State.uCurBDLE = 0;
     1611
     1612    hdaStreamMapReset(&pStream->State.Mapping);
    15711613
    15721614    LogFlowFunc(("[SD%RU8]: DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
    1573                  pStrmSt->u8SD, pStrmSt->u64BDLBase, pStrmSt->u32CBL, pStrmSt->u16LVI, pStrmSt->u16FIFOS));
     1615                 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS));
    15741616
    15751617#ifdef DEBUG
    1576     uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrmSt->u8SD),
    1577                                       HDA_STREAM_REG(pThis, BDPU, pStrmSt->u8SD));
    1578     uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, pStrmSt->u8SD);
    1579     uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrmSt->u8SD);
     1618    uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
     1619                                      HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
     1620    uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
     1621    uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
    15801622
    15811623    LogFlowFunc(("\t-> DMA @ 0x%x, LVI=%RU16, CBL=%RU32\n", u64BaseDMA, u16LVI, u32CBL));
     
    15871629}
    15881630
    1589 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm)
     1631static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt)
    15901632{
    15911633    AssertPtrReturnVoid(pThis);
    15921634    AssertPtrReturnVoid(pStrmSt);
    1593     AssertReturnVoid(u8Strm <= HDA_MAX_STREAMS);
     1635
     1636    const uint8_t uSD = pStrmSt->u8SD;
    15941637
    15951638#ifdef VBOX_STRICT
    1596     AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
    1597                      ("[SD%RU8] Cannot reset stream while in running state\n", u8Strm));
    1598 #endif
     1639    AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
     1640                     ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
     1641#endif
     1642
     1643    LogFunc(("[SD%RU8]: Reset\n", uSD));
    15991644
    16001645    /*
     
    16131658     * Second, initialize the registers.
    16141659     */
    1615     HDA_STREAM_REG(pThis, STS,   u8Strm) = 0;
     1660    HDA_STREAM_REG(pThis, STS,   uSD) = HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    16161661    /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
    16171662     * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
    1618     HDA_STREAM_REG(pThis, CTL,   u8Strm) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
     1663    HDA_STREAM_REG(pThis, CTL,   uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    16191664    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */
    1620     HDA_STREAM_REG(pThis, FIFOS, u8Strm) = u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
     1665    HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
    16211666    /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
    1622     HDA_STREAM_REG(pThis, FIFOW, u8Strm) = HDA_SDFIFOW_32B;
    1623     HDA_STREAM_REG(pThis, LPIB,  u8Strm) = 0;
    1624     HDA_STREAM_REG(pThis, CBL,   u8Strm) = 0;
    1625     HDA_STREAM_REG(pThis, LVI,   u8Strm) = 0;
    1626     HDA_STREAM_REG(pThis, FMT,   u8Strm) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ,
    1627                                                           HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT,
    1628                                                           HDA_SDFMT_CHAN_STEREO);
    1629     HDA_STREAM_REG(pThis, BDPU,  u8Strm) = 0;
    1630     HDA_STREAM_REG(pThis, BDPL,  u8Strm) = 0;
    1631 
    1632     /*
    1633      * Third, match the internal state to the just set registers.
    1634      */
    1635     pStrmSt->u8SD       = u8Strm;
    1636     pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, u8Strm),
    1637                                       HDA_STREAM_REG(pThis, BDPU, u8Strm));
    1638     pStrmSt->u32CBL     = HDA_STREAM_REG(pThis, CBL,   u8Strm);
    1639     pStrmSt->u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, u8Strm);
    1640     pStrmSt->u16FMT     = HDA_STREAM_REG(pThis, FMT,   u8Strm);
    1641     pStrmSt->u16LVI     = HDA_STREAM_REG(pThis, LVI,   u8Strm);
    1642 
    1643     LogFunc(("[SD%RU8]: Reset\n", u8Strm));
     1667    HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
     1668    HDA_STREAM_REG(pThis, LPIB,  uSD) = 0;
     1669    HDA_STREAM_REG(pThis, CBL,   uSD) = 0;
     1670    HDA_STREAM_REG(pThis, LVI,   uSD) = 0;
     1671    HDA_STREAM_REG(pThis, FMT,   uSD) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ,
     1672                                                       HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT,
     1673                                                       HDA_SDFMT_CHAN_STEREO);
     1674    HDA_STREAM_REG(pThis, BDPU,  uSD) = 0;
     1675    HDA_STREAM_REG(pThis, BDPL,  uSD) = 0;
     1676
     1677    int rc2 = hdaStreamInit(pThis, pStrmSt, uSD);
     1678    AssertRC(rc2);
     1679
     1680    /* Report that we're done resetting this stream. */
     1681    HDA_STREAM_REG(pThis, CTL,   uSD) = 0;
    16441682
    16451683    /* Exit reset state. */
     
    16921730}
    16931731
     1732static int hdaStreamChannelExtract(PPDMAUDIOSTREAMCHANNEL pChan, const void *pvBuf, size_t cbBuf)
     1733{
     1734    AssertPtrReturn(pChan, VERR_INVALID_POINTER);
     1735    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1736    AssertReturn(cbBuf,    VERR_INVALID_PARAMETER);
     1737
     1738    AssertRelease(pChan->cbOff <= cbBuf);
     1739
     1740    const uint8_t *pu8Buf = (const uint8_t *)pvBuf;
     1741
     1742    size_t         cbSrc = cbBuf - pChan->cbOff;
     1743    const uint8_t *pvSrc = &pu8Buf[pChan->cbOff];
     1744
     1745    size_t         cbDst;
     1746    uint8_t       *pvDst;
     1747    RTCircBufAcquireWriteBlock(pChan->Data.pCircBuf, cbBuf, (void **)&pvDst, &cbDst);
     1748
     1749    cbSrc = RT_MIN(cbSrc, cbDst);
     1750
     1751    while (cbSrc)
     1752    {
     1753        AssertBreak(cbDst >= cbSrc);
     1754
     1755        /* Enough data for at least one next frame? */
     1756        if (cbSrc < pChan->cbFrame)
     1757            break;
     1758
     1759        memcpy(pvDst, pvSrc, pChan->cbFrame);
     1760
     1761        /* Advance to next channel frame in stream. */
     1762        pvSrc        += pChan->cbStep;
     1763        Assert(cbSrc >= pChan->cbStep);
     1764        cbSrc        -= pChan->cbStep;
     1765
     1766        /* Advance destination by one frame. */
     1767        pvDst        += pChan->cbFrame;
     1768        Assert(cbDst >= pChan->cbFrame);
     1769        cbDst        -= pChan->cbFrame;
     1770
     1771        /* Adjust offset. */
     1772        pChan->cbOff += pChan->cbFrame;
     1773    }
     1774
     1775    RTCircBufReleaseWriteBlock(pChan->Data.pCircBuf, cbDst);
     1776
     1777    return VINF_SUCCESS;
     1778}
     1779
     1780static int hdaStreamChannelAdvance(PPDMAUDIOSTREAMCHANNEL pChan, size_t cbAdv)
     1781{
     1782    AssertPtrReturn(pChan, VERR_INVALID_POINTER);
     1783
     1784    if (!cbAdv)
     1785        return VINF_SUCCESS;
     1786
     1787    return VINF_SUCCESS;
     1788}
     1789
     1790static int hdaStreamChannelDataInit(PPDMAUDIOSTREAMCHANNELDATA pChanData, uint32_t fFlags)
     1791{
     1792    int rc = RTCircBufCreate(&pChanData->pCircBuf, 256); /** @todo Make this configurable? */
     1793    if (RT_SUCCESS(rc))
     1794    {
     1795        pChanData->fFlags = fFlags;
     1796    }
     1797
     1798    return rc;
     1799}
     1800
     1801/**
     1802 * Frees a stream channel data block again.
     1803 *
     1804 * @param   pChanData           Pointer to channel data to free.
     1805 */
     1806static void hdaStreamChannelDataDestroy(PPDMAUDIOSTREAMCHANNELDATA pChanData)
     1807{
     1808    if (!pChanData)
     1809        return;
     1810
     1811    if (pChanData->pCircBuf)
     1812    {
     1813        RTCircBufDestroy(pChanData->pCircBuf);
     1814        pChanData->pCircBuf = NULL;
     1815    }
     1816
     1817    pChanData->fFlags = PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE;
     1818}
     1819
     1820static int hdaStreamChannelAcquireData(PPDMAUDIOSTREAMCHANNELDATA pChanData, void *pvData, size_t *pcbData)
     1821{
     1822    AssertPtrReturn(pChanData, VERR_INVALID_POINTER);
     1823    AssertPtrReturn(pvData,    VERR_INVALID_POINTER);
     1824    AssertPtrReturn(pcbData,   VERR_INVALID_POINTER);
     1825
     1826    RTCircBufAcquireReadBlock(pChanData->pCircBuf, 256 /** @todo Make this configurarble? */, &pvData, &pChanData->cbAcq);
     1827
     1828    *pcbData = pChanData->cbAcq;
     1829    return VINF_SUCCESS;
     1830}
     1831
     1832static int hdaStreamChannelReleaseData(PPDMAUDIOSTREAMCHANNELDATA pChanData)
     1833{
     1834    AssertPtrReturn(pChanData, VERR_INVALID_POINTER);
     1835    RTCircBufReleaseReadBlock(pChanData->pCircBuf, pChanData->cbAcq);
     1836
     1837    return VINF_SUCCESS;
     1838}
     1839
    16941840static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout)
    16951841{
     
    18211967}
    18221968
    1823 static int hdaRegReadOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    1824 {
    1825     uint16_t u16OUTSTRMPAY = HDA_REG(pThis, OUTPAY);
    1826     LogFlowFunc(("%RU16\n", u16OUTSTRMPAY));
    1827 
    1828     if (pu32Value)
    1829         *pu32Value = u16OUTSTRMPAY;
    1830     return VINF_SUCCESS;
    1831 }
    1832 
    1833 static int hdaRegWriteOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    1834 {
    1835     LogFlowFunc(("%RU16\n", (uint16_t)u32Value));
    1836     return hdaRegWriteU16(pThis, iReg, u32Value);
    1837 }
    1838 
    1839 static int hdaRegReadOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    1840 {
    1841     uint16_t u16OUTSTRMPAY = HDA_REG(pThis, OUTSTRMPAY);
    1842     LogFlowFunc(("%RU16\n", u16OUTSTRMPAY));
    1843 
    1844     if (pu32Value)
    1845         *pu32Value = u16OUTSTRMPAY;
    1846     return VINF_SUCCESS;
    1847 }
    1848 
    1849 static int hdaRegWriteOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    1850 {
    1851     LogFlowFunc(("%RU16\n", (uint16_t)u32Value));
    1852     return hdaRegWriteU16(pThis, iReg, u32Value);
    1853 }
    1854 
    18551969static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    18561970{
     
    18641978    }
    18651979
    1866     for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
    1867     {
    1868         const uint32_t u32STS = HDA_STREAM_REG(pThis, STS, i);
    1869         bool fReport =    (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))
    1870                        || (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))
    1871                        || (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS));
    1872         v |= fReport ? RT_BIT(i) : 0;
    1873     }
    1874 
    1875     v |= v ? RT_BIT(31) : 0;
    1876 
    1877     if (pu32Value)
    1878         *pu32Value = v;
    1879 
     1980#define HDA_MARK_STREAM(x)                                             \
     1981    if (/* Descriptor Error */                                         \
     1982           (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))    \
     1983        /* FIFO Error */                                               \
     1984        || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))    \
     1985        /* Buffer Completion Interrupt Status */                       \
     1986        || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) \
     1987    {                                                                  \
     1988        Log3Func(("[SD%RU8] BCIS: Marked\n", x));                      \
     1989        v |= RT_BIT(x);                                                \
     1990    }
     1991
     1992    HDA_MARK_STREAM(0); /* SD0: Input. */
     1993    HDA_MARK_STREAM(4); /* SD4: Output. */
     1994
     1995#undef HDA_MARK_STREAM
     1996
     1997    /* "OR" bit of all interrupt status bits. */
     1998    if (v)
     1999        v |= RT_BIT(31);
     2000
     2001    *pu32Value = v;
    18802002    return VINF_SUCCESS;
    18812003}
     
    20112133    bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    20122134
     2135uint32_t uVal = HDA_REG_IND(pThis, iReg);
     2136    LogFunc(("uVal=%RU32 vs u32Value=%RU32\n", uVal, u32Value));
     2137
    20132138    if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    20142139        return VINF_SUCCESS;
     
    20752200
    20762201        LogFunc(("[SD%RU8]: Guest initiated enter to stream reset\n", pStrmSt->u8SD));
    2077         hdaStreamReset(pThis, pStrmSt, pStrmSt->u8SD);
     2202        hdaStreamReset(pThis, pStrmSt);
    20782203#endif
    20792204    }
     
    20892214            LogFunc(("[SD%RU8]: fRun=%RTbool\n", pStrmSt->u8SD, fRun));
    20902215
    2091             Assert(pStrmSt->u8SD < HDA_MAX_STREAMS);
    2092 
    2093             /*
    2094              * The register layout specifies that input streams (SDI) come first,
    2095              * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
    2096              * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
    2097              */
    2098             PHDADRIVER pDrv;
    2099             if (pStrmSt->u8SD < HDA_MAX_SDI)
     2216            AUDMIXSINKCMD enmCmd = fRun
     2217                                 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
     2218
     2219            if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
    21002220            {
    21012221# ifdef VBOX_WITH_HDA_MIC_IN
    2102 #  error "Implement mic-in support!"
    2103 # else
    2104                 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    2105                         pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
    2106                                                       pDrv->LineIn.pGstStrm, fRun);
     2222                AudioMixerSinkCtl(pThis->pSinkMicIn,  enmCmd);
    21072223# endif
     2224                AudioMixerSinkCtl(pThis->pSinkLineIn, enmCmd);
    21082225            }
    21092226            else
    21102227            {
    2111                 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    2112                 {
    2113                     pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Front.pGstStrm,     fRun);
     2228                AudioMixerSinkCtl(pThis->pSinkFront,     enmCmd);
    21142229# ifdef VBOX_WITH_HDA_51_SURROUND
    2115                     pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->CenterLFE.pGstStrm, fRun);
    2116                     pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Rear.pGstStrm,      fRun);
     2230                AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmd);
     2231                AudioMixerSinkCtl(pThis->pSinkRear,      enmCmd);
    21172232# endif
    2118                 }
     2233            }
     2234
     2235            if (fRun)
     2236            {
     2237                /* (Re-)Fetch the current BDLE entry. */
     2238                rc2 = hdaBDLEFetch(pThis, &pStrmSt->State.BDLE, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE);
     2239                AssertRC(rc2);
    21192240            }
    21202241        }
     
    21242245#endif /* IN_RING3 */
    21252246    }
     2247
     2248    /* Make sure to handle interrupts here as well. */
     2249    hdaProcessInterrupt(pThis);
    21262250
    21272251#ifdef IN_RING3
     
    21422266
    21432267    uint32_t v  = HDA_REG_IND(pThis, iReg);
     2268             /* Clear (zero) FIFOE and DESE bits when writing 1 to it. */
    21442269             v &= ~(u32Value & v);
     2270
    21452271    HDA_REG_IND(pThis, iReg) = v;
    21462272
     
    22112337        return VINF_SUCCESS;
    22122338
     2339    uint8_t  uSD      = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
    22132340    /** @todo Only allow updating FIFOS if RUN bit is 0? */
    22142341    uint32_t u32FIFOS = 0;
    22152342
    2216     /** @todo Check if this is a SDI and deny writes to this. */
     2343    if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) /* FIFOS for input streams is read-only. */
     2344    {
     2345        LogRel(("HDA: Warning: Guest tried to write read-only FIFOS for input stream #%RU8, skipping\n", uSD));
     2346        AssertFailed();
     2347        return VINF_SUCCESS;
     2348    }
     2349
    22172350    switch(u32Value)
    22182351    {
     
    22292362            /* Fall through is intentional. */
    22302363        default:
     2364            LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to input stream #%RU8, defaulting to 192 bytes\n",
     2365                    u32Value, uSD));
    22312366            u32FIFOS = HDA_SDONFIFO_192B;
     2367            AssertFailed();
    22322368            break;
    22332369    }
     
    22462382
    22472383#ifdef IN_RING3
    2248 static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pCfg)
    2249 {
    2250     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     2384static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pStrmCfg)
     2385{
     2386    AssertPtrReturn(pStrmCfg, VERR_INVALID_POINTER);
    22512387
    22522388# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
     
    22872423    }
    22882424
    2289     PDMAUDIOFMT enmFmt      = AUD_FMT_S16; /* Default to 16-bit signed. */
    2290     uint8_t     cSampleBits = 16;
     2425    PDMAUDIOFMT enmFmt;
    22912426    switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
    22922427    {
    22932428        case 0:
    2294             enmFmt      = AUD_FMT_S8;
    2295             cSampleBits = 8;
     2429            enmFmt = PDMAUDIOFMT_S8;
    22962430            break;
    22972431        case 1:
    2298             enmFmt      = AUD_FMT_S16;
    2299             break;
    2300         case 2:
    2301             cSampleBits = 20;
    2302             break;
    2303         case 3:
    2304             cSampleBits = 24;
     2432            enmFmt = PDMAUDIOFMT_S16;
    23052433            break;
    23062434        case 4:
    2307             enmFmt      = AUD_FMT_S32;
    2308             cSampleBits = 32;
     2435            enmFmt = PDMAUDIOFMT_S32;
    23092436            break;
    23102437        default:
     
    23172444    if (RT_SUCCESS(rc))
    23182445    {
    2319         pCfg->uHz           = u32Hz * u32HzMult / u32HzDiv;
    2320         pCfg->cChannels     = (u32SDFMT & 0xf) + 1;
    2321         pCfg->enmFormat     = enmFmt;
    2322         pCfg->enmEndianness = PDMAUDIOHOSTENDIANNESS;
     2446        pStrmCfg->uHz           = u32Hz * u32HzMult / u32HzDiv;
     2447        pStrmCfg->cChannels     = (u32SDFMT & 0xf) + 1;
     2448        pStrmCfg->enmFormat     = enmFmt;
     2449        pStrmCfg->enmEndianness = PDMAUDIOHOSTENDIANNESS;
    23232450    }
    23242451
     
    23262453    return rc;
    23272454}
    2328 #endif
     2455
     2456static int hdaAddStreamOut(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
     2457{
     2458    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2459    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
     2460
     2461    AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
     2462
     2463    LogFlowFunc(("Stream=%s\n", pCfg->szName));
     2464
     2465    int rc = VINF_SUCCESS;
     2466
     2467    bool fUseFront = true; /* Always use front out by default. */
     2468#ifdef VBOX_WITH_HDA_51_SURROUND
     2469    bool fUseRear;
     2470    bool fUseCenter;
     2471    bool fUseLFE;
     2472
     2473    fUseRear = fUseCenter = fUseLFE = false;
     2474
     2475    /*
     2476     * Use commonly used setups for speaker configurations.
     2477     */
     2478
     2479    /** @todo Make the following configurable through mixer API and/or CFGM? */
     2480    switch (pCfg->cChannels)
     2481    {
     2482        case 3:  /* 2.1: Front (Stereo) + LFE. */
     2483        {
     2484            fUseLFE   = true;
     2485            break;
     2486        }
     2487
     2488        case 4:  /* Quadrophonic: Front (Stereo) + Rear (Stereo). */
     2489        {
     2490            fUseRear  = true;
     2491            break;
     2492        }
     2493
     2494        case 5:  /* 4.1: Front (Stereo) + Rear (Stereo) + LFE. */
     2495        {
     2496            fUseRear  = true;
     2497            fUseLFE   = true;
     2498            break;
     2499        }
     2500
     2501        case 6:  /* 5.1: Front (Stereo) + Rear (Stereo) + Center/LFE. */
     2502        {
     2503            fUseRear   = true;
     2504            fUseCenter = true;
     2505            fUseLFE    = true;
     2506            break;
     2507        }
     2508
     2509        default: /* Unknown; fall back to 2 front channels (stereo). */
     2510        {
     2511            rc = VERR_NOT_SUPPORTED;
     2512            break;
     2513        }
     2514    }
     2515#else /* !VBOX_WITH_HDA_51_SURROUND */
     2516    if (   pCfg->cChannels != 1 /* Mono */
     2517        && pCfg->cChannels != 2 /* Stereo */)
     2518    {
     2519        rc = VERR_NOT_SUPPORTED;
     2520    }
     2521#endif
     2522
     2523    if (RT_FAILURE(rc))
     2524    {
     2525        LogRel(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->cChannels));
     2526        pCfg->cChannels = 2;
     2527    }
     2528
     2529    do
     2530    {
     2531        if (fUseFront)
     2532        {
     2533            if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Front"))
     2534            {
     2535                rc = VERR_BUFFER_OVERFLOW;
     2536                break;
     2537            }
     2538
     2539            pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     2540            pCfg->cChannels       = 2;
     2541            rc = hdaCodecRemoveStream(pThis->pCodec,  PDMAUDIOMIXERCTL_FRONT);
     2542            if (RT_SUCCESS(rc))
     2543                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
     2544        }
     2545
     2546#ifdef VBOX_WITH_HDA_51_SURROUND
     2547        if (   RT_SUCCESS(rc)
     2548            && (fUseCenter || fUseLFE))
     2549        {
     2550            if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Center/LFE"))
     2551            {
     2552                rc = VERR_BUFFER_OVERFLOW;
     2553                break;
     2554            }
     2555
     2556            pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE;
     2557            pCfg->cChannels       = (fUseCenter && fUseLFE) ? 2 : 1;
     2558            rc = hdaCodecRemoveStream(pThis->pCodec,  PDMAUDIOMIXERCTL_CENTER_LFE);
     2559            if (RT_SUCCESS(rc))
     2560                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
     2561
     2562            RTStrFree(pszName);
     2563        }
     2564
     2565        if (   RT_SUCCESS(rc)
     2566            && fUseRear)
     2567        {
     2568            if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Rear"))
     2569            {
     2570                rc = VERR_BUFFER_OVERFLOW;
     2571                break;
     2572            }
     2573
     2574            pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR;
     2575            pCfg->cChannels       = 2;
     2576            rc = hdaCodecRemoveStream(pThis->pCodec,  PDMAUDIOMIXERCTL_REAR);
     2577            if (RT_SUCCESS(rc))
     2578                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
     2579        }
     2580#endif /* VBOX_WITH_HDA_51_SURROUND */
     2581
     2582    } while (0);
     2583
     2584    return rc;
     2585}
     2586
     2587static int hdaAddStreamIn(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
     2588{
     2589    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2590    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
     2591
     2592    AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER);
     2593
     2594    LogFlowFunc(("Stream=%s\n", pCfg->szName));
     2595
     2596    int rc;
     2597
     2598    switch (pCfg->DestSource.Source)
     2599    {
     2600        case PDMAUDIORECSOURCE_LINE:
     2601        {
     2602            pCfg->DestSource.Source = PDMAUDIORECSOURCE_LINE;
     2603            pCfg->cChannels         = 2;
     2604            rc = hdaCodecRemoveStream(pThis->pCodec,  PDMAUDIOMIXERCTL_LINE_IN);
     2605            if (RT_SUCCESS(rc))
     2606                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
     2607            break;
     2608        }
     2609#ifdef VBOX_WITH_HDA_MIC_IN
     2610        case PDMAUDIORECSOURCE_MIC:
     2611        {
     2612            pCfg->DestSource.Source = PDMAUDIORECSOURCE_MIC;
     2613            pCfg->cChannels         = 2;
     2614            rc = hdaCodecRemoveStream(pThis->pCodec,  PDMAUDIOMIXERCTL_MIC_IN);
     2615            if (RT_SUCCESS(rc))
     2616                rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
     2617            break;
     2618        }
     2619#endif
     2620        default:
     2621            rc = VERR_NOT_SUPPORTED;
     2622            break;
     2623    }
     2624
     2625    return rc;
     2626}
     2627#endif /* IN_RING3 */
    23292628
    23302629static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    23312630{
    23322631#ifdef IN_RING3
     2632    if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
     2633        return VINF_SUCCESS;
     2634
    23332635    PDMAUDIOSTREAMCFG strmCfg;
     2636    RT_ZERO(strmCfg);
     2637
    23342638    int rc = hdaSDFMTToStrmCfg(u32Value, &strmCfg);
    23352639    if (RT_FAILURE(rc))
    23362640        return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    23372641
    2338     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2339         return VINF_SUCCESS;
    2340 
    23412642    PHDASTREAM pStrmSt = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FMT, iReg));
    23422643    if (!pStrmSt)
     
    23502651    AssertRC(rc);
    23512652
    2352     LogFlowFunc(("[SD%RU8]: Hz=%RU32, Channels=%RU8, enmFmt=%RU32\n",
    2353                  pStrmSt->u8SD, strmCfg.uHz, strmCfg.cChannels, strmCfg.enmFormat));
    2354 
    2355     PDMAUDIOMIXERCTL enmMixerCtl;
    2356 #ifdef VBOX_WITH_HDA_51_SURROUND
    2357 # error "Implement me!"
    2358 #endif
    2359 
    2360     enmMixerCtl = PDMAUDIOMIXERCTL_FRONT;
    2361     strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     2653    LogFunc(("[SD%RU8]: Hz=%RU32, Channels=%RU8, enmFmt=%RU32\n",
     2654             pStrmSt->u8SD, strmCfg.uHz, strmCfg.cChannels, strmCfg.enmFormat));
     2655
     2656    /* Set audio direction. */
     2657    strmCfg.enmDir = hdaGetDirFromSD(pStrmSt->u8SD);
     2658
     2659    /*
     2660     * Initialize the stream mapping in any case, regardless if
     2661     * we support surround audio or not. This is needed to handle
     2662     * the supported channels within a single audio stream, e.g. mono/stereo.
     2663     *
     2664     * In other words, the stream mapping *always* knowns the real
     2665     * number of channels in a single audio stream.
     2666     */
     2667    rc = hdaStreamMapInit(&pStrmSt->State.Mapping, &strmCfg);
     2668    AssertRC(rc);
    23622669
    23632670    if (RT_SUCCESS(rc))
    23642671    {
     2672        int rc2;
    23652673        PHDADRIVER pDrv;
    23662674        RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    23672675        {
    2368             int rc2 = hdaCodecRemoveStream(pThis->pCodec, enmMixerCtl);
    2369             if (RT_SUCCESS(rc2))
    2370                 rc2 = hdaCodecAddStream(pThis->pCodec, enmMixerCtl, &strmCfg);
     2676            switch (strmCfg.enmDir)
     2677            {
     2678                case PDMAUDIODIR_OUT:
     2679                    rc2 = hdaAddStreamOut(pThis, &strmCfg);
     2680                    break;
     2681
     2682                case PDMAUDIODIR_IN:
     2683                    rc2 = hdaAddStreamIn(pThis, &strmCfg);
     2684                    break;
     2685
     2686                default:
     2687                    rc2 = VERR_NOT_SUPPORTED;
     2688                    AssertFailed();
     2689                    break;
     2690            }
    23712691
    23722692            if (   RT_FAILURE(rc2)
     
    25062826    {
    25072827#ifdef IN_RING3
    2508         PFNHDACODECVERBPROCESSOR    pfn = NULL;
    2509         uint64_t                    resp;
    2510         uint32_t cmd = HDA_REG(pThis, IC);
     2828        uint32_t uCmd = HDA_REG(pThis, IC);
     2829
    25112830        if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP))
    25122831        {
    25132832            /*
    2514              * 3.4.3 defines behavior of immediate Command status register.
     2833             * 3.4.3: Defines behavior of immediate Command status register.
    25152834             */
    2516             LogRel(("guest attempted process immediate verb (%x) with active CORB\n", cmd));
     2835            LogRel(("HDA: Guest attempted process immediate verb (%x) with active CORB\n", uCmd));
    25172836            return rc;
    25182837        }
     2838
    25192839        HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB);  /* busy */
    2520         LogFunc(("IC:%x\n", cmd));
    2521 
    2522         rc = pThis->pCodec->pfnLookup(pThis->pCodec,
    2523                                       HDA_CODEC_CMD(cmd, 0 /* LUN */),
    2524                                       &pfn);
    2525         if (RT_FAILURE(rc))
    2526             AssertRCReturn(rc, rc);
    2527         rc = pfn(pThis->pCodec,
    2528                  HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp);
    2529         if (RT_FAILURE(rc))
    2530             AssertRCReturn(rc, rc);
    2531 
    2532         HDA_REG(pThis, IR) = (uint32_t)resp;
    2533         LogFunc(("IR:%x\n", HDA_REG(pThis, IR)));
    2534         HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV);  /* result is ready  */
     2840
     2841        uint64_t uResp;
     2842        int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec,
     2843                                           HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
     2844        if (RT_FAILURE(rc2))
     2845            LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2));
     2846
     2847        HDA_REG(pThis, IR)   = (uint32_t)uResp; /** @todo r=andy Do we need a 64-bit response? */
     2848        HDA_REG(pThis, IRS)  = HDA_REG_FIELD_FLAG_MASK(IRS, IRV);  /* result is ready  */
    25352849        HDA_REG(pThis, IRS) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
    25362850#else /* !IN_RING3 */
     
    25892903
    25902904            /* Also make sure to handle the DMA position enable bit. */
    2591             pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);
     2905            pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));
    25922906            LogRel(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));
    25932907            break;
     
    26702984    AssertPtrReturn(pBDLE,   VERR_INVALID_POINTER);
    26712985    AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
     2986
     2987    if (!u64BaseDMA)
     2988    {
     2989        LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));
     2990        return VERR_NOT_FOUND;
     2991    }
    26722992    /** @todo Compare u16Entry with LVI. */
    26732993
     
    26863006        return VERR_INVALID_STATE;
    26873007
    2688     pBDLE->fIntOnCompletion  = (*(uint32_t *)&uBundleEntry[12]) & 0x1;
     3008    pBDLE->fIntOnCompletion  = (*(uint32_t *)&uBundleEntry[12]) & RT_BIT(0);
    26893009
    26903010    return VINF_SUCCESS;
     
    26993019DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbMax)
    27003020{
    2701     AssertPtrReturn(pThis, 0);
     3021    AssertPtrReturn(pThis,   0);
    27023022    AssertPtrReturn(pStrmSt, 0);
    27033023
     
    27073027    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
    27083028
    2709     uint32_t cbFree = pStrmSt->u32CBL - HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD);
     3029    uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD);
     3030    Assert(u32LPIB <= pStrmSt->u32CBL);
     3031
     3032    uint32_t cbFree = pStrmSt->u32CBL - u32LPIB; /** @todo Convert samples to bytes? */
    27103033    if (cbFree)
    27113034    {
     
    27713094}
    27723095
     3096#ifdef IN_RING3
     3097/**
     3098 * Initializes a stream mapping structure according to the given stream configuration.
     3099 *
     3100 * @return  IPRT status code.
     3101 * @param   pMapping            Pointer to mapping to initialize.
     3102 * @param   pCfg                Pointer to stream configuration to use.
     3103 */
     3104static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg)
     3105{
     3106    AssertPtrReturn(pMapping, VERR_INVALID_POINTER);
     3107    AssertPtrReturn(pCfg,     VERR_INVALID_POINTER);
     3108
     3109    AssertReturn(pCfg->cChannels, VERR_INVALID_PARAMETER);
     3110
     3111    hdaStreamMapReset(pMapping);
     3112
     3113    pMapping->paChannels = (PPDMAUDIOSTREAMCHANNEL)RTMemAlloc(sizeof(PDMAUDIOSTREAMCHANNEL) * pCfg->cChannels);
     3114    if (!pMapping->paChannels)
     3115        return VERR_NO_MEMORY;
     3116
     3117    PDMPCMPROPS Props;
     3118    int rc = DrvAudioStreamCfgToProps(pCfg, &Props);
     3119    if (RT_FAILURE(rc))
     3120        return rc;
     3121
     3122    Assert(RT_IS_POWER_OF_TWO(Props.cBits));
     3123
     3124    /** @todo We assume all channels in a stream have the same format. */
     3125    PPDMAUDIOSTREAMCHANNEL pChan = pMapping->paChannels;
     3126    for (uint8_t i = 0; i < pCfg->cChannels; i++)
     3127    {
     3128        pChan->uChannel = i;
     3129        pChan->cbStep   = (Props.cBits / 2);
     3130        pChan->cbFrame  = pChan->cbStep * pCfg->cChannels;
     3131        pChan->cbFirst  = i * pChan->cbStep;
     3132        pChan->cbOff    = pChan->cbFirst;
     3133
     3134        int rc2 = hdaStreamChannelDataInit(&pChan->Data, PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE);
     3135        if (RT_SUCCESS(rc))
     3136            rc = rc2;
     3137
     3138        if (RT_FAILURE(rc))
     3139            break;
     3140
     3141        pChan++;
     3142    }
     3143
     3144    if (RT_SUCCESS(rc))
     3145        rc = RTCircBufCreate(&pMapping->pCircBuf, _4K);
     3146
     3147    if (RT_SUCCESS(rc))
     3148    {
     3149        pMapping->cChannels = pCfg->cChannels;
     3150#ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
     3151        pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
     3152#else
     3153        pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
     3154#endif
     3155    }
     3156
     3157    return rc;
     3158}
     3159
     3160/**
     3161 * Destroys a given stream mapping.
     3162 *
     3163 * @param   pMapping            Pointer to mapping to destroy.
     3164 */
     3165static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping)
     3166{
     3167    hdaStreamMapReset(pMapping);
     3168
     3169    if (pMapping->pCircBuf)
     3170    {
     3171        RTCircBufDestroy(pMapping->pCircBuf);
     3172        pMapping->pCircBuf = NULL;
     3173    }
     3174}
     3175
     3176/**
     3177 * Resets a given stream mapping.
     3178 *
     3179 * @param   pMapping            Pointer to mapping to reset.
     3180 */
     3181static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping)
     3182{
     3183    AssertPtrReturnVoid(pMapping);
     3184
     3185    pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN;
     3186
     3187    if (pMapping->cChannels)
     3188    {
     3189        for (uint8_t i = 0; i < pMapping->cChannels; i++)
     3190            hdaStreamChannelDataDestroy(&pMapping->paChannels[i].Data);
     3191
     3192        AssertPtr(pMapping->paChannels);
     3193        RTMemFree(pMapping->paChannels);
     3194        pMapping->paChannels = NULL;
     3195
     3196        pMapping->cChannels = 0;
     3197    }
     3198}
     3199#endif /* IN_RING3 */
     3200
    27733201DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStrmSt)
    27743202{
     
    27933221                 pStrmSt->u8SD, u32LPIB, pStrmSt->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE));
    27943222
    2795     if (fCBLLimitReached)
    2796     {
    2797         /* Reset LPIB register. */
    2798         u32LPIB -= RT_MIN(u32LPIB, pStrmSt->u32CBL);
    2799         hdaStreamUpdateLPIB(pThis, pStrmSt, u32LPIB);
    2800     }
    2801 
    28023223    return fNeedsNextBDLE;
    28033224}
     
    28113232
    28123233    Assert(cbInc <= pStrmSt->u16FIFOS);
     3234
     3235    if (!cbInc) /* Nothing to do? Bail out early. */
     3236        return;
    28133237
    28143238    PHDABDLE pBDLE = &pStrmSt->State.BDLE;
     
    28213245    if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */
    28223246    {
    2823         const uint32_t u32LPIB = RT_MIN(HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD) + cbInc,
    2824                                         pStrmSt->u32CBL);
     3247        uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD);
     3248
     3249        AssertMsg(((u32LPIB + cbInc) <= pStrmSt->u32CBL),
     3250                  ("[SD%RU8] Increment (%RU32) exceeds CBL (%RU32): LPIB (%RU32)\n",
     3251                   pStrmSt->u8SD, cbInc, pStrmSt->u32CBL, u32LPIB));
     3252
     3253        u32LPIB = RT_MIN(u32LPIB + cbInc, pStrmSt->u32CBL);
    28253254
    28263255        LogFlowFunc(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
     
    28333262}
    28343263
    2835 static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStrmSt)
     3264static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStream, bool *pfInterrupt)
    28363265{
    28373266    AssertPtrReturn(pThis,   true);
    2838     AssertPtrReturn(pStrmSt, true);
    2839 
     3267    AssertPtrReturn(pStream, true);
     3268
     3269    bool fInterrupt  = false;
    28403270    bool fIsComplete = false;
    28413271
    2842     PHDABDLE       pBDLE   = &pStrmSt->State.BDLE;
    2843     const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD);
    2844 
    2845     if (   pBDLE->State.u32BufOff >= pBDLE->u32BufSize
    2846         || u32LPIB                >= pStrmSt->u32CBL)
     3272    PHDABDLE       pBDLE   = &pStream->State.BDLE;
     3273    const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
     3274
     3275    /* Check if the current BDLE entry is complete (full). */
     3276    if (pBDLE->State.u32BufOff >= pBDLE->u32BufSize)
    28473277    {
    28483278        Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
    2849         Assert(u32LPIB                <= pStrmSt->u32CBL);
    28503279
    28513280        if (/* IOC (Interrupt On Completion) bit set? */
     
    28553284           )
    28563285        {
    2857             /**
    2858              * Set the BCIS (Buffer Completion Interrupt Status) flag as the
    2859              * last byte of data for the current descriptor has been fetched
    2860              * from memory and put into the DMA FIFO.
    2861              *
    2862              ** @todo More carefully investigate BCIS flag.
    2863              *
    2864              * Speech synthesis works fine on Mac Guest if this bit isn't set
    2865              * but in general sound quality gets worse.
    2866              */
    2867             HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     3286            LogFlowFunc(("[SD%RU8]: %R[bdle] => COMPLETE\n",  pStream->u8SD, pBDLE));
    28683287
    28693288            /*
     
    28713290             * we need to generate an interrupt.
    28723291             */
    2873             if (HDA_STREAM_REG(pThis, CTL, pStrmSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    2874                 hdaProcessInterrupt(pThis);
     3292            if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
     3293                fInterrupt = true;
    28753294        }
    28763295
     
    28783297    }
    28793298
    2880     LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, %R[bdle] => %s\n",
    2881                  pStrmSt->u8SD, u32LPIB, pStrmSt->u32CBL, pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
     3299    if (pfInterrupt)
     3300        *pfInterrupt = fInterrupt;
     3301
     3302    LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, fIsComplete=%RTbool, fInterrupt=%RTbool, %R[bdle]\n",
     3303                 pStream->u8SD, u32LPIB, pStream->u32CBL, fIsComplete, fInterrupt, pBDLE));
    28823304
    28833305    return fIsComplete;
     
    28953317    /* pcbRead is optional. */
    28963318
    2897     PHDABDLE pBDLE = &pStrmSt->State.BDLE;
    2898 
    28993319    int rc;
    29003320    uint32_t cbRead = 0;
    2901     uint32_t cbBuf  = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
    2902 
    2903     LogFlowFunc(("cbBuf=%RU32, %R[bdle]\n", cbBuf, pBDLE));
    2904 
    2905     if (!cbBuf)
    2906     {
    2907         /* Nothing to write, bail out. */
    2908         rc = VINF_EOF;
    2909     }
    2910     else
    2911     {
    2912         rc = AudioMixerProcessSinkIn(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead);
    2913         if (RT_SUCCESS(rc))
     3321
     3322    do
     3323    {
     3324        PHDABDLE pBDLE = &pStrmSt->State.BDLE;
     3325
     3326        uint32_t cbBuf = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
     3327        Log3Func(("cbBuf=%RU32, %R[bdle]\n", cbBuf, pBDLE));
     3328
     3329        if (!cbBuf)
    29143330        {
    2915             Assert(cbRead);
    2916             Assert(cbRead == cbBuf);
    2917             Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff);
    2918 
    2919             /*
    2920              * Write to the BDLE's DMA buffer.
    2921              */
    2922             rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    2923                                        pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
    2924                                        pBDLE->State.au8FIFO, cbRead);
    2925             AssertRC(rc);
    2926 
    2927             if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStrmSt))
    2928             {
    2929                 pBDLE->State.u32BufOff    += cbRead;
    2930                 pBDLE->State.cbBelowFIFOW  = 0;
    2931                 //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail);
    2932             }
    2933             else
    2934             {
    2935                 pBDLE->State.u32BufOff    += cbRead;
    2936                 pBDLE->State.cbBelowFIFOW += cbRead;
    2937                 Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt));
    2938                 //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail);
    2939 
    2940                 rc = VERR_NO_DATA;
    2941             }
     3331            rc = VINF_EOF;
     3332            break;
    29423333        }
    2943     }
    2944 
    2945     Assert(cbRead <= pStrmSt->u16FIFOS);
     3334
     3335        rc = AudioMixerSinkRead(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead);
     3336        if (RT_FAILURE(rc))
     3337            break;
     3338
     3339        if (!cbRead)
     3340        {
     3341            rc = VINF_EOF;
     3342            break;
     3343        }
     3344
     3345        /* Sanity checks. */
     3346        Assert(cbRead <= cbBuf);
     3347        Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff);
     3348        Assert(cbRead <= pStrmSt->u16FIFOS);
     3349
     3350        /*
     3351         * Write to the BDLE's DMA buffer.
     3352         */
     3353        rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
     3354                                   pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
     3355                                   pBDLE->State.au8FIFO, cbRead);
     3356        AssertRC(rc);
     3357
     3358        if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStrmSt))
     3359        {
     3360            pBDLE->State.u32BufOff    += cbRead;
     3361            pBDLE->State.cbBelowFIFOW  = 0;
     3362            //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail);
     3363        }
     3364        else
     3365        {
     3366            pBDLE->State.u32BufOff    += cbRead;
     3367            pBDLE->State.cbBelowFIFOW += cbRead;
     3368            Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt));
     3369            //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail);
     3370
     3371            rc = VERR_NO_DATA;
     3372        }
     3373
     3374    } while (0);
    29463375
    29473376    if (RT_SUCCESS(rc))
     
    29513380    }
    29523381
    2953     LogFunc(("Returning cbRead=%RU32, rc=%Rrc\n", cbRead, rc));
     3382    Log3Func(("Returning cbRead=%RU32, rc=%Rrc\n", cbRead, rc));
    29543383    return rc;
    29553384}
     
    29653394
    29663395    uint32_t cbWritten = 0;
    2967     uint32_t cbData    = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
    2968 
    2969     LogFlowFunc(("cbData=%RU32, %R[bdle]\n", cbData, pBDLE));
     3396    uint32_t cbToWrite = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);
     3397
     3398    Log3Func(("cbToWrite=%RU32, %R[bdle]\n", cbToWrite, pBDLE));
    29703399
    29713400    /*
     
    29743403     */
    29753404    int rc;
    2976     if (!cbData)
     3405    if (!cbToWrite)
    29773406    {
    29783407        rc = VINF_EOF;
     
    29803409    else
    29813410    {
     3411        void    *pvBuf = pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW;
     3412        Assert(cbToWrite >= pBDLE->State.cbBelowFIFOW);
     3413        uint32_t cbBuf = cbToWrite - pBDLE->State.cbBelowFIFOW;
     3414
    29823415        /*
    29833416         * Read from the current BDLE's DMA buffer.
     
    29853418        rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    29863419                               pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
    2987                                pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW, cbData);
     3420                               pvBuf, cbBuf);
    29883421        AssertRC(rc);
    2989 
    2990 #if 0
     3422#if defined (RT_OS_LINUX) && defined(DEBUG)
    29913423        RTFILE fh;
    2992         RTFileOpen(&fh, "c:\\temp\\hdaWriteAudio.pcm",
     3424        RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm",
    29933425                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    2994         RTFileWrite(fh, pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW, cbData, NULL);
     3426        RTFileWrite(fh, pvBuf, cbBuf, NULL);
    29953427        RTFileClose(fh);
    29963428#endif
    29973429
    29983430#ifdef VBOX_WITH_STATISTICS
    2999         STAM_COUNTER_ADD(&pThis->StatBytesRead, cbData);
     3431        STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);
    30003432#endif
    30013433        /*
    30023434         * Write to audio backend. We should ensure that we have enough bytes to copy to the backend.
    30033435         */
    3004         uint32_t cbToWrite = cbData + pBDLE->State.cbBelowFIFOW;
    3005         if (cbToWrite >= hdaStreamGetFIFOW(pThis, pStrmSt))
     3436        if (cbBuf >= hdaStreamGetFIFOW(pThis, pStrmSt))
    30063437        {
    3007             uint32_t cbWrittenToStream;
     3438            PHDASTREAMMAPPING pMapping            = &pStrmSt->State.Mapping;
     3439
     3440            /** @todo Which channel is which? */
     3441#ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
     3442            PPDMAUDIOSTREAMCHANNEL pChanFront     = &pMapping->paChannels[0];
     3443#endif
     3444#ifdef VBOX_WITH_HDA_51_SURROUND
     3445            PPDMAUDIOSTREAMCHANNEL pChanCenterLFE = &pMapping->paChannels[2]; /** @todo FIX! */
     3446            PPDMAUDIOSTREAMCHANNEL pChanRear      = &pMapping->paChannels[4]; /** @todo FIX! */
     3447#endif
    30083448            int rc2;
    30093449
    3010             PHDADRIVER pDrv;
    3011             RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    3012             {
    3013                 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pGstStrm))
    3014                 {
     3450            void  *pvDataFront = NULL;
     3451            size_t cbDataFront;
    30153452#ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
    3016                     /** @todo Needs more hacking first. */
    3017 # if 0
    3018                     static int16_t restBuf = 0;
    3019                     static size_t cbRestOff = 0;
    3020 
    3021                     uint8_t temp[HDA_SDONFIFO_256B + 1];
    3022 
    3023                     uint8_t *pu8Src = &pBDLE->State.au8FIFO[0];
    3024                     uint8_t *pu8Dst = &temp[0];
    3025 
    3026                     size_t cbSample = sizeof(int16_t) * 2;
    3027 
    3028                     size_t cbProc     = 0;
    3029                     size_t cbToSkip   = 5 * cbSample;
    3030                     size_t cbSkipSize = cbToSkip;
    3031                     size_t cbDstSize  = 0;
    3032 
    3033                     while (cbProc < cbToWrite)
    3034                     {
    3035                         memcpy(pu8Dst, pu8Src, cbSample);
    3036 
    3037                         cbSkipSize = RT_MIN(cbToSkip, cbToWrite - cbProc);
    3038 
    3039                         pu8Src += 10;
    3040                         cbProc += cbSkipSize;
    3041 
    3042                         pu8Dst    += 4;
    3043                         cbDstSize += cbSample;
    3044                     }
    3045 
    3046                     /* Sanity. */
    3047                     AssertMsg(((cbDstSize * 8 /* Bit */) % 16) == 0, ("ASDF\n"));
    3048 
    3049                     LogFlowFunc(("cbRest=%zu, cbToWrite=%zu, cbProc=%zu, cbDstSize=%zu\n",
    3050                                  0, cbToWrite, cbProc, cbDstSize));
    3051 
    3052                     rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    3053                                                      temp, cbDstSize, &cbWrittenToStream);
    3054 # if 1
    3055                     RTFILE fh;
    3056                     RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm",
    3057                                RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    3058                     RTFileWrite(fh, temp, cbDstSize, NULL);
    3059                     RTFileClose(fh);
    3060 # endif
    3061 
    3062 # else
    3063                     int16_t *pvStart;
    3064                     size_t cbAcqWrite;
    3065                     RTCircBufAcquireWriteBlock(pThis->pCircBuf, cbToWrite, (void **)&pvStart, &cbAcqWrite);
    3066 
    3067                     uint8_t cChannels = 1;
    3068                     size_t cbSample = sizeof(int16_t);
    3069 
    3070                     int16_t *pi16Src = (int16_t *)&pBDLE->State.au8FIFO[0];
    3071                     int16_t *pi16Dst = pvStart;
    3072 
    3073                     size_t cbProcSrc     = 0;
    3074                     size_t cbProcDst     = 0;
    3075 
    3076                     while (cbProcSrc < cbAcqWrite)
    3077                     {
    3078                         memcpy(pi16Dst, pi16Src, cbSample);
    3079 
    3080                         pi16Src  += 6 * cChannels;
    3081                         pi16Dst  += cChannels;
    3082 
    3083                         cbProcSrc += RT_MIN(cbAcqWrite - cbProcSrc, 6 * cbSample);
    3084                         cbProcDst += cbSample;
    3085 
    3086                         Assert(cbProcSrc <= cbAcqWrite);
    3087                         size_t cbLeft = cbAcqWrite - cbProcSrc;
    3088                         LogFlowFunc(("cbProcSrc=%zu, cbProcDst=%zu, cbLeft=%zu\n", cbProcSrc, cbProcDst, cbLeft));
    3089                         if (   cbLeft
    3090                             && cbLeft < cChannels)
    3091                         {
    3092                             LogFlowFunc(("%zu bytes left ...\n", cbAcqWrite - cbProcSrc));
    3093                             break;
    3094                         }
    3095                     }
    3096 
    3097                     RTCircBufReleaseWriteBlock(pThis->pCircBuf, cbProcDst);
    3098 
    3099                     LogFlowFunc(("cbAcqWrite=%zu, cbToWrite=%zu, cbProcSrc=%zu, cbProcDst=%zu\n",
    3100                                  cbAcqWrite, cbToWrite, cbProcSrc, cbProcDst));
    3101 
    3102                     size_t cbAcqRead = 0;
    3103                     RTCircBufAcquireReadBlock(pThis->pCircBuf, _4K, (void **)&pvStart, &cbAcqRead);
    3104 # if 1
    3105                     RTFILE fh;
    3106                     RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm",
    3107                                RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    3108                     RTFileWrite(fh, pvStart, cbAcqRead, NULL);
    3109                     RTFileClose(fh);
    3110 # endif
    3111                     rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Front.pGstStrm,
    3112                                                      pvStart, cbAcqRead, &cbWrittenToStream);
    3113 
    3114                     /** @todo Add support for writing to center/LFE + rear. */
    3115 
    3116                     RTCircBufReleaseReadBlock(pThis->pCircBuf, cbAcqRead);
    3117 # endif
    3118 
    3119 #else  /* !VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT */
    3120                     rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Front.pGstStrm,
    3121                                                      pBDLE->State.au8FIFO, cbToWrite, &cbWrittenToStream);
    3122 #endif /* VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT */
    3123                     if (RT_SUCCESS(rc2))
    3124                     {
    3125                         if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
    3126                             LogFlowFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, expect lags\n",
    3127                                          pDrv->uLUN, cbWrittenToStream, cbToWrite));
    3128                     }
    3129                 }
    3130                 else /* Stream disabled, not fatal. */
    3131                 {
    3132                     cbWrittenToStream = 0;
    3133                     rc2 = VERR_NOT_AVAILABLE;
    3134                     /* Keep going. */
    3135                 }
    3136 
    3137                 LogFlowFunc(("\tLUN#%RU8: cbToWrite=%RU32, cbWrittenToStream=%RU32, rc=%Rrc\n",
    3138                              pDrv->uLUN, cbToWrite, cbWrittenToStream, rc2));
    3139             }
     3453            rc2 = hdaStreamChannelExtract(pChanFront, pvBuf, cbBuf);
     3454            AssertRC(rc2);
     3455
     3456            rc2 = hdaStreamChannelAcquireData(&pChanFront->Data, pvDataFront, &cbDataFront);
     3457            AssertRC(rc2);
     3458#else
     3459            /* Use stuff in the whole FIFO to use for the channel data. */
     3460            pvDataFront = pvBuf;
     3461            cbDataFront = cbBuf;
     3462#endif
     3463#ifdef VBOX_WITH_HDA_51_SURROUND
     3464            void  *pvDataCenterLFE;
     3465            size_t cbDataCenterLFE;
     3466            rc2 = hdaStreamChannelExtract(pChanCenterLFE, pvBuf, cbBuf);
     3467            AssertRC(rc2);
     3468
     3469            rc2 = hdaStreamChannelAcquireData(&pChanCenterLFE->Data, pvDataCenterLFE, &cbDataCenterLFE);
     3470            AssertRC(rc2);
     3471
     3472            void  *pvDataRear;
     3473            size_t cbDataRear;
     3474            rc2 = hdaStreamChannelExtract(pChanRear, pvBuf, cbBuf);
     3475            AssertRC(rc2);
     3476
     3477            rc2 = hdaStreamChannelAcquireData(&pChanRear->Data, pvDataRear, &cbDataRear);
     3478            AssertRC(rc2);
     3479#endif
     3480            /*
     3481             * Write data to according mixer sinks.
     3482             */
     3483            rc2 = AudioMixerSinkWrite(pThis->pSinkFront,     AUDMIXOP_COPY, pvDataFront,     cbDataFront,
     3484                                      NULL /* pcbWritten */);
     3485            AssertRC(rc2);
     3486#ifdef VBOX_WITH_HDA_51_SURROUND
     3487            rc2 = AudioMixerSinkWrite(pThis->pSinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,
     3488                                      NULL /* pcbWritten */);
     3489            AssertRC(rc2);
     3490            rc2 = AudioMixerSinkWrite(pThis->pSinkRear,      AUDMIXOP_COPY, pvDataRear,      cbDataRear,
     3491                                      NULL /* pcbWritten */);
     3492            AssertRC(rc2);
     3493#endif
     3494
     3495#ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
     3496            hdaStreamChannelReleaseData(&pChanFront->Data);
     3497#endif
     3498#ifdef VBOX_WITH_HDA_51_SURROUND
     3499            hdaStreamChannelReleaseData(&pChanCenterLFE->Data);
     3500            hdaStreamChannelReleaseData(&pChanRear->Data);
     3501#endif
    31403502
    31413503            /* Always report all data as being written;
     
    31433505            cbWritten = cbToWrite;
    31443506
    3145             hdaBDLEUpdate(pBDLE, cbData, cbWritten);
     3507            hdaBDLEUpdate(pBDLE, cbToWrite, cbWritten);
    31463508        }
    31473509        else
     
    31653527    }
    31663528
    3167     LogFunc(("Returning cbWritten=%RU32, rc=%Rrc\n", cbWritten, rc));
     3529    Log3Func(("Returning cbMax=%RU32, cbWritten=%RU32, rc=%Rrc\n", cbMax, cbWritten, rc));
    31683530    return rc;
    31693531}
     
    32233585}
    32243586
    3225 static DECLCALLBACK(int) hdaMixerAddStreamIn(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
     3587static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
    32263588{
    32273589    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    32293591    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    32303592
    3231     AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER);
    3232 
    3233     LogFunc(("Sink=%s, Source=%ld\n", pSink->pszName, pCfg->DestSource.Source));
     3593    LogFunc(("Sink=%s, Stream=%s\n", pSink->pszName, pCfg->szName));
    32343594
    32353595    int rc = VINF_SUCCESS;
     
    32383598    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    32393599    {
    3240         char *pszDesc;
    3241         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pCfg->pszName) <= 0)
     3600        int rc2 = VINF_SUCCESS;
     3601        PHDAMIXERSTREAM pStream;
     3602
     3603        if (pCfg->enmDir == PDMAUDIODIR_IN)
    32423604        {
    3243             rc = VERR_NO_MEMORY;
    3244             break;
     3605            switch (pCfg->DestSource.Source)
     3606            {
     3607                case PDMAUDIORECSOURCE_LINE:
     3608                    pStream = &pDrv->LineIn;
     3609                    break;
     3610#ifdef VBOX_WITH_HDA_MIC_IN
     3611                case PDMAUDIORECSOURCE_MIC:
     3612                    pStream = &pDrv->MicIn;
     3613                    break;
     3614#endif
     3615                default:
     3616                    rc2 = VERR_NOT_SUPPORTED;
     3617                    break;
     3618            }
    32453619        }
    3246 
    3247         int rc2 = VINF_SUCCESS;
    3248         PHDAINPUTSTREAM pStream;
    3249         switch (pCfg->DestSource.Source)
     3620        else if (pCfg->enmDir == PDMAUDIODIR_OUT)
    32503621        {
    3251             case PDMAUDIORECSOURCE_LINE:
    3252                 pStream = &pDrv->LineIn;
    3253                 break;
    3254 #ifdef VBOX_WITH_HDA_MIC_IN
    3255             case PDMAUDIORECSOURCE_MIC:
    3256                 pStream = &pDrv->MicIn;
    3257                 break;
    3258 #endif
    3259             default:
    3260                 rc2 = VERR_NOT_SUPPORTED;
    3261                 break;
     3622            switch (pCfg->DestSource.Dest)
     3623            {
     3624                case PDMAUDIOPLAYBACKDEST_FRONT:
     3625                    pStream = &pDrv->Front;
     3626                    break;
     3627#ifdef VBOX_WITH_HDA_51_SURROUND
     3628                case PDMAUDIOPLAYBACKDEST_CENTER_LFE:
     3629                    pStream = &pDrv->CenterLFE;
     3630                    break;
     3631                case PDMAUDIOPLAYBACKDEST_REAR:
     3632                    pStream = &pDrv->Rear;
     3633                    break;
     3634#endif
     3635                default:
     3636                    rc2 = VERR_NOT_SUPPORTED;
     3637                    break;
     3638            }
    32623639        }
     3640        else
     3641            rc2 = VERR_NOT_SUPPORTED;
    32633642
    32643643        if (RT_SUCCESS(rc2))
    32653644        {
    3266             PPDMAUDIOGSTSTRMIN pGstStrm;
    3267             PAUDMIXSTREAM      pMixStrm;
    3268 
    3269             rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, pCfg, &pGstStrm);
    3270             LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
    3271             if (RT_SUCCESS(rc2))
    3272                 rc2 = AudioMixerAddStreamIn(pSink, pDrv->pConnector, pGstStrm, 0 /* uFlags */, &pMixStrm);
    3273 
     3645            PAUDMIXSTREAM pMixStrm;
     3646            rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm);
    32743647            if (RT_SUCCESS(rc2))
    32753648            {
    3276                 pStream->pGstStrm = pGstStrm;
     3649                rc2 = AudioMixerSinkAddStream(pSink, pMixStrm);
     3650                LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pCfg->szName , rc2));
     3651            }
     3652
     3653            if (RT_SUCCESS(rc2))
    32773654                pStream->pMixStrm = pMixStrm;
    3278             }
    32793655        }
    32803656
    32813657        if (RT_SUCCESS(rc))
    32823658            rc = rc2;
    3283 
    3284         RTStrFree(pszDesc);
    3285     }
    3286 
    3287     LogFlowFuncLeaveRC(rc);
    3288     return rc;
    3289 }
    3290 
    3291 static DECLCALLBACK(int) hdaMixerAddStreamOut(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
    3292 {
    3293     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    3294     AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    3295     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    3296 
    3297     AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
    3298 
    3299     LogFunc(("Sink=%s, Dest=%ld\n", pSink->pszName, pCfg->DestSource.Dest));
    3300 
    3301     int rc = VINF_SUCCESS;
    3302 
    3303     PHDADRIVER pDrv;
    3304     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    3305     {
    3306         char *pszDesc;
    3307         if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
    3308                          pDrv->uLUN, pCfg->pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
    3309         {
    3310             rc = VERR_NO_MEMORY;
    3311             break;
    3312         }
    3313 
    3314         int rc2 = VINF_SUCCESS;
    3315         PHDAOUTPUTSTREAM pStream;
    3316         switch (pCfg->DestSource.Dest)
    3317         {
    3318             case PDMAUDIOPLAYBACKDEST_FRONT:
    3319                 pStream = &pDrv->Front;
    3320                 break;
    3321 #ifdef VBOX_WITH_HDA_51_SURROUND
    3322             case PDMAUDIOPLAYBACKDEST_CENTER_LFE:
    3323                 pStream = &pDrv->CenterLFE;
    3324                 break;
    3325             case PDMAUDIOPLAYBACKDEST_REAR:
    3326                 pStream = &pDrv->Rear;
    3327                 break;
    3328 #endif
    3329             default:
    3330                 rc2 = VERR_NOT_SUPPORTED;
    3331                 break;
    3332         }
    3333 
    3334         if (RT_SUCCESS(rc2))
    3335         {
    3336             PPDMAUDIOGSTSTRMOUT pGstStrm;
    3337             PAUDMIXSTREAM       pMixStrm;
    3338 
    3339             rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pGstStrm);
    3340             LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2));
    3341             if (RT_SUCCESS(rc2))
    3342                 rc2 = AudioMixerAddStreamOut(pSink, pDrv->pConnector, pGstStrm, 0 /* uFlags */, &pMixStrm);
    3343 
    3344             if (RT_SUCCESS(rc2))
    3345             {
    3346                 pStream->pGstStrm = pGstStrm;
    3347                 pStream->pMixStrm = pMixStrm;
    3348             }
    3349         }
    3350 
    3351         if (RT_SUCCESS(rc))
    3352             rc = rc2;
    3353 
    3354         RTStrFree(pszDesc);
    33553659    }
    33563660
     
    33793683    if (pSink)
    33803684    {
    3381         if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
    3382         {
    3383             rc = hdaMixerAddStreamIn(pThis, pSink, pCfg);
    3384         }
    3385         else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
    3386         {
    3387             rc = hdaMixerAddStreamOut(pThis, pSink, pCfg);
    3388         }
    3389         else
    3390         {
    3391             rc = VERR_INVALID_PARAMETER;
    3392             AssertFailed();
    3393         }
     3685        rc = hdaMixerAddStream(pThis, pSink, pCfg);
    33943686    }
    33953687    else
    33963688        rc = VERR_NOT_FOUND;
    33973689
    3398     LogFlowFuncLeaveRC(rc);
     3690    LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pszName, enmMixerCtl, rc));
    33993691    return rc;
    34003692}
     
    34163708    if (pSink)
    34173709    {
    3418         if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
    3419         {
    3420             /** @todo Remove streams. */
    3421         }
    3422         else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
    3423         {
    3424             /** @todo Remove streams. */
    3425         }
    3426         else
    3427         {
    3428             rc = VERR_INVALID_PARAMETER;
    3429             AssertFailed();
    3430         }
     3710        AudioMixerSinkRemoveAllStreams(pSink);
     3711        rc = VINF_SUCCESS;
    34313712    }
    34323713    else
    34333714        rc = VERR_NOT_FOUND;
    34343715
    3435     LogFlowFuncLeaveRC(rc);
     3716    LogFlowFunc(("enmMixerCtl=%ld, rc=%Rrc\n", enmMixerCtl, rc));
    34363717    return rc;
    34373718}
     
    34553736        /* Set the volume.
    34563737         * We assume that the codec already converted it to the correct range. */
    3457         rc = AudioMixerSetSinkVolume(pSink, pVol);
     3738        rc = AudioMixerSinkSetVolume(pSink, pVol);
    34583739    }
    34593740    else
     
    34773758    uint32_t cbOutMin = UINT32_MAX;
    34783759
    3479     int rc;
    3480     PHDADRIVER pDrv;
    3481 
    34823760    uint64_t cTicksNow     = TMTimerGet(pTimer);
    3483     uint64_t cTicksElapsed = cTicksNow  - pThis->uTimerTS;
     3761    uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS;
    34843762    uint64_t cTicksPerSec  = TMTimerGetFreq(pTimer);
    34853763
     
    34993777    uint32_t cbCodecSamplesMin = cCodecSamplesMin << 1;
    35003778
     3779#if 0
    35013780    /*
    35023781     * Process all driver nodes.
    35033782     */
     3783    PHDADRIVER pDrv;
    35043784    RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    35053785    {
     
    35203800         * This is not the optimal solution, but as we have to deal with this on a timer-based approach
    35213801         * (until we have the audio callbacks) we need to have device' DMA engines running. */
    3522         if (!pDrv->pConnector->pfnIsValidOut(pDrv->pConnector, pDrv->Front.pGstStrm))
     3802        if (!AudioMixerStreamIsValid(pDrv->Front.pMixStrm))
    35233803        {
    35243804            /* Use the codec's (fixed) sampling rate. */
     
    35273807        }
    35283808
    3529         const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pGstStrm);
     3809        const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pMixStrm->InOut.pOut);
    35303810        if (   RT_FAILURE(rc)
    35313811            || !fIsActiveOut)
    35323812        {
    3533             uint32_t cSamplesMin  = (int)((2 * cTicksElapsed * pDrv->Front.pGstStrm->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
    3534             uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Front.pGstStrm->MixBuf, cSamplesMin);
     3813            uint32_t cSamplesMin  = (int)((2 * cTicksElapsed * pDrv->Front.pMixStrm->InOut.pOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
     3814            uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Front.pMixStrm->InOut.pOut->MixBuf, cSamplesMin);
    35353815
    35363816#ifdef DEBUG_TIMER
     
    35433823        cbInMax  = RT_MAX(cbInMax, cbIn);
    35443824    }
     3825#else
     3826    AudioMixerSinkUpdate(pThis->pSinkFront);
     3827    cbOutMin = _4K; //cbCodecSamplesMin;
     3828    cbInMax  = _4K;
     3829#endif
    35453830
    35463831#ifdef DEBUG_TIMER
     
    35523837
    35533838    /** @todo Determine the streams to be handled. */
    3554     PHDASTREAM pStrmStIn  = &pThis->aStreams[0];
    3555     PHDASTREAM pStrmStOut = &pThis->aStreams[4];
     3839    PHDASTREAM pStreamLineIn  = &pThis->aStreams[0];
     3840#ifdef VBOX_WITH_HDA_MIC_IN
     3841    /** @todo Anything to do for mic-in? */
     3842#endif
     3843    PHDASTREAM pStreamOut     = &pThis->aStreams[4];
    35563844
    35573845    /* Do the actual device transfers. */
    3558     hdaTransfer(pThis, pStrmStOut, cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);
    3559     hdaTransfer(pThis, pStrmStIn,  cbInMax  /* cbToProcess */, NULL /* pcbProcessed */);
     3846    hdaTransfer(pThis, pStreamOut,    cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);
     3847    hdaTransfer(pThis, pStreamLineIn,  cbInMax  /* cbToProcess */, NULL /* pcbProcessed */);
    35603848
    35613849    /* Kick the timer again. */
     
    36173905#endif /* VBOX_WITH_AUDIO_CALLBACKS */
    36183906
    3619 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbToProcess, uint32_t *pcbProcessed)
     3907static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
    36203908{
    36213909    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    3622     AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     3910    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    36233911    /* pcbProcessed is optional. */
     3912
     3913    // 44100 / 200 Hz Timer = cbToProcess = 220,8
     3914    cbToProcess = 440; // FIFO SIZE
    36243915
    36253916    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
     
    36333924
    36343925    bool fProceed = true;
    3635     int rc = RTSemMutexRequest(pStrmSt->State.hMtx, RT_INDEFINITE_WAIT);
     3926    int rc = RTSemMutexRequest(pStream->State.hMtx, RT_INDEFINITE_WAIT);
    36363927    if (RT_FAILURE(rc))
    36373928        return rc;
    36383929
    36393930    /* Stop request received? */
    3640     if (pStrmSt->State.fDoStop)
    3641     {
    3642         pStrmSt->State.fActive = false;
    3643 
    3644         rc = RTSemEventSignal(pStrmSt->State.hStateChangedEvent);
     3931    if (pStream->State.fDoStop)
     3932    {
     3933        pStream->State.fActive = false;
     3934
     3935        rc = RTSemEventSignal(pStream->State.hStateChangedEvent);
    36453936        AssertRC(rc);
    36463937
     
    36483939    }
    36493940    /* Is the stream not in a running state currently? */
    3650     else if (!(HDA_STREAM_REG(pThis, CTL, pStrmSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
     3941    else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
    36513942        fProceed = false;
    36523943    /* Nothing to process? */
     
    36543945        fProceed = false;
    36553946
     3947#if 0
     3948    Log3Func(("[SD%RU8] fProceed=%RTbool, fRun=%RTbool, cbToProcess=%RU32\n",
     3949              pStrmSt->u8SD, fProceed, HDA_STREAM_REG(pThis, CTL, pStrmSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN),
     3950              cbToProcess));
     3951#endif
     3952
     3953    if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
     3954    {
     3955        Log3Func(("[SD%RU8]: BCIS: Skipping\n", pStream->u8SD));
     3956        fProceed = false;
     3957    }
     3958
    36563959    if (!fProceed)
    36573960    {
    3658         rc = RTSemMutexRelease(pStrmSt->State.hMtx);
     3961        rc = RTSemMutexRelease(pStream->State.hMtx);
    36593962        AssertRC(rc);
    36603963
     
    36653968
    36663969    /* Sanity checks. */
    3667     Assert(pStrmSt->u8SD <= HDA_MAX_STREAMS);
    3668     Assert(pStrmSt->u64BDLBase);
    3669     Assert(pStrmSt->u32CBL);
     3970    Assert(pStream->u8SD <= HDA_MAX_STREAMS);
     3971    Assert(pStream->u64BDLBase);
     3972    Assert(pStream->u32CBL);
    36703973
    36713974    /* State sanity checks. */
    3672     Assert(pStrmSt->State.fInReset == false);
    3673 
    3674     uint32_t cbProcessedTotal = 0;
    3675     bool     fIsComplete      = false;
    3676 
    3677     while (cbToProcess)
    3678     {
     3975    Assert(pStream->State.fInReset == false);
     3976
     3977//    uint32_t cbLeft  = cbToProcess;
     3978    uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
     3979    Assert(u32LPIB <= pStream->u32CBL);
     3980
     3981    if (u32LPIB == pStream->u32CBL)
     3982         u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0);
     3983
     3984    uint32_t cbLeft  = pStream->u32CBL - u32LPIB;
     3985    uint32_t cbTotal = 0;
     3986
     3987    bool fInterrupt = false;
     3988
     3989    Log3Func(("cbLeft=%RU32\n", cbLeft));
     3990
     3991    while (cbLeft)
     3992    {
     3993    #if 1
    36793994        /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
    3680         if (hdaStreamNeedsNextBDLE(pThis, pStrmSt))
     3995        if (hdaStreamNeedsNextBDLE(pThis, pStream))
    36813996        {
    3682             rc = hdaStreamGetNextBDLE(pThis, pStrmSt);
     3997            rc = hdaStreamGetNextBDLE(pThis, pStream);
    36833998            if (RT_FAILURE(rc))
    36843999                break;
    36854000        }
     4001    #else
     4002        PHDABDLE pBDLE   = &pStream->State.BDLE;
     4003
     4004        /* Did we reach the CBL (Cyclic Buffer List) limit? */
     4005        bool fCBLLimitReached = u32LPIB >= pStream->u32CBL;
     4006
     4007        /* Do we need to use the next BDLE entry? Either because we reached
     4008         * the CBL limit or our internal DMA buffer is full. */
     4009        bool fNeedsNextBDLE   = (   fCBLLimitReached
     4010                                 || (pBDLE->State.u32BufOff >= pBDLE->u32BufSize));
     4011
     4012        Assert(u32LPIB                <= pStream->u32CBL);
     4013        Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
     4014
     4015        if (fNeedsNextBDLE)
     4016        {
     4017
     4018
     4019        #if 1
     4020            if (/* IOC (Interrupt On Completion) bit set? */
     4021                   pBDLE->fIntOnCompletion
     4022                /* All data put into the DMA FIFO? */
     4023                && pBDLE->State.cbBelowFIFOW == 0
     4024               )
     4025            {
     4026            //    fSetIRQ = true;
     4027                /*
     4028                 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
     4029                 * we need to generate an interrupt.
     4030                 */
     4031               // if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
     4032                 //   PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
     4033            }
     4034        #endif
     4035
     4036
     4037        }
     4038    #endif
    36864039
    36874040        /* Set the FIFORDY bit on the stream while doing the transfer. */
    3688         HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    3689 
    3690         /*
    3691          * The register layout specifies that input streams (SDI) come first,
    3692          * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
    3693          * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
    3694          */
     4041    //    HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4042
    36954043        uint32_t cbProcessed;
    3696         if (pStrmSt->u8SD < HDA_MAX_SDI)
    3697             rc = hdaReadAudio (pThis, pStrmSt, cbToProcess, &cbProcessed);
     4044        if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
     4045            rc = hdaReadAudio (pThis, pStream, cbLeft, &cbProcessed);
    36984046        else
    3699             rc = hdaWriteAudio(pThis, pStrmSt, cbToProcess, &cbProcessed);
     4047            rc = hdaWriteAudio(pThis, pStream, cbLeft, &cbProcessed);
    37004048
    37014049        /* Remove the FIFORDY bit again. */
    3702         HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4050    //    HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    37034051
    37044052        if (RT_FAILURE(rc))
    37054053            break;
    37064054
    3707         hdaStreamTransferUpdate(pThis, pStrmSt, cbProcessed);
    3708 
    3709         cbToProcess      -= RT_MIN(cbToProcess, cbProcessed);
     4055    #if 1
     4056        hdaStreamTransferUpdate(pThis, pStream, cbProcessed);
     4057
     4058        Assert(cbLeft >= cbProcessed);
     4059        cbLeft  -= cbProcessed;
     4060        cbTotal += cbProcessed;
     4061
     4062        LogFlowFunc(("cbProcessed=%RU32, cbLeft=%RU32, cbTotal=%RU32, rc=%Rrc\n",
     4063                     cbProcessed, cbLeft, cbTotal, rc));
     4064
     4065        if (rc == VINF_EOF)
     4066            break;
     4067
     4068        if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt))
     4069        {
     4070            rc = hdaStreamGetNextBDLE(pThis, pStream);
     4071            break;
     4072        }
     4073    #else
     4074        Assert(cbProcessedLeft >= cbProcessed);
     4075        cbProcessedLeft  -= cbProcessed;
    37104076        cbProcessedTotal += cbProcessed;
    37114077
    3712         LogFlowFunc(("cbProcessed=%RU32, cbToProcess=%RU32, cbProcessedTotal=%RU32, rc=%Rrc\n",
    3713                      cbProcessed, cbToProcess, cbProcessedTotal, rc));
    3714 
    3715         if (rc == VINF_EOF)
     4078
     4079        u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, u32LPIB + cbProcessed);
     4080
     4081        Assert(u32LPIB <= pStream->u32CBL);
     4082        if (u32LPIB == pStream->u32CBL)
     4083        {
     4084           // HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     4085            Log3Func(("[SD%RU8]: Transfer complete\n", pStream->u8SD));
     4086#if 1
     4087            if (/* IOC (Interrupt On Completion) bit set? */
     4088                   pBDLE->fIntOnCompletion
     4089                /* All data put into the DMA FIFO? */
     4090                && pBDLE->State.cbBelowFIFOW == 0
     4091               )
     4092            {
     4093                fSetIRQ = true;
     4094                /*
     4095                 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
     4096                 * we need to generate an interrupt.
     4097                 */
     4098            //    if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
     4099              //      PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
     4100              //  fIRQ = true;
     4101            }
     4102#endif
    37164103            fIsComplete = true;
    3717 
    3718         if (!fIsComplete)
    3719             fIsComplete = hdaStreamTransferIsComplete(pThis, pStrmSt);
    3720 
    3721         if (fIsComplete)
    3722             break;
    3723     }
     4104        }
     4105
     4106        if (   fIsComplete
     4107            || pBDLE->State.u32BufOff >= pBDLE->u32BufSize)
     4108        {
     4109            Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
     4110
     4111            Log3Func(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, %R[bdle] => Next BDLE\n",
     4112                      pStream->u8SD, u32LPIB, u32LPIB >= pStream->u32CBL, pBDLE));
     4113
     4114            /*
     4115             * Switch to the next BDLE entry and do a wrap around
     4116             * if we reached the end of the Buffer Descriptor List (BDL).
     4117             */
     4118            pStream->State.uCurBDLE++;
     4119            if (pStream->State.uCurBDLE == pStream->u16LVI + 1)
     4120            {
     4121                pStream->State.uCurBDLE = 0;
     4122                u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0);
     4123            }
     4124
     4125            hdaBDLEFetch(pThis, &pStream->State.BDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
     4126
     4127            if (/* IOC (Interrupt On Completion) bit set? */
     4128                   pBDLE->fIntOnCompletion
     4129                /* All data put into the DMA FIFO? */
     4130                && pBDLE->State.cbBelowFIFOW == 0
     4131               )
     4132            {
     4133                fSetIRQ = true;
     4134            }
     4135        }
     4136
     4137    #endif
     4138
     4139        /*if (fIsComplete)
     4140            break;*/
     4141    }
     4142
     4143    if (fInterrupt)
     4144    {
     4145        /**
     4146         * Set the BCIS (Buffer Completion Interrupt Status) flag as the
     4147         * last byte of data for the current descriptor has been fetched
     4148         * from memory and put into the DMA FIFO.
     4149         *
     4150         * Speech synthesis works fine on Mac Guest if this bit isn't set
     4151         * but in general sound quality gets worse.
     4152         *
     4153         * This must be set in *any* case.
     4154         */
     4155        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     4156        Log3Func(("[SD%RU8]: BCIS: Set (fInterrupt=%RTbool)\n", pStream->u8SD, fInterrupt));
     4157
     4158        hdaProcessInterrupt(pThis);
     4159    }
     4160
     4161#if 0
     4162    if (fSetIRQ)
     4163    {
     4164        Log3Func(("[SD%RU8]: IRQ\n", pStream->u8SD));
     4165
     4166        /**
     4167         * Set the BCIS (Buffer Completion Interrupt Status) flag as the
     4168         * last byte of data for the current descriptor has been fetched
     4169         * from memory and put into the DMA FIFO.
     4170         *
     4171         * Speech synthesis works fine on Mac Guest if this bit isn't set
     4172         * but in general sound quality gets worse.
     4173         *
     4174         * This must be set in *any* case.
     4175         */
     4176        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     4177
     4178        /*
     4179         * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
     4180         * we need to generate an interrupt.
     4181         */
     4182        if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
     4183            PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */);
     4184    }
     4185#endif
     4186
     4187    Log3Func(("Written %RU32 / %RU32 (left: %RU32), rc=%Rrc\n", cbTotal, cbToProcess, cbLeft, rc));
    37244188
    37254189    if (RT_SUCCESS(rc))
    37264190    {
    37274191        if (pcbProcessed)
    3728             *pcbProcessed = cbProcessedTotal;
    3729     }
    3730     else
    3731         LogFlowFunc(("Failed with %Rrc\n", rc));
    3732 
    3733     int rc2 = RTSemMutexRelease(pStrmSt->State.hMtx);
     4192            *pcbProcessed = cbTotal;
     4193    }
     4194
     4195    int rc2 = RTSemMutexRelease(pStream->State.hMtx);
    37344196    if (RT_SUCCESS(rc))
    37354197        rc = rc2;
     
    38384300    if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
    38394301    {
    3840         LogRel2(("HDA: Access to register 0x%x is blocked while reset\n", idxRegDsc));
     4302        LogRel2(("HDA: Warning: Access to register 0x%x is blocked while reset\n", idxRegDsc));
    38414303        return VINF_SUCCESS;
    38424304    }
     
    38474309#endif
    38484310    int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value);
    3849     Log3Func(("write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
     4311    Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
    38504312              g_aHdaRegMap[idxRegDsc].size, u32CurValue, pThis->au32Regs[idxRegMem], pszLog));
    38514313    return rc;
     
    43804842    {
    43814843        /*
    4382          * Update stuff after the state changes.
     4844         * Update sinks after the state changes.
    43834845         */
    4384         bool fEnableIn    = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
     4846        AUDMIXSINKCMD enmCmdLineIn = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
     4847                                   ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    43854848#ifdef VBOX_WITH_HDA_MIC_IN
    4386         bool fEnableMicIn = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
    4387 #endif
    4388         bool fEnableOut   = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
    4389 
    4390         PHDADRIVER pDrv;
    4391         RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    4392         {
    4393             PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    4394             rc = pCon->pfnEnableIn(pCon, pDrv->LineIn.pGstStrm, fEnableIn);
    4395             if (RT_FAILURE(rc))
    4396                 break;
    4397 #ifdef VBOX_WITH_HDA_MIC_IN
    4398             rc = pCon->pfnEnableIn(pCon, pDrv->MicIn.pGstStrm, fEnableMicIn);
    4399             if (RT_FAILURE(rc))
    4400                 break;
    4401 #endif
    4402             rc = pCon->pfnEnableOut(pCon, pDrv->Front.pGstStrm,     fEnableOut);
    4403             if (RT_FAILURE(rc))
    4404                 break;
    4405 #ifdef VBOX_WITH_HDA_51_SURROUND
    4406             rc = pCon->pfnEnableOut(pCon, pDrv->CenterLFE.pGstStrm, fEnableOut);
    4407             if (RT_FAILURE(rc))
    4408                 break;
    4409             rc = pCon->pfnEnableOut(pCon, pDrv->Rear.pGstStrm,      fEnableOut);
    4410             if (RT_FAILURE(rc))
    4411                 break;
    4412 #endif
    4413             if (RT_FAILURE(rc))
    4414                 break;
    4415         }
     4849        AUDMIXSINKCMD enmCmdMicIn  = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
     4850                                   ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
     4851#endif
     4852        AUDMIXSINKCMD enmCmdOut    = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
     4853                                   ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
     4854
     4855# ifdef VBOX_WITH_HDA_MIC_IN
     4856        AudioMixerSinkCtl(pThis->pSinkMicIn,     enmCmdMicIn);
     4857# endif
     4858        AudioMixerSinkCtl(pThis->pSinkLineIn,    enmCmdLineIn);
     4859        AudioMixerSinkCtl(pThis->pSinkFront,     enmCmdOut);
     4860# ifdef VBOX_WITH_HDA_51_SURROUND
     4861        AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmdOut);
     4862        AudioMixerSinkCtl(pThis->pSinkRear,      enmCmdOut);
     4863# endif
    44164864    }
    44174865
     
    44234871
    44244872        /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
    4425         pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
     4873        pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));
    44264874    }
    44274875    else
     
    44454893    PHDABDLE pBDLE = (PHDABDLE)pvValue;
    44464894    return RTStrFormat(pfnOutput,  pvArgOutput, NULL, 0,
    4447                        "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, DMA[%RU32 bytes @ 0x%x])",
    4448                        pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW, pBDLE->u32BufSize, pBDLE->u64BufAdr);
     4895                       "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])",
     4896                       pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,  pBDLE->fIntOnCompletion,
     4897                       pBDLE->u32BufSize, pBDLE->u64BufAdr);
    44494898}
    44504899
     
    47565205     * Stop any audio currently playing and/or recording.
    47575206     */
    4758     PHDADRIVER pDrv;
    4759     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    4760     {
    4761         pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pGstStrm,      false /* Disable */);
     5207    AudioMixerSinkCtl(pThis->pSinkFront,     AUDMIXSINKCMD_DISABLE);
    47625208# ifdef VBOX_WITH_HDA_MIC_IN
    4763         pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pGstStrm,       false /* Disable */);
     5209    AudioMixerSinkCtl(pThis->pSinkMicIn,     AUDMIXSINKCMD_DISABLE);
    47645210# endif
    4765         pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Front.pGstStrm,     false /* Disable */);
     5211    AudioMixerSinkCtl(pThis->pSinkLineIn,    AUDMIXSINKCMD_DISABLE);
    47665212# ifdef VBOX_WITH_HDA_51_SURROUND
    4767         pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->CenterLFE.pGstStrm, false /* Disable */);
    4768         pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Rear.pGstStrm,      false /* Disable */);
     5213    AudioMixerSinkCtl(pThis->pSinkCenterLFE, AUDMIXSINKCMD_DISABLE);
     5214    AudioMixerSinkCtl(pThis->pSinkRear,      AUDMIXSINKCMD_DISABLE);
    47695215# endif
    4770     }
    47715216
    47725217    pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */
     
    47895234        /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
    47905235        HDA_STREAM_REG(pThis, CTL, i) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN);
    4791         hdaStreamReset(pThis, &pThis->aStreams[i], i);
     5236        hdaStreamReset(pThis, &pThis->aStreams[i]);
    47925237    }
    47935238
     
    48305275    }
    48315276
    4832     if (pThis->pMixer)
    4833     {
    4834         AudioMixerDestroy(pThis->pMixer);
    4835         pThis->pMixer = NULL;
    4836     }
    4837 
    48385277    if (pThis->pCodec)
    48395278    {
    4840         int rc = hdaCodecDestruct(pThis->pCodec);
    4841         AssertRC(rc);
     5279        hdaCodecDestruct(pThis->pCodec);
    48425280
    48435281        RTMemFree(pThis->pCodec);
     
    49575395
    49585396/**
    4959  * Re-attach.
     5397 * Powers off the device.
     5398 *
     5399 * @param   pDevIns             Device instance to power off.
     5400 */
     5401static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns)
     5402{
     5403    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
     5404
     5405    LogRel2(("HDA: Powering off ...\n"));
     5406
     5407    /**
     5408     * Note: Destroy the mixer while powering off and *not* in hdaDestruct,
     5409     *       giving the mixer the chance to release any references held to
     5410     *       PDM audio streams it maintains.
     5411     */
     5412    if (pThis->pMixer)
     5413    {
     5414        AudioMixerDestroy(pThis->pMixer);
     5415        pThis->pMixer = NULL;
     5416    }
     5417
     5418    /* Ditto goes for the codec, which in turn uses the mixer. */
     5419    hdaCodecPowerOff(pThis->pCodec);
     5420}
     5421
     5422/**
     5423 * Re-attaches a new driver to the device's driver chain.
    49605424 *
    49615425 * @returns VBox status code.
    4962  * @param   pThis       Device instance.
     5426 * @param   pThis       Device instance to re-attach driver to.
    49635427 * @param   pDrv        Driver instance used for attaching to.
    49645428 *                      If NULL is specified, a new driver will be created and appended
     
    51665630
    51675631    RTListInit(&pThis->lstDrv);
    5168 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
    5169     rc = RTCircBufCreate(&pThis->pCircBuf, _4K);
    5170     if (RT_FAILURE(rc))
    5171         return rc;
    5172 #endif
    51735632
    51745633    uint8_t uLUN;
     
    52055664            streamCfg.uHz           = 44100;
    52065665            streamCfg.cChannels     = 2;
    5207             streamCfg.enmFormat     = AUD_FMT_S16;
     5666            streamCfg.enmFormat     = PDMAUDIOFMT_S16;
    52085667            streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    52095668
     
    52155674             */
    52165675#ifdef VBOX_WITH_HDA_51_SURROUND
    5217             rc = AudioMixerAddSink(pThis->pMixer, "[Playback] Front",
    5218                                    AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
     5676            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front",
     5677                                      AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
    52195678            AssertRC(rc);
    5220             rc = AudioMixerAddSink(pThis->pMixer, "[Playback] Center / Subwoofer",
    5221                                    AUDMIXSINKDIR_OUTPUT, &pThis->pSinkCenterLFE);
     5679            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer",
     5680                                      AUDMIXSINKDIR_OUTPUT, &pThis->pSinkCenterLFE);
    52225681            AssertRC(rc);
    5223             rc = AudioMixerAddSink(pThis->pMixer, "[Playback] Rear",
    5224                                    AUDMIXSINKDIR_OUTPUT, &pThis->pSinkRear);
     5682            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear",
     5683                                      AUDMIXSINKDIR_OUTPUT, &pThis->pSinkRear);
    52255684            AssertRC(rc);
    52265685#else
    5227             rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output",
    5228                                    AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
     5686            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output",
     5687                                      AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
    52295688            AssertRC(rc);
    52305689#endif
     
    52325691             * Add mixer input sinks.
    52335692             */
    5234             rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In",
    5235                                    AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
     5693            rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",
     5694                                      AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
    52365695            AssertRC(rc);
    52375696#ifdef VBOX_WITH_HDA_MIC_IN
    5238             rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In",
    5239                                    AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
     5697            rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In",
     5698                                      AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
    52405699            AssertRC(rc);
    52415700#endif
     
    52545713            return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state"));
    52555714
    5256         /* Audio driver callbacks for multiplexing. */
     5715        /* Set codec callbacks. */
    52575716        pThis->pCodec->pfnMixerAddStream    = hdaMixerAddStream;
    52585717        pThis->pCodec->pfnMixerRemoveStream = hdaMixerRemoveStream;
     
    53205779            AssertPtr(pCon);
    53215780
    5322             bool fValidLineIn = pCon->pfnIsValidIn(pCon,  pDrv->LineIn.pGstStrm);
     5781            bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
    53235782#ifdef VBOX_WITH_HDA_MIC_IN
    5324             bool fValidMicIn  = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pGstStrm);
    5325 #endif
    5326             bool fValidOut    = pCon->pfnIsValidOut(pCon, pDrv->Front.pGstStrm);
     5783            bool fValidMicIn  = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
     5784#endif
     5785            bool fValidOut    = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
     5786#ifdef VBOX_WITH_HDA_51_SURROUND
     5787            /** @todo Anything to do here? */
     5788#endif
    53275789
    53285790            if (    !fValidLineIn
     
    53465808
    53475809                PDMAUDIOBACKENDCFG backendCfg;
    5348                 int rc2 = pCon->pfnGetConfiguration(pCon, &backendCfg);
     5810                int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
    53495811                if (RT_SUCCESS(rc2))
    53505812                {
     
    56096071    NULL,
    56106072    /* pfnPowerOff */
    5611     NULL,
     6073    hdaPowerOff,
    56126074    /* pfnSoftReset */
    56136075    NULL,
  • trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp

    r60643 r60925  
    10741074                                                          CODEC_F1C_COLOR_GREEN,
    10751075                                                          CODEC_F1C_MISC_NONE,
    1076                                                           CODEC_F1C_ASSOCIATION_GROUP_0, 0xF /* Seq */);
     1076                                                          CODEC_F1C_ASSOCIATION_GROUP_1, 0x0 /* Seq */);
    10771077            goto port_init;
    10781078        }
     
    10981098                                                          CODEC_F1C_COLOR_BLACK,
    10991099                                                          CODEC_F1C_MISC_NONE,
    1100                                                           CODEC_F1C_ASSOCIATION_GROUP_1, 0xE /* Seq */);
     1100                                                          CODEC_F1C_ASSOCIATION_GROUP_0, 0x1 /* Seq */);
    11011101            goto port_init;
    11021102        }
     
    11471147                                                          CODEC_F1C_COLOR_PINK,
    11481148                                                          CODEC_F1C_MISC_NONE,
    1149                                                           CODEC_F1C_ASSOCIATION_GROUP_15, 0xD /* Seq */);
     1149                                                          CODEC_F1C_ASSOCIATION_GROUP_4, 0x0 /* Seq */);
    11501150            /* Fall through is intentional. */
     1151
    11511152        port_init:
    11521153
     
    11731174                                                | CODEC_F00_09_CAP_UNSOL
    11741175                                                | CODEC_F00_09_CAP_STEREO;
     1176
    11751177            pNode->port.node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
    11761178                                                | CODEC_F00_0C_CAP_PRESENCE_DETECT;
     
    11831185                                                          CODEC_F1C_COLOR_BLUE,
    11841186                                                          CODEC_F1C_MISC_NONE,
    1185                                                           CODEC_F1C_ASSOCIATION_GROUP_15, 0xE /* Seq */);
     1187                                                          CODEC_F1C_ASSOCIATION_GROUP_4, 0x1 /* Seq */);
    11861188            break;
    11871189        }
     
    11981200                                                | CODEC_F00_09_CAP_OUT_AMP_PRESENT
    11991201                                                | CODEC_F00_09_CAP_STEREO;
     1202
    12001203            pNode->port.node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
    12011204                                                | CODEC_F00_0C_CAP_OUTPUT;
     
    12121215                                                          CODEC_F1C_COLOR_ORANGE,
    12131216                                                          CODEC_F1C_MISC_NONE,
    1214                                                           CODEC_F1C_ASSOCIATION_GROUP_1, 0x0 /* Seq */);
     1217                                                          CODEC_F1C_ASSOCIATION_GROUP_0, 0x2 /* Seq */);
    12151218            break;
    12161219        }
     
    12671270                                                           CODEC_F1C_COLOR_BLACK,
    12681271                                                           CODEC_F1C_MISC_NONE,
    1269                                                            CODEC_F1C_ASSOCIATION_GROUP_3, 0x0 /* Seq */);
     1272                                                           CODEC_F1C_ASSOCIATION_GROUP_5, 0x0 /* Seq */);
    12701273            break;
    12711274        }
     
    12801283        {
    12811284            pNode->adcmux.u32F01_param = 1; /* Connection select control index (STAC9220_NID_PIN_CD). */
    1282 
    12831285            /* Fall through is intentional. */
     1286
    12841287        adcmux_init:
    12851288
     
    13041307
    13051308            /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplifiers initialized with 0. */
    1306             RT_BZERO(pNode->adcmux.B_params, AMPLIFIER_SIZE);
     1309            RT_ZERO(pNode->adcmux.B_params);
    13071310            break;
    13081311        }
     
    13171320            pNode->pcbeep.node.au32F00_param[0xD]  = CODEC_MAKE_F00_0D(0, 17, 3, 3);
    13181321
    1319             RT_BZERO(pNode->pcbeep.B_params, AMPLIFIER_SIZE);
     1322            RT_ZERO(pNode->pcbeep.B_params);
    13201323            break;
    13211324        }
     
    13341337                                                            CODEC_F1C_COLOR_UNKNOWN,
    13351338                                                            CODEC_F1C_MISC_NONE,
    1336                                                             CODEC_F1C_ASSOCIATION_GROUP_15, 0xF /* Seq */);
     1339                                                            CODEC_F1C_ASSOCIATION_GROUP_4, 0x2 /* Seq */);
    13371340            break;
    13381341        }
     
    13551358        }
    13561359
    1357         case STAC9220_NID_AMP_ADC0:
     1360        case STAC9220_NID_AMP_ADC0: /* ADC0Vol */
    13581361        {
    13591362            pNode->adcvol.node.au32F02_param[0] = STAC9220_NID_ADC0_MUX;
     
    13611364        }
    13621365
    1363         case STAC9220_NID_AMP_ADC1:
     1366        case STAC9220_NID_AMP_ADC1: /* ADC1Vol */
    13641367        {
    13651368            pNode->adcvol.node.au32F02_param[0] = STAC9220_NID_ADC1_MUX;
    1366 
    13671369            /* Fall through is intentional. */
     1370
    13681371        adcvol_init:
    1369 
    1370             pNode->adcvol.u32F0c_param = 0;
    13711372
    13721373            pNode->adcvol.node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
     
    13791380            pNode->adcvol.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(CODEC_F00_0E_LIST_NID_SHORT, 1 /* Entries */);
    13801381
    1381             RT_BZERO(pNode->adcvol.B_params, AMPLIFIER_SIZE);
     1382            RT_ZERO(pNode->adcvol.B_params);
    13821383            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT,  0) = RT_BIT(7);
    13831384            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
     
    14111412                                           | CODEC_F00_09_CAP_CONNECTION_LIST
    14121413                                           | CODEC_F00_09_CAP_STEREO;
     1414
    14131415            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;
    14141416
     
    14351437    return VINF_SUCCESS;
    14361438}
    1437 
    14381439
    14391440static int stac9220Construct(PHDACODEC pThis)
     
    15871588 * Verb processor functions.
    15881589 */
    1589 DECLINLINE(bool) vrbIsValidNode(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    1590 {
    1591     AssertPtrReturn(pThis, false);
    1592     AssertPtrReturn(pResp, false);
    1593 
    1594     Assert(CODEC_CAD(cmd) == pThis->id);
    1595     Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
    1596     if (CODEC_NID(cmd) >= pThis->cTotalNodes)
    1597     {
    1598         *pResp = 0;
    1599 
    1600         AssertMsgFailed(("Invalid node address: 0x%x (NID=0x%x [%RU8])\n", cmd, CODEC_NID(cmd)));
    1601         return false;
    1602     }
    1603 
    1604     return true;
    1605 }
    1606 
    16071590static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    16081591{
     
    16241607static DECLCALLBACK(int) vrbProcGetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    16251608{
    1626     if (!vrbIsValidNode(pThis, cmd, pResp))
    1627         return VINF_SUCCESS;
    1628 
    16291609    *pResp = 0;
    16301610
     
    16731653static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    16741654{
    1675     if (!vrbIsValidNode(pThis, cmd, pResp))
    1676         return VINF_SUCCESS;
    1677 
    16781655    *pResp = 0;
    16791656
     
    17351712static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    17361713{
    1737     if (!vrbIsValidNode(pThis, cmd, pResp))
    1738         return VINF_SUCCESS;
    1739 
    17401714    Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F00_PARAM_LENGTH);
    17411715    if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F00_PARAM_LENGTH)
     
    17541728static DECLCALLBACK(int) vrbProcGetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    17551729{
    1756     if (!vrbIsValidNode(pThis, cmd, pResp))
    1757         return VINF_SUCCESS;
    1758 
    17591730    *pResp = 0;
    17601731
     
    17701741        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
    17711742    else
    1772         LogRel2(("HDA: Warning: Unhandled get connection select control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1743        LogRel2(("HDA: Warning: Unhandled get connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    17731744
    17741745    return VINF_SUCCESS;
     
    17781749static DECLCALLBACK(int) vrbProcSetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    17791750{
    1780     if (!vrbIsValidNode(pThis, cmd, pResp))
    1781         return VINF_SUCCESS;
    1782 
    17831751    *pResp = 0;
    17841752
     
    17951763        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
    17961764    else
    1797         LogRel2(("HDA: Warning: Unhandled set connection select control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1765        LogRel2(("HDA: Warning: Unhandled set connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    17981766
    17991767    if (pu32Reg)
     
    18061774static DECLCALLBACK(int) vrbProcGetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    18071775{
    1808     if (!vrbIsValidNode(pThis, cmd, pResp))
    1809         return VINF_SUCCESS;
    1810 
    18111776    *pResp = 0;
    18121777
     
    18241789        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
    18251790    else
    1826         LogRel2(("HDA: Warning: Unhandled get pin control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1791        LogRel2(("HDA: Warning: Unhandled get pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    18271792
    18281793    return VINF_SUCCESS;
     
    18321797static DECLCALLBACK(int) vrbProcSetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    18331798{
    1834     if (!vrbIsValidNode(pThis, cmd, pResp))
    1835         return VINF_SUCCESS;
    1836 
    18371799    *pResp = 0;
    18381800
     
    18521814        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
    18531815    else
    1854         LogRel2(("HDA: Warning: Unhandled set pin control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1816        LogRel2(("HDA: Warning: Unhandled set pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    18551817
    18561818    if (pu32Reg)
     
    18631825static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    18641826{
    1865     if (!vrbIsValidNode(pThis, cmd, pResp))
    1866         return VINF_SUCCESS;
    1867 
    18681827    *pResp = 0;
    18691828
     
    18811840        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
    18821841    else
    1883         LogRel2(("HDA: Warning: Unhandled get unsolicited enabled command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1842        LogRel2(("HDA: Warning: Unhandled get unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    18841843
    18851844    return VINF_SUCCESS;
     
    18891848static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    18901849{
    1891     if (!vrbIsValidNode(pThis, cmd, pResp))
    1892         return VINF_SUCCESS;
    1893 
    18941850    *pResp = 0;
    18951851
     
    19081864        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
    19091865    else
    1910         LogRel2(("HDA: Warning: Unhandled set unsolicited enabled command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1866        LogRel2(("HDA: Warning: Unhandled set unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    19111867
    19121868    if (pu32Reg)
     
    19191875static DECLCALLBACK(int) vrbProcGetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    19201876{
    1921     if (!vrbIsValidNode(pThis, cmd, pResp))
    1922         return VINF_SUCCESS;
    1923 
    19241877    *pResp = 0;
    19251878
     
    19291882        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
    19301883    else
    1931         LogRel2(("HDA: Warning: Unhandled get pin sense command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1884    {
     1885        AssertFailed();
     1886        LogRel2(("HDA: Warning: Unhandled get pin sense command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     1887    }
    19321888
    19331889    return VINF_SUCCESS;
     
    19371893static DECLCALLBACK(int) vrbProcSetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    19381894{
    1939     if (!vrbIsValidNode(pThis, cmd, pResp))
    1940         return VINF_SUCCESS;
    1941 
    19421895    *pResp = 0;
    19431896
     
    19481901        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
    19491902    else
    1950         LogRel2(("HDA: Warning: Unhandled set pin sense command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     1903        LogRel2(("HDA: Warning: Unhandled set pin sense command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    19511904
    19521905    if (pu32Reg)
     
    19581911static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    19591912{
    1960     if (!vrbIsValidNode(pThis, cmd, pResp))
    1961         return VINF_SUCCESS;
    1962 
    19631913    *pResp = 0;
    19641914
     
    19761926static DECLCALLBACK(int) vrbProcGetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    19771927{
    1978     if (!vrbIsValidNode(pThis, cmd, pResp))
    1979         return VINF_SUCCESS;
    1980 
    19811928    *pResp = 0;
    19821929
     
    19901937static DECLCALLBACK(int) vrbProcSetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    19911938{
    1992     if (!vrbIsValidNode(pThis, cmd, pResp))
    1993         return VINF_SUCCESS;
    1994 
    19951939    *pResp = 0;
    19961940
     
    20031947static DECLCALLBACK(int) vrbProcGetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    20041948{
    2005     if (!vrbIsValidNode(pThis, cmd, pResp))
    2006         return VINF_SUCCESS;
    2007 
    20081949    *pResp = 0;
    20091950
     
    20181959static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
    20191960{
    2020     if (!vrbIsValidNode(pThis, cmd, pResp))
    2021         return VINF_SUCCESS;
    2022 
    20231961    *pResp = 0;
    20241962
     
    21092047    Assert(CODEC_CAD(cmd) == pThis->id);
    21102048    Assert(CODEC_NID(cmd) == STAC9220_NID_AFG);
     2049
    21112050    if (   CODEC_NID(cmd) == STAC9220_NID_AFG
    21122051        && pThis->pfnCodecNodeReset)
    21132052    {
    21142053        uint8_t i;
    2115         LogFlowFunc(("enters reset\n"));
    2116         Assert(pThis->pfnCodecNodeReset);
     2054        LogFunc(("Entering reset ...\n"));
     2055
     2056        //pThis->fInReset = true;
     2057
    21172058        for (i = 0; i < pThis->cTotalNodes; ++i)
    2118         {
    21192059            pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
    2120         }
    2121         pThis->fInReset = false;
    2122         LogFlowFunc(("exits reset\n"));
    2123     }
     2060
     2061        //pThis->fInReset = false;
     2062
     2063        LogFunc(("Exited reset\n"));
     2064    }
     2065
    21242066    *pResp = 0;
    21252067    return VINF_SUCCESS;
     
    21292071static DECLCALLBACK(int) vrbProcGetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    21302072{
    2131     if (!vrbIsValidNode(pThis, cmd, pResp))
    2132         return VINF_SUCCESS;
    2133 
    21342073    *pResp = 0;
    21352074
     
    21382077    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
    21392078        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
     2079    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
     2080        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
    21402081    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
    21412082        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
    21422083    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
    21432084        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F05_param;
    2144     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
    2145         *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
    21462085    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
    21472086        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
     
    21512090        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
    21522091    else
    2153         LogRel2(("HDA: Warning: Unhandled get power state command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
    2154 
    2155     LogFunc(("NID=0x%x, fReset=%RTbool, fStopOk=%RTbool, Set=%RU8, Act=%RU8\n",
    2156              CODEC_NID(cmd), CODEC_F05_IS_RESET(*pResp), CODEC_F05_IS_STOPOK(*pResp), CODEC_F05_SET(*pResp), CODEC_F05_ACT(*pResp)));
     2092        LogRel2(("HDA: Warning: Unhandled get power state command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2093
     2094    LogFunc(("[NID0x%02x]: fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n",
     2095             CODEC_NID(cmd), CODEC_F05_IS_RESET(*pResp), CODEC_F05_IS_STOPOK(*pResp), CODEC_F05_ACT(*pResp), CODEC_F05_SET(*pResp)));
    21572096    return VINF_SUCCESS;
    21582097}
    21592098
    21602099/* 705 */
     2100#if 1
    21612101static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    21622102{
    2163     if (!vrbIsValidNode(pThis, cmd, pResp))
    2164         return VINF_SUCCESS;
    2165 
    21662103    *pResp = 0;
    21672104
     
    21842121        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
    21852122    else
    2186         LogRel2(("HDA: Warning: Unhandled set power state command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2123    {
     2124        AssertFailed();
     2125        LogRel2(("HDA: Warning: Unhandled set power state command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2126    }
    21872127
    21882128    if (!pu32Reg)
     
    21912131    bool    fReset  = CODEC_F05_IS_RESET (*pu32Reg);
    21922132    bool    fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
     2133    bool    fError  = CODEC_F05_IS_ERROR (*pu32Reg);
    21932134    uint8_t uPwrAct = CODEC_F05_ACT      (*pu32Reg);
    21942135    uint8_t uPwrSet = CODEC_F05_SET      (*pu32Reg);
     2136
    21952137    uint8_t uPwrCmd = CODEC_F05_SET      (cmd);
    21962138
    2197     LogFunc(("[NID=0x%x] Cmd=D%RU8, Act=D%RU8, Set=D%RU8 (AFG Act=D%RU8, Set=D%RU8)\n",
    2198             CODEC_NID(cmd), uPwrCmd, uPwrAct, uPwrSet,
     2139    LogFunc(("[NID0x%02x] Cmd=D%RU8, fReset=%RTbool, fStopOk=%RTbool, fError=%RTbool, uPwrAct=D%RU8, uPwrSet=D%RU8\n",
     2140             CODEC_NID(cmd), uPwrCmd, fReset, fStopOk, fError, uPwrAct, uPwrSet));
     2141
     2142    LogFunc(("AFG: Act=D%RU8, Set=D%RU8\n",
    21992143            CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param),
    22002144            CODEC_F05_SET(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param)));
    22012145
    2202     const uint8_t uAFGPwrSet = CODEC_F05_SET(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param);
    2203 
    2204     /* If this is the AFG node, PS-Act always matches the PS-Set power state.*/
    22052146    if (CODEC_NID(cmd) == STAC9220_NID_AFG)
    2206     {
    22072147        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, uPwrCmd /* PS-Act */, uPwrCmd /* PS-Set */);
    22082148
     2149    const uint8_t uAFGPwrAct = CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param);
     2150    if (uAFGPwrAct == CODEC_F05_D0) /* Only propagate power state if AFG is on (D0). */
     2151    {
    22092152        /* Propagate to all other nodes under this AFG. */
    2210         LogFunc(("Propagating Set=D%RU8 to all nodes ...\n", uPwrCmd));
     2153        LogFunc(("Propagating Act=D%RU8 (AFG), Set=D%RU8 to all AFG child nodes ...\n", uAFGPwrAct, uPwrCmd));
    22112154
    22122155#define PROPAGATE_PWR_STATE(_aList, _aMember) \
    22132156        { \
    22142157            const uint8_t *pu8NodeIndex = &_aList[0]; \
    2215             while (*(pu8NodeIndex++)) \
     2158            while (*(++pu8NodeIndex)) \
    22162159            { \
    22172160                pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param = \
    2218                     CODEC_MAKE_F05(fReset, fStopOk, 0, RT_MIN((uAFGPwrSet + 1), CODEC_F05_D3), \
    2219                                    uPwrCmd /* Always update PS-Set with command power state just received. */); \
    2220                 LogFunc(("\t[NID=0x%x]: Act=D%RU8, Set=D%RU8\n", *pu8NodeIndex, \
     2161                    CODEC_MAKE_F05(fReset, fStopOk, 0, uAFGPwrAct, uPwrCmd); \
     2162                LogFunc(("\t[NID0x%02x]: Act=D%RU8, Set=D%RU8\n", *pu8NodeIndex, \
    22212163                         CODEC_F05_ACT(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param), \
    22222164                         CODEC_F05_SET(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param))); \
     
    22352177    }
    22362178    /*
    2237      * If this node is a reqular node (not the AFG one), adpopt PS-Set of the AFG node
     2179     * If this node is a reqular node (not the AFG one), adopt PS-Set of the AFG node
    22382180     * as PS-Set of this node. PS-Act always is one level under PS-Set here.
    22392181     */
    22402182    else
    22412183    {
     2184        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, uAFGPwrAct, uPwrCmd);
     2185    }
     2186
     2187    LogFunc(("[NID0x%02x] fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n",
     2188             CODEC_NID(cmd),
     2189             CODEC_F05_IS_RESET(*pu32Reg), CODEC_F05_IS_STOPOK(*pu32Reg), CODEC_F05_ACT(*pu32Reg), CODEC_F05_SET(*pu32Reg)));
     2190
     2191    return VINF_SUCCESS;
     2192}
     2193#else
     2194DECLINLINE(void) codecPropogatePowerState(uint32_t *pu32F05_param)
     2195{
     2196    Assert(pu32F05_param);
     2197    if (!pu32F05_param)
     2198        return;
     2199    bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
     2200    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
     2201    uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
     2202    *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
     2203}
     2204
     2205static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
     2206{
     2207    Assert(CODEC_CAD(cmd) == pThis->id);
     2208    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
     2209    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
     2210    {
     2211        LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
     2212        return VINF_SUCCESS;
     2213    }
     2214    *pResp = 0;
     2215    uint32_t *pu32Reg;
     2216    if (CODEC_NID(cmd) == 1 /* AFG */)
     2217        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
     2218    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
     2219        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
     2220    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
     2221        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
     2222    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
     2223        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
     2224    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
     2225        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
     2226    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
     2227        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
     2228    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
     2229        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
     2230    else
     2231        AssertFailedReturn(VINF_SUCCESS);
     2232
     2233    bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
     2234    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
     2235
     2236    if (CODEC_NID(cmd) != 1 /* AFG */)
     2237    {
     2238        /*
     2239         * We shouldn't propogate actual power state, which actual for AFG
     2240         */
    22422241        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
    2243                                   RT_MIN((uAFGPwrSet + 1), CODEC_F05_D3),
    2244                                   uPwrCmd /* Always update PS-Set with command power state just received. */);
    2245     }
    2246 
    2247     if (pu32Reg)
    2248         hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
    2249 
    2250     LogFunc(("[NID=0x%x] fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n",
    2251              CODEC_NID(cmd), fReset, fStopOk, CODEC_F05_ACT(*pu32Reg), CODEC_F05_SET(*pu32Reg)));
    2252 
    2253     return VINF_SUCCESS;
    2254 }
     2242                                  CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param),
     2243                                  CODEC_F05_SET(cmd));
     2244    }
     2245
     2246    /* Propagate next power state only if AFG is on or verb modifies AFG power state */
     2247    if (   CODEC_NID(cmd) == 1 /* AFG */
     2248        || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param))
     2249    {
     2250        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
     2251        if (   CODEC_NID(cmd) == 1 /* AFG */
     2252            && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
     2253        {
     2254            /* now we're powered on AFG and may propogate power states on nodes */
     2255            const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0];
     2256            while (*(++pu8NodeIndex))
     2257                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param);
     2258
     2259            pu8NodeIndex = &pThis->au8Adcs[0];
     2260            while (*(++pu8NodeIndex))
     2261                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param);
     2262
     2263            pu8NodeIndex = &pThis->au8DigInPins[0];
     2264            while (*(++pu8NodeIndex))
     2265                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param);
     2266        }
     2267    }
     2268    return VINF_SUCCESS;
     2269}
     2270#endif
    22552271
    22562272static DECLCALLBACK(int) vrbProcGetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    22572273{
    2258     if (!vrbIsValidNode(pThis, cmd, pResp))
    2259         return VINF_SUCCESS;
    2260 
    22612274    *pResp = 0;
    22622275
     
    22722285        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
    22732286    else
    2274         LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
    2275 
    2276     LogFlowFunc(("[NID0x%x] Stream ID is 0x%x\n",
    2277                  CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(*pResp)));
     2287        LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2288
     2289    /*LogFlowFunc(("[NID0x%02x] Stream ID is 0x%x\n",
     2290                 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(*pResp)));*/
    22782291
    22792292    return VINF_SUCCESS;
     
    22832296static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    22842297{
    2285     if (!vrbIsValidNode(pThis, cmd, pResp))
    2286         return VINF_SUCCESS;
    2287 
    22882298    *pResp = 0;
    22892299
     
    23002310        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
    23012311    else
    2302         LogRel2(("HDA: Warning: Unhandled set stream ID command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
    2303 
    2304     LogFlowFunc(("[NID0x%x] Setting new stream ID to 0x%x\n",
    2305                  CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd)));
     2312        LogRel2(("HDA: Warning: Unhandled set stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2313
     2314/*    LogFlowFunc(("[NID0x%02x] Setting new stream ID to 0x%x\n",
     2315                 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd)));*/
    23062316
    23072317    if (pu32Addr)
     
    23142324static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    23152325{
    2316     if (!vrbIsValidNode(pThis, cmd, pResp))
    2317         return VINF_SUCCESS;
    2318 
    23192326    *pResp = 0;
    23202327
     
    23302337        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32A_param;
    23312338    else
    2332         LogRel2(("HDA: Warning: Unhandled get converter format command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2339        LogRel2(("HDA: Warning: Unhandled get converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    23332340
    23342341    return VINF_SUCCESS;
     
    23382345static DECLCALLBACK(int) vrbProcSetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    23392346{
    2340     if (!vrbIsValidNode(pThis, cmd, pResp))
    2341         return VINF_SUCCESS;
    2342 
    23432347    *pResp = 0;
    23442348
     
    23522356        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
    23532357    else
    2354         LogRel2(("HDA: Warning: Unhandled set converter format command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2358        LogRel2(("HDA: Warning: Unhandled set converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    23552359
    23562360    return VINF_SUCCESS;
     
    23602364static DECLCALLBACK(int) vrbProcGetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    23612365{
    2362     if (!vrbIsValidNode(pThis, cmd, pResp))
    2363         return VINF_SUCCESS;
    2364 
    23652366    *pResp = 0;
    23662367
     
    23722373        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
    23732374    else
    2374         LogRel2(("HDA: Warning: Unhandled get EAPD/BTL enabled command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2375        LogRel2(("HDA: Warning: Unhandled get EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    23752376
    23762377    return VINF_SUCCESS;
     
    23802381static DECLCALLBACK(int) vrbProcSetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    23812382{
    2382     if (!vrbIsValidNode(pThis, cmd, pResp))
    2383         return VINF_SUCCESS;
    2384 
    23852383    *pResp = 0;
    23862384
     
    23932391        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
    23942392    else
    2395         LogRel2(("HDA: Warning: Unhandled set EAPD/BTL enabled command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2393        LogRel2(("HDA: Warning: Unhandled set EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    23962394
    23972395    if (pu32Reg)
     
    24042402static DECLCALLBACK(int) vrbProcGetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24052403{
    2406     if (!vrbIsValidNode(pThis, cmd, pResp))
    2407         return VINF_SUCCESS;
    2408 
    24092404    *pResp = 0;
    24102405
     
    24122407        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
    24132408    else
    2414         LogRel2(("HDA: Warning: Unhandled get volume knob control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2409        LogRel2(("HDA: Warning: Unhandled get volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    24152410
    24162411    return VINF_SUCCESS;
     
    24202415static DECLCALLBACK(int) vrbProcSetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24212416{
    2422     if (!vrbIsValidNode(pThis, cmd, pResp))
    2423         return VINF_SUCCESS;
    2424 
    24252417    *pResp = 0;
    24262418
     
    24292421        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
    24302422    else
    2431         LogRel2(("HDA: Warning: Unhandled set volume knob control command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2423        LogRel2(("HDA: Warning: Unhandled set volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    24322424
    24332425    if (pu32Reg)
     
    24402432static DECLCALLBACK(int) vrbProcGetGPIOData(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24412433{
    2442     if (!vrbIsValidNode(pThis, cmd, pResp))
    2443         return VINF_SUCCESS;
    2444 
    24452434    *pResp = 0;
    24462435
     
    24512440static DECLCALLBACK(int) vrbProcSetGPIOData(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24522441{
    2453     if (!vrbIsValidNode(pThis, cmd, pResp))
    2454         return VINF_SUCCESS;
    2455 
    24562442    *pResp = 0;
    24572443
     
    24622448static DECLCALLBACK(int) vrbProcGetGPIOEnableMask(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24632449{
    2464     if (!vrbIsValidNode(pThis, cmd, pResp))
    2465         return VINF_SUCCESS;
    2466 
    24672450    *pResp = 0;
    24682451
     
    24732456static DECLCALLBACK(int) vrbProcSetGPIOEnableMask(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24742457{
    2475     if (!vrbIsValidNode(pThis, cmd, pResp))
    2476         return VINF_SUCCESS;
    2477 
    24782458    *pResp = 0;
    24792459
     
    24842464static DECLCALLBACK(int) vrbProcGetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    24852465{
    2486     if (!vrbIsValidNode(pThis, cmd, pResp))
    2487         return VINF_SUCCESS;
    2488 
    24892466    *pResp = 0;
    24902467
     
    24932470        *pResp = pThis->paNodes[1].afg.u32F17_param;
    24942471    else
    2495         LogRel2(("HDA: Warning: Unhandled get GPIO unsolisted command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2472        LogRel2(("HDA: Warning: Unhandled get GPIO unsolisted command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    24962473
    24972474    return VINF_SUCCESS;
     
    25012478static DECLCALLBACK(int) vrbProcSetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    25022479{
    2503     if (!vrbIsValidNode(pThis, cmd, pResp))
    2504         return VINF_SUCCESS;
    2505 
    25062480    *pResp = 0;
    25072481
     
    25102484        pu32Reg = &pThis->paNodes[1].afg.u32F17_param;
    25112485    else
    2512         LogRel2(("HDA: Warning: Unhandled set GPIO unsolisted command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2486        LogRel2(("HDA: Warning: Unhandled set GPIO unsolisted command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    25132487
    25142488    if (pu32Reg)
     
    25212495static DECLCALLBACK(int) vrbProcGetConfig(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    25222496{
    2523     if (!vrbIsValidNode(pThis, cmd, pResp))
    2524         return VINF_SUCCESS;
    2525 
    25262497    *pResp = 0;
    25272498
     
    25392510        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
    25402511    else
    2541         LogRel2(("HDA: Warning: Unhandled get config command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd));
     2512        LogRel2(("HDA: Warning: Unhandled get config command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    25422513
    25432514    return VINF_SUCCESS;
     
    25602531        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
    25612532    else
    2562         LogRel2(("HDA: Warning: Unhandled set config command (%RU8) for NID0x%x: 0x%x\n", u8Offset, CODEC_NID(cmd), cmd));
     2533        LogRel2(("HDA: Warning: Unhandled set config command (%RU8) for NID0x%02x: 0x%x\n", u8Offset, CODEC_NID(cmd), cmd));
    25632534
    25642535    if (pu32Reg)
     
    25712542static DECLCALLBACK(int) vrbProcSetConfig0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    25722543{
    2573     if (!vrbIsValidNode(pThis, cmd, pResp))
    2574         return VINF_SUCCESS;
    2575 
    25762544    *pResp = 0;
    25772545    return codecSetConfigX(pThis, cmd, 0);
     
    25812549static DECLCALLBACK(int) vrbProcSetConfig1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    25822550{
    2583     if (!vrbIsValidNode(pThis, cmd, pResp))
    2584         return VINF_SUCCESS;
    2585 
    25862551    *pResp = 0;
    25872552    return codecSetConfigX(pThis, cmd, 8);
     
    25912556static DECLCALLBACK(int) vrbProcSetConfig2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    25922557{
    2593     if (!vrbIsValidNode(pThis, cmd, pResp))
    2594         return VINF_SUCCESS;
    2595 
    25962558    *pResp = 0;
    25972559    return codecSetConfigX(pThis, cmd, 16);
     
    26012563static DECLCALLBACK(int) vrbProcSetConfig3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
    26022564{
    2603     if (!vrbIsValidNode(pThis, cmd, pResp))
    2604         return VINF_SUCCESS;
    2605 
    26062565    *pResp = 0;
    26072566    return codecSetConfigX(pThis, cmd, 24);
    26082567}
    26092568
     2569/* F04 */
     2570static DECLCALLBACK(int) vrbProcGetSDISelect(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
     2571{
     2572    *pResp = 0;
     2573
     2574    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
     2575        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param;
     2576    else
     2577        LogRel2(("HDA: Warning: Unhandled get SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2578
     2579    return VINF_SUCCESS;
     2580}
     2581
     2582/* 704 */
     2583static DECLCALLBACK(int) vrbProcSetSDISelect(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
     2584{
     2585    *pResp = 0;
     2586
     2587    uint32_t *pu32Reg = NULL;
     2588    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
     2589        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param;
     2590    else
     2591        LogRel2(("HDA: Warning: Unhandled set SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
     2592
     2593    if (pu32Reg)
     2594        hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
     2595
     2596    return VINF_SUCCESS;
     2597}
    26102598
    26112599/**
     
    26152603static const CODECVERB g_aCodecVerbs[] =
    26162604{
    2617 /*     verb     | verb mask              | callback               */
    2618 /*   -----------  --------------------   -----------------------  */
    2619     { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter           },
    2620     { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl       },
    2621     { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl       },
    2622     { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId            },
    2623     { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId            },
    2624     { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl             },
    2625     { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl             },
    2626     { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled  },
    2627     { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled  },
    2628     { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense            },
    2629     { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense            },
    2630     { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry },
    2631     { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState     },
    2632     { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState     },
    2633     { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter    },
    2634     { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1   },
    2635     { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2   },
    2636     { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId               },
    2637     { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0              },
    2638     { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1              },
    2639     { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2              },
    2640     { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3              },
    2641     { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset                  },
    2642     { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState          },
    2643     { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState          },
    2644     { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled     },
    2645     { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled     },
    2646     { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl      },
    2647     { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl      },
    2648     { 0x000F1500, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOData            },
    2649     { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData            },
    2650     { 0x000F1600, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOEnableMask      },
    2651     { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask      },
    2652     { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted      },
    2653     { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted      },
    2654     { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig              },
    2655     { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0             },
    2656     { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1             },
    2657     { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2             },
    2658     { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3             },
    2659     { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat     },
    2660     { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat     },
    2661     { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier           },
    2662     { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier           },
     2605    /* Verb        Verb mask            Callback                        Name
     2606     * ---------- --------------------- ----------------------------------------------------------
     2607     */
     2608    { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter           , "GetParameter          " },
     2609    { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl       , "GetConSelectCtrl      " },
     2610    { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl       , "SetConSelectCtrl      " },
     2611    { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId            , "GetStreamId           " },
     2612    { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId            , "SetStreamId           " },
     2613    { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl             , "GetPinCtrl            " },
     2614    { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl             , "SetPinCtrl            " },
     2615    { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled  , "GetUnsolicitedEnabled " },
     2616    { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled  , "SetUnsolicitedEnabled " },
     2617    { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense            , "GetPinSense           " },
     2618    { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense            , "SetPinSense           " },
     2619    { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry , "GetConnectionListEntry" },
     2620    { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState     , "GetProcessingState    " },
     2621    { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState     , "SetProcessingState    " },
     2622    { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter    , "GetDigitalConverter   " },
     2623    { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1   , "SetDigitalConverter1  " },
     2624    { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2   , "SetDigitalConverter2  " },
     2625    { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId               , "GetSubId              " },
     2626    { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0              , "SetSubId0             " },
     2627    { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1              , "SetSubId1             " },
     2628    { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2              , "SetSubId2             " },
     2629    { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3              , "SetSubId3             " },
     2630    { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset                  , "Reset                 " },
     2631    { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState          , "GetPowerState         " },
     2632    { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState          , "SetPowerState         " },
     2633    { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled     , "GetEAPD_BTLEnabled    " },
     2634    { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled     , "SetEAPD_BTLEnabled    " },
     2635    { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl      , "GetVolumeKnobCtrl     " },
     2636    { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl      , "SetVolumeKnobCtrl     " },
     2637    { 0x000F1500, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOData            , "GetGPIOData           " },
     2638    { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData            , "SetGPIOData           " },
     2639    { 0x000F1600, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOEnableMask      , "GetGPIOEnableMask     " },
     2640    { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask      , "SetGPIOEnableMask     " },
     2641    { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted      , "GetGPIOUnsolisted     " },
     2642    { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted      , "SetGPIOUnsolisted     " },
     2643    { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig              , "GetConfig             " },
     2644    { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0             , "SetConfig0            " },
     2645    { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1             , "SetConfig1            " },
     2646    { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2             , "SetConfig2            " },
     2647    { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3             , "SetConfig3            " },
     2648    { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat     , "GetConverterFormat    " },
     2649    { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat     , "SetConverterFormat    " },
     2650    { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier           , "GetAmplifier          " },
     2651    { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier           , "SetAmplifier          " },
     2652    { 0x000F0400, CODEC_VERB_8BIT_CMD , vrbProcGetSDISelect           , "GetSDISelect          " },
     2653    { 0x00070400, CODEC_VERB_8BIT_CMD , vrbProcSetSDISelect           , "SetSDISelect          " }
    26632654    /** @todo Implement 0x7e7: IDT Set GPIO (STAC922x only). */
    26642655};
     
    27172708
    27182709    CODECDBG_INDENT
     2710        codecDbgPrintf(pInfo, "Connections: %RU8\n", CODEC_F00_0E_COUNT(paReg00[0xE]));
    27192711        codecDbgPrintf(pInfo, "Amplifier Caps:\n");
    27202712        uint32_t uReg = paReg00[0xD];
     
    27312723                           CODEC_F00_12_STEP_SIZE(uReg),
    27322724                           CODEC_F00_12_OFFSET(uReg),
    2733                            RT_BOOL(CODEC_F00_0D_IS_CAP_MUTE(uReg)));
     2725                           RT_BOOL(CODEC_F00_12_IS_CAP_MUTE(uReg)));
    27342726        CODECDBG_UNINDENT
    27352727    CODECDBG_UNINDENT
     
    27622754}
    27632755
    2764 static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode)
     2756static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode, bool fRecursive)
    27652757{
    27662758    codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node.id, pNode->node.id);
     
    28542846    else
    28552847        CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node.id);
     2848
     2849    if (fRecursive)
     2850    {
     2851#define CODECDBG_PRINT_CONLIST_ENTRY(_aNode, _aEntry)                              \
     2852        if (cCnt >= _aEntry)                                                       \
     2853        {                                                                          \
     2854            const uint8_t uID = RT_BYTE##_aEntry(_aNode->node.au32F02_param[0x0]); \
     2855            if (pNode->node.id == uID)                                             \
     2856                codecDbgPrintNode(pInfo, _aNode, false /* fRecursive */);          \
     2857        }
     2858
     2859        /* Slow recursion, but this is debug stuff anyway. */
     2860        for (uint8_t i = 0; i < pInfo->pThis->cTotalNodes; i++)
     2861        {
     2862            const PCODECNODE pSubNode = &pInfo->pThis->paNodes[i];
     2863            if (pSubNode->node.id == pNode->node.id)
     2864                continue;
     2865
     2866            const uint8_t cCnt = CODEC_F00_0E_COUNT(pSubNode->node.au32F00_param[0xE]);
     2867            if (cCnt == 0) /* No connections present? Skip. */
     2868                continue;
     2869
     2870            CODECDBG_INDENT
     2871                CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 1)
     2872                CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 2)
     2873                CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 3)
     2874                CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 4)
     2875            CODECDBG_UNINDENT
     2876        }
     2877
     2878#undef CODECDBG_PRINT_CONLIST_ENTRY
     2879   }
    28562880}
    28572881
    28582882static DECLCALLBACK(void) codecDbgListNodes(PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs)
    28592883{
    2860     pHlp->pfnPrintf(pHlp, "HDA LINK\n");
     2884    pHlp->pfnPrintf(pHlp, "HDA LINK / INPUTS\n");
    28612885
    28622886    CODECDBGINFO dbgInfo;
     
    28712895        {
    28722896            PCODECNODE pNode = &pThis->paNodes[i];
    2873             if (pNode->node.au32F00_param[0xE] == 0) /* Start with all nodes connected directly to the HDA (Azalia) link. */
    2874                 codecDbgPrintNode(&dbgInfo, pNode);
     2897
     2898            /* Start with all nodes which have connection entries set. */
     2899            if (CODEC_F00_0E_COUNT(pNode->node.au32F00_param[0xE]))
     2900                codecDbgPrintNode(&dbgInfo, pNode, true /* fRecursive */);
    28752901        }
    28762902    CODECDBG_UNINDENT
     
    28832909#endif
    28842910
    2885 static DECLCALLBACK(int) codecLookup(PHDACODEC pThis, uint32_t cmd, PPFNHDACODECVERBPROCESSOR pfn)
    2886 {
    2887     Assert(CODEC_CAD(cmd) == pThis->id);
     2911static DECLCALLBACK(int) codecLookup(PHDACODEC pThis, uint32_t cmd, uint64_t *puResp)
     2912{
     2913    AssertPtrReturn(pThis,  VERR_INVALID_POINTER);
     2914    AssertPtrReturn(puResp, VERR_INVALID_POINTER);
     2915
     2916    if (CODEC_CAD(cmd) != pThis->id)
     2917    {
     2918        *puResp = 0;
     2919        AssertMsgFailed(("Unknown codec address 0x%x\n", CODEC_CAD(cmd)));
     2920        return VERR_INVALID_PARAMETER;
     2921    }
    28882922
    28892923    if (   CODEC_VERBDATA(cmd) == 0
    28902924        || CODEC_NID(cmd) >= pThis->cTotalNodes)
    28912925    {
    2892         *pfn = vrbProcUnimplemented;
    2893         AssertMsgFailed(("Unknown / invalid node 0x%x\n", CODEC_NID(cmd)));
    2894         return VINF_SUCCESS;
    2895     }
    2896 
    2897     for (int i = 0; i < pThis->cVerbs; i++)
     2926        *puResp = 0;
     2927        AssertMsgFailed(("[NID0x%02x] Unknown / invalid node or data (0x%x)\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
     2928        return VERR_INVALID_PARAMETER;
     2929    }
     2930
     2931    /** @todo r=andy Implement a binary search here. */
     2932    for (size_t i = 0; i < pThis->cVerbs; i++)
    28982933    {
    28992934        if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb)
    29002935        {
    2901             *pfn = pThis->paVerbs[i].pfn;
    2902             return VINF_SUCCESS;
    2903         }
    2904     }
    2905 
    2906     *pfn = vrbProcUnimplemented;
    2907 
    2908     LogFlowFunc(("[NID0x%x] Callback for %x not found\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
    2909     return VINF_SUCCESS;
     2936            int rc2 = pThis->paVerbs[i].pfn(pThis, cmd, puResp);
     2937            AssertRC(rc2);
     2938            Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> 0x%x\n",
     2939                      CODEC_NID(cmd), pThis->paVerbs[i].verb, pThis->paVerbs[i].pszName, CODEC_VERB_PAYLOAD8(cmd), *puResp));
     2940            return rc2;
     2941        }
     2942    }
     2943
     2944    *puResp = 0;
     2945    LogFunc(("[NID0x%02x] Callback for %x not found\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
     2946    return VERR_NOT_FOUND;
    29102947}
    29112948
     
    29232960    switch (enmMixerCtl)
    29242961    {
     2962        case PDMAUDIOMIXERCTL_VOLUME:
     2963        case PDMAUDIOMIXERCTL_FRONT:
     2964#ifdef VBOX_WITH_HDA_51_SURROUND
     2965        case PDMAUDIOMIXERCTL_CENTER_LFE:
     2966        case PDMAUDIOMIXERCTL_REAR:
     2967#endif
     2968        {
     2969            break;
     2970        }
    29252971        case PDMAUDIOMIXERCTL_LINE_IN:
    29262972#ifdef VBOX_WITH_HDA_MIC_IN
     
    29282974#endif
    29292975        {
    2930             pCfg->enmDir = PDMAUDIODIR_IN;
    29312976            break;
    29322977        }
    2933 
    2934         case PDMAUDIOMIXERCTL_VOLUME:
    2935         case PDMAUDIOMIXERCTL_FRONT:
    2936         {
    2937             pCfg->enmDir = PDMAUDIODIR_OUT;
    2938             break;
    2939         }
    2940 
    29412978        default:
    29422979            AssertMsgFailed(("Mixer control %ld not implemented\n", enmMixerCtl));
     
    29542991int hdaCodecRemoveStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl)
    29552992{
    2956     return VINF_SUCCESS;
     2993    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2994
     2995    int rc = pThis->pfnMixerRemoveStream(pThis->pHDAState, enmMixerCtl);
     2996
     2997    LogFlowFuncLeaveRC(rc);
     2998    return rc;
    29572999}
    29583000
     
    30333075}
    30343076
    3035 int hdaCodecDestruct(PHDACODEC pThis)
    3036 {
    3037     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     3077/**
     3078 * Powers off the codec.
     3079 *
     3080 * @param   pThis           Codec to power off.
     3081 */
     3082void hdaCodecPowerOff(PHDACODEC pThis)
     3083{
     3084    if (!pThis)
     3085        return;
     3086
     3087    LogFlowFuncEnter();
     3088
     3089    LogRel2(("HDA: Powering off codec ...\n"));
     3090
     3091    int rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_FRONT);
     3092    AssertRC(rc2);
     3093#ifdef VBOX_WITH_HDA_51_SURROUND
     3094    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE);
     3095    AssertRC(rc2);
     3096    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_REAR);
     3097    AssertRC(rc2);
     3098#endif
     3099
     3100#ifdef VBOX_WITH_HDA_MIC_IN
     3101    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_MIC_IN);
     3102    AssertRC(rc2);
     3103#endif
     3104    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_LINE_IN);
     3105    AssertRC(rc2);
     3106}
     3107
     3108void hdaCodecDestruct(PHDACODEC pThis)
     3109{
     3110    if (!pThis)
     3111        return;
     3112
     3113    LogFlowFuncEnter();
    30383114
    30393115    if (pThis->paNodes)
     
    30423118        pThis->paNodes = NULL;
    30433119    }
    3044 
    3045     return VINF_SUCCESS;
    30463120}
    30473121
     
    30643138
    30653139    int rc = stac9220Construct(pThis);
    3066     AssertRC(rc);
     3140    AssertRCReturn(rc, rc);
    30673141
    30683142    /* Common root node initializers. */
     
    30763150    pThis->paNodes[STAC9220_NID_AFG].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
    30773151
    3078     /* Initialize the streams to some default values (44.1 kHz, 16-bit signed, 2 channels).
    3079      * The codec's (fixed) delivery rate is 48kHz, so a frame will be delivered every 20.83us. */
    3080     PDMAUDIOSTREAMCFG strmCfg;
    3081     strmCfg.pszName       = NULL;
    3082     strmCfg.uHz           = 44100;
    3083     strmCfg.cChannels     = 2;
    3084     strmCfg.enmFormat     = AUD_FMT_S16;
    3085     strmCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    3086 
    3087     /*
    3088      * Output streams.
    3089      */
    3090     strmCfg.enmDir = PDMAUDIODIR_OUT;
    3091 
    3092     /* Front. */
    3093     strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
    3094     rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_FRONT, &strmCfg);
    3095     AssertRC(rc);
     3152    do
     3153    {
     3154        /* Initialize the streams to some default values (44.1 kHz, 16-bit signed, 2 channels).
     3155         * The codec's (fixed) delivery rate is 48kHz, so a frame will be delivered every 20.83us. */
     3156        PDMAUDIOSTREAMCFG strmCfg;
     3157        RT_ZERO(strmCfg);
     3158        strmCfg.uHz           = 44100;
     3159        strmCfg.cChannels     = 2;
     3160        strmCfg.enmFormat     = PDMAUDIOFMT_S16;
     3161        strmCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     3162
     3163        /*
     3164         * Output streams.
     3165         */
     3166        strmCfg.enmDir = PDMAUDIODIR_OUT;
     3167
     3168        /* Front. */
     3169        RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Front");
     3170        strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     3171        rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_FRONT, &strmCfg);
     3172        AssertRCBreak(rc);
    30963173
    30973174#ifdef VBOX_WITH_HDA_51_SURROUND
    3098     /* Center / LFE. */
    3099     strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE;
    3100     rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, &strmCfg);
    3101     AssertRC(rc);
    3102 
    3103     /* Rear. */
    3104     strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR;
    3105     rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_REAR, &strmCfg);
    3106     AssertRC(rc);
     3175        /* Center / LFE. */
     3176        RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Center / LFE");
     3177        strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE;
     3178        /** @todo Handle mono channel if only center *or* LFE is available? */
     3179        rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, &strmCfg);
     3180        AssertRCBreak(rc);
     3181
     3182        /* Rear. */
     3183        RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Rear");
     3184        strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR;
     3185        rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_REAR, &strmCfg);
     3186        AssertRCBreak(rc);
    31073187#endif
    31083188
    3109     /*
    3110      * Input streams.
    3111      */
    3112     strmCfg.enmDir = PDMAUDIODIR_IN;
     3189        /*
     3190         * Input streams.
     3191         */
     3192        strmCfg.enmDir = PDMAUDIODIR_IN;
    31133193
    31143194#ifdef VBOX_WITH_HDA_MIC_IN
    3115     strmCfg.DestSource.Source = PDMAUDIORECSOURCE_MIC;
    3116     rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_MIC_IN, &strmCfg);
    3117     AssertRC(rc);
     3195        RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Microphone In");
     3196        strmCfg.DestSource.Source = PDMAUDIORECSOURCE_MIC;
     3197        rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_MIC_IN, &strmCfg);
     3198        AssertRCBreak(rc);
    31183199#endif
    3119     strmCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE;
    3120     rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_LINE_IN, &strmCfg);
    3121     AssertRC(rc);
     3200        RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Line In");
     3201        strmCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE;
     3202        rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_LINE_IN, &strmCfg);
     3203        AssertRCBreak(rc);
     3204
     3205    } while (0);
     3206
     3207    /** @todo Handle rc here? */
    31223208
    31233209    /*
  • trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h

    r60353 r60925  
    4141typedef struct CODECVERB
    4242{
    43     uint32_t verb;
    44     /** operation bitness mask */
    45     uint32_t mask;
     43    /** Verb. */
     44    uint32_t                 verb;
     45    /** Verb mask. */
     46    uint32_t                 mask;
     47    /** Function pointer for implementation callback. */
    4648    PFNHDACODECVERBPROCESSOR pfn;
     49    /** Friendly name, for debugging. */
     50    const char              *pszName;
    4751} CODECVERB;
    4852
     
    6569
    6670    CODECVERB const        *paVerbs;
    67     int                     cVerbs;
     71    size_t                  cVerbs;
    6872
    6973    PCODECNODE              paNodes;
     
    9599    DECLR3CALLBACKMEMBER(int, pfnMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol));
    96100    /** Callbacks by codec implementation. */
    97     DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t verb, PPFNHDACODECVERBPROCESSOR));
     101    DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t uVerb, uint64_t *puResp));
    98102    DECLR3CALLBACKMEMBER(int, pfnReset, (PHDACODEC pThis));
    99103    DECLR3CALLBACKMEMBER(int, pfnCodecNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE));
     
    104108
    105109int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, uint16_t uLUN, PCFGMNODE pCfg);
    106 int hdaCodecDestruct(PHDACODEC pThis);
     110void hdaCodecDestruct(PHDACODEC pThis);
     111void hdaCodecPowerOff(PHDACODEC pThis);
    107112int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM);
    108113int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion);
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r60653 r60925  
    7979    R3PTRTYPE(PPDMAUDIOGSTSTRMOUT)     pStrmOut;
    8080    /** Mixer handle for output stream. */
    81     R3PTRTYPE(PAUDMIXSTREAM)           phStrmOut;
     81    R3PTRTYPE(PAUDMIXSTREAM)           pMixStrm;
    8282} SB16OUTPUTSTREAM, *PSB16OUTPUTSTREAM;
    8383
     
    473473static void dma_cmd8(PSB16STATE pThis, int mask, int dma_len)
    474474{
    475     pThis->fmt        = AUD_FMT_U8;
     475    pThis->fmt        = PDMAUDIOFMT_U8;
    476476    pThis->use_hdma   = 0;
    477477    pThis->fmt_bits   = 8;
     
    576576
    577577    if (16 == pThis->fmt_bits)
    578         pThis->fmt = pThis->fmt_signed ? AUD_FMT_S16 : AUD_FMT_U16;
     578        pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S16 : PDMAUDIOFMT_U16;
    579579    else
    580         pThis->fmt = pThis->fmt_signed ? AUD_FMT_S8 : AUD_FMT_U8;
     580        pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S8 : PDMAUDIOFMT_U8;
    581581
    582582    pThis->left_till_irq = pThis->block_size;
     
    10951095    uint8_t rvol = sb16MixRegToVol(pThis, 0x33);
    10961096    PDMAUDIOVOLUME vol = { false, lvol, rvol };
    1097     AudioMixerSetSinkVolume(pThis->pSinkOutput, &vol);
     1097    AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol);
    10981098}
    10991099
     
    11081108    streamCfg.uHz           = pThis->freq;
    11091109    streamCfg.cChannels     = 1; /* Mono */
    1110     streamCfg.enmFormat     = AUD_FMT_U8;
     1110    streamCfg.enmFormat     = PDMAUDIOFMT_U8;
    11111111    streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    11121112
     
    13181318
    13191319    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1320         pDrv->Out.phStrmOut = NULL;
     1320        pDrv->Out.pMixStrm = NULL;
    13211321
    13221322    pThis->pSinkOutput = NULL;
     
    13641364        streamCfg.uHz           = 44100;
    13651365        streamCfg.cChannels     = 2;
    1366         streamCfg.enmFormat     = AUD_FMT_S16;
     1366        streamCfg.enmFormat     = PDMAUDIOFMT_S16;
    13671367        streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    13681368
     
    13711371
    13721372        /* Add all required audio sinks. */
    1373         rc2 = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output",
    1374                                 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
     1373        rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
    13751374        AssertRC(rc2);
    13761375    }
     
    20662065        }
    20672066
    2068         int rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
    2069         LogFlowFunc(("LUN#%RU8: Created output with rc=%Rrc\n", uLUN, rc));
    2070         if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
     2067        AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     2068
     2069        AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
     2070        pDrv->Out.pMixStrm = NULL;
     2071
     2072        int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
     2073        if (RT_SUCCESS(rc2))
    20712074        {
    2072             AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
    2073             rc = AudioMixerAddStreamOut(pThis->pSinkOutput,
    2074                                         pDrv->pConnector, pDrv->Out.pStrmOut,
    2075                                         0 /* uFlags */,
    2076                                         &pDrv->Out.phStrmOut);
     2075            rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     2076            LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2));
    20772077        }
    20782078
     
    21502150
    21512151    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    2152         pDrv->Out.phStrmOut = NULL;
     2152        pDrv->Out.pMixStrm = NULL;
    21532153
    21542154    pThis->pSinkOutput = NULL;
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r60651 r60925  
    6565#include "AudioMixBuffer.h"
    6666
     67static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn);
     68static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut);
     69static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn);
     70static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    6771static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn);
    68 
    69 static int drvAudioAllocHstIn(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn);
    70 static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    71 
    72 int drvAudioAddHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
     72static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut);
     73static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn);
     74static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
     75static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg);
     76
     77static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg);
     78
     79static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn);
     80static void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut);
     81
     82
     83int drvAudioAddHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
    7384{
    7485    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    75     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    7686    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    7787
     
    8191    if (!pHstStrmOut)
    8292    {
    83         rc = drvAudioAllocHstOut(pThis, pszName, pCfg, &pHstStrmOut);
     93        rc = drvAudioAllocHstOut(pThis, pCfg, &pHstStrmOut);
    8494        if (RT_FAILURE(rc))
    8595            pHstStrmOut = drvAudioFindAnyHstOut(pThis, NULL /* pHstStrmOut */);
     
    113123    }
    114124
    115     PDMAUDIOFMT fmt = drvAudioHlpStringToFormat(pszValue);
    116     if (fmt == AUD_FMT_INVALID)
     125    PDMAUDIOFMT fmt = DrvAudioStrToAudFmt(pszValue);
     126    if (fmt == PDMAUDIOFMT_INVALID)
    117127    {
    118128         *pfDefault = true;
     
    275285        switch (pCfg->enmFormat)
    276286        {
    277             case AUD_FMT_S8:
    278             case AUD_FMT_U8:
    279             case AUD_FMT_S16:
    280             case AUD_FMT_U16:
    281             case AUD_FMT_S32:
    282             case AUD_FMT_U32:
     287            case PDMAUDIOFMT_S8:
     288            case PDMAUDIOFMT_U8:
     289            case PDMAUDIOFMT_S16:
     290            case PDMAUDIOFMT_U16:
     291            case PDMAUDIOFMT_S32:
     292            case PDMAUDIOFMT_U32:
    283293                break;
    284294            default:
     
    294304}
    295305
    296 /**
    297  * Clears a sample buffer by the given amount of audio samples.
    298  *
    299  * @return  IPRT status code.
    300  * @param   pPCMProps               PCM properties to use for the buffer to clear.
    301  * @param   pvBuf                   Buffer to clear.
    302  * @param   cbBuf                   Size (in bytes) of the buffer.
    303  * @param   cSamples                Number of audio samples to clear in the buffer.
    304  */
    305 void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
    306 {
    307     AssertPtrReturnVoid(pPCMProps);
    308     AssertPtrReturnVoid(pvBuf);
    309 
    310     if (!cbBuf || !cSamples)
    311         return;
    312 
    313     Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n",
    314               pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift));
    315 
    316     if (pPCMProps->fSigned)
    317     {
    318         memset(pvBuf, 0, cSamples << pPCMProps->cShift);
    319     }
    320     else
    321     {
    322         switch (pPCMProps->cBits)
    323         {
    324             case 8:
    325             {
    326                 memset(pvBuf, 0x80, cSamples << pPCMProps->cShift);
    327                 break;
    328             }
    329 
    330             case 16:
    331             {
    332                 uint16_t *p = (uint16_t *)pvBuf;
    333                 int shift = pPCMProps->cChannels - 1;
    334                 short s = INT16_MAX;
    335 
    336                 if (pPCMProps->fSwapEndian)
    337                     s = RT_BSWAP_U16(s);
    338 
    339                 for (unsigned i = 0; i < cSamples << shift; i++)
    340                     p[i] = s;
    341 
    342                 break;
    343             }
    344 
    345             case 32:
    346             {
    347                 uint32_t *p = (uint32_t *)pvBuf;
    348                 int shift = pPCMProps->cChannels - 1;
    349                 int32_t s = INT32_MAX;
    350 
    351                 if (pPCMProps->fSwapEndian)
    352                     s = RT_BSWAP_U32(s);
    353 
    354                 for (unsigned i = 0; i < cSamples << shift; i++)
    355                     p[i] = s;
    356 
    357                 break;
    358             }
    359 
    360             default:
    361             {
    362                 AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits));
    363                 break;
    364             }
    365         }
    366     }
    367 }
    368 
    369306static int drvAudioControlHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd)
    370307{
     
    375312    if (RT_FAILURE(rc))
    376313        return rc;
     314
     315    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
    377316
    378317    switch (enmStreamCmd)
     
    384323                rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_ENABLE);
    385324                if (RT_SUCCESS(rc))
    386                 {
    387325                    pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    388                 }
    389                 else
    390                     LogFlowFunc(("Backend reported an error when opening input stream, rc=%Rrc\n", rc));
    391326            }
    392327            else
     
    403338                if (RT_SUCCESS(rc))
    404339                {
    405                     pHstStrmIn->fStatus = PDMAUDIOSTRMSTS_FLAG_NONE; /* Clear all. */
     340                    pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    406341                    AudioMixBufClear(&pHstStrmIn->MixBuf);
    407342                }
    408                 else
    409                     LogFlowFunc(("Backend vetoed closing output stream, rc=%Rrc\n", rc));
    410343            }
    411344            else
     
    419352            if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    420353            {
    421                 Assert(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);
    422354                rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_PAUSE);
    423355                if (RT_SUCCESS(rc))
    424                 {
    425                     LogFunc(("[%s] Pausing stream\n", pHstStrmIn->MixBuf.pszName));
    426356                    pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    427                 }
    428                 else
    429                     LogFlowFunc(("Backend vetoed pausing input stream, rc=%Rrc\n", rc));
    430357            }
    431358            else
     
    439366            if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
    440367            {
    441                 Assert(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);
    442368                rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_RESUME);
    443369                if (RT_SUCCESS(rc))
    444                 {
    445370                    pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    446                     LogFunc(("[%s] Resumed stream\n", pHstStrmIn->MixBuf.pszName));
    447                 }
    448                 else
    449                     LogFlowFunc(("Backend vetoed resuming input stream, rc=%Rrc\n", rc));
    450371            }
    451372            else
     
    461382    }
    462383
     384    LogFunc(("[%s] Returned %Rrc\n", pHstStrmIn->MixBuf.pszName, rc));
     385
    463386    int rc2 = RTCritSectLeave(&pHstStrmIn->CritSect);
    464387    if (RT_SUCCESS(rc))
     
    470393static int drvAudioControlHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)
    471394{
    472     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     395    AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
    473396    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    474397
     
    476399    if (RT_FAILURE(rc))
    477400        return rc;
     401
     402    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
    478403
    479404    switch (enmStreamCmd)
     
    488413                    Assert(!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
    489414                    pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    490                     LogFunc(("[%s] Enabled stream\n", pHstStrmOut->MixBuf.pszName));
    491415                }
    492                 else
    493                     LogFlowFunc(("[%s] Backend reported an error when enabling output stream, rc=%Rrc\n",
    494                                  pHstStrmOut->MixBuf.pszName, rc));
    495416            }
    496417            else
     
    507428                if (RT_SUCCESS(rc))
    508429                {
    509                     pHstStrmOut->fStatus = PDMAUDIOSTRMSTS_FLAG_NONE; /* Clear all. */
     430                    pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    510431                    AudioMixBufClear(&pHstStrmOut->MixBuf);
    511 
    512                     LogFunc(("[%s] Disabled stream\n", pHstStrmOut->MixBuf.pszName));
    513432                }
    514                 else
    515                     LogFlowFunc(("[%s] Backend vetoed disabling output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
    516433            }
    517434            else
     
    525442            if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    526443            {
    527                 Assert(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);
    528444                rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_PAUSE);
    529445                if (RT_SUCCESS(rc))
    530                 {
    531446                    pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    532                     LogFunc(("[%s] Pausing stream\n", pHstStrmOut->MixBuf.pszName));
    533                 }
    534                 else
    535                     LogFlowFunc(("[%s] Backend vetoed pausing output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
    536447            }
    537448            else
     
    545456            if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
    546457            {
    547                 Assert(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);
    548458                rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_RESUME);
    549459                if (RT_SUCCESS(rc))
    550                 {
    551460                    pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    552                     LogFunc(("[%s] Resumed stream\n", pHstStrmOut->MixBuf.pszName));
    553                 }
    554                 else
    555                     LogFlowFunc(("[%s] Backend vetoed resuming output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
    556461            }
    557462            else
     
    567472    }
    568473
     474    LogFunc(("[%s] Returned %Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
     475
    569476    int rc2 = RTCritSectLeave(&pHstStrmOut->CritSect);
    570477    if (RT_SUCCESS(rc))
     
    574481}
    575482
    576 int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    577 {
    578     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     483static int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     484{
     485    AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
    579486    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    580487
    581488    LogFlowFunc(("%s\n", pHstStrmOut->MixBuf.pszName));
    582489
    583     int rc;
     490    int rc = VINF_SUCCESS;
     491
    584492    if (RTListIsEmpty(&pHstStrmOut->lstGstStrmOut))
    585493    {
    586         rc = pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut);
    587         if (RT_SUCCESS(rc))
    588         {
    589             drvAudioHstOutFreeRes(pHstStrmOut);
    590 
    591             /* Remove from driver instance list. */
    592             RTListNodeRemove(&pHstStrmOut->Node);
    593 
    594             if (RTCritSectIsInitialized(&pHstStrmOut->CritSect))
    595             {
    596                 int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect);
    597                 AssertRC(rc2);
    598             }
    599 
    600             RTMemFree(pHstStrmOut);
    601             pThis->cStreamsFreeOut++;
    602             return VINF_SUCCESS;
    603         }
     494        drvAudioHstOutFreeRes(pHstStrmOut);
     495
     496        /* Remove from driver instance list. */
     497        RTListNodeRemove(&pHstStrmOut->Node);
     498
     499        if (RTCritSectIsInitialized(&pHstStrmOut->CritSect))
     500        {
     501            int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect);
     502            AssertRC(rc2);
     503        }
     504
     505        RTMemFree(pHstStrmOut);
     506        pHstStrmOut = NULL;
     507
     508        pThis->cStreamsFreeOut++;
    604509    }
    605510    else
    606511    {
    607         rc = VERR_ACCESS_DENIED;
    608         LogFlowFunc(("[%s] Still is being used, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
    609     }
    610 
    611     return rc;
    612 }
    613 
    614 int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
     512        rc = VERR_WRONG_ORDER;
     513        LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmOut->MixBuf.pszName));
     514    }
     515
     516    LogFlowFuncLeaveRC(rc);
     517    return rc;
     518}
     519
     520static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    615521{
    616522    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    619525        return VINF_SUCCESS;
    620526
     527    LogFlowFunc(("%s\n", pGstStrmOut->MixBuf.pszName));
     528
    621529    if (pGstStrmOut->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */
    622530        return VERR_WRONG_ORDER;
    623531
    624     drvAudioGstOutFreeRes(pGstStrmOut);
    625 
     532    AudioMixBufDestroy(&pGstStrmOut->MixBuf);
     533
     534    /* Is this guest stream associate to a host stream? */
    626535    if (pGstStrmOut->pHstStrmOut)
    627536    {
    628537        /* Unregister from parent first. */
    629538        RTListNodeRemove(&pGstStrmOut->Node);
    630 
    631         /* Try destroying the associated host output stream. This could
    632          * be skipped if there are other guest output streams with this
    633          * host stream. */
    634         drvAudioDestroyHstOut(pThis, pGstStrmOut->pHstStrmOut);
    635539    }
    636540
    637541    RTMemFree(pGstStrmOut);
     542    pGstStrmOut = NULL;
    638543
    639544    return VINF_SUCCESS;
    640545}
    641546
    642 PPDMAUDIOHSTSTRMIN drvAudioFindNextHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     547static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    643548{
    644549    if (pHstStrmIn)
     
    653558}
    654559
    655 PPDMAUDIOHSTSTRMIN drvAudioFindNextEnabledHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    656 {
    657     while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn)))
    658         if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    659             return pHstStrmIn;
    660 
    661     return NULL;
    662 }
    663 
    664 PPDMAUDIOHSTSTRMIN drvAudioFindNextEqHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    665                                            PPDMAUDIOSTREAMCFG pCfg)
    666 {
    667     while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn)))
    668         if (drvAudioPCMPropsAreEqual(&pHstStrmIn->Props, pCfg))
    669             return pHstStrmIn;
    670 
    671     return NULL;
    672 }
    673 
    674 static int drvAudioHstInAdd(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PDMAUDIORECSOURCE enmRecSource,
    675                             PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
    676 {
    677     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    678     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     560static int drvAudioHstInAdd(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
     561{
     562    AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
     563    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    679564    AssertPtrReturn(ppHstStrmIn, VERR_INVALID_POINTER);
    680565
    681566    PPDMAUDIOHSTSTRMIN pHstStrmIn;
    682     int rc = drvAudioAllocHstIn(pThis, pszName, pCfg, enmRecSource, &pHstStrmIn);
     567    int rc = drvAudioAllocHstIn(pThis, pCfg, &pHstStrmIn);
    683568    if (RT_SUCCESS(rc))
    684569        *ppHstStrmIn = pHstStrmIn;
     
    688573}
    689574
    690 int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut,
    691                        const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     575static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn)
     576{
     577    if (!pHstStrmIn)
     578        return;
     579
     580    AudioMixBufDestroy(&pHstStrmIn->MixBuf);
     581}
     582
     583static int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut, PPDMAUDIOSTREAMCFG pCfg)
    692584{
    693585    AssertPtrReturn(pGstStrmOut,  VERR_INVALID_POINTER);
    694586    AssertPtrReturn(pHostStrmOut, VERR_INVALID_POINTER);
    695     AssertPtrReturn(pszName,      VERR_INVALID_POINTER);
    696587    AssertPtrReturn(pCfg,         VERR_INVALID_POINTER);
    697588
     
    699590    if (RT_SUCCESS(rc))
    700591    {
    701         char *pszTemp;
    702         if (RTStrAPrintf(&pszTemp, "%s (Guest)", pszName) <= 0)
     592        char *pszName;
     593        if (RTStrAPrintf(&pszName, "%s (Guest)", pCfg->szName) <= 0)
    703594            return VERR_NO_MEMORY;
    704595
    705         rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszTemp, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf));
     596        rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszName, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf));
    706597        if (RT_SUCCESS(rc))
    707598            rc = AudioMixBufLinkTo(&pGstStrmOut->MixBuf, &pHostStrmOut->MixBuf);
    708 
    709         RTStrFree(pszTemp);
    710599
    711600        if (RT_SUCCESS(rc))
     
    715604            pGstStrmOut->State.fEmpty  = true;
    716605
    717             pGstStrmOut->State.pszName = RTStrDup(pszName);
    718             if (!pGstStrmOut->State.pszName)
    719                 return VERR_NO_MEMORY;
     606            RTStrPrintf(pGstStrmOut->State.szName, RT_ELEMENTS(pGstStrmOut->State.szName),
     607                        "%s", pszName);
    720608
    721609            pGstStrmOut->pHstStrmOut = pHostStrmOut;
    722610        }
    723     }
    724 
    725     LogFlowFunc(("pszName=%s, rc=%Rrc\n", pszName, rc));
    726     return rc;
    727 }
    728 
    729 int drvAudioAllocHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
     611
     612        RTStrFree(pszName);
     613    }
     614
     615    LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc));
     616    return rc;
     617}
     618
     619static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
    730620{
    731621    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    732     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    733     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     622    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    734623
    735624    if (!pThis->cStreamsFreeOut)
     
    755644
    756645    int rc;
    757     bool fInitialized = false;
    758646
    759647    do
     
    761649        RTListInit(&pHstStrmOut->lstGstStrmOut);
    762650
    763         uint32_t cSamples;
    764         rc = pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples);
     651        uint32_t cSamples = 0;
     652        rc = pThis->pHostDrvAudio->pfnInitOut
     653           ? pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples) : VINF_SUCCESS;
     654
    765655        if (RT_FAILURE(rc))
    766656        {
     
    769659        }
    770660
    771         fInitialized = true;
    772 
    773         char *pszTemp;
    774         if (RTStrAPrintf(&pszTemp, "%s (Host)", pszName) <= 0)
     661        pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     662
     663        char *pszName;
     664        if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0)
    775665        {
    776666            rc = VERR_NO_MEMORY;
     
    778668        }
    779669
    780         rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszTemp, &pHstStrmOut->Props, cSamples);
     670        rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszName, &pHstStrmOut->Props, cSamples);
    781671        if (RT_SUCCESS(rc))
    782672            rc = RTCritSectInit(&pHstStrmOut->CritSect);
     
    788678        }
    789679
    790         RTStrFree(pszTemp);
     680        RTStrFree(pszName);
    791681
    792682    } while (0);
     
    794684    if (RT_FAILURE(rc))
    795685    {
    796         if (fInitialized)
    797         {
    798             int rc2 = pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut);
    799             AssertRC(rc2);
     686        if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     687        {
     688            int rc2 = pThis->pHostDrvAudio->pfnFiniOut
     689                    ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS;
     690            if (RT_SUCCESS(rc2))
     691                pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    800692        }
    801693
     
    810702}
    811703
    812 int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, const char *pszName,
    813                                 PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
     704static int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
    814705{
    815706    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    816     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    817707    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    818708
     
    821711    if (!pGstStrmOut)
    822712    {
    823         LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", pszName));
     713        LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", pCfg->szName));
    824714        return VERR_NO_MEMORY;
    825715    }
     
    829719     */
    830720    PPDMAUDIOHSTSTRMOUT pHstStrmOut;
    831     int rc = drvAudioAddHstOut(pThis, pszName, pCfg, &pHstStrmOut);
     721    int rc = drvAudioAddHstOut(pThis, pCfg, &pHstStrmOut);
    832722    if (RT_FAILURE(rc))
    833723    {
    834         LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", pszName, rc));
     724        LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", pCfg->szName, rc));
    835725
    836726        RTMemFree(pGstStrmOut);
     
    842732     * by the device emulation (which in turn was/could be set by the guest OS).
    843733     */
    844     rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, pszName, pCfg);
     734    rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, pCfg);
    845735    if (RT_SUCCESS(rc))
    846736    {
     
    858748}
    859749
    860 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, const char *pszName, PDMAUDIORECSOURCE enmRecSource,
    861                                       PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
     750static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
    862751{
    863752    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    864     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    865753    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    866754
     
    873761     */
    874762    PPDMAUDIOHSTSTRMIN pHstStrmIn;
    875     int rc = drvAudioHstInAdd(pThis, pszName, pCfg, enmRecSource, &pHstStrmIn);
     763    int rc = drvAudioHstInAdd(pThis, pCfg, &pHstStrmIn);
    876764    if (RT_FAILURE(rc))
    877765    {
    878         LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", pszName, rc));
     766        LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", pCfg->szName, rc));
    879767
    880768        RTMemFree(pGstStrmIn);
     
    886774     * by the device emulation (which in turn was/could be set by the guest OS).
    887775     */
    888     rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, pszName, pCfg);
     776    rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, pCfg);
    889777    if (RT_SUCCESS(rc))
    890778    {
     
    908796 * @param   pHstStrmIn          Pointer to host input stream to associate this guest
    909797 *                              stream with.
    910  * @param   pszName             Pointer to stream name to use for this stream.
    911798 * @param   pCfg                Pointer to stream configuration to use.
    912799 */
    913 int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    914                       const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     800static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg)
    915801{
    916802    AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER);
    917803    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    918     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    919804    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    920805
     
    922807    if (RT_SUCCESS(rc))
    923808    {
    924         char *pszTemp;
    925         if (RTStrAPrintf(&pszTemp, "%s (Guest)", pszName) <= 0)
     809        char *pszName;
     810        if (RTStrAPrintf(&pszName, "%s (Guest)",
     811                         strlen(pCfg->szName) ? pCfg->szName : "<Untitled>") <= 0)
     812        {
    926813            return VERR_NO_MEMORY;
    927 
    928         rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszTemp, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf));
     814        }
     815
     816        rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszName, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf));
    929817        if (RT_SUCCESS(rc))
    930818            rc = AudioMixBufLinkTo(&pHstStrmIn->MixBuf, &pGstStrmIn->MixBuf);
    931819
    932         RTStrFree(pszTemp);
    933 
    934820        if (RT_SUCCESS(rc))
    935821        {
    936822#ifdef DEBUG
    937             drvAudioStreamCfgPrint(pCfg);
     823            DrvAudioStreamCfgPrint(pCfg);
    938824#endif
    939825            pGstStrmIn->State.cRefs   = 1;
     
    941827            pGstStrmIn->State.fEmpty  = true;
    942828
    943             pGstStrmIn->State.pszName = RTStrDup(pszName);
    944             if (!pGstStrmIn->State.pszName)
    945                 return VERR_NO_MEMORY;
     829            RTStrPrintf(pGstStrmIn->State.szName, RT_ELEMENTS(pGstStrmIn->State.szName),
     830                        "%s", pszName);
    946831
    947832            pGstStrmIn->pHstStrmIn = pHstStrmIn;
    948833        }
    949     }
    950 
    951     LogFlowFunc(("pszName=%s, rc=%Rrc\n", pszName, rc));
    952     return rc;
    953 }
    954 
    955 static int drvAudioAllocHstIn(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg,
    956                               PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
     834
     835        RTStrFree(pszName);
     836    }
     837
     838    LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc));
     839    return rc;
     840}
     841
     842static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
    957843{
    958844    if (!pThis->cStreamsFreeIn)
     
    979865
    980866    int rc;
    981     bool fInitialized = false;
    982867
    983868    do
    984869    {
    985         uint32_t cSamples;
    986         rc = pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn,
    987                                              pCfg, enmRecSource, &cSamples);
     870        uint32_t cSamples = 0;
     871        rc = pThis->pHostDrvAudio->pfnInitIn
     872           ? pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn,
     873                                             pCfg, pCfg->DestSource.Source, &cSamples) : VINF_SUCCESS;
    988874        if (RT_FAILURE(rc))
    989875        {
     
    992878        }
    993879
    994         fInitialized = true;
    995 
    996         char *pszTemp;
    997         if (RTStrAPrintf(&pszTemp, "%s (Host)", pszName) <= 0)
     880        pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     881
     882        char *pszName;
     883        if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0)
    998884        {
    999885            rc = VERR_NO_MEMORY;
     
    1001887        }
    1002888
    1003         rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszTemp, &pHstStrmIn->Props, cSamples);
     889        rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszName, &pHstStrmIn->Props, cSamples);
    1004890        if (RT_SUCCESS(rc))
    1005891            rc = RTCritSectInit(&pHstStrmIn->CritSect);
     
    1011897        }
    1012898
    1013         RTStrFree(pszTemp);
     899        RTStrFree(pszName);
    1014900
    1015901    } while (0);
     
    1017903    if (RT_FAILURE(rc))
    1018904    {
    1019         if (fInitialized)
    1020         {
    1021             int rc2 = pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio,
    1022                                                       pHstStrmIn);
    1023             AssertRC(rc2);
     905        if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     906        {
     907            int rc2 = pThis->pHostDrvAudio->pfnFiniIn
     908                    ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS;
     909            if (RT_SUCCESS(rc2))
     910                pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    1024911        }
    1025912
     
    11161003    }
    11171004
    1118     LogFlowFunc(("%s -> %s: Written pvBuf=%p, cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",
    1119                  pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, pvBuf, cbBuf, cWritten,
     1005    LogFlowFunc(("%s -> %s: cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",
     1006                 pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, cbBuf, cWritten,
    11201007                 AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cWritten), cMixed, rc));
    11211008
     
    11271014}
    11281015
    1129 PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1016static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    11301017{
    11311018    if (pHstStrmOut)
     
    11401027}
    11411028
    1142 PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut)
     1029static PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut)
    11431030{
    11441031    while ((pHostStrmOut = drvAudioFindAnyHstOut(pThis, pHostStrmOut)))
     
    11511038}
    11521039
    1153 PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1154                                             PPDMAUDIOSTREAMCFG pCfg)
     1040static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
     1041                                                   PPDMAUDIOSTREAMCFG pCfg)
    11551042{
    11561043    while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    11571044    {
    1158         if (drvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg))
     1045        if (DrvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg))
    11591046            return pHstStrmOut;
    11601047    }
     
    11651052int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    11661053{
     1054    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
     1055    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     1056
     1057    LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName));
     1058
     1059    int rc = VINF_SUCCESS;
     1060
     1061    if (!pHstStrmIn->pGstStrmIn)
     1062    {
     1063        drvAudioHstInFreeRes(pHstStrmIn);
     1064
     1065        if (RTCritSectIsInitialized(&pHstStrmIn->CritSect))
     1066        {
     1067            int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect);
     1068            AssertRC(rc2);
     1069        }
     1070
     1071        /* Remove from driver instance list. */
     1072        RTListNodeRemove(&pHstStrmIn->Node);
     1073
     1074        RTMemFree(pHstStrmIn);
     1075        pThis->cStreamsFreeIn++;
     1076    }
     1077    else
     1078    {
     1079        rc = VERR_WRONG_ORDER;
     1080        LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmIn->MixBuf.pszName));
     1081    }
     1082
     1083    LogFlowFuncLeaveRC(rc);
     1084    return rc;
     1085}
     1086
     1087static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn)
     1088{
    11671089    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1168     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    1169 
    1170     LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName));
    1171 
    1172     int rc;
    1173     if (!pHstStrmIn->pGstStrmIn) /* No parent anymore? */
    1174     {
    1175         rc = pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn);
    1176         if (RT_SUCCESS(rc))
    1177         {
    1178             drvAudioHstInFreeRes(pHstStrmIn);
    1179 
    1180             if (RTCritSectIsInitialized(&pHstStrmIn->CritSect))
    1181             {
    1182                 int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect);
    1183                 AssertRC(rc2);
    1184             }
    1185 
    1186             /* Remove from driver instance list. */
    1187             RTListNodeRemove(&pHstStrmIn->Node);
    1188 
    1189             RTMemFree(pHstStrmIn);
    1190             pThis->cStreamsFreeIn++;
    1191         }
    1192     }
    1193     else
    1194     {
    1195         rc = VERR_ACCESS_DENIED;
    1196         LogFlowFunc(("[%s] Still is being used, rc=%Rrc\n", pHstStrmIn->MixBuf.pszName, rc));
    1197     }
    1198 
    1199     return rc;
    1200 }
    1201 
    1202 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn)
    1203 {
    1204     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1205 
    1206     LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName));
    12071090
    12081091    if (!pGstStrmIn)
    12091092        return VINF_SUCCESS;
    12101093
     1094    LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName));
     1095
    12111096    if (pGstStrmIn->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */
    12121097        return VERR_WRONG_ORDER;
    12131098
    1214     drvAudioGstInFreeRes(pGstStrmIn);
    1215 
     1099    AudioMixBufDestroy(&pGstStrmIn->MixBuf);
     1100
     1101    /* Is this guest stream associate to a host stream? */
    12161102    if (pGstStrmIn->pHstStrmIn)
    12171103    {
    12181104        /* Unlink child. */
    12191105        pGstStrmIn->pHstStrmIn->pGstStrmIn = NULL;
    1220 
    1221         /* Try destroying the associated host input stream. This could
    1222          * be skipped if there are other guest input streams with this
    1223          * host stream. */
    1224         drvAudioDestroyHstIn(pThis, pGstStrmIn->pHstStrmIn);
    12251106    }
    12261107
    12271108    RTMemFree(pGstStrmIn);
     1109    pGstStrmIn = NULL;
    12281110
    12291111    return VINF_SUCCESS;
     1112}
     1113
     1114static DECLCALLBACK(uint32_t) drvAudioAddRefIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm)
     1115{
     1116   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1117   AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER);
     1118
     1119   NOREF(pInterface);
     1120
     1121   return ++pGstStrm->State.cRefs;
     1122}
     1123
     1124static DECLCALLBACK(uint32_t) drvAudioAddRefOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm)
     1125{
     1126   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1127   AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
     1128
     1129   NOREF(pInterface);
     1130
     1131   return ++pGstStrm->State.cRefs;
     1132}
     1133
     1134static DECLCALLBACK(uint32_t) drvAudioReleaseIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm)
     1135{
     1136   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1137   AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
     1138
     1139   NOREF(pInterface);
     1140
     1141   Assert(pGstStrm->State.cRefs);
     1142   if (pGstStrm->State.cRefs)
     1143       pGstStrm->State.cRefs--;
     1144
     1145   return pGstStrm->State.cRefs;
     1146}
     1147
     1148static DECLCALLBACK(uint32_t) drvAudioReleaseOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm)
     1149{
     1150   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1151   AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
     1152
     1153   NOREF(pInterface);
     1154
     1155   Assert(pGstStrm->State.cRefs);
     1156   if (pGstStrm->State.cRefs)
     1157       pGstStrm->State.cRefs--;
     1158
     1159   return pGstStrm->State.cRefs;
    12301160}
    12311161
     
    13091239
    13101240    PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    1311     while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn)))
    1312     {
     1241    while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
     1242    {
     1243        /* Disabled? Skip it! */
     1244        if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     1245            continue;
     1246
    13131247        /* Call the host backend to capture the audio input data. */
    13141248        uint32_t cSamplesCaptured;
     
    13731307        AssertRC(rc);
    13741308
    1375         if (!pThis->BackendCfg.cMaxStreamsOut)
     1309        if (   !pThis->BackendCfg.cSinks
     1310            || !pThis->BackendCfg.cMaxStreamsOut)
    13761311        {
    13771312            int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    14221357        if (RT_FAILURE(rc2))
    14231358        {
    1424             rc2 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    1425             AssertRC(rc2);
     1359            int rc3 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
     1360            AssertRC(rc3);
    14261361        }
    14271362        else
     
    16201555    }
    16211556
    1622     if (pThis->BackendCfg.cbStreamOut)
    1623     {
     1557    pThis->cStreamsFreeIn  = 0;
     1558    pThis->cStreamsFreeOut = 0;
     1559
     1560    if (pThis->BackendCfg.cSinks)
     1561    {
     1562        Assert(pThis->BackendCfg.cbStreamOut);
     1563
    16241564        pThis->cStreamsFreeOut = pThis->BackendCfg.cMaxStreamsOut;
    16251565    }
    1626     else
    1627         pThis->cStreamsFreeOut = 0;
    1628 
    1629     if (pThis->BackendCfg.cbStreamIn)
    1630     {
    1631         /*
    1632          * Note:
    1633          *  - Our AC'97 emulation has two inputs, line (ac97.pi) and microphone (ac97.mc).
    1634          *  - Our HDA emulation currently has only line input (hda.pi).
    1635          */
     1566
     1567    if (pThis->BackendCfg.cSources)
     1568    {
     1569        Assert(pThis->BackendCfg.cbStreamIn);
     1570
    16361571        pThis->cStreamsFreeIn = pThis->BackendCfg.cMaxStreamsIn;
    16371572    }
    1638     else
    1639         pThis->cStreamsFreeIn = 0;
    16401573
    16411574    LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->cStreamsFreeIn, pThis->cStreamsFreeOut));
     
    16601593
    16611594    PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
    1662     while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut)))
     1595    while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    16631596        drvAudioControlHstOut(pThis, pHstStrmOut, enmCmd);
    16641597
    16651598    PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    1666     while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn)))
     1599    while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
    16671600        drvAudioControlHstIn(pThis, pHstStrmIn, enmCmd);
    16681601}
     
    16741607
    16751608    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
    1676     LogFlowFunc(("pDrvAudio=%p, pDrvIns=%p\n", pThis, pDrvIns));
     1609    LogFlowFunc(("pThis=%p, pDrvIns=%p\n", pThis, pDrvIns));
    16771610
    16781611    RTListInit(&pThis->lstHstStrmIn);
     
    17031636    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    17041637
    1705     AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER);
     1638    if (!pGstStrmIn)
     1639        return VERR_NOT_AVAILABLE;
     1640
    17061641    AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    17071642    AssertReturn(cbBuf,         VERR_INVALID_PARAMETER);
     
    17541689{
    17551690    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1756     /* pGstStrmOut is optional. */
     1691
     1692    if (!pGstStrmOut)
     1693        return VERR_NOT_AVAILABLE;
    17571694
    17581695    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     
    17601697    int rc = VINF_SUCCESS;
    17611698
    1762     if (pGstStrmOut)
    1763     {
    1764         PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut;
    1765         AssertPtr(pHstStrmOut);
    1766 
    1767         if (fEnable)
    1768         {
    1769             /* Is a pending disable outstanding? Then disable first. */
    1770             if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
     1699    PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut;
     1700    AssertPtr(pHstStrmOut);
     1701
     1702    if (fEnable)
     1703    {
     1704        /* Is a pending disable outstanding? Then disable first. */
     1705        if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
     1706        {
     1707            rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
     1708            if (RT_SUCCESS(rc))
     1709                pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     1710        }
     1711
     1712        if (RT_SUCCESS(rc))
     1713            rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
     1714    }
     1715    else /* Disable */
     1716    {
     1717        if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     1718        {
     1719            uint32_t cGstStrmsActive = 0;
     1720
     1721            /*
     1722             * Check if there are any active guest streams assigned
     1723             * to this host stream which still are being marked as active.
     1724             *
     1725             * In that case we have to defer closing the host stream and
     1726             * wait until all guest streams have been finished.
     1727             */
     1728            PPDMAUDIOGSTSTRMOUT pIter;
     1729            RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node)
    17711730            {
     1731                if (pIter->State.fActive)
     1732                {
     1733                    cGstStrmsActive++;
     1734                    break; /* At least one assigned & active guest stream is enough. */
     1735                }
     1736            }
     1737
     1738            /* Do we need to defer closing the host stream? */
     1739            if (cGstStrmsActive >= 1)
     1740                pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     1741
     1742            /* Can we close the host stream now instead of deferring it? */
     1743            if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))
    17721744                rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    1773                 if (RT_SUCCESS(rc))
    1774                     pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    1775             }
    1776 
    1777             if (RT_SUCCESS(rc))
    1778                 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
    1779         }
    1780         else /* Disable */
    1781         {
    1782             if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    1783             {
    1784                 uint32_t cGstStrmsActive = 0;
    1785 
    1786                 /*
    1787                  * Check if there are any active guest streams assigned
    1788                  * to this host stream which still are being marked as active.
    1789                  *
    1790                  * In that case we have to defer closing the host stream and
    1791                  * wait until all guest streams have been finished.
    1792                  */
    1793                 PPDMAUDIOGSTSTRMOUT pIter;
    1794                 RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node)
    1795                 {
    1796                     if (pIter->State.fActive)
    1797                     {
    1798                         cGstStrmsActive++;
    1799                         break; /* At least one assigned & active guest stream is enough. */
    1800                     }
    1801                 }
    1802 
    1803                 /* Do we need to defer closing the host stream? */
    1804                 if (cGstStrmsActive >= 1)
    1805                     pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    1806 
    1807                 /* Can we close the host stream now instead of deferring it? */
    1808                 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE))
    1809                     rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    1810             }
    1811         }
    1812 
    1813         if (RT_SUCCESS(rc))
    1814             pGstStrmOut->State.fActive = fEnable;
    1815 
    1816         LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
    1817                      pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));
    1818     }
     1745        }
     1746    }
     1747
     1748    if (RT_SUCCESS(rc))
     1749        pGstStrmOut->State.fActive = fEnable;
     1750
     1751    LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n",
     1752                 pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc));
    18191753
    18201754    return rc;
     
    18251759{
    18261760    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1827     /* pGstStrmIn is optional. */
     1761
     1762    if (!pGstStrmIn)
     1763        return VERR_NOT_AVAILABLE;
    18281764
    18291765    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     
    18311767    int rc = VINF_SUCCESS;
    18321768
    1833     if (pGstStrmIn)
    1834     {
    1835         PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn;
    1836         AssertPtr(pHstStrmIn);
    1837 
    1838         LogFlowFunc(("%s: fEnable=%RTbool\n", pGstStrmIn->MixBuf.pszName, fEnable));
    1839 
    1840         rc = drvAudioControlHstIn(pThis, pHstStrmIn,
    1841                                   fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
    1842         if (RT_SUCCESS(rc))
    1843             pGstStrmIn->State.fActive = fEnable;
    1844 
    1845         LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));
    1846     }
     1769    PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn;
     1770    AssertPtr(pHstStrmIn);
     1771
     1772    rc = drvAudioControlHstIn(pThis, pHstStrmIn,
     1773                              fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
     1774    if (RT_SUCCESS(rc))
     1775        pGstStrmIn->State.fActive = fEnable;
     1776
     1777    LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));
    18471778
    18481779    return rc;
     
    18611792}
    18621793
    1863 static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, const char *pszName,
    1864                                           PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
     1794static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
     1795                                          PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
    18651796{
    18661797    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    1867     AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);
    1868     AssertPtrReturn(pszName,     VERR_INVALID_POINTER);
    18691798    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    18701799    AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);
     
    18781807        return rc;
    18791808
    1880     LogFlowFunc(("pszName=%s, pCfg=%p\n", pszName, pCfg));
     1809    LogFlowFunc(("szName=%s\n", pCfg->szName));
    18811810
    18821811    if (!drvAudioStreamCfgIsValid(pCfg))
     
    18891818    {
    18901819        PPDMAUDIOGSTSTRMIN pGstStrmIn;
    1891         rc = drvAudioCreateStreamPairIn(pThis, pszName, pCfg->DestSource.Source, pCfg, &pGstStrmIn);
     1820        rc = drvAudioCreateStreamPairIn(pThis, pCfg, &pGstStrmIn);
    18921821        if (RT_SUCCESS(rc))
    18931822            *ppGstStrmIn = pGstStrmIn;
     
    19021831}
    19031832
    1904 static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, const char *pszName,
    1905                                            PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
     1833static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
     1834                                           PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
    19061835{
    19071836    AssertPtrReturn(pInterface,   VERR_INVALID_POINTER);
    1908     AssertPtrReturn(pszName,      VERR_INVALID_POINTER);
    19091837    AssertPtrReturn(pCfg,         VERR_INVALID_POINTER);
    19101838    AssertPtrReturn(ppGstStrmOut, VERR_INVALID_POINTER);
     
    19181846        return rc;
    19191847
    1920     LogFlowFunc(("pszName=%s, pCfg=%p\n", pszName, pCfg));
     1848    LogFlowFunc(("pszName=%s\n", pCfg->szName));
    19211849
    19221850    if (!drvAudioStreamCfgIsValid(pCfg))
     
    19291857    {
    19301858        PPDMAUDIOGSTSTRMOUT pGstStrmOut;
    1931         rc = drvAudioCreateStreamPairOut(pThis, pszName, pCfg, &pGstStrmOut);
     1859        rc = drvAudioCreateStreamPairOut(pThis, pCfg, &pGstStrmOut);
    19321860        if (RT_SUCCESS(rc))
    19331861            *ppGstStrmOut = pGstStrmOut;
     
    19421870}
    19431871
    1944 static DECLCALLBACK(int) drvAudioGetConfiguration(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)
     1872static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)
    19451873{
    19461874    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    20061934    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    20071935
     1936    if (!pGstStrmIn)
     1937        return;
     1938
    20081939    int rc2 = RTCritSectEnter(&pThis->CritSect);
    20091940    AssertRC(rc2);
    20101941
    2011     if (pGstStrmIn)
    2012         drvAudioDestroyGstIn(pThis, pGstStrmIn);
     1942    rc2 = drvAudioDestroyGstIn(pThis, pGstStrmIn);
     1943    AssertRC(rc2);
    20131944
    20141945    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    20231954    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    20241955
     1956    if (!pGstStrmOut)
     1957        return;
     1958
    20251959    int rc2 = RTCritSectEnter(&pThis->CritSect);
    20261960    AssertRC(rc2);
    20271961
    2028     if (pGstStrmOut)
    2029         drvAudioDestroyGstOut(pThis, pGstStrmOut);
     1962    rc2 = drvAudioDestroyGstOut(pThis, pGstStrmOut);
     1963    AssertRC(rc2);
    20301964
    20311965    rc2 = RTCritSectLeave(&pThis->CritSect);
    20321966    AssertRC(rc2);
     1967}
     1968
     1969void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1970{
     1971    AssertPtrReturnVoid(pHstStrmOut);
     1972    AudioMixBufDestroy(&pHstStrmOut->MixBuf);
    20331973}
    20341974
     
    20581998static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns)
    20591999{
     2000    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
     2001
    20602002    LogFlowFuncEnter();
    2061     PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    2062 
    2063     PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
    2064 
    2065     if (!pThis->pHostDrvAudio)
    2066         return;
    2067 
    2068     /* Tear down all host output streams. */
     2003
     2004    /* First, disable all streams. */
     2005    drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_DISABLE);
     2006
     2007    int rc2;
     2008
    20692009    PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
    20702010    while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    20712011    {
    2072         drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    2073         pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut);
    2074     }
    2075 
    2076     /* Tear down all host input streams. */
     2012        if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     2013        {
     2014            rc2 = pThis->pHostDrvAudio->pfnFiniOut
     2015                ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS;
     2016            if (RT_SUCCESS(rc2))
     2017                pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     2018        }
     2019        else
     2020            rc2 = VINF_SUCCESS;
     2021
     2022        AssertMsgRC(rc2, ("Host output stream %p failed to uninit: %Rrc\n",  pHstStrmOut, rc2));
     2023    }
     2024
    20772025    PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    2078     while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn)))
    2079     {
    2080         drvAudioControlHstIn(pThis, pHstStrmIn, PDMAUDIOSTREAMCMD_DISABLE);
    2081         pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn);
    2082     }
    2083 
     2026    while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
     2027    {
     2028        if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     2029        {
     2030            rc2 = pThis->pHostDrvAudio->pfnFiniIn
     2031                ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS;
     2032            if (RT_SUCCESS(rc2))
     2033                pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     2034        }
     2035        else
     2036            rc2 = VINF_SUCCESS;
     2037
     2038        AssertMsgRC(rc2, ("Host input stream %p failed to uninit: %Rrc\n",  pHstStrmIn, rc2));
     2039    }
     2040
     2041    /*
     2042     * Last call for the driver below us.
     2043     * Let it know that we reached end of life.
     2044     */
    20842045    if (pThis->pHostDrvAudio->pfnShutdown)
    20852046        pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
    20862047
    2087 #ifdef VBOX_WITH_AUDIO_CALLBACKS
    2088     PPDMAUDIOCALLBACK pCB, pCBNext;
    2089     RTListForEachSafe(&pThis->lstCBIn, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
    2090         drvAudioCallbackDestroy(pCB);
    2091 
    2092     RTListForEachSafe(&pThis->lstCBOut, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
    2093         drvAudioCallbackDestroy(pCB);
    2094 #endif
     2048    pThis->pHostDrvAudio = NULL;
    20952049
    20962050    LogFlowFuncLeave();
     
    21172071    /* IAudioConnector. */
    21182072    pThis->IAudioConnector.pfnQueryStatus            = drvAudioQueryStatus;
     2073    pThis->IAudioConnector.pfnAddRefIn               = drvAudioAddRefIn;
     2074    pThis->IAudioConnector.pfnAddRefOut              = drvAudioAddRefOut;
     2075    pThis->IAudioConnector.pfnReleaseIn              = drvAudioReleaseIn;
     2076    pThis->IAudioConnector.pfnReleaseOut             = drvAudioReleaseOut;
    21192077    pThis->IAudioConnector.pfnRead                   = drvAudioRead;
    21202078    pThis->IAudioConnector.pfnWrite                  = drvAudioWrite;
    2121     pThis->IAudioConnector.pfnGetConfiguration       = drvAudioGetConfiguration;
     2079    pThis->IAudioConnector.pfnGetConfig              = drvAudioGetConfig;
    21222080    pThis->IAudioConnector.pfnIsActiveIn             = drvAudioIsActiveIn;
    21232081    pThis->IAudioConnector.pfnIsActiveOut            = drvAudioIsActiveOut;
     
    21792137    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
    21802138
    2181     if (RTCritSectIsInitialized(&pThis->CritSect))
    2182     {
    2183         int rc2 = RTCritSectDelete(&pThis->CritSect);
     2139    int rc2 = RTCritSectEnter(&pThis->CritSect);
     2140    AssertRC(rc2);
     2141
     2142    /*
     2143     * Note: No calls here to the driver below us anymore,
     2144     *       as PDM already has destroyed it.
     2145     *       If you need to call something from the host driver,
     2146     *       do this in drvAudioPowerOff() instead.
     2147     */
     2148
     2149    /*
     2150     * Destroy all host input streams.
     2151     */
     2152    PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
     2153    while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
     2154    {
     2155        rc2 = drvAudioDestroyHstOut(pThis, pHstStrmOut);
    21842156        AssertRC(rc2);
    2185     }
     2157
     2158        /* Sanity. */
     2159        Assert(RTListIsEmpty(&pHstStrmOut->lstGstStrmOut));
     2160
     2161        pHstStrmOut = NULL;
     2162    }
     2163
     2164    /*
     2165     * Destroy all host input streams.
     2166     */
     2167    PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
     2168    while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
     2169    {
     2170        rc2 = drvAudioDestroyHstIn(pThis, pHstStrmIn);
     2171        AssertRC(rc2);
     2172
     2173        /* Sanity. */
     2174        Assert(pHstStrmIn->pGstStrmIn == NULL);
     2175
     2176        pHstStrmIn = NULL;
     2177    }
     2178
     2179    /* Sanity. */
     2180    Assert(RTListIsEmpty(&pThis->lstHstStrmIn));
     2181    Assert(RTListIsEmpty(&pThis->lstHstStrmOut));
     2182
     2183#ifdef VBOX_WITH_AUDIO_CALLBACKS
     2184    /*
     2185     * Destroy callbacks, if any.
     2186     */
     2187    PPDMAUDIOCALLBACK pCB, pCBNext;
     2188    RTListForEachSafe(&pThis->lstCBIn, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
     2189        drvAudioCallbackDestroy(pCB);
     2190
     2191    RTListForEachSafe(&pThis->lstCBOut, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
     2192        drvAudioCallbackDestroy(pCB);
     2193#endif
     2194
     2195    rc2 = RTCritSectLeave(&pThis->CritSect);
     2196    AssertRC(rc2);
     2197
     2198    rc2 = RTCritSectDelete(&pThis->CritSect);
     2199    AssertRC(rc2);
     2200
     2201    LogFlowFuncLeave();
    21862202}
    21872203
     
    22562272    PDM_DRVREG_VERSION
    22572273};
     2274
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r60353 r60925  
    113113    ( (PDRVAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIO, IAudioConnector)) )
    114114
    115 //const char *drvAudioHlpFormatToString(PDMAUDIOFMT fmt);
    116 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource);
    117 PDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat);
    118 
    119 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS info, PPDMAUDIOSTREAMCFG pCfg);
    120 void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg);
    121 
    122 /* AUDIO IN function declarations. */
    123 void drvAudioHlpPcmSwFreeResourcesIn(PPDMAUDIOGSTSTRMIN pGstStrmIn);
    124 void drvAudioGstInFreeRes(PPDMAUDIOGSTSTRMIN pGstStrmIn);
    125 void drvAudioGstInRemove(PPDMAUDIOGSTSTRMIN pGstStrmIn);
    126 uint32_t drvAudioHstInFindMinCaptured(PPDMAUDIOHSTSTRMIN pHstStrmIn);
    127 void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn);
    128 uint32_t drvAudioHstInGetFree(PPDMAUDIOHSTSTRMIN pHstStrmIn);
    129 uint32_t drvAudioHstInGetLive(PPDMAUDIOHSTSTRMIN pHstStrmIn);
    130 void drvAudioGstInRemove(PPDMAUDIOGSTSTRMIN pGstStrmIn);
    131 int  drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, const char *pszName, PPDMAUDIOSTREAMCFG pCfg);
    132 
    133 PPDMAUDIOHSTSTRMIN drvAudioFindNextHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    134 PPDMAUDIOHSTSTRMIN drvAudioFindNextEnabledHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    135 PPDMAUDIOHSTSTRMIN drvAudioFindNextEqHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg);
    136 
    137 /* AUDIO OUT function declarations. */
    138 int  drvAudioGstOutAlloc(PPDMAUDIOGSTSTRMOUT pGstStrmOut);
    139 void drvAudioGstOutFreeRes(PPDMAUDIOGSTSTRMOUT pGstStrmOut);
    140 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    141 int  drvAudioDestroyGstOut(PDRVAUDIO pDrvAudio, PPDMAUDIOGSTSTRMOUT pGstStrmOut);
    142 void drvAudioDestroyHstOut(PDRVAUDIO pDrvAudio, PDMAUDIOHSTSTRMOUT pHstStrmOut);
    143 int  drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHstStrmOut, const char *pszName, PPDMAUDIOSTREAMCFG pCfg);
    144 
    145 PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    146 PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    147 PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg);
    148 int drvAudioAllocHstOut(PDRVAUDIO pDrvAudio, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut);
    149 int drvAudioHlpPcmHwAddOut(PDRVAUDIO pDrvAudio, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut);
    150 int drvAudioHlpPcmCreateVoicePairOut(PDRVAUDIO pDrvAudio, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut);
    151 
    152 /* Common functions between DrvAudio and backends (host audio drivers). */
     115const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt);
    153116void DrvAudioClearBuf(PPDMPCMPROPS pPCMInfo, void *pvBuf, size_t cbBuf, uint32_t cSamples);
     117bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pPCMInfo, PPDMAUDIOSTREAMCFG pCfg);
     118const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSource);
     119void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg);
    154120int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps);
     121PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt);
    155122
    156123#endif /* DRV_AUDIO_H */
  • trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp

    r60353 r60925  
    77
    88/*
    9  * Copyright (C) 2006-2015 Oracle Corporation
     9 * Copyright (C) 2006-2016 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6161#include "AudioMixBuffer.h"
    6262
    63 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg);
    64 
    65 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource)
    66 {
    67     switch (enmRecSource)
    68     {
    69         case PDMAUDIORECSOURCE_MIC:     return "Microphone In";
    70         case PDMAUDIORECSOURCE_CD:      return "CD";
    71         case PDMAUDIORECSOURCE_VIDEO:   return "Video";
    72         case PDMAUDIORECSOURCE_AUX:     return "AUX";
    73         case PDMAUDIORECSOURCE_LINE: return "Line In";
    74         case PDMAUDIORECSOURCE_PHONE:   return "Phone";
    75         default:
    76             break;
    77     }
    78 
    79     AssertMsgFailed(("Bogus recording source %ld\n", enmRecSource));
     63/**
     64 * Clears a sample buffer by the given amount of audio samples.
     65 *
     66 * @return  IPRT status code.
     67 * @param   pPCMProps               PCM properties to use for the buffer to clear.
     68 * @param   pvBuf                   Buffer to clear.
     69 * @param   cbBuf                   Size (in bytes) of the buffer.
     70 * @param   cSamples                Number of audio samples to clear in the buffer.
     71 */
     72void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
     73{
     74    AssertPtrReturnVoid(pPCMProps);
     75    AssertPtrReturnVoid(pvBuf);
     76
     77    if (!cbBuf || !cSamples)
     78        return;
     79
     80    Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n",
     81              pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift));
     82
     83    if (pPCMProps->fSigned)
     84    {
     85        memset(pvBuf, 0, cSamples << pPCMProps->cShift);
     86    }
     87    else
     88    {
     89        switch (pPCMProps->cBits)
     90        {
     91            case 8:
     92            {
     93                memset(pvBuf, 0x80, cSamples << pPCMProps->cShift);
     94                break;
     95            }
     96
     97            case 16:
     98            {
     99                uint16_t *p = (uint16_t *)pvBuf;
     100                int shift = pPCMProps->cChannels - 1;
     101                short s = INT16_MAX;
     102
     103                if (pPCMProps->fSwapEndian)
     104                    s = RT_BSWAP_U16(s);
     105
     106                for (unsigned i = 0; i < cSamples << shift; i++)
     107                    p[i] = s;
     108
     109                break;
     110            }
     111
     112            case 32:
     113            {
     114                uint32_t *p = (uint32_t *)pvBuf;
     115                int shift = pPCMProps->cChannels - 1;
     116                int32_t s = INT32_MAX;
     117
     118                if (pPCMProps->fSwapEndian)
     119                    s = RT_BSWAP_U32(s);
     120
     121                for (unsigned i = 0; i < cSamples << shift; i++)
     122                    p[i] = s;
     123
     124                break;
     125            }
     126
     127            default:
     128            {
     129                AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits));
     130                break;
     131            }
     132        }
     133    }
     134}
     135
     136const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSrc)
     137{
     138    switch (enmRecSrc)
     139    {
     140        case PDMAUDIORECSOURCE_MIC:   return "Microphone In";
     141        case PDMAUDIORECSOURCE_CD:    return "CD";
     142        case PDMAUDIORECSOURCE_VIDEO: return "Video";
     143        case PDMAUDIORECSOURCE_AUX:   return "AUX";
     144        case PDMAUDIORECSOURCE_LINE:  return "Line In";
     145        case PDMAUDIORECSOURCE_PHONE: return "Phone";
     146        default:
     147            break;
     148    }
     149
     150    AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc));
    80151    return "Unknown";
    81152}
    82153
    83 const char *drvAudioHlpFormatToString(PDMAUDIOFMT enmFormat)
    84 {
    85     switch (enmFormat)
    86     {
    87         case AUD_FMT_U8:
     154const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt)
     155{
     156    switch (enmFmt)
     157    {
     158        case PDMAUDIOFMT_U8:
    88159            return "U8";
    89160
    90         case AUD_FMT_U16:
     161        case PDMAUDIOFMT_U16:
    91162            return "U16";
    92163
    93         case AUD_FMT_U32:
     164        case PDMAUDIOFMT_U32:
    94165            return "U32";
    95166
    96         case AUD_FMT_S8:
     167        case PDMAUDIOFMT_S8:
    97168            return "S8";
    98169
    99         case AUD_FMT_S16:
     170        case PDMAUDIOFMT_S16:
    100171            return "S16";
    101172
    102         case AUD_FMT_S32:
     173        case PDMAUDIOFMT_S32:
    103174            return "S32";
    104175
     
    107178    }
    108179
    109     AssertMsgFailed(("Bogus audio format %ld\n", enmFormat));
     180    AssertMsgFailed(("Bogus audio format %ld\n", enmFmt));
    110181    return "Invalid";
    111182}
    112183
    113 PDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat)
    114 {
    115     if (!RTStrICmp(pszFormat, "u8"))
    116         return AUD_FMT_U8;
    117     else if (!RTStrICmp(pszFormat, "u16"))
    118         return AUD_FMT_U16;
    119     else if (!RTStrICmp(pszFormat, "u32"))
    120         return AUD_FMT_U32;
    121     else if (!RTStrICmp(pszFormat, "s8"))
    122         return AUD_FMT_S8;
    123     else if (!RTStrICmp(pszFormat, "s16"))
    124         return AUD_FMT_S16;
    125     else if (!RTStrICmp(pszFormat, "s32"))
    126         return AUD_FMT_S32;
    127 
    128     AssertMsgFailed(("Bogus audio format \"%s\"\n", pszFormat));
    129     return AUD_FMT_INVALID;
    130 }
    131 
    132 /*********************************** In Stream Functions **********************************************/
    133 
    134 void drvAudioGstInFreeRes(PPDMAUDIOGSTSTRMIN pGstStrmIn)
    135 {
    136     AssertPtrReturnVoid(pGstStrmIn);
    137 
    138     if (pGstStrmIn->State.pszName)
    139     {
    140         RTStrFree(pGstStrmIn->State.pszName);
    141         pGstStrmIn->State.pszName = NULL;
    142     }
    143 
    144     AudioMixBufDestroy(&pGstStrmIn->MixBuf);
    145 }
    146 
    147 void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn)
    148 {
    149     AssertPtrReturnVoid(pHstStrmIn);
    150     AudioMixBufDestroy(&pHstStrmIn->MixBuf);
    151 }
    152 
    153 void drvAudioGstOutFreeRes(PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    154 {
    155     if (!pGstStrmOut)
    156         return;
    157 
    158     if (pGstStrmOut->State.pszName)
    159     {
    160         RTStrFree(pGstStrmOut->State.pszName);
    161         pGstStrmOut->State.pszName = NULL;
    162     }
    163 
    164     AudioMixBufDestroy(&pGstStrmOut->MixBuf);
    165 }
    166 
    167 #if 0
    168 
    169 /**
    170  * Finds the minimum number of not yet captured samples of all
    171  * attached guest input streams for a certain host input stream.
    172  *
    173  * @return  uint32_t            Minimum number of not yet captured samples.
    174  *                              UINT32_MAX if none found.
    175  * @param   pHstStrmIn          Host input stream to check for.
    176  */
    177 inline uint32_t drvAudioHstInFindMinCaptured(PPDMAUDIOHSTSTRMIN pHstStrmIn)
    178 {
    179     AssertPtrReturn(pHstStrmIn, 0);
    180     uint32_t cMinSamples = UINT32_MAX;
    181 
    182     PPDMAUDIOGSTSTRMIN pGstStrmIn;
    183     RTListForEach(&pHstStrmIn->lstGstStrmIn, pGstStrmIn, PDMAUDIOGSTSTRMIN, Node)
    184     {
    185         if (pGstStrmIn->State.fActive)
    186             cMinSamples = RT_MIN(cMinSamples, audioMixBufMixed(&pGstStrmIn->MixBuf));
    187     }
    188 
    189 #ifdef DEBUG_andy
    190     LogFlowFunc(("cMinSamples=%RU32\n", cMinSamples));
    191 #endif
    192     return cMinSamples;
    193 }
    194 
    195 uint32_t drvAudioHstInGetFree(PPDMAUDIOHSTSTRMIN pHstStrmIn)
    196 {
    197     AssertPtrReturn(pHstStrmIn, 0);
    198 
    199     return audioMixBufSize(&pHstStrmIn->MixBuf) - drvAudioHstInGetLive(pHstStrmIn);
    200 }
    201 
    202 uint32_t drvAudioHstInGetLive(PPDMAUDIOHSTSTRMIN pHstStrmIn)
    203 {
    204     AssertPtrReturn(pHstStrmIn, 0);
    205 
    206     uint32_t cMinSamplesCaptured = drvAudioHstInFindMinCaptured(pHstStrmIn);
    207     uint32_t cSamplesCaptured = audioMixBufMixed(&pHstStrmIn->MixBuf);
    208 
    209     Assert(cSamplesCaptured >= cMinSamplesCaptured);
    210     uint32_t cSamplesLive = cSamplesCaptured - cMinSamplesCaptured;
    211     Assert(cSamplesLive <= audioMixBufSize(&pHstStrmIn->MixBuf));
    212 
    213 #ifdef DEBUG_andy
    214     LogFlowFunc(("cSamplesLive=%RU32\n", cSamplesLive));
    215 #endif
    216     return cSamplesLive;
    217 }
    218 #endif
    219 
    220 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    221 {
    222     AssertPtrReturnVoid(pHstStrmOut);
    223     AudioMixBufDestroy(&pHstStrmOut->MixBuf);
    224 }
    225 
    226 #if 0
    227 /**
    228  * Returns the number of live sample data (in bytes) of a certain
    229  * guest input stream.
    230  *
    231  * @return  uint32_t            Live sample data (in bytes), 0 if none.
    232  * @param   pGstStrmIn          Guest input stream to check for.
    233  */
    234 uint32_t drvAudioGstInGetLiveBytes(PPDMAUDIOGSTSTRMIN pGstStrmIn)
    235 {
    236     AssertPtrReturn(pGstStrmIn, 0);
    237     AssertPtrReturn(pGstStrmIn->pHstStrmIn, 0);
    238 
    239     Assert(pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured >= pGstStrmIn->cTotalHostSamplesRead);
    240     uint32_t cSamplesLive = pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured - pGstStrmIn->cTotalHostSamplesRead;
    241     if (!cSamplesLive)
    242         return 0;
    243     Assert(cSamplesLive <= pGstStrmIn->pHstStrmIn->cSamples);
    244 
    245     /** @todo Document / refactor this! */
    246     return (((int64_t) cSamplesLive << 32) / pGstStrmIn->State.uFreqRatio) << pGstStrmIn->Props.cShift;
    247 }
    248 
    249 
    250 /**
    251  * Returns the total number of unused sample data (in bytes) of a certain
    252  * guest output stream.
    253  *
    254  * @return  uint32_t            Number of unused sample data (in bytes), 0 if all used up.
    255  * @param   pGstStrmOut         Guest output stream to check for.
    256  */
    257 uint32_t drvAudioGstOutGetFreeBytes(PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    258 {
    259     AssertPtrReturn(pGstStrmOut, 0);
    260 
    261     Assert(pGstStrmOut->cTotalSamplesWritten <= pGstStrmOut->pHstStrmOut->cSamples);
    262     uint32_t cSamplesFree =   pGstStrmOut->pHstStrmOut->cSamples
    263                             - pGstStrmOut->cTotalSamplesWritten;
    264     if (!cSamplesFree)
    265         return 0;
    266 
    267     /** @todo Document / refactor this! */
    268     return (((int64_t) cSamplesFree << 32) / pGstStrmOut->State.uFreqRatio) << pGstStrmOut->Props.cShift;
    269 }
    270 #endif
    271 
    272 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
     184PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt)
     185{
     186    AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID);
     187
     188    if (!RTStrICmp(pszFmt, "u8"))
     189        return PDMAUDIOFMT_U8;
     190    else if (!RTStrICmp(pszFmt, "u16"))
     191        return PDMAUDIOFMT_U16;
     192    else if (!RTStrICmp(pszFmt, "u32"))
     193        return PDMAUDIOFMT_U32;
     194    else if (!RTStrICmp(pszFmt, "s8"))
     195        return PDMAUDIOFMT_S8;
     196    else if (!RTStrICmp(pszFmt, "s16"))
     197        return PDMAUDIOFMT_S16;
     198    else if (!RTStrICmp(pszFmt, "s32"))
     199        return PDMAUDIOFMT_S32;
     200
     201    AssertMsgFailed(("Invalid audio format \"%s\"\n", pszFmt));
     202    return PDMAUDIOFMT_INVALID;
     203}
     204
     205bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
    273206{
    274207    int cBits = 8;
     
    277210    switch (pCfg->enmFormat)
    278211    {
    279         case AUD_FMT_S8:
    280             fSigned = true;
    281         case AUD_FMT_U8:
    282             break;
    283 
    284         case AUD_FMT_S16:
    285             fSigned = true;
    286         case AUD_FMT_U16:
     212        case PDMAUDIOFMT_S8:
     213            fSigned = true;
     214        case PDMAUDIOFMT_U8:
     215            break;
     216
     217        case PDMAUDIOFMT_S16:
     218            fSigned = true;
     219        case PDMAUDIOFMT_U16:
    287220            cBits = 16;
    288221            break;
    289222
    290         case AUD_FMT_S32:
    291             fSigned = true;
    292         case AUD_FMT_U32:
     223        case PDMAUDIOFMT_S32:
     224            fSigned = true;
     225        case PDMAUDIOFMT_U32:
    293226            cBits = 32;
    294227            break;
     
    304237                  && pProps->cBits       == cBits
    305238                  && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
    306 
    307     LogFlowFunc(("fEqual=%RTbool\n", fEqual));
    308239    return fEqual;
    309240}
     
    328259    switch (pCfg->enmFormat)
    329260    {
    330         case AUD_FMT_S8:
    331             fSigned = true;
    332         case AUD_FMT_U8:
    333             break;
    334 
    335         case AUD_FMT_S16:
    336             fSigned = true;
    337         case AUD_FMT_U16:
     261        case PDMAUDIOFMT_S8:
     262            fSigned = true;
     263        case PDMAUDIOFMT_U8:
     264            break;
     265
     266        case PDMAUDIOFMT_S16:
     267            fSigned = true;
     268        case PDMAUDIOFMT_U16:
    338269            cBits = 16;
    339270            cShift = 1;
    340271            break;
    341272
    342         case AUD_FMT_S32:
    343             fSigned = true;
    344         case AUD_FMT_U32:
     273        case PDMAUDIOFMT_S32:
     274            fSigned = true;
     275        case PDMAUDIOFMT_U32:
    345276            cBits = 32;
    346277            cShift = 2;
     
    368299}
    369300
    370 void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
    371 {
    372     LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=",
    373                  pCfg->uHz, pCfg->cChannels));
     301void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
     302{
     303    AssertPtrReturnVoid(pCfg);
     304
     305    LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", pCfg->uHz, pCfg->cChannels));
    374306
    375307    switch (pCfg->enmFormat)
    376308    {
    377         case AUD_FMT_S8:
     309        case PDMAUDIOFMT_S8:
    378310            LogFlow(("S8"));
    379311            break;
    380         case AUD_FMT_U8:
     312        case PDMAUDIOFMT_U8:
    381313            LogFlow(("U8"));
    382314            break;
    383         case AUD_FMT_S16:
     315        case PDMAUDIOFMT_S16:
    384316            LogFlow(("S16"));
    385317            break;
    386         case AUD_FMT_U16:
     318        case PDMAUDIOFMT_U16:
    387319            LogFlow(("U16"));
    388320            break;
    389         case AUD_FMT_S32:
     321        case PDMAUDIOFMT_S32:
    390322            LogFlow(("S32"));
    391323            break;
    392         case AUD_FMT_U32:
     324        case PDMAUDIOFMT_U32:
    393325            LogFlow(("U32"));
    394326            break;
     
    412344    }
    413345}
     346
  • trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp

    r59989 r60925  
    181181    switch (fmt)
    182182    {
    183         case AUD_FMT_S8:
     183        case PDMAUDIOFMT_S8:
    184184            return SND_PCM_FORMAT_S8;
    185185
    186         case AUD_FMT_U8:
     186        case PDMAUDIOFMT_U8:
    187187            return SND_PCM_FORMAT_U8;
    188188
    189         case AUD_FMT_S16:
     189        case PDMAUDIOFMT_S16:
    190190            return SND_PCM_FORMAT_S16_LE;
    191191
    192         case AUD_FMT_U16:
     192        case PDMAUDIOFMT_U16:
    193193            return SND_PCM_FORMAT_U16_LE;
    194194
    195         case AUD_FMT_S32:
     195        case PDMAUDIOFMT_S32:
    196196            return SND_PCM_FORMAT_S32_LE;
    197197
    198         case AUD_FMT_U32:
     198        case PDMAUDIOFMT_U32:
    199199            return SND_PCM_FORMAT_U32_LE;
    200200
     
    216216    {
    217217        case SND_PCM_FORMAT_S8:
    218             *pFmt = AUD_FMT_S8;
     218            *pFmt = PDMAUDIOFMT_S8;
    219219            if (pEndianness)
    220220                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    222222
    223223        case SND_PCM_FORMAT_U8:
    224             *pFmt = AUD_FMT_U8;
     224            *pFmt = PDMAUDIOFMT_U8;
    225225            if (pEndianness)
    226226                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    228228
    229229        case SND_PCM_FORMAT_S16_LE:
    230             *pFmt = AUD_FMT_S16;
     230            *pFmt = PDMAUDIOFMT_S16;
    231231            if (pEndianness)
    232232                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    234234
    235235        case SND_PCM_FORMAT_U16_LE:
    236             *pFmt = AUD_FMT_U16;
     236            *pFmt = PDMAUDIOFMT_U16;
    237237            if (pEndianness)
    238238                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    240240
    241241        case SND_PCM_FORMAT_S16_BE:
    242             *pFmt = AUD_FMT_S16;
     242            *pFmt = PDMAUDIOFMT_S16;
    243243            if (pEndianness)
    244244                *pEndianness = PDMAUDIOENDIANNESS_BIG;
     
    246246
    247247        case SND_PCM_FORMAT_U16_BE:
    248             *pFmt = AUD_FMT_U16;
     248            *pFmt = PDMAUDIOFMT_U16;
    249249            if (pEndianness)
    250250                *pEndianness = PDMAUDIOENDIANNESS_BIG;
     
    252252
    253253        case SND_PCM_FORMAT_S32_LE:
    254             *pFmt = AUD_FMT_S32;
     254            *pFmt = PDMAUDIOFMT_S32;
    255255            if (pEndianness)
    256256                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    258258
    259259        case SND_PCM_FORMAT_U32_LE:
    260             *pFmt = AUD_FMT_U32;
     260            *pFmt = PDMAUDIOFMT_U32;
    261261            if (pEndianness)
    262262                *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
     
    264264
    265265        case SND_PCM_FORMAT_S32_BE:
    266             *pFmt = AUD_FMT_S32;
     266            *pFmt = PDMAUDIOFMT_S32;
    267267            if (pEndianness)
    268268                *pEndianness = PDMAUDIOENDIANNESS_BIG;
     
    270270
    271271        case SND_PCM_FORMAT_U32_BE:
    272             *pFmt = AUD_FMT_U32;
     272            *pFmt = PDMAUDIOFMT_U32;
    273273            if (pEndianness)
    274274                *pEndianness = PDMAUDIOENDIANNESS_BIG;
     
    11091109
    11101110        ALSAAUDIOSTREAMCFG obt;
    1111         rc = alsaStreamOpen(false /* false */, &req, &obt, &phPCM);
     1111        rc = alsaStreamOpen(false /* fIn */, &req, &obt, &phPCM);
    11121112        if (RT_FAILURE(rc))
    11131113            break;
     
    13651365        LogRel2(("ALSA: Error enumerating PCM devices: %Rrc (%d)\n", RTErrConvertFromErrno(err), err));
    13661366
    1367     /* ALSA only allows one input and one output used at a time for
    1368      * the selected device(s). */
    1369     pCfg->cMaxStreamsIn   = 1;
    1370     pCfg->cMaxStreamsOut  = 1;
     1367    /* ALSA allows exactly one input and one output used at a time for the selected device(s). */
     1368    pCfg->cMaxStreamsIn  = 1;
     1369    pCfg->cMaxStreamsOut = 1;
    13711370
    13721371    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r60353 r60925  
    221221    switch (pCfg->enmFormat)
    222222    {
    223         case AUD_FMT_S8:
    224         case AUD_FMT_U8:
     223        case PDMAUDIOFMT_S8:
     224        case PDMAUDIOFMT_U8:
    225225            pFmt->wBitsPerSample = 8;
    226226            break;
    227227
    228         case AUD_FMT_S16:
    229         case AUD_FMT_U16:
     228        case PDMAUDIOFMT_S16:
     229        case PDMAUDIOFMT_U16:
    230230            pFmt->wBitsPerSample = 16;
    231231            pFmt->nAvgBytesPerSec <<= 1;
     
    233233            break;
    234234
    235         case AUD_FMT_S32:
    236         case AUD_FMT_U32:
     235        case PDMAUDIOFMT_S32:
     236        case PDMAUDIOFMT_U32:
    237237            pFmt->wBitsPerSample = 32;
    238238            pFmt->nAvgBytesPerSec <<= 2;
     
    916916        {
    917917            DSLOG(("DSound: Guest \"%s\" is using host \"%s\"\n",
    918                    drvAudioRecSourceToString(pDSoundStrmIn->enmRecSource), pDev->pszName));
     918                   DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pDev->pszName));
    919919
    920920            pGUID = &pDev->Guid;
     
    925925    /* This always has to be in the release log. */
    926926    LogRel(("DSound: Guest \"%s\" is using host device with GUID: %s\n",
    927             drvAudioRecSourceToString(pDSoundStrmIn->enmRecSource), pszGUID? pszGUID: "{?}"));
     927            DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pszGUID? pszGUID: "{?}"));
    928928    RTStrFree(pszGUID);
    929929
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r59987 r60925  
    104104    NOREF(pInterface);
    105105
     106    LogFlowFuncLeaveRC(VINF_SUCCESS);
    106107    return VINF_SUCCESS;
    107108}
     
    123124    }
    124125
    125     return VINF_SUCCESS;
     126    LogFlowFuncLeaveRC(rc);
     127    return rc;
    126128}
    127129
     
    146148        }
    147149        else
    148         {
    149150            rc = VERR_NO_MEMORY;
    150         }
    151151    }
    152152
     153    LogFlowFuncLeaveRC(rc);
    153154    return rc;
    154155}
     
    231232static DECLCALLBACK(int) drvHostNullAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    232233{
     234    LogFlowFuncLeaveRC(VINF_SUCCESS);
    233235    return VINF_SUCCESS;
    234236}
     
    236238static DECLCALLBACK(int) drvHostNullAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    237239{
     240    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
     241
    238242    PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;
    239243    if (   pNullStrmOut
     
    241245    {
    242246        RTMemFree(pNullStrmOut->pu8PlayBuffer);
     247        pNullStrmOut->pu8PlayBuffer = NULL;
    243248    }
     249
     250    LogFlowFuncLeaveRC(VINF_SUCCESS);
    244251    return VINF_SUCCESS;
    245252}
  • trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp

    r59992 r60925  
    155155    switch (fmt)
    156156    {
    157         case AUD_FMT_S8:
     157        case PDMAUDIOFMT_S8:
    158158            return AFMT_S8;
    159159
    160         case AUD_FMT_U8:
     160        case PDMAUDIOFMT_U8:
    161161            return AFMT_U8;
    162162
    163         case AUD_FMT_S16:
     163        case PDMAUDIOFMT_S16:
    164164            return AFMT_S16_LE;
    165165
    166         case AUD_FMT_U16:
     166        case PDMAUDIOFMT_U16:
    167167            return AFMT_U16_LE;
    168168
     
    180180    {
    181181        case AFMT_S8:
    182             *pFmt = AUD_FMT_S8;
     182            *pFmt = PDMAUDIOFMT_S8;
    183183            if (pENDIANNESS)
    184184                *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE;
     
    186186
    187187        case AFMT_U8:
    188             *pFmt = AUD_FMT_U8;
     188            *pFmt = PDMAUDIOFMT_U8;
    189189            if (pENDIANNESS)
    190190                *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE;
     
    192192
    193193        case AFMT_S16_LE:
    194             *pFmt = AUD_FMT_S16;
     194            *pFmt = PDMAUDIOFMT_S16;
    195195            if (pENDIANNESS)
    196196                *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE;
     
    198198
    199199        case AFMT_U16_LE:
    200             *pFmt = AUD_FMT_U16;
     200            *pFmt = PDMAUDIOFMT_U16;
    201201            if (pENDIANNESS)
    202202                *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE;
     
    204204
    205205        case AFMT_S16_BE:
    206             *pFmt = AUD_FMT_S16;
     206            *pFmt = PDMAUDIOFMT_S16;
    207207            if (pENDIANNESS)
    208208                *pENDIANNESS = PDMAUDIOENDIANNESS_BIG;
     
    210210
    211211        case AFMT_U16_BE:
    212             *pFmt = AUD_FMT_U16;
     212            *pFmt = PDMAUDIOFMT_U16;
    213213            if (pENDIANNESS)
    214214                *pENDIANNESS = PDMAUDIOENDIANNESS_BIG;
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r59989 r60925  
    182182    switch (fmt)
    183183    {
    184         case AUD_FMT_U8:
     184        case PDMAUDIOFMT_U8:
    185185            return PA_SAMPLE_U8;
    186186
    187         case AUD_FMT_S16:
     187        case PDMAUDIOFMT_S16:
    188188            return PA_SAMPLE_S16LE;
    189189
    190190#ifdef PA_SAMPLE_S32LE
    191         case AUD_FMT_S32:
     191        case PDMAUDIOFMT_S32:
    192192            return PA_SAMPLE_S32LE;
    193193#endif
     
    206206    {
    207207        case PA_SAMPLE_U8:
    208             *pFmt = AUD_FMT_U8;
     208            *pFmt = PDMAUDIOFMT_U8;
    209209            *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
    210210            break;
    211211
    212212        case PA_SAMPLE_S16LE:
    213             *pFmt = AUD_FMT_S16;
     213            *pFmt = PDMAUDIOFMT_S16;
    214214            *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
    215215            break;
    216216
    217217        case PA_SAMPLE_S16BE:
    218             *pFmt = AUD_FMT_S16;
     218            *pFmt = PDMAUDIOFMT_S16;
    219219            *pEndianness = PDMAUDIOENDIANNESS_BIG;
    220220            break;
     
    222222#ifdef PA_SAMPLE_S32LE
    223223        case PA_SAMPLE_S32LE:
    224             *pFmt = AUD_FMT_S32;
     224            *pFmt = PDMAUDIOFMT_S32;
    225225            *pEndianness = PDMAUDIOENDIANNESS_LITTLE;
    226226            break;
     
    229229#ifdef PA_SAMPLE_S32BE
    230230        case PA_SAMPLE_S32BE:
    231             *pFmt = AUD_FMT_S32;
     231            *pFmt = PDMAUDIOFMT_S32;
    232232            *pEndianness = PDMAUDIOENDIANNESS_BIG;
    233233            break;
     
    899899    if (!cLive)
    900900    {
    901         LogFlowFunc(("%p: No live samples, skipping\n", pHstStrmOut));
    902 
     901#if 0
     902        LogFlowFunc(("No live samples, skipping\n"));
     903#endif
    903904        if (pcSamplesPlayed)
    904905            *pcSamplesPlayed = 0;
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r60354 r60925  
    4848        44100,                    /* Hz */
    4949        2                         /* Channels */,
    50         AUD_FMT_S16               /* Format */,
     50        PDMAUDIOFMT_S16               /* Format */,
    5151        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    5252    };
     
    150150        44100,                    /* Hz */
    151151        2                         /* Channels */,
    152         AUD_FMT_S16               /* Format */,
     152        PDMAUDIOFMT_S16               /* Format */,
    153153        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    154154    };
     
    168168        22050,                    /* Hz */
    169169        2                         /* Channels */,
    170         AUD_FMT_S16               /* Format */,
     170        PDMAUDIOFMT_S16               /* Format */,
    171171        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    172172    };
     
    186186        48000,                    /* Hz */
    187187        2                         /* Channels */,
    188         AUD_FMT_S16               /* Format */,
     188        PDMAUDIOFMT_S16               /* Format */,
    189189        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    190190    };
     
    271271        44100,                    /* Hz */
    272272        1                         /* Channels */,
    273         AUD_FMT_U8                /* Format */,
     273        PDMAUDIOFMT_U8                /* Format */,
    274274        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    275275    };
     
    295295        22050,                    /* Hz */
    296296        1                         /* Channels */,
    297         AUD_FMT_U8                /* Format */,
     297        PDMAUDIOFMT_U8                /* Format */,
    298298        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    299299    };
     
    381381        44100,                    /* Hz */
    382382        1                         /* Channels */,
    383         AUD_FMT_S16               /* Format */,
     383        PDMAUDIOFMT_S16               /* Format */,
    384384        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    385385    };
     
    398398        22050,                    /* Hz */
    399399        1                         /* Channels */,
    400         AUD_FMT_S16               /* Format */,
     400        PDMAUDIOFMT_S16               /* Format */,
    401401        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    402402    };
     
    485485        44100,                    /* Hz */
    486486        2                         /* Channels */,
    487         AUD_FMT_S16               /* Format */,
     487        PDMAUDIOFMT_S16               /* Format */,
    488488        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    489489    };
  • trunk/src/VBox/Devices/Makefile.kmk

    r60693 r60925  
    540540 # --- Audio bits. ---
    541541
     542 if 0
     543  VBoxDD_DEFS += VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
     544  VBoxDD_DEFS += VBOX_WITH_HDA_51_SURROUND
     545 endif
     546
    542547 VBoxDD_SOURCES         += \
    543548   Audio/AudioMixBuffer.cpp \
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r60804 r60925  
    19231923    GEN_CHECK_OFF(AC97DRIVER, Out);
    19241924
    1925     GEN_CHECK_SIZE(HDAINPUTSTREAM);
    1926     GEN_CHECK_OFF(HDAINPUTSTREAM, pGstStrm);
    1927     GEN_CHECK_OFF(HDAINPUTSTREAM, pMixStrm);
    1928 
    1929     GEN_CHECK_SIZE(HDAOUTPUTSTREAM);
    1930     GEN_CHECK_OFF(HDAOUTPUTSTREAM, pGstStrm);
    1931     GEN_CHECK_OFF(HDAOUTPUTSTREAM, pMixStrm);
     1925    GEN_CHECK_SIZE(HDAMIXERSTREAM);
     1926    GEN_CHECK_OFF(HDAMIXERSTREAM, DestSource);
     1927    GEN_CHECK_OFF(HDAMIXERSTREAM, pMixStrm);
    19321928
    19331929    GEN_CHECK_SIZE(HDADRIVER);
     
    19431939#endif
    19441940    GEN_CHECK_OFF(HDADRIVER, Front);
     1941#ifdef VBOX_WITH_HDA_51_SURROUND
     1942    GEN_CHECK_OFF(HDADRIVER, CenterLFE);
     1943    GEN_CHECK_OFF(HDADRIVER, Rear);
     1944#endif
    19451945
    19461946    GEN_CHECK_SIZE(HDABDLESTATE);
     
    20152015    GEN_CHECK_OFF(HDASTATE, u64BaseTS);
    20162016    GEN_CHECK_OFF(HDASTATE, u8RespIntCnt);
    2017 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT
    2018     GEN_CHECK_OFF(HDASTATE, pCircBuf);
    2019 #endif
    20202017
    20212018#ifdef VBOX_WITH_NVME_IMPL
  • trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp

    r59987 r60925  
    139139    switch (as->enmFormat)
    140140    {
    141         case AUD_FMT_S8:
     141        case PDMAUDIOFMT_S8:
    142142            fSigned = 1;
    143         case AUD_FMT_U8:
     143        case PDMAUDIOFMT_U8:
    144144            break;
    145145
    146         case AUD_FMT_S16:
     146        case PDMAUDIOFMT_S16:
    147147            fSigned = 1;
    148         case AUD_FMT_U16:
     148        case PDMAUDIOFMT_U16:
    149149            cBits = 16;
    150150            cShift = 1;
    151151            break;
    152152
    153         case AUD_FMT_S32:
     153        case PDMAUDIOFMT_S32:
    154154            fSigned = 1;
    155         case AUD_FMT_U32:
     155        case PDMAUDIOFMT_U32:
    156156            cBits = 32;
    157157            cShift = 2;
Note: See TracChangeset for help on using the changeset viewer.

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