|
1 /* This file is part of the KDE project. |
|
2 |
|
3 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 |
|
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. |
|
8 |
|
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. |
|
13 |
|
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/>. |
|
16 */ |
|
17 |
|
18 #include "audioeffects.h" |
|
19 |
|
20 QT_BEGIN_NAMESPACE |
|
21 |
|
22 namespace Phonon |
|
23 { |
|
24 namespace QT7 |
|
25 { |
|
26 |
|
27 AudioEffectAudioNode::AudioEffectAudioNode(int effectType) |
|
28 : AudioNode(1, 1), m_effectType(effectType) |
|
29 { |
|
30 } |
|
31 |
|
32 ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const |
|
33 { |
|
34 ComponentDescription d; |
|
35 d.componentType = kAudioUnitType_Effect; |
|
36 d.componentSubType = m_effectType; |
|
37 d.componentManufacturer = kAudioUnitManufacturer_Apple; |
|
38 d.componentFlags = 0; |
|
39 d.componentFlagsMask = 0; |
|
40 return d; |
|
41 } |
|
42 |
|
43 void AudioEffectAudioNode::initializeAudioUnit() |
|
44 { |
|
45 if (!m_audioUnit) |
|
46 return; |
|
47 foreach(int id, m_alteredParameters.keys()){ |
|
48 Float32 value = m_alteredParameters.value(id); |
|
49 ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0); |
|
50 BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR) |
|
51 } |
|
52 } |
|
53 |
|
54 QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter ¶meter) const |
|
55 { |
|
56 if (m_audioUnit){ |
|
57 Float32 value = 0; |
|
58 AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value); |
|
59 return QVariant(value); |
|
60 } else if (m_alteredParameters.contains(parameter.id())){ |
|
61 return QVariant(m_alteredParameters.value(parameter.id())); |
|
62 } else { |
|
63 // Use default value: |
|
64 AudioUnit tmpAudioUnit; |
|
65 ComponentDescription description = getAudioNodeDescription(); |
|
66 Component component = FindNextComponent(0, &description); |
|
67 BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) |
|
68 OSErr err = OpenAComponent(component, &tmpAudioUnit); |
|
69 BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) |
|
70 AudioUnitParameterInfo info; |
|
71 UInt32 size = sizeof(info); |
|
72 ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, |
|
73 kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); |
|
74 BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant()) |
|
75 return QVariant(info.defaultValue); |
|
76 } |
|
77 } |
|
78 |
|
79 void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) |
|
80 { |
|
81 Float32 value = 0; |
|
82 if (newValue.isValid()){ |
|
83 value = newValue.toDouble(); |
|
84 m_alteredParameters.insert(parameter.id(), value); |
|
85 } else { |
|
86 // Use default value: |
|
87 m_alteredParameters.remove(parameter.id()); |
|
88 if (m_audioUnit){ |
|
89 AudioUnit tmpAudioUnit; |
|
90 ComponentDescription description = getAudioNodeDescription(); |
|
91 Component component = FindNextComponent(0, &description); |
|
92 BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR) |
|
93 OSErr err = OpenAComponent(component, &tmpAudioUnit); |
|
94 BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR) |
|
95 AudioUnitParameterInfo info; |
|
96 UInt32 size = sizeof(info); |
|
97 ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, |
|
98 kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); |
|
99 BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR) |
|
100 value = info.defaultValue; |
|
101 } |
|
102 } |
|
103 |
|
104 if (m_audioUnit){ |
|
105 ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0); |
|
106 BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR) |
|
107 } |
|
108 } |
|
109 |
|
110 /////////////////////////////////////////////////////////////////////// |
|
111 |
|
112 AudioEffect::AudioEffect(int effectType, QObject *parent) |
|
113 : MediaNode(AudioSink | AudioSource, 0, parent) |
|
114 { |
|
115 m_audioNode = new AudioEffectAudioNode(effectType); |
|
116 setAudioNode(m_audioNode); |
|
117 } |
|
118 |
|
119 QList<Phonon::EffectParameter> AudioEffect::parameters() const |
|
120 { |
|
121 QList<Phonon::EffectParameter> effectList; |
|
122 // Create a temporary audio unit: |
|
123 AudioUnit audioUnit; |
|
124 ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
|
125 Component component = FindNextComponent(0, &description); |
|
126 BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) |
|
127 OSErr err = OpenAComponent(component, &audioUnit); |
|
128 BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) |
|
129 |
|
130 UInt32 size = 0; |
|
131 // Get parameter count: |
|
132 ComponentResult res = AudioUnitGetProperty(audioUnit, |
|
133 kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size); |
|
134 BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList) |
|
135 int paramCount = size / sizeof(AudioUnitParameterID); |
|
136 |
|
137 // Get parameters: |
|
138 AudioUnitParameterID parameters[paramCount]; |
|
139 res = AudioUnitGetProperty(audioUnit, |
|
140 kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, ¶meters, &size); |
|
141 BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList) |
|
142 |
|
143 for (int i=0; i<paramCount; ++i) |
|
144 effectList << createParameter(audioUnit, parameters[i]); |
|
145 |
|
146 CloseComponent(audioUnit); |
|
147 return effectList; |
|
148 } |
|
149 |
|
150 QString AudioEffect::name() |
|
151 { |
|
152 ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
|
153 Component component = FindNextComponent(0, &description); |
|
154 BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("<unknown effect>")) |
|
155 |
|
156 ComponentDescription cDesc; |
|
157 Handle nameH = NewHandle(0); |
|
158 GetComponentInfo(component, &cDesc, nameH, 0, 0); |
|
159 HLock(nameH); |
|
160 char *namePtr = *nameH; |
|
161 int len = *namePtr++; |
|
162 namePtr[len] = 0; |
|
163 QString qsName = QString::fromUtf8(namePtr); |
|
164 DisposeHandle(nameH); |
|
165 return qsName; |
|
166 } |
|
167 |
|
168 QString AudioEffect::description() |
|
169 { |
|
170 ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
|
171 Component component = FindNextComponent(0, &description); |
|
172 BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("<unknown effect>")) |
|
173 |
|
174 ComponentDescription cDesc; |
|
175 Handle descH = NewHandle(0); |
|
176 GetComponentInfo(component, &cDesc, 0, descH, 0); |
|
177 HLock(descH); |
|
178 char *descPtr = *descH; |
|
179 int len = *descPtr++; |
|
180 descPtr[len] = 0; |
|
181 QString qsDesc = QString::fromUtf8(descPtr); |
|
182 DisposeHandle(descH); |
|
183 return qsDesc; |
|
184 } |
|
185 |
|
186 QList<int> AudioEffect::effectList() |
|
187 { |
|
188 QList<int> effects; |
|
189 |
|
190 ComponentDescription d; |
|
191 d.componentType = kAudioUnitType_Effect; |
|
192 d.componentSubType = 0; |
|
193 d.componentManufacturer = 0; |
|
194 d.componentFlags = 0; |
|
195 d.componentFlagsMask = 0; |
|
196 Component component = FindNextComponent(0, &d); |
|
197 |
|
198 while (component) { |
|
199 ComponentDescription cDesc; |
|
200 GetComponentInfo(component, &cDesc, 0, 0, 0); |
|
201 effects << cDesc.componentSubType; |
|
202 component = FindNextComponent(component, &d); |
|
203 } |
|
204 return effects; |
|
205 } |
|
206 |
|
207 Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const |
|
208 { |
|
209 AudioUnitParameterInfo info; |
|
210 UInt32 size = sizeof(info); |
|
211 ComponentResult res = AudioUnitGetProperty(audioUnit, |
|
212 kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size); |
|
213 BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter()) |
|
214 |
|
215 QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString |
|
216 ? PhononCFString::toQString(info.cfNameString) : QLatin1String("<unknown parameter>"); |
|
217 |
|
218 Phonon::EffectParameter::Hint hint; |
|
219 switch(info.unit){ |
|
220 case (kAudioUnitParameterUnit_Indexed): |
|
221 case (kAudioUnitParameterUnit_Seconds): |
|
222 case (kAudioUnitParameterUnit_SampleFrames): |
|
223 case (kAudioUnitParameterUnit_Milliseconds): |
|
224 hint = Phonon::EffectParameter::IntegerHint; |
|
225 break; |
|
226 case (kAudioUnitParameterUnit_Boolean): |
|
227 hint = Phonon::EffectParameter::ToggledHint; |
|
228 break; |
|
229 default: |
|
230 hint = Phonon::EffectParameter::LogarithmicHint; |
|
231 break; |
|
232 } |
|
233 |
|
234 QVariant def(info.defaultValue); |
|
235 QVariant min(info.minValue); |
|
236 QVariant max(info.maxValue); |
|
237 return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name); |
|
238 } |
|
239 |
|
240 QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const |
|
241 { |
|
242 return m_audioNode->parameterValue(value); |
|
243 } |
|
244 |
|
245 void AudioEffect::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) |
|
246 { |
|
247 m_audioNode->setParameterValue(parameter, newValue); |
|
248 } |
|
249 |
|
250 }} //namespace Phonon::QT7 |
|
251 |
|
252 QT_END_NAMESPACE |
|
253 |
|
254 #include "moc_audioeffects.cpp" |