bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc) { if (!pDesc || !m_StreamId) return false; std::string formatString; if (!m_OriginalPhysicalFormat.mFormatID) { // Store the original format (as we found it) so that it can be restored later if (!GetPhysicalFormat(&m_OriginalPhysicalFormat)) { CLog::Log(LOGERROR, "CCoreAudioStream::SetPhysicalFormat: " "Unable to retrieve current physical format for stream 0x%04x.", (uint)m_StreamId); return false; } } m_physical_format_event.Reset(); OSStatus ret = AudioStreamSetProperty(m_StreamId, NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), pDesc); if (ret) { CLog::Log(LOGERROR, "CCoreAudioStream::SetPhysicalFormat: " "Unable to set physical format for stream 0x%04x. Error = %s", (uint)m_StreamId, GetError(ret).c_str()); return false; } // The AudioStreamSetProperty is not only asynchronious, // it is also not Atomic, in its behaviour. // Therefore we check 5 times before we really give up. // FIXME: failing isn't actually implemented yet. for(int i = 0; i < 10; ++i) { AudioStreamBasicDescription checkPhysicalFormat; if (!GetPhysicalFormat(&checkPhysicalFormat)) { CLog::Log(LOGERROR, "CCoreAudioStream::SetPhysicalFormat: " "Unable to retrieve current physical format for stream 0x%04x.", (uint)m_StreamId); return false; } if (checkPhysicalFormat.mSampleRate == pDesc->mSampleRate && checkPhysicalFormat.mFormatID == pDesc->mFormatID && checkPhysicalFormat.mFramesPerPacket == pDesc->mFramesPerPacket) { // The right format is now active. CLog::Log(LOGDEBUG, "CCoreAudioStream::SetPhysicalFormat: " "Physical format for stream 0x%04x. now active (%s)", (uint)m_StreamId, StreamDescriptionToString(checkPhysicalFormat, formatString)); break; } m_physical_format_event.WaitMSec(100); } return true; }
/***************************************************************************** * AudioStreamChangeFormat: Change i_stream_id to change_format *****************************************************************************/ int CoreAudioAUHAL::AudioStreamChangeFormat(CoreAudioDeviceParameters *deviceParameters, AudioStreamID i_stream_id, AudioStreamBasicDescription change_format) { OSStatus err = noErr; UInt32 i_param_size = 0; int i; CLog::Log(LOGINFO, STREAM_FORMAT_MSG( "setting stream format: ", change_format )); CSingleLock lock(m_cs); // acquire lock /* change the format */ err = AudioStreamSetProperty( i_stream_id, 0, 0, kAudioStreamPropertyPhysicalFormat, sizeof( AudioStreamBasicDescription ), &change_format ); if( err != noErr ) { CLog::Log(LOGERROR, "could not set the stream format: [%4.4s]", (char *)&err ); return false; } /* The AudioStreamSetProperty is not only asynchronious (requiring the locks) * it is also not atomic in its behaviour. * Therefore we check 5 times before we really give up.*/ for( i = 0; i < 5; i++ ) { AudioStreamBasicDescription actual_format; usleep(20); i_param_size = sizeof( AudioStreamBasicDescription ); err = AudioStreamGetProperty( i_stream_id, 0, kAudioStreamPropertyPhysicalFormat, &i_param_size, &actual_format ); CLog::Log(LOGDEBUG, STREAM_FORMAT_MSG( "actual format in use: ", actual_format ) ); if( actual_format.mSampleRate == change_format.mSampleRate && actual_format.mFormatID == change_format.mFormatID && actual_format.mFramesPerPacket == change_format.mFramesPerPacket ) { /* The right format is now active */ break; } /* We need to check again */ } 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 CCoreAudioHardware::ResetStream(AudioStreamID stream) { // Find the streams current physical format AudioStreamBasicDescription currentFormat; UInt32 paramSize = sizeof(currentFormat); AudioStreamGetProperty(stream, 0, kAudioStreamPropertyPhysicalFormat, ¶mSize, ¤tFormat); // If it's currently AC-3/SPDIF then reset it to some mixable format if (currentFormat.mFormatID == 'IAC3' || currentFormat.mFormatID == kAudioFormat60958AC3) { AudioStreamBasicDescription *formats = CCoreAudioHardware::FormatsList(stream); bool streamReset = false; if (!formats) return; for (int i = 0; !streamReset && formats[i].mFormatID != 0; i++) { if (formats[i].mFormatID == kAudioFormatLinearPCM) { OSStatus ret = AudioStreamSetProperty(stream, NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(formats[i]), &(formats[i])); if (ret != noErr) { CLog::Log(LOGDEBUG, "CCoreAudioHardware::ResetStream: " "Unable to retrieve the list of available devices. Error = %s", GetError(ret).c_str()); continue; } else { streamReset = true; Sleep(10); } } } free(formats); } }
void PlexAudioDevice::reset() { OSStatus err = noErr; UInt32 paramSize = 0; AudioStreamBasicDescription deviceFormat; // Set up the basic default format. deviceFormat.mSampleRate = 48000.0; deviceFormat.mFormatID = kAudioFormatLinearPCM; deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; deviceFormat.mBitsPerChannel = 16; deviceFormat.mChannelsPerFrame = 2; deviceFormat.mFramesPerPacket = 1; deviceFormat.mBytesPerFrame = 4; deviceFormat.mBytesPerPacket = 4; deviceFormat.mReserved = 0; // Retrieve all the output streams. SAFELY(AudioDeviceGetPropertyInfo(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, NULL)); if (err == noErr) { int numStreams = paramSize / sizeof(AudioStreamID); AudioStreamID* pStreams = (AudioStreamID *)malloc(paramSize); SAFELY(AudioDeviceGetProperty(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, pStreams)); if (err == noErr) { for (int i=0; i<numStreams; i++) { // Change the format. SAFELY(AudioStreamSetProperty(pStreams[i], 0, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), &deviceFormat)); } } free(pStreams); } }
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"); }