1
/* This file is part of the KDE project.
3
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
5
This library is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published by
7
the Free Software Foundation, either version 2.1 or 3 of the License.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with this library. If not, see <http://www.gnu.org/licenses/>.
18
#include "audionode.h"
19
#include "audiograph.h"
20
#include "audioconnection.h"
21
#include "medianode.h"
30
AudioNode::AudioNode(int maxInputBusses, int maxOutputBusses)
35
m_maxInputBusses = maxInputBusses;
36
m_maxOutputBusses = maxOutputBusses;
37
m_lastConnectionIn = 0;
40
AudioNode::~AudioNode()
45
void AudioNode::setGraph(AudioGraph *audioGraph)
47
if (m_audioGraph == audioGraph)
50
DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "is setting graph:" << int(audioGraph))
52
AUGraphRemoveNode(m_audioGraph->audioGraphRef(), m_auNode);
57
m_lastConnectionIn = 0;
58
m_audioGraph = audioGraph;
61
void AudioNode::createAndConnectAUNodes()
66
ComponentDescription description = getAudioNodeDescription();
67
DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AUNode"
68
<< QString(!FindNextComponent(0, &description) ? "ERROR: COMPONENT NOT FOUND!" : "OK!"))
71
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
72
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
73
err = AUGraphAddNode(m_audioGraph->audioGraphRef(), &description, &m_auNode);
76
err = AUGraphNewNode(m_audioGraph->audioGraphRef(), &description, 0, 0, &m_auNode);
78
BACKEND_ASSERT2(err != kAUGraphErr_OutputNodeErr, "A MediaObject can only be connected to one audio output device.", FATAL_ERROR)
79
BACKEND_ASSERT2(err == noErr, "Could not create new AUNode.", FATAL_ERROR)
82
AUNode AudioNode::getInputAUNode()
87
AUNode AudioNode::getOutputAUNode()
92
void AudioNode::createAudioUnits()
97
DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AudioUnit")
98
OSStatus err = AUGraphGetNodeInfo(m_audioGraph->audioGraphRef(), m_auNode, 0, 0, 0, &m_audioUnit);
99
BACKEND_ASSERT2(err == noErr, "Could not get audio unit from audio node.", FATAL_ERROR)
100
initializeAudioUnit();
103
ComponentDescription AudioNode::getAudioNodeDescription() const
105
// Override if needed.
106
ComponentDescription cd;
111
bool AudioNode::setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource)
114
OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
115
bus, &c->m_sourceStreamDescription, sizeof(AudioStreamBasicDescription));
117
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
120
AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
121
bus, c->m_sourceChannelLayout, c->m_sourceChannelLayoutSize);
123
OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
124
bus, &c->m_sinkStreamDescription, sizeof(AudioStreamBasicDescription));
126
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
129
AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
130
bus, c->m_sinkChannelLayout, c->m_sourceChannelLayoutSize);
135
bool AudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
138
// This object am source of connection:
139
if (connection->m_hasSourceSpecification){
140
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification out"
141
<< connection->m_sourceOutputBus << "from connection source")
142
return setStreamHelp(connection, connection->m_sourceOutputBus, kAudioUnitScope_Output, true);
144
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification out")
147
if (connection->m_hasSinkSpecification){
148
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
149
<< connection->m_sinkInputBus << "from connection sink")
150
return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, false);
151
} else if (connection->m_hasSourceSpecification){
152
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
153
<< connection->m_sinkInputBus << "from connection source")
154
return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, true);
156
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification in")
162
bool AudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
165
// As default, use the last description to describe the source:
166
if (m_lastConnectionIn->m_hasSinkSpecification){
167
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection sink.")
168
connection->m_sourceStreamDescription = m_lastConnectionIn->m_sinkStreamDescription;
169
connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sinkChannelLayoutSize);
170
memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sinkChannelLayout, m_lastConnectionIn->m_sinkChannelLayoutSize);
171
connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sinkChannelLayoutSize;
172
connection->m_hasSourceSpecification = true;
173
} else if (m_lastConnectionIn->m_hasSourceSpecification){
174
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection source.")
175
connection->m_sourceStreamDescription = m_lastConnectionIn->m_sourceStreamDescription;
176
connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sourceChannelLayoutSize);
177
memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayoutSize);
178
connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sourceChannelLayoutSize;
179
connection->m_hasSourceSpecification = true;
181
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " __WARNING__: could not get stream specification...")
184
DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is sink, skips filling in stream.")
185
if (!connection->isSinkOnly())
186
m_lastConnectionIn = connection;
192
Let timeProperty be one of e.g
193
{kAudioUnitProperty_Latency, kAudioUnitProperty_TailTime,
194
kAudioOutputUnitProperty_StartTime, kAudioUnitProperty_CurrentPlayTime}
196
Float64 AudioNode::getTimeInSamples(int timeProperty)
201
AudioTimeStamp timeStamp;
202
UInt32 size = sizeof(timeStamp);
203
memset(&timeStamp, 0, sizeof(timeStamp));
204
OSStatus err = AudioUnitGetProperty(m_audioUnit,
205
timeProperty, kAudioUnitScope_Global,
206
0, &timeStamp, &size);
209
return timeStamp.mSampleTime;
212
void AudioNode::notify(const MediaNodeEvent *event)
214
switch(event->type()){
215
case MediaNodeEvent::AudioGraphAboutToBeDeleted:
218
case MediaNodeEvent::NewAudioGraph:
219
setGraph(static_cast<AudioGraph *>(event->data()));
225
mediaNodeEvent(event);
228
void AudioNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
230
// Override if needed
233
void AudioNode::initializeAudioUnit()
235
// Override if needed.
238
}} //namespace Phonon::QT7