VirtualBox

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


Ignore:
Timestamp:
Jun 20, 2016 9:49:55 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
108154
Message:

Audio: Implemented backend-independent handling of added/removed audio devices.

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

Legend:

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

    r61723 r61764  
    559559# error "Implement me!"
    560560#else
    561     LogFlowFunc(("[%s]: cbReadable=%RU32\n", pSink->pszName, pSink->In.cbReadable));
     561    Log3Func(("[%s]: cbReadable=%RU32\n", pSink->pszName, pSink->In.cbReadable));
    562562    return pSink->In.cbReadable;
    563563#endif
     
    580580# error "Implement me!"
    581581#else
    582     LogFlowFunc(("[%s]: cbWritable=%RU32\n", pSink->pszName, pSink->Out.cbWritable));
     582    Log3Func(("[%s]: cbWritable=%RU32\n", pSink->pszName, pSink->Out.cbWritable));
    583583    return pSink->Out.cbWritable;
    584584#endif
     
    665665    {
    666666        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     667        {
     668            LogFlowFunc(("%s: Stream '%s' Disabled, skipping ...\n", pMixStream->pszName, pMixStream->pStream->szName));
    667669            continue;
     670        }
    668671
    669672        uint32_t cbTotalRead = 0;
     
    10711074        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    10721075        {
    1073             LogFlowFunc(("%s: Disabled, skipping ...\n", pSink->pszName));
     1076            LogFlowFunc(("%s: Stream '%s' Disabled, skipping ...\n", pMixStream->pszName, pMixStream->pStream->szName));
    10741077            continue;
    10751078        }
     
    11741177bool AudioMixerStreamIsActive(PAUDMIXSTREAM pMixStream)
    11751178{
    1176     if (   !pMixStream
    1177         || !pMixStream->pConn)
    1178     {
    1179         return false;
    1180     }
    1181 
    11821179    bool fIsActive =
    1183         RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED);
     1180           pMixStream
     1181        && RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED);
    11841182
    11851183    return fIsActive;
     
    11881186bool AudioMixerStreamIsValid(PAUDMIXSTREAM pMixStream)
    11891187{
    1190     if (!pMixStream)
    1191         return false;
    1192 
    1193     uint32_t fStatus = pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream);
    1194 
    1195     return (fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED);
    1196 }
    1197 
     1188    bool fIsValid =
     1189           pMixStream
     1190        && RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_INITIALIZED);
     1191
     1192    return fIsValid;
     1193}
     1194
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r61668 r61764  
    4646static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream);
    4747static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
     48static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest);
    4849static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
     50static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    4951
    5052#ifndef VBOX_AUDIO_TESTCASE
     
    254256        return rc;
    255257
    256     LogFlowFunc(("%s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));
     258    LogFlowFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd));
    257259
    258260    rc = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
     
    270272    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    271273
    272     LogFlowFunc(("%s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));
     274    LogFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd));
    273275
    274276    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     
    308310                if (pHstStream)
    309311                {
    310                     LogFlowFunc(("%s: Pending disable/pause\n", pHstStream->szName));
     312                    LogFunc(("[%s] Pending disable/pause\n", pHstStream->szName));
    311313                    pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
    312314                }
     
    345347
    346348        default:
    347             AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd));
     349            AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd));
    348350            rc = VERR_NOT_IMPLEMENTED;
    349351            break;
     
    351353
    352354    if (RT_FAILURE(rc))
    353         LogFunc(("%s: Failed with %Rrc\n", pStream->szName, rc));
     355        LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
    354356
    355357    return rc;
     
    361363    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    362364
    363     LogFlowFunc(("%s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));
     365    LogFlowFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd));
    364366
    365367    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     
    370372    int rc = VINF_SUCCESS;
    371373
    372     switch (enmStreamCmd)
    373     {
    374         case PDMAUDIOSTREAMCMD_ENABLE:
    375         {
    376             if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    377             {
    378                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE);
    379                 if (RT_SUCCESS(rc))
    380                     pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    381             }
    382             break;
    383         }
    384 
    385         case PDMAUDIOSTREAMCMD_DISABLE:
    386         {
    387             if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    388             {
    389                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    390                 if (RT_SUCCESS(rc))
     374    if (RT_SUCCESS(rc))
     375    {
     376        switch (enmStreamCmd)
     377        {
     378            case PDMAUDIOSTREAMCMD_ENABLE:
     379            {
     380                if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    391381                {
    392                     pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    393                     AudioMixBufReset(&pHstStream->MixBuf);
     382                    rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE);
     383                    if (RT_SUCCESS(rc))
     384                        pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    394385                }
    395             }
    396             break;
    397         }
    398 
    399         case PDMAUDIOSTREAMCMD_PAUSE:
    400         {
    401             if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    402             {
    403                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE);
    404                 if (RT_SUCCESS(rc))
    405                     pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    406             }
    407             break;
    408         }
    409 
    410         case PDMAUDIOSTREAMCMD_RESUME:
    411         {
    412             if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
    413             {
    414                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME);
    415                 if (RT_SUCCESS(rc))
    416                     pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    417             }
    418             break;
    419         }
    420 
    421         default:
    422             AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd));
    423             rc = VERR_NOT_IMPLEMENTED;
    424             break;
    425     }
    426 
    427     if (RT_FAILURE(rc))
    428         LogFunc(("%s: Failed with %Rrc\n", pStream->szName, rc));
    429 
     386                break;
     387            }
     388
     389            case PDMAUDIOSTREAMCMD_DISABLE:
     390            {
     391                if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     392                {
     393                    rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     394                    if (RT_SUCCESS(rc))
     395                    {
     396                        pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
     397                        pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     398                        AudioMixBufReset(&pHstStream->MixBuf);
     399                    }
     400                }
     401                break;
     402            }
     403
     404            case PDMAUDIOSTREAMCMD_PAUSE:
     405            {
     406                if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
     407                {
     408                    rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE);
     409                    if (RT_SUCCESS(rc))
     410                        pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
     411                }
     412                break;
     413            }
     414
     415            case PDMAUDIOSTREAMCMD_RESUME:
     416            {
     417                if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
     418                {
     419                    rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME);
     420                    if (RT_SUCCESS(rc))
     421                        pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
     422                }
     423                break;
     424            }
     425
     426            default:
     427                AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd));
     428                rc = VERR_NOT_IMPLEMENTED;
     429                break;
     430        }
     431    }
     432
     433    if (RT_FAILURE(rc))
     434        LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
     435
     436    return rc;
     437}
     438
     439static int drvAudioStreamInitInternal(PDRVAUDIO pThis,
     440                                      PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest)
     441{
     442    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     443    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     444
     445    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     446    PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream;
     447    AssertPtr(pGstStream);
     448
     449    LogFlowFunc(("[%s]\n", pStream->szName));
     450
     451    /*
     452     * Init host stream.
     453     */
     454
     455    uint32_t cSamples = 0;
     456    int rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStream, pCfgHost, &cSamples);
     457    if (RT_SUCCESS(rc))
     458    {
     459        /* Only set the host's stream to initialized if we were able create the stream
     460         * in the host backend. This is necessary for trying to re-initialize the stream
     461         * at some later point in time. */
     462        pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     463    }
     464    else
     465        LogFlowFunc(("[%s] Initializing stream in host backend failed with rc=%Rrc\n", pStream->szName, rc));
     466
     467    int rc2 = DrvAudioHlpStreamCfgToProps(pCfgHost, &pHstStream->Props);
     468    AssertRC(rc2);
     469
     470    /* Destroy any former mixing buffer. */
     471    AudioMixBufDestroy(&pHstStream->MixBuf);
     472
     473    if (cSamples)
     474    {
     475        rc2 = AudioMixBufInit(&pHstStream->MixBuf, pHstStream->szName, &pHstStream->Props, cSamples * 4);
     476        AssertRC(rc2);
     477    }
     478
     479    /* Make a copy of the host stream configuration. */
     480    memcpy(&pHstStream->Cfg, pCfgHost, sizeof(PDMAUDIOSTREAMCFG));
     481
     482    /*
     483     * Init guest stream.
     484     */
     485
     486    rc2 = DrvAudioHlpStreamCfgToProps(pCfgGuest, &pGstStream->Props);
     487    AssertRC(rc2);
     488
     489    /* Destroy any former mixing buffer. */
     490    AudioMixBufDestroy(&pGstStream->MixBuf);
     491
     492    if (cSamples)
     493    {
     494        rc2 = AudioMixBufInit(&pGstStream->MixBuf, pGstStream->szName, &pGstStream->Props, cSamples * 2);
     495        AssertRC(rc2);
     496    }
     497
     498    if (cSamples)
     499    {
     500        if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     501        {
     502            /* Host (Parent) -> Guest (Child). */
     503            rc2 = AudioMixBufLinkTo(&pHstStream->MixBuf, &pGstStream->MixBuf);
     504            AssertRC(rc2);
     505        }
     506        else
     507        {
     508            /* Guest (Parent) -> Host (Child). */
     509            rc2 = AudioMixBufLinkTo(&pGstStream->MixBuf, &pHstStream->MixBuf);
     510            AssertRC(rc2);
     511        }
     512    }
     513
     514    /* Make a copy of the host stream configuration. */
     515    memcpy(&pGstStream->Cfg, pCfgGuest, sizeof(PDMAUDIOSTREAMCFG));
     516
     517    LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
     518    return rc;
     519}
     520
     521static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     522{
     523    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     524    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     525
     526    LogFlowFunc(("[%s]\n", pStream->szName));
     527
     528    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     529    PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream;
     530    AssertPtr(pGstStream);
     531
     532    int rc;
     533
     534    if (/* Stream initialized? */
     535            (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     536        /* Not in pending re-init before? */
     537        && !(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT))
     538    {
     539        /* Disable first. */
     540        rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     541        if (RT_FAILURE(rc))
     542        {
     543            LogFunc(("[%s] Error disabling stream, rc=%Rrc\n", pStream->szName, rc));
     544            return rc;
     545        }
     546
     547        /* Give the backend the chance to clean up the old context. */
     548        rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStream);
     549        if (RT_FAILURE(rc))
     550        {
     551            LogFunc(("[%s] Error destroying stream in backend, rc=%Rrc\n", pStream->szName, rc));
     552            return rc;
     553        }
     554
     555        /* Set the pending re-init bit. */
     556        pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT;
     557    }
     558
     559    LogFlowFunc(("[%s] Host status is 0x%x\n", pStream->szName, pHstStream->fStatus));
     560
     561    /* Try to re-initialize the stream. */
     562    rc = drvAudioStreamInitInternal(pThis, pStream, &pHstStream->Cfg, &pGstStream->Cfg);
     563    if (RT_SUCCESS(rc))
     564    {
     565        /* Try to restore the previous stream status, if possible. */
     566        PDMAUDIOSTREAMCMD enmCmdRestore = PDMAUDIOSTREAMCMD_UNKNOWN;
     567
     568        if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) /* Stream was running before? */
     569        {
     570            LogFunc(("[%s] Re-enabling host stream ...\n", pStream->szName));
     571            enmCmdRestore = PDMAUDIOSTREAMCMD_ENABLE;
     572        }
     573
     574        if (enmCmdRestore != PDMAUDIOSTREAMCMD_UNKNOWN)
     575            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE);
     576
     577        /* Re-initialization successful, remove bit again. */
     578        pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT;
     579    }
     580
     581    LogFunc(("[%s] Reinitialization returned %Rrc\n", pStream->szName, rc));
    430582    return rc;
    431583}
     
    465617               pStream->szName, pStream->enmDir));
    466618
    467     LogFlowFunc(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf));
     619    Log3Func(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf));
    468620
    469621    int rc = RTCritSectEnter(&pThis->CritSect);
     
    508660    }
    509661
    510     LogFlowFunc(("cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",
    511                  cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), 0, rc));
     662    Log3Func(("cWritten=%RU32 (%RU32 bytes), rc=%Rrc\n", cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), rc));
    512663
    513664    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    553704        return rc;
    554705
    555     LogFlowFunc(("%s\n", pStream->szName));
    556 
    557706    rc = drvAudioStreamIterateInternal(pThis, pStream);
    558707
     
    573722    if (!pStream)
    574723        return VINF_SUCCESS;
    575 
    576     LogFlowFunc(("%s\n", pStream->szName));
    577724
    578725    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     
    599746            uint32_t cSamplesCaptured = AudioMixBufUsed(&pHstStream->MixBuf);
    600747
    601             LogFlowFunc(("[%s] %RU32 samples captured\n", pHstStream->szName, cSamplesCaptured));
     748            Log3Func(("[%s] %RU32 samples captured\n", pHstStream->szName, cSamplesCaptured));
    602749
    603750            if (cSamplesCaptured)
     
    609756                    && cSamplesMixed)
    610757                {
    611                     LogFlowFunc(("[%s] %RU32 captured samples mixed\n", pHstStream->szName, cSamplesMixed));
     758                    Log3Func(("[%s] %RU32 captured samples mixed\n", pHstStream->szName, cSamplesMixed));
    612759                }
    613760            }
     
    628775                    && cSamplesMixed)
    629776                {
    630                     LogFlowFunc(("[%s] %RU32 samples mixed\n", pHstStream->szName, cSamplesMixed));
     777                    Log3Func(("[%s] %RU32 samples mixed\n", pHstStream->szName, cSamplesMixed));
    631778                }
    632779
     
    635782            }
    636783
    637             LogFlowFunc(("[%s] %RU32 live samples\n", pHstStream->szName, cSamplesLive));
     784            Log3Func(("[%s] %RU32 live samples\n", pHstStream->szName, cSamplesLive));
    638785
    639786            if (!cSamplesLive) /* No live samples (anymore)? */
     
    677824    /* pcSamplesPlayed is optional. */
    678825
     826    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     827
     828    int rc = RTCritSectEnter(&pThis->CritSect);
     829    if (RT_FAILURE(rc))
     830        return rc;
     831
    679832    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
    680833              ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
    681834               pStream->szName, pStream->enmDir));
    682835
    683     AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED,
    684               ("Unable to play stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus));
    685 
    686     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    687 
    688     int rc = RTCritSectEnter(&pThis->CritSect);
    689     if (RT_FAILURE(rc))
    690         return rc;
     836    Log3Func(("[%s]\n", pStream->szName));
    691837
    692838    uint32_t cSamplesPlayed = 0;
     
    713859        AssertPtr(pGstStream);
    714860
     861        PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     862        if (!(strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED))
     863        {
     864            LogFunc(("[%s] Backend not initialized (anymore), re-initializing ...\n", pHstStream->szName));
     865            rc = drvAudioStreamReInitInternal(pThis, pStream);
     866            break;
     867        }
     868
    715869        uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
    716870        if (cSamplesLive)
    717871        {
    718             PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
    719             if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)
     872            if (   (strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     873                && (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE))
    720874            {
    721875                rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed);
     
    727881            }
    728882
    729             LogFlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesPlayed, rc));
     883            Log3Func(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesPlayed, rc));
    730884        }
    731885
     
    768922                                               uint32_t *pcSamplesCaptured)
    769923{
     924    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     925
     926    int rc = RTCritSectEnter(&pThis->CritSect);
     927    if (RT_FAILURE(rc))
     928        return rc;
     929
    770930    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN,
    771931              ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n",
    772932               pStream->szName, pStream->enmDir));
    773933
    774     AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED,
    775               ("Unable to capture stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus));
    776 
    777     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    778 
    779     int rc = RTCritSectEnter(&pThis->CritSect);
    780     if (RT_FAILURE(rc))
    781         return rc;
    782 
    783     LogFlowFunc(("[%s]\n", pStream->szName));
     934    Log3Func(("[%s]\n", pStream->szName));
    784935
    785936    uint32_t cSamplesCaptured = 0;
     
    806957        AssertPtr(pGstStream);
    807958
     959        PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     960        if (!(strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED))
     961        {
     962            LogFunc(("[%s] Backend not initialized (anymore), re-initializing ...\n", pHstStream->szName));
     963            rc = drvAudioStreamReInitInternal(pThis, pStream);
     964            break;
     965        }
     966
    808967        uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf);
    809968        if (!cSamplesLive)
    810969        {
    811             PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
    812             if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_READABLE)
     970            if (   (strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     971                && (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_READABLE))
    813972            {
    814973                rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured);
     
    820979            }
    821980
    822             LogFlowFunc(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesCaptured, rc));
     981            Log3Func(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesCaptured, rc));
    823982        }
    824983
     
    10321191    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
    10331192
    1034     LogFlowFunc(("enmCmd=%ld\n", enmCmd));
     1193    LogFlowFunc(("enmCmd=%RU32\n", enmCmd));
    10351194
    10361195    if (!pThis->pHostDrvAudio)
     
    11201279    }
    11211280
    1122     LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n",
    1123                  cRead, AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cRead), rc));
     1281    Log3Func(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n", cRead, AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cRead), rc));
    11241282
    11251283    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    11831341        {
    11841342            if (!pThis->cStreamsFreeIn)
    1185             {
    1186                 LogFlowFunc(("No more input streams free to use, bailing out\n"));
    1187                 RC_BREAK(VERR_AUDIO_NO_FREE_INPUT_STREAMS);
    1188             }
     1343                LogFunc(("Warning: No more input streams free to use\n"));
    11891344
    11901345            /* Validate backend configuration. */
    11911346            if (!pThis->BackendCfg.cbStreamIn)
    11921347            {
    1193                 LogFlowFunc(("Backend input configuration not valid, bailing out\n"));
     1348                LogFunc(("Backend input configuration not valid, bailing out\n"));
    11941349                RC_BREAK(VERR_INVALID_PARAMETER);
    11951350            }
     
    12281383
    12291384        /*
    1230          * Create host stream.
     1385         * Init host stream.
    12311386         */
    1232 
    12331387        RTStrPrintf(pHstStrm->szName, RT_ELEMENTS(pHstStrm->szName), "%s (Host)",
    12341388                    strlen(pCfgHost->szName) ? pCfgHost->szName : "<Untitled>");
    12351389
    1236         /* Note: Direction is always from child -> parent. */
    1237         uint32_t cSamples = 0;
    1238         rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStrm, pCfgHost, &cSamples);
    1239         if (RT_FAILURE(rc))
    1240         {
    1241             LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc));
    1242             break;
    1243         }
    1244 
    1245         pHstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    1246         pHstStrm->pPair    = pGstStrm;
    1247 
    1248         rc = DrvAudioHlpStreamCfgToProps(pCfgHost, &pHstStrm->Props);
    1249         AssertRCBreak(rc);
    1250 
    1251         rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples * 4);
    1252         AssertRCBreak(rc);
     1390        pHstStrm->pPair = pGstStrm;
    12531391
    12541392        /*
    1255          * Create guest stream.
     1393         * Init guest stream.
    12561394         */
    1257 
    12581395        RTStrPrintf(pGstStrm->szName, RT_ELEMENTS(pGstStrm->szName), "%s (Guest)",
    12591396                    strlen(pCfgGuest->szName) ? pCfgGuest->szName : "<Untitled>");
    12601397
    1261         rc = DrvAudioHlpStreamCfgToProps(pCfgGuest, &pGstStrm->Props);
    1262         AssertRCBreak(rc);
    1263 
    1264         rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, cSamples * 2);
    1265         if (RT_SUCCESS(rc))
    1266         {
    1267             if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    1268             {
    1269                 /* Host (Parent) -> Guest (Child). */
    1270                 rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf);
    1271             }
    1272             else
    1273             {
    1274                 /* Guest (Parent) -> Host (Child). */
    1275                 rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf);
    1276             }
    1277         }
    1278 
    1279         pGstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    1280         pGstStrm->pPair    = pHstStrm;
    1281 
    1282         AssertRCBreak(rc);
     1398        pGstStrm->fStatus = pHstStrm->fStatus; /* Reflect the host stream's status. */
     1399        pGstStrm->pPair   = pHstStrm;
     1400
     1401        /*
     1402         * Try to init the rest.
     1403         */
     1404        rc = drvAudioStreamInitInternal(pThis, pHstStrm, pCfgHost, pCfgGuest);
     1405        if (RT_FAILURE(rc))
     1406        {
     1407            LogFlowFunc(("Stream not available (yet)\n"));
     1408            rc = VINF_SUCCESS;
     1409        }
    12831410
    12841411    } while (0);
     
    13111438        if (pCfgHost->enmDir == PDMAUDIODIR_IN)
    13121439        {
    1313             Assert(pThis->cStreamsFreeIn);
    1314             pThis->cStreamsFreeIn--;
     1440            if (pThis->cStreamsFreeIn)
     1441                pThis->cStreamsFreeIn--;
    13151442        }
    13161443        else /* Out */
    13171444        {
    1318             Assert(pThis->cStreamsFreeOut);
    1319             pThis->cStreamsFreeOut--;
     1445            if (pThis->cStreamsFreeOut)
     1446                pThis->cStreamsFreeOut--;
    13201447        }
    13211448
     
    14011528        cReadable = AudioMixBufLive(&pGstStream->MixBuf);
    14021529
    1403     LogFlowFunc(("[%s] cbReadable=%RU32\n", pHstStream->szName, cReadable));
     1530    Log3Func(("[%s] cbReadable=%RU32\n", pHstStream->szName, cReadable));
    14041531
    14051532    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    14381565        cWritable = AudioMixBufFreeBytes(&pGstStream->MixBuf);
    14391566
    1440     LogFlowFunc(("[%s] cWritable=%RU32\n", pHstStream->szName, cWritable));
     1567    Log3Func(("[%s] cWritable=%RU32\n", pHstStream->szName, cWritable));
    14411568
    14421569    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    14621589    PDMAUDIOSTRMSTS strmSts    = pHstStream->fStatus;
    14631590
    1464     LogFlowFunc(("%s: strmSts=0x%x\n", pHstStream->szName, strmSts));
     1591    Log3Func(("%s: strmSts=0x%x\n", pHstStream->szName, strmSts));
     1592
    14651593    rc2 = RTCritSectLeave(&pThis->CritSect);
    14661594    AssertRC(rc2);
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r61729 r61764  
    354354
    355355static int coreAudioInitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples);
    356 static int coreAudioReinitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);
    357356static int coreAudioInitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples);
    358 static int coreAudioReinitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);
    359357static int coreAudioControlStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    360358static int coreAudioControlStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
     359static int coreAudioCreateStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples);
     360static int coreAudioCreateStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples);
    361361static int coreAudioDestroyStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);
    362362static int coreAudioDestroyStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);
     
    380380    int rc = VINF_SUCCESS;
    381381
     382    uint8_t cDevs = 0;
     383
    382384    do
    383385    {
     
    456458                {
    457459                    LogRel2(("CoreAudio: Found %s device '%s'\n", fIn ? "recording" : "playback", pszName));
    458 
    459                     if (pCfg)
    460                     {
    461                         if (fIn)
    462                             pCfg->cSources++;
    463                         else
    464                             pCfg->cSinks++;
    465                     }
     460                    cDevs++;
    466461                }
    467462
     
    477472
    478473    } while (0);
     474
     475    if (fIn)
     476        LogRel2(("CoreAudio: Found %RU8 capturing device(s)\n", cDevs));
     477    else
     478        LogRel2(("CoreAudio: Found %RU8 playback device(s)\n", cDevs));
     479
     480    if (pCfg)
     481    {
     482        if (fIn)
     483            pCfg->cSources = cDevs;
     484        else
     485            pCfg->cSinks   = cDevs;
     486    }
    479487
    480488    LogFlowFuncLeaveRC(rc);
     
    609617            {
    610618                PCOREAUDIOSTREAMIN pStreamIn = pCbCtx->pIn;
     619                AssertPtr(pStreamIn);
    611620
    612621                /* This listener is called on every change of the hardware
     
    615624                UInt32 uResp;
    616625                err = AudioObjectGetPropertyData(kAudioObjectSystemObject, pProperty, 0, NULL, &uSize, &uResp);
    617 
    618626                if (err == noErr)
    619627                {
    620628                    if (pStreamIn->deviceID != uResp)
    621629                    {
    622                         LogRel(("CoreAudio: Default recording device has changed\n"));
     630                        LogRel2(("CoreAudio: Default device for recording has changed\n"));
    623631
    624632                        /* We move the reinitialization to the next input event.
     
    634642            {
    635643                PCOREAUDIOSTREAMOUT pStreamOut = pCbCtx->pOut;
     644                AssertPtr(pStreamOut);
    636645
    637646                /* This listener is called on every change of the hardware
     
    643652                UInt32 uResp;
    644653                err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &uResp);
    645 
    646654                if (err == noErr)
    647655                {
    648656                    if (pStreamOut->deviceID != uResp)
    649657                    {
    650                         LogRel(("CoreAudio: Default playback device has changed\n"));
     658                        LogRel2(("CoreAudio: Default device for playback has changed\n"));
    651659
    652660                        /* We move the reinitialization to the next input event.
     
    675683}
    676684
    677 static int coreAudioReinitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream)
    678 {
    679     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    680 
    681     int rc = coreAudioDestroyStreamIn(pThis, &pStreamIn->Stream);
    682     if (RT_SUCCESS(rc))
    683     {
    684         rc = coreAudioInitIn(pThis, &pStreamIn->Stream, NULL /* pcSamples */);
    685         if (RT_SUCCESS(rc))
    686             rc = coreAudioControlStreamIn(pThis, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_ENABLE);
    687     }
    688 
    689     if (RT_FAILURE(rc))
    690         LogRel(("CoreAudio: Unable to re-init input stream: %Rrc\n", rc));
    691 
    692     return rc;
    693 }
    694 
    695 static int coreAudioReinitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream)
    696 {
    697     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    698 
    699     int rc = coreAudioDestroyStreamOut(pThis, &pStreamOut->Stream);
    700     if (RT_SUCCESS(rc))
    701     {
    702         rc = coreAudioInitOut(pThis, &pStreamOut->Stream, NULL /* pcSamples */);
    703         if (RT_SUCCESS(rc))
    704             rc = coreAudioControlStreamOut(pThis, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_ENABLE);
    705     }
    706 
    707     if (RT_FAILURE(rc))
    708         LogRel(("CoreAudio: Unable to re-init output stream: %Rrc\n", rc));
    709 
    710     return rc;
    711 }
    712 
    713685/* Callback for getting notified when some of the properties of an audio device has changed. */
    714686static DECLCALLBACK(OSStatus) coreAudioRecordingAudioDevicePropertyChanged(AudioObjectID                     propertyID,
     
    882854                   && err != caConverterEOFDErr)
    883855                {
    884                     LogFlowFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err,
    885                                  RT_BYTE4(err), RT_BYTE3(err), RT_BYTE2(err), RT_BYTE1(err)));
     856                    LogFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err,
     857                             RT_BYTE4(err), RT_BYTE3(err), RT_BYTE2(err), RT_BYTE1(err)));
    886858                    rc = VERR_IO_GEN_FAILURE;
    887859                    break;
     
    890862                /* Check in any case what processed size is returned. It could be less than we expected. */
    891863                cbToWrite = ioOutputDataPacketSize * pStreamIn->streamFormat.mBytesPerPacket;
     864
     865                Log3Func(("cbToWrite=%RU32\n", cbToWrite));
    892866
    893867                /* Release the ring buffer, so the main thread could start reading this data. */
     
    932906                  size_t   cbAvail    = RT_MIN(cbDataSize, cbBufFree);
    933907
    934             LogFlowFunc(("cbDataSize=%RU32, cbBufFree=%zu, cbAvail=%zu\n", cbDataSize, cbBufFree, cbAvail));
     908            Log3Func(("cbDataSize=%RU32, cbBufFree=%zu, cbAvail=%zu\n", cbDataSize, cbBufFree, cbAvail));
    935909
    936910            /* Iterate as long as data is available. */
     
    957931            }
    958932
    959             LogFlowFunc(("cbWrittenTotal=%RU32, cbLeft=%zu\n", cbWrittenTotal, cbAvail));
     933            Log3Func(("cbWrittenTotal=%RU32, cbLeft=%zu\n", cbWrittenTotal, cbAvail));
    960934        }
    961935
     
    968942    }
    969943
    970     LogFlowFuncLeaveRC(rc);
     944    if (RT_FAILURE(rc))
     945        LogFunc(("Failed with rc=%Rrc\n", rc));
     946
    971947    return err;
    972948}
     949
     950# define CA_BREAK_STMT(stmt) \
     951    stmt; \
     952    break;
    973953
    974954/** @todo Eventually split up this function, as this already is huge! */
    975955static int coreAudioInitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples)
    976956{
    977     OSStatus err = noErr;
     957    int rc = VINF_SUCCESS;
    978958
    979959    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    980 
    981     ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT);
    982 
    983     UInt32 uSize = 0;
    984     if (pStreamIn->deviceID == kAudioDeviceUnknown)
    985     {
    986         /* Fetch the default audio recording device currently in use. */
    987         AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice,
    988                                                kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
    989         uSize = sizeof(pStreamIn->deviceID);
    990         err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize,  &pStreamIn->deviceID);
    991         if (err != noErr)
    992         {
    993             LogRel(("CoreAudio: Unable to determine default recording device (%RI32)\n", err));
    994             return VERR_NOT_FOUND;
    995         }
    996     }
    997 
    998     /*
    999      * Try to get the name of the recording device and log it. It's not fatal if it fails.
    1000      */
    1001     CFStringRef strTemp;
    1002 
    1003     AudioObjectPropertyAddress propAdr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal,
    1004                                            kAudioObjectPropertyElementMaster };
    1005     uSize = sizeof(CFStringRef);
    1006     err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp);
    1007     if (err == noErr)
    1008     {
    1009         char *pszDevName = NULL;
    1010         err = coreAudioCFStringToCString(strTemp, &pszDevName);
     960    UInt32 cSamples = 0;
     961
     962    do
     963    {
     964        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT);
     965
     966        OSStatus err;
     967
     968        UInt32 uSize = 0;
     969        if (pStreamIn->deviceID == kAudioDeviceUnknown)
     970        {
     971            /* Fetch the default audio recording device currently in use. */
     972            AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice,
     973                                                   kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
     974            uSize = sizeof(pStreamIn->deviceID);
     975            err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &pStreamIn->deviceID);
     976            if (err != noErr)
     977            {
     978                LogRel2(("CoreAudio: Unable to determine default recording device (%RI32)\n", err));
     979                return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
     980            }
     981        }
     982
     983        if (pStreamIn->deviceID == kAudioDeviceUnknown)
     984        {
     985            LogFlowFunc(("No default recording device found\n"));
     986            return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
     987        }
     988
     989        /*
     990         * Try to get the name of the recording device and log it. It's not fatal if it fails.
     991         */
     992        CFStringRef strTemp;
     993
     994        AudioObjectPropertyAddress propAdr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal,
     995                                               kAudioObjectPropertyElementMaster };
     996        uSize = sizeof(CFStringRef);
     997        err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp);
    1011998        if (err == noErr)
    1012999        {
    1013             CFRelease(strTemp);
    1014 
    1015             /* Get the device' UUID. */
    1016             propAdr.mSelector = kAudioDevicePropertyDeviceUID;
    1017             err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp);
     1000            char *pszDevName = NULL;
     1001            err = coreAudioCFStringToCString(strTemp, &pszDevName);
    10181002            if (err == noErr)
    10191003            {
    1020                 char *pszUID = NULL;
    1021                 err = coreAudioCFStringToCString(strTemp, &pszUID);
     1004                CFRelease(strTemp);
     1005
     1006                /* Get the device' UUID. */
     1007                propAdr.mSelector = kAudioDevicePropertyDeviceUID;
     1008                err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp);
    10221009                if (err == noErr)
    10231010                {
    1024                     CFRelease(strTemp);
    1025                     LogRel(("CoreAudio: Using recording device: %s (UID: %s)\n", pszDevName, pszUID));
    1026 
    1027                     RTMemFree(pszUID);
     1011                    char *pszUID = NULL;
     1012                    err = coreAudioCFStringToCString(strTemp, &pszUID);
     1013                    if (err == noErr)
     1014                    {
     1015                        CFRelease(strTemp);
     1016                        LogRel(("CoreAudio: Using recording device: %s (UID: %s)\n", pszDevName, pszUID));
     1017
     1018                        RTMemFree(pszUID);
     1019                    }
    10281020                }
    1029             }
    1030 
    1031             RTMemFree(pszDevName);
    1032         }
    1033     }
    1034     else
    1035     {
    1036         /* This is not fatal, can happen for some Macs. */
    1037         LogRel2(("CoreAudio: Unable to determine recording device name (%RI32)\n", err));
    1038     }
    1039 
    1040     /* Get the default frames buffer size, so that we can setup our internal buffers. */
    1041     UInt32 cFrames;
    1042     uSize = sizeof(cFrames);
    1043     propAdr.mSelector = kAudioDevicePropertyBufferFrameSize;
    1044     propAdr.mScope    = kAudioDevicePropertyScopeInput;
    1045     err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &cFrames);
    1046     if (err != noErr)
    1047     {
    1048         /* Can happen if no recording device is available by default. Happens on some Macs,
    1049          * so don't log this by default to not scare people. */
    1050         LogRel2(("CoreAudio: Failed to determine frame buffer size of the audio recording device (%RI32)\n", err));
    1051         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1052     }
    1053 
    1054     /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */
    1055     err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames);
    1056     if (err != noErr)
    1057     {
    1058         LogRel(("CoreAudio: Failed to set frame buffer size for the audio recording device (%RI32)\n", err));
    1059         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1060     }
    1061 
    1062     LogFlowFunc(("cFrames=%RU32\n", cFrames));
    1063 
    1064     ComponentDescription cd;
    1065     RT_ZERO(cd);
    1066     cd.componentType         = kAudioUnitType_Output;
    1067     cd.componentSubType      = kAudioUnitSubType_HALOutput;
    1068     cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    1069 
    1070     /* Try to find the default HAL output component. */
    1071     Component cp = FindNextComponent(NULL, &cd);
    1072     if (cp == 0)
    1073     {
    1074         LogRel(("CoreAudio: Failed to find HAL output component\n")); /** @todo Return error value? */
    1075         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1076     }
    1077 
    1078     /* Open the default HAL output component. */
    1079     err = OpenAComponent(cp, &pStreamIn->audioUnit);
    1080     if (err != noErr)
    1081     {
    1082         LogRel(("CoreAudio: Failed to open output component (%RI32)\n", err));
    1083         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1084     }
    1085 
    1086     /* Switch the I/O mode for input to on. */
    1087     UInt32 uFlag = 1;
    1088     err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
    1089                                1, &uFlag, sizeof(uFlag));
    1090     if (err != noErr)
    1091     {
    1092         LogRel(("CoreAudio: Failed to disable input I/O mode for input stream (%RI32)\n", err));
    1093         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1094     }
    1095 
    1096     /* Switch the I/O mode for output to off. This is important, as this is a pure input stream. */
    1097     uFlag = 0;
    1098     err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
    1099                                0, &uFlag, sizeof(uFlag));
    1100     if (err != noErr)
    1101     {
    1102         LogRel(("CoreAudio: Failed to disable output I/O mode for input stream (%RI32)\n", err));
    1103         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1104     }
    1105 
    1106     /* Set the default audio recording device as the device for the new AudioUnit. */
    1107     err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global,
    1108                                0, &pStreamIn->deviceID, sizeof(pStreamIn->deviceID));
    1109     if (err != noErr)
    1110     {
    1111         LogRel(("CoreAudio: Failed to set current device (%RI32)\n", err));
    1112         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1113     }
    1114 
    1115     /*
    1116      * CoreAudio will inform us on a second thread for new incoming audio data.
    1117      * Therefor register a callback function which will process the new data.
    1118      */
    1119     AURenderCallbackStruct cb;
    1120     RT_ZERO(cb);
    1121     cb.inputProc       = coreAudioRecordingCb;
    1122     cb.inputProcRefCon = pStreamIn;
    1123 
    1124     err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global,
    1125                                0, &cb, sizeof(cb));
    1126     if (err != noErr)
    1127     {
    1128         LogRel(("CoreAudio: Failed to register input callback (%RI32)\n", err));
    1129         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1130     }
    1131 
    1132     /* Fetch the current stream format of the device. */
    1133     uSize = sizeof(pStreamIn->deviceFormat);
    1134     err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
    1135                                1, &pStreamIn->deviceFormat, &uSize);
    1136     if (err != noErr)
    1137     {
    1138         LogRel(("CoreAudio: Failed to get device format (%RI32)\n", err));
    1139         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1140     }
    1141 
    1142     /* Create an AudioStreamBasicDescription based on our required audio settings. */
    1143     coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat);
    1144 
    1145     coreAudioPrintASBDesc("CoreAudio: recording device", &pStreamIn->deviceFormat);
    1146     coreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat);
    1147 
    1148     /* If the frequency of the device is different from the requested one we
    1149      * need a converter. The same count if the number of channels is different. */
    1150     if (   pStreamIn->deviceFormat.mSampleRate       != pStreamIn->streamFormat.mSampleRate
    1151         || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame)
    1152     {
    1153         LogRel(("CoreAudio: Input converter is active\n"));
    1154 
    1155         err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter);
    1156         if (RT_UNLIKELY(err != noErr))
    1157         {
    1158             LogRel(("CoreAudio: Failed to create the audio converter (%RI32)\n", err));
    1159             return VERR_AUDIO_BACKEND_INIT_FAILED;
    1160         }
    1161 
    1162         if (   pStreamIn->deviceFormat.mChannelsPerFrame == 1 /* Mono */
    1163             && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */)
    1164         {
    1165             /*
    1166              * If the channel count is different we have to tell this the converter
    1167              * and supply a channel mapping. For now we only support mapping
    1168              * from mono to stereo. For all other cases the core audio defaults
    1169              * are used, which means dropping additional channels in most
    1170              * cases.
    1171              */
    1172             const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo, */
    1173 
    1174             err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap);
     1021
     1022                RTMemFree(pszDevName);
     1023            }
     1024        }
     1025        else
     1026        {
     1027            /* This is not fatal, can happen for some Macs. */
     1028            LogRel2(("CoreAudio: Unable to determine recording device name (%RI32)\n", err));
     1029        }
     1030
     1031        /* Get the default frames buffer size, so that we can setup our internal buffers. */
     1032        UInt32 cFrames;
     1033        uSize = sizeof(cFrames);
     1034        propAdr.mSelector = kAudioDevicePropertyBufferFrameSize;
     1035        propAdr.mScope    = kAudioDevicePropertyScopeInput;
     1036        err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &cFrames);
     1037        if (err != noErr)
     1038        {
     1039            /* Can happen if no recording device is available by default. Happens on some Macs,
     1040             * so don't log this by default to not scare people. */
     1041            LogRel2(("CoreAudio: Failed to determine frame buffer size of the audio recording device (%RI32)\n", err));
     1042            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1043        }
     1044
     1045        /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */
     1046        err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames);
     1047        if (err != noErr)
     1048        {
     1049            LogRel(("CoreAudio: Failed to set frame buffer size for the audio recording device (%RI32)\n", err));
     1050            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1051        }
     1052
     1053        LogFlowFunc(("cFrames=%RU32\n", cFrames));
     1054
     1055        ComponentDescription cd;
     1056        RT_ZERO(cd);
     1057        cd.componentType         = kAudioUnitType_Output;
     1058        cd.componentSubType      = kAudioUnitSubType_HALOutput;
     1059        cd.componentManufacturer = kAudioUnitManufacturer_Apple;
     1060
     1061        /* Try to find the default HAL output component. */
     1062        Component cp = FindNextComponent(NULL, &cd);
     1063        if (cp == 0)
     1064        {
     1065            LogRel(("CoreAudio: Failed to find HAL output component\n")); /** @todo Return error value? */
     1066            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1067        }
     1068
     1069        /* Open the default HAL output component. */
     1070        err = OpenAComponent(cp, &pStreamIn->audioUnit);
     1071        if (err != noErr)
     1072        {
     1073            LogRel(("CoreAudio: Failed to open output component (%RI32)\n", err));
     1074            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1075        }
     1076
     1077        /* Switch the I/O mode for input to on. */
     1078        UInt32 uFlag = 1;
     1079        err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
     1080                                   1, &uFlag, sizeof(uFlag));
     1081        if (err != noErr)
     1082        {
     1083            LogRel(("CoreAudio: Failed to disable input I/O mode for input stream (%RI32)\n", err));
     1084            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1085        }
     1086
     1087        /* Switch the I/O mode for output to off. This is important, as this is a pure input stream. */
     1088        uFlag = 0;
     1089        err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
     1090                                   0, &uFlag, sizeof(uFlag));
     1091        if (err != noErr)
     1092        {
     1093            LogRel(("CoreAudio: Failed to disable output I/O mode for input stream (%RI32)\n", err));
     1094            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1095        }
     1096
     1097        /* Set the default audio recording device as the device for the new AudioUnit. */
     1098        err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global,
     1099                                   0, &pStreamIn->deviceID, sizeof(pStreamIn->deviceID));
     1100        if (err != noErr)
     1101        {
     1102            LogRel(("CoreAudio: Failed to set current device (%RI32)\n", err));
     1103            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1104        }
     1105
     1106        /*
     1107         * CoreAudio will inform us on a second thread for new incoming audio data.
     1108         * Therefore register a callback function which will process the new data.
     1109         */
     1110        AURenderCallbackStruct cb;
     1111        RT_ZERO(cb);
     1112        cb.inputProc       = coreAudioRecordingCb;
     1113        cb.inputProcRefCon = pStreamIn;
     1114
     1115        err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global,
     1116                                   0, &cb, sizeof(cb));
     1117        if (err != noErr)
     1118        {
     1119            LogRel(("CoreAudio: Failed to register input callback (%RI32)\n", err));
     1120            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1121        }
     1122
     1123        /* Fetch the current stream format of the device. */
     1124        uSize = sizeof(pStreamIn->deviceFormat);
     1125        err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
     1126                                   1, &pStreamIn->deviceFormat, &uSize);
     1127        if (err != noErr)
     1128        {
     1129            LogRel(("CoreAudio: Failed to get device format (%RI32)\n", err));
     1130            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1131        }
     1132
     1133        /* Create an AudioStreamBasicDescription based on our required audio settings. */
     1134        coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat);
     1135
     1136        coreAudioPrintASBDesc("CoreAudio: Recording device", &pStreamIn->deviceFormat);
     1137        coreAudioPrintASBDesc("CoreAudio: Recording stream", &pStreamIn->streamFormat);
     1138
     1139        /* If the frequency of the device is different from the requested one we
     1140         * need a converter. The same count if the number of channels is different. */
     1141        if (   pStreamIn->deviceFormat.mSampleRate       != pStreamIn->streamFormat.mSampleRate
     1142            || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame)
     1143        {
     1144            LogRel(("CoreAudio: Input converter is active\n"));
     1145
     1146            err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter);
     1147            if (RT_UNLIKELY(err != noErr))
     1148            {
     1149                LogRel(("CoreAudio: Failed to create the audio converter (%RI32)\n", err));
     1150                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1151            }
     1152
     1153            if (   pStreamIn->deviceFormat.mChannelsPerFrame == 1 /* Mono */
     1154                && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */)
     1155            {
     1156                /*
     1157                 * If the channel count is different we have to tell this the converter
     1158                 * and supply a channel mapping. For now we only support mapping
     1159                 * from mono to stereo. For all other cases the core audio defaults
     1160                 * are used, which means dropping additional channels in most
     1161                 * cases.
     1162                 */
     1163                const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo, */
     1164
     1165                err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap);
     1166                if (err != noErr)
     1167                {
     1168                    LogRel(("CoreAudio: Failed to set channel mapping (mono -> stereo) for the audio input converter (%RI32)\n", err));
     1169                    CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1170                }
     1171            }
     1172#if 0
     1173            /* Set sample rate converter quality to maximum. */
     1174            uFlag = kAudioConverterQuality_Max;
     1175            err = AudioConverterSetProperty(pStreamIn->converter, kAudioConverterSampleRateConverterQuality,
     1176                                            sizeof(uFlag), &uFlag);
    11751177            if (err != noErr)
    1176             {
    1177                 LogRel(("CoreAudio: Failed to set channel mapping (mono -> stereo) for the audio input converter (%RI32)\n", err));
    1178                 return VERR_AUDIO_BACKEND_INIT_FAILED;
    1179             }
    1180         }
    1181 #if 0
    1182         /* Set sample rate converter quality to maximum */
    1183         uFlag = kAudioConverterQuality_Max;
    1184         err = AudioConverterSetProperty(pStreamIn->converter, kAudioConverterSampleRateConverterQuality,
    1185                                         sizeof(uFlag), &uFlag);
     1178                LogRel(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err));
     1179#endif
     1180            /* Set the new format description for the stream. */
     1181            err = AudioUnitSetProperty(pStreamIn->audioUnit,
     1182                                       kAudioUnitProperty_StreamFormat,
     1183                                       kAudioUnitScope_Output,
     1184                                       1,
     1185                                       &pStreamIn->deviceFormat,
     1186                                       sizeof(pStreamIn->deviceFormat));
     1187            if (RT_UNLIKELY(err != noErr))
     1188            {
     1189                LogRel(("CoreAudio: Failed to set input stream output format (%RI32)\n", err));
     1190                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1191            }
     1192
     1193            err = AudioUnitSetProperty(pStreamIn->audioUnit,
     1194                                       kAudioUnitProperty_StreamFormat,
     1195                                       kAudioUnitScope_Input,
     1196                                       1,
     1197                                       &pStreamIn->deviceFormat,
     1198                                       sizeof(pStreamIn->deviceFormat));
     1199            if (RT_UNLIKELY(err != noErr))
     1200            {
     1201                LogRel(("CoreAudio: Failed to set stream input format (%RI32)\n", err));
     1202                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1203            }
     1204        }
     1205        else
     1206        {
     1207
     1208            /* Set the new output format description for the input stream. */
     1209            err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
     1210                                       1, &pStreamIn->streamFormat, sizeof(pStreamIn->streamFormat));
     1211            if (err != noErr)
     1212            {
     1213                LogRel(("CoreAudio: Failed to set output format for input stream (%RI32)\n", err));
     1214                CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1215            }
     1216        }
     1217
     1218        /*
     1219         * Also set the frame buffer size off the device on our AudioUnit. This
     1220         * should make sure that the frames count which we receive in the render
     1221         * thread is as we like.
     1222         */
     1223        err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
     1224                                   1, &cFrames, sizeof(cFrames));
    11861225        if (err != noErr)
    1187             LogRel(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err));
    1188 #endif
    1189 
    1190         /* Set the new format description for the stream. */
    1191         err = AudioUnitSetProperty(pStreamIn->audioUnit,
    1192                                    kAudioUnitProperty_StreamFormat,
    1193                                    kAudioUnitScope_Output,
    1194                                    1,
    1195                                    &pStreamIn->deviceFormat,
    1196                                    sizeof(pStreamIn->deviceFormat));
    1197         if (RT_UNLIKELY(err != noErr))
    1198         {
    1199             LogRel(("CoreAudio: Failed to set input stream output format (%RI32)\n", err));
    1200             return VERR_AUDIO_BACKEND_INIT_FAILED;
    1201         }
    1202 
    1203         err = AudioUnitSetProperty(pStreamIn->audioUnit,
    1204                                    kAudioUnitProperty_StreamFormat,
    1205                                    kAudioUnitScope_Input,
    1206                                    1,
    1207                                    &pStreamIn->deviceFormat,
    1208                                    sizeof(pStreamIn->deviceFormat));
    1209         if (RT_UNLIKELY(err != noErr))
    1210         {
    1211             LogRel(("CoreAudio: Failed to set stream input format (%RI32)\n", err));
    1212             return VERR_AUDIO_BACKEND_INIT_FAILED;
    1213         }
    1214     }
    1215     else
    1216     {
    1217 
    1218         /* Set the new output format description for the input stream. */
    1219         err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
    1220                                    1, &pStreamIn->streamFormat, sizeof(pStreamIn->streamFormat));
     1226        {
     1227            LogRel(("CoreAudio: Failed to set maximum frame buffer size for input stream (%RI32)\n", err));
     1228            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1229        }
     1230
     1231        /* Finally initialize the new AudioUnit. */
     1232        err = AudioUnitInitialize(pStreamIn->audioUnit);
    12211233        if (err != noErr)
    12221234        {
    1223             LogRel(("CoreAudio: Failed to set output format for input stream (%RI32)\n", err));
    1224             return VERR_AUDIO_BACKEND_INIT_FAILED;
    1225         }
    1226     }
    1227 
    1228     /*
    1229      * Also set the frame buffer size off the device on our AudioUnit. This
    1230      * should make sure that the frames count which we receive in the render
    1231      * thread is as we like.
    1232      */
    1233     err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
    1234                                1, &cFrames, sizeof(cFrames));
    1235     if (err != noErr)    {
    1236         LogRel(("CoreAudio: Failed to set maximum frame buffer size for input stream (%RI32)\n", err));
    1237         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1238     }
    1239 
    1240     /* Finally initialize the new AudioUnit. */
    1241     err = AudioUnitInitialize(pStreamIn->audioUnit);
    1242     if (err != noErr)
    1243     {
    1244         LogRel(("CoreAudio: Failed to initialize audio unit for input stream (%RI32)\n", err));
    1245         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1246     }
    1247 
    1248     uSize = sizeof(pStreamIn->deviceFormat);
    1249     err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
    1250                                1, &pStreamIn->deviceFormat, &uSize);
    1251     if (err != noErr)
    1252     {
    1253         LogRel(("CoreAudio: Failed to get recording device format (%RI32)\n", err));
    1254         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1255     }
    1256 
    1257     /*
    1258      * There are buggy devices (e.g. my Bluetooth headset) which doesn't honor
    1259      * the frame buffer size set in the previous calls. So finally get the
    1260      * frame buffer size after the AudioUnit was initialized.
    1261      */
    1262     uSize = sizeof(cFrames);
    1263     err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
    1264                                0, &cFrames, &uSize);
    1265     if (err != noErr)
    1266     {
    1267         LogRel(("CoreAudio: Failed to get maximum frame buffer size from input audio device (%RI32)\n", err));
    1268         return VERR_AUDIO_BACKEND_INIT_FAILED;
    1269     }
    1270 
    1271     /* Destroy any former internal ring buffer. */
    1272     if (pStreamIn->pBuf)
    1273     {
    1274         RTCircBufDestroy(pStreamIn->pBuf);
    1275         pStreamIn->pBuf = NULL;
    1276     }
    1277 
    1278     /* Calculate the ratio between the device and the stream sample rate. */
    1279     pStreamIn->sampleRatio = pStreamIn->streamFormat.mSampleRate / pStreamIn->deviceFormat.mSampleRate;
    1280 
    1281     /* Create the AudioBufferList structure with one buffer. */
    1282     pStreamIn->bufferList.mNumberBuffers = 1;
    1283     /* Initialize the buffer to nothing. */
    1284     pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
    1285     pStreamIn->bufferList.mBuffers[0].mDataByteSize = 0;
    1286     pStreamIn->bufferList.mBuffers[0].mData = NULL;
    1287 
    1288     int rc = VINF_SUCCESS;
    1289 
    1290     /*
    1291      * Make sure that the ring buffer is big enough to hold the recording
    1292      * data. Compare the maximum frames per slice value with the frames
    1293      * necessary when using the converter where the sample rate could differ.
    1294      * The result is always multiplied by the channels per frame to get the
    1295      * samples count.
    1296      */
    1297     UInt32 cSamples = RT_MAX(cFrames,
    1298                              (cFrames * pStreamIn->deviceFormat.mBytesPerFrame * pStreamIn->sampleRatio)
    1299                               / pStreamIn->streamFormat.mBytesPerFrame)
    1300                              * pStreamIn->streamFormat.mChannelsPerFrame;
    1301     if (!cSamples)
    1302     {
    1303         LogRel(("CoreAudio: Failed to determine samples buffer count input stream\n"));
    1304         rc = VERR_INVALID_PARAMETER;
    1305     }
    1306 
    1307     /* Create the internal ring buffer. */
     1235            LogRel(("CoreAudio: Failed to initialize audio unit for input stream (%RI32)\n", err));
     1236            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1237        }
     1238
     1239        uSize = sizeof(pStreamIn->deviceFormat);
     1240        err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
     1241                                   1, &pStreamIn->deviceFormat, &uSize);
     1242        if (err != noErr)
     1243        {
     1244            LogRel(("CoreAudio: Failed to get recording device format (%RI32)\n", err));
     1245            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1246        }
     1247
     1248        /*
     1249         * There are buggy devices (e.g. my Bluetooth headset) which doesn't honor
     1250         * the frame buffer size set in the previous calls. So finally get the
     1251         * frame buffer size after the AudioUnit was initialized.
     1252         */
     1253        uSize = sizeof(cFrames);
     1254        err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
     1255                                   0, &cFrames, &uSize);
     1256        if (err != noErr)
     1257        {
     1258            LogRel(("CoreAudio: Failed to get maximum frame buffer size from input audio device (%RI32)\n", err));
     1259            CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED);
     1260        }
     1261
     1262        /* Destroy any former internal ring buffer. */
     1263        if (pStreamIn->pBuf)
     1264        {
     1265            RTCircBufDestroy(pStreamIn->pBuf);
     1266            pStreamIn->pBuf = NULL;
     1267        }
     1268
     1269        /* Calculate the ratio between the device and the stream sample rate. */
     1270        pStreamIn->sampleRatio = pStreamIn->streamFormat.mSampleRate / pStreamIn->deviceFormat.mSampleRate;
     1271
     1272        /* Create the AudioBufferList structure with one buffer. */
     1273        pStreamIn->bufferList.mNumberBuffers = 1;
     1274        /* Initialize the buffer to nothing. */
     1275        pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame;
     1276        pStreamIn->bufferList.mBuffers[0].mDataByteSize = 0;
     1277        pStreamIn->bufferList.mBuffers[0].mData = NULL;
     1278
     1279        /*
     1280         * Make sure that the ring buffer is big enough to hold the recording
     1281         * data. Compare the maximum frames per slice value with the frames
     1282         * necessary when using the converter where the sample rate could differ.
     1283         * The result is always multiplied by the channels per frame to get the
     1284         * samples count.
     1285         */
     1286        cSamples = RT_MAX(cFrames,
     1287                          (cFrames * pStreamIn->deviceFormat.mBytesPerFrame * pStreamIn->sampleRatio)
     1288                           / pStreamIn->streamFormat.mBytesPerFrame)
     1289                           * pStreamIn->streamFormat.mChannelsPerFrame;
     1290        if (!cSamples)
     1291        {
     1292            LogRel(("CoreAudio: Failed to determine samples buffer count input stream\n"));
     1293            CA_BREAK_STMT(rc = VERR_INVALID_PARAMETER);
     1294        }
     1295
     1296        /* Create the internal ring buffer. */
     1297        rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift);
     1298
     1299    } while (0);
     1300
    13081301    if (RT_SUCCESS(rc))
    1309         rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift);
    1310     if (RT_SUCCESS(rc))
    1311     {
    1312 #ifdef DEBUG
    1313         propAdr.mSelector = kAudioDeviceProcessorOverload;
    1314         propAdr.mScope    = kAudioUnitScope_Global;
    1315         err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
    1316                                              coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
    1317         if (RT_UNLIKELY(err != noErr))
    1318             LogRel(("CoreAudio: Failed to add the processor overload listener for input stream (%RI32)\n", err));
    1319 #endif /* DEBUG */
    1320         propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
    1321         propAdr.mScope    = kAudioUnitScope_Global;
    1322         err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr,
    1323                                              coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);
    1324         /* Not fatal. */
    1325         if (RT_UNLIKELY(err != noErr))
    1326             LogRel(("CoreAudio: Failed to register sample rate changed listener for input stream (%RI32)\n", err));
    1327     }
    1328 
    1329     if (RT_SUCCESS(rc))
    1330     {
    1331         /* Set callback context. */
    1332         pStreamIn->cbCtx.pThis  = pThis;
    1333         pStreamIn->cbCtx.enmDir = PDMAUDIODIR_IN;
    1334         pStreamIn->cbCtx.pIn    = pStreamIn;
    1335 
     1302    {
    13361303        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_INIT);
     1304
     1305        LogFunc(("cSamples=%RU32\n", cSamples));
    13371306
    13381307        if (pcSamples)
     
    13481317            pStreamIn->pBuf = NULL;
    13491318        }
    1350     }
    1351 
    1352     LogFunc(("cSamples=%RU32, rc=%Rrc\n", cSamples, rc));
     1319
     1320        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT);
     1321    }
     1322
     1323    LogFunc(("rc=%Rrc\n", rc));
    13531324    return rc;
    13541325}
     
    16161587    if (RT_SUCCESS(rc))
    16171588    {
    1618         /* Set callback context. */
    1619         pStreamOut->cbCtx.pThis  = pThis;
    1620         pStreamOut->cbCtx.enmDir = PDMAUDIODIR_OUT;
    1621         pStreamOut->cbCtx.pOut   = pStreamOut;
    1622 
    16231589        ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_INIT);
    16241590
     
    16501616    {
    16511617#ifdef DEBUG
    1652         case kAudioDeviceProcessorOverload:
    1653         {
    1654             Log2(("CoreAudio: [Output] Processor overload detected!\n"));
    1655             break;
    1656         }
    16571618#endif /* DEBUG */
    16581619        default:
     
    16711632                                                  AudioBufferList            *pBufData)
    16721633{
    1673     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;
    1674     PPDMAUDIOSTREAM pStream        = &pStreamOut->Stream;
     1634    PCOREAUDIOSTREAMOUT pStreamOut  = (PCOREAUDIOSTREAMOUT)pvUser;
     1635    PPDMAUDIOSTREAM     pStream     = &pStreamOut->Stream;
    16751636
    16761637    if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT)
     
    16811642
    16821643    /* How much space is used in the ring buffer? */
    1683     size_t cbDataAvail = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);
    1684     if (!cbDataAvail)
     1644    size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);
     1645    if (!cbToRead)
    16851646    {
    16861647        pBufData->mBuffers[0].mDataByteSize = 0;
     
    16891650
    16901651    uint8_t *pbSrc = NULL;
    1691     size_t cbRead = 0;
    1692     size_t cbToRead;
    1693     while (cbDataAvail)
     1652    size_t cbRead  = 0;
     1653
     1654    size_t cbLeft  = cbToRead;
     1655    while (cbLeft)
    16941656    {
    16951657        /* Try to acquire the necessary block from the ring buffer. */
    1696         RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbDataAvail, (void **)&pbSrc, &cbToRead);
     1658        RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbLeft, (void **)&pbSrc, &cbToRead);
    16971659
    16981660        /* Break if nothing is used anymore. */
     
    17101672        Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead);
    17111673
    1712         Assert(cbToRead <= cbDataAvail);
    1713         cbDataAvail -= cbToRead;
     1674        Assert(cbToRead <= cbLeft);
     1675        cbLeft -= cbToRead;
    17141676    }
    17151677
     
    17171679    pBufData->mBuffers[0].mDataByteSize = cbRead;
    17181680
    1719     LogFlowFunc(("CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail));
     1681    LogFlowFunc(("Read %zu / %zu bytes\n", cbRead, cbToRead));
    17201682
    17211683    return noErr;
     
    17431705    PPDMAUDIOSAMPLE psDst;
    17441706
    1745     /* Check if the audio device should be reinitialized. If so do it. */
    1746     if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT)
    1747         coreAudioReinitIn(pThis, &pStreamIn->Stream);
    1748 
    17491707    if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
    17501708    {
     
    17661724        size_t   cbToRead;
    17671725
    1768         LogFlowFunc(("cbBuf=%zu, cbToWrite=%zu\n", cbBuf, cbToWrite));
     1726        Log3Func(("cbBuf=%zu, cbToWrite=%zu\n", cbBuf, cbToWrite));
    17691727
    17701728        while (cbToWrite)
     
    17961754        }
    17971755
    1798         LogFlowFunc(("cbToWrite=%zu, cbToRead=%zu, cbWrittenTotal=%RU32, rc=%Rrc\n", cbToWrite, cbToRead, cbWrittenTotal, rc));
     1756        Log3Func(("cbToWrite=%zu, cbToRead=%zu, cbWrittenTotal=%RU32, rc=%Rrc\n", cbToWrite, cbToRead, cbWrittenTotal, rc));
    17991757    }
    18001758    while (0);
     
    18071765            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cCaptured);
    18081766
    1809         LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc));
     1767        Log3Func(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc));
     1768
     1769        if (cCaptured)
     1770            LogFlowFunc(("%RU32 samples captured\n", cCaptured));
    18101771
    18111772        if (pcSamplesCaptured)
     
    18131774    }
    18141775
    1815     LogFlowFuncLeaveRC(rc);
     1776    if (RT_FAILURE(rc))
     1777        LogFunc(("Failed with rc=%Rrc\n", rc));
     1778
    18161779    return rc;
    18171780}
     
    18261789
    18271790    int rc = VINF_SUCCESS;
    1828 
    1829     /* Check if the audio device should be reinitialized. If so do it. */
    1830     if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT)
    1831     {
    1832         rc = coreAudioReinitOut(pThis, &pStreamOut->Stream);
    1833         if (RT_FAILURE(rc))
    1834             return rc;
    1835     }
    1836 
    1837     /* Not much else to do here. */
    18381791
    18391792    uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
     
    19081861    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    19091862
    1910     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     1863    LogFlowFunc(("enmStreamCmd=%RU32\n", enmStreamCmd));
    19111864
    19121865    uint32_t uStatus = ASMAtomicReadU32(&pStreamOut->status);
     
    19841937    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    19851938
    1986     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     1939    LogFlowFunc(("enmStreamCmd=%RU32\n", enmStreamCmd));
    19871940
    19881941    uint32_t uStatus = ASMAtomicReadU32(&pStreamIn->status);
     
    20832036#ifdef DEBUG
    20842037        err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr,
    2085                                                 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
    2086         /* Not Fatal */
    2087         if (RT_UNLIKELY(err != noErr))
     2038                                                coreAudioRecordingAudioDevicePropertyChanged, &pStreamIn->cbCtx);
     2039        if (   err != noErr
     2040            && err != kAudioHardwareBadObjectError)
     2041        {
    20882042            LogRel(("CoreAudio: Failed to remove the recording processor overload listener (%RI32)\n", err));
     2043        }
    20892044#endif /* DEBUG */
    20902045
    20912046        propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
    20922047        err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr,
    2093                                                 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn);
    2094         /* Not Fatal */
    2095         if (RT_UNLIKELY(err != noErr))
     2048                                                coreAudioRecordingAudioDevicePropertyChanged, &pStreamIn->cbCtx);
     2049        if (   err != noErr
     2050            && err != kAudioHardwareBadObjectError)
     2051        {
    20962052            LogRel(("CoreAudio: Failed to remove the recording sample rate changed listener (%RI32)\n", err));
     2053        }
    20972054
    20982055        if (pStreamIn->fDefDevChgListReg)
     
    21002057            propAdr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
    21012058            err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr,
    2102                                                     coreAudioDefaultDeviceChanged, pStreamIn);
    2103             if (RT_LIKELY(err == noErr))
    2104             {
    2105                 pStreamIn->fDefDevChgListReg = false;
    2106             }
    2107             else
     2059                                                    coreAudioDefaultDeviceChanged, &pStreamIn->cbCtx);
     2060            if (   err != noErr
     2061                && err != kAudioHardwareBadObjectError)
     2062            {
    21082063                LogRel(("CoreAudio: Failed to remove the default recording device changed listener (%RI32)\n", err));
     2064            }
     2065
     2066            pStreamIn->fDefDevChgListReg = false;
    21092067        }
    21102068
    21112069        if (pStreamIn->fDevStateChgListReg)
    21122070        {
     2071            Assert(pStreamIn->deviceID != kAudioDeviceUnknown);
     2072
    21132073            AudioObjectPropertyAddress propAdr2 = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
    21142074                                                    kAudioObjectPropertyElementMaster };
    21152075            err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr2,
    21162076                                                    drvHostCoreAudioDeviceStateChanged, &pStreamIn->cbCtx);
    2117             if (RT_LIKELY(err == noErr))
    2118             {
    2119                 pStreamIn->fDevStateChgListReg = false;
    2120             }
    2121             else
     2077            if (   err != noErr
     2078                && err != kAudioHardwareBadObjectError)
     2079            {
    21222080                LogRel(("CoreAudio: Failed to remove the recording device state changed listener (%RI32)\n", err));
     2081            }
     2082
     2083            pStreamIn->fDevStateChgListReg = false;
    21232084        }
    21242085
     
    21302091
    21312092        err = AudioUnitUninitialize(pStreamIn->audioUnit);
    2132         if (RT_LIKELY(err == noErr))
    2133         {
     2093        if (err == noErr)
    21342094            err = CloseComponent(pStreamIn->audioUnit);
    2135             if (RT_LIKELY(err == noErr))
    2136             {
    2137                 pStreamIn->deviceID      = kAudioDeviceUnknown;
    2138                 pStreamIn->audioUnit     = NULL;
    2139                 pStreamIn->offBufferRead = 0;
    2140                 pStreamIn->sampleRatio   = 1;
    2141                 if (pStreamIn->pBuf)
    2142                 {
    2143                     RTCircBufDestroy(pStreamIn->pBuf);
    2144                     pStreamIn->pBuf = NULL;
    2145                 }
    2146 
    2147                 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT);
    2148             }
    2149             else
    2150             {
    2151                 LogRel(("CoreAudio: Failed to close the recording unit (%RI32)\n", err));
    2152                 rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
    2153             }
    2154         }
    2155         else
    2156         {
    2157             LogRel(("CoreAudio: Failed to uninitialize the recording unit (%RI32)\n", err));
    2158             rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
    2159         }
     2095
     2096        if (   err != noErr
     2097            && err != kAudioHardwareBadObjectError)
     2098        {
     2099            LogRel(("CoreAudio: Failed to uninit the recording device (%RI32)\n", err));
     2100        }
     2101
     2102        pStreamIn->deviceID      = kAudioDeviceUnknown;
     2103        pStreamIn->audioUnit     = NULL;
     2104        pStreamIn->offBufferRead = 0;
     2105        pStreamIn->sampleRatio   = 1;
     2106        if (pStreamIn->pBuf)
     2107        {
     2108            RTCircBufDestroy(pStreamIn->pBuf);
     2109            pStreamIn->pBuf = NULL;
     2110        }
     2111
     2112        ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT);
    21602113    }
    21612114    else
    2162     {
    2163         LogRel(("CoreAudio: Failed to stop recording (%RI32)\n", err));
    2164         rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
    2165     }
     2115        LogRel(("CoreAudio: Failed to stop recording on uninit, rc=%Rrc\n", rc));
    21662116
    21672117    LogFlowFuncLeaveRC(rc);
     
    21962146#ifdef DEBUG
    21972147        err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr,
    2198                                                 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
    2199         /* Not Fatal */
    2200         if (RT_UNLIKELY(err != noErr))
     2148                                                coreAudioPlaybackAudioDevicePropertyChanged, &pStreamOut->cbCtx);
     2149        if (   err != noErr
     2150            && err != kAudioHardwareBadObjectError)
     2151        {
    22012152            LogRel(("CoreAudio: Failed to remove the playback processor overload listener (%RI32)\n", err));
     2153        }
    22022154#endif /* DEBUG */
    22032155
    22042156        propAdr.mSelector = kAudioDevicePropertyNominalSampleRate;
    22052157        err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr,
    2206                                                 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);
    2207         /* Not Fatal */
    2208         if (RT_UNLIKELY(err != noErr))
     2158                                                coreAudioPlaybackAudioDevicePropertyChanged, &pStreamOut->cbCtx);
     2159        if (   err != noErr
     2160            && err != kAudioHardwareBadObjectError)
     2161        {
    22092162            LogRel(("CoreAudio: Failed to remove the playback sample rate changed listener (%RI32)\n", err));
     2163        }
    22102164
    22112165        if (pStreamOut->fDefDevChgListReg)
     
    22152169            propAdr.mElement  = kAudioObjectPropertyElementMaster;
    22162170            err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr,
    2217                                                     coreAudioDefaultDeviceChanged, pStreamOut);
    2218             if (RT_LIKELY(err == noErr))
    2219             {
    2220                 pStreamOut->fDefDevChgListReg = false;
    2221             }
    2222             else
     2171                                                    coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx);
     2172            if (   err != noErr
     2173                && err != kAudioHardwareBadObjectError)
     2174            {
    22232175                LogRel(("CoreAudio: Failed to remove the default playback device changed listener (%RI32)\n", err));
     2176            }
     2177
     2178            pStreamOut->fDefDevChgListReg = false;
    22242179        }
    22252180
    22262181        if (pStreamOut->fDevStateChgListReg)
    22272182        {
     2183            Assert(pStreamOut->deviceID != kAudioDeviceUnknown);
     2184
    22282185            AudioObjectPropertyAddress propAdr2 = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
    22292186                                                    kAudioObjectPropertyElementMaster };
    22302187            err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr2,
    22312188                                                    drvHostCoreAudioDeviceStateChanged, &pStreamOut->cbCtx);
    2232             if (RT_LIKELY(err == noErr))
    2233             {
    2234                 pStreamOut->fDevStateChgListReg = false;
    2235             }
    2236             else
     2189            if (   err != noErr
     2190                && err != kAudioHardwareBadObjectError)
     2191            {
    22372192                LogRel(("CoreAudio: Failed to remove the playback device state changed listener (%RI32)\n", err));
     2193            }
     2194
     2195            pStreamOut->fDevStateChgListReg = false;
    22382196        }
    22392197
    22402198        err = AudioUnitUninitialize(pStreamOut->audioUnit);
    22412199        if (err == noErr)
    2242         {
    22432200            err = CloseComponent(pStreamOut->audioUnit);
    2244             if (err == noErr)
    2245             {
    2246                 pStreamOut->deviceID  = kAudioDeviceUnknown;
    2247                 pStreamOut->audioUnit = NULL;
    2248                 if (pStreamOut->pBuf)
    2249                 {
    2250                     RTCircBufDestroy(pStreamOut->pBuf);
    2251                     pStreamOut->pBuf = NULL;
    2252                 }
    2253 
    2254                 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_UNINIT);
    2255             }
    2256             else
    2257                 LogRel(("CoreAudio: Failed to close the playback unit (%RI32)\n", err));
    2258         }
    2259         else
    2260             LogRel(("CoreAudio: Failed to uninitialize the playback unit (%RI32)\n", err));
     2201
     2202        if (   err != noErr
     2203            && err != kAudioHardwareBadObjectError)
     2204        {
     2205            LogRel(("CoreAudio: Failed to uninit the playback device (%RI32)\n", err));
     2206        }
     2207
     2208        pStreamOut->deviceID  = kAudioDeviceUnknown;
     2209        pStreamOut->audioUnit = NULL;
     2210        if (pStreamOut->pBuf)
     2211        {
     2212            RTCircBufDestroy(pStreamOut->pBuf);
     2213            pStreamOut->pBuf = NULL;
     2214        }
     2215
     2216        ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_UNINIT);
    22612217    }
    22622218    else
    2263         LogRel(("CoreAudio: Failed to stop playback, rc=%Rrc\n", rc));
     2219        LogRel(("CoreAudio: Failed to stop playback on uninit, rc=%Rrc\n", rc));
    22642220
    22652221    LogFlowFuncLeaveRC(rc);
     
    22712227{
    22722228    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    2273 
    2274     LogFlowFunc(("enmRecSource=%ld\n", pCfg->DestSource.Source));
    22752229
    22762230    pStreamIn->deviceID                  = kAudioDeviceUnknown;
     
    22852239    pStreamIn->fDevStateChgListReg       = false;
    22862240
     2241    /* Set callback context. */
     2242    pStreamIn->cbCtx.pThis  = pThis;
     2243    pStreamIn->cbCtx.enmDir = PDMAUDIODIR_IN;
     2244    pStreamIn->cbCtx.pIn    = pStreamIn;
     2245
    22872246    bool fDeviceByUser = false; /* Do we use a device which was set by the user? */
    22882247
    2289     /* Initialize the hardware info section with the audio settings */
     2248    LogFlowFunc(("enmRecSource=%RU32\n", pCfg->DestSource.Source));
     2249
    22902250    int rc = DrvAudioHlpStreamCfgToProps(pCfg, &pStreamIn->Stream.Props);
    22912251    if (RT_SUCCESS(rc))
     
    23062266    }
    23072267
    2308     if (RT_SUCCESS(rc))
    2309     {
    2310         OSStatus err;
    2311 
    2312         /* When the devices isn't forced by the user, we want default device change notifications. */
    2313         if (!fDeviceByUser)
     2268    OSStatus err;
     2269
     2270    /* When the devices isn't forced by the user, we want default device change notifications. */
     2271    if (!fDeviceByUser)
     2272    {
     2273        if (!pStreamIn->fDefDevChgListReg)
    23142274        {
    23152275            AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal,
     
    23172277            err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,
    23182278                                                 coreAudioDefaultDeviceChanged, &pStreamIn->cbCtx);
    2319             /* Not fatal. */
    2320             if (RT_LIKELY(err == noErr))
     2279            if (   err == noErr
     2280                || err == kAudioHardwareIllegalOperationError)
    23212281            {
    23222282                pStreamIn->fDefDevChgListReg = true;
     
    23252285                LogRel(("CoreAudio: Failed to add the default recording device changed listener (%RI32)\n", err));
    23262286        }
    2327 
     2287    }
     2288
     2289    if (   !pStreamIn->fDevStateChgListReg
     2290        && (pStreamIn->deviceID != kAudioDeviceUnknown))
     2291    {
    23282292        /* Register callback for being notified if the device stops being alive. */
    23292293        AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
     
    23312295        err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, drvHostCoreAudioDeviceStateChanged,
    23322296                                             &pStreamIn->cbCtx);
    2333         /* Not fatal. */
    2334         if (RT_LIKELY(err == noErr))
     2297        if (err == noErr)
    23352298        {
    23362299            pStreamIn->fDevStateChgListReg = true;
     
    23592322    pStreamOut->fDevStateChgListReg       = false;
    23602323
     2324    /* Set callback context. */
     2325    pStreamOut->cbCtx.pThis  = pThis;
     2326    pStreamOut->cbCtx.enmDir = PDMAUDIODIR_OUT;
     2327    pStreamOut->cbCtx.pOut   = pStreamOut;
     2328
    23612329    bool fDeviceByUser = false; /* Do we use a device which was set by the user? */
    23622330
    2363     /* Initialize the hardware info section with the audio settings */
     2331    /* If a stream configuration is given, apply that to the stream. */
    23642332    int rc = DrvAudioHlpStreamCfgToProps(pCfg, &pStreamOut->Stream.Props);
    23652333    if (RT_SUCCESS(rc))
     
    23822350    }
    23832351
    2384     if (RT_SUCCESS(rc))
    2385     {
    2386         OSStatus err;
    2387 
    2388         /* When the devices isn't forced by the user, we want default device change notifications. */
    2389         if (!fDeviceByUser)
    2390         {
    2391             AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal,
    2392                                                    kAudioObjectPropertyElementMaster };
    2393             err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,
    2394                                                  coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx);
    2395             /* Not fatal. */
    2396             if (RT_LIKELY(err == noErr))
    2397             {
    2398                 pStreamOut->fDefDevChgListReg = true;
    2399             }
    2400             else
    2401                 LogRel(("CoreAudio: Failed to add the default playback device changed listener (%RI32)\n", err));
    2402         }
    2403 
     2352    OSStatus err;
     2353
     2354    /* When the devices isn't forced by the user, we want default device change notifications. */
     2355    if (!fDeviceByUser)
     2356    {
     2357        AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal,
     2358                                               kAudioObjectPropertyElementMaster };
     2359        err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,
     2360                                             coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx);
     2361        if (err == noErr)
     2362        {
     2363            pStreamOut->fDefDevChgListReg = true;
     2364        }
     2365        else
     2366            LogRel(("CoreAudio: Failed to add the default playback device changed listener (%RI32)\n", err));
     2367    }
     2368
     2369    if (   !pStreamOut->fDevStateChgListReg
     2370        && (pStreamOut->deviceID != kAudioDeviceUnknown))
     2371    {
    24042372        /* Register callback for being notified if the device stops being alive. */
    24052373        AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal,
     
    24072375        err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr, drvHostCoreAudioDeviceStateChanged,
    24082376                                             &pStreamOut->cbCtx);
    2409         /* Not fatal. */
    2410         if (RT_LIKELY(err == noErr))
     2377        if (err == noErr)
    24112378        {
    24122379            pStreamOut->fDevStateChgListReg = true;
     
    24982465{
    24992466    NOREF(pInterface);
    2500     NOREF(pStream);
    2501 
    2502     PDMAUDIOSTRMSTS strmSts =   PDMAUDIOSTRMSTS_FLAG_INITIALIZED
    2503                               | PDMAUDIOSTRMSTS_FLAG_ENABLED;
     2467    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     2468
     2469    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     2470
     2471    PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_NONE;
    25042472
    25052473    if (pStream->enmDir == PDMAUDIODIR_IN)
    2506         strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE;
     2474    {
     2475        PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
     2476
     2477        if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_INIT)
     2478            strmSts |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED;
     2479
     2480        if (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     2481            strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE;
     2482    }
     2483    else if (pStream->enmDir == PDMAUDIODIR_OUT)
     2484    {
     2485        PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
     2486
     2487        if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_INIT)
     2488            strmSts |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED;
     2489
     2490        if (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     2491            strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
     2492    }
    25072493    else
    2508         strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
     2494        AssertFailed();
    25092495
    25102496    return strmSts;
     
    25152501    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    25162502    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    2517 
    2518     LogFlowFuncEnter();
    25192503
    25202504    /* Nothing to do here for Core Audio. */
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