diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/3rdparty/phonon/qt7/audionode.mm | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/3rdparty/phonon/qt7/audionode.mm')
-rw-r--r-- | src/3rdparty/phonon/qt7/audionode.mm | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/qt7/audionode.mm b/src/3rdparty/phonon/qt7/audionode.mm new file mode 100644 index 0000000..cb9e82f --- /dev/null +++ b/src/3rdparty/phonon/qt7/audionode.mm @@ -0,0 +1,240 @@ +/* This file is part of the KDE project. + + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + + This library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2.1 or 3 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "audionode.h" +#include "audiograph.h" +#include "audioconnection.h" +#include "medianode.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace QT7 +{ + +AudioNode::AudioNode(int maxInputBusses, int maxOutputBusses) +{ + m_auNode = 0; + m_audioUnit = 0; + m_audioGraph = 0; + m_maxInputBusses = maxInputBusses; + m_maxOutputBusses = maxOutputBusses; + m_lastConnectionIn = 0; +} + +AudioNode::~AudioNode() +{ + setGraph(0); +} + +void AudioNode::setGraph(AudioGraph *audioGraph) +{ + if (m_audioGraph == audioGraph) + return; + + DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "is setting graph:" << int(audioGraph)) + if (m_auNode){ + AUGraphRemoveNode(m_audioGraph->audioGraphRef(), m_auNode); + m_auNode = 0; + } + + m_audioUnit = 0; + m_lastConnectionIn = 0; + m_audioGraph = audioGraph; +} + +void AudioNode::createAndConnectAUNodes() +{ + if (m_auNode) + return; + + ComponentDescription description = getAudioNodeDescription(); + DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AUNode" + << QString(!FindNextComponent(0, &description) ? "ERROR: COMPONENT NOT FOUND!" : "OK!")) + + OSStatus err = noErr; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) + err = AUGraphAddNode(m_audioGraph->audioGraphRef(), &description, &m_auNode); + else +#endif + err = AUGraphNewNode(m_audioGraph->audioGraphRef(), &description, 0, 0, &m_auNode); + + BACKEND_ASSERT2(err != kAUGraphErr_OutputNodeErr, "A MediaObject can only be connected to one audio output device.", FATAL_ERROR) + BACKEND_ASSERT2(err == noErr, "Could not create new AUNode.", FATAL_ERROR) +} + +AUNode AudioNode::getInputAUNode() +{ + return m_auNode; +} + +AUNode AudioNode::getOutputAUNode() +{ + return m_auNode; +} + +void AudioNode::createAudioUnits() +{ + if (m_audioUnit) + return; + + DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AudioUnit") + OSStatus err = AUGraphGetNodeInfo(m_audioGraph->audioGraphRef(), m_auNode, 0, 0, 0, &m_audioUnit); + BACKEND_ASSERT2(err == noErr, "Could not get audio unit from audio node.", FATAL_ERROR) + initializeAudioUnit(); +} + +ComponentDescription AudioNode::getAudioNodeDescription() const +{ + // Override if needed. + ComponentDescription cd; + Q_UNUSED(cd); + return cd; +} + +bool AudioNode::setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource) +{ + if (fromSource){ + OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, + bus, &c->m_sourceStreamDescription, sizeof(AudioStreamBasicDescription)); + if (err != noErr){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format") + return false; + } + AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope, + bus, c->m_sourceChannelLayout, c->m_sourceChannelLayoutSize); + } else { + OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, + bus, &c->m_sinkStreamDescription, sizeof(AudioStreamBasicDescription)); + if (err != noErr){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format") + return false; + } + AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope, + bus, c->m_sinkChannelLayout, c->m_sourceChannelLayoutSize); + } + return true; +} + +bool AudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side) +{ + if (side == Source){ + // This object am source of connection: + if (connection->m_hasSourceSpecification){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification out" + << connection->m_sourceOutputBus << "from connection source") + return setStreamHelp(connection, connection->m_sourceOutputBus, kAudioUnitScope_Output, true); + } else { + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification out") + } + } else { + if (connection->m_hasSinkSpecification){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification" + << connection->m_sinkInputBus << "from connection sink") + return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, false); + } else if (connection->m_hasSourceSpecification){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification" + << connection->m_sinkInputBus << "from connection source") + return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, true); + } else { + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification in") + } + } + return true; +} + +bool AudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side) +{ + if (side == Source){ + // As default, use the last description to describe the source: + if (m_lastConnectionIn->m_hasSinkSpecification){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection sink.") + connection->m_sourceStreamDescription = m_lastConnectionIn->m_sinkStreamDescription; + connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sinkChannelLayoutSize); + memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sinkChannelLayout, m_lastConnectionIn->m_sinkChannelLayoutSize); + connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sinkChannelLayoutSize; + connection->m_hasSourceSpecification = true; + } else if (m_lastConnectionIn->m_hasSourceSpecification){ + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection source.") + connection->m_sourceStreamDescription = m_lastConnectionIn->m_sourceStreamDescription; + connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sourceChannelLayoutSize); + memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayoutSize); + connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sourceChannelLayoutSize; + connection->m_hasSourceSpecification = true; + } else { + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " __WARNING__: could not get stream specification...") + } + } else { + DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is sink, skips filling in stream.") + if (!connection->isSinkOnly()) + m_lastConnectionIn = connection; + } + return true; +} + +/** + Let timeProperty be one of e.g + {kAudioUnitProperty_Latency, kAudioUnitProperty_TailTime, + kAudioOutputUnitProperty_StartTime, kAudioUnitProperty_CurrentPlayTime} +*/ +Float64 AudioNode::getTimeInSamples(int timeProperty) +{ + if (!m_audioUnit) + return 0; + + AudioTimeStamp timeStamp; + UInt32 size = sizeof(timeStamp); + memset(&timeStamp, 0, sizeof(timeStamp)); + OSStatus err = AudioUnitGetProperty(m_audioUnit, + timeProperty, kAudioUnitScope_Global, + 0, &timeStamp, &size); + if (err != noErr) + return 0; + return timeStamp.mSampleTime; +} + +void AudioNode::notify(const MediaNodeEvent *event) +{ + switch(event->type()){ + case MediaNodeEvent::AudioGraphAboutToBeDeleted: + setGraph(0); + break; + case MediaNodeEvent::NewAudioGraph: + setGraph(static_cast<AudioGraph *>(event->data())); + break; + default: + break; + } + + mediaNodeEvent(event); +} + +void AudioNode::mediaNodeEvent(const MediaNodeEvent */*event*/) +{ + // Override if needed +} + +void AudioNode::initializeAudioUnit() +{ + // Override if needed. +} + +}} //namespace Phonon::QT7 + +QT_END_NAMESPACE |