/*============================================================================= CAAudioHardwareDevice.cpp $Log: CAAudioHardwareDevice.cpp,v $ Revision 1.12 2005/01/19 02:48:12 jcm10 add HasClockDomain() Revision 1.11 2004/11/06 02:37:37 jcm10 add support for some new Tiger properties Revision 1.10 2004/02/13 23:03:45 jcm10 make sure the related devices property exists before trying to get the number of related devices Revision 1.9 2003/11/19 00:01:24 jcm10 add support for accessing the related devices property Revision 1.8 2003/07/18 22:55:53 jcm10 add support for setting the IsRunning property Revision 1.7 2003/07/18 00:33:01 jcm10 add support for the iSub controls Revision 1.6 2003/06/18 22:09:20 jcm10 add IsControlEnabled methods Revision 1.5 2003/06/05 19:08:33 jcm10 add StartIOProcAtTime Revision 1.4 2003/06/04 22:34:59 jcm10 adjust to the StartAtTime API change Revision 1.3 2003/05/29 18:08:09 jcm10 implement GetNearestStartTime() Revision 1.2 2003/05/28 19:42:37 jcm10 the value of kAudioDevicePropertyConfigurationApplication is a bundle ID rather than a path Revision 1.1 2003/05/23 19:06:50 jcm10 first checked in Revision 1.12 2003/05/06 18:42:39 jcm10 add support for displaying/manipulating the IOProc format Revision 1.11 2003/04/07 23:20:18 jcm10 return an empty string instead of throwing an exception in CopyName() Revision 1.10 2003/04/03 01:39:49 jcm10 add GetCurrentTime and TranslateTime Revision 1.9 2003/02/17 20:54:03 jcm10 add Get/SetIOProcStreamUsage() Revision 1.8 2003/02/05 02:58:17 jcm10 make the controls tab work in the device window Revision 1.7 2003/02/04 02:38:41 jcm10 preliminary support for the controls list Revision 1.6 2003/01/30 22:31:31 jcm10 make the Streams tab of the Device window work Revision 1.5 2003/01/29 19:33:40 jcm10 make everything on the device window's info tab work Revision 1.4 2003/01/27 20:08:32 jcm10 make pretty much everything work Revision 1.3 2003/01/25 02:59:12 jcm10 hook up hog mode and mixability items Revision 1.2 2003/01/24 03:25:43 jcm10 add file player window Revision 1.1 2002/11/27 22:33:09 jcm10 first checked in Revision 0.0 Wed Nov 20 2002 18:05:08 US/Pacific moorf Created $NoKeywords: $ =============================================================================*/ //============================================================================= // Includes //============================================================================= // Self Include #include "CAAudioHardwareDevice.h" // Internal Includes #include "CAAudioHardwareStream.h" // PublicUtility Includes #include "CAAutoDisposer.h" #include "CADebugMacros.h" #include "CAException.h" // System Includes #include #include // Standard Library Includes #include //============================================================================= // CAAudioHardwareDevice //============================================================================= CAAudioHardwareDevice::CAAudioHardwareDevice(AudioDeviceID inAudioDeviceID) : mAudioDeviceID(inAudioDeviceID) { } CAAudioHardwareDevice::~CAAudioHardwareDevice() { } CFStringRef CAAudioHardwareDevice::CopyName() const { CFStringRef theAnswer = NULL; try { UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceNameCFString, theSize, &theAnswer); } catch(...) { // Sometimes a device doesn't have a name. Rather than throw an exception here // it is better for the rest of the code if it just return an empty string. // At some point, this should probably go back to throwing an exception. theAnswer = CFSTR(""); } return theAnswer; } CFStringRef CAAudioHardwareDevice::CopyManufacturer() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceManufacturerCFString, theSize, &theAnswer); return theAnswer; } CFStringRef CAAudioHardwareDevice::CopyOwningPlugInBundleID() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioObjectPropertyCreator, theSize, &theAnswer); return theAnswer; } CFStringRef CAAudioHardwareDevice::CopyUID() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceUID, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::HasModelUID() const { return HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyModelUID); } CFStringRef CAAudioHardwareDevice::CopyModelUID() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyModelUID, theSize, &theAnswer); return theAnswer; } CFStringRef CAAudioHardwareDevice::CopyConfigurationApplicationBundleID() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyConfigurationApplication, theSize, &theAnswer); return theAnswer; } UInt32 CAAudioHardwareDevice::GetTransportType() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::CanBeDefaultDevice(CAAudioHardwareDeviceSectionID inSection, bool inIsSystem) const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); AudioHardwarePropertyID thePropertyID = inIsSystem ? kAudioDevicePropertyDeviceCanBeDefaultSystemDevice : kAudioDevicePropertyDeviceCanBeDefaultDevice; GetPropertyData(0, inSection, thePropertyID, theSize, &theAnswer); return theAnswer != 0; } bool CAAudioHardwareDevice::HasDevicePlugInStatus() const { return HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyPlugIn); } OSStatus CAAudioHardwareDevice::GetDevicePlugInStatus() const { OSStatus theAnswer = 0; UInt32 theSize = sizeof(OSStatus); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyPlugIn, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::IsAlive() const { bool theAnswer = HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive); if(theAnswer) { UInt32 isAlive = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, theSize, &isAlive); theAnswer = isAlive != 0; } return theAnswer; } bool CAAudioHardwareDevice::IsRunning() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, theSize, &theAnswer); return theAnswer != 0; } void CAAudioHardwareDevice::SetIsRunning(bool inIsRunning) { UInt32 theValue = inIsRunning ? 1 : 0; UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, theSize, &theValue); } bool CAAudioHardwareDevice::IsRunningSomewhere() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunningSomewhere, theSize, &theAnswer); return theAnswer != 0; } pid_t CAAudioHardwareDevice::GetHogModeOwner() const { pid_t theAnswer = 0; UInt32 theSize = sizeof(pid_t); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyHogMode, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::TakeHogMode() { pid_t thePID = 0; UInt32 theSize = sizeof(pid_t); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyHogMode, theSize, &thePID); return thePID == getpid(); } void CAAudioHardwareDevice::ReleaseHogMode() { pid_t thePID = -1; UInt32 theSize = sizeof(pid_t); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyHogMode, theSize, &thePID); } bool CAAudioHardwareDevice::SupportsChangingMixability() const { bool theAnswer = HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertySupportsMixing); if(theAnswer) { theAnswer = PropertyIsSettable(0, kAudioDeviceSectionGlobal, kAudioDevicePropertySupportsMixing); } return theAnswer; } bool CAAudioHardwareDevice::IsMixable() const { UInt32 theAnswer = 1; if(HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertySupportsMixing)) { UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertySupportsMixing, theSize, &theAnswer); } return theAnswer != 0; } void CAAudioHardwareDevice::SetIsMixable(bool inIsMixable) { UInt32 theValue = inIsMixable ? 1 : 0; UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertySupportsMixing, theSize, &theValue); } bool CAAudioHardwareDevice::HasIsConnectedStatus(CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(0, inSection, kAudioDevicePropertyJackIsConnected); } bool CAAudioHardwareDevice::GetIsConnectedStatus(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertyJackIsConnected, theSize, &theAnswer); return theAnswer != 0; } bool CAAudioHardwareDevice::HasPreferredStereoChannels(CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(0, inSection, kAudioDevicePropertyPreferredChannelsForStereo); } void CAAudioHardwareDevice::GetPreferredStereoChannels(CAAudioHardwareDeviceSectionID inSection, UInt32& outLeft, UInt32& outRight) const { UInt32 theStereoPair[2] = { 0, 0 }; UInt32 theSize = 2 * sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertyPreferredChannelsForStereo, theSize, theStereoPair); outLeft = theStereoPair[0]; outRight = theStereoPair[1]; } void CAAudioHardwareDevice::SetPreferredStereoChannels(CAAudioHardwareDeviceSectionID inSection, UInt32 inLeft, UInt32 inRight) { UInt32 theStereoPair[2] = { inLeft, inRight }; UInt32 theSize = 2 * sizeof(UInt32); SetPropertyData(0, inSection, kAudioDevicePropertyPreferredChannelsForStereo, theSize, theStereoPair); } UInt32 CAAudioHardwareDevice::GetNumberRelatedDevices() const { UInt32 theAnswer = 0; if(HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyRelatedDevices)) { theAnswer = GetPropertyDataSize(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyRelatedDevices); theAnswer = theAnswer / sizeof(AudioDeviceID); } return theAnswer; } AudioDeviceID CAAudioHardwareDevice::GetRelatedDeviceByIndex(UInt32 inIndex) const { AudioDeviceID theAnswer = 0; UInt32 theNumberRelatedDevices = GetNumberRelatedDevices(); if((theNumberRelatedDevices > 0) && (inIndex < theNumberRelatedDevices)) { CAAutoArrayDelete theRelatedDevices(theNumberRelatedDevices); GetRelatedDevices(theNumberRelatedDevices, theRelatedDevices); theAnswer = theRelatedDevices[inIndex]; } return theAnswer; } void CAAudioHardwareDevice::GetRelatedDevices(UInt32& ioNumberRelatedDevices, AudioDeviceID* outRelatedDevices) const { UInt32 theNumberRelatedDevices = std::min(GetNumberRelatedDevices(), ioNumberRelatedDevices); UInt32 theSize = theNumberRelatedDevices * sizeof(AudioDeviceID); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyRelatedDevices, theSize, outRelatedDevices); ioNumberRelatedDevices = theSize / sizeof(AudioDeviceID); } UInt32 CAAudioHardwareDevice::GetLatency(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertyLatency, theSize, &theAnswer); return theAnswer; } UInt32 CAAudioHardwareDevice::GetSafetyOffset(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertySafetyOffset, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::HasClockDomain() const { return HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain); } UInt32 CAAudioHardwareDevice::GetClockDomain() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareDevice::HasClockSourceControl() const { return HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSource); } bool CAAudioHardwareDevice::ClockSourceControlIsSettable() const { return PropertyIsSettable(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSource); } UInt32 CAAudioHardwareDevice::GetCurrentClockSourceID() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSource, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareDevice::SetCurrentClockSourceByID(UInt32 inID) { UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSource, theSize, &inID); } UInt32 CAAudioHardwareDevice::GetNumberAvailableClockSources() const { UInt32 theAnswer = 0; if(HasClockSourceControl()) { UInt32 theSize = GetPropertyDataSize(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSources); theAnswer = theSize / sizeof(UInt32); } return theAnswer; } UInt32 CAAudioHardwareDevice::GetAvailableClockSourceByIndex(UInt32 inIndex) const { AudioStreamID theAnswer = 0; UInt32 theNumberSources = GetNumberAvailableClockSources(); if((theNumberSources > 0) && (inIndex < theNumberSources)) { CAAutoArrayDelete theSourceList(theNumberSources); GetAvailableClockSources(theNumberSources, theSourceList); theAnswer = theSourceList[inIndex]; } return theAnswer; } void CAAudioHardwareDevice::GetAvailableClockSources(UInt32& ioNumberSources, UInt32* outSources) const { UInt32 theNumberSources = std::min(GetNumberAvailableClockSources(), ioNumberSources); UInt32 theSize = theNumberSources * sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSources, theSize, outSources); ioNumberSources = theSize / sizeof(UInt32); UInt32* theFirstItem = &(outSources[0]); UInt32* theLastItem = theFirstItem + ioNumberSources; std::sort(theFirstItem, theLastItem); } CFStringRef CAAudioHardwareDevice::CopyClockSourceNameForID(UInt32 inID) const { CFStringRef theAnswer = NULL; AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; UInt32 theSize = sizeof(AudioValueTranslation); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockSourceNameForIDCFString, theSize, &theTranslation); return theAnswer; } bool CAAudioHardwareDevice::HasDataSourceControl(CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(0, inSection, kAudioDevicePropertyDataSource); } bool CAAudioHardwareDevice::DataSourceControlIsSettable(CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(0, inSection, kAudioDevicePropertyDataSource); } UInt32 CAAudioHardwareDevice::GetCurrentDataSourceID(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertyDataSource, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareDevice::SetCurrentDataSourceByID(CAAudioHardwareDeviceSectionID inSection, UInt32 inID) { UInt32 theSize = sizeof(UInt32); SetPropertyData(0, inSection, kAudioDevicePropertyDataSource, theSize, &inID); } UInt32 CAAudioHardwareDevice::GetNumberAvailableDataSources(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; if(HasDataSourceControl(inSection)) { UInt32 theSize = GetPropertyDataSize(0, inSection, kAudioDevicePropertyDataSources); theAnswer = theSize / sizeof(UInt32); } return theAnswer; } UInt32 CAAudioHardwareDevice::GetAvailableDataSourceByIndex(CAAudioHardwareDeviceSectionID inSection, UInt32 inIndex) const { AudioStreamID theAnswer = 0; UInt32 theNumberSources = GetNumberAvailableDataSources(inSection); if((theNumberSources > 0) && (inIndex < theNumberSources)) { CAAutoArrayDelete theSourceList(theNumberSources); GetAvailableDataSources(inSection, theNumberSources, theSourceList); theAnswer = theSourceList[inIndex]; } return theAnswer; } void CAAudioHardwareDevice::GetAvailableDataSources(CAAudioHardwareDeviceSectionID inSection, UInt32& ioNumberSources, UInt32* outSources) const { UInt32 theNumberSources = std::min(GetNumberAvailableDataSources(inSection), ioNumberSources); UInt32 theSize = theNumberSources * sizeof(UInt32); GetPropertyData(0, inSection, kAudioDevicePropertyDataSources, theSize, outSources); ioNumberSources = theSize / sizeof(UInt32); UInt32* theFirstItem = &(outSources[0]); UInt32* theLastItem = theFirstItem + ioNumberSources; std::sort(theFirstItem, theLastItem); } CFStringRef CAAudioHardwareDevice::CopyDataSourceNameForID(CAAudioHardwareDeviceSectionID inSection, UInt32 inID) const { CFStringRef theAnswer = NULL; AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; UInt32 theSize = sizeof(AudioValueTranslation); GetPropertyData(0, inSection, kAudioDevicePropertyDataSourceNameForIDCFString, theSize, &theTranslation); return theAnswer; } Float64 CAAudioHardwareDevice::GetActualSampleRate() const { Float64 theAnswer = 0; UInt32 theSize = sizeof(Float64); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyActualSampleRate, theSize, &theAnswer); return theAnswer; } Float64 CAAudioHardwareDevice::GetNominalSampleRate() const { Float64 theAnswer = 0; UInt32 theSize = sizeof(Float64); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareDevice::SetNominalSampleRate(Float64 inSampleRate) { UInt32 theSize = sizeof(Float64); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, theSize, &inSampleRate); } bool CAAudioHardwareDevice::IsValidNominalSampleRate(Float64 inSampleRate) const { bool theAnswer = false; UInt32 theNumberRanges = GetNumberNominalSampleRateRanges(); CAAutoArrayDelete theRanges(theNumberRanges); GetNominalSampleRateRanges(theNumberRanges, theRanges); for(UInt32 theIndex = 0; !theAnswer && (theIndex < theNumberRanges); ++theIndex) { theAnswer = (inSampleRate >= theRanges[theIndex].mMinimum) && (inSampleRate <= theRanges[theIndex].mMinimum); } return theAnswer; } UInt32 CAAudioHardwareDevice::GetNumberNominalSampleRateRanges() const { UInt32 theSize = GetPropertyDataSize(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyAvailableNominalSampleRates); return theSize / sizeof(AudioValueRange); } void CAAudioHardwareDevice::GetNominalSampleRateRanges(UInt32& ioNumberRanges, AudioValueRange* outRanges) const { UInt32 theSize = ioNumberRanges * sizeof(AudioValueRange); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyAvailableNominalSampleRates, theSize, outRanges); ioNumberRanges = theSize / sizeof(AudioValueRange); } void CAAudioHardwareDevice::GetNominalSampleRateRangeByIndex(UInt32 inIndex, Float64& outMinimum, Float64& outMaximum) const { UInt32 theNumberRanges = GetNumberNominalSampleRateRanges(); ThrowIf(inIndex >= theNumberRanges, CAException(kAudioHardwareIllegalOperationError), "CAAudioHardwareDevice::GetNominalSampleRateRangeByIndex: index out of range"); CAAutoArrayDelete theRanges(theNumberRanges); GetNominalSampleRateRanges(theNumberRanges, theRanges); outMinimum = theRanges[inIndex].mMinimum; outMaximum = theRanges[inIndex].mMaximum; } UInt32 CAAudioHardwareDevice::GetIOBufferSize() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareDevice::SetIOBufferSize(UInt32 inBufferSize) { UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, theSize, &inBufferSize); } bool CAAudioHardwareDevice::UsesVariableIOBufferSizes() const { return HasProperty(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyUsesVariableBufferFrameSizes); } UInt32 CAAudioHardwareDevice::GetMaximumVariableIOBufferSize() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyUsesVariableBufferFrameSizes, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareDevice::GetIOBufferSizeRange(UInt32& outMinimum, UInt32& outMaximum) const { AudioValueRange theAnswer = { 0, 0 }; UInt32 theSize = sizeof(AudioValueRange); GetPropertyData(0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSizeRange, theSize, &theAnswer); outMinimum = static_cast(theAnswer.mMinimum); outMaximum = static_cast(theAnswer.mMaximum); } void CAAudioHardwareDevice::AddIOProc(AudioDeviceIOProc inIOProc, void* inClientData) { OSStatus theError = AudioDeviceAddIOProc(mAudioDeviceID, inIOProc, inClientData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::AddIOProc: got an error adding an IOProc"); } void CAAudioHardwareDevice::RemoveIOProc(AudioDeviceIOProc inIOProc) { OSStatus theError = AudioDeviceRemoveIOProc(mAudioDeviceID, inIOProc); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::RemoveIOProc: got an error removing an IOProc"); } void CAAudioHardwareDevice::StartIOProc(AudioDeviceIOProc inIOProc) { OSStatus theError = AudioDeviceStart(mAudioDeviceID, inIOProc); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::StartIOProc: got an error starting an IOProc"); } void CAAudioHardwareDevice::StartIOProcAtTime(AudioDeviceIOProc inIOProc, AudioTimeStamp& ioStartTime, bool inIsInput, bool inIgnoreHardware) { UInt32 theFlags = 0; if(inIsInput) { theFlags |= kAudioDeviceStartTimeIsInputFlag; } if(inIgnoreHardware) { theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag; } OSStatus theError = AudioDeviceStartAtTime(mAudioDeviceID, inIOProc, &ioStartTime, theFlags); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::StartIOProcAtTime: got an error starting an IOProc"); } void CAAudioHardwareDevice::StopIOProc(AudioDeviceIOProc inIOProc) { OSStatus theError = AudioDeviceStop(mAudioDeviceID, inIOProc); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::StopIOProc: got an error stopping an IOProc"); } void CAAudioHardwareDevice::GetIOProcStreamUsage(AudioDeviceIOProc inIOProc, CAAudioHardwareDeviceSectionID inSection, bool* outStreamUsage) const { // make an AudioHardwareIOProcStreamUsage the right size UInt32 theNumberStreams = GetNumberStreams(inSection); UInt32 theSize = sizeof(void*) + sizeof(UInt32) + (theNumberStreams * sizeof(UInt32)); CAAutoFree theStreamUsage(theSize); // set it up theStreamUsage->mIOProc = (void*)inIOProc; theStreamUsage->mNumberStreams = theNumberStreams; // get the property GetPropertyData(0, inSection, kAudioDevicePropertyIOProcStreamUsage, theSize, theStreamUsage); // fill out the return value for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex) { outStreamUsage[theIndex] = (theStreamUsage->mStreamIsOn[theIndex] != 0); } } void CAAudioHardwareDevice::SetIOProcStreamUsage(AudioDeviceIOProc inIOProc, CAAudioHardwareDeviceSectionID inSection, const bool* inStreamUsage) { // make an AudioHardwareIOProcStreamUsage the right size UInt32 theNumberStreams = GetNumberStreams(inSection); UInt32 theSize = sizeof(void*) + sizeof(UInt32) + (theNumberStreams * sizeof(UInt32)); CAAutoFree theStreamUsage(theSize); // set it up theStreamUsage->mIOProc = (void*)inIOProc; theStreamUsage->mNumberStreams = theNumberStreams; for(UInt32 theIndex = 0; theIndex < theNumberStreams; ++theIndex) { theStreamUsage->mStreamIsOn[theIndex] = (inStreamUsage[theIndex] ? 1 : 0); } // set the property SetPropertyData(0, inSection, kAudioDevicePropertyIOProcStreamUsage, theSize, theStreamUsage); } void CAAudioHardwareDevice::GetCurrentTime(AudioTimeStamp& outTime) { OSStatus theError = AudioDeviceGetCurrentTime(mAudioDeviceID, &outTime); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::GetCurrentTime: got an error retrieving the current time"); } void CAAudioHardwareDevice::TranslateTime(const AudioTimeStamp& inTime, AudioTimeStamp& outTime) { OSStatus theError = AudioDeviceTranslateTime(mAudioDeviceID, &inTime, &outTime); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::TranslateTime: got an error translating time"); } void CAAudioHardwareDevice::GetNearestStartTime(AudioTimeStamp& ioTime, bool inIsInput, bool inIgnoreHardware) { UInt32 theFlags = 0; if(inIsInput) { theFlags |= kAudioDeviceStartTimeIsInputFlag; } if(inIgnoreHardware) { theFlags |= kAudioDeviceStartTimeDontConsultDeviceFlag; } OSStatus theError = AudioDeviceGetNearestStartTime(mAudioDeviceID, &ioTime, theFlags); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::GetNearestStartTime: got an error getting the nearest start time"); } UInt32 CAAudioHardwareDevice::GetNumberStreams(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theSize = GetPropertyDataSize(0, inSection, kAudioDevicePropertyStreams); return theSize / sizeof(AudioStreamID); } void CAAudioHardwareDevice::GetStreams(CAAudioHardwareDeviceSectionID inSection, UInt32& ioNumberStreams, AudioStreamID* outStreamList) const { ioNumberStreams = std::min(GetNumberStreams(inSection), ioNumberStreams); UInt32 theSize = ioNumberStreams * sizeof(AudioStreamID); GetPropertyData(0, inSection, kAudioDevicePropertyStreams, theSize, outStreamList); ioNumberStreams = theSize / sizeof(AudioStreamID); AudioStreamID* theFirstItem = &(outStreamList[0]); AudioStreamID* theLastItem = theFirstItem + ioNumberStreams; std::sort(theFirstItem, theLastItem); } AudioStreamID CAAudioHardwareDevice::GetStreamByIndex(CAAudioHardwareDeviceSectionID inSection, UInt32 inIndex) const { AudioStreamID theAnswer = 0; UInt32 theNumberStreams = GetNumberStreams(inSection); if((theNumberStreams > 0) && (inIndex < theNumberStreams)) { CAAutoArrayDelete theStreamList(theNumberStreams); GetStreams(inSection, theNumberStreams, theStreamList); theAnswer = theStreamList[inIndex]; } return theAnswer; } UInt32 CAAudioHardwareDevice::GetTotalNumberChannels(CAAudioHardwareDeviceSectionID inSection) const { UInt32 theAnswer = 0; UInt32 theSize = GetPropertyDataSize(0, inSection, kAudioDevicePropertyStreamConfiguration); CAAutoFree theBufferList(theSize); GetPropertyData(0, inSection, kAudioDevicePropertyStreamConfiguration, theSize, theBufferList); for(UInt32 theIndex = 0; theIndex < theBufferList->mNumberBuffers; ++theIndex) { theAnswer += theBufferList->mBuffers[theIndex].mNumberChannels; } return theAnswer; } void CAAudioHardwareDevice::GetCurrentIOProcFormats(CAAudioHardwareDeviceSectionID inSection, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const { ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inSection)); for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex) { CAAudioHardwareStream theStream(GetStreamByIndex(inSection, theIndex)); theStream.GetCurrentIOProcFormat(outFormats[theIndex]); } } void CAAudioHardwareDevice::GetCurrentPhysicalFormats(CAAudioHardwareDeviceSectionID inSection, UInt32& ioNumberStreams, AudioStreamBasicDescription* outFormats) const { ioNumberStreams = std::min(ioNumberStreams, GetNumberStreams(inSection)); for(UInt32 theIndex = 0; theIndex < ioNumberStreams; ++theIndex) { CAAudioHardwareStream theStream(GetStreamByIndex(inSection, theIndex)); theStream.GetCurrentPhysicalFormat(outFormats[theIndex]); } } bool CAAudioHardwareDevice::HasVolumeControl(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(inChannel, inSection, kAudioDevicePropertyVolumeScalar); } bool CAAudioHardwareDevice::VolumeControlIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(inChannel, inSection, kAudioDevicePropertyVolumeScalar); } Float32 CAAudioHardwareDevice::GetVolumeControlScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { Float32 theValue = 0.0; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeScalar, theSize, &theValue); return theValue; } Float32 CAAudioHardwareDevice::GetVolumeControlDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { Float32 theValue = 0.0; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeDecibels, theSize, &theValue); return theValue; } void CAAudioHardwareDevice::SetVolumeControlScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) { UInt32 theSize = sizeof(Float32); SetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeScalar, theSize, &inValue); } void CAAudioHardwareDevice::SetVolumeControlDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) { UInt32 theSize = sizeof(Float32); SetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeDecibels, theSize, &inValue); } Float32 CAAudioHardwareDevice::GetVolumeControlScalarForDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) const { Float32 theValue = inValue; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeDecibelsToScalar, theSize, &theValue); return theValue; } Float32 CAAudioHardwareDevice::GetVolumeControlDecibelForScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) const { Float32 theValue = inValue; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyVolumeScalarToDecibels, theSize, &theValue); return theValue; } bool CAAudioHardwareDevice::HasMuteControl(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(inChannel, inSection, kAudioDevicePropertyMute); } bool CAAudioHardwareDevice::MuteControlIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(inChannel, inSection, kAudioDevicePropertyMute); } bool CAAudioHardwareDevice::GetMuteControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { UInt32 theValue = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyMute, theSize, &theValue); return theValue != 0; } void CAAudioHardwareDevice::SetMuteControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, bool inValue) { UInt32 theValue = (inValue ? 1 : 0); UInt32 theSize = sizeof(UInt32); SetPropertyData(inChannel, inSection, kAudioDevicePropertyMute, theSize, &theValue); } bool CAAudioHardwareDevice::HasPlayThruControl(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(inChannel, inSection, kAudioDevicePropertyPlayThru); } bool CAAudioHardwareDevice::PlayThruControlIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(inChannel, inSection, kAudioDevicePropertyPlayThru); } bool CAAudioHardwareDevice::GetPlayThruControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { UInt32 theValue = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(inChannel, inSection, kAudioDevicePropertyPlayThru, theSize, &theValue); return theValue != 0; } void CAAudioHardwareDevice::SetPlayThruControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, bool inValue) { UInt32 theValue = (inValue ? 1 : 0); UInt32 theSize = sizeof(UInt32); SetPropertyData(inChannel, inSection, kAudioDevicePropertyPlayThru, theSize, &theValue); } bool CAAudioHardwareDevice::HasISubOwnershipControl() const { return HasProperty(0, kAudioDeviceSectionOutput, kAudioDevicePropertyDriverShouldOwniSub); } bool CAAudioHardwareDevice::ISubOwnershipControlIsSettable() const { return PropertyIsSettable(0, kAudioDeviceSectionOutput, kAudioDevicePropertyDriverShouldOwniSub); } bool CAAudioHardwareDevice::GetISubOwnershipControlValue() const { UInt32 theValue = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDeviceSectionOutput, kAudioDevicePropertyDriverShouldOwniSub, theSize, &theValue); return theValue != 0; } void CAAudioHardwareDevice::SetISubOwnershipControlValue(bool inValue) { UInt32 theValue = (inValue ? 1 : 0); UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDeviceSectionOutput, kAudioDevicePropertyDriverShouldOwniSub, theSize, &theValue); } bool CAAudioHardwareDevice::HasSubMuteControl(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(inChannel, inSection, kAudioDevicePropertySubMute); } bool CAAudioHardwareDevice::SubMuteControlIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(inChannel, inSection, kAudioDevicePropertySubMute); } bool CAAudioHardwareDevice::GetSubMuteControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { UInt32 theValue = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(inChannel, inSection, kAudioDevicePropertySubMute, theSize, &theValue); return theValue != 0; } void CAAudioHardwareDevice::SetSubMuteControlValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, bool inValue) { UInt32 theValue = (inValue ? 1 : 0); UInt32 theSize = sizeof(UInt32); SetPropertyData(inChannel, inSection, kAudioDevicePropertySubMute, theSize, &theValue); } bool CAAudioHardwareDevice::HasSubVolumeControl(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return HasProperty(inChannel, inSection, kAudioDevicePropertySubVolumeScalar); } bool CAAudioHardwareDevice::SubVolumeControlIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { return PropertyIsSettable(inChannel, inSection, kAudioDevicePropertySubVolumeScalar); } Float32 CAAudioHardwareDevice::GetSubVolumeControlScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { Float32 theValue = 0.0; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeScalar, theSize, &theValue); return theValue; } Float32 CAAudioHardwareDevice::GetSubVolumeControlDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection) const { Float32 theValue = 0.0; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeDecibels, theSize, &theValue); return theValue; } void CAAudioHardwareDevice::SetSubVolumeControlScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) { UInt32 theSize = sizeof(Float32); SetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeScalar, theSize, &inValue); } void CAAudioHardwareDevice::SetSubVolumeControlDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) { UInt32 theSize = sizeof(Float32); SetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeDecibels, theSize, &inValue); } Float32 CAAudioHardwareDevice::GetSubVolumeControlScalarForDecibelValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) const { Float32 theValue = inValue; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeDecibelsToScalar, theSize, &theValue); return theValue; } Float32 CAAudioHardwareDevice::GetSubVolumeControlDecibelForScalarValue(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, Float32 inValue) const { Float32 theValue = inValue; UInt32 theSize = sizeof(Float32); GetPropertyData(inChannel, inSection, kAudioDevicePropertySubVolumeScalarToDecibels, theSize, &theValue); return theValue; } bool CAAudioHardwareDevice::HasProperty(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID) const { OSStatus theError = AudioDeviceGetPropertyInfo(mAudioDeviceID, inChannel, inSection, inPropertyID, NULL, NULL); return theError == 0; } bool CAAudioHardwareDevice::PropertyIsSettable(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID) const { Boolean isWritable = false; OSStatus theError = AudioDeviceGetPropertyInfo(mAudioDeviceID, inChannel, inSection, inPropertyID, NULL, &isWritable); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::PropertyIsSettable: got an error getting info about a property"); return isWritable != 0; } UInt32 CAAudioHardwareDevice::GetPropertyDataSize(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID) const { UInt32 theSize = 0; OSStatus theError = AudioDeviceGetPropertyInfo(mAudioDeviceID, inChannel, inSection, inPropertyID, &theSize, NULL); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::GetPropertyDataSize: got an error getting info about a property"); return theSize; } void CAAudioHardwareDevice::GetPropertyData(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID, UInt32& ioDataSize, void* outData) const { OSStatus theError = AudioDeviceGetProperty(mAudioDeviceID, inChannel, inSection, inPropertyID, &ioDataSize, outData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::GetPropertyData: got an error getting the value of a property"); } void CAAudioHardwareDevice::SetPropertyData(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID, UInt32 inDataSize, const void* inData, const AudioTimeStamp* inWhen) { OSStatus theError = AudioDeviceSetProperty(mAudioDeviceID, inWhen, inChannel, inSection, inPropertyID, inDataSize, inData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::SetPropertyData: got an error setting the value of a property"); } void CAAudioHardwareDevice::AddPropertyListener(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID, AudioDevicePropertyListenerProc inListenerProc, void* inClientData) { OSStatus theError = AudioDeviceAddPropertyListener(mAudioDeviceID, inChannel, inSection, inPropertyID, inListenerProc, inClientData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::AddPropertyListener: got an error adding a property listener"); } void CAAudioHardwareDevice::RemovePropertyListener(UInt32 inChannel, CAAudioHardwareDeviceSectionID inSection, AudioHardwarePropertyID inPropertyID, AudioDevicePropertyListenerProc inListenerProc) { OSStatus theError = AudioDeviceRemovePropertyListener(mAudioDeviceID, inChannel, inSection, inPropertyID, inListenerProc); ThrowIfError(theError, CAException(theError), "CAAudioHardwareDevice::RemovePropertyListener: got an error removing a property listener"); } void CAAudioHardwareDevice::GetNameForTransportType(UInt32 inTransportType, char* outName) { switch(inTransportType) { case 0: strcpy(outName, "Unknown"); break; case kIOAudioDeviceTransportTypeBuiltIn: strcpy(outName, "Built-In"); break; case kIOAudioDeviceTransportTypePCI: strcpy(outName, "PCI"); break; case kIOAudioDeviceTransportTypeUSB: strcpy(outName, "USB"); break; case kIOAudioDeviceTransportTypeFireWire: strcpy(outName, "FireWire"); break; case kIOAudioDeviceTransportTypeNetwork: strcpy(outName, "Network"); break; case kIOAudioDeviceTransportTypeWireless: strcpy(outName, "Wireless"); break; case kIOAudioDeviceTransportTypeOther: strcpy(outName, "Other"); break; default: { char* the4CC = (char*)&inTransportType; outName[0] = the4CC[0]; outName[1] = the4CC[1]; outName[2] = the4CC[2]; outName[3] = the4CC[3]; outName[4] = 0; } break; }; }