/*============================================================================= CAAudioHardwareStream.cpp $Log: CAAudioHardwareStream.cpp,v $ Revision 1.3 2004/02/24 02:27:06 jcm10 make it compile without a prefix header Revision 1.2 2003/06/18 22:09:20 jcm10 add IsControlEnabled methods Revision 1.1 2003/05/23 19:06:50 jcm10 first checked in Revision 1.3 2003/05/06 18:42:40 jcm10 add support for displaying/manipulating the IOProc format Revision 1.2 2003/01/30 22:31:31 jcm10 make the Streams tab of the Device window work Revision 1.1 2003/01/24 03:24:57 jcm10 first checked in Revision 0.0 Wed Jan 15 2003 12:52:54 US/Pacific moorf Created $NoKeywords: $ =============================================================================*/ //============================================================================= // Includes //============================================================================= // Self Include #include "CAAudioHardwareStream.h" // PublicUtility Includes #include "CAAutoDisposer.h" #include "CADebugMacros.h" #include "CAException.h" // System Includes #include // Standard Library Includes #include //============================================================================= // CAAudioHardwareStream //============================================================================= CAAudioHardwareStream::CAAudioHardwareStream(AudioStreamID inAudioStreamID) : mAudioStreamID(inAudioStreamID) { } CAAudioHardwareStream::~CAAudioHardwareStream() { } CFStringRef CAAudioHardwareStream::CopyName() const { CFStringRef theAnswer = NULL; UInt32 theSize = sizeof(CFStringRef); GetPropertyData(0, kAudioDevicePropertyDeviceNameCFString, theSize, &theAnswer); return theAnswer; } AudioDeviceID CAAudioHardwareStream::GetOwningDevice() const { AudioDeviceID theAnswer = 0; UInt32 theSize = sizeof(AudioDeviceID); GetPropertyData(0, kAudioStreamPropertyOwningDevice, theSize, &theAnswer); return theAnswer; } CAAudioHardwareDeviceSectionID CAAudioHardwareStream::GetSection() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioStreamPropertyDirection, theSize, &theAnswer); return (theAnswer == 0) ? kAudioDeviceSectionOutput : kAudioDeviceSectionInput; } UInt32 CAAudioHardwareStream::GetTerminalType() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioStreamPropertyTerminalType, theSize, &theAnswer); return theAnswer; } UInt32 CAAudioHardwareStream::GetStartingDeviceChannel() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioStreamPropertyStartingChannel, theSize, &theAnswer); return theAnswer; } bool CAAudioHardwareStream::HasIsConnectedStatus() const { return HasProperty(0, kAudioDevicePropertyJackIsConnected); } bool CAAudioHardwareStream::GetIsConnectedStatus() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDevicePropertyJackIsConnected, theSize, &theAnswer); return theAnswer != 0; } bool CAAudioHardwareStream::HasDataSourceControl() const { return HasProperty(0, kAudioDevicePropertyDataSource); } bool CAAudioHardwareStream::DataSourceControlIsSettable() const { return PropertyIsSettable(0, kAudioDevicePropertyDataSource); } UInt32 CAAudioHardwareStream::GetCurrentDataSourceID() const { UInt32 theAnswer = 0; UInt32 theSize = sizeof(UInt32); GetPropertyData(0, kAudioDevicePropertyDataSource, theSize, &theAnswer); return theAnswer; } void CAAudioHardwareStream::SetCurrentDataSourceByID(UInt32 inID) { UInt32 theSize = sizeof(UInt32); SetPropertyData(0, kAudioDevicePropertyDataSource, theSize, &inID); } UInt32 CAAudioHardwareStream::GetNumberAvailableDataSources() const { UInt32 theAnswer = 0; if(HasDataSourceControl()) { UInt32 theSize = GetPropertyDataSize(0, kAudioDevicePropertyDataSources); theAnswer = theSize / sizeof(UInt32); } return theAnswer; } UInt32 CAAudioHardwareStream::GetAvailableDataSourceByIndex(UInt32 inIndex) const { AudioStreamID theAnswer = 0; UInt32 theNumberSources = GetNumberAvailableDataSources(); if((theNumberSources > 0) && (inIndex < theNumberSources)) { CAAutoArrayDelete theSourceList(theNumberSources); GetAvailableDataSources(theNumberSources, theSourceList); theAnswer = theSourceList[inIndex]; } return theAnswer; } void CAAudioHardwareStream::GetAvailableDataSources(UInt32& ioNumberSources, UInt32* outSources) const { UInt32 theNumberSources = std::min(GetNumberAvailableDataSources(), ioNumberSources); UInt32 theSize = theNumberSources * sizeof(UInt32); GetPropertyData(0, kAudioDevicePropertyDataSources, theSize, outSources); ioNumberSources = theSize / sizeof(UInt32); UInt32* theFirstItem = &(outSources[0]); UInt32* theLastItem = theFirstItem + ioNumberSources; std::sort(theFirstItem, theLastItem); } CFStringRef CAAudioHardwareStream::CopyDataSourceNameForID(UInt32 inID) const { CFStringRef theAnswer = NULL; AudioValueTranslation theTranslation = { &inID, sizeof(UInt32), &theAnswer, sizeof(CFStringRef) }; UInt32 theSize = sizeof(AudioValueTranslation); GetPropertyData(0, kAudioDevicePropertyDataSourceNameForIDCFString, theSize, &theTranslation); return theAnswer; } void CAAudioHardwareStream::GetCurrentIOProcFormat(AudioStreamBasicDescription& outFormat) const { memset(&outFormat, 0, sizeof(AudioStreamBasicDescription)); UInt32 theSize = sizeof(AudioStreamBasicDescription); GetPropertyData(0, kAudioDevicePropertyStreamFormat, theSize, &outFormat); } void CAAudioHardwareStream::SetCurrentIOProcFormat(const AudioStreamBasicDescription& inFormat) { UInt32 theSize = sizeof(AudioStreamBasicDescription); SetPropertyData(0, kAudioDevicePropertyStreamFormat, theSize, &inFormat); } UInt32 CAAudioHardwareStream::GetNumberAvailableIOProcFormats() const { UInt32 theAnswer = GetPropertyDataSize(0, kAudioDevicePropertyStreamFormats); theAnswer /= sizeof(AudioStreamBasicDescription); return theAnswer; } void CAAudioHardwareStream::GetAvailableIOProcFormats(UInt32& ioNumberFormats, AudioStreamBasicDescription* outFormats) const { UInt32 theSize = ioNumberFormats * sizeof(AudioStreamBasicDescription); GetPropertyData(0, kAudioDevicePropertyStreamFormats, theSize, outFormats); ioNumberFormats = theSize / sizeof(AudioStreamBasicDescription); } void CAAudioHardwareStream::GetAvailableIOProcFormatByIndex(UInt32 inIndex, AudioStreamBasicDescription& outFormat) const { UInt32 theNumberFormats = GetNumberAvailableIOProcFormats(); ThrowIf(inIndex >= theNumberFormats, CAException(kAudioHardwareIllegalOperationError), "CAAudioHardwareStream::GetAvailableIOProcFormatByIndex: index out of range"); CAAutoArrayDelete theFormats(theNumberFormats); GetAvailableIOProcFormats(theNumberFormats, theFormats); outFormat = theFormats[inIndex]; } void CAAudioHardwareStream::GetCurrentPhysicalFormat(AudioStreamBasicDescription& outFormat) const { memset(&outFormat, 0, sizeof(AudioStreamBasicDescription)); UInt32 theSize = sizeof(AudioStreamBasicDescription); GetPropertyData(0, kAudioStreamPropertyPhysicalFormat, theSize, &outFormat); } void CAAudioHardwareStream::SetCurrentPhysicalFormat(const AudioStreamBasicDescription& inFormat) { UInt32 theSize = sizeof(AudioStreamBasicDescription); SetPropertyData(0, kAudioStreamPropertyPhysicalFormat, theSize, &inFormat); } UInt32 CAAudioHardwareStream::GetNumberAvailablePhysicalFormats() const { UInt32 theAnswer = GetPropertyDataSize(0, kAudioStreamPropertyPhysicalFormats); theAnswer /= sizeof(AudioStreamBasicDescription); return theAnswer; } void CAAudioHardwareStream::GetAvailablePhysicalFormats(UInt32& ioNumberFormats, AudioStreamBasicDescription* outFormats) const { UInt32 theSize = ioNumberFormats * sizeof(AudioStreamBasicDescription); GetPropertyData(0, kAudioStreamPropertyPhysicalFormats, theSize, outFormats); ioNumberFormats = theSize / sizeof(AudioStreamBasicDescription); } void CAAudioHardwareStream::GetAvailablePhysicalFormatByIndex(UInt32 inIndex, AudioStreamBasicDescription& outFormat) const { UInt32 theNumberFormats = GetNumberAvailablePhysicalFormats(); ThrowIf(inIndex >= theNumberFormats, CAException(kAudioHardwareIllegalOperationError), "CAAudioHardwareStream::GetAvailablePhysicalFormatByIndex: index out of range"); CAAutoArrayDelete theFormats(theNumberFormats); GetAvailablePhysicalFormats(theNumberFormats, theFormats); outFormat = theFormats[inIndex]; } bool CAAudioHardwareStream::HasProperty(UInt32 inChannel, AudioHardwarePropertyID inPropertyID) const { OSStatus theError = AudioStreamGetPropertyInfo(GetAudioStreamID(), inChannel, inPropertyID, NULL, NULL); return theError == 0; } bool CAAudioHardwareStream::PropertyIsSettable(UInt32 inChannel, AudioHardwarePropertyID inPropertyID) const { Boolean isWritable = false; OSStatus theError = AudioStreamGetPropertyInfo(GetAudioStreamID(), inChannel, inPropertyID, NULL, &isWritable); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::PropertyIsSettable: got an error getting info about a property"); return isWritable != 0; } UInt32 CAAudioHardwareStream::GetPropertyDataSize(UInt32 inChannel, AudioHardwarePropertyID inPropertyID) const { UInt32 theSize = 0; OSStatus theError = AudioStreamGetPropertyInfo(GetAudioStreamID(), inChannel, inPropertyID, &theSize, NULL); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::GetPropertyDataSize: got an error getting info about a property"); return theSize; } void CAAudioHardwareStream::GetPropertyData(UInt32 inChannel, AudioHardwarePropertyID inPropertyID, UInt32& ioDataSize, void* outData) const { OSStatus theError = AudioStreamGetProperty(GetAudioStreamID(), inChannel, inPropertyID, &ioDataSize, outData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::GetPropertyData: got an error getting the value of a property"); } void CAAudioHardwareStream::SetPropertyData(UInt32 inChannel, AudioHardwarePropertyID inPropertyID, UInt32 inDataSize, const void* inData, const AudioTimeStamp* inWhen) { OSStatus theError = AudioStreamSetProperty(GetAudioStreamID(), inWhen, inChannel, inPropertyID, inDataSize, inData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::SetPropertyData: got an error setting the value of a property"); } void CAAudioHardwareStream::AddPropertyListener(UInt32 inChannel, AudioHardwarePropertyID inPropertyID, AudioStreamPropertyListenerProc inListenerProc, void* inClientData) { OSStatus theError = AudioStreamAddPropertyListener(GetAudioStreamID(), inChannel, inPropertyID, inListenerProc, inClientData); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::AddPropertyListener: got an error adding a property listener"); } void CAAudioHardwareStream::RemovePropertyListener(UInt32 inChannel, AudioHardwarePropertyID inPropertyID, AudioStreamPropertyListenerProc inListenerProc) { OSStatus theError = AudioStreamRemovePropertyListener(GetAudioStreamID(), inChannel, inPropertyID, inListenerProc); ThrowIfError(theError, CAException(theError), "CAAudioHardwareStream::RemovePropertyListener: got an error removing a property listener"); } void CAAudioHardwareStream::GetNameForTerminalType(UInt32 inTerminalType, char* outName) { switch(inTerminalType) { // types that go nowhere case OUTPUT_NULL: strcpy(outName, "Null Output"); break; case INPUT_NULL: strcpy(outName, "Null Input"); break; // Input terminal types case INPUT_UNDEFINED: strcpy(outName, "Undefined Input"); break; case INPUT_MICROPHONE: strcpy(outName, "Microphone"); break; case INPUT_DESKTOP_MICROPHONE: strcpy(outName, "Desktop Microphone"); break; case INPUT_PERSONAL_MICROPHONE: strcpy(outName, "Personal Microphone"); break; case INPUT_OMNIDIRECTIONAL_MICROPHONE: strcpy(outName, "Omnidirectional Microphone"); break; case INPUT_MICROPHONE_ARRAY: strcpy(outName, "Microphone Array"); break; case INPUT_PROCESSING_MICROPHONE_ARRAY: strcpy(outName, "Processing Microphone Array"); break; case INPUT_MODEM_AUDIO: strcpy(outName, "Modem"); break; // Output terminal types case OUTPUT_UNDEFINED: strcpy(outName, "Undefined Output"); break; case OUTPUT_SPEAKER: strcpy(outName, "Speaker"); break; case OUTPUT_HEADPHONES: strcpy(outName, "Headphones"); break; case OUTPUT_HEAD_MOUNTED_DISPLAY_AUDIO: strcpy(outName, "Head-Monted Display"); break; case OUTPUT_DESKTOP_SPEAKER: strcpy(outName, "Desktop Speaker"); break; case OUTPUT_ROOM_SPEAKER: strcpy(outName, "Room Speaker"); break; case OUTPUT_COMMUNICATION_SPEAKER: strcpy(outName, "Communication Speaker"); break; case OUTPUT_LOW_FREQUENCY_EFFECTS_SPEAKER: strcpy(outName, "LFE Speaker"); break; // Bi-directional terminal types case BIDIRECTIONAL_UNDEFINED: strcpy(outName, "Undefined Bidirectional"); break; case BIDIRECTIONAL_HANDSET: strcpy(outName, "Handset"); break; case BIDIRECTIONAL_HEADSET: strcpy(outName, "Headset"); break; case BIDIRECTIONAL_SPEAKERPHONE_NO_ECHO_REDX: strcpy(outName, "Speakerphone w/o Echo Reduction"); break; case BIDIRECTIONAL_ECHO_SUPPRESSING_SPEAKERPHONE: strcpy(outName, "Speakerphone w/ Echo Suppression"); break; case BIDIRECTIONAL_ECHO_CANCELING_SPEAKERPHONE: strcpy(outName, "Speakerphone w/ Echo Cacellation"); break; // Telephony terminal types case TELEPHONY_UNDEFINED: strcpy(outName, "Undefined telephony"); break; case TELEPHONY_PHONE_LINE: strcpy(outName, "Telephone Line"); break; case TELEPHONY_TELEPHONE: strcpy(outName, "Telephone"); break; case TELEPHONY_DOWN_LINE_PHONE: strcpy(outName, "Down Line Telephone"); break; // External terminal types case EXTERNAL_UNDEFINED: strcpy(outName, "Undefined External"); break; case EXTERNAL_ANALOG_CONNECTOR: strcpy(outName, "Analog"); break; case EXTERNAL_DIGITAL_AUDIO_INTERFACE: strcpy(outName, "Digital Interface"); break; case EXTERNAL_LINE_CONNECTOR: strcpy(outName, "Line"); break; case EXTERNAL_LEGACY_AUDIO_CONNECTOR: strcpy(outName, "Legacy"); break; case EXTERNAL_SPDIF_INTERFACE: strcpy(outName, "SPDIF"); break; case EXTERNAL_1394_DA_STREAM: strcpy(outName, "1394 Digital Audio"); break; case EXTERNAL_1394_DV_STREAM_SOUNDTRACK: strcpy(outName, "1394 Digital Video"); break; // Embedded terminal types case EMBEDDED_UNDEFINED: strcpy(outName, "Undefined Embedded"); break; case EMBEDDED_LEVEL_CALIBRATION_NOISE_SOURCE: strcpy(outName, "Level Calibration Noise Source"); break; case EMBEDDED_EQUALIZATION_NOISE: strcpy(outName, "Equalization Noise"); break; case EMBEDDED_CD_PLAYER: strcpy(outName, "CD Player"); break; case EMBEDDED_DAT: strcpy(outName, "DAT"); break; case EMBEDDED_DCC: strcpy(outName, "DCC"); break; case EMBEDDED_MINIDISK: strcpy(outName, "Minidisk"); break; case EMBEDDED_ANALOG_TAPE: strcpy(outName, "Analog Tape"); break; case EMBEDDED_PHONOGRAPH: strcpy(outName, "Phonograph"); break; case EMBEDDED_VCR_AUDIO: strcpy(outName, "VCR"); break; case EMBEDDED_VIDEO_DISC_AUDIO: strcpy(outName, "Video Disc"); break; case EMBEDDED_DVD_AUDIO: strcpy(outName, "DVD"); break; case EMBEDDED_TV_TUNER_AUDIO: strcpy(outName, "TV Tuner"); break; case EMBEDDED_SATELLITE_RECEIVER_AUDIO: strcpy(outName, "Satellite Receiver"); break; case EMBEDDED_CABLE_TUNER_AUDIO: strcpy(outName, "Cable Tuner"); break; case EMBEDDED_DSS_AUDIO: strcpy(outName, "DSS"); break; case EMBEDDED_RADIO_RECEIVER: strcpy(outName, "Radio Receiver"); break; case EMBEDDED_RADIO_TRANSMITTER: strcpy(outName, "Radio Transmitter"); break; case EMBEDDED_MULTITRACK_RECORDER: strcpy(outName, "Mutitrack Recorder"); break; case EMBEDDED_SYNTHESIZER: strcpy(outName, "Synthesizer"); break; // Processing terminal types case PROCESSOR_UNDEFINED: strcpy(outName, "Undefined Processor"); break; case PROCESSOR_GENERAL: strcpy(outName, "General Processor"); break; default: sprintf(outName, "0x%X", (unsigned int)inTerminalType); break; }; }