Float32 CCoreAudioUnit::GetCurrentVolume() { if (!m_Component) return 0.0f; Float32 volPct = 0.0f; OSStatus ret = AudioUnitGetParameter(m_Component, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &volPct); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetCurrentVolume: Unable to get AudioUnit volume. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return 0.0f; } return volPct; }
bool CCoreAudioDevice::GetPreferredChannelLayout(CoreAudioChannelList* pChannelMap) { if (!pChannelMap || !m_DeviceId) return false; UInt32 propertySize = 0; Boolean writable = false; OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false, kAudioDevicePropertyPreferredChannelLayout, &propertySize, &writable); if (ret) return false; // kAudioChannelLabel_Unknown = -1 (0xffffffff) // kAudioChannelLabel_Unused = 0 // kAudioChannelLabel_Left = 1 // kAudioChannelLabel_Right = 2 // ... void* pBuf = malloc(propertySize); AudioChannelLayout* pLayout = (AudioChannelLayout*)pBuf; ret = AudioDeviceGetProperty(m_DeviceId, 0, false, kAudioDevicePropertyPreferredChannelLayout, &propertySize, pBuf); if (ret) CLog::Log(LOGERROR, "CCoreAudioUnit::GetPreferredChannelLayout: Unable to retrieve preferred channel layout. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); else { if(pLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) { for (UInt32 i = 0; i < pLayout->mNumberChannelDescriptions; i++) { if (pLayout->mChannelDescriptions[i].mChannelLabel == kAudioChannelLabel_Unknown) pChannelMap->push_back(i + 1); // TODO: This is not the best way to handle unknown/unconfigured speaker layouts else pChannelMap->push_back(pLayout->mChannelDescriptions[i].mChannelLabel); // Will be one of kAudioChannelLabel_xxx } } else { // TODO: Determine if a method that uses a channel bitmap is also necessary free(pLayout); return false; } } free(pLayout); return (ret == noErr); }
bool CCoreAudioUnit::SetMaxFramesPerSlice(UInt32 maxFrames) { if (!m_Component) return false; OSStatus ret = AudioUnitSetProperty(m_Component, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(UInt32)); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetMaxFramesPerSlice: Unable to set AudioUnit max frames per slice. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
bool CCoreAudioUnit::GetInputChannelMap(CoreAudioChannelList* pChannelMap) { if (!m_Component) return false; UInt32 size = 0; Boolean writable = false; AudioUnitGetPropertyInfo(m_Component, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, &size, &writable); UInt32 channels = size/sizeof(SInt32); SInt32* pMap = new SInt32[channels]; OSStatus ret = AudioUnitGetProperty(m_Component, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, &size); if (ret) CLog::Log(LOGERROR, "CCoreAudioUnit::GetInputChannelMap: Unable to retrieve AudioUnit input channel map. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); else for (UInt32 i = 0; i < channels; i++) pChannelMap->push_back(pMap[i]); delete[] pMap; return (!ret); }
bool CCoreAudioUnit::Initialize() { if (!m_Component) return false; OSStatus ret = AudioUnitInitialize(m_Component); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::Initialize: Unable to Initialize AudioUnit. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } m_Initialized = true; return true; }
bool CCoreAudioUnit::SetRenderProc(AURenderCallback callback, void* pClientData) { if (!m_Component) return false; AURenderCallbackStruct callbackInfo; callbackInfo.inputProc = callback; // Function to be called each time the AudioUnit needs data callbackInfo.inputProcRefCon = pClientData; // Pointer to be returned in the callback proc OSStatus ret = AudioUnitSetProperty(m_Component, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct)); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetRenderProc: Unable to set AudioUnit render callback. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
void CCoreAudioDevice::Stop() { if (!m_DeviceId || !m_Started) return; OSStatus ret = AudioDeviceStop(m_DeviceId, m_IoProc); if (ret) CLog::Log(LOGERROR, "CCoreAudioDevice::Stop: Unable to stop device. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); m_Started = false; }
AudioDeviceID CCoreAudioHardware::FindAudioDevice(CStdString searchName) { if (!searchName.length()) return 0; UInt32 size = 0; AudioDeviceID deviceId = 0; OSStatus ret; if (searchName.Equals("Default Output Device")) { AudioDeviceID defaultDevice = GetDefaultOutputDevice(); CLog::Log(LOGDEBUG, "CCoreAudioHardware::FindAudioDevice: Returning default device [0x%04x].", defaultDevice); return defaultDevice; } CLog::Log(LOGDEBUG, "CCoreAudioHardware::FindAudioDevice: Searching for device - %s.", searchName.c_str()); // Obtain a list of all available audio devices AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); UInt32 deviceCount = size / sizeof(AudioDeviceID); AudioDeviceID* pDevices = new AudioDeviceID[deviceCount]; ret = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, pDevices); if (ret) { CLog::Log(LOGERROR, "CCoreAudioHardware::FindAudioDevice: Unable to retrieve the list of available devices. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); delete[] pDevices; return 0; } // Attempt to locate the requested device CStdString deviceName; for (UInt32 dev = 0; dev < deviceCount; dev++) { CCoreAudioDevice::GetName(deviceName, pDevices[dev]); UInt32 totalChannels = CCoreAudioDevice::GetTotalOutputChannels(pDevices[dev]); CLog::Log(LOGDEBUG, "CCoreAudioHardware::FindAudioDevice: Device[0x%04x] - Name: '%s', Total Ouput Channels: %u. ", pDevices[dev], deviceName.c_str(), totalChannels); if (searchName.Equals(deviceName)) deviceId = pDevices[dev]; if (deviceId) break; } delete[] pDevices; return deviceId; }
bool CCoreAudioHardware::GetAutoHogMode() { UInt32 val = 0; UInt32 size = sizeof(val); OSStatus ret = AudioHardwareGetProperty(kAudioHardwarePropertyHogModeIsAllowed, &size, &val); if (ret) { CLog::Log(LOGERROR, "CCoreAudioHardware::GetAutoHogMode: Unable to get auto 'hog' mode. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); return false; } return (val == 1); }
void CCoreAudioHardware::SetAutoHogMode(bool enable) { UInt32 val = enable ? 1 : 0; OSStatus ret = AudioHardwareSetProperty(kAudioHardwarePropertyHogModeIsAllowed, sizeof(val), &val); if (ret) CLog::Log(LOGERROR, "CCoreAudioHardware::SetAutoHogMode: Unable to set auto 'hog' mode. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); }
UInt32 CCoreAudioHardware::GetOutputDevices(CoreAudioDeviceList* pList) { if (!pList) return 0; // Obtain a list of all available audio devices UInt32 found = 0; UInt32 size = 0; AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); UInt32 deviceCount = size / sizeof(AudioDeviceID); AudioDeviceID* pDevices = new AudioDeviceID[deviceCount]; OSStatus ret = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, pDevices); if (ret) CLog::Log(LOGERROR, "CCoreAudioHardware::GetOutputDevices: Unable to retrieve the list of available devices. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); else { for (UInt32 dev = 0; dev < deviceCount; dev++) { if (CCoreAudioDevice::GetTotalOutputChannels(pDevices[dev]) == 0) continue; found++; pList->push_back(pDevices[dev]); } } delete[] pDevices; return found; }
AudioDeviceID CCoreAudioHardware::GetDefaultOutputDevice() { UInt32 size = sizeof(AudioDeviceID); static AudioDeviceID deviceId = 0; if (deviceId) return deviceId; OSStatus ret = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &deviceId); if (ret || !deviceId) // outputDevice is set to 0 if there is no audio device available, or if the default device is set to an encoded format { CLog::Log(LOGERROR, "CCoreAudioHardware::GetDefaultOutputDevice: Unable to identify default output device. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); return 0; } return deviceId; }
core_audio_sound* CCoreAudioSoundManager::LoadSoundFromFile(const CStdString& fileName) { FSRef fileRef; UInt32 size = 0; ExtAudioFileRef audioFile; OSStatus ret = FSPathMakeRef((const UInt8*) fileName.c_str(), &fileRef, false); ret = ExtAudioFileOpen(&fileRef, &audioFile); if (ret) { CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to open source file (%s). Error = 0x%08x (%4.4s)", fileName.c_str(), ret, CONVERT_OSSTATUS(ret)); return NULL; } core_audio_sound* pSound = new core_audio_sound; // Retrieve the format of the source file AudioStreamBasicDescription inputFormat; size = sizeof(inputFormat); ret = ExtAudioFileGetProperty(audioFile, kExtAudioFileProperty_FileDataFormat, &size, &inputFormat); if (ret) { CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to fetch source file format. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); delete pSound; return NULL; } // Set up format conversion. This is the format that will be produced by Read/Write calls. // Here we use the same format provided to the output AudioUnit ret = ExtAudioFileSetProperty(audioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &m_OutputFormat); if (ret) { CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to set conversion format. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); delete pSound; return NULL; } // Retrieve the file size (in terms of the file's sample-rate, not the output sample-rate) UInt64 totalFrames; size = sizeof(totalFrames); ret = ExtAudioFileGetProperty(audioFile, kExtAudioFileProperty_FileLengthFrames, &size, &totalFrames); if (ret) { CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to fetch source file size. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); delete pSound; return NULL; } // Calculate the total number of converted frames to be read totalFrames *= (float)m_OutputFormat.mSampleRate / (float)inputFormat.mSampleRate; // TODO: Verify the accuracy of this // Allocate AudioBuffers UInt32 channelCount = m_OutputFormat.mChannelsPerFrame; pSound->buffer_list = (AudioBufferList*)calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer) * (channelCount - kVariableLengthArray)); pSound->buffer_list->mNumberBuffers = channelCount; // One buffer per channel for deinterlaced pcm float* buffers = (float*)calloc(1, sizeof(float) * totalFrames * channelCount); for(int i = 0; i < channelCount; i++) { pSound->buffer_list->mBuffers[i].mNumberChannels = 1; // One channel per buffer for deinterlaced pcm pSound->buffer_list->mBuffers[i].mData = buffers + (totalFrames * i); pSound->buffer_list->mBuffers[i].mDataByteSize = totalFrames * sizeof(float); } // Read the entire file // TODO: Should we limit the total file length? UInt32 readFrames = totalFrames; ret = ExtAudioFileRead(audioFile, &readFrames, pSound->buffer_list); if (ret) { CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to read from file (%s). Error = 0x%08x (%4.4s)", fileName.c_str(), ret, CONVERT_OSSTATUS(ret)); delete pSound; return NULL; } pSound->total_frames = readFrames; // Store the actual number of frames read from the file. Rounding errors in calcuating the converted number of frames can truncate the read. // TODO: What do we do with files with more than 2 channels. Currently we just copy the first two and dump the rest. if (inputFormat.mChannelsPerFrame == 1) // Copy Left channel into Right if the source file is Mono memcpy(pSound->buffer_list->mBuffers[1].mData, pSound->buffer_list->mBuffers[0].mData, pSound->buffer_list->mBuffers[0].mDataByteSize); ret = ExtAudioFileDispose(audioFile); // Close the file. We have what we need. Not a lot to be done on failure. if (ret) CLog::Log(LOGERROR, "CCoreAudioSoundManager::LoadSoundFromFile: Unable to close file (%s). Error = 0x%08x (%4.4s)", fileName.c_str(), ret, CONVERT_OSSTATUS(ret)); pSound->ref_count = 1; // The caller holds a reference to this object now pSound->play_count = 0; return pSound; }
bool CCoreAudioDevice::SetNominalSampleRate(Float64 sampleRate) { if (!m_DeviceId || sampleRate == 0.0f) return false; Float64 currentRate = GetNominalSampleRate(); if (currentRate == sampleRate) return true; //No need to change UInt32 size = sizeof(Float64); OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertyNominalSampleRate, size, &sampleRate); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetNominalSampleRate: Unable to set current device sample rate to %0.0f. Error = 0x%08x (%4.4s)", (float)sampleRate, ret, CONVERT_OSSTATUS(ret)); return false; } CLog::Log(LOGDEBUG, "CCoreAudioUnit::SetNominalSampleRate: Changed device sample rate from %0.0f to %0.0f.", (float)currentRate, (float)sampleRate); if (m_SampleRateRestore == 0.0f) m_SampleRateRestore = currentRate; return true; }
bool CCoreAudioDevice::AddIOProc(AudioDeviceIOProc ioProc, void* pCallbackData) { if (!m_DeviceId || m_IoProc) // Only one IOProc at a time return false; OSStatus ret = AudioDeviceAddIOProc(m_DeviceId, ioProc, pCallbackData); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::Stop: Unable to add IOProc. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); return false; } m_IoProc = ioProc; CLog::Log(LOGDEBUG, "CCoreAudioDevice::AddIOProc: IOProc set for device 0x%04x", m_DeviceId); return true; }
bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc) { if (!pDesc || !m_StreamId) return false; if (!m_OriginalPhysicalFormat.mFormatID) { if (!GetPhysicalFormat(m_StreamId, &m_OriginalPhysicalFormat)) // Store the original format (as we found it) so that it can be restored later { CLog::Log(LOGERROR, "CCoreAudioStream::SetPhysicalFormat: Unable to retrieve current physical format for stream 0x%04x.", m_StreamId); return false; } } OSStatus ret = AudioStreamSetProperty(m_StreamId, NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), pDesc); if (ret) { CLog::Log(LOGERROR, "CCoreAudioStream::SetVirtualFormat: Unable to set physical format for stream 0x%04x. Error = 0x%08x (%4.4s)", m_StreamId, ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
void CCoreAudioDevice::RemoveIOProc() { if (!m_DeviceId || !m_IoProc) return; Stop(); OSStatus ret = AudioDeviceRemoveIOProc(m_DeviceId, m_IoProc); if (ret) CLog::Log(LOGERROR, "CCoreAudioDevice::RemoveIOProc: Unable to remove IOProc. Error = 0x%08x (%4.4s).", ret, CONVERT_OSSTATUS(ret)); else CLog::Log(LOGDEBUG, "CCoreAudioDevice::AddIOProc: IOProc removed for device 0x%04x", m_DeviceId); m_IoProc = NULL; // Clear the reference no matter what }
bool CCoreAudioUnit::Open(ComponentDescription desc) { if (m_Component) Close(); // Find the required Component Component outputComp = FindNextComponent(NULL, &desc); if (outputComp == NULL) // Unable to find the AudioUnit we requested { CLog::Log(LOGERROR, "CCoreAudioUnit::Open: Unable to locate AudioUnit Component."); return false; } // Create an instance of the AudioUnit Component OSStatus ret = OpenAComponent(outputComp, &m_Component); if (ret) // Unable to open AudioUnit { CLog::Log(LOGERROR, "CCoreAudioUnit::Open: Unable to open AudioUnit Component. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
const char* CCoreAudioDevice::GetName(CStdString& name, const AudioDeviceID &id) { UInt32 size = 0; AudioDeviceGetPropertyInfo(id,0, false, kAudioDevicePropertyDeviceName, &size, NULL); // TODO: Change to kAudioObjectPropertyObjectName OSStatus ret = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name.GetBufferSetLength(size)); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::GetName: Unable to get device name - id: 0x%04x Error = 0x%08x (%4.4s)", id, ret, CONVERT_OSSTATUS(ret)); return NULL; } return name.c_str(); }
bool CCoreAudioUnit::SetOutputFormat(AudioStreamBasicDescription* pDesc) { if (!m_Component || !pDesc) return false; OSStatus ret = AudioUnitSetProperty(m_Component, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, pDesc, sizeof(AudioStreamBasicDescription)); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetInputFormat: Unable to set AudioUnit output format. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
UInt32 CCoreAudioDevice::GetTotalOutputChannels(const AudioDeviceID &id) { UInt32 channels = 0; UInt32 size = 0; AudioDeviceGetPropertyInfo(id, 0, false, kAudioDevicePropertyStreamConfiguration, &size, NULL); AudioBufferList* pList = (AudioBufferList*)malloc(size); OSStatus ret = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyStreamConfiguration, &size, pList); if (!ret) for(UInt32 buffer = 0; buffer < pList->mNumberBuffers; ++buffer) channels += pList->mBuffers[buffer].mNumberChannels; else CLog::Log(LOGERROR, "CCoreAudioDevice::GetTotalOutputChannels: Unable to get total device output channels - id: 0x%04x Error = 0x%08x (%4.4s)", id, ret, CONVERT_OSSTATUS(ret)); CLog::Log(LOGDEBUG, "CCoreAudioDevice::GetTotalOutputChannels: Found %u channels in %u buffers", channels, pList->mNumberBuffers); free(pList); return channels; }
UInt32 CCoreAudioUnit::GetBufferFrameSize() { if (!m_Component) return 0; UInt32 size = sizeof(UInt32); UInt32 bufferSize = 0; OSStatus ret = AudioUnitGetProperty(m_Component, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Input, 0, &bufferSize, &size); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: Unable to get current device's buffer size. ErrCode = Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return 0; } return bufferSize; }
bool CCoreAudioDevice::SetHogStatus(bool hog) { if (!m_DeviceId) return false; pid_t holder = GetHogStatus(); pid_t me = getpid(); if (hog) { if (holder != me) { CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Setting 'hog' status on device 0x%04x", m_DeviceId); OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertyHogMode, sizeof(me), &me); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: Unable to set 'hog' status. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } pid_t holder = GetHogStatus(); if (holder != getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: Unable to set 'hog' status. another process (%x) has it.", holder); return false; } CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Successfully set 'hog' status on device 0x%04x", m_DeviceId); } } else { if (holder == me) // Currently Set { CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Releasing 'hog' status on device 0x%04x", m_DeviceId); pid_t hogPid = -1; OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertyHogMode, sizeof(hogPid), &hogPid); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: Unable to release 'hog' status. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } pid_t holder = GetHogStatus(); if (holder == getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: failed to release. still hogging!"); return false; } } } return true; }
bool CCoreAudioUnit::SetCurrentDevice(AudioDeviceID deviceId) { if (!m_Component) return false; OSStatus ret = AudioUnitSetProperty(m_Component, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentDevice: Unable to set current device. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
bool CCoreAudioDevice::SetMixingSupport(bool mix) { if (!m_DeviceId) return false; int restore = -1; if (m_MixerRestore == -1) // This is our first change to this setting. Store the original setting for restore restore = (GetMixingSupport() ? 1 : 0); UInt32 mixEnable = mix ? 1 : 0; CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetMixingSupport: %sabling mixing for device 0x%04x",mix ? "En" : "Dis", m_DeviceId); OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertySupportsMixing, sizeof(mixEnable), &mixEnable); if (ret) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetMixingSupport: Unable to set MixingSupport to %s. Error = 0x%08x (%4.4s)", mix ? "'On'" : "'Off'", ret, CONVERT_OSSTATUS(ret)); return false; } if (m_MixerRestore == -1) m_MixerRestore = restore; return true; }
bool CCoreAudioUnit::SetInputChannelMap(CoreAudioChannelList* pChannelMap) { if (!m_Component || !pChannelMap) return false; UInt32 channels = pChannelMap->size(); UInt32 size = sizeof(SInt32) * channels; SInt32* pMap = new SInt32[channels]; for (UInt32 i = 0; i < channels; i++) pMap[i] = (*pChannelMap)[i]; OSStatus ret = AudioUnitSetProperty(m_Component, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, size); if (ret) CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: Unable to get current device's buffer size. ErrCode = Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); delete[] pMap; return (!ret); }
Float64 CCoreAudioDevice::GetNominalSampleRate() { if (!m_DeviceId) return 0.0f; Float64 sampleRate = 0.0f; UInt32 size = sizeof(Float64); OSStatus ret = AudioDeviceGetProperty(m_DeviceId, 0, false, kAudioDevicePropertyNominalSampleRate, &size, &sampleRate); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::GetNominalSampleRate: Unable to retrieve current device sample rate. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return 0.0f; } return sampleRate; }
bool CCoreAudioUnit::SetCurrentVolume(Float32 vol) { if (!m_Component) return false; OSStatus ret = AudioUnitSetParameter(m_Component, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, vol, 0); if (ret) { CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentVolume: Unable to set AudioUnit volume. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } return true; }
bool CCoreAudioDevice::SetHogStatus(bool hog) { // According to Jeff Moore (Core Audio, Apple), Setting kAudioDevicePropertyHogMode // is a toggle and the only way to tell if you do get hog mode is to compare // the returned pid against getpid, if the match, you have hog mode, if not you don't. if (!m_DeviceId) return false; if (hog) { if (m_Hog == -1) // Not already set { CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Setting 'hog' status on device 0x%04x", m_DeviceId); OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertyHogMode, sizeof(m_Hog), &m_Hog); if (ret || m_Hog != getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: Unable to set 'hog' status. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Successfully set 'hog' status on device 0x%04x", m_DeviceId); } } else { if (m_Hog > -1) // Currently Set { CLog::Log(LOGDEBUG, "CCoreAudioDevice::SetHogStatus: Releasing 'hog' status on device 0x%04x", m_DeviceId); pid_t hogPid = -1; OSStatus ret = AudioDeviceSetProperty(m_DeviceId, NULL, 0, false, kAudioDevicePropertyHogMode, sizeof(hogPid), &hogPid); if (ret || hogPid == getpid()) { CLog::Log(LOGERROR, "CCoreAudioDevice::SetHogStatus: Unable to release 'hog' status. Error = 0x%08x (%4.4s)", ret, CONVERT_OSSTATUS(ret)); return false; } m_Hog = hogPid; // Reset internal state } } return true; }