Home | History | Annotate | Download | only in libmedia
      1 /*
      2 **
      3 ** Copyright 2010, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "AudioEffect"
     21 
     22 #include <stdint.h>
     23 #include <sys/types.h>
     24 #include <limits.h>
     25 
     26 #include <private/media/AudioEffectShared.h>
     27 #include <media/AudioEffect.h>
     28 
     29 #include <utils/Log.h>
     30 #include <binder/IPCThreadState.h>
     31 
     32 
     33 
     34 namespace android {
     35 
     36 // ---------------------------------------------------------------------------
     37 
     38 AudioEffect::AudioEffect()
     39     : mStatus(NO_INIT)
     40 {
     41 }
     42 
     43 
     44 AudioEffect::AudioEffect(const effect_uuid_t *type,
     45                 const effect_uuid_t *uuid,
     46                 int32_t priority,
     47                 effect_callback_t cbf,
     48                 void* user,
     49                 int sessionId,
     50                 audio_io_handle_t io
     51                 )
     52     : mStatus(NO_INIT)
     53 {
     54     mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
     55 }
     56 
     57 AudioEffect::AudioEffect(const char *typeStr,
     58                 const char *uuidStr,
     59                 int32_t priority,
     60                 effect_callback_t cbf,
     61                 void* user,
     62                 int sessionId,
     63                 audio_io_handle_t io
     64                 )
     65     : mStatus(NO_INIT)
     66 {
     67     effect_uuid_t type;
     68     effect_uuid_t *pType = NULL;
     69     effect_uuid_t uuid;
     70     effect_uuid_t *pUuid = NULL;
     71 
     72     ALOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
     73 
     74     if (typeStr != NULL) {
     75         if (stringToGuid(typeStr, &type) == NO_ERROR) {
     76             pType = &type;
     77         }
     78     }
     79 
     80     if (uuidStr != NULL) {
     81         if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
     82             pUuid = &uuid;
     83         }
     84     }
     85 
     86     mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
     87 }
     88 
     89 status_t AudioEffect::set(const effect_uuid_t *type,
     90                 const effect_uuid_t *uuid,
     91                 int32_t priority,
     92                 effect_callback_t cbf,
     93                 void* user,
     94                 int sessionId,
     95                 audio_io_handle_t io)
     96 {
     97     sp<IEffect> iEffect;
     98     sp<IMemory> cblk;
     99     int enabled;
    100 
    101     ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
    102 
    103     if (mIEffect != 0) {
    104         ALOGW("Effect already in use");
    105         return INVALID_OPERATION;
    106     }
    107 
    108     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    109     if (audioFlinger == 0) {
    110         ALOGE("set(): Could not get audioflinger");
    111         return NO_INIT;
    112     }
    113 
    114     if (type == NULL && uuid == NULL) {
    115         ALOGW("Must specify at least type or uuid");
    116         return BAD_VALUE;
    117     }
    118 
    119     mPriority = priority;
    120     mCbf = cbf;
    121     mUserData = user;
    122     mSessionId = sessionId;
    123 
    124     memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
    125     mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
    126     mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
    127 
    128     mIEffectClient = new EffectClient(this);
    129 
    130     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
    131             mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled);
    132 
    133     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
    134         ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
    135         return mStatus;
    136     }
    137 
    138     mEnabled = (volatile int32_t)enabled;
    139 
    140     mIEffect = iEffect;
    141     cblk = iEffect->getCblk();
    142     if (cblk == 0) {
    143         mStatus = NO_INIT;
    144         ALOGE("Could not get control block");
    145         return mStatus;
    146     }
    147 
    148     mIEffect = iEffect;
    149     mCblkMemory = cblk;
    150     mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
    151     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
    152     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
    153 
    154     iEffect->asBinder()->linkToDeath(mIEffectClient);
    155     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d", this, mDescriptor.name, mId,
    156             mStatus, mEnabled);
    157 
    158     return mStatus;
    159 }
    160 
    161 
    162 AudioEffect::~AudioEffect()
    163 {
    164     ALOGV("Destructor %p", this);
    165 
    166     if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
    167         if (mIEffect != NULL) {
    168             mIEffect->disconnect();
    169             mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
    170         }
    171         IPCThreadState::self()->flushCommands();
    172     }
    173     mIEffect.clear();
    174     mIEffectClient.clear();
    175     mCblkMemory.clear();
    176 }
    177 
    178 
    179 status_t AudioEffect::initCheck() const
    180 {
    181     return mStatus;
    182 }
    183 
    184 // -------------------------------------------------------------------------
    185 
    186 effect_descriptor_t AudioEffect::descriptor() const
    187 {
    188     return mDescriptor;
    189 }
    190 
    191 bool AudioEffect::getEnabled() const
    192 {
    193     return (mEnabled != 0);
    194 }
    195 
    196 status_t AudioEffect::setEnabled(bool enabled)
    197 {
    198     if (mStatus != NO_ERROR) {
    199         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    200     }
    201 
    202     status_t status = NO_ERROR;
    203 
    204     AutoMutex lock(mLock);
    205     if (enabled != mEnabled) {
    206         if (enabled) {
    207             ALOGV("enable %p", this);
    208             status = mIEffect->enable();
    209         } else {
    210             ALOGV("disable %p", this);
    211             status = mIEffect->disable();
    212         }
    213         if (status == NO_ERROR) {
    214             mEnabled = enabled;
    215         }
    216     }
    217     return status;
    218 }
    219 
    220 status_t AudioEffect::command(uint32_t cmdCode,
    221                               uint32_t cmdSize,
    222                               void *cmdData,
    223                               uint32_t *replySize,
    224                               void *replyData)
    225 {
    226     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
    227         ALOGV("command() bad status %d", mStatus);
    228         return mStatus;
    229     }
    230 
    231     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
    232         if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
    233             return NO_ERROR;
    234         }
    235         if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
    236             return BAD_VALUE;
    237         }
    238         mLock.lock();
    239     }
    240 
    241     status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
    242 
    243     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
    244         if (status == NO_ERROR) {
    245             status = *(status_t *)replyData;
    246         }
    247         if (status == NO_ERROR) {
    248             mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
    249         }
    250         mLock.unlock();
    251     }
    252 
    253     return status;
    254 }
    255 
    256 
    257 status_t AudioEffect::setParameter(effect_param_t *param)
    258 {
    259     if (mStatus != NO_ERROR) {
    260         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    261     }
    262 
    263     if (param == NULL || param->psize == 0 || param->vsize == 0) {
    264         return BAD_VALUE;
    265     }
    266 
    267     uint32_t size = sizeof(int);
    268     uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
    269 
    270     ALOGV("setParameter: param: %d, param2: %d", *(int *)param->data,
    271             (param->psize == 8) ? *((int *)param->data + 1): -1);
    272 
    273     return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size,
    274             &param->status);
    275 }
    276 
    277 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
    278 {
    279     if (mStatus != NO_ERROR) {
    280         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    281     }
    282 
    283     if (param == NULL || param->psize == 0 || param->vsize == 0) {
    284         return BAD_VALUE;
    285     }
    286 
    287     Mutex::Autolock _l(mCblk->lock);
    288 
    289     int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
    290     int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
    291 
    292     if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
    293         return NO_MEMORY;
    294     }
    295     int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
    296     *p++ = size;
    297     memcpy(p, param, sizeof(effect_param_t) + psize);
    298     mCblk->clientIndex += size;
    299 
    300     return NO_ERROR;
    301 }
    302 
    303 status_t AudioEffect::setParameterCommit()
    304 {
    305     if (mStatus != NO_ERROR) {
    306         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    307     }
    308 
    309     Mutex::Autolock _l(mCblk->lock);
    310     if (mCblk->clientIndex == 0) {
    311         return INVALID_OPERATION;
    312     }
    313     uint32_t size = 0;
    314     return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
    315 }
    316 
    317 status_t AudioEffect::getParameter(effect_param_t *param)
    318 {
    319     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
    320         return mStatus;
    321     }
    322 
    323     if (param == NULL || param->psize == 0 || param->vsize == 0) {
    324         return BAD_VALUE;
    325     }
    326 
    327     ALOGV("getParameter: param: %d, param2: %d", *(int *)param->data,
    328             (param->psize == 8) ? *((int *)param->data + 1): -1);
    329 
    330     uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
    331             param->vsize;
    332 
    333     return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param,
    334             &psize, param);
    335 }
    336 
    337 
    338 // -------------------------------------------------------------------------
    339 
    340 void AudioEffect::binderDied()
    341 {
    342     ALOGW("IEffect died");
    343     mStatus = DEAD_OBJECT;
    344     if (mCbf != NULL) {
    345         status_t status = DEAD_OBJECT;
    346         mCbf(EVENT_ERROR, mUserData, &status);
    347     }
    348     mIEffect.clear();
    349 }
    350 
    351 // -------------------------------------------------------------------------
    352 
    353 void AudioEffect::controlStatusChanged(bool controlGranted)
    354 {
    355     ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
    356             mUserData);
    357     if (controlGranted) {
    358         if (mStatus == ALREADY_EXISTS) {
    359             mStatus = NO_ERROR;
    360         }
    361     } else {
    362         if (mStatus == NO_ERROR) {
    363             mStatus = ALREADY_EXISTS;
    364         }
    365     }
    366     if (mCbf != NULL) {
    367         mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
    368     }
    369 }
    370 
    371 void AudioEffect::enableStatusChanged(bool enabled)
    372 {
    373     ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
    374     if (mStatus == ALREADY_EXISTS) {
    375         mEnabled = enabled;
    376         if (mCbf != NULL) {
    377             mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
    378         }
    379     }
    380 }
    381 
    382 void AudioEffect::commandExecuted(uint32_t cmdCode,
    383                                   uint32_t cmdSize,
    384                                   void *cmdData,
    385                                   uint32_t replySize,
    386                                   void *replyData)
    387 {
    388     if (cmdData == NULL || replyData == NULL) {
    389         return;
    390     }
    391 
    392     if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
    393         effect_param_t *cmd = (effect_param_t *)cmdData;
    394         cmd->status = *(int32_t *)replyData;
    395         mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
    396     }
    397 }
    398 
    399 // -------------------------------------------------------------------------
    400 
    401 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
    402 {
    403     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    404     if (af == 0) return PERMISSION_DENIED;
    405     return af->queryNumberEffects(numEffects);
    406 }
    407 
    408 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
    409 {
    410     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    411     if (af == 0) return PERMISSION_DENIED;
    412     return af->queryEffect(index, descriptor);
    413 }
    414 
    415 status_t AudioEffect::getEffectDescriptor(const effect_uuid_t *uuid,
    416         effect_descriptor_t *descriptor) /*const*/
    417 {
    418     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    419     if (af == 0) return PERMISSION_DENIED;
    420     return af->getEffectDescriptor(uuid, descriptor);
    421 }
    422 
    423 
    424 status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
    425                                           effect_descriptor_t *descriptors,
    426                                           uint32_t *count)
    427 {
    428     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    429     if (aps == 0) return PERMISSION_DENIED;
    430     return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
    431 }
    432 // -------------------------------------------------------------------------
    433 
    434 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
    435 {
    436     if (str == NULL || guid == NULL) {
    437         return BAD_VALUE;
    438     }
    439 
    440     int tmp[10];
    441 
    442     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    443             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
    444         return BAD_VALUE;
    445     }
    446     guid->timeLow = (uint32_t)tmp[0];
    447     guid->timeMid = (uint16_t)tmp[1];
    448     guid->timeHiAndVersion = (uint16_t)tmp[2];
    449     guid->clockSeq = (uint16_t)tmp[3];
    450     guid->node[0] = (uint8_t)tmp[4];
    451     guid->node[1] = (uint8_t)tmp[5];
    452     guid->node[2] = (uint8_t)tmp[6];
    453     guid->node[3] = (uint8_t)tmp[7];
    454     guid->node[4] = (uint8_t)tmp[8];
    455     guid->node[5] = (uint8_t)tmp[9];
    456 
    457     return NO_ERROR;
    458 }
    459 
    460 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
    461 {
    462     if (guid == NULL || str == NULL) {
    463         return BAD_VALUE;
    464     }
    465 
    466     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    467             guid->timeLow,
    468             guid->timeMid,
    469             guid->timeHiAndVersion,
    470             guid->clockSeq,
    471             guid->node[0],
    472             guid->node[1],
    473             guid->node[2],
    474             guid->node[3],
    475             guid->node[4],
    476             guid->node[5]);
    477 
    478     return NO_ERROR;
    479 }
    480 
    481 
    482 }; // namespace android
    483