| /* 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 "audioeffects.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| namespace Phonon |
| { |
| namespace QT7 |
| { |
| |
| AudioEffectAudioNode::AudioEffectAudioNode(int effectType) |
| : AudioNode(1, 1), m_effectType(effectType) |
| { |
| } |
| |
| ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const |
| { |
| ComponentDescription d; |
| d.componentType = kAudioUnitType_Effect; |
| d.componentSubType = m_effectType; |
| d.componentManufacturer = kAudioUnitManufacturer_Apple; |
| d.componentFlags = 0; |
| d.componentFlagsMask = 0; |
| return d; |
| } |
| |
| void AudioEffectAudioNode::initializeAudioUnit() |
| { |
| if (!m_audioUnit) |
| return; |
| foreach(int id, m_alteredParameters.keys()){ |
| Float32 value = m_alteredParameters.value(id); |
| ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0); |
| BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR) |
| } |
| } |
| |
| QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter ¶meter) const |
| { |
| if (m_audioUnit){ |
| Float32 value = 0; |
| AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value); |
| return QVariant(value); |
| } else if (m_alteredParameters.contains(parameter.id())){ |
| return QVariant(m_alteredParameters.value(parameter.id())); |
| } else { |
| // Use default value: |
| AudioUnit tmpAudioUnit; |
| ComponentDescription description = getAudioNodeDescription(); |
| Component component = FindNextComponent(0, &description); |
| BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) |
| OSErr err = OpenAComponent(component, &tmpAudioUnit); |
| BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) |
| AudioUnitParameterInfo info; |
| UInt32 size = sizeof(info); |
| ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, |
| kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); |
| BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant()) |
| return QVariant(info.defaultValue); |
| } |
| } |
| |
| void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) |
| { |
| Float32 value = 0; |
| if (newValue.isValid()){ |
| value = newValue.toDouble(); |
| m_alteredParameters.insert(parameter.id(), value); |
| } else { |
| // Use default value: |
| m_alteredParameters.remove(parameter.id()); |
| if (m_audioUnit){ |
| AudioUnit tmpAudioUnit; |
| ComponentDescription description = getAudioNodeDescription(); |
| Component component = FindNextComponent(0, &description); |
| BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR) |
| OSErr err = OpenAComponent(component, &tmpAudioUnit); |
| BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR) |
| AudioUnitParameterInfo info; |
| UInt32 size = sizeof(info); |
| ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, |
| kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); |
| BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR) |
| value = info.defaultValue; |
| } |
| } |
| |
| if (m_audioUnit){ |
| ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0); |
| BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR) |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////// |
| |
| AudioEffect::AudioEffect(int effectType, QObject *parent) |
| : MediaNode(AudioSink | AudioSource, 0, parent) |
| { |
| m_audioNode = new AudioEffectAudioNode(effectType); |
| setAudioNode(m_audioNode); |
| } |
| |
| QList<Phonon::EffectParameter> AudioEffect::parameters() const |
| { |
| QList<Phonon::EffectParameter> effectList; |
| // Create a temporary audio unit: |
| AudioUnit audioUnit; |
| ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
| Component component = FindNextComponent(0, &description); |
| BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) |
| OSErr err = OpenAComponent(component, &audioUnit); |
| BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) |
| |
| UInt32 size = 0; |
| // Get parameter count: |
| ComponentResult res = AudioUnitGetProperty(audioUnit, |
| kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size); |
| BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList) |
| int paramCount = size / sizeof(AudioUnitParameterID); |
| |
| // Get parameters: |
| AudioUnitParameterID parameters[paramCount]; |
| res = AudioUnitGetProperty(audioUnit, |
| kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, ¶meters, &size); |
| BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList) |
| |
| for (int i=0; i<paramCount; ++i) |
| effectList << createParameter(audioUnit, parameters[i]); |
| |
| CloseComponent(audioUnit); |
| return effectList; |
| } |
| |
| QString AudioEffect::name() |
| { |
| ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
| Component component = FindNextComponent(0, &description); |
| BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("<unknown effect>")) |
| |
| ComponentDescription cDesc; |
| Handle nameH = NewHandle(0); |
| GetComponentInfo(component, &cDesc, nameH, 0, 0); |
| HLock(nameH); |
| char *namePtr = *nameH; |
| int len = *namePtr++; |
| namePtr[len] = 0; |
| QString qsName = QString::fromUtf8(namePtr); |
| DisposeHandle(nameH); |
| return qsName; |
| } |
| |
| QString AudioEffect::description() |
| { |
| ComponentDescription description = m_audioNode->getAudioNodeDescription(); |
| Component component = FindNextComponent(0, &description); |
| BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("<unknown effect>")) |
| |
| ComponentDescription cDesc; |
| Handle descH = NewHandle(0); |
| GetComponentInfo(component, &cDesc, 0, descH, 0); |
| HLock(descH); |
| char *descPtr = *descH; |
| int len = *descPtr++; |
| descPtr[len] = 0; |
| QString qsDesc = QString::fromUtf8(descPtr); |
| DisposeHandle(descH); |
| return qsDesc; |
| } |
| |
| QList<int> AudioEffect::effectList() |
| { |
| QList<int> effects; |
| |
| ComponentDescription d; |
| d.componentType = kAudioUnitType_Effect; |
| d.componentSubType = 0; |
| d.componentManufacturer = 0; |
| d.componentFlags = 0; |
| d.componentFlagsMask = 0; |
| Component component = FindNextComponent(0, &d); |
| |
| while (component) { |
| ComponentDescription cDesc; |
| GetComponentInfo(component, &cDesc, 0, 0, 0); |
| effects << cDesc.componentSubType; |
| component = FindNextComponent(component, &d); |
| } |
| return effects; |
| } |
| |
| Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const |
| { |
| AudioUnitParameterInfo info; |
| UInt32 size = sizeof(info); |
| ComponentResult res = AudioUnitGetProperty(audioUnit, |
| kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size); |
| BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter()) |
| |
| QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString |
| ? PhononCFString::toQString(info.cfNameString) : QLatin1String("<unknown parameter>"); |
| |
| Phonon::EffectParameter::Hint hint; |
| switch(info.unit){ |
| case (kAudioUnitParameterUnit_Indexed): |
| case (kAudioUnitParameterUnit_Seconds): |
| case (kAudioUnitParameterUnit_SampleFrames): |
| case (kAudioUnitParameterUnit_Milliseconds): |
| hint = Phonon::EffectParameter::IntegerHint; |
| break; |
| case (kAudioUnitParameterUnit_Boolean): |
| hint = Phonon::EffectParameter::ToggledHint; |
| break; |
| default: |
| hint = Phonon::EffectParameter::LogarithmicHint; |
| break; |
| } |
| |
| QVariant def(info.defaultValue); |
| QVariant min(info.minValue); |
| QVariant max(info.maxValue); |
| return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name); |
| } |
| |
| QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const |
| { |
| return m_audioNode->parameterValue(value); |
| } |
| |
| void AudioEffect::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) |
| { |
| m_audioNode->setParameterValue(parameter, newValue); |
| } |
| |
| }} //namespace Phonon::QT7 |
| |
| QT_END_NAMESPACE |
| |
| #include "moc_audioeffects.cpp" |