/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /*! * @header IOAudioDevice */ #ifndef _IOKIT_IOAUDIOENGINE_H #define _IOKIT_IOAUDIOENGINE_H #include <IOKit/IOService.h> #include <IOKit/audio/IOAudioTypes.h> class OSDictionary; class OSCollection; class OSOrderedSet; class IOAudioEngineUserClient; class IOAudioDevice; class IOAudioStream; class IOAudioControl; class IOCommandGate; #define IOAUDIOENGINE_DEFAULT_NUM_ERASES_PER_BUFFER 4 /*! * @typedef IOAudioEnginePosition * @abstract Represents a position in an audio audio engine based on the sample frame within a * loop around the sample buffer, and the loop count which starts at 0 when the audio engine * begins playback * @field fSampleFrame The sample frame within the buffer - starts at 0 * @field fLoopCount The number of times the ring buffer has looped */ typedef struct { UInt32 fSampleFrame; UInt32 fLoopCount; } IOAudioEnginePosition; #define CMP_IOAUDIOENGINEPOSITION(p1, p2) \ (((p1)->fLoopCount > (p2)->fLoopCount) ? 1 : \ ((p1)->fLoopCount == (p2)->fLoopCount) && ((p1)->fSampleFrame > (p2)->fSampleFrame) ? 1 : \ ((p1)->fLoopCount == (p2)->fLoopCount) && ((p1)->fSampleFrame == (p2)->fSampleFrame) ? 0 : -1) #define IOAUDIOENGINEPOSITION_IS_ZERO(p1) (((p1)->fLoopCount == 0) && ((p1)->fSampleFrame == 0)) /*! * @class IOAudioEngine * @abstract Abstract base class for a single audio audio / I/O engine. * @discussion An IOAudioEngine is defined by a single I/O engine to transfer data to * or from one ore more sample buffers. Each sample buffer is represented by a single IOAudioStream * instance. A single IOAudioEngine must contain at least one IOAudioStream, but has no upper * limit on the number of IOAudioStreams it may contain. An IOAudioEngine instance may contain * both input and output IOAudioStreams. * * An audio driver must subclass IOAudioEngine in order to provide certain services. An * IOAudioEngine subclass must start and stop the I/O engine when requested. The I/O * engine should be continuously running and loop around from end to beginning. While the audio * engine is running, it must take a timestamp as the sample buffer(s) wrap around and start at * the beginning. The CoreAudio.framework uses the timestamp to calculate the exact position of * the audio engine. An IOAudioEngine subclass must implement getCurrentSampleFrame() to provide * a sample position on demand. Finally, an IOAudioEngine subclass must provide clipping and * format conversion routines to go to/from the CoreAudio.framework's native float format. * * If multiple stream formats or sample rates are allowed, the IOAudioEngine * subclass must provide support for changing the hardware when a format or sample rate is * changed. * * There are several attributes associated with a single IOAudioEngine: . * * The IOAudioEngine superclass provides a shared status buffer that contains all of the dynamic pieces * of information about the audio engine (type IOAudioEngineStatus). It runs an erase process on * all of the output streams. The erase head is used to zero out the mix and sample buffers after * the samples have been played. Additionally, the IOAudioEngine superclass handles the * communication with the CoreAudio.framework and makes the decision to start and stop the * audio engine when it detects it is in use. * * In order for an audio device to play back or record sound, an IOAudioEngine subclass must be created. * The subclass must initialize all of the necessary hardware resources to prepare for starting the * audio I/O engine. It typically will perform these tasks in the initHardware() method. A subclass * may also implement a stop() method which is called as the driver is being torn down. This is * typically called in preparation of removing the device from the system for removable devices. * * In addition to initializing the necessary hardware, there are a number of other tasks an * IOAudioEngine must do during initHardware(). It must create the necessary IOAudioStream objects * to match the device capabilities. Each IOAudioStream must be added using addAudioStream(). It * also should create the IOAudioControls needed to control the various attributes of the audio engine: * output volume, mute, input gain, input selection, analog passthru. To do that, addDefaultAudioControl() * should be called with each IOAudioControl to be attached to the IOAudioEngine. In order to provide * for proper synchronization, the latency of the audio engine should be specified with setSampleLatency(). * This value represents the latency between the timestamp taken at the beginning of the buffer and * when the audio is actually played (or recorded) by the device. If a device is block based or if * there is a need to keep the CoreAudio.framework a certain number of samples ahead of (or behind for * input) the I/O head, that value should be specified using setSampleOffset(). If this is not specified * the CoreAudio.framework may attempt to get as close to the I/O head as possible. * * The following fields in the shared IOAudioEngineStatus struct must be maintained by the subclass * implementation: * <pre> * <t> fCurrentLoopCount - the number of times the sample buffer has wrapped around to the beginning * <t> fLastLoopTime - timestamp of the most recent time that the I/O engine looped back to the * beginning of the sample buffer * </pre> * It is critically important that the fLastLoopTime field be as accurate as possible. It is * the basis for the entire timer and synchronization mechanism used by the audio system. * * At init time, the IOAudioEngine subclass must call setNumSampleFramesPerBuffer() to indicate how large * each of the sample buffers are (measured in sample frames). Within a single IOAudioEngine, all sample * buffers must be the same size and be running at the same sample rate. If different buffers/streams can * be run at different rates, separate IOAudioEngines should be used. The IOAudioEngine subclass must * also call setSampleRate() at init time to indicate the starting sample rate of the device. * */ class IOAudioEngine : public IOService { OSDeclareAbstractStructors(IOAudioEngine) friend class IOAudioEngineUserClient; friend class IOAudioDevice; friend class IOAudioStream; public: /*! @var gSampleRateWholeNumberKey */ static const OSSymbol *gSampleRateWholeNumberKey; /*! @var gSampleRateFractionKey */ static const OSSymbol *gSampleRateFractionKey; /*! @var numSampleFramesPerBuffer */ UInt32 numSampleFramesPerBuffer; /*! @var sampleRate The current sample rate of the audio engine in samples per second */ IOAudioSampleRate sampleRate; /*! @var numErasesPerBuffer The number of times the erase head get scheduled to run for each * cycle of the audio engine */ UInt32 numErasesPerBuffer; /*! @var runEraseHead Set to true if the erase head is to run when the audio engine is running. This is the * case if there are any output streams. */ bool runEraseHead; /*! @var audioEngineStopPosition When all clients have disconnected, this is set to one buffer length past the * current audio engine position at the time. Then when the stop position is reached, the audio engine * is stopped */ IOAudioEnginePosition audioEngineStopPosition; /*! @var isRegistered Internal state variable to keep track or whether registerService() has been called. */ bool isRegistered; /*! @var configurationChangeInProgress Set to true after beginConfigurationChange() and false upon a * subsequent call to completeConfigurationChange() or cancelConfigurationChange(). */ bool configurationChangeInProgress; /*! @var state The current state of the IOAudioEngine - running, stopped, paused */ IOAudioEngineState state; /*! @var status Status struct shared with the CoreAudio.framework */ IOAudioEngineStatus * status; /*! @var audioDevice The IOAudioDevice instance to which the IOAudioEngine belongs */ IOAudioDevice * audioDevice; /*! @var workLoop The IOWorkLoop for the audio driver - shared with the IOAudioDevice */ IOWorkLoop *workLoop; /*! @var commandGate The IOCommandGate for this audio engine - attached to the driver's IOWorkLoop */ IOCommandGate *commandGate; /*! @var inputStreams An OSSet of all of the input IOAudioStreams attached to this IOAudioEngine */ OSOrderedSet *inputStreams; UInt32 maxNumInputChannels; /*! @var outputStreams An OSSet of all of the output IOAudioStreams attached to this IOAudioEngine */ OSOrderedSet *outputStreams; UInt32 maxNumOutputChannels; /*! @var userClients An OSSet of all of the currently connected user clients */ OSSet *userClients; /*! @var defaultAudioControls All of the IOAudioControls that affect this audio engine */ OSSet *defaultAudioControls; /*! @var numActiveUserClients A total of the active user clients - those that are currently playing or * recording audio */ UInt32 numActiveUserClients; UInt32 sampleOffset; UInt32 index; bool duringStartup; protected: /*! * @var deviceStartedAudioEngine Used by the IOAudioDevice to determine responsibility for shutting * the audio engine down when it is no longer needed. */ bool deviceStartedAudioEngine; protected: struct ExpansionData { UInt32 pauseCount; }; ExpansionData *reserved; public: // This takes the 0th reserved slot: virtual IOReturn performFormatChange(IOAudioStream *audioStream, const IOAudioStreamFormat *newFormat, const IOAudioStreamFormatExtension *formatExtension, const IOAudioSampleRate *newSampleRate); private: OSMetaClassDeclareReservedUsed(IOAudioEngine, 0); OSMetaClassDeclareReservedUnused(IOAudioEngine, 1); OSMetaClassDeclareReservedUnused(IOAudioEngine, 2); OSMetaClassDeclareReservedUnused(IOAudioEngine, 3); OSMetaClassDeclareReservedUnused(IOAudioEngine, 4); OSMetaClassDeclareReservedUnused(IOAudioEngine, 5); OSMetaClassDeclareReservedUnused(IOAudioEngine, 6); OSMetaClassDeclareReservedUnused(IOAudioEngine, 7); OSMetaClassDeclareReservedUnused(IOAudioEngine, 8); OSMetaClassDeclareReservedUnused(IOAudioEngine, 9); OSMetaClassDeclareReservedUnused(IOAudioEngine, 10); OSMetaClassDeclareReservedUnused(IOAudioEngine, 11); OSMetaClassDeclareReservedUnused(IOAudioEngine, 12); OSMetaClassDeclareReservedUnused(IOAudioEngine, 13); OSMetaClassDeclareReservedUnused(IOAudioEngine, 14); OSMetaClassDeclareReservedUnused(IOAudioEngine, 15); OSMetaClassDeclareReservedUnused(IOAudioEngine, 16); OSMetaClassDeclareReservedUnused(IOAudioEngine, 17); OSMetaClassDeclareReservedUnused(IOAudioEngine, 18); OSMetaClassDeclareReservedUnused(IOAudioEngine, 19); OSMetaClassDeclareReservedUnused(IOAudioEngine, 20); OSMetaClassDeclareReservedUnused(IOAudioEngine, 21); OSMetaClassDeclareReservedUnused(IOAudioEngine, 22); OSMetaClassDeclareReservedUnused(IOAudioEngine, 23); OSMetaClassDeclareReservedUnused(IOAudioEngine, 24); OSMetaClassDeclareReservedUnused(IOAudioEngine, 25); OSMetaClassDeclareReservedUnused(IOAudioEngine, 26); OSMetaClassDeclareReservedUnused(IOAudioEngine, 27); OSMetaClassDeclareReservedUnused(IOAudioEngine, 28); OSMetaClassDeclareReservedUnused(IOAudioEngine, 29); OSMetaClassDeclareReservedUnused(IOAudioEngine, 30); OSMetaClassDeclareReservedUnused(IOAudioEngine, 31); OSMetaClassDeclareReservedUnused(IOAudioEngine, 32); OSMetaClassDeclareReservedUnused(IOAudioEngine, 33); OSMetaClassDeclareReservedUnused(IOAudioEngine, 34); OSMetaClassDeclareReservedUnused(IOAudioEngine, 35); OSMetaClassDeclareReservedUnused(IOAudioEngine, 36); OSMetaClassDeclareReservedUnused(IOAudioEngine, 37); OSMetaClassDeclareReservedUnused(IOAudioEngine, 38); OSMetaClassDeclareReservedUnused(IOAudioEngine, 39); OSMetaClassDeclareReservedUnused(IOAudioEngine, 40); OSMetaClassDeclareReservedUnused(IOAudioEngine, 41); OSMetaClassDeclareReservedUnused(IOAudioEngine, 42); OSMetaClassDeclareReservedUnused(IOAudioEngine, 43); OSMetaClassDeclareReservedUnused(IOAudioEngine, 44); OSMetaClassDeclareReservedUnused(IOAudioEngine, 45); OSMetaClassDeclareReservedUnused(IOAudioEngine, 46); OSMetaClassDeclareReservedUnused(IOAudioEngine, 47); public: /*! * @function createDictionaryFromSampleRate * @abstract Internal routine used to generate a dictionary matching the given sample rate. * @discussion Used to generate a sample rate dictionary for the IORegistry - used by the * CoreAudio.framework. * @result Returns the newly create OSDictionary */ static OSDictionary *createDictionaryFromSampleRate(const IOAudioSampleRate *sampleRate, OSDictionary *rateDict = 0); /*! * @function createSampleRateFromDictionary * @abstract Internal routine used to generate a sample rate from an OSDictionary. * @discussion Used to generate a sample rate give a new OSDictionary from the IORegistry - coming * from the CoreAudio.framework. * @result Returns the sample rate */ static IOAudioSampleRate *createSampleRateFromDictionary(const OSDictionary *rateDict, IOAudioSampleRate *sampleRate = 0); /*! * @function init * @abstract Performs initialization of a newly allocated IOAudioEngine. * @discussion This function is responsible for initialization of all of the general attributes of * a new IOAudioEngine. It initializes instance variables to their default * values and allocates the shared status buffer. Subclasses will likely want to override this method * and do all of their common initialization in their implementation. They do need to be sure to call * IOAudioEngine's implementation of init and pay attention to the return value. * @param properties The default properties for the IOAudioEngine * @result Returns true if initialization was successful */ virtual bool init(OSDictionary *properties); /*! * @function free * @abstract Frees all of the resources allocated by the IOAudioEngine. * @discussion Do not call this directly. This is called automatically by the system when the instance's * refcount goes to 0. To decrement the refcount, call release() on the object. */ virtual void free(); /*! * @function getWorkLoop * @abstract Returns the IOWorkLoop for the driver */ virtual IOWorkLoop *getWorkLoop() const; /*! * @function getCommandGate * @abstract Returns the IOCommandGate for this IOAudioEngine */ virtual IOCommandGate *getCommandGate() const; /*! * @function start * @abstract A simple cover function for start(IOService *, IOAudioDevice *) that assumes the provider * is the IOAudioDevice. * @discussion Subclasses will want to override start(IOService *, IOAudioDevice *) rather than this * one. * @param provider The service provider for the IOAudioEngine (the IOAudioDevice in this case) * @result Returns true if the IOAudioEngine was successfully started. */ virtual bool start(IOService *provider); /*! * @function start * @abstract Standard IOKit start() routine called to start an IOService * @discussion This function is called in order to prepare the IOAudioEngine for use. It does NOT * mean that the audio I/O engine itself should be started. This implementation gets the IOWorkLoop * from the IOAudioDevice and allocates an IOCommandGate. Finally it calls initHardware() in which * all of the subclass-specific device initialization should be done. Upon return from initHardware() * all IOAudioStreams should be created and added to the audio engine. Also, all IOAudioControls * for this IOAudioEngine should be created and attached. * @param provider The service provider for the IOAudioEngine * @param device The IOAudioDevice to which this IOAudioEngine belongs * @result Returns true if the service was successfully started */ virtual bool start(IOService *provider, IOAudioDevice *device); /*! * @function initHardware * @abstract This function is called by start() to provide a convenient place for the subclass to * perform its hardware initialization. * @discussion Upon return from this function, all IOAudioStreams and IOAudioControls should be created * and the audio engine should be ready to be started when a client requests that playback begin. * @function provider The service provider numb for this audio engine - typically the IOAudioDevice. * @result Returns true if the hardware was successfully initialized */ virtual bool initHardware(IOService *provider); /*! * @function stop * @abstract Called to stop the service and prepare for the driver to be terminated. * @discussion This function is called before the driver is terminated and usually means that the device * has been removed from the system. * @param provider The service provider for the IOAudioEngine */ virtual void stop(IOService *provider); /*! * @function registerService * @abstract Called when this audio engine is ready to begin vending services * @discussion This function is called by IOAudioDevice::activateAudioEngine() once the audio engine * has been fully initialized and is ready to begin audio playback. * @var options */ virtual void registerService(IOOptionBits options = 0); virtual void setAudioDevice(IOAudioDevice *device); virtual void setIndex(UInt32 index); virtual void setDescription(const char *description); /*! * @function newUserClient * @abstract Called to request a new user client object for this service * @discussion This function is called automatically by IOKit when a user process attempts * to connect to this service. It allocates a new IOAudioEngineUserClient object and increments * the number of connections for this audio engine. If this is the first user client for this IOAudioEngine, * it calls startAudioEngine(). There is no need to call this function directly. * @param task The task requesting the new user client * @param securityID Optional security paramater passed in by the client - ignored * @param type Optional user client type passed in by the client - ignored * @param handler The new IOUserClient * must be stored in this param on a successful completion * @result Returns kIOReturnSuccess on success. May also result kIOReturnError or kIOReturnNoMemory. */ virtual IOReturn newUserClient(task_t task, void *securityID, UInt32 type, IOUserClient **handler); /*! * @function addAudioStream * @abstract Called by the driver to add an IOAudioStream to the audio engine * @discussion This must be called at least once to make sure the audio engine has at least one IOAudioStream. * @param stream The IOAudioStream to be added * @result Returns kIOReturnSuccess if the stream was successfully added */ virtual IOReturn addAudioStream(IOAudioStream *stream); virtual IOAudioStream *getAudioStream(IOAudioStreamDirection direction, UInt32 channelID); virtual void lockAllStreams(); virtual void unlockAllStreams(); virtual void updateChannelNumbers(); /*! * @function resetStatusBuffer * @abstract Resets the status buffer to its default values * @discussion This is called during startAudioEngine() and resumeAudioEngine() to clear out the status buffer * in preparation of starting up the I/O engine. There is no need to call this directly. */ virtual void resetStatusBuffer(); /*! * @function clearAllSampleBuffers * @abstract Zeros out all of the sample and mix buffers associated with the IOAudioEngine * @discussion This is called during resumeAudioEngine() since the audio engine gets started back at the * beginning of the sample buffer. */ virtual void clearAllSampleBuffers(); /*! * @function getCurrentSampleFrame * @abstract Called to get the current sample frame from the IOAudioEngine subclass * @discussion * @result */ virtual UInt32 getCurrentSampleFrame() = 0; /*! * @function startAudioEngine * @abstract Called to start the audio I/O engine * @discussion This method is called automatically when the audio engine is placed into use the first time. * This must be overridden by the subclass. No call to the superclass' implementation is * necessary. The subclass' implementation must start up the audio I/O engine. This includes any audio * engine that needs to be started as well as any interrupts that need to be enabled. Upon successfully * starting the engine, the subclass' implementation must call _setState(kAudioEngineRunning). If * it has also checked the state using getState() earlier in the implementation, the stateLock must be * acquired for the entire initialization process (using IORecursiveLockLock(stateLock) and * IORecursiveLockUnlock(stateLock)) to ensure that the state remains consistent. See the general class * comments for an example. * @result Must return kIOReturnSuccess on a successful start of the engine. */ virtual IOReturn startAudioEngine(); /*! * @function stopAudioEngine * @abstract Called to stop the audio I/O engine * @discussion This method is called automatically when the last client disconnects from this audio engine. * It must be overridden by the subclass. No call to the superclass' implementation is necessary. * The subclass' implementation must stop the audio I/O engine. The audio engine (if it exists) should * be stopped and any interrupts disabled. Upon successfully stopping the engine, the subclass must call * _setState(kAudioEngineStopped). If it has also checked the state using getState() earlier in the * implementation, the stateLock must be acquired for the entire initialization process (using * IORecursiveLockLock(stateLock) and IORecursiveLockUnlock(stateLock)) to ensure that the state remains * consistent. * @result Must return kIOReturnSuccess on a successful stop of the engine. */ virtual IOReturn stopAudioEngine(); virtual IOReturn pauseAudioEngine(); virtual IOReturn resumeAudioEngine(); /*! * @function performAudioEngineStart * @abstract Called to start the audio I/O engine * @discussion This method is called by startAudioEngine(). This must be overridden by the subclass. * No call to the superclass' implementation is necessary. The subclass' implementation must start up the * audio I/O engine. This includes any audio engine that needs to be started as well as any interrupts * that need to be enabled. * @result Must return kIOReturnSuccess on a successful start of the engine. */ virtual IOReturn performAudioEngineStart(); /*! * @function performAudioEngineStop * @abstract Called to stop the audio I/O engine * @discussion This method is called by stopAudioEngine() and pauseAudioEngine. * This must be overridden by the subclass. No call to the superclass' implementation is * necessary. The subclass' implementation must stop the audio I/O engine. This includes any audio * engine that needs to be stopped as well as any interrupts that need to be disabled. * @result Must return kIOReturnSuccess on a successful stop of the engine. */ virtual IOReturn performAudioEngineStop(); /*! * @function getState * @abstract Returns the current state of the IOAudioEngine * @discussion If this method is called in preparation for calling _setState(), the stateLock must * be acquired before the first call to getState() and held until after the last call to _setState(). * Be careful not to return from the code acquiring the lock while the lock is being held. That * will cause a deadlock situation. * @result The current state of the IOAudioEngine: kAudioEngineRunning, kAudioEngineStopped */ virtual IOAudioEngineState getState(); /*! * @function getSampleRate Returns the sample rate of the IOAudioEngine in samples per second */ virtual const IOAudioSampleRate *getSampleRate(); virtual IOReturn hardwareSampleRateChanged(const IOAudioSampleRate *sampleRate); /*! * @function getErases Returns true if the audio engine will run the erase head when the audio engine is running. */ virtual bool getRunEraseHead(); /*! * @function getStatus Returns a pointer to the shared status buffer */ virtual const IOAudioEngineStatus *getStatus(); /*! * @function timerCallback * @abstract A static method used as a callback for the IOAudioDevice timer services * @discussion This method implements the IOAudioDevice::TimerEvent type. * @param arg1 The IOAudioEngine that is the target of the event * @param device The IOAudioDevice that sent the timer event */ static void timerCallback(OSObject *arg1, IOAudioDevice *device); /*! * @function timerFired * @abstract Called by timerCallback to indicate the timer has fired * @discussion This method calls performErase() and performFlush() to do erase head processing and * audio engine flushing each time the timer event fires. */ virtual void timerFired(); /*! * @function getTimerInterval * @abstract Called to get the timer interval for use by the timer event * @discussion This method is called each timer the timer event is enabled through addTimer(). The default * implementation is set to return a value such that the timer event runs n times each cycle of the audio * engine through the sample buffer. The value n is stored as the instance variable: numErasesPerBuffer. * The default value of numErasesPerBuffer is set to IOAUDIOENGINE_DEFAULT_NUM_ERASES_PER_BUFFER which is 4. * A subclass may change the value of numErasesPerBuffer or override getTimerInterval. If it is overridden, * the subclass should call the superclass' implementation, compare its interval with the superclass' and * return the smaller of the two. * @result Returns the interval for the timer event */ virtual AbsoluteTime getTimerInterval(); /*! * @function performErase * @abstract Called to perform erase head processing * @discussion This method is called automatically each time the timer event fires and erases the sample * buffer and mix buffer from the previous location up to the current location of the audio engine. */ virtual void performErase(); /*! * @function performFlush * @abstract Called to perform the flush operation * @discussion This method is called automatically each time the timer event fires. It stops the audio engine * if there are no more clients and the audio engine is passed the latest flush ending position. */ virtual void performFlush(); virtual void stopEngineAtPosition(IOAudioEnginePosition *endingPosition); virtual IOReturn mixOutputSamples(const void *sourceBuf, void *mixBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream); virtual IOReturn clipOutputSamples(const void *mixBuf, void *sampleBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream); virtual void resetClipPosition(IOAudioStream *audioStream, UInt32 clipSampleFrame); virtual IOReturn convertInputSamples(const void *sampleBuf, void *destBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream); virtual void takeTimeStamp(bool incrementLoopCount = true, AbsoluteTime *timestamp = NULL); virtual IOReturn getLoopCountAndTimeStamp(UInt32 *loopCount, AbsoluteTime *timestamp); virtual IOReturn calculateSampleTimeout(AbsoluteTime *sampleInterval, UInt32 numSampleFrames, IOAudioEnginePosition *startingPosition, AbsoluteTime *wakeupTime); virtual IOReturn performFormatChange(IOAudioStream *audioStream, const IOAudioStreamFormat *newFormat, const IOAudioSampleRate *newSampleRate); virtual void beginConfigurationChange(); virtual void completeConfigurationChange(); virtual void cancelConfigurationChange(); virtual IOReturn addDefaultAudioControl(IOAudioControl *defaultAudioControl); virtual IOReturn removeDefaultAudioControl(IOAudioControl *defaultAudioControl); virtual void removeAllDefaultAudioControls(); virtual OSString *getGlobalUniqueID(); virtual OSString *getLocalUniqueID(); protected: /*! * @function initKeys * @abstract Internal initialization routine which generates the OSSymbols with the keys. * @discussion Do not call this directly. */ static void initKeys(); virtual void setNumSampleFramesPerBuffer(UInt32 numSampleFrames); virtual UInt32 getNumSampleFramesPerBuffer(); /*! * @function _setState * @abstract Used to indicate that the audio engine is in the specified state * @discussion This method simply sets the internal state of the audio engine to the specified state. It does not * affect a change to the state. It does however keep other internal state-related attributes consistent. * For example, it enables or disables the timer as needed when the state changes to running or stopped. * @param newState The state the audio engine is in * @result Returns the old state */ virtual IOAudioEngineState setState(IOAudioEngineState newState); /*! * @function setSampleRate * @abstract Records the sample rate of the audio engine * @discussion This method must be called during initialization of a new audio engine to record the audio engine's * initial sample rate. It also is intended to be used to record changes to the sample rate during use. * Currently changing sample rates after the audio engine has been started is not supported. * It may require that the sample buffers be re-sized. This will be available in an upcoming release. * @param newSampleRate The sample rate of the audio engine in samples per second */ virtual void setSampleRate(const IOAudioSampleRate *newSampleRate); /*! * @function _setSampleLatency * @abstract Sets the sample latency for the audio engine * @discussion The sample latency represents the number of samples ahead of the playback head * that it is safe to write into the sample buffer. The audio device API will never write * closer to the playback head than the number of samples specified. For input audio engines * the number of samples is behind the record head. */ virtual void setSampleLatency(UInt32 numSamples); virtual void setOutputSampleLatency(UInt32 numSamples); virtual void setInputSampleLatency(UInt32 numSamples); virtual void setSampleOffset(UInt32 numSamples); /*! * @function _setErases * @abstract Tells the audio engine whether or not to run the erase head * @discussion By default, output audio engines run the erase head and input audio engines do not. This method can * be called after _setDirection() is called in order to change the default behavior. * @param runEraseHead The audio engine will run the erase head if this value is true */ virtual void setRunEraseHead(bool runEraseHead); /*! * @function clientClosed * @abstract Called automatically when a user client closes its connection to the audio engine * @discussion This method decrements the number of connections to the audio engine and if they reach * zero, the audio engine is called with a call to stopAudioEngine(). This method should not be called directly. * @param client The user client that has disconnected. */ virtual void clientClosed(IOAudioEngineUserClient *client); /*! * @function addTimer * @abstract Enables the timer event for the audio engine * @discussion There is a timer event needed by the IOAudioEngine for processing the erase head * and performing flushing operations. When the timer fires, the method timerFired() is ultimately * called which in turn calls performErase() and performFlush(). This is called automatically * to enable the timer event for this audio engine. It is called by _setState() when the audio engine state * is set to kAudioEngineRunning. When the timer is no longer needed, removeTimer() is called. * There is no need to call this directly. */ virtual void addTimer(); /*! * @function removeTimer * @abstract Disables the timer event for the audio engine * @discussion This method is called automatically to disable the timer event for this audio engine. * There is need to call it directly. This method is called by _setState() when the audio engine state * is changed from kAudioEngineRunning to one of the stopped states. */ virtual void removeTimer(); virtual void sendFormatChangeNotification(IOAudioStream *audioStream); virtual void sendNotification(UInt32 notificationType); virtual IOReturn createUserClient(task_t task, void *securityID, UInt32 type, IOAudioEngineUserClient **newUserClient); static IOReturn addUserClientAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4); static IOReturn removeUserClientAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4); static IOReturn detachUserClientsAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4); virtual IOReturn addUserClient(IOAudioEngineUserClient *newUserClient); virtual IOReturn removeUserClient(IOAudioEngineUserClient *userClient); virtual IOReturn detachUserClients(); virtual IOReturn startClient(IOAudioEngineUserClient *userClient); virtual IOReturn stopClient(IOAudioEngineUserClient *userClient); virtual IOReturn incrementActiveUserClients(); virtual IOReturn decrementActiveUserClients(); virtual void detachAudioStreams(); void setWorkLoopOnAllAudioControls(IOWorkLoop *wl); }; #endif /* _IOKIT_IOAUDIOENGINE_H */