Home | History | Annotate | Download | only in itf
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /* AndroidEffectSend implementation */
     18 
     19 #include "sles_allinclusive.h"
     20 
     21 
     22 static SLresult IAndroidEffectSend_EnableEffectSend(SLAndroidEffectSendItf self,
     23     SLInterfaceID effectImplementationId, SLboolean enable, SLmillibel initialLevel)
     24 {
     25     SL_ENTER_INTERFACE
     26 
     27     //if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) {
     28     // comparison (SL_MILLIBEL_MIN <= initialLevel) is always true due to range of SLmillibel
     29     if (!(initialLevel <= 0)) {
     30         result = SL_RESULT_PARAMETER_INVALID;
     31     } else {
     32         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
     33         interface_lock_exclusive(thiz);
     34         // is SLAndroidEffectSendItf on an AudioPlayer?
     35         CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
     36                 (CAudioPlayer *) thiz->mThis : NULL;
     37         if (NULL == ap) {
     38             SL_LOGE("invalid interface: not attached to an AudioPlayer");
     39             result = SL_RESULT_PARAMETER_INVALID;
     40         } else {
     41             COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
     42             // the initial send level set here is the total energy on the aux bus,
     43             //  so it must take into account the player volume level
     44             result = android_fxSend_attachToAux(ap, effectImplementationId, enable,
     45                     initialLevel + ap->mVolume.mLevel);
     46             if (SL_RESULT_SUCCESS == result) {
     47                 // there currently is support for only one send bus, so there is a single send
     48                 // level and a single enable flag
     49                 thiz->mSendLevel = initialLevel;
     50                 thiz->mEnabled = enable;
     51             }
     52         }
     53         interface_unlock_exclusive(thiz);
     54     }
     55 
     56     SL_LEAVE_INTERFACE
     57 }
     58 
     59 
     60 static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self,
     61     SLInterfaceID effectImplementationId, SLboolean *pEnable)
     62 {
     63     SL_ENTER_INTERFACE
     64 
     65     if (NULL == pEnable) {
     66         result = SL_RESULT_PARAMETER_INVALID;
     67     } else {
     68         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
     69         interface_lock_shared(thiz);
     70         // there currently is support for only one send bus, so there is a single enable flag
     71         SLboolean enable = thiz->mEnabled;
     72         interface_unlock_shared(thiz);
     73         *pEnable = enable;
     74         result = SL_RESULT_SUCCESS;
     75     }
     76 
     77     SL_LEAVE_INTERFACE
     78 }
     79 
     80 
     81 static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self,
     82         SLmillibel directLevel)
     83 {
     84     SL_ENTER_INTERFACE
     85 
     86     //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
     87     // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel
     88     if (!(directLevel <= 0)) {
     89         result = SL_RESULT_PARAMETER_INVALID;
     90     } else {
     91         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
     92         interface_lock_exclusive(thiz);
     93         CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
     94                 (CAudioPlayer *) thiz->mThis : NULL;
     95         if (NULL != ap) {
     96             SLmillibel oldDirectLevel = ap->mDirectLevel;
     97             if (oldDirectLevel != directLevel) {
     98                 ap->mDirectLevel = directLevel;
     99                 ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
    100                 interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
    101             } else {
    102                 interface_unlock_exclusive(thiz);
    103             }
    104             result = SL_RESULT_SUCCESS;
    105         } else {
    106             interface_unlock_exclusive(thiz);
    107             SL_LOGE("invalid interface: not attached to an AudioPlayer");
    108             result = SL_RESULT_PARAMETER_INVALID;
    109         }
    110     }
    111 
    112      SL_LEAVE_INTERFACE
    113 }
    114 
    115 
    116 static SLresult IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self,
    117         SLmillibel *pDirectLevel)
    118 {
    119     SL_ENTER_INTERFACE
    120 
    121     if (NULL == pDirectLevel) {
    122         result = SL_RESULT_PARAMETER_INVALID;
    123     } else {
    124         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
    125         interface_lock_shared(thiz);
    126         CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
    127                 (CAudioPlayer *) thiz->mThis : NULL;
    128         if (NULL != ap) {
    129             *pDirectLevel = ap->mDirectLevel;
    130             result = SL_RESULT_SUCCESS;
    131         } else {
    132             SL_LOGE("invalid interface: not attached to an AudioPlayer");
    133             result = SL_RESULT_PARAMETER_INVALID;
    134         }
    135         interface_unlock_shared(thiz);
    136     }
    137 
    138     SL_LEAVE_INTERFACE
    139 }
    140 
    141 
    142 static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self,
    143         SLInterfaceID effectImplementationId, SLmillibel sendLevel)
    144 {
    145     SL_ENTER_INTERFACE
    146 
    147     //if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
    148     // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel
    149     if (!(sendLevel <= 0)) {
    150         result = SL_RESULT_PARAMETER_INVALID;
    151     } else {
    152         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
    153         interface_lock_exclusive(thiz);
    154         // is SLAndroidEffectSendItf on an AudioPlayer?
    155         CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
    156                  (CAudioPlayer *) thiz->mThis : NULL;
    157         if (NULL == ap) {
    158             SL_LOGE("invalid interface: not attached to an AudioPlayer");
    159             result = SL_RESULT_PARAMETER_INVALID;
    160         } else {
    161             COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
    162             if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
    163                 // the send level set here is the total energy on the aux bus, so it must take
    164                 // into account the player volume level
    165                 result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel);
    166             } else {
    167                  SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix");
    168                  result = SL_RESULT_PARAMETER_INVALID;
    169             }
    170             if (SL_RESULT_SUCCESS == result) {
    171                 // there currently is support for only one send bus, so there is a single send
    172                 // level
    173                 thiz->mSendLevel = sendLevel;
    174             }
    175         }
    176         interface_unlock_exclusive(thiz);
    177     }
    178 
    179     SL_LEAVE_INTERFACE
    180 }
    181 
    182 
    183 static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self,
    184         SLInterfaceID effectImplementationId, SLmillibel *pSendLevel)
    185 {
    186     SL_ENTER_INTERFACE
    187 
    188     if (NULL == pSendLevel) {
    189         result = SL_RESULT_PARAMETER_INVALID;
    190     } else {
    191         IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
    192         interface_lock_exclusive(thiz);
    193         // is SLAndroidEffectSendItf on an AudioPlayer?
    194         CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
    195                 (CAudioPlayer *) thiz->mThis : NULL;
    196         if (NULL == ap) {
    197             SL_LOGE("invalid interface: not attached to an AudioPlayer");
    198             result = SL_RESULT_PARAMETER_INVALID;
    199         } else {
    200             COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
    201             if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
    202                 result = SL_RESULT_SUCCESS;
    203             } else {
    204                 SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \
    205 OutputMix");
    206                 result = SL_RESULT_PARAMETER_INVALID;
    207                 }
    208             if (SL_RESULT_SUCCESS == result) {
    209                 // there currently is support for only one send bus, so there is a single send
    210                 // level
    211                 *pSendLevel = thiz->mSendLevel;
    212             }
    213         }
    214         interface_unlock_exclusive(thiz);
    215     }
    216 
    217     SL_LEAVE_INTERFACE
    218 }
    219 
    220 
    221 static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = {
    222     IAndroidEffectSend_EnableEffectSend,
    223     IAndroidEffectSend_IsEnabled,
    224     IAndroidEffectSend_SetDirectLevel,
    225     IAndroidEffectSend_GetDirectLevel,
    226     IAndroidEffectSend_SetSendLevel,
    227     IAndroidEffectSend_GetSendLevel
    228 };
    229 
    230 void IAndroidEffectSend_init(void *self)
    231 {
    232     IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
    233     thiz->mItf = &IAndroidEffectSend_Itf;
    234     thiz->mEnabled =  SL_BOOLEAN_FALSE;
    235     thiz->mSendLevel = SL_MILLIBEL_MIN;
    236 }
    237