src/3rdparty/phonon/qt7/audioeffects.mm
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 &parameter) 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 &parameter, 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, &parameters, &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 &parameter, 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"