VirtualBox

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


Ignore:
Timestamp:
May 12, 2021 10:05:33 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144361
Message:

DrvHostAudioCoreAudio: Cleanups. bugref:9890

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

Legend:

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

    r88993 r89022  
    22042204        drvAudioStreamResetInternal(pStreamEx);
    22052205
     2206/** @todo
     2207 *  We need to zero the backend storage here!!
     2208 *  We need to zero the backend storage here!!
     2209 *  We need to zero the backend storage here!!
     2210 *  We need to zero the backend storage here!!
     2211 *  We need to zero the backend storage here!!
     2212 *  We need to zero the backend storage here!!
     2213 *  We need to zero the backend storage here!!
     2214 *   */
    22062215        PDMAUDIOSTREAMCFG CfgHostAcq;
    22072216        rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, &pStreamEx->Host.Cfg, &CfgHostAcq);
  • trunk/src/VBox/Devices/Audio/DrvHostAudioCoreAudio.cpp

    r89009 r89022  
    22/** @file
    33 * Host audio driver - Mac OS X CoreAudio.
     4 *
     5 * For relevant Apple documentation, here are some starters:
     6 *     - http://developer.apple.com/mac/library/technotes/tn2004/tn2097.html
     7 *     - http://developer.apple.com/mac/library/technotes/tn2002/tn2091.html
     8 *     - http://developer.apple.com/mac/library/qa/qa2007/qa1533.html
     9 *     - http://developer.apple.com/mac/library/qa/qa2001/qa1317.html
     10 *     - http://developer.apple.com/mac/library/documentation/AudioUnit/Reference/AUComponentServicesReference/Reference/reference.html
    411 */
    512
     
    5663 */
    5764
    58 /*
    59  * Most of this is based on:
    60  * http://developer.apple.com/mac/library/technotes/tn2004/tn2097.html
    61  * http://developer.apple.com/mac/library/technotes/tn2002/tn2091.html
    62  * http://developer.apple.com/mac/library/qa/qa2007/qa1533.html
    63  * http://developer.apple.com/mac/library/qa/qa2001/qa1317.html
    64  * http://developer.apple.com/mac/library/documentation/AudioUnit/Reference/AUComponentServicesReference/Reference/reference.html
    65  */
    66 
    67 /* Prototypes needed for COREAUDIODEVICE. */
    68 struct DRVHOSTCOREAUDIO;
     65
     66/*********************************************************************************************************************************
     67*   Structures and Typedefs                                                                                                      *
     68*********************************************************************************************************************************/
     69/** Pointer to the instance data for a Core Audio driver instance.  */
    6970typedef struct DRVHOSTCOREAUDIO *PDRVHOSTCOREAUDIO;
    70 
    71 /**
    72  * Core Audio-specific device entry.
     71/** Pointer to the Core Audio specific backend data for an audio stream. */
     72typedef struct COREAUDIOSTREAM *PCOREAUDIOSTREAM;
     73
     74/**
     75 * Core Audio device entry (enumeration).
    7376 *
    7477 * @note This is definitely not safe to just copy!
     
    7780{
    7881    /** The core PDM structure. */
    79     PDMAUDIOHOSTDEV      Core;
     82    PDMAUDIOHOSTDEV     Core;
    8083
    8184    /** Pointer to driver instance this device is bound to. */
     
    8992    RTLISTANCHOR        lstStreams;
    9093} COREAUDIODEVICEDATA;
     94/** Pointer to a Core Audio device entry (enumeration). */
    9195typedef COREAUDIODEVICEDATA *PCOREAUDIODEVICEDATA;
    9296
    93 /**
    94  * Host Coreaudio driver instance data.
     97
     98/**
     99 * Core Audio stream state.
     100 */
     101typedef enum COREAUDIOINITSTATE
     102{
     103    /** The device is uninitialized. */
     104    COREAUDIOINITSTATE_UNINIT = 0,
     105    /** The device is currently initializing. */
     106    COREAUDIOINITSTATE_IN_INIT,
     107    /** The device is initialized. */
     108    COREAUDIOINITSTATE_INIT,
     109    /** The device is currently uninitializing. */
     110    COREAUDIOINITSTATE_IN_UNINIT,
     111    /** The usual 32-bit hack. */
     112    COREAUDIOINITSTATE_32BIT_HACK = 0x7fffffff
     113} COREAUDIOINITSTATE;
     114
     115
     116#ifdef VBOX_WITH_AUDIO_CA_CONVERTER
     117/**
     118 * Context data for the audio format converter.
     119 */
     120typedef struct COREAUDIOCONVCBCTX
     121{
     122    /** Pointer to the stream this context is bound to. */
     123    PCOREAUDIOSTREAM             pStream; /**< @todo r=bird: It's part of the COREAUDIOSTREAM structure! You don't need this. */
     124    /** Source stream description. */
     125    AudioStreamBasicDescription  asbdSrc;
     126    /** Destination stream description. */
     127    AudioStreamBasicDescription  asbdDst;
     128    /** Pointer to native buffer list used for rendering the source audio data into. */
     129    AudioBufferList             *pBufLstSrc;
     130    /** Total packet conversion count. */
     131    UInt32                       uPacketCnt;
     132    /** Current packet conversion index. */
     133    UInt32                       uPacketIdx;
     134    /** Error count, for limiting the logging. */
     135    UInt32                       cErrors;
     136} COREAUDIOCONVCBCTX;
     137/** Pointer to the context of a conversion callback. */
     138typedef COREAUDIOCONVCBCTX *PCOREAUDIOCONVCBCTX;
     139#endif /* VBOX_WITH_AUDIO_CA_CONVERTER */
     140
     141
     142/**
     143 * Core Audio specific data for an audio stream.
     144 */
     145typedef struct COREAUDIOSTREAM
     146{
     147    /** Common part. */
     148    PDMAUDIOBACKENDSTREAM       Core;
     149
     150    /** The stream's acquired configuration. */
     151    PDMAUDIOSTREAMCFG           Cfg;
     152    /** Stream-specific data, depending on the stream type. */
     153    union
     154    {
     155        struct
     156        {
     157#if 0 /* Unused */
     158            /** The ratio between the device & the stream sample rate. */
     159            Float64             sampleRatio;
     160#endif
     161#ifdef VBOX_WITH_AUDIO_CA_CONVERTER
     162            /** The audio converter if necessary. NULL if no converter is being used. */
     163            AudioConverterRef   ConverterRef;
     164            /** Callback context for the audio converter. */
     165            COREAUDIOCONVCBCTX  convCbCtx;
     166#endif
     167        } In;
     168        //struct {}      Out;
     169    };
     170    /** List node for the device's stream list. */
     171    RTLISTNODE                  Node;
     172    /** Pointer to driver instance this stream is bound to. */
     173    PDRVHOSTCOREAUDIO           pDrv;
     174    /** The stream's thread handle for maintaining the audio queue. */
     175    RTTHREAD                    hThread;
     176    /** The runloop of the queue thread. */
     177    CFRunLoopRef                hRunLoop;
     178    /** Flag indicating to start a stream's data processing. */
     179    bool                        fRun;
     180    /** Whether the stream is in a running (active) state or not.
     181     *  For playback streams this means that audio data can be (or is being) played,
     182     *  for capturing streams this means that audio data is being captured (if available). */
     183    bool                        fIsRunning;
     184    /** Thread shutdown indicator. */
     185    bool volatile               fShutdown;
     186    /** The actual audio queue being used. */
     187    AudioQueueRef               hAudioQueue;
     188    /** The audio buffers which are used with the above audio queue. */
     189    AudioQueueBufferRef         apAudioBuffers[2];
     190    /** The acquired (final) audio format for this stream. */
     191    AudioStreamBasicDescription asbdStream;
     192    /** The audio unit for this stream. */
     193    struct
     194    {
     195        /** Pointer to the device this audio unit is bound to.
     196         *  Can be NULL if not bound to a device (anymore). */
     197        PCOREAUDIODEVICEDATA    pDevice;
     198#if 0 /* not used */
     199        /** The actual audio unit object. */
     200        AudioUnit                   hAudioUnit;
     201        /** Stream description for using with VBox:
     202         *  - When using this audio unit for input (capturing), this format states
     203         *    the unit's output format.
     204         *  - When using this audio unit for output (playback), this format states
     205         *    the unit's input format. */
     206        AudioStreamBasicDescription StreamFmt;
     207#endif
     208    } Unit;
     209    /** Initialization status tracker, actually COREAUDIOINITSTATE.
     210     * Used when some of the device parameters or the device itself is changed
     211     * during the runtime. */
     212    volatile uint32_t           enmInitState;
     213    /** An internal ring buffer for transferring data from/to the rendering callbacks. */
     214    PRTCIRCBUF                  pCircBuf;
     215    /** Critical section for serializing access between thread + callbacks. */
     216    RTCRITSECT                  CritSect;
     217} COREAUDIOSTREAM;
     218
     219
     220/**
     221 * Instance data for a Core Audio host audio driver.
     222 *
    95223 * @implements PDMIAUDIOCONNECTOR
    96224 */
     
    114242    PPDMIHOSTAUDIOPORT      pIHostAudioPort;
    115243    /** Indicates whether we've registered default input device change listener. */
    116     bool                     fRegisteredDefaultInputListener;
     244    bool                    fRegisteredDefaultInputListener;
    117245    /** Indicates whether we've registered default output device change listener. */
    118     bool                     fRegisteredDefaultOutputListener;
    119 } DRVHOSTCOREAUDIO, *PDRVHOSTCOREAUDIO;
    120 
    121 /** Converts a pointer to DRVHOSTCOREAUDIO::IHostAudio to a PDRVHOSTCOREAUDIO. */
    122 #define PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface) RT_FROM_MEMBER(pInterface, DRVHOSTCOREAUDIO, IHostAudio)
    123 
    124 /**
    125  * Structure for holding a Core Audio unit
    126  * and its data.
    127  */
    128 typedef struct COREAUDIOUNIT
    129 {
    130     /** Pointer to the device this audio unit is bound to.
    131      *  Can be NULL if not bound to a device (anymore). */
    132     PCOREAUDIODEVICEDATA        pDevice;
    133     /** The actual audio unit object. */
    134     AudioUnit                   audioUnit;
    135     /** Stream description for using with VBox:
    136      *  - When using this audio unit for input (capturing), this format states
    137      *    the unit's output format.
    138      *  - When using this audio unit for output (playback), this format states
    139      *    the unit's input format. */
    140     AudioStreamBasicDescription streamFmt;
    141 } COREAUDIOUNIT, *PCOREAUDIOUNIT;
    142 
    143 
    144 DECLHIDDEN(int) coreAudioInputPermissionCheck(void);
     246    bool                    fRegisteredDefaultOutputListener;
     247} DRVHOSTCOREAUDIO;
    145248
    146249
    147250/*********************************************************************************************************************************
    148 *   Helper function section                                                                                                      *
     251*   Global Variables                                                                                                             *
    149252*********************************************************************************************************************************/
    150 
    151 /* Move these down below the internal function prototypes... */
     253#ifdef VBOX_WITH_AUDIO_CA_CONVERTER
     254/** Error code which indicates "End of data" */
     255static const OSStatus g_rcCoreAudioConverterEOFDErr = 0x656F6664; /* 'eofd' */
     256#endif
     257
     258
     259/*********************************************************************************************************************************
     260*   Internal Functions                                                                                                           *
     261*********************************************************************************************************************************/
     262DECLHIDDEN(int) coreAudioInputPermissionCheck(void); /* DrvHostAudioCoreAudioAuth.mm */
     263static int drvHostCoreAudioStreamControlInternal(PCOREAUDIOSTREAM pStreamCA, PDMAUDIOSTREAMCMD enmStreamCmd);
     264static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer,
     265                                                const AudioTimeStamp *pAudioTS, UInt32 cPacketDesc,
     266                                                const AudioStreamPacketDescription *paPacketDesc);
     267static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer);
     268
     269
     270
    152271
    153272static void coreAudioPrintASBD(const char *pszDesc, const AudioStreamBasicDescription *pASBD)
     
    184303}
    185304
     305
    186306static void coreAudioPCMPropsToASBD(PCPDMAUDIOPCMPROPS pProps, AudioStreamBasicDescription *pASBD)
    187307{
     
    258378
    259379
    260 /*********************************************************************************************************************************
    261 *   Structures and Typedefs                                                                                                      *
    262 *********************************************************************************************************************************/
    263 
    264 /** @name Initialization status indicator used for the recreation of the AudioUnits.
    265  *
    266  * Global structures section
    267  *
    268  ******************************************************************************/
    269 
    270 /**
    271  * Enumeration for a Core Audio stream status.
    272  */
    273 typedef enum COREAUDIOSTATUS
    274 {
    275     /** The device is uninitialized. */
    276     COREAUDIOSTATUS_UNINIT  = 0,
    277     /** The device is currently initializing. */
    278     COREAUDIOSTATUS_IN_INIT,
    279     /** The device is initialized. */
    280     COREAUDIOSTATUS_INIT,
    281     /** The device is currently uninitializing. */
    282     COREAUDIOSTATUS_IN_UNINIT,
    283     /** The usual 32-bit hack. */
    284     COREAUDIOSTATUS_32BIT_HACK = 0x7fffffff
    285 } COREAUDIOSTATUS, *PCOREAUDIOSTATUS;
    286 
    287 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
    288  /* Error code which indicates "End of data" */
    289  static const OSStatus caConverterEOFDErr = 0x656F6664; /* 'eofd' */
    290 #endif
    291 
    292 /* Prototypes needed for COREAUDIOSTREAMCBCTX. */
    293 struct COREAUDIOSTREAM;
    294 typedef struct COREAUDIOSTREAM *PCOREAUDIOSTREAM;
    295 
    296 /**
    297  * Structure for keeping a conversion callback context.
    298  * This is needed when using an audio converter during input/output processing.
    299  */
    300 typedef struct COREAUDIOCONVCBCTX
    301 {
    302     /** Pointer to the stream this context is bound to. */
    303     PCOREAUDIOSTREAM             pStream;
    304     /** Source stream description. */
    305     AudioStreamBasicDescription  asbdSrc;
    306     /** Destination stream description. */
    307     AudioStreamBasicDescription  asbdDst;
    308     /** Pointer to native buffer list used for rendering the source audio data into. */
    309     AudioBufferList             *pBufLstSrc;
    310     /** Total packet conversion count. */
    311     UInt32                       uPacketCnt;
    312     /** Current packet conversion index. */
    313     UInt32                       uPacketIdx;
    314     /** Error count, for limiting the logging. */
    315     UInt32                       cErrors;
    316 } COREAUDIOCONVCBCTX, *PCOREAUDIOCONVCBCTX;
    317 
    318 /**
    319  * Structure for keeping the input stream specifics.
    320  */
    321 typedef struct COREAUDIOSTREAMIN
    322 {
    323 #ifdef VBOX_WITH_AUDIO_CA_CONVERTER
    324     /** The audio converter if necessary. NULL if no converter is being used. */
    325     AudioConverterRef           ConverterRef;
    326     /** Callback context for the audio converter. */
    327     COREAUDIOCONVCBCTX          convCbCtx;
    328 #endif
    329     /** The ratio between the device & the stream sample rate. */
    330     Float64                     sampleRatio;
    331 } COREAUDIOSTREAMIN, *PCOREAUDIOSTREAMIN;
    332 
    333 /**
    334  * Structure for keeping the output stream specifics.
    335  */
    336 typedef struct COREAUDIOSTREAMOUT
    337 {
    338     /** Nothing here yet. */
    339 } COREAUDIOSTREAMOUT, *PCOREAUDIOSTREAMOUT;
    340 
    341 /**
    342  * Structure for maintaining a Core Audio stream.
    343  */
    344 typedef struct COREAUDIOSTREAM
    345 {
    346     /** Common part. */
    347     PDMAUDIOBACKENDSTREAM       Core;
    348 
    349     /** The stream's acquired configuration. */
    350     PPDMAUDIOSTREAMCFG          pCfg;
    351     /** Stream-specific data, depending on the stream type. */
    352     union
    353     {
    354         COREAUDIOSTREAMIN       In;
    355         COREAUDIOSTREAMOUT      Out;
    356     };
    357     /** List node for the device's stream list. */
    358     RTLISTNODE                  Node;
    359     /** Pointer to driver instance this stream is bound to. */
    360     PDRVHOSTCOREAUDIO           pDrv;
    361     /** The stream's thread handle for maintaining the audio queue. */
    362     RTTHREAD                    hThread;
    363     /** Flag indicating to start a stream's data processing. */
    364     bool                        fRun;
    365     /** Whether the stream is in a running (active) state or not.
    366      *  For playback streams this means that audio data can be (or is being) played,
    367      *  for capturing streams this means that audio data is being captured (if available). */
    368     bool                        fIsRunning;
    369     /** Thread shutdown indicator. */
    370     bool                        fShutdown;
    371     /** Critical section for serializing access between thread + callbacks. */
    372     RTCRITSECT                  CritSect;
    373     /** The actual audio queue being used. */
    374     AudioQueueRef               audioQueue;
    375     /** The audio buffers which are used with the above audio queue. */
    376     AudioQueueBufferRef         audioBuffer[2];
    377     /** The acquired (final) audio format for this stream. */
    378     AudioStreamBasicDescription asbdStream;
    379     /** The audio unit for this stream. */
    380     COREAUDIOUNIT               Unit;
    381     /** Initialization status tracker, actually COREAUDIOSTATUS.
    382      * Used when some of the device parameters or the device itself is changed
    383      * during the runtime. */
    384     volatile uint32_t           enmStatus;
    385     /** An internal ring buffer for transferring data from/to the rendering callbacks. */
    386     PRTCIRCBUF                  pCircBuf;
    387 } COREAUDIOSTREAM, *PCOREAUDIOSTREAM;
    388 
    389 
    390 /*********************************************************************************************************************************
    391 *   Internal Functions                                                                                                           *
    392 *********************************************************************************************************************************/
    393 static int coreAudioStreamUninit(PCOREAUDIOSTREAM pCAStream);
    394 
    395 static int coreAudioStreamControl(PDRVHOSTCOREAUDIO pThis, PCOREAUDIOSTREAM pCAStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    396 
    397 static int coreAudioStreamInitQueue(PCOREAUDIOSTREAM pCAStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
    398 static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer,
    399                                                 const AudioTimeStamp *pAudioTS, UInt32 cPacketDesc,
    400                                                 const AudioStreamPacketDescription *paPacketDesc);
    401 static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer);
    402 
    403 
    404380#ifdef VBOX_WITH_AUDIO_CA_CONVERTER
    405381
     
    467443 * @param  enmSts               Status to propagate.
    468444 */
    469 static int coreAudioDevicePropagateStatus(PCOREAUDIODEVICEDATA pDev, COREAUDIOSTATUS enmSts)
     445static int coreAudioDevicePropagateStatus(PCOREAUDIODEVICEDATA pDev, COREAUDIOINITSTATE enmSts)
    470446{
    471447    AssertPtrReturn(pDev, VERR_INVALID_POINTER);
     
    477453    LogFlowFunc(("pDev=%p enmSts=%RU32\n", pDev, enmSts));
    478454
    479     PCOREAUDIOSTREAM pCAStream;
    480     RTListForEach(&pDev->lstStreams, pCAStream, COREAUDIOSTREAM, Node)
    481     {
    482         LogFlowFunc(("pCAStream=%p\n", pCAStream));
     455    PCOREAUDIOSTREAM pStreamCA;
     456    RTListForEach(&pDev->lstStreams, pStreamCA, COREAUDIOSTREAM, Node)
     457    {
     458        LogFlowFunc(("pStreamCA=%p\n", pStreamCA));
    483459
    484460        /* We move the reinitialization to the next output event.
    485461         * This make sure this thread isn't blocked and the
    486462         * reinitialization is done when necessary only. */
    487         ASMAtomicXchgU32(&pCAStream->enmStatus, enmSts);
     463        ASMAtomicWriteU32(&pStreamCA->enmInitState, enmSts);
    488464    }
    489465
     
    536512
    537513        /* Mark device as dead. */
    538         rc2 = coreAudioDevicePropagateStatus(pDev, COREAUDIOSTATUS_UNINIT);
     514        rc2 = coreAudioDevicePropagateStatus(pDev, COREAUDIOINITSTATE_UNINIT);
    539515        AssertRC(rc2);
    540516    }
     
    613589    RT_NOREF(inAudioConverter);
    614590
    615     AssertPtrReturn(ioNumberDataPackets, caConverterEOFDErr);
    616     AssertPtrReturn(ioData,              caConverterEOFDErr);
     591    AssertPtrReturn(ioNumberDataPackets, g_rcCoreAudioConverterEOFDErr);
     592    AssertPtrReturn(ioData,              g_rcCoreAudioConverterEOFDErr);
    617593
    618594    PCOREAUDIOCONVCBCTX pConvCbCtx = (PCOREAUDIOCONVCBCTX)pvUser;
     
    693669
    694670/**
    695  * Thread for a Core Audio stream's audio queue handling.
     671 * @callback_method_impl{FNRTTHREAD,
     672 * Thread for a Core Audio stream's audio queue handling.}
    696673 *
    697674 * This thread is required per audio queue to pump data to/from the Core Audio
    698675 * stream and handling its callbacks.
    699  *
    700  * @returns IPRT status code.
    701  * @param   hThreadSelf         Thread handle.
    702  * @param   pvUser              User argument.
    703676 */
    704677static DECLCALLBACK(int) coreAudioQueueThread(RTTHREAD hThreadSelf, void *pvUser)
    705678{
    706     RT_NOREF(hThreadSelf);
    707 
    708     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pvUser;
    709     AssertPtr(pCAStream);
    710     AssertPtr(pCAStream->pCfg);
    711 
    712     const bool fIn = pCAStream->pCfg->enmDir == PDMAUDIODIR_IN;
    713 
    714     LogFunc(("Thread started for pCAStream=%p, fIn=%RTbool\n", pCAStream, fIn));
     679    PCOREAUDIOSTREAM           pStreamCA = (PCOREAUDIOSTREAM)pvUser;
     680    AssertPtr(pStreamCA);
     681    const bool                 fIn       = pStreamCA->Cfg.enmDir == PDMAUDIODIR_IN;
     682    PCOREAUDIODEVICEDATA const pDev      = (PCOREAUDIODEVICEDATA)pStreamCA->Unit.pDevice;
     683    CFRunLoopRef const         hRunLoop  = CFRunLoopGetCurrent();
     684    AssertPtr(pDev);
     685
     686    LogFunc(("Thread started for pStreamCA=%p fIn=%RTbool\n", pStreamCA, fIn));
    715687
    716688    /*
    717689     * Create audio queue.
    718690     */
    719     OSStatus err;
     691    int rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     692    OSStatus orc;
    720693    if (fIn)
    721         err = AudioQueueNewInput(&pCAStream->asbdStream, coreAudioInputQueueCb, pCAStream /* pvData */,
    722                                  CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &pCAStream->audioQueue);
     694        orc = AudioQueueNewInput(&pStreamCA->asbdStream, coreAudioInputQueueCb, pStreamCA /* pvData */,
     695                                 CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &pStreamCA->hAudioQueue);
    723696    else
    724         err = AudioQueueNewOutput(&pCAStream->asbdStream, coreAudioOutputQueueCb, pCAStream /* pvData */,
    725                                   CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &pCAStream->audioQueue);
    726 
    727     if (err != noErr)
    728         return VERR_GENERAL_FAILURE; /** @todo Fudge! */
    729 
    730     /*
    731      * Assign device to queue.
    732      */
    733     PCOREAUDIODEVICEDATA pDev = (PCOREAUDIODEVICEDATA)pCAStream->Unit.pDevice;
    734     AssertPtr(pDev);
    735 
    736     UInt32 uSize = sizeof(pDev->UUID);
    737     err = AudioQueueSetProperty(pCAStream->audioQueue, kAudioQueueProperty_CurrentDevice, &pDev->UUID, uSize);
    738     if (err != noErr)
    739         return VERR_GENERAL_FAILURE; /** @todo Fudge! */
    740 
    741     const size_t cbBufSize = PDMAudioPropsFramesToBytes(&pCAStream->pCfg->Props, pCAStream->pCfg->Backend.cFramesPeriod);
    742 
    743     /*
    744      * Allocate audio buffers.
    745      */
    746     for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++)
    747     {
    748         err = AudioQueueAllocateBuffer(pCAStream->audioQueue, cbBufSize, &pCAStream->audioBuffer[i]);
    749         if (err != noErr)
    750             break;
    751     }
    752 
    753     if (err != noErr)
    754         return VERR_GENERAL_FAILURE; /** @todo Fudge! */
    755 
    756     /* Signal the main thread before entering the main loop. */
    757     RTThreadUserSignal(RTThreadSelf());
    758 
    759     /*
    760      * Enter the main loop.
    761      */
    762     while (!ASMAtomicReadBool(&pCAStream->fShutdown))
    763     {
    764         CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
    765     }
    766 
    767     /*
    768      * Cleanup.
    769      */
    770     if (fIn)
    771     {
    772         AudioQueueStop(pCAStream->audioQueue, 1);
     697        orc = AudioQueueNewOutput(&pStreamCA->asbdStream, coreAudioOutputQueueCb, pStreamCA /* pvData */,
     698                                  CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &pStreamCA->hAudioQueue);
     699    if (orc == noErr)
     700    {
     701        /*
     702         * Assign device to the queue.
     703         */
     704        UInt32 uSize = sizeof(pDev->UUID);
     705        orc = AudioQueueSetProperty(pStreamCA->hAudioQueue, kAudioQueueProperty_CurrentDevice, &pDev->UUID, uSize);
     706        if (orc == noErr)
     707        {
     708            /*
     709             * Allocate audio buffers.
     710             */
     711            const size_t cbBuf = PDMAudioPropsFramesToBytes(&pStreamCA->Cfg.Props, pStreamCA->Cfg.Backend.cFramesPeriod);
     712            size_t iBuf;
     713            for (iBuf = 0; orc == noErr && iBuf < RT_ELEMENTS(pStreamCA->apAudioBuffers); iBuf++)
     714                orc = AudioQueueAllocateBuffer(pStreamCA->hAudioQueue, cbBuf, &pStreamCA->apAudioBuffers[iBuf]);
     715            if (orc == noErr)
     716            {
     717                /*
     718                 * Get a reference to our runloop so it can be stopped then signal
     719                 * our creator to say that we're done.  The runloop reference is the
     720                 * success indicator.
     721                 */
     722                pStreamCA->hRunLoop = hRunLoop;
     723                CFRetain(hRunLoop);
     724                RTThreadUserSignal(hThreadSelf);
     725
     726                /*
     727                 * The main loop.
     728                 */
     729                while (!ASMAtomicReadBool(&pStreamCA->fShutdown))
     730                {
     731                    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 30.0 /*sec*/, 1);
     732                }
     733
     734                AudioQueueStop(pStreamCA->hAudioQueue, fIn ? 1 : 0);
     735                rc = VINF_SUCCESS;
     736            }
     737            else
     738                LogRel(("CoreAudio: Failed to allocate %#x byte queue buffer #%u: %#x (%d)\n", cbBuf, iBuf, orc, orc));
     739
     740            while (iBuf-- > 0)
     741            {
     742                AudioQueueFreeBuffer(pStreamCA->hAudioQueue, pStreamCA->apAudioBuffers[iBuf]);
     743                pStreamCA->apAudioBuffers[iBuf] = NULL;
     744            }
     745        }
     746        else
     747            LogRel(("CoreAudio: Failed to associate device with queue: %#x (%d)\n", orc, orc));
     748
     749        AudioQueueDispose(pStreamCA->hAudioQueue, 1);
    773750    }
    774751    else
    775     {
    776         AudioQueueStop(pCAStream->audioQueue, 0);
    777     }
    778 
    779     for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++)
    780     {
    781         if (pCAStream->audioBuffer[i])
    782             AudioQueueFreeBuffer(pCAStream->audioQueue, pCAStream->audioBuffer[i]);
    783     }
    784 
    785     AudioQueueDispose(pCAStream->audioQueue, 1);
    786 
    787     LogFunc(("Thread ended for pCAStream=%p, fIn=%RTbool\n", pCAStream, fIn));
    788     return VINF_SUCCESS;
     752        LogRel(("CoreAudio: Failed to create audio queue: %#x (%d)\n", orc, orc));
     753
     754
     755    RTThreadUserSignal(hThreadSelf);
     756    LogFunc(("Thread ended for pStreamCA=%p fIn=%RTbool: rc=%Rrc (orc=%#x/%d)\n", pStreamCA, fIn, rc, orc, orc));
     757    return rc;
    789758}
    790759
     
    793762 *
    794763 * @returns IPRT status code.
    795  * @param   pCAStream           Core Audio stream to store input data into.
     764 * @param   pStreamCA           Core Audio stream to store input data into.
    796765 * @param   audioBuffer         Audio buffer to process input data from.
    797766 */
    798 static int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pCAStream, AudioQueueBufferRef audioBuffer)
    799 {
    800     PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
     767static int coreAudioInputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
     768{
     769    PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
    801770    AssertPtr(pCircBuf);
    802771
     
    818787
    819788        /* Copy the data from our ring buffer to the core audio buffer. */
     789        /** @todo r=bird: WTF is the (UInt8 *) cast for? Despite the 'pv' prefix, pvDst
     790         * is a UInt8 pointer.  Whoever wrote this crap needs to check his/her
     791         * medication.  I shouldn't have to wast my time fixing crap like this! */
    820792        memcpy((UInt8 *)pvDst, pvSrc + cbWritten, cbToWrite);
    821793
     
    829801    }
    830802
    831     Log3Func(("pCAStream=%p, cbBuffer=%RU32/%zu, cbWritten=%zu\n",
    832               pCAStream, audioBuffer->mAudioDataByteSize, audioBuffer->mAudioDataBytesCapacity, cbWritten));
     803    Log3Func(("pStreamCA=%p, cbBuffer=%RU32/%zu, cbWritten=%zu\n",
     804              pStreamCA, audioBuffer->mAudioDataByteSize, audioBuffer->mAudioDataBytesCapacity, cbWritten));
    833805
    834806    return VINF_SUCCESS;
     
    839811 *
    840812 * @param   pvUser              User argument.
    841  * @param   audioQueue          Audio queue to process input data from.
     813 * @param   hAudioQueue         Audio queue to process input data from.
    842814 * @param   audioBuffer         Audio buffer to process input data from. Must be part of audio queue.
    843815 * @param   pAudioTS            Audio timestamp.
     
    845817 * @param   paPacketDesc        Array of packet descriptors.
    846818 */
    847 static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer,
     819static DECLCALLBACK(void) coreAudioInputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer,
    848820                                                const AudioTimeStamp *pAudioTS,
    849821                                                UInt32 cPacketDesc, const AudioStreamPacketDescription *paPacketDesc)
    850822{
    851     RT_NOREF(audioQueue, pAudioTS, cPacketDesc, paPacketDesc);
    852 
    853     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pvUser;
    854     AssertPtr(pCAStream);
    855 
    856     int rc = RTCritSectEnter(&pCAStream->CritSect);
     823    RT_NOREF(pAudioTS, cPacketDesc, paPacketDesc);
     824
     825    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
     826    AssertPtr(pStreamCA);
     827
     828    int rc = RTCritSectEnter(&pStreamCA->CritSect);
    857829    AssertRC(rc);
    858830
    859     rc = coreAudioInputQueueProcBuffer(pCAStream, audioBuffer);
     831    rc = coreAudioInputQueueProcBuffer(pStreamCA, audioBuffer);
    860832    if (RT_SUCCESS(rc))
    861         AudioQueueEnqueueBuffer(audioQueue, audioBuffer, 0, NULL);
    862 
    863     rc = RTCritSectLeave(&pCAStream->CritSect);
     833        AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
     834
     835    rc = RTCritSectLeave(&pStreamCA->CritSect);
    864836    AssertRC(rc);
    865837}
     
    869841 *
    870842 * @returns IPRT status code.
    871  * @param   pCAStream           Core Audio stream to process output data for.
     843 * @param   pStreamCA           Core Audio stream to process output data for.
    872844 * @param   audioBuffer         Audio buffer to store data into.
    873845 */
    874 int coreAudioOutputQueueProcBuffer(PCOREAUDIOSTREAM pCAStream, AudioQueueBufferRef audioBuffer)
    875 {
    876     AssertPtr(pCAStream);
    877 
    878     PRTCIRCBUF pCircBuf = pCAStream->pCircBuf;
     846int coreAudioOutputQueueProcBuffer(PCOREAUDIOSTREAM pStreamCA, AudioQueueBufferRef audioBuffer)
     847{
     848    AssertPtr(pStreamCA);
     849
     850    PRTCIRCBUF pCircBuf = pStreamCA->pCircBuf;
    879851    AssertPtr(pCircBuf);
    880852
     
    922894    }
    923895
    924     Log3Func(("pCAStream=%p, cbCapacity=%RU32, cbRead=%zu\n",
    925               pCAStream, audioBuffer->mAudioDataBytesCapacity, cbRead));
     896    Log3Func(("pStreamCA=%p, cbCapacity=%RU32, cbRead=%zu\n",
     897              pStreamCA, audioBuffer->mAudioDataBytesCapacity, cbRead));
    926898
    927899    return VINF_SUCCESS;
     
    932904 *
    933905 * @param   pvUser              User argument.
    934  * @param   audioQueue          Audio queue to process output data for.
     906 * @param   hAudioQueue         Audio queue to process output data for.
    935907 * @param   audioBuffer         Audio buffer to store output data in. Must be part of audio queue.
    936908 */
    937 static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer)
    938 {
    939     RT_NOREF(audioQueue);
    940 
    941     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pvUser;
    942     AssertPtr(pCAStream);
    943 
    944     int rc = RTCritSectEnter(&pCAStream->CritSect);
     909static DECLCALLBACK(void) coreAudioOutputQueueCb(void *pvUser, AudioQueueRef hAudioQueue, AudioQueueBufferRef audioBuffer)
     910{
     911    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pvUser;
     912    AssertPtr(pStreamCA);
     913
     914    int rc = RTCritSectEnter(&pStreamCA->CritSect);
    945915    AssertRC(rc);
    946916
    947     rc = coreAudioOutputQueueProcBuffer(pCAStream, audioBuffer);
     917    rc = coreAudioOutputQueueProcBuffer(pStreamCA, audioBuffer);
    948918    if (RT_SUCCESS(rc))
    949         AudioQueueEnqueueBuffer(audioQueue, audioBuffer, 0, NULL);
    950 
    951     rc = RTCritSectLeave(&pCAStream->CritSect);
     919        AudioQueueEnqueueBuffer(hAudioQueue, audioBuffer, 0, NULL);
     920
     921    rc = RTCritSectLeave(&pStreamCA->CritSect);
    952922    AssertRC(rc);
    953923}
     
    957927 *
    958928 * @returns IPRT status code.
    959  * @param   pCAStream           Core Audio stream to invalidate its queue for.
    960  */
    961 static int coreAudioStreamInvalidateQueue(PCOREAUDIOSTREAM pCAStream)
     929 * @param   pStreamCA           Core Audio stream to invalidate its queue for.
     930 *
     931 * @todo r=bird: Which use of the word 'invalidate' is this?
     932 */
     933static int coreAudioStreamInvalidateQueue(PCOREAUDIOSTREAM pStreamCA)
    962934{
    963935    int rc = VINF_SUCCESS;
    964936
    965     Log3Func(("pCAStream=%p\n", pCAStream));
    966 
    967     for (size_t i = 0; i < RT_ELEMENTS(pCAStream->audioBuffer); i++)
    968     {
    969         AudioQueueBufferRef pBuf = pCAStream->audioBuffer[i];
    970 
    971         if (pCAStream->pCfg->enmDir == PDMAUDIODIR_IN)
    972         {
    973             int rc2 = coreAudioInputQueueProcBuffer(pCAStream, pBuf);
     937    Log3Func(("pStreamCA=%p\n", pStreamCA));
     938
     939    for (size_t i = 0; i < RT_ELEMENTS(pStreamCA->apAudioBuffers); i++)
     940    {
     941        AudioQueueBufferRef pBuf = pStreamCA->apAudioBuffers[i];
     942        if (pStreamCA->Cfg.enmDir == PDMAUDIODIR_IN)
     943        {
     944            int rc2 = coreAudioInputQueueProcBuffer(pStreamCA, pBuf);
    974945            if (RT_SUCCESS(rc2))
    975             {
    976                 AudioQueueEnqueueBuffer(pCAStream->audioQueue, pBuf, 0, NULL);
    977             }
    978         }
    979         else if (pCAStream->pCfg->enmDir == PDMAUDIODIR_OUT)
    980         {
    981             int rc2 = coreAudioOutputQueueProcBuffer(pCAStream, pBuf);
     946                AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDescs*/, NULL /*inPacketDescs*/);
     947        }
     948        else
     949        {
     950            Assert(pStreamCA->Cfg.enmDir == PDMAUDIODIR_OUT);
     951            int rc2 = coreAudioOutputQueueProcBuffer(pStreamCA, pBuf);
    982952            if (   RT_SUCCESS(rc2)
    983953                && pBuf->mAudioDataByteSize)
    984             {
    985                 AudioQueueEnqueueBuffer(pCAStream->audioQueue, pBuf, 0, NULL);
    986             }
     954                AudioQueueEnqueueBuffer(pStreamCA->hAudioQueue, pBuf, 0 /*inNumPacketDescs*/, NULL /*inPacketDescs*/);
    987955
    988956            if (RT_SUCCESS(rc))
    989957                rc = rc2;
    990958        }
    991         else
    992             AssertFailed();
    993959    }
    994960
     
    10431009static DECLCALLBACK(int) drvHostCoreAudioHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
    10441010{
    1045     PDRVHOSTCOREAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
     1011    PDRVHOSTCOREAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVHOSTCOREAUDIO, IHostAudio);
    10461012    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    10471013
     
    10961062/**
    10971063 * Does a (re-)enumeration of the host's playback + recording devices.
     1064 *
     1065 * @todo No, it doesn't do playback & recording, it does only what @a enmUsage
     1066 *       says.
    10981067 *
    10991068 * @return  IPRT status code.
     
    16471616static DECLCALLBACK(int) drvHostCoreAudioHA_GetDevices(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHOSTENUM pDeviceEnum)
    16481617{
    1649     AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
     1618    PDRVHOSTCOREAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVHOSTCOREAUDIO, IHostAudio);
    16501619    AssertPtrReturn(pDeviceEnum, VERR_INVALID_POINTER);
    16511620
    1652     PDRVHOSTCOREAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    1653 
     1621    PDMAudioHostEnumInit(pDeviceEnum);
     1622
     1623    /*
     1624     * We update the enumeration associated with pThis.
     1625     */
    16541626    int rc = RTCritSectEnter(&pThis->CritSect);
    16551627    if (RT_SUCCESS(rc))
     
    16581630        if (RT_SUCCESS(rc))
    16591631        {
    1660             if (pDeviceEnum)
    1661             {
    1662                 /* Return a copy with only PDMAUDIOHOSTDEV, none of the extra bits in COREAUDIODEVICEDATA. */
    1663                 PDMAudioHostEnumInit(pDeviceEnum);
    1664                 rc = PDMAudioHostEnumCopy(pDeviceEnum, &pThis->Devices, PDMAUDIODIR_INVALID /*all*/, true /*fOnlyCoreData*/);
    1665                 if (RT_FAILURE(rc))
    1666                     PDMAudioHostEnumDelete(pDeviceEnum);
    1667             }
    1668         }
    1669 
    1670         int rc2 = RTCritSectLeave(&pThis->CritSect);
    1671         AssertRC(rc2);
    1672     }
    1673 
    1674     LogFlowFunc(("Returning %Rrc\n", rc));
     1632            /*
     1633             * Return a copy with only PDMAUDIOHOSTDEV and none of the extra
     1634             * bits in COREAUDIODEVICEDATA.
     1635             */
     1636            rc = PDMAudioHostEnumCopy(pDeviceEnum, &pThis->Devices, PDMAUDIODIR_INVALID /*all*/, true /*fOnlyCoreData*/);
     1637            if (RT_FAILURE(rc))
     1638                PDMAudioHostEnumDelete(pDeviceEnum);
     1639        }
     1640
     1641        RTCritSectLeave(&pThis->CritSect);
     1642    }
     1643
     1644    LogFlowFunc(("returns %Rrc\n", rc));
    16751645    return rc;
    16761646}
     
    16831653{
    16841654    RT_NOREF(pInterface, enmDir);
    1685     AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
    1686 
    16871655    return PDMAUDIOBACKENDSTS_RUNNING;
    16881656}
     
    16901658
    16911659/**
    1692  * Initializes a Core Audio stream's audio queue.
    1693  *
    1694  * @returns IPRT status code.
    1695  * @param   pCAStream           Core Audio stream to initialize audio queue for.
    1696  * @param   pCfgReq             Requested stream configuration.
    1697  * @param   pCfgAcq             Acquired stream configuration on success.
    1698  */
    1699 static int coreAudioStreamInitQueue(PCOREAUDIOSTREAM pCAStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1700 {
    1701     RT_NOREF(pCfgAcq);
    1702 
    1703     LogFunc(("pCAStream=%p, pCfgReq=%p, pCfgAcq=%p\n", pCAStream, pCfgReq, pCfgAcq));
    1704 
    1705     /* No device assigned? Bail out early. */
    1706     if (pCAStream->Unit.pDevice == NULL)
    1707         return VERR_NOT_AVAILABLE;
    1708 
    1709     const bool fIn = pCfgReq->enmDir == PDMAUDIODIR_IN;
    1710 
    1711     int rc = VINF_SUCCESS;
    1712 
    1713     if (fIn)
     1660 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
     1661 */
     1662static DECLCALLBACK(int) drvHostCoreAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     1663                                                         PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     1664{
     1665    PDRVHOSTCOREAUDIO pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTCOREAUDIO, IHostAudio);
     1666    PCOREAUDIOSTREAM  pStreamCA = (PCOREAUDIOSTREAM)pStream;
     1667    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
     1668    AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
     1669    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
     1670    AssertReturn(pCfgReq->enmDir == PDMAUDIODIR_IN || pCfgReq->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
     1671    int rc;
     1672
     1673    /*
     1674     * Permission check for input devices before we start.
     1675     */
     1676    if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    17141677    {
    17151678        rc = coreAudioInputPermissionCheck();
     
    17181681    }
    17191682
    1720     /* Create the recording device's out format based on our required audio settings. */
    1721     Assert(pCAStream->pCfg == NULL);
    1722     pCAStream->pCfg = PDMAudioStrmCfgDup(pCfgReq);
    1723     if (!pCAStream->pCfg)
    1724         rc = VERR_NO_MEMORY;
    1725 
    1726     coreAudioPCMPropsToASBD(&pCfgReq->Props, &pCAStream->asbdStream);
    1727     /** @todo Do some validation? */
    1728 
    1729     coreAudioPrintASBD(  fIn
    1730                        ? "Capturing queue format"
    1731                        : "Playback queue format", &pCAStream->asbdStream);
    1732 
    1733     if (RT_FAILURE(rc))
    1734     {
    1735         LogRel(("CoreAudio: Failed to convert requested %s format to native format (%Rrc)\n", fIn ? "input" : "output", rc));
    1736         return rc;
    1737     }
    1738 
    1739     rc = RTCircBufCreate(&pCAStream->pCircBuf, PDMAUDIOSTREAMCFG_F2B(pCfgReq, pCfgReq->Backend.cFramesBufferSize));
    1740     if (RT_FAILURE(rc))
    1741         return rc;
    1742 
    17431683    /*
    1744      * Start the thread.
     1684     * Do we have a device for the requested stream direction?
    17451685     */
    1746     rc = RTThreadCreate(&pCAStream->hThread, coreAudioQueueThread,
    1747                         pCAStream /* pvUser */, 0 /* Default stack size */,
    1748                         RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CAQUEUE");
    1749     if (RT_SUCCESS(rc))
    1750         rc = RTThreadUserWait(pCAStream->hThread, 10 * 1000 /* 10s timeout */);
    1751 
    1752     LogFunc(("Returning %Rrc\n", rc));
    1753     return rc;
    1754 }
    1755 
    1756 
    1757 /**
    1758  * Initializes a Core Audio stream.
    1759  *
    1760  * @return IPRT status code.
    1761  * @param  pThis                Driver instance.
    1762  * @param  pCAStream            Stream to initialize.
    1763  * @param  pDev                 Audio device to use for this stream.
    1764  */
    1765 static int coreAudioStreamInit(PCOREAUDIOSTREAM pCAStream, PDRVHOSTCOREAUDIO pThis, PCOREAUDIODEVICEDATA pDev)
    1766 {
    1767     AssertPtrReturn(pCAStream, VERR_INVALID_POINTER);
    1768     AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
    1769     AssertPtrReturn(pDev,      VERR_INVALID_POINTER);
    1770 
    1771     Assert(pCAStream->Unit.pDevice == NULL); /* Make sure no device is assigned yet. */
    1772     Assert(pDev->Core.cbSelf == sizeof(COREAUDIODEVICEDATA));
    1773 
    1774     LogFunc(("pCAStream=%p, pDev=%p ('%s', ID=%RU32)\n", pCAStream, pDev, pDev->Core.szName, pDev->deviceID));
    1775 
    1776     pCAStream->Unit.pDevice = pDev;
    1777     pCAStream->pDrv = pThis;
    1778 
    1779     return VINF_SUCCESS;
    1780 }
    1781 
    1782 
    1783 /**
    1784  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    1785  */
    1786 static DECLCALLBACK(int) drvHostCoreAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    1787                                                          PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    1788 {
    1789     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1790     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    1791     AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
    1792     AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
    1793 
    1794     PDRVHOSTCOREAUDIO pThis     = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    1795     PCOREAUDIOSTREAM  pCAStream = (PCOREAUDIOSTREAM)pStream;
    1796 
    1797     int rc = RTCritSectInit(&pCAStream->CritSect);
    1798     if (RT_FAILURE(rc))
    1799         return rc;
    1800 
    1801     pCAStream->hThread    = NIL_RTTHREAD;
    1802     pCAStream->fRun       = false;
    1803     pCAStream->fIsRunning = false;
    1804     pCAStream->fShutdown  = false;
    1805 
    1806     /* Input or output device? */
    1807     bool fIn = pCfgReq->enmDir == PDMAUDIODIR_IN;
    1808 
    1809     /* For now, just use the default device available. */
    1810     PCOREAUDIODEVICEDATA pDev = fIn ? pThis->pDefaultDevIn : pThis->pDefaultDevOut;
    1811 
    1812     LogFunc(("pStream=%p, pCfgReq=%p, pCfgAcq=%p, fIn=%RTbool, pDev=%p\n", pStream, pCfgReq, pCfgAcq, fIn, pDev));
    1813 
    1814     if (pDev) /* (Default) device available? */
    1815     {
    1816         /* Sanity. */
     1686    PCOREAUDIODEVICEDATA pDev = pCfgReq->enmDir == PDMAUDIODIR_IN ? pThis->pDefaultDevIn : pThis->pDefaultDevOut;
     1687#ifdef LOG_ENABLED
     1688    char szTmp[PDMAUDIOSTRMCFGTOSTRING_MAX];
     1689#endif
     1690    LogFunc(("pDev=%p *pCfgReq: %s\n", pDev, PDMAudioStrmCfgToString(pCfgReq, szTmp, sizeof(szTmp)) ));
     1691    if (pDev)
     1692    {
    18171693        Assert(pDev->Core.cbSelf == sizeof(*pDev));
    18181694
    1819         /* Init the Core Audio stream. */
    1820         rc = coreAudioStreamInit(pCAStream, pThis, pDev);
     1695        /*
     1696         * Basic structure init.
     1697         */
     1698        pStreamCA->pDrv         = pThis;
     1699        pStreamCA->hThread      = NIL_RTTHREAD;
     1700        pStreamCA->fRun         = false;
     1701        pStreamCA->fIsRunning   = false;
     1702        pStreamCA->fShutdown    = false;
     1703        pStreamCA->Unit.pDevice = pDev;   /** @todo r=bird: How do we protect this against enumeration releasing pDefaultDevOut/In. */
     1704        pStreamCA->enmInitState = COREAUDIOINITSTATE_IN_INIT;
     1705
     1706        rc = RTCritSectInit(&pStreamCA->CritSect);
    18211707        if (RT_SUCCESS(rc))
    18221708        {
    1823             ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_IN_INIT);
    1824 
    1825             rc = coreAudioStreamInitQueue(pCAStream, pCfgReq, pCfgAcq);
     1709            /*
     1710             * Do format conversion and create the circular buffer we use to shuffle
     1711             * data to/from the queue thread.
     1712             */
     1713            PDMAudioStrmCfgCopy(&pStreamCA->Cfg, pCfgReq);
     1714            coreAudioPCMPropsToASBD(&pCfgReq->Props, &pStreamCA->asbdStream);
     1715            /** @todo Do some validation? */
     1716            coreAudioPrintASBD(  pCfgReq->enmDir == PDMAUDIODIR_IN
     1717                               ? "Capturing queue format"
     1718                               : "Playback queue format", &pStreamCA->asbdStream);
     1719
     1720            rc = RTCircBufCreate(&pStreamCA->pCircBuf,
     1721                                 PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize));
    18261722            if (RT_SUCCESS(rc))
    18271723            {
    1828                 ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_INIT);
     1724                /*
     1725                 * Start the thread.
     1726                 */
     1727                static uint32_t volatile s_idxThread = 0;
     1728                uint32_t idxThread = ASMAtomicIncU32(&s_idxThread);
     1729
     1730                rc = RTThreadCreateF(&pStreamCA->hThread, coreAudioQueueThread, pStreamCA, 0 /*cbStack*/,
     1731                                     RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CaQue%u", idxThread);
     1732                if (RT_SUCCESS(rc))
     1733                {
     1734                    rc = RTThreadUserWait(pStreamCA->hThread, RT_MS_10SEC);
     1735                    AssertRC(rc);
     1736                    if (RT_SUCCESS(rc) && pStreamCA->hRunLoop != NULL)
     1737                    {
     1738                        ASMAtomicWriteU32(&pStreamCA->enmInitState, COREAUDIOINITSTATE_INIT);
     1739
     1740                        LogFunc(("returns VINF_SUCCESS\n"));
     1741                        return VINF_SUCCESS;
     1742                    }
     1743
     1744                    /*
     1745                     * Failed, clean up.
     1746                     */
     1747                    LogRel(("CoreAudio: Thread failed to initialize in a timely manner (%Rrc).\n", rc));
     1748
     1749                    ASMAtomicWriteBool(&pStreamCA->fShutdown, true);
     1750                    RTThreadPoke(pStreamCA->hThread);
     1751                    int rcThread = 0;
     1752                    rc = RTThreadWait(pStreamCA->hThread, RT_MS_15SEC, NULL);
     1753                    AssertLogRelRC(rc);
     1754                    LogRel(("CoreAudio: Thread exit code: %Rrc / %Rrc.\n", rc, rcThread));
     1755                    pStreamCA->hThread = NIL_RTTHREAD;
     1756                }
     1757                else
     1758                    LogRel(("CoreAudio: Failed to create queue thread for stream: %Rrc\n", rc));
     1759                RTCircBufDestroy(pStreamCA->pCircBuf);
     1760                pStreamCA->pCircBuf = NULL;
    18291761            }
    18301762            else
     1763                LogRel(("CoreAudio: Failed to allocate stream buffer: %Rrc\n", rc));
     1764            RTCritSectDelete(&pStreamCA->CritSect);
     1765        }
     1766        else
     1767            LogRel(("CoreAudio: Failed to initialize critical section for stream: %Rrc\n", rc));
     1768    }
     1769    else
     1770    {
     1771        LogFunc(("No device for stream.\n"));
     1772        rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     1773    }
     1774
     1775    LogFunc(("returns %Rrc\n", rc));
     1776    return rc;
     1777}
     1778
     1779
     1780/**
     1781 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
     1782 */
     1783static DECLCALLBACK(int) drvHostCoreAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1784{
     1785    RT_NOREF(pInterface);
     1786    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pStream;
     1787    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
     1788
     1789    /*
     1790     * Never mind if the status isn't INIT (it should always be, though).
     1791     */
     1792    COREAUDIOINITSTATE const enmInitState = (COREAUDIOINITSTATE)ASMAtomicReadU32(&pStreamCA->enmInitState);
     1793    AssertMsg(enmInitState == COREAUDIOINITSTATE_INIT, ("%d\n", enmInitState));
     1794    if (enmInitState == COREAUDIOINITSTATE_INIT)
     1795    {
     1796        Assert(RTCritSectIsInitialized(&pStreamCA->CritSect));
     1797
     1798        /*
     1799         * Disable (stop) the stream just in case it's running.
     1800         */
     1801        /** @todo this isn't paranoid enough, the pStreamCA->hAudioQueue is
     1802         *        owned+released by the queue thread. */
     1803        drvHostCoreAudioStreamControlInternal(pStreamCA, PDMAUDIOSTREAMCMD_DISABLE);
     1804
     1805        /*
     1806         * Change the state (cannot do before the stop).
     1807         * Enter and leave the critsect afterwards for paranoid reasons.
     1808         */
     1809        ASMAtomicWriteU32(&pStreamCA->enmInitState, COREAUDIOINITSTATE_IN_UNINIT);
     1810        RTCritSectEnter(&pStreamCA->CritSect);
     1811        RTCritSectLeave(&pStreamCA->CritSect);
     1812
     1813        /*
     1814         * Bring down the queue thread.
     1815         */
     1816        if (pStreamCA->hThread != NIL_RTTHREAD)
     1817        {
     1818            LogFunc(("Waiting for thread ...\n"));
     1819            ASMAtomicXchgBool(&pStreamCA->fShutdown, true);
     1820            int rcThread = VERR_IPE_UNINITIALIZED_STATUS;
     1821            int rc       = VERR_TIMEOUT;
     1822            for (uint32_t iWait = 0; rc == VERR_TIMEOUT && iWait < 60; iWait++)
    18311823            {
    1832                 ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_IN_UNINIT);
    1833 
    1834                 int rc2 = coreAudioStreamUninit(pCAStream);
    1835                 AssertRC(rc2);
    1836 
    1837                 ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_UNINIT);
     1824                LogFunc(("%u ...\n", iWait));
     1825                if (pStreamCA->hRunLoop != NULL)
     1826                    CFRunLoopStop(pStreamCA->hRunLoop);
     1827                if (iWait >= 10)
     1828                    RTThreadPoke(pStreamCA->hThread);
     1829
     1830                rcThread = VERR_IPE_UNINITIALIZED_STATUS;
     1831                rc = RTThreadWait(pStreamCA->hThread, RT_MS_1SEC / 2, &rcThread);
    18381832            }
    1839         }
    1840     }
    1841     else
    1842         rc = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
    1843 
    1844     LogFunc(("Returning %Rrc\n", rc));
    1845     return rc;
    1846 }
    1847 
    1848 
    1849 static int coreAudioStreamControl(PDRVHOSTCOREAUDIO pThis, PCOREAUDIOSTREAM pCAStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    1850 {
    1851     RT_NOREF(pThis);
    1852 
    1853     uint32_t enmStatus = ASMAtomicReadU32(&pCAStream->enmStatus);
    1854 
    1855     LogFlowFunc(("enmStreamCmd=%RU32, enmStatus=%RU32\n", enmStreamCmd, enmStatus));
    1856 
    1857     if (enmStatus != COREAUDIOSTATUS_INIT)
     1833            AssertLogRelRC(rc);
     1834            LogFunc(("Thread stopped with: %Rrc/%Rrc\n", rc, rcThread));
     1835            pStreamCA->hThread = NIL_RTTHREAD;
     1836        }
     1837
     1838        if (pStreamCA->hRunLoop != NULL)
     1839        {
     1840            CFRelease(pStreamCA->hRunLoop);
     1841            pStreamCA->hRunLoop = NULL;
     1842        }
     1843
     1844        /*
     1845         * Kill the circular buffer and NULL essential variable.
     1846         */
     1847        if (pStreamCA->pCircBuf)
     1848        {
     1849            RTCircBufDestroy(pStreamCA->pCircBuf);
     1850            pStreamCA->pCircBuf = NULL;
     1851        }
     1852
     1853        pStreamCA->Unit.pDevice = NULL;
     1854        pStreamCA->pDrv         = NULL;
     1855
     1856        RTCritSectDelete(&pStreamCA->CritSect);
     1857
     1858        /*
     1859         * Done.
     1860         */
     1861        ASMAtomicWriteU32(&pStreamCA->enmInitState, COREAUDIOINITSTATE_UNINIT);
     1862    }
     1863
     1864    LogFunc(("returns\n"));
     1865    return VINF_SUCCESS;
     1866}
     1867
     1868
     1869static int drvHostCoreAudioStreamControlInternal(PCOREAUDIOSTREAM pStreamCA, PDMAUDIOSTREAMCMD enmStreamCmd)
     1870{
     1871    uint32_t enmInitState = ASMAtomicReadU32(&pStreamCA->enmInitState);
     1872
     1873    LogFlowFunc(("enmStreamCmd=%RU32, enmInitState=%RU32\n", enmStreamCmd, enmInitState));
     1874
     1875    if (enmInitState != COREAUDIOINITSTATE_INIT)
    18581876    {
    18591877        return VINF_SUCCESS;
    18601878    }
    18611879
    1862     if (!pCAStream->pCfg) /* Not (yet) configured? Skip. */
    1863         return VINF_SUCCESS;
    1864 
    18651880    int rc = VINF_SUCCESS;
    1866 
    18671881    switch (enmStreamCmd)
    18681882    {
     
    18711885        {
    18721886            LogFunc(("Queue enable\n"));
    1873             if (pCAStream->pCfg->enmDir == PDMAUDIODIR_IN)
     1887            if (pStreamCA->Cfg.enmDir == PDMAUDIODIR_IN)
    18741888            {
    1875                 rc = coreAudioStreamInvalidateQueue(pCAStream);
     1889                rc = coreAudioStreamInvalidateQueue(pStreamCA);
    18761890                if (RT_SUCCESS(rc))
    18771891                {
    18781892                    /* Start the audio queue immediately. */
    1879                     AudioQueueStart(pCAStream->audioQueue, NULL);
     1893                    AudioQueueStart(pStreamCA->hAudioQueue, NULL);
    18801894                }
    18811895            }
    1882             else if (pCAStream->pCfg->enmDir == PDMAUDIODIR_OUT)
     1896            else if (pStreamCA->Cfg.enmDir == PDMAUDIODIR_OUT)
    18831897            {
    18841898                /* Touch the run flag to start the audio queue as soon as
    18851899                 * we have anough data to actually play something. */
    1886                 ASMAtomicXchgBool(&pCAStream->fRun, true);
     1900                ASMAtomicXchgBool(&pStreamCA->fRun, true);
    18871901            }
    18881902            break;
     
    18921906        {
    18931907            LogFunc(("Queue disable\n"));
    1894             AudioQueueStop(pCAStream->audioQueue, 1 /* Immediately */);
    1895             ASMAtomicXchgBool(&pCAStream->fRun,       false);
    1896             ASMAtomicXchgBool(&pCAStream->fIsRunning, false);
     1908            AudioQueueStop(pStreamCA->hAudioQueue, 1 /* Immediately */);
     1909            ASMAtomicXchgBool(&pStreamCA->fRun,       false);
     1910            ASMAtomicXchgBool(&pStreamCA->fIsRunning, false);
    18971911            break;
    18981912        }
     
    19001914        {
    19011915            LogFunc(("Queue pause\n"));
    1902             AudioQueuePause(pCAStream->audioQueue);
    1903             ASMAtomicXchgBool(&pCAStream->fIsRunning, false);
     1916            AudioQueuePause(pStreamCA->hAudioQueue);
     1917            ASMAtomicXchgBool(&pStreamCA->fIsRunning, false);
    19041918            break;
    19051919        }
     
    19161930
    19171931/**
    1918  * Unitializes a Core Audio stream's audio queue.
    1919  *
    1920  * @returns IPRT status code.
    1921  * @param   pCAStream           Core Audio stream to unitialize audio queue for.
    1922  */
    1923 static int coreAudioStreamUninitQueue(PCOREAUDIOSTREAM pCAStream)
    1924 {
    1925     LogFunc(("pCAStream=%p\n", pCAStream));
    1926 
    1927     if (pCAStream->hThread != NIL_RTTHREAD)
    1928     {
    1929         LogFunc(("Waiting for thread ...\n"));
    1930 
    1931         ASMAtomicXchgBool(&pCAStream->fShutdown, true);
    1932 
    1933         int rcThread;
    1934         int rc = RTThreadWait(pCAStream->hThread, 30 * 1000, &rcThread);
    1935         if (RT_FAILURE(rc))
    1936             return rc;
    1937 
    1938         RT_NOREF(rcThread);
    1939         LogFunc(("Thread stopped with %Rrc\n", rcThread));
    1940 
    1941         pCAStream->hThread = NIL_RTTHREAD;
    1942     }
    1943 
    1944     if (pCAStream->pCfg)
    1945     {
    1946         PDMAudioStrmCfgFree(pCAStream->pCfg);
    1947         pCAStream->pCfg = NULL;
    1948     }
    1949 
    1950     if (pCAStream->pCircBuf)
    1951     {
    1952         RTCircBufDestroy(pCAStream->pCircBuf);
    1953         pCAStream->pCircBuf = NULL;
    1954     }
    1955 
    1956     LogFunc(("Returning\n"));
    1957     return VINF_SUCCESS;
    1958 }
    1959 
    1960 
    1961 /**
    1962  * Unitializes a Core Audio stream.
    1963  *
    1964  * @returns IPRT status code.
    1965  * @param   pCAStream           Core Audio stream to uninitialize.
    1966  */
    1967 static int coreAudioStreamUninit(PCOREAUDIOSTREAM pCAStream)
    1968 {
    1969     LogFunc(("pCAStream=%p\n", pCAStream));
    1970 
    1971     int rc = coreAudioStreamUninitQueue(pCAStream);
    1972     if (RT_SUCCESS(rc))
    1973     {
    1974         pCAStream->Unit.pDevice = NULL;
    1975         pCAStream->pDrv         = NULL;
    1976     }
    1977 
    1978     return rc;
    1979 }
    1980 
    1981 
    1982 /**
    1983  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
    1984  */
    1985 static DECLCALLBACK(int) drvHostCoreAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    1986 {
    1987     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1988     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    1989 
    1990     PDRVHOSTCOREAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    1991 
    1992     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pStream;
    1993 
    1994     uint32_t status = ASMAtomicReadU32(&pCAStream->enmStatus);
    1995     if (status != COREAUDIOSTATUS_INIT)
    1996     {
    1997         return VINF_SUCCESS;
    1998     }
    1999 
    2000     if (!pCAStream->pCfg) /* Not (yet) configured? Skip. */
    2001         return VINF_SUCCESS;
    2002 
    2003     int rc = coreAudioStreamControl(pThis, pCAStream, PDMAUDIOSTREAMCMD_DISABLE);
    2004     if (RT_SUCCESS(rc))
    2005     {
    2006         ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_IN_UNINIT);
    2007 
    2008         rc = coreAudioStreamUninit(pCAStream);
    2009 
    2010         if (RT_SUCCESS(rc))
    2011             ASMAtomicXchgU32(&pCAStream->enmStatus, COREAUDIOSTATUS_UNINIT);
    2012     }
    2013 
    2014     if (RT_SUCCESS(rc))
    2015     {
    2016         if (RTCritSectIsInitialized(&pCAStream->CritSect))
    2017             RTCritSectDelete(&pCAStream->CritSect);
    2018     }
    2019 
    2020     LogFunc(("rc=%Rrc\n", rc));
    2021     return rc;
    2022 }
    2023 
    2024 
    2025 /**
    20261932 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
    20271933 */
    2028 static DECLCALLBACK(int) drvHostCoreAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface,
    2029                                                           PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    2030 {
    2031     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    2032     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    2033 
    2034     PDRVHOSTCOREAUDIO pThis    = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    2035     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pStream;
    2036 
    2037     return coreAudioStreamControl(pThis, pCAStream, enmStreamCmd);
     1934static DECLCALLBACK(int) drvHostCoreAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     1935                                                          PDMAUDIOSTREAMCMD enmStreamCmd)
     1936{
     1937    RT_NOREF(pInterface);
     1938    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pStream;
     1939    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
     1940
     1941    return drvHostCoreAudioStreamControlInternal(pStreamCA, enmStreamCmd);
    20381942}
    20391943
     
    20451949{
    20461950    RT_NOREF(pInterface);
    2047     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2048 
    2049     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pStream;
    2050 
    2051     if (ASMAtomicReadU32(&pCAStream->enmStatus) != COREAUDIOSTATUS_INIT)
     1951    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pStream;
     1952    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
     1953
     1954    if (ASMAtomicReadU32(&pStreamCA->enmInitState) != COREAUDIOINITSTATE_INIT)
    20521955        return 0;
    20531956
    2054     AssertPtr(pCAStream->pCfg);
    2055     AssertPtr(pCAStream->pCircBuf);
    2056 
    2057     switch (pCAStream->pCfg->enmDir)
    2058     {
    2059         case PDMAUDIODIR_IN:
    2060             return (uint32_t)RTCircBufUsed(pCAStream->pCircBuf);
    2061 
    2062         case PDMAUDIODIR_OUT:
    2063         default:
    2064             AssertFailed();
    2065             break;
    2066     }
    2067 
     1957    if (pStreamCA->Cfg.enmDir == PDMAUDIODIR_IN)
     1958    {
     1959        AssertPtr(pStreamCA->pCircBuf);
     1960        return (uint32_t)RTCircBufUsed(pStreamCA->pCircBuf);
     1961    }
     1962    AssertFailed();
    20681963    return 0;
    20691964}
     
    20761971{
    20771972    RT_NOREF(pInterface);
    2078     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2079 
    2080     PCOREAUDIOSTREAM pCAStream = (PCOREAUDIOSTREAM)pStream;
     1973    PCOREAUDIOSTREAM pStreamCA = (PCOREAUDIOSTREAM)pStream;
     1974    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
     1975
    20811976
    20821977    uint32_t cbWritable = 0;
    2083 
    2084     if (ASMAtomicReadU32(&pCAStream->enmStatus) == COREAUDIOSTATUS_INIT)
    2085     {
    2086         AssertPtr(pCAStream->pCfg);
    2087         AssertPtr(pCAStream->pCircBuf);
    2088 
    2089         switch (pCAStream->pCfg->enmDir)
    2090         {
    2091             case PDMAUDIODIR_OUT:
    2092                 cbWritable = (uint32_t)RTCircBufFree(pCAStream->pCircBuf);
    2093                 break;
    2094 
    2095             default:
    2096                 break;
    2097         }
     1978    if (ASMAtomicReadU32(&pStreamCA->enmInitState) == COREAUDIOINITSTATE_INIT)
     1979    {
     1980        AssertPtr(pStreamCA->pCircBuf);
     1981
     1982        if (pStreamCA->Cfg.enmDir == PDMAUDIODIR_OUT)
     1983            cbWritable = (uint32_t)RTCircBufFree(pStreamCA->pCircBuf);
    20981984    }
    20991985
     
    21131999    AssertPtrReturn(pStreamCa, PDMHOSTAUDIOSTREAMSTATE_INVALID);
    21142000
    2115     if (pStreamCa->pCfg) /* Configured?  */
    2116     {
    2117         if (ASMAtomicReadU32(&pStreamCa->enmStatus) == COREAUDIOSTATUS_INIT)
    2118             return PDMHOSTAUDIOSTREAMSTATE_OKAY;
    2119     }
    2120 
     2001    if (ASMAtomicReadU32(&pStreamCa->enmInitState) == COREAUDIOINITSTATE_INIT)
     2002        return PDMHOSTAUDIOSTREAMSTATE_OKAY;
    21212003    return PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING; /** @todo ?? */
    21222004}
     
    21282010                                                       const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    21292011{
    2130     PDRVHOSTCOREAUDIO pThis     = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    2131     PCOREAUDIOSTREAM  pCAStream = (PCOREAUDIOSTREAM)pStream;
     2012    PDRVHOSTCOREAUDIO pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTCOREAUDIO, IHostAudio);
     2013    PCOREAUDIOSTREAM  pStreamCA = (PCOREAUDIOSTREAM)pStream;
    21322014
    21332015    RT_NOREF(pThis);
    21342016
    2135     if (ASMAtomicReadU32(&pCAStream->enmStatus) != COREAUDIOSTATUS_INIT)
     2017    if (ASMAtomicReadU32(&pStreamCA->enmInitState) != COREAUDIOINITSTATE_INIT)
    21362018    {
    21372019        *pcbWritten = 0;
     
    21392021    }
    21402022
     2023    int rc = RTCritSectEnter(&pStreamCA->CritSect);
     2024    AssertRCReturn(rc, rc);
     2025
     2026    size_t cbToWrite = RT_MIN(cbBuf, RTCircBufFree(pStreamCA->pCircBuf));
     2027    Log3Func(("cbToWrite=%zu\n", cbToWrite));
     2028
    21412029    uint32_t cbWrittenTotal = 0;
    2142 
    2143     int rc = VINF_SUCCESS;
    2144 
    2145     rc = RTCritSectEnter(&pCAStream->CritSect);
    2146     AssertRC(rc);
    2147 
    2148     size_t cbToWrite = RT_MIN(cbBuf, RTCircBufFree(pCAStream->pCircBuf));
    2149     Log3Func(("cbToWrite=%zu\n", cbToWrite));
    2150 
    2151     uint8_t *pvChunk;
    2152     size_t   cbChunk;
    2153 
    2154     while (cbToWrite)
     2030    while (cbToWrite > 0)
    21552031    {
    21562032        /* Try to acquire the necessary space from the ring buffer. */
    2157         RTCircBufAcquireWriteBlock(pCAStream->pCircBuf, cbToWrite, (void **)&pvChunk, &cbChunk);
    2158         if (!cbChunk)
    2159         {
    2160             RTCircBufReleaseWriteBlock(pCAStream->pCircBuf, cbChunk);
    2161             break;
    2162         }
     2033        void    *pvChunk = NULL;
     2034        size_t   cbChunk = 0;
     2035        RTCircBufAcquireWriteBlock(pStreamCA->pCircBuf, cbToWrite, &pvChunk, &cbChunk);
     2036        AssertBreakStmt(cbChunk > 0, RTCircBufReleaseWriteBlock(pStreamCA->pCircBuf, cbChunk));
    21632037
    21642038        Assert(cbChunk <= cbToWrite);
     
    21812055
    21822056        /* Release the ring buffer, so the read thread could start reading this data. */
    2183         RTCircBufReleaseWriteBlock(pCAStream->pCircBuf, cbChunk);
     2057        RTCircBufReleaseWriteBlock(pStreamCA->pCircBuf, cbChunk);
    21842058
    21852059        if (RT_FAILURE(rc))
     
    21932067
    21942068    if (    RT_SUCCESS(rc)
    2195         &&  pCAStream->fRun
    2196         && !pCAStream->fIsRunning)
    2197     {
    2198         rc = coreAudioStreamInvalidateQueue(pCAStream);
     2069        &&  pStreamCA->fRun
     2070        && !pStreamCA->fIsRunning)
     2071    {
     2072        rc = coreAudioStreamInvalidateQueue(pStreamCA);
    21992073        if (RT_SUCCESS(rc))
    22002074        {
    2201             AudioQueueStart(pCAStream->audioQueue, NULL);
    2202             pCAStream->fRun       = false;
    2203             pCAStream->fIsRunning = true;
    2204         }
    2205     }
    2206 
    2207     int rc2 = RTCritSectLeave(&pCAStream->CritSect);
     2075            AudioQueueStart(pStreamCA->hAudioQueue, NULL);
     2076            pStreamCA->fRun       = false;
     2077            pStreamCA->fIsRunning = true;
     2078        }
     2079    }
     2080
     2081    int rc2 = RTCritSectLeave(&pStreamCA->CritSect);
    22082082    AssertRC(rc2);
    22092083
    2210     if (RT_SUCCESS(rc))
    2211         *pcbWritten = cbWrittenTotal;
    2212 
     2084    *pcbWritten = cbWrittenTotal;
    22132085    return rc;
    22142086}
     
    22212093                                                          void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    22222094{
    2223     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    2224     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     2095    RT_NOREF(pInterface);
     2096    PCOREAUDIOSTREAM  pStreamCA = (PCOREAUDIOSTREAM)pStream;
     2097    AssertPtrReturn(pStreamCA, VERR_INVALID_POINTER);
    22252098    AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
    22262099
    2227     PCOREAUDIOSTREAM  pCAStream = (PCOREAUDIOSTREAM)pStream;
    2228     PDRVHOSTCOREAUDIO pThis     = PDMIHOSTAUDIO_2_DRVHOSTCOREAUDIO(pInterface);
    2229 
    2230     RT_NOREF(pThis);
    2231 
    2232     if (ASMAtomicReadU32(&pCAStream->enmStatus) != COREAUDIOSTATUS_INIT)
     2100
     2101    if (ASMAtomicReadU32(&pStreamCA->enmInitState) != COREAUDIOINITSTATE_INIT)
    22332102    {
    22342103        *pcbRead = 0;
     
    22362105    }
    22372106
    2238     int rc = RTCritSectEnter(&pCAStream->CritSect);
     2107    int rc = RTCritSectEnter(&pStreamCA->CritSect);
    22392108    AssertRCReturn(rc, rc);
    22402109
    2241     size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pCAStream->pCircBuf));
    2242     Log3Func(("cbToWrite=%zu/%zu\n", cbToWrite, RTCircBufSize(pCAStream->pCircBuf)));
     2110    size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamCA->pCircBuf));
     2111    Log3Func(("cbToWrite=%zu/%zu\n", cbToWrite, RTCircBufSize(pStreamCA->pCircBuf)));
    22432112
    22442113    uint32_t cbReadTotal = 0;
     
    22472116        void    *pvChunk = NULL;
    22482117        size_t   cbChunk = 0;
    2249         RTCircBufAcquireReadBlock(pCAStream->pCircBuf, cbToWrite, &pvChunk, &cbChunk);
     2118        RTCircBufAcquireReadBlock(pStreamCA->pCircBuf, cbToWrite, &pvChunk, &cbChunk);
    22502119
    22512120        AssertStmt(cbChunk <= cbToWrite, cbChunk = cbToWrite);
    22522121        memcpy((uint8_t *)pvBuf + cbReadTotal, pvChunk, cbChunk);
    22532122
    2254         RTCircBufReleaseReadBlock(pCAStream->pCircBuf, cbChunk);
     2123        RTCircBufReleaseReadBlock(pStreamCA->pCircBuf, cbChunk);
    22552124
    22562125        cbToWrite      -= cbChunk;
     
    22602129    *pcbRead = cbReadTotal;
    22612130
    2262     RTCritSectLeave(&pCAStream->CritSect);
     2131    RTCritSectLeave(&pStreamCA->CritSect);
    22632132    return VINF_SUCCESS;
    22642133}
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