VirtualBox

Changeset 89025 in vbox for trunk


Ignore:
Timestamp:
May 13, 2021 12:13:17 AM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioCoreAudio: Notification callback cleanups & writing todos. bugref:9890

File:
1 edited

Legend:

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

    r89024 r89025  
    234234    /** Pointer to host audio interface. */
    235235    PDMIHOSTAUDIO           IHostAudio;
    236     /** Critical section to serialize access. */
    237     RTCRITSECT              CritSect;
    238236    /** Current (last reported) device enumeration. */
    239237    PDMAUDIOHOSTENUM        Devices;
     
    250248    /** Indicates whether we've registered default output device change listener. */
    251249    bool                    fRegisteredDefaultOutputListener;
     250    /** Critical section to serialize access. */
     251    RTCRITSECT              CritSect;
    252252} DRVHOSTCOREAUDIO;
    253253
     
    267267DECLHIDDEN(int) coreAudioInputPermissionCheck(void); /* DrvHostAudioCoreAudioAuth.mm */
    268268static int drvHostCoreAudioStreamControlInternal(PCOREAUDIOSTREAM pStreamCA, PDMAUDIOSTREAMCMD enmStreamCmd);
    269 static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer,
    270                                                 const AudioTimeStamp *pAudioTS, UInt32 cPacketDesc,
    271                                                 const AudioStreamPacketDescription *paPacketDesc);
    272 static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer);
    273269
    274270
     
    438434}
    439435
    440 #endif /* VBOX_WITH_AUDIO_CA_CONVERTER */
    441 
    442 
    443 /**
    444  * Propagates an audio device status to all its connected Core Audio streams.
    445  *
    446  * @return IPRT status code.
    447  * @param  pDev                 Audio device to propagate status for.
    448  * @param  enmSts               Status to propagate.
    449  */
    450 static int coreAudioDevicePropagateStatus(PCOREAUDIODEVICEDATA pDev, COREAUDIOINITSTATE enmSts)
    451 {
    452     AssertPtrReturn(pDev, VERR_INVALID_POINTER);
    453 
    454 
    455     /* Sanity. */
    456     AssertPtr(pDev->pDrv);
    457 
    458     LogFlowFunc(("pDev=%p enmSts=%RU32\n", pDev, enmSts));
    459 
    460     PCOREAUDIOSTREAM pStreamCA;
    461     RTListForEach(&pDev->lstStreams, pStreamCA, COREAUDIOSTREAM, Node)
    462     {
    463         LogFlowFunc(("pStreamCA=%p\n", pStreamCA));
    464 
    465         /* We move the reinitialization to the next output event.
    466          * This make sure this thread isn't blocked and the
    467          * reinitialization is done when necessary only. */
    468         ASMAtomicWriteU32(&pStreamCA->enmInitState, enmSts);
    469     }
    470 
    471     return VINF_SUCCESS;
    472 }
    473 
    474 
    475 static DECLCALLBACK(OSStatus) coreAudioDeviceStateChangedCb(AudioObjectID propertyID,
    476                                                             UInt32 nAddresses,
    477                                                             const AudioObjectPropertyAddress properties[],
    478                                                             void *pvUser)
    479 {
    480     RT_NOREF(propertyID, nAddresses, properties);
    481 
    482     LogFlowFunc(("propertyID=%u, nAddresses=%u, pvUser=%p\n", propertyID, nAddresses, pvUser));
    483 
    484     PCOREAUDIODEVICEDATA pDev = (PCOREAUDIODEVICEDATA)pvUser;
    485     AssertPtr(pDev);
    486 
    487     PDRVHOSTCOREAUDIO pThis = pDev->pDrv;
    488     AssertPtr(pThis);
    489 
    490     int rc2 = RTCritSectEnter(&pThis->CritSect);
    491     AssertRC(rc2);
    492 
    493     UInt32 uAlive = 1;
    494     UInt32 uSize  = sizeof(UInt32);
    495 
    496     AudioObjectPropertyAddress PropAddr =
    497     {
    498         kAudioDevicePropertyDeviceIsAlive,
    499         kAudioObjectPropertyScopeGlobal,
    500         kAudioObjectPropertyElementMaster
    501     };
    502 
    503     AudioDeviceID deviceID = pDev->deviceID;
    504 
    505     OSStatus err = AudioObjectGetPropertyData(deviceID, &PropAddr, 0, NULL, &uSize, &uAlive);
    506 
    507     bool fIsDead = false;
    508 
    509     if (err == kAudioHardwareBadDeviceError)
    510         fIsDead = true; /* Unplugged. */
    511     else if ((err == kAudioHardwareNoError) && (!RT_BOOL(uAlive)))
    512         fIsDead = true; /* Something else happened. */
    513 
    514     if (fIsDead)
    515     {
    516         LogRel2(("CoreAudio: Device '%s' stopped functioning\n", pDev->Core.szName));
    517 
    518         /* Mark device as dead. */
    519         rc2 = coreAudioDevicePropagateStatus(pDev, COREAUDIOINITSTATE_UNINIT);
    520         AssertRC(rc2);
    521     }
    522 
    523     rc2 = RTCritSectLeave(&pThis->CritSect);
    524     AssertRC(rc2);
    525 
    526     return noErr;
    527 }
    528 
    529 /* Callback for getting notified when the default recording/playback device has been changed. */
    530 /** @todo r=bird: Why DECLCALLBACK? */
    531 static DECLCALLBACK(OSStatus) coreAudioDefaultDeviceChangedCb(AudioObjectID propertyID,
    532                                                               UInt32 nAddresses,
    533                                                               const AudioObjectPropertyAddress properties[],
    534                                                               void *pvUser)
    535 {
    536     RT_NOREF(propertyID, nAddresses);
    537 
    538     LogFlowFunc(("propertyID=%u, nAddresses=%u, pvUser=%p\n", propertyID, nAddresses, pvUser));
    539 
    540     PDRVHOSTCOREAUDIO pThis = (PDRVHOSTCOREAUDIO)pvUser;
    541     AssertPtr(pThis);
    542 
    543     int rc2 = RTCritSectEnter(&pThis->CritSect);
    544     AssertRC(rc2);
    545 
    546     for (UInt32 idxAddress = 0; idxAddress < nAddresses; idxAddress++)
    547     {
    548         PCOREAUDIODEVICEDATA pDev = NULL;
    549 
    550         /*
    551          * Check if the default input / output device has been changed.
    552          */
    553         const AudioObjectPropertyAddress *pProperty = &properties[idxAddress];
    554         switch (pProperty->mSelector)
    555         {
    556             case kAudioHardwarePropertyDefaultInputDevice:
    557                 LogFlowFunc(("kAudioHardwarePropertyDefaultInputDevice\n"));
    558                 pDev = pThis->pDefaultDevIn;
    559                 break;
    560 
    561             case kAudioHardwarePropertyDefaultOutputDevice:
    562                 LogFlowFunc(("kAudioHardwarePropertyDefaultOutputDevice\n"));
    563                 pDev = pThis->pDefaultDevOut;
    564                 break;
    565 
    566             default:
    567                 /* Skip others. */
    568                 break;
    569         }
    570 
    571         LogFlowFunc(("pDev=%p\n", pDev));
    572     }
    573 
    574     /* Make sure to leave the critical section before notify higher drivers/devices. */
    575     rc2 = RTCritSectLeave(&pThis->CritSect);
    576     AssertRC(rc2);
    577 
    578     /* Notify the driver/device above us about possible changes in devices. */
    579     if (pThis->pIHostAudioPort)
    580         pThis->pIHostAudioPort->pfnNotifyDevicesChanged(pThis->pIHostAudioPort);
    581 
    582     return noErr;
    583 }
    584 
    585 
    586 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
    587436/* Callback to convert audio input data from one format to another. */
    588 static DECLCALLBACK(OSStatus) coreAudioConverterCb(AudioConverterRef              inAudioConverter,
    589                                                    UInt32                        *ioNumberDataPackets,
    590                                                    AudioBufferList               *ioData,
    591                                                    AudioStreamPacketDescription **ppASPD,
    592                                                    void                          *pvUser)
     437static OSStatus coreAudioConverterCb(AudioConverterRef              inAudioConverter,
     438                                     UInt32                        *ioNumberDataPackets,
     439                                     AudioBufferList               *ioData,
     440                                     AudioStreamPacketDescription **ppASPD,
     441                                     void                          *pvUser)
    593442{
    594443    RT_NOREF(inAudioConverter);
     
    646495            ioData->mBuffers[0].mData           = pvAvail;
    647496
    648 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
     497# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    649498            RTFILE fh;
    650499            int rc = RTFileOpen(&fh,VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "caConverterCbInput.pcm",
     
    657506            else
    658507                AssertFailed();
    659 #endif
     508# endif
    660509            pConvCbCtx->uPacketIdx += cNumberDataPackets;
    661510            Assert(pConvCbCtx->uPacketIdx <= pConvCbCtx->uPacketCnt);
     
    670519    return noErr;
    671520}
     521
    672522#endif /* VBOX_WITH_AUDIO_CA_CONVERTER */
     523
     524
     525/*********************************************************************************************************************************
     526*   Device Change Notification Callbacks                                                                                         *
     527*********************************************************************************************************************************/
     528
     529/**
     530 * Called when the kAudioDevicePropertyNominalSampleRate or
     531 * kAudioDeviceProcessorOverload properties changes on a default device.
     532 *
     533 * Registered on default devices after device enumeration.
     534 * Not sure on which thread/runloop this runs.
     535 *
     536 * (See AudioObjectPropertyListenerProc in the SDK headers.)
     537 */
     538static OSStatus drvHostAudioCaDevicePropertyChangedCallback(AudioObjectID idObject, UInt32 cAddresses,
     539                                                            const AudioObjectPropertyAddress paAddresses[], void *pvUser)
     540{
     541    PCOREAUDIODEVICEDATA pDev = (PCOREAUDIODEVICEDATA)pvUser;
     542    AssertPtr(pDev);
     543    RT_NOREF(pDev, cAddresses, paAddresses);
     544
     545    LogFlowFunc(("idObject=%#x (%u) cAddresses=%u pDev=%p\n", idObject, idObject, cAddresses, pDev));
     546    for (UInt32 idx = 0; idx < cAddresses; idx++)
     547        LogFlowFunc(("  #%u: sel=%#x scope=%#x element=%#x\n",
     548                     idx, paAddresses[idx].mSelector, paAddresses[idx].mScope, paAddresses[idx].mElement));
     549
     550/** @todo r=bird: What's the plan here exactly?   */
     551    switch (idObject)
     552    {
     553        case kAudioDeviceProcessorOverload:
     554            LogFunc(("Processor overload detected!\n"));
     555            break;
     556        case kAudioDevicePropertyNominalSampleRate:
     557            LogFunc(("kAudioDevicePropertyNominalSampleRate!\n"));
     558            break;
     559        default:
     560            /* Just skip. */
     561            break;
     562    }
     563
     564    return noErr;
     565}
     566
     567
     568/**
     569 * Propagates an audio device status to all its Core Audio streams.
     570 *
     571 * @param  pDev     Audio device to propagate status for.
     572 * @param  enmSts   Status to propagate.
     573 */
     574static void drvHostAudioCaDevicePropagateStatus(PCOREAUDIODEVICEDATA pDev, COREAUDIOINITSTATE enmSts)
     575{
     576    /* Sanity. */
     577    AssertPtr(pDev);
     578    AssertPtr(pDev->pDrv);
     579
     580    LogFlowFunc(("pDev=%p enmSts=%RU32\n", pDev, enmSts));
     581
     582    PCOREAUDIOSTREAM pStreamCA;
     583    RTListForEach(&pDev->lstStreams, pStreamCA, COREAUDIOSTREAM, Node)
     584    {
     585        LogFlowFunc(("pStreamCA=%p\n", pStreamCA));
     586
     587        /* We move the reinitialization to the next output event.
     588         * This make sure this thread isn't blocked and the
     589         * reinitialization is done when necessary only. */
     590/** @todo r=bird: This is now extremely bogus, see comment in caller. */
     591        ASMAtomicWriteU32(&pStreamCA->enmInitState, enmSts);
     592    }
     593}
     594
     595
     596/**
     597 * Called when the kAudioDevicePropertyDeviceIsAlive property changes on a
     598 * default device.
     599 *
     600 * Registered on default devices after device enumeration.
     601 * Not sure on which thread/runloop this runs.
     602 *
     603 * (See AudioObjectPropertyListenerProc in the SDK headers.)
     604 */
     605static OSStatus drvHostAudioCaDeviceIsAliveChangedCallback(AudioObjectID idObject, UInt32 cAddresses,
     606                                                           const AudioObjectPropertyAddress paAddresses[], void *pvUser)
     607{
     608    PCOREAUDIODEVICEDATA pDev = (PCOREAUDIODEVICEDATA)pvUser;
     609    AssertPtr(pDev);
     610    PDRVHOSTCOREAUDIO    pThis = pDev->pDrv;
     611    AssertPtr(pThis);
     612    RT_NOREF(idObject, cAddresses, paAddresses);
     613
     614    LogFlowFunc(("idObject=%#x (%u) cAddresses=%u pDev=%p\n", idObject, idObject, cAddresses, pDev));
     615    for (UInt32 idx = 0; idx < cAddresses; idx++)
     616        LogFlowFunc(("  #%u: sel=%#x scope=%#x element=%#x\n",
     617                     idx, paAddresses[idx].mSelector, paAddresses[idx].mScope, paAddresses[idx].mElement));
     618
     619    int rc = RTCritSectEnter(&pThis->CritSect);
     620    AssertRC(rc);
     621
     622    UInt32 uAlive = 1;
     623    UInt32 uSize  = sizeof(UInt32);
     624
     625    AudioObjectPropertyAddress PropAddr =
     626    {
     627        kAudioDevicePropertyDeviceIsAlive,
     628        kAudioObjectPropertyScopeGlobal,
     629        kAudioObjectPropertyElementMaster
     630    };
     631
     632    OSStatus err = AudioObjectGetPropertyData(pDev->deviceID, &PropAddr, 0, NULL, &uSize, &uAlive);
     633
     634    bool fIsDead = false;
     635    if (err == kAudioHardwareBadDeviceError)
     636        fIsDead = true; /* Unplugged. */
     637    else if (err == kAudioHardwareNoError && !RT_BOOL(uAlive))
     638        fIsDead = true; /* Something else happened. */
     639
     640    if (fIsDead)
     641    {
     642        LogRel2(("CoreAudio: Device '%s' stopped functioning\n", pDev->Core.szName));
     643
     644        /* Mark device as dead. */
     645/** @todo r=bird: This is certifiably insane given how StreamDestroy does absolutely _nothing_ unless the init state is INIT.
     646 * The queue thread will be running and trashing random heap if it tries to modify anything in the stream structure. */
     647        drvHostAudioCaDevicePropagateStatus(pDev, COREAUDIOINITSTATE_UNINIT);
     648    }
     649
     650    RTCritSectLeave(&pThis->CritSect);
     651    return noErr;
     652}
     653
     654
     655/**
     656 * Called when the default recording or playback device has changed.
     657 *
     658 * Registered by the constructor.  Not sure on which thread/runloop this runs.
     659 *
     660 * (See AudioObjectPropertyListenerProc in the SDK headers.)
     661 */
     662static OSStatus drvHostAudioCaDefaultDeviceChangedCallback(AudioObjectID idObject, UInt32 cAddresses,
     663                                                           const AudioObjectPropertyAddress *paAddresses, void *pvUser)
     664
     665{
     666    PDRVHOSTCOREAUDIO pThis = (PDRVHOSTCOREAUDIO)pvUser;
     667    AssertPtr(pThis);
     668    LogFunc(("idObject=%#x (%u) cAddresses=%u\n", idObject, idObject, cAddresses));
     669    RT_NOREF(idObject);
     670
     671    //int rc2 = RTCritSectEnter(&pThis->CritSect);
     672    //AssertRC(rc2);
     673
     674    for (UInt32 idxAddress = 0; idxAddress < cAddresses; idxAddress++)
     675    {
     676        /// @todo r=bird: what's the plan here? PCOREAUDIODEVICEDATA pDev = NULL;
     677
     678        /*
     679         * Check if the default input / output device has been changed.
     680         */
     681        const AudioObjectPropertyAddress *pProperty = &paAddresses[idxAddress];
     682        switch (pProperty->mSelector)
     683        {
     684            case kAudioHardwarePropertyDefaultInputDevice:
     685                LogFlowFunc(("#%u: sel=kAudioHardwarePropertyDefaultInputDevice scope=%#x element=%#x\n",
     686                             idxAddress, pProperty->mScope, pProperty->mElement));
     687                //pDev = pThis->pDefaultDevIn;
     688                break;
     689
     690            case kAudioHardwarePropertyDefaultOutputDevice:
     691                LogFlowFunc(("#%u: sel=kAudioHardwarePropertyDefaultOutputDevice scope=%#x element=%#x\n",
     692                             idxAddress, pProperty->mScope, pProperty->mElement));
     693                //pDev = pThis->pDefaultDevOut;
     694                break;
     695
     696            default:
     697                LogFlowFunc(("#%u: sel=%#x scope=%#x element=%#x\n",
     698                             idxAddress, pProperty->mSelector, pProperty->mScope, pProperty->mElement));
     699                break;
     700        }
     701    }
     702
     703    /* Make sure to leave the critical section before notify higher drivers/devices. */
     704    //rc2 = RTCritSectLeave(&pThis->CritSect);
     705    //AssertRC(rc2);
     706
     707    /*
     708     * Notify the driver/device above us about possible changes in devices.
     709     */
     710    if (pThis->pIHostAudioPort)
     711        pThis->pIHostAudioPort->pfnNotifyDevicesChanged(pThis->pIHostAudioPort);
     712
     713    return noErr;
     714}
     715
     716
     717/*********************************************************************************************************************************
     718*   Queue Thread                                                                                                                 *
     719*********************************************************************************************************************************/
     720
     721/**
     722 * Processes output data of a Core Audio stream into an audio queue buffer.
     723 *
     724 * @returns IPRT status code.
     725 * @param   pStreamCA           Core Audio stream to process output data for.
     726 * @param   audioBuffer         Audio buffer to store data into.
     727 */
     728static int coreAudioOutputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
     729{
     730    AssertPtr(pStreamCA);
     731
     732    PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
     733    AssertPtr(pCircBuf);
     734
     735    size_t cbRead = 0;
     736
     737    UInt8 *pvSrc = NULL;
     738    UInt8 *pvDst = (UInt8 *)audioBuffer->mAudioData;
     739
     740    size_t cbToRead = RT_MIN(RTCircBufUsed(pCircBuf), audioBuffer->mAudioDataBytesCapacity);
     741    size_t cbLeft   = cbToRead;
     742
     743    while (cbLeft)
     744    {
     745        /* Try to acquire the necessary block from the ring buffer. */
     746        RTCircBufAcquireReadBlock(pCircBuf, cbLeft, (void **)&pvSrc, &cbToRead);
     747
     748        if (cbToRead)
     749        {
     750            /* Copy the data from our ring buffer to the core audio buffer. */
     751            memcpy((UInt8 *)pvDst + cbRead, pvSrc, cbToRead);
     752        }
     753
     754        /* Release the read buffer, so it could be used for new data. */
     755        RTCircBufReleaseReadBlock(pCircBuf, cbToRead);
     756
     757        if (!cbToRead)
     758            break;
     759
     760        /* Move offset. */
     761        cbRead += cbToRead;
     762        Assert(cbRead <= audioBuffer->mAudioDataBytesCapacity);
     763
     764        Assert(cbToRead <= cbLeft);
     765        cbLeft -= cbToRead;
     766    }
     767
     768    audioBuffer->mAudioDataByteSize = cbRead;
     769
     770    if (audioBuffer->mAudioDataByteSize < audioBuffer->mAudioDataBytesCapacity)
     771    {
     772        RT_BZERO((UInt8 *)audioBuffer->mAudioData + audioBuffer->mAudioDataByteSize,
     773                 audioBuffer->mAudioDataBytesCapacity - audioBuffer->mAudioDataByteSize);
     774
     775        audioBuffer->mAudioDataByteSize = audioBuffer->mAudioDataBytesCapacity;
     776    }
     777
     778    Log3Func(("pStreamCA=%p, cbCapacity=%RU32, cbRead=%zu\n",
     779              pStreamCA, audioBuffer->mAudioDataBytesCapacity, cbRead));
     780
     781    return VINF_SUCCESS;
     782}
     783
     784
     785/**
     786 * Output audio queue callback.
     787 *
     788 * Called whenever an audio queue is ready to process more output data.
     789 *
     790 * @param   pvUser              User argument.
     791 * @param   hAudioQueue         Audio queue to process output data for.
     792 * @param   audioBuffer         Audio buffer to store output data in. Must be part of audio queue.
     793 *
     794 * @thread  queue thread.
     795 */
     796static void coreAudioOutputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer)
     797{
     798    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
     799    AssertPtr(pStreamCA);
     800
     801    int rc = RTCritSectEnter(&pStreamCA->CritSect);
     802    AssertRC(rc);
     803
     804    rc = coreAudioOutputQueueProcBuffer(pStreamCA, audioBuffer);
     805    if (RT_SUCCESS(rc))
     806        AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
     807
     808    rc = RTCritSectLeave(&pStreamCA->CritSect);
     809    AssertRC(rc);
     810}
     811
     812
     813/**
     814 * Processes input data of an audio queue buffer and stores it into a Core Audio stream.
     815 *
     816 * @returns IPRT status code.
     817 * @param   pStreamCA           Core Audio stream to store input data into.
     818 * @param   audioBuffer         Audio buffer to process input data from.
     819 */
     820static int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
     821{
     822    PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
     823    AssertPtr(pCircBuf);
     824
     825    UInt8 *pvSrc = (UInt8 *)audioBuffer->mAudioData;
     826    UInt8 *pvDst = NULL;
     827
     828    size_t cbWritten = 0;
     829
     830    size_t cbToWrite = audioBuffer->mAudioDataByteSize;
     831    size_t cbLeft    = RT_MIN(cbToWrite, RTCircBufFree(pCircBuf));
     832
     833    while (cbLeft)
     834    {
     835        /* Try to acquire the necessary block from the ring buffer. */
     836        RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, (void **)&pvDst, &cbToWrite);
     837
     838        if (!cbToWrite)
     839            break;
     840
     841        /* Copy the data from our ring buffer to the core audio buffer. */
     842        /** @todo r=bird: WTF is the (UInt8 *) cast for? Despite the 'pv' prefix, pvDst
     843         * is a UInt8 pointer.  Whoever wrote this crap needs to check his/her
     844         * medication.  I shouldn't have to wast my time fixing crap like this! */
     845        memcpy((UInt8 *)pvDst, pvSrc + cbWritten, cbToWrite);
     846
     847        /* Release the read buffer, so it could be used for new data. */
     848        RTCircBufReleaseWriteBlock(pCircBuf, cbToWrite);
     849
     850        cbWritten += cbToWrite;
     851
     852        Assert(cbLeft >= cbToWrite);
     853        cbLeft -= cbToWrite;
     854    }
     855
     856    Log3Func(("pStreamCA=%p, cbBuffer=%RU32/%zu, cbWritten=%zu\n",
     857              pStreamCA, audioBuffer->mAudioDataByteSize, audioBuffer->mAudioDataBytesCapacity, cbWritten));
     858
     859    return VINF_SUCCESS;
     860}
     861
     862
     863/**
     864 * Input audio queue callback.
     865 *
     866 * Called whenever input data from the audio queue becomes available.
     867 *
     868 * @param   pvUser              User argument.
     869 * @param   hAudioQueue         Audio queue to process input data from.
     870 * @param   audioBuffer         Audio buffer to process input data from. Must be part of audio queue.
     871 * @param   pAudioTS            Audio timestamp.
     872 * @param   cPacketDesc         Number of packet descriptors.
     873 * @param   paPacketDesc        Array of packet descriptors.
     874 */
     875static void coreAudioInputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer,
     876                                  const AudioTimeStamp *pAudioTS,
     877                                  UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
     878{
     879    RT_NOREF(pAudioTS, cPacketDesc, paPacketDesc);
     880
     881    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
     882    AssertPtr(pStreamCA);
     883
     884    int rc = RTCritSectEnter(&pStreamCA->CritSect);
     885    AssertRC(rc);
     886
     887    rc = coreAudioInputQueueProcBuffer(pStreamCA, audioBuffer);
     888    if (RT_SUCCESS(rc))
     889        AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
     890
     891    rc = RTCritSectLeave(&pStreamCA->CritSect);
     892    AssertRC(rc);
     893}
    673894
    674895
     
    752973            LogRel(("CoreAudio: Failed to associate device with queue: %#x (%d)\n", orc, orc));
    753974
    754         AudioQueueDispose(pStreamCA->hAudioQueue, 1);
     975        AudioQueueDispose(pStreamCA->hAudioQueue, TRUE /*inImmediate*/);
    755976    }
    756977    else
     
    763984}
    764985
    765 /**
    766  * Processes input data of an audio queue buffer and stores it into a Core Audio stream.
    767  *
    768  * @returns IPRT status code.
    769  * @param   pStreamCA           Core Audio stream to store input data into.
    770  * @param   audioBuffer         Audio buffer to process input data from.
    771  */
    772 static int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
    773 {
    774     PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
    775     AssertPtr(pCircBuf);
    776 
    777     UInt8 *pvSrc = (UInt8 *)audioBuffer->mAudioData;
    778     UInt8 *pvDst = NULL;
    779 
    780     size_t cbWritten = 0;
    781 
    782     size_t cbToWrite = audioBuffer->mAudioDataByteSize;
    783     size_t cbLeft    = RT_MIN(cbToWrite, RTCircBufFree(pCircBuf));
    784 
    785     while (cbLeft)
    786     {
    787         /* Try to acquire the necessary block from the ring buffer. */
    788         RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, (void **)&pvDst, &cbToWrite);
    789 
    790         if (!cbToWrite)
    791             break;
    792 
    793         /* Copy the data from our ring buffer to the core audio buffer. */
    794         /** @todo r=bird: WTF is the (UInt8 *) cast for? Despite the 'pv' prefix, pvDst
    795          * is a UInt8 pointer.  Whoever wrote this crap needs to check his/her
    796          * medication.  I shouldn't have to wast my time fixing crap like this! */
    797         memcpy((UInt8 *)pvDst, pvSrc + cbWritten, cbToWrite);
    798 
    799         /* Release the read buffer, so it could be used for new data. */
    800         RTCircBufReleaseWriteBlock(pCircBuf, cbToWrite);
    801 
    802         cbWritten += cbToWrite;
    803 
    804         Assert(cbLeft >= cbToWrite);
    805         cbLeft -= cbToWrite;
    806     }
    807 
    808     Log3Func(("pStreamCA=%p, cbBuffer=%RU32/%zu, cbWritten=%zu\n",
    809               pStreamCA, audioBuffer->mAudioDataByteSize, audioBuffer->mAudioDataBytesCapacity, cbWritten));
    810 
    811     return VINF_SUCCESS;
    812 }
    813 
    814 /**
    815  * Input audio queue callback. Called whenever input data from the audio queue becomes available.
    816  *
    817  * @param   pvUser              User argument.
    818  * @param   hAudioQueue         Audio queue to process input data from.
    819  * @param   audioBuffer         Audio buffer to process input data from. Must be part of audio queue.
    820  * @param   pAudioTS            Audio timestamp.
    821  * @param   cPacketDesc         Number of packet descriptors.
    822  * @param   paPacketDesc        Array of packet descriptors.
    823  */
    824 static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer,
    825                                                 const AudioTimeStamp *pAudioTS,
    826                                                 UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
    827 {
    828     RT_NOREF(pAudioTS, cPacketDesc, paPacketDesc);
    829 
    830     PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
    831     AssertPtr(pStreamCA);
    832 
    833     int rc = RTCritSectEnter(&pStreamCA->CritSect);
    834     AssertRC(rc);
    835 
    836     rc = coreAudioInputQueueProcBuffer(pStreamCA, audioBuffer);
    837     if (RT_SUCCESS(rc))
    838         AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
    839 
    840     rc = RTCritSectLeave(&pStreamCA->CritSect);
    841     AssertRC(rc);
    842 }
    843 
    844 /**
    845  * Processes output data of a Core Audio stream into an audio queue buffer.
    846  *
    847  * @returns IPRT status code.
    848  * @param   pStreamCA           Core Audio stream to process output data for.
    849  * @param   audioBuffer         Audio buffer to store data into.
    850  */
    851 int coreAudioOutputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
    852 {
    853     AssertPtr(pStreamCA);
    854 
    855     PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
    856     AssertPtr(pCircBuf);
    857 
    858     size_t cbRead = 0;
    859 
    860     UInt8 *pvSrc = NULL;
    861     UInt8 *pvDst = (UInt8 *)audioBuffer->mAudioData;
    862 
    863     size_t cbToRead = RT_MIN(RTCircBufUsed(pCircBuf), audioBuffer->mAudioDataBytesCapacity);
    864     size_t cbLeft   = cbToRead;
    865 
    866     while (cbLeft)
    867     {
    868         /* Try to acquire the necessary block from the ring buffer. */
    869         RTCircBufAcquireReadBlock(pCircBuf, cbLeft, (void **)&pvSrc, &cbToRead);
    870 
    871         if (cbToRead)
    872         {
    873             /* Copy the data from our ring buffer to the core audio buffer. */
    874             memcpy((UInt8 *)pvDst + cbRead, pvSrc, cbToRead);
    875         }
    876 
    877         /* Release the read buffer, so it could be used for new data. */
    878         RTCircBufReleaseReadBlock(pCircBuf, cbToRead);
    879 
    880         if (!cbToRead)
    881             break;
    882 
    883         /* Move offset. */
    884         cbRead += cbToRead;
    885         Assert(cbRead <= audioBuffer->mAudioDataBytesCapacity);
    886 
    887         Assert(cbToRead <= cbLeft);
    888         cbLeft -= cbToRead;
    889     }
    890 
    891     audioBuffer->mAudioDataByteSize = cbRead;
    892 
    893     if (audioBuffer->mAudioDataByteSize < audioBuffer->mAudioDataBytesCapacity)
    894     {
    895         RT_BZERO((UInt8 *)audioBuffer->mAudioData + audioBuffer->mAudioDataByteSize,
    896                  audioBuffer->mAudioDataBytesCapacity - audioBuffer->mAudioDataByteSize);
    897 
    898         audioBuffer->mAudioDataByteSize = audioBuffer->mAudioDataBytesCapacity;
    899     }
    900 
    901     Log3Func(("pStreamCA=%p, cbCapacity=%RU32, cbRead=%zu\n",
    902               pStreamCA, audioBuffer->mAudioDataBytesCapacity, cbRead));
    903 
    904     return VINF_SUCCESS;
    905 }
    906 
    907 /**
    908  * Output audio queue callback. Called whenever an audio queue is ready to process more output data.
    909  *
    910  * @param   pvUser              User argument.
    911  * @param   hAudioQueue         Audio queue to process output data for.
    912  * @param   audioBuffer         Audio buffer to store output data in. Must be part of audio queue.
    913  */
    914 static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer)
    915 {
    916     PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
    917     AssertPtr(pStreamCA);
    918 
    919     int rc = RTCritSectEnter(&pStreamCA->CritSect);
    920     AssertRC(rc);
    921 
    922     rc = coreAudioOutputQueueProcBuffer(pStreamCA, audioBuffer);
    923     if (RT_SUCCESS(rc))
    924         AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
    925 
    926     rc = RTCritSectLeave(&pStreamCA->CritSect);
    927     AssertRC(rc);
    928 }
    929986
    930987/**
     
    9651022
    9661023    return rc;
    967 }
    968 
    969 
    970 /* Callback for getting notified when some of the properties of an audio device have changed. */
    971 static DECLCALLBACK(OSStatus) coreAudioDevPropChgCb(AudioObjectID                     propertyID,
    972                                                     UInt32                            cAddresses,
    973                                                     const AudioObjectPropertyAddress  properties[],
    974                                                     void                             *pvUser)
    975 {
    976     RT_NOREF(cAddresses, properties, pvUser);
    977 
    978     PCOREAUDIODEVICEDATA pDev = (PCOREAUDIODEVICEDATA)pvUser;
    979     AssertPtr(pDev);
    980 
    981     LogFlowFunc(("propertyID=%u, nAddresses=%u, pDev=%p\n", propertyID, cAddresses, pDev));
    982 
    983     switch (propertyID)
    984     {
    985 #ifdef DEBUG
    986        case kAudioDeviceProcessorOverload:
    987         {
    988             LogFunc(("Processor overload detected!\n"));
    989             break;
    990         }
    991 #endif /* DEBUG */
    992         case kAudioDevicePropertyNominalSampleRate:
    993         {
    994             RT_NOREF(pDev);
    995             break;
    996         }
    997 
    998         default:
    999             /* Just skip. */
    1000             break;
    1001     }
    1002 
    1003     return noErr;
    10041024}
    10051025
     
    14791499            kAudioObjectPropertyElementMaster
    14801500        };
    1481         OSStatus err = AudioObjectAddPropertyListener(deviceID, &PropAddr, coreAudioDeviceStateChangedCb, pDev /* pvUser */);
     1501        OSStatus err = AudioObjectAddPropertyListener(deviceID, &PropAddr,
     1502                                                      drvHostAudioCaDeviceIsAliveChangedCallback, pDev /*pvUser*/);
    14821503        if (   err != noErr
    14831504            && err != kAudioHardwareIllegalOperationError)
     
    14861507        PropAddr.mSelector = kAudioDeviceProcessorOverload;
    14871508        PropAddr.mScope    = kAudioUnitScope_Global;
    1488         err = AudioObjectAddPropertyListener(deviceID, &PropAddr, coreAudioDevPropChgCb, pDev /* pvUser */);
     1509        err = AudioObjectAddPropertyListener(deviceID, &PropAddr, drvHostAudioCaDevicePropertyChangedCallback, pDev /* pvUser */);
    14891510        if (err != noErr)
    14901511            LogRel(("CoreAudio: Failed to register processor overload listener (%RI32)\n", err));
     
    14921513        PropAddr.mSelector = kAudioDevicePropertyNominalSampleRate;
    14931514        PropAddr.mScope    = kAudioUnitScope_Global;
    1494         err = AudioObjectAddPropertyListener(deviceID, &PropAddr, coreAudioDevPropChgCb, pDev /* pvUser */);
     1515        err = AudioObjectAddPropertyListener(deviceID, &PropAddr, drvHostAudioCaDevicePropertyChangedCallback, pDev /* pvUser */);
    14951516        if (err != noErr)
    14961517            LogRel(("CoreAudio: Failed to register sample rate changed listener (%RI32)\n", err));
     
    15301551            kAudioObjectPropertyElementMaster
    15311552        };
    1532         OSStatus err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, coreAudioDevPropChgCb, pDev /* pvUser */);
     1553        OSStatus err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, drvHostAudioCaDevicePropertyChangedCallback, pDev /* pvUser */);
    15331554        if (   err != noErr
    15341555            && err != kAudioHardwareBadObjectError)
     
    15361557
    15371558        PropAddr.mSelector = kAudioDevicePropertyNominalSampleRate;
    1538         err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, coreAudioDevPropChgCb, pDev /* pvUser */);
     1559        err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, drvHostAudioCaDevicePropertyChangedCallback, pDev /* pvUser */);
    15391560        if (   err != noErr
    15401561            && err != kAudioHardwareBadObjectError)
     
    15421563
    15431564        PropAddr.mSelector = kAudioDevicePropertyDeviceIsAlive;
    1544         err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, coreAudioDeviceStateChangedCb, pDev /* pvUser */);
     1565        err = AudioObjectRemovePropertyListener(deviceID, &PropAddr, drvHostAudioCaDeviceIsAliveChangedCallback, pDev /* pvUser */);
    15451566        if (   err != noErr
    15461567            && err != kAudioHardwareBadObjectError)
     
    21782199    if (pThis->fRegisteredDefaultInputListener)
    21792200    {
    2180         orc = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &PropAddr, coreAudioDefaultDeviceChangedCb, pThis);
     2201        orc = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &PropAddr, drvHostAudioCaDefaultDeviceChangedCallback, pThis);
    21812202        if (   orc != noErr
    21822203            && orc != kAudioHardwareBadObjectError)
     
    21892210
    21902211        PropAddr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
    2191         orc = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &PropAddr, coreAudioDefaultDeviceChangedCb, pThis);
     2212        orc = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &PropAddr, drvHostAudioCaDefaultDeviceChangedCallback, pThis);
    21922213        if (   orc != noErr
    21932214            && orc != kAudioHardwareBadObjectError)
     
    22832304    };
    22842305
    2285     OSStatus orc = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &PropAddr, coreAudioDefaultDeviceChangedCb, pThis);
     2306    OSStatus orc = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &PropAddr, drvHostAudioCaDefaultDeviceChangedCallback, pThis);
    22862307    pThis->fRegisteredDefaultInputListener = orc == noErr;
    22872308    if (   orc != noErr
     
    22902311
    22912312    PropAddr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
    2292     orc = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &PropAddr, coreAudioDefaultDeviceChangedCb, pThis);
     2313    orc = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &PropAddr, drvHostAudioCaDefaultDeviceChangedCallback, pThis);
    22932314    pThis->fRegisteredDefaultOutputListener = orc == noErr;
    22942315    if (   orc != noErr
Note: See TracChangeset for help on using the changeset viewer.

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