VirtualBox

Changeset 88477 in vbox for trunk


Ignore:
Timestamp:
Apr 12, 2021 11:00:05 PM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioPulseAudio: Cleaned up drvHostAudioPaHA_GetConfig and its 'enumeration' code (mostly pointless in its present form). bugref:9890

File:
1 edited

Legend:

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

    r88467 r88477  
    5353#define VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS  64
    5454
     55
     56/** @name PULSEAUDIOENUMCBFLAGS_XXX
     57 * @{ */
    5558/** No flags specified. */
    5659#define PULSEAUDIOENUMCBFLAGS_NONE          0
    5760/** (Release) log found devices. */
    5861#define PULSEAUDIOENUMCBFLAGS_LOG           RT_BIT(0)
     62/** @} */
    5963
    6064
     
    6266*   Structures                                                                                                                   *
    6367*********************************************************************************************************************************/
     68/** Pointer to the instance data for a pulse audio host audio driver. */
     69typedef struct DRVHOSTPULSEAUDIO *PDRVHOSTPULSEAUDIO;
     70
     71
    6472/**
    6573 * Callback context for the server init context state changed callback.
     
    6876{
    6977    /** The event semaphore. */
    70     RTSEMEVENT                      hEvtInit;
     78    RTSEMEVENT                  hEvtInit;
    7179    /** The returned context state. */
    72     volatile pa_context_state_t    enmCtxState;
     80    pa_context_state_t volatile enmCtxState;
    7381} PULSEAUDIOSTATECHGCTX;
    7482/** Pointer to a server init context state changed callback context. */
    7583typedef PULSEAUDIOSTATECHGCTX *PPULSEAUDIOSTATECHGCTX;
    7684
    77 /**
    78  * Host Pulse audio driver instance data.
    79  * @implements PDMIAUDIOCONNECTOR
    80  */
    81 typedef struct DRVHOSTPULSEAUDIO
    82 {
    83     /** Pointer to the driver instance structure. */
    84     PPDMDRVINS            pDrvIns;
     85
     86/**
     87 * Enumeration callback context used by the pfnGetConfig code.
     88 */
     89typedef struct PULSEAUDIOENUMCBCTX
     90{
     91    /** Pointer to host backend driver. */
     92    PDRVHOSTPULSEAUDIO      pDrv;
    8593    /** Pointer to PulseAudio's threaded main loop. */
    86     pa_threaded_mainloop *pMainLoop;
    87     /**
    88     * Pointer to our PulseAudio context.
    89     * Note: We use a pMainLoop in a separate thread (pContext).
    90     *       So either use callback functions or protect these functions
    91     *       by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock().
    92     */
    93     pa_context           *pContext;
    94     /** Shutdown indicator. */
    95     volatile bool         fAbortLoop;
    96     /** Enumeration operation successful? */
    97     volatile bool         fEnumOpSuccess;
    98     /** Pointer to host audio interface. */
    99     PDMIHOSTAUDIO         IHostAudio;
    100     /** Error count for not flooding the release log.
    101      *  Specify UINT32_MAX for unlimited logging. */
    102     uint32_t              cLogErrors;
    103     /** The stream (base) name; needed for distinguishing
    104      *  streams in the PulseAudio mixer controls if multiple
    105      *  VMs are running at the same time. */
    106     char                  szStreamName[64];
    107 
    108     /** Don't want to put this on the stack... */
    109     PULSEAUDIOSTATECHGCTX   InitStateChgCtx;
    110 } DRVHOSTPULSEAUDIO, *PDRVHOSTPULSEAUDIO;
    111 
     94    pa_threaded_mainloop   *pMainLoop;
     95    /** Enumeration flags, PULSEAUDIOENUMCBFLAGS_XXX. */
     96    uint32_t                fFlags;
     97    /** VBox status code for the operation. */
     98    int32_t                 rcEnum;
     99    /** Number of found input devices. */
     100    uint8_t                 cDevIn;
     101    /** Number of found output devices. */
     102    uint8_t                 cDevOut;
     103    /** Name of default sink being used. Must be free'd using RTStrFree(). */
     104    char                   *pszDefaultSink;
     105    /** Name of default source being used. Must be free'd using RTStrFree(). */
     106    char                   *pszDefaultSource;
     107} PULSEAUDIOENUMCBCTX;
     108/** Pointer to an enumeration callback context. */
     109typedef PULSEAUDIOENUMCBCTX *PPULSEAUDIOENUMCBCTX;
     110
     111
     112/**
     113 * Pulse audio stream data.
     114 */
    112115typedef struct PULSEAUDIOSTREAM
    113116{
     
    141144    pa_usec_t              tsLastReadWrittenUs;
    142145#endif
    143 } PULSEAUDIOSTREAM, *PPULSEAUDIOSTREAM;
    144 
    145 /**
    146  * Callback context for server enumeration callbacks.
    147  */
    148 typedef struct PULSEAUDIOENUMCBCTX
    149 {
    150     /** Pointer to host backend driver. */
    151     PDRVHOSTPULSEAUDIO  pDrv;
    152     /** Enumeration flags. */
    153     uint32_t            fFlags;
    154     /** Number of found input devices. */
    155     uint8_t             cDevIn;
    156     /** Number of found output devices. */
    157     uint8_t             cDevOut;
    158     /** Name of default sink being used. Must be free'd using RTStrFree(). */
    159     char               *pszDefaultSink;
    160     /** Name of default source being used. Must be free'd using RTStrFree(). */
    161     char               *pszDefaultSource;
    162 } PULSEAUDIOENUMCBCTX, *PPULSEAUDIOENUMCBCTX;
     146} PULSEAUDIOSTREAM;
     147/** Pointer to pulse audio stream data. */
     148typedef PULSEAUDIOSTREAM *PPULSEAUDIOSTREAM;
     149
     150
     151/**
     152 * Pulse audio host audio driver instance data.
     153 * @implements PDMIAUDIOCONNECTOR
     154 */
     155typedef struct DRVHOSTPULSEAUDIO
     156{
     157    /** Pointer to the driver instance structure. */
     158    PPDMDRVINS              pDrvIns;
     159    /** Pointer to PulseAudio's threaded main loop. */
     160    pa_threaded_mainloop   *pMainLoop;
     161    /**
     162     * Pointer to our PulseAudio context.
     163     * @note We use a pMainLoop in a separate thread (pContext).
     164     *       So either use callback functions or protect these functions
     165     *       by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock().
     166     */
     167    pa_context             *pContext;
     168    /** Shutdown indicator. */
     169    volatile bool           fAbortLoop;
     170    /** Error count for not flooding the release log.
     171     *  Specify UINT32_MAX for unlimited logging. */
     172    uint32_t                cLogErrors;
     173    /** The stream (base) name; needed for distinguishing
     174     *  streams in the PulseAudio mixer controls if multiple
     175     *  VMs are running at the same time. */
     176    char                    szStreamName[64];
     177    /** Don't want to put this on the stack... */
     178    PULSEAUDIOSTATECHGCTX   InitStateChgCtx;
     179    /** Pointer to host audio interface. */
     180    PDMIHOSTAUDIO           IHostAudio;
     181} DRVHOSTPULSEAUDIO;
    163182
    164183
     
    212231static void drvHostAudioPaSignalWaiter(PDRVHOSTPULSEAUDIO pThis)
    213232{
    214     if (!pThis)
    215         return;
    216 
    217     pThis->fAbortLoop = true;
    218     pa_threaded_mainloop_signal(pThis->pMainLoop, 0);
     233    if (pThis)
     234    {
     235        pThis->fAbortLoop = true;
     236        pa_threaded_mainloop_signal(pThis->pMainLoop, 0);
     237    }
    219238}
    220239
     
    276295    while (pa_operation_get_state(pOP) == PA_OPERATION_RUNNING)
    277296    {
    278         if (!pThis->fAbortLoop)
     297        if (!pThis->fAbortLoop) /** @todo r=bird: I do _not_ get the logic behind this fAbortLoop mechanism, it looks more
     298                                 * than a little mixed up and too much generalized see drvHostAudioPaSignalWaiter. */
    279299        {
    280300            AssertPtr(pThis->pMainLoop);
     
    283303                || pa_context_get_state(pThis->pContext) != PA_CONTEXT_READY)
    284304            {
     305                pa_operation_cancel(pOP);
    285306                LogRel(("PulseAudio: pa_context_get_state context not ready\n"));
     307                rc = VERR_INVALID_STATE;
    286308                break;
    287309            }
     
    292314        if (u64ElapsedMs >= cMsTimeout)
    293315        {
     316            pa_operation_cancel(pOP);
    294317            rc = VERR_TIMEOUT;
    295318            break;
     
    309332
    310333
    311 static void drvHostAudioPaEnumSinkCallback(pa_context *pCtx, const pa_sink_info *pInfo, int eol, void *pvUserData)
    312 {
    313     if (eol > 0)
    314         return;
    315 
     334
     335/*********************************************************************************************************************************
     336*   PDMIHOSTAUDIO                                                                                                                *
     337*********************************************************************************************************************************/
     338
     339/**
     340 * Enumeration callback - source info.
     341 *
     342 * @param   pCtx        The context (DRVHOSTPULSEAUDIO::pContext).
     343 * @param   pInfo       The info.  NULL when @a eol is not zero.
     344 * @param   eol         Error-or-last indicator or something like that:
     345 *                          -  0: Normal call with info.
     346 *                          -  1: End of list, no info.
     347 *                          - -1: Error callback, no info.
     348 */
     349static void drvHostAudioPaEnumSourceCallback(pa_context *pCtx, const pa_source_info *pInfo, int eol, void *pvUserData)
     350{
     351    LogFlowFunc(("pCtx=%p pInfo=%p eol=%d pvUserData=%p\n", pCtx, pInfo, eol, pvUserData));
    316352    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
    317353    AssertPtrReturnVoid(pCbCtx);
    318     PDRVHOSTPULSEAUDIO pThis = pCbCtx->pDrv;
    319     AssertPtrReturnVoid(pThis);
    320     if (eol < 0)
    321     {
    322         pThis->fEnumOpSuccess = false;
    323         pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
    324         return;
    325     }
    326 
    327     AssertPtrReturnVoid(pCtx);
    328     AssertPtrReturnVoid(pInfo);
    329 
    330     LogRel2(("PulseAudio: Using output sink '%s'\n", pInfo->name));
    331 
    332     /** @todo Store sinks + channel mapping in callback context as soon as we have surround support. */
    333     pCbCtx->cDevOut++;
    334 
    335     pThis->fEnumOpSuccess = true;
    336     pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
    337 }
    338 
    339 
    340 static void drvHostAudioPaEnumSourceCallback(pa_context *pCtx, const pa_source_info *pInfo, int eol, void *pvUserData)
    341 {
    342     if (eol > 0)
    343         return;
    344 
     354    Assert((pInfo == NULL) == (eol != 0));
     355    RT_NOREF(pCtx);
     356
     357    if (eol == 0 && pInfo != NULL)
     358    {
     359        LogRel2(("PulseAudio: Using input source '%s'\n", pInfo->name));
     360        /** @todo Store sources + channel mapping in callback context as soon as we have surround support. */
     361        pCbCtx->cDevIn++;
     362        pCbCtx->rcEnum = VINF_SUCCESS;
     363    }
     364
     365    /* Wake up the calling thread when done: */
     366    if (eol != 0)
     367        pa_threaded_mainloop_signal(pCbCtx->pMainLoop, 0);
     368}
     369
     370
     371/**
     372 * Enumeration callback - sink info.
     373 *
     374 * @param   pCtx        The context (DRVHOSTPULSEAUDIO::pContext).
     375 * @param   pInfo       The info.  NULL when @a eol is not zero.
     376 * @param   eol         Error-or-last indicator or something like that:
     377 *                          -  0: Normal call with info.
     378 *                          -  1: End of list, no info.
     379 *                          - -1: Error callback, no info.
     380 */
     381static void drvHostAudioPaEnumSinkCallback(pa_context *pCtx, const pa_sink_info *pInfo, int eol, void *pvUserData)
     382{
     383    LogFlowFunc(("pCtx=%p pInfo=%p eol=%d pvUserData=%p\n", pCtx, pInfo, eol, pvUserData));
    345384    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
    346385    AssertPtrReturnVoid(pCbCtx);
    347     PDRVHOSTPULSEAUDIO pThis = pCbCtx->pDrv;
    348     AssertPtrReturnVoid(pThis);
    349     if (eol < 0)
    350     {
    351         pThis->fEnumOpSuccess = false;
    352         pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
    353         return;
    354     }
    355 
    356     AssertPtrReturnVoid(pCtx);
    357     AssertPtrReturnVoid(pInfo);
    358 
    359     LogRel2(("PulseAudio: Using input source '%s'\n", pInfo->name));
    360 
    361     /** @todo Store sources + channel mapping in callback context as soon as we have surround support. */
    362     pCbCtx->cDevIn++;
    363 
    364     pThis->fEnumOpSuccess = true;
    365     pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
    366 }
    367 
    368 
     386    Assert((pInfo == NULL) == (eol != 0));
     387    RT_NOREF(pCtx);
     388
     389    if (eol == 0 && pInfo != NULL)
     390    {
     391        LogRel2(("PulseAudio: Using output sink '%s'\n", pInfo->name));
     392        /** @todo Store sinks + channel mapping in callback context as soon as we have surround support. */
     393        pCbCtx->cDevOut++;
     394        pCbCtx->rcEnum = VINF_SUCCESS;
     395    }
     396
     397    /* Wake up the calling thread when done: */
     398    if (eol != 0)
     399        pa_threaded_mainloop_signal(pCbCtx->pMainLoop, 0);
     400}
     401
     402
     403/**
     404 * Enumeration callback - service info.
     405 *
     406 * Copy down the default names.
     407 */
    369408static void drvHostAudioPaEnumServerCallback(pa_context *pCtx, const pa_server_info *pInfo, void *pvUserData)
    370409{
    371     AssertPtrReturnVoid(pCtx);
     410    LogFlowFunc(("pCtx=%p pInfo=%p pvUserData=%p\n", pCtx, pInfo, pvUserData));
    372411    PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData;
    373412    AssertPtrReturnVoid(pCbCtx);
    374     PDRVHOSTPULSEAUDIO pThis = pCbCtx->pDrv;
    375     AssertPtrReturnVoid(pThis);
    376 
    377     if (!pInfo)
    378     {
    379         pThis->fEnumOpSuccess = false;
    380         pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0);
    381         return;
    382     }
    383 
    384     if (pInfo->default_sink_name)
    385     {
    386         Assert(RTStrIsValidEncoding(pInfo->default_sink_name));
    387         pCbCtx->pszDefaultSink   = RTStrDup(pInfo->default_sink_name);
    388     }
    389 
    390     if (pInfo->default_sink_name)
    391     {
    392         Assert(RTStrIsValidEncoding(pInfo->default_source_name));
    393         pCbCtx->pszDefaultSource = RTStrDup(pInfo->default_source_name);
    394     }
    395 
    396     pThis->fEnumOpSuccess = true;
    397     pa_threaded_mainloop_signal(pThis->pMainLoop, 0);
    398 }
    399 
    400 
     413    RT_NOREF(pCtx);
     414
     415    if (pInfo)
     416    {
     417        LogRel2(("PulseAudio: Server info: user=%s host=%s ver=%s name=%s defsink=%s defsrc=%s spec: %d %uHz %uch\n",
     418                 pInfo->user_name, pInfo->host_name, pInfo->server_version, pInfo->server_name,
     419                 pInfo->default_sink_name, pInfo->default_source_name,
     420                 pInfo->sample_spec.format, pInfo->sample_spec.rate, pInfo->sample_spec.channels));
     421
     422        pCbCtx->rcEnum = VINF_SUCCESS;
     423
     424        if (pInfo->default_sink_name)
     425        {
     426            Assert(RTStrIsValidEncoding(pInfo->default_sink_name));
     427            pCbCtx->pszDefaultSink = RTStrDup(pInfo->default_sink_name);
     428            AssertStmt(pCbCtx->pszDefaultSink, pCbCtx->rcEnum = VERR_NO_STR_MEMORY);
     429        }
     430
     431        if (pInfo->default_source_name)
     432        {
     433            Assert(RTStrIsValidEncoding(pInfo->default_source_name));
     434            pCbCtx->pszDefaultSource = RTStrDup(pInfo->default_source_name);
     435            AssertStmt(pCbCtx->pszDefaultSource, pCbCtx->rcEnum = VERR_NO_STR_MEMORY);
     436        }
     437    }
     438    else
     439        pCbCtx->rcEnum = VERR_INVALID_POINTER;
     440
     441    pa_threaded_mainloop_signal(pCbCtx->pMainLoop, 0);
     442}
     443
     444
     445/**
     446 * @note Called with the PA main loop locked.
     447 */
    401448static int drvHostAudioPaEnumerate(PDRVHOSTPULSEAUDIO pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum)
    402449{
    403     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    404     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    405 
    406     PDMAUDIOBACKENDCFG Cfg;
    407     RT_ZERO(Cfg);
    408 
    409     RTStrPrintf2(Cfg.szName, sizeof(Cfg.szName), "PulseAudio");
    410 
    411     Cfg.cbStreamOut    = sizeof(PULSEAUDIOSTREAM);
    412     Cfg.cbStreamIn     = sizeof(PULSEAUDIOSTREAM);
    413     Cfg.cMaxStreamsOut = UINT32_MAX;
    414     Cfg.cMaxStreamsIn  = UINT32_MAX;
    415 
    416     PULSEAUDIOENUMCBCTX CbCtx;
    417     RT_ZERO(CbCtx);
    418 
    419     CbCtx.pDrv   = pThis;
    420     CbCtx.fFlags = fEnum;
    421 
    422     bool fLog = (fEnum & PULSEAUDIOENUMCBFLAGS_LOG);
    423 
    424     pa_threaded_mainloop_lock(pThis->pMainLoop);
    425 
    426     pThis->fEnumOpSuccess = false;
    427 
     450    PULSEAUDIOENUMCBCTX CbCtx = { pThis, pThis->pMainLoop, fEnum, VERR_AUDIO_BACKEND_INIT_FAILED, 0, 0, NULL, NULL };
     451    bool const          fLog  = (fEnum & PULSEAUDIOENUMCBFLAGS_LOG);
     452    int                 rc;
     453
     454    /*
     455     * Check if server information is available and bail out early if it isn't.
     456     * This should give us a default (playback) sink and (recording) source.
     457     */
    428458    LogRel(("PulseAudio: Retrieving server information ...\n"));
    429 
    430     /* Check if server information is available and bail out early if it isn't. */
     459    CbCtx.rcEnum = VERR_AUDIO_BACKEND_INIT_FAILED;
    431460    pa_operation *paOpServerInfo = pa_context_get_server_info(pThis->pContext, drvHostAudioPaEnumServerCallback, &CbCtx);
    432     if (!paOpServerInfo)
    433     {
    434         pa_threaded_mainloop_unlock(pThis->pMainLoop);
    435 
    436         LogRel(("PulseAudio: Server information not available, skipping enumeration\n"));
     461    if (paOpServerInfo)
     462        rc = drvHostAudioPaWaitFor(pThis, paOpServerInfo);
     463    else
     464    {
     465        LogRel(("PulseAudio: Server information not available, skipping enumeration.\n"));
    437466        return VINF_SUCCESS;
    438467    }
    439 
    440     int rc = drvHostAudioPaWaitFor(pThis, paOpServerInfo);
    441     if (RT_SUCCESS(rc) && !pThis->fEnumOpSuccess)
    442         rc = VERR_AUDIO_BACKEND_INIT_FAILED; /* error code does not matter */
    443468    if (RT_SUCCESS(rc))
    444     {
    445         if (CbCtx.pszDefaultSink)
    446         {
    447             if (fLog)
    448                 LogRel2(("PulseAudio: Default output sink is '%s'\n", CbCtx.pszDefaultSink));
    449 
    450             pThis->fEnumOpSuccess = false;
    451             rc = drvHostAudioPaWaitFor(pThis, pa_context_get_sink_info_by_name(pThis->pContext, CbCtx.pszDefaultSink,
    452                                                                    drvHostAudioPaEnumSinkCallback, &CbCtx));
    453             if (RT_SUCCESS(rc) && !pThis->fEnumOpSuccess)
    454                 rc = VERR_AUDIO_BACKEND_INIT_FAILED; /* error code does not matter */
    455             if (   RT_FAILURE(rc)
    456                 && fLog)
    457             {
    458                 LogRel(("PulseAudio: Error enumerating properties for default output sink '%s'\n", CbCtx.pszDefaultSink));
    459             }
    460         }
    461         else if (fLog)
    462             LogRel2(("PulseAudio: No default output sink found\n"));
    463 
     469        rc = CbCtx.rcEnum;
     470    if (RT_FAILURE(rc))
     471    {
     472        if (fLog)
     473            LogRel(("PulseAudio: Error enumerating PulseAudio server properties: %Rrc\n", rc));
     474        return rc;
     475    }
     476
     477    /*
     478     * Get info about the playback sink.
     479     */
     480    if (CbCtx.pszDefaultSink)
     481    {
     482        if (fLog)
     483            LogRel2(("PulseAudio: Default output sink is '%s'\n", CbCtx.pszDefaultSink));
     484        CbCtx.rcEnum = VERR_AUDIO_BACKEND_INIT_FAILED;
     485        rc = drvHostAudioPaWaitFor(pThis, pa_context_get_sink_info_by_name(pThis->pContext, CbCtx.pszDefaultSink,
     486                                                                           drvHostAudioPaEnumSinkCallback, &CbCtx));
    464487        if (RT_SUCCESS(rc))
    465         {
    466             if (CbCtx.pszDefaultSource)
    467             {
    468                 if (fLog)
    469                     LogRel2(("PulseAudio: Default input source is '%s'\n", CbCtx.pszDefaultSource));
    470 
    471                 pThis->fEnumOpSuccess = false;
    472                 rc = drvHostAudioPaWaitFor(pThis, pa_context_get_source_info_by_name(pThis->pContext, CbCtx.pszDefaultSource,
    473                                                                          drvHostAudioPaEnumSourceCallback, &CbCtx));
    474                 if (   (RT_FAILURE(rc) || !pThis->fEnumOpSuccess)
    475                     && fLog)
    476                 {
    477                     LogRel(("PulseAudio: Error enumerating properties for default input source '%s'\n", CbCtx.pszDefaultSource));
    478                 }
    479             }
    480             else if (fLog)
    481                 LogRel2(("PulseAudio: No default input source found\n"));
    482         }
    483 
     488            rc = CbCtx.rcEnum;
     489        if (fLog)
     490        {
     491            if (RT_SUCCESS(rc))
     492                LogRel2(("PulseAudio: Found %RU8 host playback device(s)\n",  CbCtx.cDevOut));
     493            else
     494                LogRel(("PulseAudio: Error enumerating properties for default output sink '%s': %Rrc\n",
     495                        CbCtx.pszDefaultSink, rc));
     496        }
     497    }
     498    else if (fLog)
     499        LogRel2(("PulseAudio: No default output sink found\n"));
     500
     501    /*
     502     * Get info about the recording source.
     503     */
     504    if (CbCtx.pszDefaultSource)
     505    {
     506        if (fLog)
     507            LogRel2(("PulseAudio: Default input source is '%s'\n", CbCtx.pszDefaultSource));
     508        CbCtx.rcEnum = VERR_AUDIO_BACKEND_INIT_FAILED;
     509        int rc2 = drvHostAudioPaWaitFor(pThis, pa_context_get_source_info_by_name(pThis->pContext, CbCtx.pszDefaultSource,
     510                                                                                  drvHostAudioPaEnumSourceCallback, &CbCtx));
     511        if (RT_SUCCESS(rc2))
     512            rc2 = CbCtx.rcEnum;
     513        if (fLog)
     514        {
     515            if (RT_SUCCESS(rc2))
     516                LogRel2(("PulseAudio: Found %RU8 host capturing device(s)\n", CbCtx.cDevIn));
     517            else
     518                LogRel(("PulseAudio: Error enumerating properties for default input source '%s': %Rrc\n",
     519                        CbCtx.pszDefaultSource, rc));
     520        }
    484521        if (RT_SUCCESS(rc))
    485         {
    486             if (fLog)
    487             {
    488                 LogRel2(("PulseAudio: Found %RU8 host playback device(s)\n",  CbCtx.cDevOut));
    489                 LogRel2(("PulseAudio: Found %RU8 host capturing device(s)\n", CbCtx.cDevIn));
    490             }
    491 
    492             if (pCfg)
    493                 memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG));
    494         }
    495 
    496         if (CbCtx.pszDefaultSink)
    497         {
    498             RTStrFree(CbCtx.pszDefaultSink);
    499             CbCtx.pszDefaultSink = NULL;
    500         }
    501 
    502         if (CbCtx.pszDefaultSource)
    503         {
    504             RTStrFree(CbCtx.pszDefaultSource);
    505             CbCtx.pszDefaultSource = NULL;
    506         }
     522            rc = rc2;
    507523    }
    508524    else if (fLog)
    509         LogRel(("PulseAudio: Error enumerating PulseAudio server properties\n"));
    510 
    511     pa_threaded_mainloop_unlock(pThis->pMainLoop);
     525        LogRel2(("PulseAudio: No default input source found\n"));
     526
     527    /** @todo r=bird: WTF are we making all this effort here w/o actually
     528     *        updating niether the backend configuration structure nor pThis?
     529     *        Sigh^3! */
     530    RT_NOREF(pCfg);
     531
     532    /* clean up */
     533    RTStrFree(CbCtx.pszDefaultSink);
     534    RTStrFree(CbCtx.pszDefaultSource);
    512535
    513536    LogFlowFuncLeaveRC(rc);
     
    524547    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    525548
    526     return drvHostAudioPaEnumerate(pThis, pBackendCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);
     549    /* Basic init: */
     550    RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "PulseAudio");
     551    pBackendCfg->cbStreamOut    = sizeof(PULSEAUDIOSTREAM);
     552    pBackendCfg->cbStreamIn     = sizeof(PULSEAUDIOSTREAM);
     553    pBackendCfg->cMaxStreamsOut = UINT32_MAX;
     554    pBackendCfg->cMaxStreamsIn  = UINT32_MAX;
     555
     556    /* Refine it or something (currently only some LogRel2 stuff): */
     557    pa_threaded_mainloop_lock(pThis->pMainLoop);
     558    int rc = drvHostAudioPaEnumerate(pThis, pBackendCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);
     559    pa_threaded_mainloop_unlock(pThis->pMainLoop);
     560    return rc;
    527561}
    528562
Note: See TracChangeset for help on using the changeset viewer.

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