VirtualBox

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


Ignore:
Timestamp:
Mar 11, 2016 12:03:37 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
105954
Message:

Audio: Decoupled backend sinks and sources from the maximum of concurrent streams a backend can handle. Also, added some more enumeration code to the ALSA, PulseAudio and OSS backends, which later also can be used for configuration change callbacks. Some function renaming.

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

Legend:

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

    r59470 r59987  
    642642            pStrmIn = &pDrv->LineIn;
    643643
    644         rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);
     644        int rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);
    645645
    646646        LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
    647         if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
     647        if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
    648648        {
    649649            AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn);
    650             rc = AudioMixerAddStreamIn(pSink,
    651                                        pDrv->pConnector, pStrmIn->pStrmIn,
    652                                        0 /* uFlags */, &pStrmIn->phStrmIn);
     650            rc2 = AudioMixerAddStreamIn(pSink,
     651                                        pDrv->pConnector, pStrmIn->pStrmIn,
     652                                        0 /* uFlags */, &pStrmIn->phStrmIn);
    653653        }
    654654
     
    25342534            AssertPtr(pCon);
    25352535
    2536             bool fValidLineIn = pCon->pfnIsValidIn(pCon, pDrv->LineIn.pStrmIn);
     2536            bool fValidLineIn = pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn);
    25372537            bool fValidMicIn  = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn);
    25382538            bool fValidOut    = pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut);
     
    25592559                if (RT_SUCCESS(rc2))
    25602560                {
    2561                     if (backendCfg.cMaxHstStrmsIn)
     2561                    if (backendCfg.cSources)
    25622562                    {
    25632563                        /* If the audio backend supports two or more input streams at once,
    25642564                         * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
    2565                         if (backendCfg.cMaxHstStrmsIn >= 2)
     2565                        if (backendCfg.cMaxStreamsIn >= 2)
    25662566                            fWarn = !fValidLineIn || !fValidMicIn;
    25672567                        /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
    25682568                         * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
    25692569                         * One of the two simply is not in use then. */
    2570                         else if (backendCfg.cMaxHstStrmsIn == 1)
     2570                        else if (backendCfg.cMaxStreamsIn == 1)
    25712571                            fWarn = !fValidLineIn && !fValidMicIn;
    25722572                        /* Don't warn if our backend is not able of supporting any input streams at all. */
     
    25742574
    25752575                    if (   !fWarn
    2576                         && backendCfg.cMaxHstStrmsOut)
     2576                        && backendCfg.cSinks)
    25772577                    {
    25782578                        fWarn = !fValidOut;
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r59470 r59987  
    48074807                if (RT_SUCCESS(rc2))
    48084808                {
    4809                     if (backendCfg.cMaxHstStrmsIn)
     4809                    if (backendCfg.cSources)
    48104810                    {
    48114811#ifdef VBOX_WITH_HDA_MIC_IN
    48124812                        /* If the audio backend supports two or more input streams at once,
    48134813                         * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
    4814                         if (backendCfg.cMaxHstStrmsIn >= 2)
     4814                        if (backendCfg.cMaxStreamsIn >= 2)
    48154815                            fWarn = !fValidLineIn || !fValidMicIn;
    48164816                        /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
    48174817                         * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
    48184818                         * One of the two simply is not in use then. */
    4819                         else if (backendCfg.cMaxHstStrmsIn == 1)
     4819                        else if (backendCfg.cMaxStreamsIn == 1)
    48204820                            fWarn = !fValidLineIn && !fValidMicIn;
    48214821                        /* Don't warn if our backend is not able of supporting any input streams at all. */
     
    48274827
    48284828                    if (   !fWarn
    4829                         && backendCfg.cMaxHstStrmsOut)
     4829                        && backendCfg.cSinks)
    48304830                    {
    48314831                        fWarn = !fValidOut;
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r59890 r59987  
    615615
    616616            RTMemFree(pHstStrmOut);
    617             pThis->cFreeOutputStreams++;
     617            pThis->cStreamsFreeOut++;
    618618            return VINF_SUCCESS;
    619619        }
     
    749749    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    750750
    751     if (!pThis->cFreeOutputStreams)
     751    if (!pThis->cStreamsFreeOut)
    752752    {
    753753        LogFlowFunc(("Maximum number of host output streams reached\n"));
     
    801801        {
    802802            RTListPrepend(&pThis->lstHstStrmOut, &pHstStrmOut->Node);
    803             pThis->cFreeOutputStreams--;
     803            pThis->cStreamsFreeOut--;
    804804        }
    805805
     
    10051005                              PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
    10061006{
    1007     if (!pThis->cFreeInputStreams)
     1007    if (!pThis->cStreamsFreeIn)
    10081008    {
    10091009        LogFlowFunc(("No more input streams free to use, bailing out\n"));
     
    10571057        {
    10581058            RTListPrepend(&pThis->lstHstStrmIn, &pHstStrmIn->Node);
    1059             pThis->cFreeInputStreams--;
     1059            pThis->cStreamsFreeIn--;
    10601060        }
    10611061
     
    12371237
    12381238            RTMemFree(pHstStrmIn);
    1239             pThis->cFreeInputStreams++;
     1239            pThis->cStreamsFreeIn++;
    12401240        }
    12411241    }
     
    14221422        AssertRC(rc);
    14231423
    1424         if (!pThis->BackendCfg.cMaxHstStrmsOut)
     1424        if (!pThis->BackendCfg.cMaxStreamsOut)
    14251425        {
    14261426            int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    16691669    }
    16701670
    1671     uint32_t cMaxHstStrmsOut = pThis->BackendCfg.cMaxHstStrmsOut;
    1672     size_t cbHstStrmsOut     = pThis->BackendCfg.cbStreamOut;
    1673 
    1674     if (cbHstStrmsOut)
    1675     {
    1676         pThis->cFreeOutputStreams = cMaxHstStrmsOut;
     1671    if (pThis->BackendCfg.cbStreamOut)
     1672    {
     1673        pThis->cStreamsFreeOut = pThis->BackendCfg.cMaxStreamsOut;
    16771674    }
    16781675    else
    1679         pThis->cFreeOutputStreams = 0;
    1680 
    1681     uint32_t cMaxHstStrmsIn = pThis->BackendCfg.cMaxHstStrmsIn;
    1682     size_t cbHstStrmIn      = pThis->BackendCfg.cbStreamIn;
    1683 
    1684     if (cbHstStrmIn)
     1676        pThis->cStreamsFreeOut = 0;
     1677
     1678    if (pThis->BackendCfg.cbStreamIn)
    16851679    {
    16861680        /*
     
    16891683         *  - Our HDA emulation currently has only line input (hda.pi).
    16901684         */
    1691         pThis->cFreeInputStreams = cMaxHstStrmsIn;
     1685        pThis->cStreamsFreeIn = pThis->BackendCfg.cMaxStreamsIn;
    16921686    }
    16931687    else
    1694         pThis->cFreeInputStreams = 0;
    1695 
    1696     LogFlowFunc(("cMaxHstStrmsOut=%RU32 (cb=%zu), cMaxHstStrmsIn=%RU32 (cb=%zu)\n",
    1697                  cMaxHstStrmsOut, cbHstStrmsOut, cMaxHstStrmsIn, cbHstStrmIn));
    1698 
    1699     LogFlowFunc(("cFreeInputStreams=%RU8, cFreeOutputStreams=%RU8\n",
    1700                  pThis->cFreeInputStreams, pThis->cFreeOutputStreams));
    1701 
    1702     LogRel(("Audio: Host audio backend supports %RU32 output streams and %RU32 input streams at once\n",
    1703             /* Clamp for logging. Unlimited streams are defined by UINT32_MAX. */
    1704             RT_MIN(64, cMaxHstStrmsOut), RT_MIN(64, cMaxHstStrmsIn)));
     1688        pThis->cStreamsFreeIn = 0;
     1689
     1690    LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->cStreamsFreeIn, pThis->cStreamsFreeOut));
     1691
     1692    LogRel2(("Audio: Host audio backend supports %RU32 input streams and %RU32 output streams at once\n",
     1693             /* Clamp for logging. Unlimited streams are defined by UINT32_MAX. */
     1694             RT_MIN(64, pThis->cStreamsFreeIn), RT_MIN(64, pThis->cStreamsFreeOut)));
    17051695
    17061696    LogFlowFuncLeave();
     
    17921782        /** @todo Check for invalid options? */
    17931783
    1794         pThis->cFreeOutputStreams = conf.fixed_out.cStreams;
    1795         pThis->cFreeInputStreams  = conf.fixed_in.cStreams;
    1796 
    1797         if (!pThis->cFreeOutputStreams)
    1798             pThis->cFreeOutputStreams = 1;
    1799 
    1800         if (!pThis->cFreeInputStreams)
    1801             pThis->cFreeInputStreams = 1;
     1784        pThis->cStreamsFreeOut = conf.fixed_out.cStreams;
     1785        pThis->cStreamsFreeIn  = conf.fixed_in.cStreams;
     1786
     1787        if (!pThis->cStreamsFreeOut)
     1788            pThis->cStreamsFreeOut = 1;
     1789
     1790        if (!pThis->cStreamsFreeIn)
     1791            pThis->cStreamsFreeIn = 1;
    18021792    }
    18031793
     
    20552045            *ppGstStrmIn = pGstStrmIn;
    20562046    }
    2057     else
    2058     {
    2059         switch (rc)
    2060         {
    2061             case VERR_NO_MORE_HANDLES: /** @todo Find a better rc. */
    2062                 LogRel(("Audio: Skipping to create input stream \"%s\", " \
    2063                         "as the host audio backend reached its maximum of concurrent audio input streams\n", pszName));
    2064                 break;
    2065 
    2066             default:
    2067                 break;
    2068         }
    2069     }
    20702047
    20712048    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    21792156        }
    21802157#endif
    2181     }
    2182     else
    2183     {
    2184         switch (rc)
    2185         {
    2186             case VERR_NO_MORE_HANDLES: /** @todo Find a better rc. */
    2187                 LogRel(("Audio: Skipping to create output stream \"%s\", " \
    2188                         "as the host audio backend reached its maximum of concurrent audio output streams\n", pszName));
    2189                 break;
    2190 
    2191             default:
    2192                 break;
    2193         }
    21942158    }
    21952159
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r59470 r59987  
    9696    /** Max. number of free input streams.
    9797     *  UINT32_MAX for unlimited streams. */
    98     uint32_t                cFreeInputStreams;
     98    uint32_t                cStreamsFreeIn;
    9999    /** Max. number of free output streams.
    100100     *  UINT32_MAX for unlimited streams. */
    101     uint32_t                cFreeOutputStreams;
     101    uint32_t                cStreamsFreeOut;
    102102    /** Audio configuration settings retrieved from the backend. */
    103103    PDMAUDIOBACKENDCFG      BackendCfg;
  • trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp

    r59470 r59987  
    55
    66/*
    7  * Copyright (C) 2006-2015 Oracle Corporation
     7 * Copyright (C) 2006-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5757
    5858#include <alsa/asoundlib.h>
     59#include <alsa/control.h> /* For device enumeration. */
    5960
    6061#include "DrvAudio.h"
     
    6263
    6364#include "VBoxDD.h"
     65
     66/*********************************************************************************************************************************
     67*   Defines                                                                                                                      *
     68*********************************************************************************************************************************/
     69
     70/** Makes DRVHOSTALSAAUDIO out of PDMIHOSTAUDIO. */
     71#define PDMIHOSTAUDIO_2_DRVHOSTALSAAUDIO(pInterface) \
     72    ( (PDRVHOSTALSAAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTALSAAUDIO, IHostAudio)) )
     73
     74/*********************************************************************************************************************************
     75*   Structures                                                                                                                   *
     76*********************************************************************************************************************************/
    6477
    6578typedef struct ALSAAUDIOSTREAMIN
     
    101114} ALSAAUDIOCFG, *PALSAAUDIOCFG;
    102115
    103 static int drvHostALSAAudioRecover(snd_pcm_t *phPCM);
     116static int alsaStreamRecover(snd_pcm_t *phPCM);
    104117
    105118static ALSAAUDIOCFG s_ALSAConf =
     
    162175} ALSAAUDIOSTREAMCFG, *PALSAAUDIOSTREAMCFG;
    163176
    164 static int drvHostALSAAudioClose(snd_pcm_t **pphPCM)
    165 {
    166     if (!pphPCM || !*pphPCM)
    167         return VINF_SUCCESS;
    168 
    169     int rc;
    170     int rc2 = snd_pcm_close(*pphPCM);
    171     if (rc2)
    172     {
    173         LogRel(("ALSA: Closing PCM descriptor failed: %s\n", snd_strerror(rc2)));
    174         rc = VERR_GENERAL_FAILURE; /** @todo */
    175     }
    176     else
    177     {
    178         *pphPCM = NULL;
    179         rc = VINF_SUCCESS;
    180     }
    181 
    182     return rc;
    183 }
    184 
    185 static snd_pcm_format_t drvHostALSAAudioFmtToALSA(PDMAUDIOFMT fmt)
     177
     178
     179static snd_pcm_format_t alsaAudioFmtToALSA(PDMAUDIOFMT fmt)
    186180{
    187181    switch (fmt)
     
    213207}
    214208
    215 static int drvHostALSAAudioALSAToFmt(snd_pcm_format_t fmt,
    216                                      PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness)
     209static int alsaALSAToAudioFmt(snd_pcm_format_t fmt,
     210                              PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness)
    217211{
    218212    AssertPtrReturn(pFmt, VERR_INVALID_POINTER);
     
    289283}
    290284
    291 static int drvHostALSAAudioALSAGetShift(snd_pcm_format_t fmt, unsigned *puShift)
     285static int alsaGetSampleShift(snd_pcm_format_t fmt, unsigned *puShift)
    292286{
    293287    AssertPtrReturn(puShift, VERR_INVALID_POINTER);
     
    322316}
    323317
    324 static int drvHostALSAAudioSetThreshold(snd_pcm_t *phPCM,
    325                                         snd_pcm_uframes_t threshold)
     318static int alsaStreamSetThreshold(snd_pcm_t *phPCM, snd_pcm_uframes_t threshold)
    326319{
    327320    snd_pcm_sw_params_t *pSWParms = NULL;
     
    368361}
    369362
    370 static int drvHostALSAAudioOpen(bool fIn,
    371                                 PALSAAUDIOSTREAMCFG pCfgReq,
    372                                 PALSAAUDIOSTREAMCFG pCfgObt,
    373                                 snd_pcm_t **pphPCM)
     363static int alsaStreamClose(snd_pcm_t **pphPCM)
     364{
     365    if (!pphPCM || !*pphPCM)
     366        return VINF_SUCCESS;
     367
     368    int rc;
     369    int rc2 = snd_pcm_close(*pphPCM);
     370    if (rc2)
     371    {
     372        LogRel(("ALSA: Closing PCM descriptor failed: %s\n", snd_strerror(rc2)));
     373        rc = VERR_GENERAL_FAILURE; /** @todo */
     374    }
     375    else
     376    {
     377        *pphPCM = NULL;
     378        rc = VINF_SUCCESS;
     379    }
     380
     381    return rc;
     382}
     383
     384static int alsaStreamOpen(bool fIn, PALSAAUDIOSTREAMCFG pCfgReq, PALSAAUDIOSTREAMCFG pCfgObt, snd_pcm_t **pphPCM)
    374385{
    375386    snd_pcm_t *phPCM = NULL;
     
    624635        {
    625636            unsigned uShift;
    626             rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift);
     637            rc = alsaGetSampleShift(pCfgReq->fmt, &uShift);
    627638            if (RT_SUCCESS(rc))
    628639            {
     
    634645                    = (s_ALSAConf.threshold * bytes_per_sec) / 1000;
    635646
    636                 rc = drvHostALSAAudioSetThreshold(phPCM, threshold);
     647                rc = alsaStreamSetThreshold(phPCM, threshold);
    637648            }
    638649        }
     
    652663    }
    653664    else
    654         drvHostALSAAudioClose(&phPCM);
     665        alsaStreamClose(&phPCM);
    655666
    656667    LogFlowFuncLeaveRC(rc);
     
    659670
    660671#ifdef DEBUG
    661 static void drvHostALSAAudioErrorHandler(const char *file, int line, const char *function,
    662                                          int err, const char *fmt, ...)
     672static void alsaDbgErrorHandler(const char *file, int line, const char *function,
     673                                int err, const char *fmt, ...)
    663674{
    664675    /** @todo Implement me! */
     
    666677#endif
    667678
    668 static int drvHostALSAAudioGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)
     679static int alsaStreamGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)
    669680{
    670681    AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
     
    679690        if (framesAvail == -EPIPE)
    680691        {
    681             rc = drvHostALSAAudioRecover(phPCM);
     692            rc = alsaStreamRecover(phPCM);
    682693            if (RT_SUCCESS(rc))
    683694                framesAvail = snd_pcm_avail_update(phPCM);
     
    695706}
    696707
    697 static int drvHostALSAAudioRecover(snd_pcm_t *phPCM)
     708static int alsaStreamRecover(snd_pcm_t *phPCM)
    698709{
    699710    AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
     
    709720}
    710721
    711 static int drvHostALSAAudioResume(snd_pcm_t *phPCM)
     722static int alsaStreamResume(snd_pcm_t *phPCM)
    712723{
    713724    AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
     
    760771    {
    761772#ifdef DEBUG
    762         snd_lib_error_set_handler(drvHostALSAAudioErrorHandler);
     773        snd_lib_error_set_handler(alsaDbgErrorHandler);
    763774#endif
    764775    }
     
    776787
    777788    snd_pcm_sframes_t cAvail;
    778     int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail);
     789    int rc = alsaStreamGetAvail(pThisStrmIn->phPCM, &cAvail);
    779790    if (RT_FAILURE(rc))
    780791    {
     
    794805            case SND_PCM_STATE_SUSPENDED:
    795806            {
    796                 rc = drvHostALSAAudioResume(pThisStrmIn->phPCM);
     807                rc = alsaStreamResume(pThisStrmIn->phPCM);
    797808                if (RT_FAILURE(rc))
    798809                    break;
     
    860871                case -EPIPE:
    861872                {
    862                     rc = drvHostALSAAudioRecover(pThisStrmIn->phPCM);
     873                    rc = alsaStreamRecover(pThisStrmIn->phPCM);
    863874                    if (RT_FAILURE(rc))
    864875                        break;
     
    932943    {
    933944        snd_pcm_sframes_t cAvail;
    934         rc = drvHostALSAAudioGetAvail(pThisStrmOut->phPCM, &cAvail);
     945        rc = alsaStreamGetAvail(pThisStrmOut->phPCM, &cAvail);
    935946        if (RT_FAILURE(rc))
    936947        {
     
    975986                        case -EPIPE:
    976987                        {
    977                             rc = drvHostALSAAudioRecover(pThisStrmOut->phPCM);
     988                            rc = alsaStreamRecover(pThisStrmOut->phPCM);
    978989                            if (RT_FAILURE(rc))
    979990                                break;
     
    986997                        {
    987998                            /* Stream was suspended and waiting for a recovery. */
    988                             rc = drvHostALSAAudioResume(pThisStrmOut->phPCM);
     999                            rc = alsaStreamResume(pThisStrmOut->phPCM);
    9891000                            if (RT_FAILURE(rc))
    9901001                            {
     
    10461057    PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
    10471058
    1048     drvHostALSAAudioClose(&pThisStrmIn->phPCM);
     1059    alsaStreamClose(&pThisStrmIn->phPCM);
    10491060
    10501061    if (pThisStrmIn->pvBuf)
     
    10641075    PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
    10651076
    1066     drvHostALSAAudioClose(&pThisStrmOut->phPCM);
     1077    alsaStreamClose(&pThisStrmOut->phPCM);
    10671078
    10681079    if (pThisStrmOut->pvBuf)
     
    10911102    {
    10921103        ALSAAUDIOSTREAMCFG req;
    1093         req.fmt         = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
     1104        req.fmt         = alsaAudioFmtToALSA(pCfg->enmFormat);
    10941105        req.freq        = pCfg->uHz;
    10951106        req.nchannels   = pCfg->cChannels;
     
    10981109
    10991110        ALSAAUDIOSTREAMCFG obt;
    1100         rc = drvHostALSAAudioOpen(false /* false */, &req, &obt, &phPCM);
     1111        rc = alsaStreamOpen(false /* false */, &req, &obt, &phPCM);
    11011112        if (RT_FAILURE(rc))
    11021113            break;
     
    11041115        PDMAUDIOFMT enmFormat;
    11051116        PDMAUDIOENDIANNESS enmEnd;
    1106         rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
     1117        rc = alsaALSAToAudioFmt(obt.fmt, &enmFormat, &enmEnd);
    11071118        if (RT_FAILURE(rc))
    11081119            break;
     
    11391150
    11401151    if (RT_FAILURE(rc))
    1141         drvHostALSAAudioClose(&phPCM);
     1152        alsaStreamClose(&phPCM);
    11421153
    11431154    LogFlowFuncLeaveRC(rc);
     
    11621173    {
    11631174        ALSAAUDIOSTREAMCFG req;
    1164         req.fmt         = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
     1175        req.fmt         = alsaAudioFmtToALSA(pCfg->enmFormat);
    11651176        req.freq        = pCfg->uHz;
    11661177        req.nchannels   = pCfg->cChannels;
     
    11691180
    11701181        ALSAAUDIOSTREAMCFG obt;
    1171         rc = drvHostALSAAudioOpen(true /* fIn */, &req, &obt, &phPCM);
     1182        rc = alsaStreamOpen(true /* fIn */, &req, &obt, &phPCM);
    11721183        if (RT_FAILURE(rc))
    11731184            break;
     
    11751186        PDMAUDIOFMT enmFormat;
    11761187        PDMAUDIOENDIANNESS enmEnd;
    1177         rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
     1188        rc = alsaALSAToAudioFmt(obt.fmt, &enmFormat, &enmEnd);
    11781189        if (RT_FAILURE(rc))
    11791190            break;
     
    12101221
    12111222    if (RT_FAILURE(rc))
    1212         drvHostALSAAudioClose(&phPCM);
     1223        alsaStreamClose(&phPCM);
    12131224
    12141225    LogFlowFuncLeaveRC(rc);
     
    12901301    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    12911302
    1292     pCfg->cbStreamIn      = sizeof(ALSAAUDIOSTREAMIN);
    1293     pCfg->cbStreamOut     = sizeof(ALSAAUDIOSTREAMOUT);
     1303    pCfg->cbStreamIn  = sizeof(ALSAAUDIOSTREAMIN);
     1304    pCfg->cbStreamOut = sizeof(ALSAAUDIOSTREAMOUT);
     1305
     1306    pCfg->cSources    = 0;
     1307    pCfg->cSinks      = 0;
     1308
     1309    /* Enumerate sound devices. */
     1310    char **pszHints;
     1311    int err = snd_device_name_hint(-1 /* All cards */, "pcm", (void***)&pszHints);
     1312    if (err == 0)
     1313    {
     1314        char** pszHintCur = pszHints;
     1315        while (*pszHintCur != NULL)
     1316        {
     1317            char *pszDev = snd_device_name_get_hint(*pszHintCur, "NAME");
     1318            bool fSkip =    !pszDev
     1319                         || !RTStrICmp("null", pszDev);
     1320            if (fSkip)
     1321            {
     1322                if (pszDev)
     1323                    free(pszDev);
     1324                pszHintCur++;
     1325                continue;
     1326            }
     1327
     1328            char *pszIOID = snd_device_name_get_hint(*pszHintCur, "IOID");
     1329            if (pszIOID)
     1330            {
     1331                if (!RTStrICmp("input", pszIOID))
     1332                    pCfg->cSources++;
     1333                else if (!RTStrICmp("output", pszIOID))
     1334                    pCfg->cSinks++;
     1335            }
     1336            else /* NULL means bidirectional, input + output. */
     1337            {
     1338                pCfg->cSources++;
     1339                pCfg->cSinks++;
     1340            }
     1341
     1342            LogRel2(("ALSA: Found %s device: %s\n", pszIOID ?  RTStrToLower(pszIOID) : "bidirectional", pszDev));
     1343
     1344            /* Special case for PulseAudio. */
     1345            if (   pszDev
     1346                && RTStrIStr("pulse", pszDev) != NULL)
     1347                LogRel2(("ALSA: PulseAudio plugin in use\n"));
     1348
     1349            if (pszIOID)
     1350                free(pszIOID);
     1351
     1352            if (pszDev)
     1353                free(pszDev);
     1354
     1355            pszHintCur++;
     1356        }
     1357
     1358        LogRel2(("ALSA: Found %RU8 host playback devices\n",  pCfg->cSinks));
     1359        LogRel2(("ALSA: Found %RU8 host capturing devices\n", pCfg->cSources));
     1360
     1361        snd_device_name_free_hint((void **)pszHints);
     1362        pszHints = NULL;
     1363    }
     1364    else
     1365        LogRel2(("ALSA: Error enumerating PCM devices: %Rrc (%d)\n", RTErrConvertFromErrno(err), err));
    12941366
    12951367    /* ALSA only allows one input and one output used at a time for
    1296      * the selected device. */
    1297     pCfg->cMaxHstStrmsIn  = 1;
    1298     pCfg->cMaxHstStrmsOut = 1;
     1368     * the selected device(s). */
     1369    pCfg->cMaxStreamsIn   = 1;
     1370    pCfg->cMaxStreamsOut = 1;
    12991371
    13001372    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r59470 r59987  
    311311} COREAUDIOSTREAMIN, *PCOREAUDIOSTREAMIN;
    312312
     313
     314static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples);
     315static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);
     316static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples);
     317static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
     318static OSStatus coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser);
     319static OSStatus coreAudioPlaybackCb(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData);
     320
    313321static int drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd);
    314 static int drvHostCoreAudioInitInput(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples);
     322static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd);
    315323static int drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    316 static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    317 
    318 static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd);
    319 static int drvHostCoreAudioInitOutput(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples);
    320324static int drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    321 static int drvHostCoreAudioReinitOutput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    322 static OSStatus drvHostCoreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser);
    323 static OSStatus drvHostCoreAudioPlaybackCallback(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData);
    324325
    325326/* Callback for getting notified when the default input/output device has been changed. */
    326 static DECLCALLBACK(OSStatus) drvHostCoreAudioDefaultDeviceChanged(AudioObjectID propertyID,
    327                                                                    UInt32 nAddresses,
    328                                                                    const AudioObjectPropertyAddress properties[],
    329                                                                    void *pvUser)
     327static DECLCALLBACK(OSStatus) coreAudioDefaultDeviceChanged(AudioObjectID propertyID,
     328                                                            UInt32 nAddresses,
     329                                                            const AudioObjectPropertyAddress properties[],
     330                                                            void *pvUser)
    330331{
    331332    OSStatus err = noErr;
     
    397398    }
    398399
     400    /** @todo Implement callback notification here to let the audio connector / device emulation
     401     *        know that something has changed. */
     402
    399403    return noErr;
    400404}
    401405
    402 static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     406static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    403407{
    404408    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
     
    409413    drvHostCoreAudioFiniIn(pInterface, &pStreamIn->streamIn);
    410414
    411     drvHostCoreAudioInitInput(&pStreamIn->streamIn, NULL /* pcSamples */);
     415    coreAudioInitIn(&pStreamIn->streamIn, NULL /* pcSamples */);
    412416    drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_ENABLE);
    413417
     
    415419}
    416420
    417 static int drvHostCoreAudioReinitOutput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     421static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    418422{
    419423    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
     
    424428    drvHostCoreAudioFiniOut(pInterface, &pStreamOut->streamOut);
    425429
    426     drvHostCoreAudioInitOutput(&pStreamOut->streamOut, NULL /* pcSamples */);
     430    coreAudioInitOut(&pStreamOut->streamOut, NULL /* pcSamples */);
    427431    drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_ENABLE);
    428432
     
    431435
    432436/* Callback for getting notified when some of the properties of an audio device has changed. */
    433 static DECLCALLBACK(OSStatus) drvHostCoreAudioRecordingAudioDevicePropertyChanged(AudioObjectID                     propertyID,
    434                                                                                   UInt32                            cAdresses,
    435                                                                                   const AudioObjectPropertyAddress  aProperties[],
    436                                                                                   void                             *pvUser)
     437static DECLCALLBACK(OSStatus) coreAudioRecordingAudioDevicePropertyChanged(AudioObjectID                     propertyID,
     438                                                                           UInt32                            cAdresses,
     439                                                                           const AudioObjectPropertyAddress  aProperties[],
     440                                                                           void                             *pvUser)
    437441{
    438442    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser;
     
    466470
    467471/* Callback to convert audio input data from one format to another. */
    468 static DECLCALLBACK(OSStatus) drvHostCoreAudioConverterCallback(AudioConverterRef              converterID,
    469                                                                 UInt32                        *pcPackets,
    470                                                                 AudioBufferList               *pBufData,
    471                                                                 AudioStreamPacketDescription **ppPacketDesc,
    472                                                                 void                          *pvUser)
     472static DECLCALLBACK(OSStatus) coreAudioConverterCb(AudioConverterRef              converterID,
     473                                                   UInt32                        *pcPackets,
     474                                                   AudioBufferList               *pBufData,
     475                                                   AudioStreamPacketDescription **ppPacketDesc,
     476                                                   void                          *pvUser)
    473477{
    474478    /** @todo Check incoming pointers. */
     
    521525
    522526/* Callback to feed audio input buffer. */
    523 static DECLCALLBACK(OSStatus) drvHostCoreAudioRecordingCallback(void                      *pvUser,
    524                                                                 AudioUnitRenderActionFlags *pActionFlags,
    525                                                                 const AudioTimeStamp       *pAudioTS,
    526                                                                 UInt32                      uBusID,
    527                                                                 UInt32                      cFrames,
    528                                                                 AudioBufferList            *pBufData)
     527static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void *pvUser,
     528                                                   AudioUnitRenderActionFlags *pActionFlags,
     529                                                   const AudioTimeStamp       *pAudioTS,
     530                                                   UInt32                      uBusID,
     531                                                   UInt32                      cFrames,
     532                                                   AudioBufferList            *pBufData)
    529533{
    530534    PCOREAUDIOSTREAMIN pStreamIn  = (PCOREAUDIOSTREAMIN)pvUser;
     
    596600                AudioConverterReset(pStreamIn->converter);
    597601
    598                 err = AudioConverterFillComplexBuffer(pStreamIn->converter, drvHostCoreAudioConverterCallback, pStreamIn,
     602                err = AudioConverterFillComplexBuffer(pStreamIn->converter, coreAudioConverterCb, pStreamIn,
    599603                                                      &ioOutputDataPacketSize, &tmpList, NULL);
    600604                if(   err != noErr
     
    692696
    693697/** @todo Eventually split up this function, as this already is huge! */
    694 static int drvHostCoreAudioInitInput(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples)
     698static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples)
    695699{
    696700    OSStatus err = noErr;
     
    833837    AURenderCallbackStruct cb;
    834838    RT_ZERO(cb);
    835     cb.inputProc       = drvHostCoreAudioRecordingCallback;
     839    cb.inputProc       = coreAudioRecordingCb;
    836840    cb.inputProcRefCon = pStreamIn;
    837841
     
    10231027        propAdr.mScope    = kAudioUnitScope_Global;
    10241028        err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
    1025                                              drvHostCoreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
     1029                                             coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
    10261030        if (RT_UNLIKELY(err != noErr))
    10271031            LogRel(("CoreAudio: Failed to add the processor overload listener for input stream (%RI32)\n", err));
     
    10301034        propAdr.mScope    = kAudioUnitScope_Global;
    10311035        err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
    1032                                              drvHostCoreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
     1036                                             coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
    10331037        /* Not fatal. */
    10341038        if (RT_UNLIKELY(err != noErr))
     
    10591063
    10601064/** @todo Eventually split up this function, as this already is huge! */
    1061 static int drvHostCoreAudioInitOutput(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples)
     1065static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples)
    10621066{
    10631067    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     
    11881192    AURenderCallbackStruct cb;
    11891193    RT_ZERO(cb);
    1190     cb.inputProc       = drvHostCoreAudioPlaybackCallback; /* pvUser */
     1194    cb.inputProc       = coreAudioPlaybackCb; /* pvUser */
    11911195    cb.inputProcRefCon = pStreamOut;
    11921196
     
    12971301        propAdr.mScope    = kAudioUnitScope_Global;
    12981302        err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr,
    1299                                              drvHostCoreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);
     1303                                             coreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);
    13001304        if (err != noErr)
    13011305            LogRel(("CoreAudio: Failed to register processor overload listener for output stream (%RI32)\n", err));
     
    13051309        propAdr.mScope    = kAudioUnitScope_Global;
    13061310        err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr,
    1307                                              drvHostCoreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);
     1311                                             coreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);
    13081312        /* Not fatal. */
    13091313        if (err != noErr)
     
    13331337}
    13341338
     1339
     1340/* Callback for getting notified when some of the properties of an audio device has changed. */
     1341static DECLCALLBACK(OSStatus) coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID,
     1342                                                                          UInt32 nAddresses,
     1343                                                                          const AudioObjectPropertyAddress properties[],
     1344                                                                          void *pvUser)
     1345{
     1346    switch (propertyID)
     1347    {
     1348#ifdef DEBUG
     1349        case kAudioDeviceProcessorOverload:
     1350        {
     1351            Log2(("CoreAudio: [Output] Processor overload detected!\n"));
     1352            break;
     1353        }
     1354#endif /* DEBUG */
     1355        default:
     1356            break;
     1357    }
     1358
     1359    return noErr;
     1360}
     1361
     1362/* Callback to feed audio output buffer. */
     1363static DECLCALLBACK(OSStatus) coreAudioPlaybackCb(void *pvUser,
     1364                                                  AudioUnitRenderActionFlags *pActionFlags,
     1365                                                  const AudioTimeStamp       *pAudioTS,
     1366                                                  UInt32                      uBusID,
     1367                                                  UInt32                      cFrames,
     1368                                                  AudioBufferList            *pBufData)
     1369{
     1370    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;
     1371    PPDMAUDIOHSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut;
     1372
     1373    if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT)
     1374    {
     1375        pBufData->mBuffers[0].mDataByteSize = 0;
     1376        return noErr;
     1377    }
     1378
     1379    /* How much space is used in the ring buffer? */
     1380    size_t cbDataAvail = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);
     1381    if (!cbDataAvail)
     1382    {
     1383        pBufData->mBuffers[0].mDataByteSize = 0;
     1384        return noErr;
     1385    }
     1386
     1387    uint8_t *pbSrc = NULL;
     1388    size_t cbRead = 0;
     1389    size_t cbToRead;
     1390    while (cbDataAvail)
     1391    {
     1392        /* Try to acquire the necessary block from the ring buffer. */
     1393        RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbDataAvail, (void **)&pbSrc, &cbToRead);
     1394
     1395        /* Break if nothing is used anymore. */
     1396        if (!cbToRead)
     1397            break;
     1398
     1399        /* Copy the data from our ring buffer to the core audio buffer. */
     1400        memcpy((uint8_t *)pBufData->mBuffers[0].mData + cbRead, pbSrc, cbToRead);
     1401
     1402        /* Release the read buffer, so it could be used for new data. */
     1403        RTCircBufReleaseReadBlock(pStreamOut->pBuf, cbToRead);
     1404
     1405        /* Move offset. */
     1406        cbRead += cbToRead;
     1407        Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead);
     1408
     1409        Assert(cbToRead <= cbDataAvail);
     1410        cbDataAvail -= cbToRead;
     1411    }
     1412
     1413    /* Write the bytes to the core audio buffer which where really written. */
     1414    pBufData->mBuffers[0].mDataByteSize = cbRead;
     1415
     1416    LogFlowFunc(("CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail));
     1417
     1418    return noErr;
     1419}
     1420
    13351421static DECLCALLBACK(int) drvHostCoreAudioInit(PPDMIHOSTAUDIO pInterface)
    13361422{
     
    13561442    /* Check if the audio device should be reinitialized. If so do it. */
    13571443    if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT)
    1358         drvHostCoreAudioReinitInput(pInterface, &pStreamIn->streamIn);
     1444        coreAudioReinitIn(pInterface, &pStreamIn->streamIn);
    13591445
    13601446    if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
     
    14281514}
    14291515
    1430 /* Callback for getting notified when some of the properties of an audio device has changed. */
    1431 static DECLCALLBACK(OSStatus) drvHostCoreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID,
    1432                                                                                  UInt32 nAddresses,
    1433                                                                                  const AudioObjectPropertyAddress properties[],
    1434                                                                                  void *pvUser)
    1435 {
    1436     switch (propertyID)
    1437     {
    1438 #ifdef DEBUG
    1439         case kAudioDeviceProcessorOverload:
    1440         {
    1441             Log2(("CoreAudio: [Output] Processor overload detected!\n"));
    1442             break;
    1443         }
    1444 #endif /* DEBUG */
    1445         default:
    1446             break;
    1447     }
    1448 
    1449     return noErr;
    1450 }
    1451 
    1452 /* Callback to feed audio output buffer. */
    1453 static DECLCALLBACK(OSStatus) drvHostCoreAudioPlaybackCallback(void                       *pvUser,
    1454                                                                AudioUnitRenderActionFlags *pActionFlags,
    1455                                                                const AudioTimeStamp       *pAudioTS,
    1456                                                                UInt32                      uBusID,
    1457                                                                UInt32                      cFrames,
    1458                                                                AudioBufferList            *pBufData)
    1459 {
    1460     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;
    1461     PPDMAUDIOHSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut;
    1462 
    1463     if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT)
    1464     {
    1465         pBufData->mBuffers[0].mDataByteSize = 0;
    1466         return noErr;
    1467     }
    1468 
    1469     /* How much space is used in the ring buffer? */
    1470     size_t cbDataAvail = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);
    1471     if (!cbDataAvail)
    1472     {
    1473         pBufData->mBuffers[0].mDataByteSize = 0;
    1474         return noErr;
    1475     }
    1476 
    1477     uint8_t *pbSrc = NULL;
    1478     size_t cbRead = 0;
    1479     size_t cbToRead;
    1480     while (cbDataAvail)
    1481     {
    1482         /* Try to acquire the necessary block from the ring buffer. */
    1483         RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbDataAvail, (void **)&pbSrc, &cbToRead);
    1484 
    1485         /* Break if nothing is used anymore. */
    1486         if (!cbToRead)
    1487             break;
    1488 
    1489         /* Copy the data from our ring buffer to the core audio buffer. */
    1490         memcpy((uint8_t *)pBufData->mBuffers[0].mData + cbRead, pbSrc, cbToRead);
    1491 
    1492         /* Release the read buffer, so it could be used for new data. */
    1493         RTCircBufReleaseReadBlock(pStreamOut->pBuf, cbToRead);
    1494 
    1495         /* Move offset. */
    1496         cbRead += cbToRead;
    1497         Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead);
    1498 
    1499         Assert(cbToRead <= cbDataAvail);
    1500         cbDataAvail -= cbToRead;
    1501     }
    1502 
    1503     /* Write the bytes to the core audio buffer which where really written. */
    1504     pBufData->mBuffers[0].mDataByteSize = cbRead;
    1505 
    1506     LogFlowFunc(("CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail));
    1507 
    1508     return noErr;
    1509 }
    1510 
    15111516static DECLCALLBACK(int) drvHostCoreAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    15121517                                                 uint32_t *pcSamplesPlayed)
     
    15191524    /* Check if the audio device should be reinitialized. If so do it. */
    15201525    if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT)
    1521         drvHostCoreAudioReinitOutput(pInterface, &pStreamOut->streamOut);
     1526        coreAudioReinitOut(pInterface, &pStreamOut->streamOut);
    15221527
    15231528    /* Not much else to do here. */
     
    17721777#ifdef DEBUG
    17731778        err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr,
    1774                                                 drvHostCoreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
     1779                                                coreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
    17751780        /* Not Fatal */
    17761781        if (RT_UNLIKELY(err != noErr))
     
    17801785        propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
    17811786        err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr,
    1782                                                 drvHostCoreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
     1787                                                coreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
    17831788        /* Not Fatal */
    17841789        if (RT_UNLIKELY(err != noErr))
     
    17891794            propAdr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
    17901795            err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr,
    1791                                                     drvHostCoreAudioDefaultDeviceChanged, pStreamIn);
     1796                                                    coreAudioDefaultDeviceChanged, pStreamIn);
    17921797            if (RT_LIKELY(err == noErr))
    17931798            {
     
    18721877#ifdef DEBUG
    18731878        err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr,
    1874                                                 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
     1879                                                coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
    18751880        /* Not Fatal */
    18761881        if (RT_UNLIKELY(err != noErr))
     
    18801885        propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
    18811886        err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr,
    1882                                                 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
     1887                                                coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
    18831888        /* Not Fatal */
    18841889        if (RT_UNLIKELY(err != noErr))
     
    18911896            propAdr.mElement  = kAudioObjectPropertyElementMaster;
    18921897            err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr,
    1893                                                     drvHostCoreAudioDefaultDeviceChanged, pStreamOut);
     1898                                                    coreAudioDefaultDeviceChanged, pStreamOut);
    18941899            if (RT_LIKELY(err == noErr))
    18951900            {
     
    19621967        }
    19631968#endif
    1964         rc = drvHostCoreAudioInitInput(&pStreamIn->streamIn, pcSamples);
     1969        rc = coreAudioInitIn(&pStreamIn->streamIn, pcSamples);
    19651970    }
    19661971
     
    19731978                                                   kAudioObjectPropertyElementMaster };
    19741979            OSStatus err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,
    1975                                                           drvHostCoreAudioDefaultDeviceChanged, (void *)pStreamIn);
     1980                                                          coreAudioDefaultDeviceChanged, (void *)pStreamIn);
    19761981            /* Not fatal. */
    19771982            if (RT_LIKELY(err == noErr))
     
    20232028#endif
    20242029
    2025     rc = drvHostCoreAudioInitOutput(pHstStrmOut, pcSamples);
     2030    rc = coreAudioInitOut(pHstStrmOut, pcSamples);
    20262031    if (RT_FAILURE(rc))
    20272032        return rc;
     
    20332038                                               kAudioObjectPropertyElementMaster };
    20342039        err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,
    2035                                              drvHostCoreAudioDefaultDeviceChanged, (void *)pStreamOut);
     2040                                             coreAudioDefaultDeviceChanged, (void *)pStreamOut);
    20362041        /* Not fatal. */
    20372042        if (RT_LIKELY(err == noErr))
     
    20532058}
    20542059
    2055 static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pAudioConf)
    2056 {
    2057     pAudioConf->cbStreamOut     = sizeof(COREAUDIOSTREAMOUT);
    2058     pAudioConf->cbStreamIn      = sizeof(COREAUDIOSTREAMIN);
    2059     pAudioConf->cMaxHstStrmsOut = 1;
    2060     pAudioConf->cMaxHstStrmsIn  = 2;
     2060static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     2061{
     2062    NOREF(pInterface);
     2063    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     2064
     2065    LogFlowFuncEnter();
     2066
     2067    pCfg->cbStreamIn      = sizeof(COREAUDIOSTREAMIN);
     2068    pCfg->cbStreamOut     = sizeof(COREAUDIOSTREAMOUT);
     2069    pCfg->cMaxStreamsIn   = UINT32_MAX;
     2070    pCfg->cMaxStreamsOut  = UINT32_MAX;
     2071
     2072    /** @todo Implement a proper device detection. */
     2073    pCfg->cDevsIn         = 1;
     2074    pCfg->cDevsOut        = 1;
    20612075
    20622076    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r59890 r59987  
    9191{
    9292    PDMAUDIOHSTSTRMOUT   strmOut; /* Always must come first! */
    93     LPDIRECTSOUND8       pDS;
     93    LPDIRECTSOUND8       pDS;     /** @todo Move this out of this structure! Not required per-stream (e.g. for multi-channel). */
    9494    LPDIRECTSOUNDBUFFER8 pDSB;
    9595    DWORD                cbPlayWritePos;
     
    160160typedef struct DSOUNDENUMCBCTX
    161161{
     162    /** Pointer to host backend driver. */
    162163    PDRVHOSTDSOUND      pDrv;
    163     PPDMAUDIOBACKENDCFG pCfg;
    164164    /** Enumeration flags. */
    165165    uint32_t            fFlags;
     166    /** Number of found input devices. */
     167    uint8_t             cDevIn;
     168    /** Number of found output devices. */
     169    uint8_t             cDevOut;
    166170} DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX;
    167171
     
    173177} DSOUNDDEV, *PDSOUNDDEV;
    174178
     179/*********************************************************************************************************************************
     180*   Defines                                                                                                                      *
     181*********************************************************************************************************************************/
     182
    175183/** Maximum number of attempts to restore the sound buffer before giving up. */
    176184#define DRV_DSOUND_RESTORE_ATTEMPTS_MAX         3
     
    179187#define PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface) \
    180188    ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTDSOUND, IHostAudio)) )
     189
     190/*********************************************************************************************************************************
     191*   Prototypes                                                                                                                   *
     192*********************************************************************************************************************************/
    181193
    182194static HRESULT directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB);
     
    12431255    AssertPtrReturn(pCtx, FALSE);
    12441256    AssertPtrReturn(pCtx->pDrv, FALSE);
    1245     AssertPtrReturn(pCtx->pCfg, FALSE);
    12461257
    12471258    if (!lpGUID)
     
    12591270        return FALSE; /* Abort enumeration. */
    12601271
    1261     pCtx->pCfg->cMaxHstStrmsOut++;
     1272    pCtx->cDevOut++;
    12621273
    12631274    return TRUE;
     
    12701281    AssertPtrReturn(pCtx, FALSE);
    12711282    AssertPtrReturn(pCtx->pDrv, FALSE);
    1272     AssertPtrReturn(pCtx->pCfg, FALSE);
    12731283
    12741284    if (!lpGUID)
     
    12831293        return FALSE; /* Abort enumeration. */
    12841294
    1285     pCtx->pCfg->cMaxHstStrmsIn++;
     1295    pCtx->cDevIn++;
    12861296
    12871297    return TRUE;
     
    12931303 * @return  IPRT status code.
    12941304 * @param   pThis               Host audio driver instance.
    1295  * @param   pCfg                Where to store the enumeration results.
     1305 * @param   pEnmCtx             Enumeration context to use.
    12961306 * @param   fEnum               Enumeration flags.
    12971307 */
    1298 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum)
    1299 {
    1300     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1301     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     1308static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDSOUNDENUMCBCTX pEnmCtx, uint32_t fEnum)
     1309{
     1310    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1311    AssertPtrReturn(pEnmCtx, VERR_INVALID_POINTER);
    13021312
    13031313    dsoundDevicesClear(pThis);
    1304 
    1305     pCfg->cMaxHstStrmsOut = 0;
    1306     pCfg->cMaxHstStrmsIn  = 0;
    13071314
    13081315    RTLDRMOD hDSound = NULL;
     
    13191326        if (RT_SUCCESS(rc))
    13201327        {
    1321             DSOUNDENUMCBCTX ctx = { pThis, pCfg, fEnum };
    1322 
    1323             HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, &ctx);
     1328            HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, pEnmCtx);
    13241329            if (FAILED(hr))
    13251330                LogRel2(("DSound: Error enumerating host playback devices: %Rhrc\n", hr));
    13261331
    1327             hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &ctx);
     1332            hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, pEnmCtx);
    13281333            if (FAILED(hr))
    13291334                LogRel2(("DSound: Error enumerating host capturing devices: %Rhrc\n", hr));
     1335
     1336            if (fEnum & DSOUNDENUMCBFLAGS_LOG)
     1337            {
     1338                LogRel2(("DSound: Found %RU8 host playback devices\n",  pEnmCtx->cDevOut));
     1339                LogRel2(("DSound: Found %RU8 host capturing devices\n", pEnmCtx->cDevIn));
     1340            }
    13301341        }
    13311342
     
    13571368    RT_ZERO(Cfg);
    13581369
    1359     Cfg.cbStreamOut = sizeof(DSOUNDSTREAMOUT);
    1360     Cfg.cbStreamIn  = sizeof(DSOUNDSTREAMIN);
    1361 
    1362     int rc = dsoundDevicesEnumerate(pThis, &Cfg, fEnum);
    1363     AssertRC(rc);
    1364 
     1370    Cfg.cbStreamOut     = sizeof(DSOUNDSTREAMOUT);
     1371    Cfg.cbStreamIn      = sizeof(DSOUNDSTREAMIN);
     1372
     1373    DSOUNDENUMCBCTX cbCtx = { pThis, fEnum, 0, 0 };
     1374
     1375    int rc = dsoundDevicesEnumerate(pThis, &cbCtx, fEnum);
     1376    if (RT_SUCCESS(rc))
     1377    {
    13651378#ifdef VBOX_WITH_AUDIO_CALLBACKS
    1366     if (   pThis->fEnabledOut != RT_BOOL(Cfg.cMaxHstStrmsOut)
    1367         || pThis->fEnabledIn  != RT_BOOL(Cfg.cMaxHstStrmsIn))
    1368     {
    1369         /** @todo Use a registered callback to the audio connector (e.g "OnConfigurationChanged") to
    1370          *        let the connector know that something has changed within the host backend. */
    1371     }
     1379        if (   pThis->fEnabledOut != RT_BOOL(cbCtx.cDevOut)
     1380            || pThis->fEnabledIn  != RT_BOOL(cbCtx.cDevIn))
     1381        {
     1382            /** @todo Use a registered callback to the audio connector (e.g "OnConfigurationChanged") to
     1383             *        let the connector know that something has changed within the host backend. */
     1384        }
    13721385#else
    1373     pThis->fEnabledOut = RT_BOOL(Cfg.cMaxHstStrmsOut);
    1374     pThis->fEnabledIn  = RT_BOOL(Cfg.cMaxHstStrmsIn);
     1386        pThis->fEnabledOut = RT_BOOL(cbCtx.cDevOut);
     1387        pThis->fEnabledIn  = RT_BOOL(cbCtx.cDevIn);
    13751388#endif
    13761389
    1377     if (pCfg)
    1378         memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG));
     1390        Cfg.cSources       = cbCtx.cDevIn;
     1391        Cfg.cSinks         = cbCtx.cDevOut;
     1392        Cfg.cMaxStreamsIn  = UINT32_MAX;
     1393        Cfg.cMaxStreamsOut = UINT32_MAX;
     1394
     1395        if (pCfg)
     1396            memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG));
     1397    }
    13791398
    13801399    LogFlowFuncLeaveRC(rc);
     
    20962115#endif
    20972116
    2098         PDMAUDIOBACKENDCFG Cfg;
    2099         dsoundUpdateStatusInternalEx(pThis, &Cfg, DSOUNDENUMCBFLAGS_LOG /* fEnum */);
    2100 
    2101         DSLOGREL(("DSound: Found %RU32 host playback devices\n",  Cfg.cMaxHstStrmsOut));
    2102         DSLOGREL(("DSound: Found %RU32 host capturing devices\n", Cfg.cMaxHstStrmsIn));
     2117        dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */);
    21032118    }
    21042119    else
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r58983 r59987  
    66
    77/*
    8  * Copyright (C) 2006-2015 Oracle Corporation
     8 * Copyright (C) 2006-2016 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    8787    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    8888
    89     pCfg->cbStreamOut = sizeof(NULLAUDIOSTREAMOUT);
    90     pCfg->cbStreamIn  = sizeof(NULLAUDIOSTREAMIN);
    91 
    92     pCfg->cMaxHstStrmsOut = 1; /* Output */
    93     pCfg->cMaxHstStrmsIn  = 2; /* Line input + microphone input. */
     89    pCfg->cbStreamOut    = sizeof(NULLAUDIOSTREAMOUT);
     90    pCfg->cbStreamIn     = sizeof(NULLAUDIOSTREAMIN);
     91
     92    /* The NULL backend has exactly one input source and one output sink. */
     93    pCfg->cSources       = 1;
     94    pCfg->cSinks         = 1;
     95
     96    pCfg->cMaxStreamsOut = 1; /* Output */
     97    pCfg->cMaxStreamsIn  = 2; /* Line input + microphone input. */
    9498
    9599    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp

    r59097 r59987  
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3434#include <VBox/vmm/pdmaudioifs.h>
    3535
     36/*********************************************************************************************************************************
     37*   Defines                                                                                                                      *
     38*********************************************************************************************************************************/
     39
     40#if ((SOUND_VERSION > 360) && (defined(OSS_SYSINFO)))
     41/* OSS > 3.6 has a new syscall available for querying a bit more detailed information
     42 * about OSS' audio capabilities. */
     43# define VBOX_WITH_OSS_SYSINFO 1
     44#endif
     45
     46/** Makes DRVHOSTOSSAUDIO out of PDMIHOSTAUDIO. */
     47#define PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface) \
     48    ( (PDRVHOSTOSSAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTOSSAUDIO, IHostAudio)) )
     49
     50/*********************************************************************************************************************************
     51*   Structures                                                                                                                   *
     52*********************************************************************************************************************************/
     53
    3654/**
    3755 * OSS host audio driver instance data.
     
    6785    int                cbFragmentSize;
    6886    /** Own PCM buffer. */
    69     void              *pvPCMBuf;
     87    void              *pvBuf;
    7088    /** Size (in bytes) of own PCM buffer. */
    71     size_t             cbPCMBuf;
     89    size_t             cbBuf;
    7290    int                old_optr;
    7391} OSSAUDIOSTREAMIN, *POSSAUDIOSTREAMIN;
     
    86104#endif
    87105    /** Own PCM buffer in case memory mapping is unavailable. */
    88     void               *pvPCMBuf;
     106    void               *pvBuf;
    89107    /** Size (in bytes) of own PCM buffer. */
    90     size_t              cbPCMBuf;
     108    size_t              cbBuf;
    91109    int                 old_optr;
    92110} OSSAUDIOSTREAMOUT, *POSSAUDIOSTREAMOUT;
     
    133151}
    134152
    135 static int drvHostOSSAudioFmtToOSS(PDMAUDIOFMT fmt)
     153static int ossAudioFmtToOSS(PDMAUDIOFMT fmt)
    136154{
    137155    switch (fmt)
     
    157175}
    158176
    159 static int drvHostOSSAudioOSSToFmt(int fmt,
    160                                    PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pENDIANNESS)
     177static int ossOSSToAudioFmt(int fmt, PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pENDIANNESS)
    161178{
    162179    switch (fmt)
     
    206223}
    207224
    208 static int drvHostOSSAudioClose(int *phFile)
     225static int ossStreamClose(int *phFile)
    209226{
    210227    if (!phFile || !*phFile)
     
    214231    if (close(*phFile))
    215232    {
    216         LogRel(("OSS: Closing descriptor failed: %s\n",
    217                 strerror(errno)));
     233        LogRel(("OSS: Closing stream failed: %s\n", strerror(errno)));
    218234        rc = VERR_GENERAL_FAILURE; /** @todo */
    219235    }
     
    227243}
    228244
    229 static int drvHostOSSAudioOpen(bool fIn,
    230                                POSSAUDIOSTREAMCFG pReq, POSSAUDIOSTREAMCFG pObt,
    231                                int *phFile)
    232 {
    233     AssertPtrReturn(pReq, VERR_INVALID_POINTER);
    234     AssertPtrReturn(pObt, VERR_INVALID_POINTER);
     245static int ossStreamOpen(const char *pszDev, int fOpen, POSSAUDIOSTREAMCFG pReq, POSSAUDIOSTREAMCFG pObt, int *phFile)
     246{
     247    AssertPtrReturn(pszDev, VERR_INVALID_POINTER);
     248    AssertPtrReturn(pReq,   VERR_INVALID_POINTER);
     249    AssertPtrReturn(pObt,   VERR_INVALID_POINTER);
    235250    AssertPtrReturn(phFile, VERR_INVALID_POINTER);
    236251
    237252    int rc;
    238     int hFile;
    239 
     253
     254    int hFile = -1;
    240255    do
    241256    {
    242         const char *pszDev = fIn ? s_OSSConf.devpath_in : s_OSSConf.devpath_out;
    243         if (!pszDev)
    244         {
    245             LogRel(("OSS: Invalid or no %s device name set\n",
    246                     fIn ? "input" : "output"));
    247             rc = VERR_INVALID_PARAMETER;
    248             break;
    249         }
    250 
    251         hFile = open(pszDev, (fIn ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
     257        hFile = open(pszDev, fOpen);
    252258        if (hFile == -1)
    253259        {
    254             LogRel(("OSS: Failed to open %s: %s(%d)\n", pszDev, strerror(errno), errno));
     260            LogRel(("OSS: Failed to open %s: %s (%d)\n", pszDev, strerror(errno), errno));
    255261            rc = RTErrConvertFromErrno(errno);
    256262            break;
    257263        }
    258264
    259         int iFormat = drvHostOSSAudioFmtToOSS(pReq->enmFormat);
     265        int iFormat = ossAudioFmtToOSS(pReq->enmFormat);
    260266        if (ioctl(hFile, SNDCTL_DSP_SAMPLESIZE, &iFormat))
    261267        {
    262             LogRel(("OSS: Failed to set audio format to %ld errno=%s(%d)\n", iFormat, strerror(errno), errno));
     268            LogRel(("OSS: Failed to set audio format to %ld: %s (%d)\n", iFormat, strerror(errno), errno));
    263269            rc = RTErrConvertFromErrno(errno);
    264270            break;
     
    268274        if (ioctl(hFile, SNDCTL_DSP_CHANNELS, &cChannels))
    269275        {
    270             LogRel(("OSS: Failed to set number of audio channels (%d): %s(%d)\n", pReq->cChannels, strerror(errno), errno));
     276            LogRel(("OSS: Failed to set number of audio channels (%d): %s (%d)\n", pReq->cChannels, strerror(errno), errno));
    271277            rc = RTErrConvertFromErrno(errno);
    272278            break;
     
    276282        if (ioctl(hFile, SNDCTL_DSP_SPEED, &freq))
    277283        {
    278             LogRel(("OSS: Failed to set audio frequency (%dHZ): %s(%d)\n", pReq->uFreq, strerror(errno), errno));
     284            LogRel(("OSS: Failed to set audio frequency (%dHZ): %s (%d)\n", pReq->uFreq, strerror(errno), errno));
    279285            rc = RTErrConvertFromErrno(errno);
    280286            break;
     
    285291        if (ioctl(hFile, SNDCTL_DSP_NONBLOCK))
    286292        {
    287             LogRel(("OSS: Failed to set non-blocking mode: %s(%d)\n", strerror(errno), errno));
     293            LogRel(("OSS: Failed to set non-blocking mode: %s (%d)\n", strerror(errno), errno));
    288294            rc = RTErrConvertFromErrno(errno);
    289295            break;
     
    293299        if (ioctl(hFile, SNDCTL_DSP_SETFRAGMENT, &mmmmssss))
    294300        {
    295             LogRel(("OSS: Failed to set %RU16 fragments to %RU32 bytes each: %s(%d)\n",
     301            LogRel(("OSS: Failed to set %RU16 fragments to %RU32 bytes each: %s (%d)\n",
    296302                    pReq->cFragments, pReq->cbFragmentSize, strerror(errno), errno));
    297303            rc = RTErrConvertFromErrno(errno);
     
    300306
    301307        audio_buf_info abinfo;
    302         if (ioctl(hFile, fIn ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo))
    303         {
    304             LogRel(("OSS: Failed to retrieve buffer length: %s(%d)\n", strerror(errno), errno));
     308        if (ioctl(hFile, (fOpen & O_RDONLY) ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo))
     309        {
     310            LogRel(("OSS: Failed to retrieve buffer length: %s (%d)\n", strerror(errno), errno));
    305311            rc = RTErrConvertFromErrno(errno);
    306312            break;
    307313        }
    308314
    309         rc = drvHostOSSAudioOSSToFmt(iFormat, &pObt->enmFormat, &pObt->enmENDIANNESS);
     315        rc = ossOSSToAudioFmt(iFormat, &pObt->enmFormat, &pObt->enmENDIANNESS);
    310316        if (RT_SUCCESS(rc))
    311317        {
     
    321327
    322328    if (RT_FAILURE(rc))
    323         drvHostOSSAudioClose(&hFile);
     329        ossStreamClose(&hFile);
    324330
    325331    LogFlowFuncLeaveRC(rc);
     
    362368        {
    363369            DrvAudioClearBuf(&pHstStrmOut->Props,
    364                              pThisStrmOut->pvPCMBuf, pThisStrmOut->cbPCMBuf, AudioMixBufSize(&pHstStrmOut->MixBuf));
     370                             pThisStrmOut->pvBuf, pThisStrmOut->cbBuf, AudioMixBufSize(&pHstStrmOut->MixBuf));
    365371
    366372            mask = PCM_ENABLE_OUTPUT;
     
    412418    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    413419
    414     POSSAUDIOSTREAMIN pThisStrmIn = (POSSAUDIOSTREAMIN)pHstStrmIn;
     420    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
    415421
    416422    int rc = VINF_SUCCESS;
    417     size_t cbToRead = RT_MIN(pThisStrmIn->cbPCMBuf,
     423    size_t cbToRead = RT_MIN(pStrm->cbBuf,
    418424                             AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
    419425
     
    427433    while (cbToRead)
    428434    {
    429         cbTemp = RT_MIN(cbToRead, pThisStrmIn->cbPCMBuf);
     435        cbTemp = RT_MIN(cbToRead, pStrm->cbBuf);
    430436        AssertBreakStmt(cbTemp, rc = VERR_NO_DATA);
    431         cbRead = read(pThisStrmIn->hFile, (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbTemp);
    432 
    433         LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n",
    434                      cbRead, cbTemp, cbToRead));
     437        cbRead = read(pStrm->hFile, (uint8_t *)pStrm->pvBuf + offWrite, cbTemp);
     438
     439        LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n", cbRead, cbTemp, cbToRead));
    435440
    436441        if (cbRead < 0)
     
    451456
    452457                default:
    453                     LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n",
    454                                  cbTemp, rc));
    455                     rc = VERR_GENERAL_FAILURE; /** @todo */
     458                    LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n", cbTemp, rc));
     459                    rc = VERR_GENERAL_FAILURE; /** @todo Fix this. */
    456460                    break;
    457461            }
     
    463467        {
    464468            uint32_t cWritten;
    465             rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
    466                                       pThisStrmIn->pvPCMBuf, cbRead,
    467                                       &cWritten);
     469            rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, pStrm->pvBuf, cbRead, &cWritten);
    468470            if (RT_FAILURE(rc))
    469471                break;
     
    487489        uint32_t cProcessed = 0;
    488490        if (cWrittenTotal)
    489             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
    490                                         &cProcessed);
     491            rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cProcessed);
    491492
    492493        if (pcSamplesCaptured)
     
    506507    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    507508
    508     POSSAUDIOSTREAMIN pThisStrmIn = (POSSAUDIOSTREAMIN)pHstStrmIn;
     509    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
    509510
    510511    LogFlowFuncEnter();
    511512
    512     if (pThisStrmIn->pvPCMBuf)
    513     {
    514         Assert(pThisStrmIn->cbPCMBuf);
    515 
    516         RTMemFree(pThisStrmIn->pvPCMBuf);
    517         pThisStrmIn->pvPCMBuf = NULL;
    518     }
    519 
    520     pThisStrmIn->cbPCMBuf = 0;
     513    if (pStrm->pvBuf)
     514    {
     515        Assert(pStrm->cbBuf);
     516
     517        RTMemFree(pStrm->pvBuf);
     518        pStrm->pvBuf = NULL;
     519    }
     520
     521    pStrm->cbBuf = 0;
     522
     523    ossStreamClose(&pStrm->hFile);
    521524
    522525    return VINF_SUCCESS;
     
    528531    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    529532
    530     POSSAUDIOSTREAMOUT pThisStrmOut = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     533    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
    531534
    532535    LogFlowFuncEnter();
    533536
    534537#ifndef RT_OS_L4
    535     if (!pThisStrmOut->fMemMapped)
    536     {
    537         if (pThisStrmOut->pvPCMBuf)
    538         {
    539             Assert(pThisStrmOut->cbPCMBuf);
    540 
    541             RTMemFree(pThisStrmOut->pvPCMBuf);
    542             pThisStrmOut->pvPCMBuf = NULL;
    543         }
    544 
    545         pThisStrmOut->cbPCMBuf = 0;
    546     }
    547 #endif
     538    if (pStrm->fMemMapped)
     539    {
     540        if (pStrm->pvBuf)
     541        {
     542            Assert(pStrm->cbBuf);
     543
     544            int rc2 = munmap(pStrm->pvBuf, pStrm->cbBuf);
     545            if (rc2 == 0)
     546            {
     547                pStrm->pvBuf      = NULL;
     548                pStrm->cbBuf      = 0;
     549
     550                pStrm->fMemMapped = false;
     551            }
     552            else
     553                LogRel(("OSS: Failed to memory unmap playback buffer on close: %s\n", strerror(errno)));
     554        }
     555    }
     556    else
     557    {
     558#endif
     559        if (pStrm->pvBuf)
     560        {
     561            Assert(pStrm->cbBuf);
     562
     563            RTMemFree(pStrm->pvBuf);
     564            pStrm->pvBuf = NULL;
     565        }
     566
     567        pStrm->cbBuf = 0;
     568#ifndef RT_OS_L4
     569    }
     570#endif
     571
     572    ossStreamClose(&pStrm->hFile);
    548573
    549574    return VINF_SUCCESS;
     
    554579    NOREF(pInterface);
    555580
     581    pCfg->cbStreamIn  = sizeof(OSSAUDIOSTREAMIN);
    556582    pCfg->cbStreamOut = sizeof(OSSAUDIOSTREAMOUT);
    557     pCfg->cbStreamIn = sizeof(OSSAUDIOSTREAMIN);
    558     pCfg->cMaxHstStrmsOut = INT_MAX;
    559     pCfg->cMaxHstStrmsIn = INT_MAX;
     583
     584    pCfg->cSources    = 0;
     585    pCfg->cSinks      = 0;
     586
     587    int hFile = open("/dev/dsp", O_WRONLY | O_NONBLOCK, 0);
     588    if (hFile == -1)
     589    {
     590        /* Try opening the mixing device instead. */
     591        hFile = open("/dev/mixer", O_RDONLY | O_NONBLOCK, 0);
     592    }
     593
     594    int ossVer = -1;
     595
     596#ifdef VBOX_WITH_OSS_SYSINFO
     597    oss_sysinfo ossInfo;
     598    RT_ZERO(ossInfo);
     599#endif
     600
     601    if (hFile != -1)
     602    {
     603        int err = ioctl(hFile, OSS_GETVERSION, &ossVer);
     604        if (err == 0)
     605        {
     606            LogRel2(("OSS: Using version: %d\n", ossVer));
     607#ifdef VBOX_WITH_OSS_SYSINFO
     608            err = ioctl(hFile, OSS_SYSINFO, &ossInfo);
     609            if (err == 0)
     610            {
     611                LogRel2(("OSS: Number of DSPs: %d\n", ossVer.numaudios));
     612                LogRel2(("OSS: Number of mixers: %d\n", ossVer.nummixers));
     613                /** @todo Determine number of input devices + output devices. */
     614            }
     615            else
     616            {
     617#endif
     618                /* Since we cannot query anything, assume that we have at least
     619                 * one input and one output if we found "/dev/dsp" or "/dev/mixer". */
     620                pCfg->cSources        = 1;
     621                pCfg->cSinks          = 1;
     622
     623                pCfg->cMaxStreamsIn   = UINT32_MAX; /* Line in + microphone in. */
     624                pCfg->cMaxStreamsOut  = UINT32_MAX;
     625#ifdef VBOX_WITH_OSS_SYSINFO
     626            }
     627#endif
     628        }
     629        else
     630            LogRel(("OSS: Unable to determine installed version: %s (%d)\n", strerror(err), err));
     631    }
     632    else
     633        LogRel(("OSS: No devices found, audio is not available\n"));
    560634
    561635    return VINF_SUCCESS;
     
    567641                                               uint32_t *pcSamples)
    568642{
    569     NOREF(pInterface);
     643    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    570644    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    571     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    572 
    573     POSSAUDIOSTREAMIN pThisStrmIn = (POSSAUDIOSTREAMIN)pHstStrmIn;
     645    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     646
     647    PDRVHOSTOSSAUDIO  pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface);
     648    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
    574649
    575650    int rc;
     
    587662        reqStream.cbFragmentSize = s_OSSConf.fragsize;
    588663
    589         rc = drvHostOSSAudioOpen(true /* fIn */,
    590                                  &reqStream, &obtStream, &hFile);
     664        rc = ossStreamOpen(s_OSSConf.devpath_in, O_RDONLY | O_NONBLOCK, &reqStream, &obtStream, &hFile);
    591665        if (RT_SUCCESS(rc))
    592666        {
    593667            if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmIn->Props.uAlign)
    594                 LogRel(("OSS: Warning: Misaligned DAC output buffer: Size = %zu, Alignment = %u\n",
     668                LogRel(("OSS: Warning: Misaligned capturing buffer: Size = %zu, Alignment = %u\n",
    595669                        obtStream.cFragments * obtStream.cbFragmentSize,
    596670                        pHstStrmIn->Props.uAlign + 1));
    597 
    598             pThisStrmIn->hFile = hFile;
    599671
    600672            PDMAUDIOSTREAMCFG streamCfg;
     
    617689        {
    618690            size_t cbSample = (1 << pHstStrmIn->Props.cShift);
    619             size_t cbBuf    = cSamples * cbSample;
    620             pThisStrmIn->pvPCMBuf = RTMemAlloc(cbBuf);
    621             if (!pThisStrmIn->pvPCMBuf)
    622             {
    623                 LogRel(("OSS: Failed allocating ADC buffer with %RU32 samples (%zu bytes per sample)\n", cSamples, cbSample));
     691
     692            size_t cbBuf = cSamples * cbSample;
     693            void  *pvBuf = RTMemAlloc(cbBuf);
     694            if (!pvBuf)
     695            {
     696                LogRel(("OSS: Failed allocating capturing buffer with %RU32 samples (%zu bytes per sample)\n",
     697                        cSamples, cbSample));
    624698                rc = VERR_NO_MEMORY;
    625             }
    626 
    627             pThisStrmIn->cbPCMBuf = cbBuf;
     699                break;
     700            }
     701
     702            pStrm->hFile = hFile;
     703            pStrm->pvBuf = pvBuf;
     704            pStrm->cbBuf = cbBuf;
    628705
    629706            if (pcSamples)
     
    634711
    635712    if (RT_FAILURE(rc))
    636         drvHostOSSAudioClose(&hFile);
     713        ossStreamClose(&hFile);
    637714
    638715    LogFlowFuncLeaveRC(rc);
     
    644721                                                uint32_t *pcSamples)
    645722{
    646     NOREF(pInterface);
     723    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    647724    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    648     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    649 
    650     POSSAUDIOSTREAMOUT pThisStrmOut = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     725    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
     726
     727    PDRVHOSTOSSAUDIO   pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface);
     728    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
    651729
    652730    int rc;
     
    664742        reqStream.cbFragmentSize = s_OSSConf.fragsize;
    665743
    666         rc = drvHostOSSAudioOpen(false /* fIn */,
    667                                  &reqStream, &obtStream, &hFile);
     744        rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY | O_NONBLOCK, &reqStream, &obtStream, &hFile);
    668745        if (RT_SUCCESS(rc))
    669746        {
    670747            if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmOut->Props.uAlign)
    671                 LogRel(("OSS: Warning: Misaligned DAC output buffer: Size = %zu, Alignment = %u\n",
     748                LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n",
    672749                        obtStream.cFragments * obtStream.cbFragmentSize,
    673750                        pHstStrmOut->Props.uAlign + 1));
    674 
    675             pThisStrmOut->hFile = hFile;
    676751
    677752            PDMAUDIOSTREAMCFG streamCfg;
     
    689764        if (RT_SUCCESS(rc))
    690765        {
     766            pStrm->fMemMapped = false;
     767
     768            size_t cbSamples =  cSamples << pHstStrmOut->Props.cShift;
     769            Assert(cbSamples);
     770
    691771#ifndef RT_OS_L4
    692             pThisStrmOut->fMemMapped = false;
    693772            if (s_OSSConf.try_mmap)
    694773            {
    695                 pThisStrmOut->pvPCMBuf = mmap(0, cSamples << pHstStrmOut->Props.cShift,
    696                                               PROT_READ | PROT_WRITE, MAP_SHARED, hFile, 0);
    697                 if (pThisStrmOut->pvPCMBuf == MAP_FAILED)
     774                pStrm->pvBuf = mmap(0, cbSamples, PROT_READ | PROT_WRITE, MAP_SHARED, hFile, 0);
     775                if (pStrm->pvBuf == MAP_FAILED)
    698776                {
    699                     LogRel(("OSS: Failed to memory map %zu bytes of DAC output file: %s\n",
    700                             cSamples << pHstStrmOut->Props.cShift, strerror(errno)));
     777                    LogRel(("OSS: Failed to memory map %zu bytes of playback buffer: %s\n", cbSamples, strerror(errno)));
    701778                    rc = RTErrConvertFromErrno(errno);
    702779                    break;
     
    707784                    if (ioctl(hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    708785                    {
    709                         LogRel(("OSS: Failed to retrieve initial trigger mask: %s\n",
    710                                 strerror(errno)));
     786                        LogRel(("OSS: Failed to retrieve initial trigger mask for playback buffer: %s\n", strerror(errno)));
    711787                        rc = RTErrConvertFromErrno(errno);
    712788                        /* Note: No break here, need to unmap file first! */
     
    717793                        if (ioctl (hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    718794                        {
    719                             LogRel(("OSS: Failed to retrieve PCM_ENABLE_OUTPUT mask: %s\n",
    720                                     strerror(errno)));
     795                            LogRel(("OSS: Failed to retrieve PCM_ENABLE_OUTPUT mask: %s\n", strerror(errno)));
    721796                            rc = RTErrConvertFromErrno(errno);
    722797                            /* Note: No break here, need to unmap file first! */
    723798                        }
    724799                        else
    725                             pThisStrmOut->fMemMapped = true;
     800                            pStrm->fMemMapped = true;
    726801                    }
    727802
    728                     if (!pThisStrmOut->fMemMapped)
     803                    if (RT_FAILURE(rc))
    729804                    {
    730                         int rc2 = munmap(pThisStrmOut->pvPCMBuf,
    731                                          cSamples << pHstStrmOut->Props.cShift);
     805                        int rc2 = munmap(pStrm->pvBuf, cbSamples);
    732806                        if (rc2)
    733                             LogRel(("OSS: Failed to unmap DAC output file: %s\n", strerror(errno)));
     807                            LogRel(("OSS: Failed to memory unmap playback buffer: %s\n", strerror(errno)));
    734808                        break;
    735809                    }
     
    740814            /* Memory mapping failed above? Try allocating an own buffer. */
    741815#ifndef RT_OS_L4
    742             if (!pThisStrmOut->fMemMapped)
    743             {
    744 #endif
    745                 size_t cbSample = (1 << pHstStrmOut->Props.cShift);
    746                 size_t cbPCMBuf = cSamples * cbSample;
    747 
    748                 LogFlowFunc(("cSamples=%RU32\n", cSamples));
    749 
    750                 pThisStrmOut->pvPCMBuf = RTMemAlloc(cbPCMBuf);
    751                 if (!pThisStrmOut->pvPCMBuf)
     816            if (!pStrm->fMemMapped)
     817            {
     818#endif
     819                void *pvBuf = RTMemAlloc(cbSamples);
     820                if (!pvBuf)
    752821                {
    753                     LogRel(("OSS: Failed allocating DAC buffer with %RU32 samples (%zu bytes per sample)\n", cSamples, cbSample));
     822                    LogRel(("OSS: Failed allocating playback buffer with %RU32 samples (%zu bytes)\n", cSamples, cbSamples));
    754823                    rc = VERR_NO_MEMORY;
    755824                    break;
    756825                }
    757826
    758                 pThisStrmOut->cbPCMBuf = cbPCMBuf;
     827                pStrm->hFile = hFile;
     828                pStrm->pvBuf = pvBuf;
     829                pStrm->cbBuf = cbSamples;
    759830#ifndef RT_OS_L4
    760831            }
     
    767838
    768839    if (RT_FAILURE(rc))
    769         drvHostOSSAudioClose(&hFile);
     840        ossStreamClose(&hFile);
    770841
    771842    LogFlowFuncLeaveRC(rc);
     
    786857    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    787858
    788     POSSAUDIOSTREAMOUT pThisStrmOut = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     859    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
    789860
    790861    int rc = VINF_SUCCESS;
     
    800871
    801872#ifndef RT_OS_L4
    802         if (pThisStrmOut->fMemMapped)
     873        if (pStrm->fMemMapped)
    803874        {
    804875            /* Get current playback pointer. */
    805             int rc2 = ioctl(pThisStrmOut->hFile, SNDCTL_DSP_GETOPTR, &cntinfo);
     876            int rc2 = ioctl(pStrm->hFile, SNDCTL_DSP_GETOPTR, &cntinfo);
    806877            if (!rc2)
    807878            {
     
    813884
    814885            /* Nothing to play? */
    815             if (cntinfo.ptr == pThisStrmOut->old_optr)
     886            if (cntinfo.ptr == pStrm->old_optr)
    816887                break;
    817888
    818889            int cbData;
    819             if (cntinfo.ptr > pThisStrmOut->old_optr)
    820                 cbData = cntinfo.ptr - pThisStrmOut->old_optr;
     890            if (cntinfo.ptr > pStrm->old_optr)
     891                cbData = cntinfo.ptr - pStrm->old_optr;
    821892            else
    822                 cbData = cbBuf + cntinfo.ptr - pThisStrmOut->old_optr;
     893                cbData = cbBuf + cntinfo.ptr - pStrm->old_optr;
    823894            Assert(cbData);
    824895
     
    830901#endif
    831902            audio_buf_info abinfo;
    832             int rc2 = ioctl(pThisStrmOut->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
     903            int rc2 = ioctl(pStrm->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);
    833904            if (rc2 < 0)
    834905            {
    835                 LogRel(("OSS: Failed to retrieve current playback buffer: %s\n",
    836                         strerror(errno)));
     906                LogRel(("OSS: Failed to retrieve current playback buffer: %s\n", strerror(errno)));
    837907                rc = RTErrConvertFromErrno(errno);
    838908                break;
     
    841911            if ((size_t)abinfo.bytes > cbBuf)
    842912            {
    843                 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%d\n",
    844                              abinfo.bytes, cbBuf));
     913                LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBuf));
    845914                abinfo.bytes = cbBuf;
    846915                /* Keep going. */
     
    849918            if (abinfo.bytes < 0)
    850919            {
    851                 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%d\n",
    852                              abinfo.bytes, cbBuf));
     920                LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBuf));
    853921                rc = VERR_INVALID_PARAMETER;
    854922                break;
    855923            }
    856924
    857             cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, abinfo.bytes),
    858                              cLive);
     925            cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, abinfo.bytes), cLive);
    859926            if (!cToRead)
    860927                break;
     
    868935        while (cbToRead)
    869936        {
    870             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf,
    871                                      pThisStrmOut->pvPCMBuf, cbToRead, &cRead);
     937            rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvBuf, cbToRead, &cRead);
    872938            if (RT_FAILURE(rc))
    873939                break;
    874940
    875941            cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
    876             ssize_t cbWritten = write(pThisStrmOut->hFile, pThisStrmOut->pvPCMBuf,
    877                                       cbRead);
     942            ssize_t cbWritten = write(pStrm->hFile, pStrm->pvBuf, cbRead);
    878943            if (cbWritten == -1)
    879944            {
     
    884949
    885950            Assert(cbToRead >= cbRead);
    886             cbToRead -= cbRead;
     951            cbToRead    -= cbRead;
    887952            cbReadTotal += cbRead;
    888953        }
     
    890955#ifndef RT_OS_L4
    891956        /* Update read pointer. */
    892         if (pThisStrmOut->fMemMapped)
    893             pThisStrmOut->old_optr = cntinfo.ptr;
     957        if (pStrm->fMemMapped)
     958            pStrm->old_optr = cntinfo.ptr;
    894959#endif
    895960
     
    905970            *pcSamplesPlayed = cReadTotal;
    906971
    907         LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n",
    908                      cReadTotal, cbReadTotal, rc));
     972        LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", cReadTotal, cbReadTotal, rc));
    909973    }
    910974
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r59470 r59987  
    1616 */
    1717
    18 
    1918/*********************************************************************************************************************************
    2019*   Header Files                                                                                                                 *
     
    4140#include "VBoxDD.h"
    4241
     42/*********************************************************************************************************************************
     43*   Defines                                                                                                                      *
     44*********************************************************************************************************************************/
    4345#define VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS 32 /** @todo Make this configurable thru driver options. */
    4446
     
    5153#endif
    5254
    53 /*
    54  * We use a g_pMainLoop in a separate thread g_pContext. We have to call functions for
    55  * manipulating objects either from callback functions or we have to protect
    56  * these functions by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock().
    57  */
    58 static struct pa_threaded_mainloop *g_pMainLoop;
    59 static struct pa_context           *g_pContext;
    60 static volatile bool                g_fAbortMainLoop;
     55/** No flags specified. */
     56#define PULSEAUDIOENUMCBFLAGS_NONE          0
     57/** (Release) log found devices. */
     58#define PULSEAUDIOENUMCBFLAGS_LOG           RT_BIT(0)
     59
     60/** Makes DRVHOSTPULSEAUDIO out of PDMIHOSTAUDIO. */
     61#define PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface) \
     62    ( (PDRVHOSTPULSEAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPULSEAUDIO, IHostAudio)) )
     63
     64/*********************************************************************************************************************************
     65*   Structures                                                                                                                   *
     66*********************************************************************************************************************************/
    6167
    6268/**
     
    6773{
    6874    /** Pointer to the driver instance structure. */
    69     PPDMDRVINS         pDrvIns;
     75    PPDMDRVINS            pDrvIns;
     76    /** Pointer to PulseAudio's threaded main loop. */
     77    pa_threaded_mainloop *pMainLoop;
     78    /**
     79    * Pointer to our PulseAudio context.
     80    * Note: We use a pMainLoop in a separate thread (pContext).
     81    *       So either use callback functions or protect these functions
     82    *       by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock().
     83    */
     84    pa_context           *pContext;
     85    /** Shutdown indicator. */
     86    bool                  fLoopWait;
    7087    /** Pointer to host audio interface. */
    71     PDMIHOSTAUDIO      IHostAudio;
     88    PDMIHOSTAUDIO         IHostAudio;
    7289    /** Error count for not flooding the release log.
    73      *  UINT32_MAX for unlimited logging. */
    74     uint32_t           cLogErrors;
    75     /** Configuration option: stream name. */
    76     char               *pszStreamName;
     90     *  Specify UINT32_MAX for unlimited logging. */
     91    uint32_t              cLogErrors;
     92    /** Configuration option: stream name. Optional. */
     93    char                 *pszStreamName;
    7794} DRVHOSTPULSEAUDIO, *PDRVHOSTPULSEAUDIO;
    7895
     
    124141};
    125142
    126 /** Makes DRVHOSTPULSEAUDIO out of PDMIHOSTAUDIO. */
    127 #define PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface) \
    128     ( (PDRVHOSTPULSEAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPULSEAUDIO, IHostAudio)) )
    129 
    130 static int  drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg);
    131 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext);
     143/**
     144 * Callback context for server enumeration callbacks.
     145 */
     146typedef struct PULSEAUDIOENUMCBCTX
     147{
     148    /** Pointer to host backend driver. */
     149    PDRVHOSTPULSEAUDIO  pDrv;
     150    /** Enumeration flags. */
     151    uint32_t            fFlags;
     152    /** Number of found input devices. */
     153    uint8_t             cDevIn;
     154    /** Number of found output devices. */
     155    uint8_t             cDevOut;
     156    /** Name of default sink being used. Must be free'd using RTStrFree(). */
     157    char               *pszDefaultSink;
     158    /** Name of default source being used. Must be free'd using RTStrFree(). */
     159    char               *pszDefaultSource;
     160} PULSEAUDIOENUMCBCTX, *PPULSEAUDIOENUMCBCTX;
     161
     162/*********************************************************************************************************************************
     163*   Prototypes                                                                                                                   *
     164*********************************************************************************************************************************/
     165
     166static int  paEnumerate(PDRVHOSTPULSEAUDIO pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum);
     167static int  paError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg);
     168static void paStreamCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext);
    132169
    133170/**
     
    135172 * mainloop might not have been entered yet.
    136173 */
    137 static void drvHostPulseAudioAbortMainLoop(void)
    138 {
    139     g_fAbortMainLoop = true;
    140     pa_threaded_mainloop_signal(g_pMainLoop, 0);
    141 }
    142 
    143 static pa_sample_format_t drvHostPulseAudioFmtToPulse(PDMAUDIOFMT fmt)
     174static void paSignalWaiter(PDRVHOSTPULSEAUDIO pThis)
     175{
     176    pThis->fLoopWait = true;
     177    pa_threaded_mainloop_signal(pThis->pMainLoop, 0);
     178}
     179
     180static pa_sample_format_t paFmtToPulse(PDMAUDIOFMT fmt)
    144181{
    145182    switch (fmt)
     
    163200}
    164201
    165 static int drvHostPulseAudioPulseToFmt(pa_sample_format_t pulsefmt,
    166                                        PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness)
     202static int paPulseToFmt(pa_sample_format_t pulsefmt,
     203                        PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness)
    167204{
    168205    switch (pulsefmt)
     
    208245 * Synchronously wait until an operation completed.
    209246 */
    210 static int drvHostPulseAudioWaitFor(pa_operation *pOP, RTMSINTERVAL cMsTimeout)
    211 {
    212     AssertPtrReturn(pOP, VERR_INVALID_POINTER);
     247static int paWaitForEx(PDRVHOSTPULSEAUDIO pThis, pa_operation *pOP, RTMSINTERVAL cMsTimeout)
     248{
     249    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     250    AssertPtrReturn(pOP,   VERR_INVALID_POINTER);
    213251
    214252    int rc = VINF_SUCCESS;
    215     if (pOP)
    216     {
    217         uint64_t u64StartMs = RTTimeMilliTS();
    218         while (pa_operation_get_state(pOP) == PA_OPERATION_RUNNING)
    219         {
    220             if (!g_fAbortMainLoop)
    221                 pa_threaded_mainloop_wait(g_pMainLoop);
    222             g_fAbortMainLoop = false;
    223 
    224             uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs;
    225             if (u64ElapsedMs >= cMsTimeout)
    226             {
    227                 rc = VERR_TIMEOUT;
    228                 break;
    229             }
    230         }
    231 
    232         pa_operation_unref(pOP);
    233     }
     253
     254    uint64_t u64StartMs = RTTimeMilliTS();
     255    while (pa_operation_get_state(pOP) == PA_OPERATION_RUNNING)
     256    {
     257        if (!pThis->fLoopWait)
     258        {
     259            AssertPtr(pThis->pMainLoop);
     260            pa_threaded_mainloop_wait(pThis->pMainLoop);
     261        }
     262        pThis->fLoopWait = false;
     263
     264        uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs;
     265        if (u64ElapsedMs >= cMsTimeout)
     266        {
     267            rc = VERR_TIMEOUT;
     268            break;
     269        }
     270    }
     271
     272    pa_operation_unref(pOP);
    234273
    235274    return rc;
     275}
     276
     277static int paWaitFor(PDRVHOSTPULSEAUDIO pThis, pa_operation *pOP)
     278{
     279    return paWaitForEx(pThis, pOP, 10 * 1000 /* 10s timeout */);
    236280}
    237281
     
    239283 * Context status changed.
    240284 */
    241 static void drvHostPulseAudioCbCtxState(pa_context *pContext, void *pvUser)
    242 {
    243     AssertPtrReturnVoid(pContext);
    244     NOREF(pvUser);
    245 
    246     switch (pa_context_get_state(pContext))
     285static void paContextCbStateChanged(pa_context *pCtx, void *pvUser)
     286{
     287    AssertPtrReturnVoid(pCtx);
     288
     289    PDRVHOSTPULSEAUDIO pThis = (PDRVHOSTPULSEAUDIO)pvUser;
     290    AssertPtrReturnVoid(pThis);
     291
     292    switch (pa_context_get_state(pCtx))
    247293    {
    248294        case PA_CONTEXT_READY:
    249295        case PA_CONTEXT_TERMINATED:
    250             drvHostPulseAudioAbortMainLoop();
     296            paSignalWaiter(pThis);
    251297            break;
    252298
    253299        case PA_CONTEXT_FAILED:
    254             LogRel(("PulseAudio: Audio input/output stopped!\n"));
    255             drvHostPulseAudioAbortMainLoop();
     300            LogRel(("PulseAudio: Audio context has failed, stopping\n"));
     301            paSignalWaiter(pThis);
    256302            break;
    257303
     
    264310 * Callback called when our pa_stream_drain operation was completed.
    265311 */
    266 static void drvHostPulseAudioCbStreamDrain(pa_stream *pStream, int fSuccess, void *pvContext)
     312static void paStreamCbDrain(pa_stream *pStream, int fSuccess, void *pvUser)
    267313{
    268314    AssertPtrReturnVoid(pStream);
    269315
    270     PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvContext;
     316    PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvUser;
    271317    AssertPtrReturnVoid(pStrm);
    272318
     
    275321    {
    276322        pa_operation_unref(pa_stream_cork(pStream, 1,
    277                                           drvHostPulseAudioCbSuccess, pvContext));
     323                                          paStreamCbSuccess, pvUser));
    278324    }
    279325    else
    280         drvHostPulseAudioError(pStrm->pDrv, "Failed to drain stream");
     326        paError(pStrm->pDrv, "Failed to drain stream");
    281327
    282328    pa_operation_unref(pStrm->pDrainOp);
     
    287333 * Stream status changed.
    288334 */
    289 static void drvHostPulseAudioCbStreamState(pa_stream *pStream, void *pvContext)
     335static void paStreamCbStateChanged(pa_stream *pStream, void *pvUser)
    290336{
    291337    AssertPtrReturnVoid(pStream);
    292     NOREF(pvContext);
     338
     339    PDRVHOSTPULSEAUDIO pThis = (PDRVHOSTPULSEAUDIO)pvUser;
     340    AssertPtrReturnVoid(pThis);
    293341
    294342    switch (pa_stream_get_state(pStream))
     
    297345        case PA_STREAM_FAILED:
    298346        case PA_STREAM_TERMINATED:
    299             drvHostPulseAudioAbortMainLoop();
     347            paSignalWaiter(pThis);
    300348            break;
    301349
     
    305353}
    306354
    307 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext)
     355static void paStreamCbSuccess(pa_stream *pStream, int fSuccess, void *pvUser)
    308356{
    309357    AssertPtrReturnVoid(pStream);
    310358
    311     PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvContext;
     359    PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvUser;
    312360    AssertPtrReturnVoid(pStrm);
    313361
     
    315363
    316364    if (fSuccess)
    317         drvHostPulseAudioAbortMainLoop();
     365        paSignalWaiter(pStrm->pDrv);
    318366    else
    319         drvHostPulseAudioError(pStrm->pDrv, "Failed to finish stream operation");
    320 }
    321 
    322 static int drvHostPulseAudioOpen(bool fIn, const char *pszName,
    323                                  pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr,
    324                                  pa_stream **ppStream)
    325 {
    326     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     367        paError(pStrm->pDrv, "Failed to finish stream operation");
     368}
     369
     370static int paStreamOpen(PDRVHOSTPULSEAUDIO pThis, bool fIn, const char *pszName,
     371                        pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr,
     372                        pa_stream **ppStream)
     373{
     374    AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
     375    AssertPtrReturn(pszName,     VERR_INVALID_POINTER);
    327376    AssertPtrReturn(pSampleSpec, VERR_INVALID_POINTER);
    328     AssertPtrReturn(pBufAttr, VERR_INVALID_POINTER);
    329     AssertPtrReturn(ppStream, VERR_INVALID_POINTER);
     377    AssertPtrReturn(pBufAttr,    VERR_INVALID_POINTER);
     378    AssertPtrReturn(ppStream,    VERR_INVALID_POINTER);
    330379
    331380    if (!pa_sample_spec_valid(pSampleSpec))
     
    345394             pa_sample_format_to_string(pSampleSpec->format)));
    346395
    347     pa_threaded_mainloop_lock(g_pMainLoop);
     396    pa_threaded_mainloop_lock(pThis->pMainLoop);
    348397
    349398    do
    350399    {
    351         if (!(pStream = pa_stream_new(g_pContext, pszName, pSampleSpec,
     400        if (!(pStream = pa_stream_new(pThis->pContext, pszName, pSampleSpec,
    352401                                      NULL /* pa_channel_map */)))
    353402        {
     
    357406        }
    358407
    359         pa_stream_set_state_callback(pStream, drvHostPulseAudioCbStreamState, NULL);
     408        pa_stream_set_state_callback(pStream, paStreamCbStateChanged, pThis);
    360409
    361410#if PA_API_VERSION >= 12
     
    379428            {
    380429                LogRel(("PulseAudio: Could not connect input stream \"%s\": %s\n",
    381                         pszName, pa_strerror(pa_context_errno(g_pContext))));
     430                        pszName, pa_strerror(pa_context_errno(pThis->pContext))));
    382431                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
    383432                break;
     
    393442            {
    394443                LogRel(("PulseAudio: Could not connect playback stream \"%s\": %s\n",
    395                         pszName, pa_strerror(pa_context_errno(g_pContext))));
     444                        pszName, pa_strerror(pa_context_errno(pThis->pContext))));
    396445                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
    397446                break;
     
    402451        for (;;)
    403452        {
    404             if (!g_fAbortMainLoop)
    405                 pa_threaded_mainloop_wait(g_pMainLoop);
    406             g_fAbortMainLoop = false;
    407 
    408             pa_stream_state_t sstate = pa_stream_get_state(pStream);
    409             if (sstate == PA_STREAM_READY)
     453            if (!pThis->fLoopWait)
     454                pa_threaded_mainloop_wait(pThis->pMainLoop);
     455            pThis->fLoopWait = false;
     456
     457            pa_stream_state_t streamSt = pa_stream_get_state(pStream);
     458            if (streamSt == PA_STREAM_READY)
    410459                break;
    411             else if (   sstate == PA_STREAM_FAILED
    412                      || sstate == PA_STREAM_TERMINATED)
     460            else if (   streamSt == PA_STREAM_FAILED
     461                     || streamSt == PA_STREAM_TERMINATED)
    413462            {
    414                 LogRel(("PulseAudio: Failed to initialize stream \"%s\" (state %ld)\n",
    415                         pszName, sstate));
     463                LogRel(("PulseAudio: Failed to initialize stream \"%s\" (state %ld)\n", pszName, streamSt));
    416464                rc = VERR_AUDIO_BACKEND_INIT_FAILED;
    417465                break;
     
    440488        pa_stream_disconnect(pStream);
    441489
    442     pa_threaded_mainloop_unlock(g_pMainLoop);
     490    pa_threaded_mainloop_unlock(pThis->pMainLoop);
    443491
    444492    if (RT_FAILURE(rc))
     
    456504static DECLCALLBACK(int) drvHostPulseAudioInit(PPDMIHOSTAUDIO pInterface)
    457505{
    458     NOREF(pInterface);
     506    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     507
     508    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    459509
    460510    LogFlowFuncEnter();
     
    467517    }
    468518
     519    pThis->fLoopWait = false;
     520    pThis->pMainLoop = NULL;
     521
    469522    bool fLocked = false;
    470523
    471524    do
    472525    {
    473         if (!(g_pMainLoop = pa_threaded_mainloop_new()))
     526        if (!(pThis->pMainLoop = pa_threaded_mainloop_new()))
    474527        {
    475528            LogRel(("PulseAudio: Failed to allocate main loop: %s\n",
    476                      pa_strerror(pa_context_errno(g_pContext))));
     529                     pa_strerror(pa_context_errno(pThis->pContext))));
    477530            rc = VERR_NO_MEMORY;
    478531            break;
    479532        }
    480533
    481         if (!(g_pContext = pa_context_new(pa_threaded_mainloop_get_api(g_pMainLoop), "VirtualBox")))
     534        if (!(pThis->pContext = pa_context_new(pa_threaded_mainloop_get_api(pThis->pMainLoop), "VirtualBox")))
    482535        {
    483536            LogRel(("PulseAudio: Failed to allocate context: %s\n",
    484                      pa_strerror(pa_context_errno(g_pContext))));
     537                     pa_strerror(pa_context_errno(pThis->pContext))));
    485538            rc = VERR_NO_MEMORY;
    486539            break;
    487540        }
    488541
    489         if (pa_threaded_mainloop_start(g_pMainLoop) < 0)
     542        if (pa_threaded_mainloop_start(pThis->pMainLoop) < 0)
    490543        {
    491544            LogRel(("PulseAudio: Failed to start threaded mainloop: %s\n",
    492                      pa_strerror(pa_context_errno(g_pContext))));
     545                     pa_strerror(pa_context_errno(pThis->pContext))));
    493546            rc = VERR_AUDIO_BACKEND_INIT_FAILED;
    494547            break;
    495548        }
    496549
    497         g_fAbortMainLoop = false;
    498         pa_context_set_state_callback(g_pContext, drvHostPulseAudioCbCtxState, NULL);
    499         pa_threaded_mainloop_lock(g_pMainLoop);
     550        /* Install a global callback to known if something happens to our acquired context. */
     551        pa_context_set_state_callback(pThis->pContext, paContextCbStateChanged, pThis /* pvUserData */);
     552
     553        pa_threaded_mainloop_lock(pThis->pMainLoop);
    500554        fLocked = true;
    501555
    502         if (pa_context_connect(g_pContext, NULL /* pszServer */,
     556        if (pa_context_connect(pThis->pContext, NULL /* pszServer */,
    503557                               PA_CONTEXT_NOFLAGS, NULL) < 0)
    504558        {
    505559            LogRel(("PulseAudio: Failed to connect to server: %s\n",
    506                      pa_strerror(pa_context_errno(g_pContext))));
     560                     pa_strerror(pa_context_errno(pThis->pContext))));
    507561            rc = VERR_AUDIO_BACKEND_INIT_FAILED;
    508562            break;
    509563        }
    510564
    511         /* Wait until the g_pContext is ready */
     565        /* Wait until the pThis->pContext is ready. */
    512566        for (;;)
    513567        {
    514             if (!g_fAbortMainLoop)
    515                 pa_threaded_mainloop_wait(g_pMainLoop);
    516             g_fAbortMainLoop = false;
    517 
    518             pa_context_state_t cstate = pa_context_get_state(g_pContext);
     568            if (!pThis->fLoopWait)
     569                pa_threaded_mainloop_wait(pThis->pMainLoop);
     570            pThis->fLoopWait = false;
     571
     572            pa_context_state_t cstate = pa_context_get_state(pThis->pContext);
    519573            if (cstate == PA_CONTEXT_READY)
    520574                break;
     
    531585
    532586    if (fLocked)
    533         pa_threaded_mainloop_unlock(g_pMainLoop);
     587        pa_threaded_mainloop_unlock(pThis->pMainLoop);
    534588
    535589    if (RT_FAILURE(rc))
    536590    {
    537         if (g_pMainLoop)
    538             pa_threaded_mainloop_stop(g_pMainLoop);
    539 
    540         if (g_pContext)
    541         {
    542             pa_context_disconnect(g_pContext);
    543             pa_context_unref(g_pContext);
    544             g_pContext = NULL;
    545         }
    546 
    547         if (g_pMainLoop)
    548         {
    549             pa_threaded_mainloop_free(g_pMainLoop);
    550             g_pMainLoop = NULL;
     591        if (pThis->pMainLoop)
     592            pa_threaded_mainloop_stop(pThis->pMainLoop);
     593
     594        if (pThis->pContext)
     595        {
     596            pa_context_disconnect(pThis->pContext);
     597            pa_context_unref(pThis->pContext);
     598            pThis->pContext = NULL;
     599        }
     600
     601        if (pThis->pMainLoop)
     602        {
     603            pa_threaded_mainloop_free(pThis->pMainLoop);
     604            pThis->pMainLoop = NULL;
    551605        }
    552606    }
     
    560614                                                  uint32_t *pcSamples)
    561615{
    562     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     616    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    563617    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    564     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     618    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    565619    /* pcSamples is optional. */
    566620
    567     PDRVHOSTPULSEAUDIO pDrv = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    568     PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut;
     621    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     622    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
    569623
    570624    LogFlowFuncEnter();
    571625
    572     pThisStrmOut->pDrainOp            = NULL;
    573 
    574     pThisStrmOut->SampleSpec.format   = drvHostPulseAudioFmtToPulse(pCfg->enmFormat);
    575     pThisStrmOut->SampleSpec.rate     = pCfg->uHz;
    576     pThisStrmOut->SampleSpec.channels = pCfg->cChannels;
     626    pStrm->pDrainOp            = NULL;
     627
     628    pStrm->SampleSpec.format   = paFmtToPulse(pCfg->enmFormat);
     629    pStrm->SampleSpec.rate     = pCfg->uHz;
     630    pStrm->SampleSpec.channels = pCfg->cChannels;
    577631
    578632    /* Note that setting maxlength to -1 does not work on PulseAudio servers
    579633     * older than 0.9.10. So use the suggested value of 3/2 of tlength */
    580     pThisStrmOut->BufAttr.tlength     =   (pa_bytes_per_second(&pThisStrmOut->SampleSpec)
     634    pStrm->BufAttr.tlength     =   (pa_bytes_per_second(&pStrm->SampleSpec)
    581635                                        * s_pulseCfg.buffer_msecs_out) / 1000;
    582     pThisStrmOut->BufAttr.maxlength   = (pThisStrmOut->BufAttr.tlength * 3) / 2;
    583     pThisStrmOut->BufAttr.prebuf      = -1; /* Same as tlength */
    584     pThisStrmOut->BufAttr.minreq      = -1; /* Pulse should set something sensible for minreq on it's own */
     636    pStrm->BufAttr.maxlength   = (pStrm->BufAttr.tlength * 3) / 2;
     637    pStrm->BufAttr.prebuf      = -1; /* Same as tlength */
     638    pStrm->BufAttr.minreq      = -1; /* Pulse should set something sensible for minreq on it's own */
    585639
    586640    /* Note that the struct BufAttr is updated to the obtained values after this call! */
    587641    char achName[64];
    588     RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pDrv->pszStreamName);
    589     int rc = drvHostPulseAudioOpen(false /* fIn */, achName, &pThisStrmOut->SampleSpec, &pThisStrmOut->BufAttr,
    590                                    &pThisStrmOut->pStream);
     642    RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pThis->pszStreamName);
     643
     644    int rc = paStreamOpen(pThis, false /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream);
    591645    if (RT_FAILURE(rc))
    592646        return rc;
    593647
    594648    PDMAUDIOSTREAMCFG streamCfg;
    595     rc = drvHostPulseAudioPulseToFmt(pThisStrmOut->SampleSpec.format,
    596                                      &streamCfg.enmFormat, &streamCfg.enmEndianness);
     649    rc = paPulseToFmt(pStrm->SampleSpec.format,
     650                      &streamCfg.enmFormat, &streamCfg.enmEndianness);
    597651    if (RT_FAILURE(rc))
    598652    {
    599         LogRel(("PulseAudio: Cannot find audio output format %ld\n", pThisStrmOut->SampleSpec.format));
     653        LogRel(("PulseAudio: Cannot find audio output format %ld\n", pStrm->SampleSpec.format));
    600654        return rc;
    601655    }
    602656
    603     streamCfg.uHz       = pThisStrmOut->SampleSpec.rate;
    604     streamCfg.cChannels = pThisStrmOut->SampleSpec.channels;
     657    streamCfg.uHz       = pStrm->SampleSpec.rate;
     658    streamCfg.cChannels = pStrm->SampleSpec.channels;
    605659
    606660    rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
    607661    if (RT_SUCCESS(rc))
    608662    {
    609         uint32_t cbBuf  = RT_MIN(pThisStrmOut->BufAttr.tlength * 2,
    610                                  pThisStrmOut->BufAttr.maxlength); /** @todo Make this configurable! */
     663        uint32_t cbBuf  = RT_MIN(pStrm->BufAttr.tlength * 2,
     664                                 pStrm->BufAttr.maxlength); /** @todo Make this configurable! */
    611665        if (cbBuf)
    612666        {
    613             pThisStrmOut->pvPCMBuf = RTMemAllocZ(cbBuf);
    614             if (pThisStrmOut->pvPCMBuf)
     667            pStrm->pvPCMBuf = RTMemAllocZ(cbBuf);
     668            if (pStrm->pvPCMBuf)
    615669            {
    616                 pThisStrmOut->cbPCMBuf = cbBuf;
     670                pStrm->cbPCMBuf = cbBuf;
    617671
    618672                uint32_t cSamples = cbBuf >> pHstStrmOut->Props.cShift;
     
    621675
    622676                /* Save pointer to driver instance. */
    623                 pThisStrmOut->pDrv = pDrv;
     677                pStrm->pDrv = pThis;
    624678
    625679                LogFunc(("cbBuf=%RU32, cSamples=%RU32\n", cbBuf, cSamples));
     
    653707    /* pcSamples is optional. */
    654708
    655     PDRVHOSTPULSEAUDIO pDrv = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    656     PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn;
     709    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     710    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
    657711
    658712    LogFunc(("enmRecSrc=%ld\n", enmRecSource));
    659713
    660     pThisStrmIn->SampleSpec.format   = drvHostPulseAudioFmtToPulse(pCfg->enmFormat);
    661     pThisStrmIn->SampleSpec.rate     = pCfg->uHz;
    662     pThisStrmIn->SampleSpec.channels = pCfg->cChannels;
     714    pStrm->SampleSpec.format   = paFmtToPulse(pCfg->enmFormat);
     715    pStrm->SampleSpec.rate     = pCfg->uHz;
     716    pStrm->SampleSpec.channels = pCfg->cChannels;
    663717
    664718    /* XXX check these values */
    665     pThisStrmIn->BufAttr.fragsize    = (pa_bytes_per_second(&pThisStrmIn->SampleSpec)
     719    pStrm->BufAttr.fragsize    = (pa_bytes_per_second(&pStrm->SampleSpec)
    666720                                   * s_pulseCfg.buffer_msecs_in) / 1000;
    667     pThisStrmIn->BufAttr.maxlength   = (pThisStrmIn->BufAttr.fragsize * 3) / 2;
     721    pStrm->BufAttr.maxlength   = (pStrm->BufAttr.fragsize * 3) / 2;
    668722    /* Note: Other members of pa_buffer_attr are ignored for record streams. */
    669723
    670724    char achName[64];
    671     RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pDrv->pszStreamName);
    672     int rc = drvHostPulseAudioOpen(true /* fIn */, achName, &pThisStrmIn->SampleSpec, &pThisStrmIn->BufAttr,
    673                                    &pThisStrmIn->pStream);
     725    RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pThis->pszStreamName);
     726
     727    int rc = paStreamOpen(pThis, true /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr,
     728                          &pStrm->pStream);
    674729    if (RT_FAILURE(rc))
    675730        return rc;
    676731
    677732    PDMAUDIOSTREAMCFG streamCfg;
    678     rc = drvHostPulseAudioPulseToFmt(pThisStrmIn->SampleSpec.format, &streamCfg.enmFormat,
    679                                      &streamCfg.enmEndianness);
     733    rc = paPulseToFmt(pStrm->SampleSpec.format, &streamCfg.enmFormat,
     734                      &streamCfg.enmEndianness);
    680735    if (RT_FAILURE(rc))
    681736    {
    682         LogRel(("PulseAudio: Cannot find audio capture format %ld\n", pThisStrmIn->SampleSpec.format));
     737        LogRel(("PulseAudio: Cannot find audio capture format %ld\n", pStrm->SampleSpec.format));
    683738        return rc;
    684739    }
    685740
    686     streamCfg.uHz       = pThisStrmIn->SampleSpec.rate;
    687     streamCfg.cChannels = pThisStrmIn->SampleSpec.channels;
     741    streamCfg.uHz       = pStrm->SampleSpec.rate;
     742    streamCfg.cChannels = pStrm->SampleSpec.channels;
    688743
    689744    rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
    690745    if (RT_SUCCESS(rc))
    691746    {
    692         uint32_t cSamples = RT_MIN(pThisStrmIn->BufAttr.fragsize * 10, pThisStrmIn->BufAttr.maxlength)
     747        uint32_t cSamples = RT_MIN(pStrm->BufAttr.fragsize * 10, pStrm->BufAttr.maxlength)
    693748                            >> pHstStrmIn->Props.cShift;
    694749        LogFunc(("cShift=%RU8, cSamples=%RU32\n", pHstStrmIn->Props.cShift, cSamples));
     
    698753
    699754        /* Save pointer to driver instance. */
    700         pThisStrmIn->pDrv = pDrv;
    701 
    702         pThisStrmIn->pu8PeekBuf = NULL;
     755        pStrm->pDrv = pThis;
     756
     757        pStrm->pu8PeekBuf = NULL;
    703758    }
    704759
     
    710765                                                    uint32_t *pcSamplesCaptured)
    711766{
    712     NOREF(pInterface);
     767    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    713768    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    714769    /* pcSamplesPlayed is optional. */
    715770
    716     PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn;
     771    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     772    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
    717773
    718774    /* We should only call pa_stream_readable_size() once and trust the first value. */
    719     pa_threaded_mainloop_lock(g_pMainLoop);
    720     size_t cbAvail = pa_stream_readable_size(pThisStrmIn->pStream);
    721     pa_threaded_mainloop_unlock(g_pMainLoop);
     775    pa_threaded_mainloop_lock(pThis->pMainLoop);
     776    size_t cbAvail = pa_stream_readable_size(pStrm->pStream);
     777    pa_threaded_mainloop_unlock(pThis->pMainLoop);
    722778
    723779    if (cbAvail == (size_t)-1)
    724         return drvHostPulseAudioError(pThisStrmIn->pDrv, "Failed to determine input data size");
     780        return paError(pStrm->pDrv, "Failed to determine input data size");
    725781
    726782    /* If the buffer was not dropped last call, add what remains. */
    727     if (pThisStrmIn->pu8PeekBuf)
    728     {
    729         Assert(pThisStrmIn->cbPeekBuf >= pThisStrmIn->offPeekBuf);
    730         cbAvail += (pThisStrmIn->cbPeekBuf - pThisStrmIn->offPeekBuf);
     783    if (pStrm->pu8PeekBuf)
     784    {
     785        Assert(pStrm->cbPeekBuf >= pStrm->offPeekBuf);
     786        cbAvail += (pStrm->cbPeekBuf - pStrm->offPeekBuf);
    731787    }
    732788
     
    739795
    740796    int rc = VINF_SUCCESS;
     797
    741798    size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
    742799
    743800    LogFlowFunc(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
    744                  cbToRead, cbAvail, pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf));
    745 
    746     size_t offWrite = 0;
     801                 cbToRead, cbAvail, pStrm->offPeekBuf, pStrm->cbPeekBuf));
     802
     803    size_t   offWrite      = 0;
    747804    uint32_t cWrittenTotal = 0;
    748805
     
    750807    {
    751808        /* If there is no data, do another peek. */
    752         if (!pThisStrmIn->pu8PeekBuf)
    753         {
    754             pa_threaded_mainloop_lock(g_pMainLoop);
    755             pa_stream_peek(pThisStrmIn->pStream,
    756                            (const void**)&pThisStrmIn->pu8PeekBuf, &pThisStrmIn->cbPeekBuf);
    757             pa_threaded_mainloop_unlock(g_pMainLoop);
    758 
    759             pThisStrmIn->offPeekBuf = 0;
     809        if (!pStrm->pu8PeekBuf)
     810        {
     811            pa_threaded_mainloop_lock(pThis->pMainLoop);
     812            pa_stream_peek(pStrm->pStream,
     813                           (const void**)&pStrm->pu8PeekBuf, &pStrm->cbPeekBuf);
     814            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     815
     816            pStrm->offPeekBuf = 0;
    760817
    761818            /* No data anymore?
    762819             * Note: If there's a data hole (cbPeekBuf then contains the length of the hole)
    763820             *       we need to drop the stream lateron. */
    764             if (   !pThisStrmIn->pu8PeekBuf
    765                 && !pThisStrmIn->cbPeekBuf)
     821            if (   !pStrm->pu8PeekBuf
     822                && !pStrm->cbPeekBuf)
    766823            {
    767824                break;
     
    769826        }
    770827
    771         Assert(pThisStrmIn->cbPeekBuf >= pThisStrmIn->offPeekBuf);
    772         size_t cbToWrite = RT_MIN(pThisStrmIn->cbPeekBuf - pThisStrmIn->offPeekBuf, cbToRead);
     828        Assert(pStrm->cbPeekBuf >= pStrm->offPeekBuf);
     829        size_t cbToWrite = RT_MIN(pStrm->cbPeekBuf - pStrm->offPeekBuf, cbToRead);
    773830
    774831        LogFlowFunc(("cbToRead=%zu, cbToWrite=%zu, offPeekBuf=%zu, cbPeekBuf=%zu, pu8PeekBuf=%p\n",
    775832                     cbToRead, cbToWrite,
    776                      pThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf, pThisStrmIn->pu8PeekBuf));
     833                     pStrm->offPeekBuf, pStrm->cbPeekBuf, pStrm->pu8PeekBuf));
    777834
    778835        if (cbToWrite)
     
    780837            uint32_t cWritten;
    781838            rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
    782                                       pThisStrmIn->pu8PeekBuf + pThisStrmIn->offPeekBuf,
     839                                      pStrm->pu8PeekBuf + pStrm->offPeekBuf,
    783840                                      cbToWrite, &cWritten);
    784841            if (RT_FAILURE(rc))
     
    790847            cbToRead -= cbWritten;
    791848            cWrittenTotal += cWritten;
    792             pThisStrmIn->offPeekBuf += cbWritten;
     849            pStrm->offPeekBuf += cbWritten;
    793850        }
    794851
     
    796853               !cbToWrite
    797854            /* Was there a hole in the peeking buffer? Drop it. */
    798             || !pThisStrmIn->pu8PeekBuf
     855            || !pStrm->pu8PeekBuf
    799856            /* If the buffer is done, drop it. */
    800             || pThisStrmIn->offPeekBuf == pThisStrmIn->cbPeekBuf)
    801         {
    802             pa_threaded_mainloop_lock(g_pMainLoop);
    803             pa_stream_drop(pThisStrmIn->pStream);
    804             pa_threaded_mainloop_unlock(g_pMainLoop);
    805 
    806             pThisStrmIn->pu8PeekBuf = NULL;
     857            || pStrm->offPeekBuf == pStrm->cbPeekBuf)
     858        {
     859            pa_threaded_mainloop_lock(pThis->pMainLoop);
     860            pa_stream_drop(pStrm->pStream);
     861            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     862
     863            pStrm->pu8PeekBuf = NULL;
    807864        }
    808865    }
     
    829886                                                  uint32_t *pcSamplesPlayed)
    830887{
    831     NOREF(pInterface);
     888    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    832889    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    833890    /* pcSamplesPlayed is optional. */
    834891
    835     PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut;
     892    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     893    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
    836894
    837895    int rc = VINF_SUCCESS;
     
    848906    }
    849907
    850     pa_threaded_mainloop_lock(g_pMainLoop);
     908    pa_threaded_mainloop_lock(pThis->pMainLoop);
    851909
    852910    do
    853911    {
    854         size_t cbWriteable = pa_stream_writable_size(pThisStrmOut->pStream);
     912        size_t cbWriteable = pa_stream_writable_size(pStrm->pStream);
    855913        if (cbWriteable == (size_t)-1)
    856914        {
    857             rc = drvHostPulseAudioError(pThisStrmOut->pDrv, "Failed to determine output data size");
     915            rc = paError(pStrm->pDrv, "Failed to determine output data size");
    858916            break;
    859917        }
     
    868926        while (cbToRead)
    869927        {
    870             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvPCMBuf,
    871                                      RT_MIN(cbToRead, pThisStrmOut->cbPCMBuf), &cRead);
     928            rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvPCMBuf,
     929                                     RT_MIN(cbToRead, pStrm->cbPCMBuf), &cRead);
    872930            if (   !cRead
    873931                || RT_FAILURE(rc))
     
    877935
    878936            cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
    879             if (pa_stream_write(pThisStrmOut->pStream, pThisStrmOut->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
     937            if (pa_stream_write(pStrm->pStream, pStrm->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
    880938                                0, PA_SEEK_RELATIVE) < 0)
    881939            {
    882                 rc = drvHostPulseAudioError(pThisStrmOut->pDrv, "Failed to write to output stream");
     940                rc = paError(pStrm->pDrv, "Failed to write to output stream");
    883941                break;
    884942            }
     
    894952    } while (0);
    895953
    896     pa_threaded_mainloop_unlock(g_pMainLoop);
     954    pa_threaded_mainloop_unlock(pThis->pMainLoop);
    897955
    898956    if (RT_SUCCESS(rc))
     
    913971
    914972/** @todo Implement va handling. */
    915 static int drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg)
     973static int paError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg)
    916974{
    917975    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    920978    if (pThis->cLogErrors++ < VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS)
    921979    {
    922         int rc2 = pa_context_errno(g_pContext);
     980        int rc2 = pa_context_errno(pThis->pContext);
    923981        LogRel(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2)));
    924982    }
     
    928986}
    929987
     988static DECLCALLBACK(void) paEnumSinkCb(pa_context *pCtx, const pa_sink_info *pInfo, int eol, void *pvUserData)
     989{
     990    if (eol != 0)
     991        return;
     992
     993    AssertPtrReturnVoid(pCtx);
     994    AssertPtrReturnVoid(pInfo);
     995
     996    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
     997    AssertPtrReturnVoid(pCbCtx);
     998    AssertPtrReturnVoid(pCbCtx->pDrv);
     999
     1000    LogRel2(("PulseAudio: Using output sink '%s'\n", pInfo->name));
     1001
     1002    /** @todo Store sinks + channel mapping in callback context as soon as we have surround support. */
     1003    pCbCtx->cDevOut++;
     1004
     1005    pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
     1006}
     1007
     1008static DECLCALLBACK(void) paEnumSourceCb(pa_context *pCtx, const pa_source_info *pInfo, int eol, void *pvUserData)
     1009{
     1010    if (eol != 0)
     1011        return;
     1012
     1013    AssertPtrReturnVoid(pCtx);
     1014    AssertPtrReturnVoid(pInfo);
     1015
     1016    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
     1017    AssertPtrReturnVoid(pCbCtx);
     1018    AssertPtrReturnVoid(pCbCtx->pDrv);
     1019
     1020    LogRel2(("PulseAudio: Using input source '%s'\n", pInfo->name));
     1021
     1022    /** @todo Store sources + channel mapping in callback context as soon as we have surround support. */
     1023    pCbCtx->cDevIn++;
     1024
     1025    pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
     1026}
     1027
     1028static DECLCALLBACK(void) paEnumServerCb(pa_context *pCtx, const pa_server_info *pInfo, void *pvUserData)
     1029{
     1030    AssertPtrReturnVoid(pCtx);
     1031    AssertPtrReturnVoid(pInfo);
     1032
     1033    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
     1034    AssertPtrReturnVoid(pCbCtx);
     1035
     1036    PDRVHOSTPULSEAUDIO pThis    = pCbCtx->pDrv;
     1037    AssertPtrReturnVoid(pThis);
     1038
     1039    if (pInfo->default_sink_name)
     1040    {
     1041        Assert(RTStrIsValidEncoding(pInfo->default_sink_name));
     1042        pCbCtx->pszDefaultSink   = RTStrDup(pInfo->default_sink_name);
     1043    }
     1044
     1045    if (pInfo->default_sink_name)
     1046    {
     1047        Assert(RTStrIsValidEncoding(pInfo->default_source_name));
     1048        pCbCtx->pszDefaultSource = RTStrDup(pInfo->default_source_name);
     1049    }
     1050
     1051    pa_threaded_mainloop_signal(pThis->pMainLoop, 0);
     1052}
     1053
     1054static int paEnumerate(PDRVHOSTPULSEAUDIO pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum)
     1055{
     1056    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1057    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
     1058
     1059    PDMAUDIOBACKENDCFG Cfg;
     1060    RT_ZERO(Cfg);
     1061
     1062    Cfg.cbStreamOut    = sizeof(PULSEAUDIOSTREAM);
     1063    Cfg.cbStreamIn     = sizeof(PULSEAUDIOSTREAM);
     1064    Cfg.cMaxStreamsOut = UINT32_MAX;
     1065    Cfg.cMaxStreamsIn  = UINT32_MAX;
     1066
     1067    PULSEAUDIOENUMCBCTX cbCtx;
     1068    RT_ZERO(cbCtx);
     1069
     1070    cbCtx.pDrv   = pThis;
     1071    cbCtx.fFlags = fEnum;
     1072
     1073    bool fLog = (fEnum & PULSEAUDIOENUMCBFLAGS_LOG);
     1074
     1075    int rc = paWaitFor(pThis, pa_context_get_server_info(pThis->pContext, paEnumServerCb, &cbCtx));
     1076    if (RT_SUCCESS(rc))
     1077    {
     1078        if (cbCtx.pszDefaultSink)
     1079        {
     1080            if (fLog)
     1081                LogRel2(("PulseAudio: Default output sink is '%s'\n", cbCtx.pszDefaultSink));
     1082
     1083            rc = paWaitFor(pThis, pa_context_get_sink_info_by_name(pThis->pContext, cbCtx.pszDefaultSink,
     1084                                                                   paEnumSinkCb, &cbCtx));
     1085            if (   RT_FAILURE(rc)
     1086                && fLog)
     1087            {
     1088                LogRel(("PulseAudio: Error enumerating properties for default output sink '%s'\n", cbCtx.pszDefaultSink));
     1089            }
     1090        }
     1091        else if (fLog)
     1092            LogRel2(("PulseAudio: No default output sink found\n"));
     1093
     1094        if (RT_SUCCESS(rc))
     1095        {
     1096            if (cbCtx.pszDefaultSource)
     1097            {
     1098                if (fLog)
     1099                    LogRel2(("PulseAudio: Default input source is '%s'\n", cbCtx.pszDefaultSource));
     1100
     1101                rc = paWaitFor(pThis, pa_context_get_source_info_by_name(pThis->pContext, cbCtx.pszDefaultSource,
     1102                                                                         paEnumSourceCb, &cbCtx));
     1103                if (   RT_FAILURE(rc)
     1104                    && fLog)
     1105                {
     1106                    LogRel(("PulseAudio: Error enumerating properties for default input source '%s'\n", cbCtx.pszDefaultSource));
     1107                }
     1108            }
     1109            else if (fLog)
     1110                LogRel2(("PulseAudio: No default input source found\n"));
     1111        }
     1112
     1113        if (RT_SUCCESS(rc))
     1114        {
     1115            Cfg.cSinks   = cbCtx.cDevOut;
     1116            Cfg.cSources = cbCtx.cDevIn;
     1117
     1118            if (fLog)
     1119            {
     1120                LogRel2(("PulseAudio: Found %RU8 host playback device(s)\n",  cbCtx.cDevOut));
     1121                LogRel2(("PulseAudio: Found %RU8 host capturing device(s)\n", cbCtx.cDevIn));
     1122            }
     1123
     1124            if (pCfg)
     1125                memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG));
     1126        }
     1127
     1128        if (cbCtx.pszDefaultSink)
     1129        {
     1130            RTStrFree(cbCtx.pszDefaultSink);
     1131            cbCtx.pszDefaultSink = NULL;
     1132        }
     1133
     1134        if (cbCtx.pszDefaultSource)
     1135        {
     1136            RTStrFree(cbCtx.pszDefaultSource);
     1137            cbCtx.pszDefaultSource = NULL;
     1138        }
     1139    }
     1140    else if (fLog)
     1141        LogRel(("PulseAudio: Error enumerating PulseAudio server properties\n"));
     1142
     1143    LogFlowFuncLeaveRC(rc);
     1144    return rc;
     1145}
     1146
    9301147static DECLCALLBACK(int) drvHostPulseAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    9311148{
    932     NOREF(pInterface);
     1149    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    9331150    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    9341151
     1152    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1153    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
     1154
    9351155    LogFlowFuncEnter();
    9361156
    937     PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn;
    938     if (pThisStrmIn->pStream)
    939     {
    940         pa_threaded_mainloop_lock(g_pMainLoop);
    941         pa_stream_disconnect(pThisStrmIn->pStream);
    942         pa_stream_unref(pThisStrmIn->pStream);
    943         pa_threaded_mainloop_unlock(g_pMainLoop);
    944 
    945         pThisStrmIn->pStream = NULL;
     1157    if (pStrm->pStream)
     1158    {
     1159        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1160        pa_stream_disconnect(pStrm->pStream);
     1161        pa_stream_unref(pStrm->pStream);
     1162        pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1163
     1164        pStrm->pStream = NULL;
    9461165    }
    9471166
     
    9511170static DECLCALLBACK(int) drvHostPulseAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    9521171{
    953     NOREF(pInterface);
     1172    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    9541173    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    9551174
     1175    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1176    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     1177
    9561178    LogFlowFuncEnter();
    9571179
    958     PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut;
    959     if (pThisStrmOut->pStream)
    960     {
    961         pa_threaded_mainloop_lock(g_pMainLoop);
    962         pa_stream_disconnect(pThisStrmOut->pStream);
    963         pa_stream_unref(pThisStrmOut->pStream);
    964         pa_threaded_mainloop_unlock(g_pMainLoop);
    965 
    966         pThisStrmOut->pStream = NULL;
    967     }
    968 
    969     if (pThisStrmOut->pvPCMBuf)
    970     {
    971         RTMemFree(pThisStrmOut->pvPCMBuf);
    972         pThisStrmOut->pvPCMBuf = NULL;
    973 
    974         pThisStrmOut->cbPCMBuf = 0;
     1180    if (pStrm->pStream)
     1181    {
     1182        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1183        pa_stream_disconnect(pStrm->pStream);
     1184        pa_stream_unref(pStrm->pStream);
     1185        pa_threaded_mainloop_unlock(pThis->pMainLoop);
     1186
     1187        pStrm->pStream = NULL;
     1188    }
     1189
     1190    if (pStrm->pvPCMBuf)
     1191    {
     1192        RTMemFree(pStrm->pvPCMBuf);
     1193        pStrm->pvPCMBuf = NULL;
     1194        pStrm->cbPCMBuf = 0;
    9751195    }
    9761196
     
    9811201                                                     PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)
    9821202{
    983     NOREF(pInterface);
     1203    AssertPtrReturn(pInterface , VERR_INVALID_POINTER);
    9841204    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    9851205
    986     PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut;
     1206    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1207    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     1208
    9871209    int rc = VINF_SUCCESS;
    9881210
     
    9941216        case PDMAUDIOSTREAMCMD_RESUME:
    9951217        {
    996             pa_threaded_mainloop_lock(g_pMainLoop);
    997 
    998             if (   pThisStrmOut->pDrainOp
    999                 && pa_operation_get_state(pThisStrmOut->pDrainOp) != PA_OPERATION_DONE)
     1218            pa_threaded_mainloop_lock(pThis->pMainLoop);
     1219
     1220            if (   pStrm->pDrainOp
     1221                && pa_operation_get_state(pStrm->pDrainOp) != PA_OPERATION_DONE)
    10001222            {
    1001                 pa_operation_cancel(pThisStrmOut->pDrainOp);
    1002                 pa_operation_unref(pThisStrmOut->pDrainOp);
    1003 
    1004                 pThisStrmOut->pDrainOp = NULL;
     1223                pa_operation_cancel(pStrm->pDrainOp);
     1224                pa_operation_unref(pStrm->pDrainOp);
     1225
     1226                pStrm->pDrainOp = NULL;
    10051227            }
    10061228            else
    10071229            {
    1008                 /* This should return immediately. */
    1009                 rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmOut->pStream, 0,
    1010                                                              drvHostPulseAudioCbSuccess, pThisStrmOut),
    1011                                               15 * 1000 /* 15s timeout */);
     1230                rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0, paStreamCbSuccess, pStrm));
    10121231            }
    10131232
    1014             pa_threaded_mainloop_unlock(g_pMainLoop);
     1233            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    10151234            break;
    10161235        }
     
    10211240            /* Pause audio output (the Pause bit of the AC97 x_CR register is set).
    10221241             * Note that we must return immediately from here! */
    1023             pa_threaded_mainloop_lock(g_pMainLoop);
    1024             if (!pThisStrmOut->pDrainOp)
     1242            pa_threaded_mainloop_lock(pThis->pMainLoop);
     1243            if (!pStrm->pDrainOp)
    10251244            {
    1026                 /* This should return immediately. */
    1027                 rc = drvHostPulseAudioWaitFor(pa_stream_trigger(pThisStrmOut->pStream,
    1028                                                                 drvHostPulseAudioCbSuccess, pThisStrmOut),
    1029                                               15 * 1000 /* 15s timeout */);
     1245                rc = paWaitFor(pThis, pa_stream_trigger(pStrm->pStream, paStreamCbSuccess, pStrm));
    10301246                if (RT_LIKELY(RT_SUCCESS(rc)))
    1031                     pThisStrmOut->pDrainOp = pa_stream_drain(pThisStrmOut->pStream,
    1032                                                              drvHostPulseAudioCbStreamDrain, pThisStrmOut);
     1247                    pStrm->pDrainOp = pa_stream_drain(pStrm->pStream, paStreamCbDrain, pStrm);
    10331248            }
    1034             pa_threaded_mainloop_unlock(g_pMainLoop);
     1249            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    10351250            break;
    10361251        }
     
    10491264                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
    10501265{
    1051     NOREF(pInterface);
     1266    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    10521267    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    10531268
    1054     PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn;
     1269    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1270    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
     1271
    10551272    int rc = VINF_SUCCESS;
    10561273
     
    10621279        case PDMAUDIOSTREAMCMD_RESUME:
    10631280        {
    1064             pa_threaded_mainloop_lock(g_pMainLoop);
    1065             /* This should return immediately. */
    1066             rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmIn->pStream, 0 /* Play / resume */,
    1067                                                          drvHostPulseAudioCbSuccess, pThisStrmIn),
    1068                                           15 * 1000 /* 15s timeout */);
    1069             pa_threaded_mainloop_unlock(g_pMainLoop);
     1281            pa_threaded_mainloop_lock(pThis->pMainLoop);
     1282            rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0 /* Play / resume */, paStreamCbSuccess, pStrm));
     1283            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    10701284            break;
    10711285        }
     
    10741288        case PDMAUDIOSTREAMCMD_PAUSE:
    10751289        {
    1076             pa_threaded_mainloop_lock(g_pMainLoop);
    1077             if (pThisStrmIn->pu8PeekBuf) /* Do we need to drop the peek buffer?*/
     1290            pa_threaded_mainloop_lock(pThis->pMainLoop);
     1291            if (pStrm->pu8PeekBuf) /* Do we need to drop the peek buffer?*/
    10781292            {
    1079                 pa_stream_drop(pThisStrmIn->pStream);
    1080                 pThisStrmIn->pu8PeekBuf = NULL;
     1293                pa_stream_drop(pStrm->pStream);
     1294                pStrm->pu8PeekBuf = NULL;
    10811295            }
    1082             /* This should return immediately. */
    1083             rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmIn->pStream, 1 /* Stop / pause */,
    1084                                                          drvHostPulseAudioCbSuccess, pThisStrmIn),
    1085                                           15 * 1000 /* 15s timeout */);
    1086             pa_threaded_mainloop_unlock(g_pMainLoop);
     1296
     1297            rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm));
     1298            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    10871299            break;
    10881300        }
     
    10991311static DECLCALLBACK(int) drvHostPulseAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    11001312{
    1101     NOREF(pInterface);
    1102     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    1103 
    1104     pCfg->cbStreamOut     = sizeof(PULSEAUDIOSTREAM);
    1105     pCfg->cbStreamIn      = sizeof(PULSEAUDIOSTREAM);
    1106     pCfg->cMaxHstStrmsOut = UINT32_MAX;
    1107     pCfg->cMaxHstStrmsIn  = UINT32_MAX;
    1108 
    1109     return VINF_SUCCESS;
     1313    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1314    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1315
     1316    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1317
     1318    return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);
    11101319}
    11111320
    11121321static DECLCALLBACK(void) drvHostPulseAudioShutdown(PPDMIHOSTAUDIO pInterface)
    11131322{
    1114     NOREF(pInterface);
     1323    AssertPtrReturnVoid(pInterface);
     1324
     1325    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    11151326
    11161327    LogFlowFuncEnter();
    11171328
    1118     if (g_pMainLoop)
    1119         pa_threaded_mainloop_stop(g_pMainLoop);
    1120 
    1121     if (g_pContext)
    1122     {
    1123         pa_context_disconnect(g_pContext);
    1124         pa_context_unref(g_pContext);
    1125         g_pContext = NULL;
    1126     }
    1127 
    1128     if (g_pMainLoop)
    1129     {
    1130         pa_threaded_mainloop_free(g_pMainLoop);
    1131         g_pMainLoop = NULL;
     1329    if (pThis->pMainLoop)
     1330        pa_threaded_mainloop_stop(pThis->pMainLoop);
     1331
     1332    if (pThis->pContext)
     1333    {
     1334        pa_context_disconnect(pThis->pContext);
     1335        pa_context_unref(pThis->pContext);
     1336        pThis->pContext = NULL;
     1337    }
     1338
     1339    if (pThis->pMainLoop)
     1340    {
     1341        pa_threaded_mainloop_free(pThis->pMainLoop);
     1342        pThis->pMainLoop = NULL;
    11321343    }
    11331344
  • trunk/src/VBox/Devices/Audio/alsa_mangling.h

    r56292 r59987  
    66
    77/*
    8  * Copyright (C) 2013-2015 Oracle Corporation
     8 * Copyright (C) 2013-2016 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121
    2222#define ALSA_MANGLER(symbol) VBox_##symbol
     23
     24#define snd_device_name_hint                    ALSA_MANGLER(snd_device_name_hint)
     25#define snd_device_name_get_hint                ALSA_MANGLER(snd_device_name_get_hint)
     26#define snd_device_name_free_hint               ALSA_MANGLER(snd_device_name_free_hint)
    2327
    2428#define snd_pcm_hw_params_any                   ALSA_MANGLER(snd_pcm_hw_params_any)
  • trunk/src/VBox/Devices/Audio/alsa_stubs.c

    r56648 r59987  
    55
    66/*
    7  * Copyright (C) 2006-2015 Oracle Corporation
     7 * Copyright (C) 2006-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3535        return pfn_ ## function shortsig; \
    3636    }
     37
     38PROXY_STUB(snd_device_name_hint, int,
     39           (int card, const char *iface, void ***hints),
     40           (card, iface, hints))
     41PROXY_STUB(snd_device_name_free_hint, int,
     42           (void ***hints),
     43           (hints))
     44PROXY_STUB(snd_device_name_get_hint, char *,
     45           (const void *hint, const char *id),
     46           (hint, id))
    3747
    3848PROXY_STUB(snd_pcm_hw_params_any, int,
     
    118128static SHARED_FUNC SharedFuncs[] =
    119129{
     130    ELEMENT(snd_device_name_hint),
     131    ELEMENT(snd_device_name_get_hint),
     132    ELEMENT(snd_device_name_free_hint),
     133
    120134    ELEMENT(snd_pcm_hw_params_any),
    121135    ELEMENT(snd_pcm_close),
  • trunk/src/VBox/Devices/Audio/pulse_mangling.h

    r56292 r59987  
    66
    77/*
    8  * Copyright (C) 2013-2015 Oracle Corporation
     8 * Copyright (C) 2013-2016 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4242#define pa_context_connect                      PULSE_MANGLER(pa_context_connect)
    4343#define pa_context_disconnect                   PULSE_MANGLER(pa_context_disconnect)
     44#define pa_context_get_server_info              PULSE_MANGLER(pa_context_get_server_info)
     45#define pa_context_get_sink_info_by_name        PULSE_MANGLER(pa_context_get_sink_info_by_name)
     46#define pa_context_get_source_info_by_name      PULSE_MANGLER(pa_context_get_source_info_by_name)
    4447#define pa_context_get_state                    PULSE_MANGLER(pa_context_get_state)
    4548#define pa_context_unref                        PULSE_MANGLER(pa_context_unref)
  • trunk/src/VBox/Devices/Audio/pulse_stubs.c

    r56648 r59987  
    55
    66/*
    7  * Copyright (C) 2006-2015 Oracle Corporation
     7 * Copyright (C) 2006-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    111111                (p))
    112112PROXY_STUB     (pa_context_connect, int,
    113                 (pa_context *c, const char *server, pa_context_flags_t flags,
    114                  const pa_spawn_api *api),
     113                (pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api),
    115114                (c, server, flags, api))
    116115PROXY_STUB_VOID(pa_context_disconnect,
    117116                (pa_context *c),
    118117                (c))
     118PROXY_STUB     (pa_context_get_server_info, pa_operation*,
     119                (pa_context *c, const char *name, pa_server_info_cb_t cb, void *userdata),
     120                (c, name, cb, userdata))
     121PROXY_STUB     (pa_context_get_sink_info_by_name, pa_operation*,
     122                (pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata),
     123                (c, name, cb, userdata))
     124PROXY_STUB     (pa_context_get_source_info_by_name, pa_operation*,
     125                (pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata),
     126                (c, name, cb, userdata))
    119127PROXY_STUB     (pa_context_get_state, pa_context_state_t,
    120128                (pa_context *c),
     
    220228    ELEMENT(pa_context_connect),
    221229    ELEMENT(pa_context_disconnect),
     230    ELEMENT(pa_context_get_server_info),
     231    ELEMENT(pa_context_get_sink_info_by_name),
     232    ELEMENT(pa_context_get_source_info_by_name),
    222233    ELEMENT(pa_context_get_state),
    223234    ELEMENT(pa_context_unref),
     
    285296    return rc;
    286297}
    287 
Note: See TracChangeset for help on using the changeset viewer.

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