EffectsFactory.c revision 284c17e73bbff51cb5b1adcee98386d47733757a
1f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/* 2f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * Copyright (C) 2010 The Android Open Source Project 3f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * 4f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * Licensed under the Apache License, Version 2.0 (the "License"); 5f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * you may not use this file except in compliance with the License. 6f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * You may obtain a copy of the License at 7f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * 8f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * http://www.apache.org/licenses/LICENSE-2.0 9f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * 10f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * Unless required by applicable law or agreed to in writing, software 11f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * distributed under the License is distributed on an "AS IS" BASIS, 12f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * See the License for the specific language governing permissions and 14f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard * limitations under the License. 15f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard */ 16f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 17f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#define LOG_TAG "EffectsFactory" 18f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//#define LOG_NDEBUG 0 19f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 20f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "EffectsFactory.h" 21f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include <string.h> 22cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <stdlib.h> 23f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard#include <dlfcn.h> 242a74639bc7713146b1182328892807c421c84265Vincent Lejeune 25141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune#include <cutils/misc.h> 265c35290fa35ae234fed02496404cb0fc37e1c8a5Benjamin Kramer#include <cutils/config_utils.h> 275c35290fa35ae234fed02496404cb0fc37e1c8a5Benjamin Kramer#include <audio_effects/audio_effects_conf.h> 285c35290fa35ae234fed02496404cb0fc37e1c8a5Benjamin Kramer 29bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellardstatic list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects 30bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellardstatic list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries 31f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// list of effect_descriptor and list of sub effects : all currently loaded 32bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard// It does not contain effects without sub effects. 33e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellardstatic list_sub_elem_t *gSubEffectList; 34f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList 3558a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruthstatic uint32_t gNumEffects; // total number number of effects 36f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic list_elem_t *gCurLib; // current library in enumeration process 37f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic list_elem_t *gCurEffect; // current effect in enumeration process 38f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic uint32_t gCurEffectIdx; // current effect index in enumeration process 39cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic lib_entry_t *gCachedLibrary; // last library accessed by getLibrary() 40cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 41cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int gInitDone; // true is global initialization has been preformed 42cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects 43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // was not modified since last call to EffectQueryNumberEffects() 44cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 45cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 46cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///////////////////////////////////////////////// 47cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// Local functions prototypes 48cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///////////////////////////////////////////////// 49cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 50cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int init(); 51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int loadEffectConfigFile(const char *path); 52cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int loadLibraries(cnode *root); 53cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int loadLibrary(cnode *root, const char *name); 54cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int loadEffects(cnode *root); 55cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic int loadEffect(cnode *node); 56cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// To get and add the effect pointed by the passed node to the gSubEffectList 57f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic int addSubEffect(cnode *root); 58f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic lib_entry_t *getLibrary(const char *path); 59f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic void resetEffectEnumeration(); 60f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic uint32_t updateNumEffects(); 61f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic int findEffect(const effect_uuid_t *type, 62f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard const effect_uuid_t *uuid, 63f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard lib_entry_t **lib, 64f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard effect_descriptor_t **desc); 65f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// To search a subeffect in the gSubEffectList 66f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardint findSubEffect(const effect_uuid_t *uuid, 67f9318673178309288f9320efe02d529419ac32a2Tom Stellard lib_entry_t **lib, 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines effect_descriptor_t **desc); 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len); 70f9318673178309288f9320efe02d529419ac32a2Tom Stellardstatic int stringToUuid(const char *str, effect_uuid_t *uuid); 71f9318673178309288f9320efe02d529419ac32a2Tom Stellardstatic int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen); 72f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard///////////////////////////////////////////////// 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Effect Control Interface functions 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///////////////////////////////////////////////// 76141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune 77f9318673178309288f9320efe02d529419ac32a2Tom Stellardint Effect_Process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) 78f9318673178309288f9320efe02d529419ac32a2Tom Stellard{ 7987cba4a4c1d5b8b026c83b0916b37255600ecd5fTom Stellard int ret = init(); 80141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune if (ret < 0) { 81141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune return ret; 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 83f9318673178309288f9320efe02d529419ac32a2Tom Stellard effect_entry_t *fx = (effect_entry_t *)self; 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines pthread_mutex_lock(&gLibLock); 853ff0abfaabc2c7f604d490be587b9c27e7c91ac0Tom Stellard if (fx->lib == NULL) { 86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines pthread_mutex_unlock(&gLibLock); 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -EPIPE; 88141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune } 89141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune pthread_mutex_lock(&fx->lib->lock); 90f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_unlock(&gLibLock); 91f9318673178309288f9320efe02d529419ac32a2Tom Stellard 92f9318673178309288f9320efe02d529419ac32a2Tom Stellard ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer); 93f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_unlock(&fx->lib->lock); 94f9318673178309288f9320efe02d529419ac32a2Tom Stellard return ret; 95f9318673178309288f9320efe02d529419ac32a2Tom Stellard} 96bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard 97f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardint Effect_Command(effect_handle_t self, 98f9318673178309288f9320efe02d529419ac32a2Tom Stellard uint32_t cmdCode, 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t cmdSize, 10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void *pCmdData, 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t *replySize, 10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void *pReplyData) 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int ret = init(); 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ret < 0) { 106dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return ret; 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines effect_entry_t *fx = (effect_entry_t *)self; 109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines pthread_mutex_lock(&gLibLock); 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (fx->lib == NULL) { 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines pthread_mutex_unlock(&gLibLock); 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -EPIPE; 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 114cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines pthread_mutex_lock(&fx->lib->lock); 115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines pthread_mutex_unlock(&gLibLock); 116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData); 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines pthread_mutex_unlock(&fx->lib->lock); 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ret; 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint Effect_GetDescriptor(effect_handle_t self, 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines effect_descriptor_t *desc) 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 125f9318673178309288f9320efe02d529419ac32a2Tom Stellard int ret = init(); 126f9318673178309288f9320efe02d529419ac32a2Tom Stellard if (ret < 0) { 127f9318673178309288f9320efe02d529419ac32a2Tom Stellard return ret; 128f9318673178309288f9320efe02d529419ac32a2Tom Stellard } 129f9318673178309288f9320efe02d529419ac32a2Tom Stellard effect_entry_t *fx = (effect_entry_t *)self; 130f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_lock(&gLibLock); 131f9318673178309288f9320efe02d529419ac32a2Tom Stellard if (fx->lib == NULL) { 132f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_unlock(&gLibLock); 133f9318673178309288f9320efe02d529419ac32a2Tom Stellard return -EPIPE; 134f9318673178309288f9320efe02d529419ac32a2Tom Stellard } 135f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_lock(&fx->lib->lock); 136f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_unlock(&gLibLock); 137f9318673178309288f9320efe02d529419ac32a2Tom Stellard 138f9318673178309288f9320efe02d529419ac32a2Tom Stellard ret = (*fx->subItfe)->get_descriptor(fx->subItfe, desc); 139f9318673178309288f9320efe02d529419ac32a2Tom Stellard pthread_mutex_unlock(&fx->lib->lock); 140f9318673178309288f9320efe02d529419ac32a2Tom Stellard return ret; 141f9318673178309288f9320efe02d529419ac32a2Tom Stellard} 142f9318673178309288f9320efe02d529419ac32a2Tom Stellard 143f9318673178309288f9320efe02d529419ac32a2Tom Stellardint Effect_ProcessReverse(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) 144f9318673178309288f9320efe02d529419ac32a2Tom Stellard{ 145f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard int ret = init(); 146f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (ret < 0) { 147f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return ret; 148141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune } 149141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune effect_entry_t *fx = (effect_entry_t *)self; 15086cdb704174828b8e91e94132a19634e3c11d87dVincent Lejeune pthread_mutex_lock(&gLibLock); 151141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune if (fx->lib == NULL) { 152141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune pthread_mutex_unlock(&gLibLock); 1532a74639bc7713146b1182328892807c421c84265Vincent Lejeune return -EPIPE; 154f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard } 155141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune pthread_mutex_lock(&fx->lib->lock); 156141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune pthread_mutex_unlock(&gLibLock); 157141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune 158141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune if ((*fx->subItfe)->process_reverse != NULL) { 159141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune ret = (*fx->subItfe)->process_reverse(fx->subItfe, inBuffer, outBuffer); 160141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune } else { 161141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune ret = -ENOSYS; 16286cdb704174828b8e91e94132a19634e3c11d87dVincent Lejeune } 16386cdb704174828b8e91e94132a19634e3c11d87dVincent Lejeune pthread_mutex_unlock(&fx->lib->lock); 164141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune return ret; 165141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune} 166141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune 167141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune 168141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeuneconst struct effect_interface_s gInterface = { 169141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune Effect_Process, 170141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune Effect_Command, 171141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune Effect_GetDescriptor, 172141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune NULL 173141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune}; 174141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune 175141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeuneconst struct effect_interface_s gInterfaceWithReverse = { 176141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune Effect_Process, 177141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune Effect_Command, 178f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard Effect_GetDescriptor, 179f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard Effect_ProcessReverse 1803ff0abfaabc2c7f604d490be587b9c27e7c91ac0Tom Stellard}; 181f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard 182f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard///////////////////////////////////////////////// 183f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard// Effect Factory Interface functions 184f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard///////////////////////////////////////////////// 185f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard 186f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellardint EffectQueryNumberEffects(uint32_t *pNumEffects) 187f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard{ 188f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard int ret = init(); 189f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard if (ret < 0) { 190f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard return ret; 191f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard } 192f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard if (pNumEffects == NULL) { 193f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard return -EINVAL; 194f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard } 195f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard 196f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard pthread_mutex_lock(&gLibLock); 197f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard *pNumEffects = gNumEffects; 198f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard gCanQueryEffect = 1; 199f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard pthread_mutex_unlock(&gLibLock); 200f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard ALOGV("EffectQueryNumberEffects(): %d", *pNumEffects); 201f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard return ret; 202f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard} 203f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellard 204f07b5373d7493d29cd758ababf135c2d0d8da127Tom Stellardint EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) 205e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard{ 206e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard int ret = init(); 207e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard if (ret < 0) { 208e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard return ret; 209e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard } 210141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune if (pDescriptor == NULL || 211141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune index >= gNumEffects) { 212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return -EINVAL; 213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 214dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (gCanQueryEffect == 0) { 215f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return -ENOSYS; 216f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 217f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 218f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_lock(&gLibLock); 219f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ret = -ENOENT; 220f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (index < gCurEffectIdx) { 221f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard resetEffectEnumeration(); 222f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 223f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard while (gCurLib) { 224f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (gCurEffect) { 225f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (index == gCurEffectIdx) { 226f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard *pDescriptor = *(effect_descriptor_t *)gCurEffect->object; 227f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ret = 0; 228dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines break; 229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } else { 230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines gCurEffect = gCurEffect->next; 231f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard gCurEffectIdx++; 232f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 23329a651af8a4b522daf1f9102c93e4c8ecc2ef3c2Matt Arsenault } else { 234f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard gCurLib = gCurLib->next; 235f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard gCurEffect = ((lib_entry_t *)gCurLib->object)->effects; 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 237f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 238f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 239f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#if (LOG_NDEBUG == 0) 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char str[256]; 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines dumpEffectDescriptor(pDescriptor, str, 256); 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ALOGV("EffectQueryEffect() desc:%s", str); 243f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#endif 244f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_unlock(&gLibLock); 245f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return ret; 2468305cae0045f804b7cca7c69f83f20ad847817bdMatt Arsenault} 247f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 248f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardint EffectGetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) 2498305cae0045f804b7cca7c69f83f20ad847817bdMatt Arsenault{ 250f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard lib_entry_t *l = NULL; 251f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard effect_descriptor_t *d = NULL; 252f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 253f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard int ret = init(); 254f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (ret < 0) { 255f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return ret; 256f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 257f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (pDescriptor == NULL || uuid == NULL) { 258f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return -EINVAL; 259f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 260f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_lock(&gLibLock); 261f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ret = findEffect(NULL, uuid, &l, &d); 262f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (ret == 0) { 263f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard *pDescriptor = *d; 264f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 265f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_unlock(&gLibLock); 266f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard return ret; 2674d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konig} 2684d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konig 2694d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konigint EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle) 270f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard{ 271f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard list_elem_t *e = gLibraryList; 272f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard lib_entry_t *l = NULL; 273f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard effect_descriptor_t *d = NULL; 274f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard effect_handle_t itfe; 275f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard effect_entry_t *fx; 276f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard int found = 0; 277f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard int ret; 278f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 27936ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard if (uuid == NULL || pHandle == NULL) { 28036ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard return -EINVAL; 28136ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard } 282f9e5c398119a77202dc0f7861f5131a7b9f7b8b3Tom Stellard 283f9e5c398119a77202dc0f7861f5131a7b9f7b8b3Tom Stellard ALOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n", 284f9e5c398119a77202dc0f7861f5131a7b9f7b8b3Tom Stellard uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, 28536ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2], 28636ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard uuid->node[3],uuid->node[4],uuid->node[5]); 28736ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard 288f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ret = init(); 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 290f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (ret < 0) { 29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ALOGW("EffectCreate() init error: %d", ret); 29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ret; 293f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard } 294f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 295f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard pthread_mutex_lock(&gLibLock); 296f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard 297f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard ret = findEffect(NULL, uuid, &l, &d); 298f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (ret < 0){ 299f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard // Sub effects are not associated with the library->effects, 300f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard // so, findEffect will fail. Search for the effect in gSubEffectList. 30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ret = findSubEffect(uuid, &l, &d); 30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ret < 0 ) { 303f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard goto exit; 30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 305dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 306cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 307cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // create effect in library 308cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe); 309cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (ret != 0) { 310cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines ALOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret); 311cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines goto exit; 312cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 313cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 314cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // add entry to effect list 315cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines fx = (effect_entry_t *)malloc(sizeof(effect_entry_t)); 316cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines fx->subItfe = itfe; 317cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if ((*itfe)->process_reverse != NULL) { 318cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines fx->itfe = (struct effect_interface_s *)&gInterfaceWithReverse; 31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ALOGV("EffectCreate() gInterfaceWithReverse"); 32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fx->itfe = (struct effect_interface_s *)&gInterface; 32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ALOGV("EffectCreate() gInterface"); 32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fx->lib = l; 325cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 3269a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard e = (list_elem_t *)malloc(sizeof(list_elem_t)); 3279a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard e->object = fx; 3289a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard e->next = gEffectList; 3299a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard gEffectList = e; 3309a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard 3319a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard *pHandle = (effect_handle_t)fx; 3329a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard 3339a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard ALOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pHandle, itfe, l->name); 3349a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard 33554328c772c5519e56c13667c2b1d1e830580c44dTom Stellardexit: 33654328c772c5519e56c13667c2b1d1e830580c44dTom Stellard pthread_mutex_unlock(&gLibLock); 337cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ret; 33854328c772c5519e56c13667c2b1d1e830580c44dTom Stellard} 33954328c772c5519e56c13667c2b1d1e830580c44dTom Stellard 340cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesint EffectRelease(effect_handle_t handle) 34154328c772c5519e56c13667c2b1d1e830580c44dTom Stellard{ 34254328c772c5519e56c13667c2b1d1e830580c44dTom Stellard effect_entry_t *fx; 343cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines list_elem_t *e1; 34454328c772c5519e56c13667c2b1d1e830580c44dTom Stellard list_elem_t *e2; 345cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 34654328c772c5519e56c13667c2b1d1e830580c44dTom Stellard int ret = init(); 347a3e39dc7055486cbf514ccd868cfabc69d7f6f4eMichel Danzer if (ret < 0) { 348cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ret; 349cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 350cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 351cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // remove effect from effect list 352cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines pthread_mutex_lock(&gLibLock); 353cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines e1 = gEffectList; 354cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines e2 = NULL; 355cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines while (e1) { 356cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (e1->object == handle) { 357cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (e2) { 358cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines e2->next = e1->next; 359cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } else { 360cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines gEffectList = e1->next; 361cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 362a3e39dc7055486cbf514ccd868cfabc69d7f6f4eMichel Danzer fx = (effect_entry_t *)e1->object; 36354328c772c5519e56c13667c2b1d1e830580c44dTom Stellard free(e1); 364cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines break; 365cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 366cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines e2 = e1; 367cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines e1 = e1->next; 368a3e39dc7055486cbf514ccd868cfabc69d7f6f4eMichel Danzer } 369cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (e1 == NULL) { 3709a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard ret = -ENOENT; 371a3e39dc7055486cbf514ccd868cfabc69d7f6f4eMichel Danzer pthread_mutex_unlock(&gLibLock); 37254328c772c5519e56c13667c2b1d1e830580c44dTom Stellard goto exit; 3739a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard } 3749a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard 3759a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard // release effect in library 376f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard if (fx->lib == NULL) { 377 ALOGW("EffectRelease() fx %p library already unloaded", handle); 378 pthread_mutex_unlock(&gLibLock); 379 } else { 380 pthread_mutex_lock(&fx->lib->lock); 381 // Releasing the gLibLock here as the list access is over as the 382 // effect is removed from the list. 383 // If the gLibLock is not released, we will have a deadlock situation 384 // since we call the sub effect release inside the EffectRelease of Proxy 385 pthread_mutex_unlock(&gLibLock); 386 fx->lib->desc->release_effect(fx->subItfe); 387 pthread_mutex_unlock(&fx->lib->lock); 388 } 389 free(fx); 390 391exit: 392 return ret; 393} 394 395int EffectIsNullUuid(const effect_uuid_t *uuid) 396{ 397 if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) { 398 return 0; 399 } 400 return 1; 401} 402 403// Function to get the sub effect descriptors of the effect whose uuid 404// is pointed by the first argument. It searches the gSubEffectList for the 405// matching uuid and then copies the corresponding sub effect descriptors 406// to the inout param 407int EffectGetSubEffects(const effect_uuid_t *uuid, 408 effect_descriptor_t *pDescriptors, size_t size) 409{ 410 ALOGV("EffectGetSubEffects() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X" 411 "%02X\n",uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, 412 uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2], 413 uuid->node[3],uuid->node[4],uuid->node[5]); 414 415 // Check if the size of the desc buffer is large enough for 2 subeffects 416 if ((uuid == NULL) || (pDescriptors == NULL) || 417 (size < 2*sizeof(effect_descriptor_t))) { 418 ALOGW("NULL pointer or insufficient memory. Cannot query subeffects"); 419 return -EINVAL; 420 } 421 int ret = init(); 422 if (ret < 0) 423 return ret; 424 list_sub_elem_t *e = gSubEffectList; 425 sub_effect_entry_t *subeffect; 426 effect_descriptor_t *d; 427 int count = 0; 428 while (e != NULL) { 429 d = (effect_descriptor_t*)e->object; 430 if (memcmp(uuid, &d->uuid, sizeof(effect_uuid_t)) == 0) { 431 ALOGV("EffectGetSubEffects: effect found in the list"); 432 list_elem_t *subefx = e->sub_elem; 433 while (subefx != NULL) { 434 subeffect = (sub_effect_entry_t*)subefx->object; 435 d = (effect_descriptor_t*)(subeffect->object); 436 pDescriptors[count++] = *d; 437 subefx = subefx->next; 438 } 439 ALOGV("EffectGetSubEffects end - copied the sub effect descriptors"); 440 return count; 441 } 442 e = e->next; 443 } 444 return -ENOENT; 445} 446///////////////////////////////////////////////// 447// Local functions 448///////////////////////////////////////////////// 449 450int init() { 451 int hdl; 452 453 if (gInitDone) { 454 return 0; 455 } 456 457 pthread_mutex_init(&gLibLock, NULL); 458 459 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) { 460 loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE); 461 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) { 462 loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE); 463 } 464 465 updateNumEffects(); 466 gInitDone = 1; 467 ALOGV("init() done"); 468 return 0; 469} 470 471int loadEffectConfigFile(const char *path) 472{ 473 cnode *root; 474 char *data; 475 476 data = load_file(path, NULL); 477 if (data == NULL) { 478 return -ENODEV; 479 } 480 root = config_node("", ""); 481 config_load(root, data); 482 loadLibraries(root); 483 loadEffects(root); 484 config_free(root); 485 free(root); 486 free(data); 487 488 return 0; 489} 490 491int loadLibraries(cnode *root) 492{ 493 cnode *node; 494 495 node = config_find(root, LIBRARIES_TAG); 496 if (node == NULL) { 497 return -ENOENT; 498 } 499 node = node->first_child; 500 while (node) { 501 loadLibrary(node, node->name); 502 node = node->next; 503 } 504 return 0; 505} 506 507int loadLibrary(cnode *root, const char *name) 508{ 509 cnode *node; 510 void *hdl; 511 audio_effect_library_t *desc; 512 list_elem_t *e; 513 lib_entry_t *l; 514 515 node = config_find(root, PATH_TAG); 516 if (node == NULL) { 517 return -EINVAL; 518 } 519 520 hdl = dlopen(node->value, RTLD_NOW); 521 if (hdl == NULL) { 522 ALOGW("loadLibrary() failed to open %s", node->value); 523 goto error; 524 } 525 526 desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); 527 if (desc == NULL) { 528 ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); 529 goto error; 530 } 531 532 if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) { 533 ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag); 534 goto error; 535 } 536 537 if (EFFECT_API_VERSION_MAJOR(desc->version) != 538 EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) { 539 ALOGW("loadLibrary() bad lib version %08x", desc->version); 540 goto error; 541 } 542 543 // add entry for library in gLibraryList 544 l = malloc(sizeof(lib_entry_t)); 545 l->name = strndup(name, PATH_MAX); 546 l->path = strndup(node->value, PATH_MAX); 547 l->handle = hdl; 548 l->desc = desc; 549 l->effects = NULL; 550 pthread_mutex_init(&l->lock, NULL); 551 552 e = malloc(sizeof(list_elem_t)); 553 e->object = l; 554 pthread_mutex_lock(&gLibLock); 555 e->next = gLibraryList; 556 gLibraryList = e; 557 pthread_mutex_unlock(&gLibLock); 558 ALOGV("getLibrary() linked library %p for path %s", l, node->value); 559 560 return 0; 561 562error: 563 if (hdl != NULL) { 564 dlclose(hdl); 565 } 566 return -EINVAL; 567} 568 569// This will find the library and UUID tags of the sub effect pointed by the 570// node, gets the effect descriptor and lib_entry_t and adds the subeffect - 571// sub_entry_t to the gSubEffectList 572int addSubEffect(cnode *root) 573{ 574 ALOGV("addSubEffect"); 575 cnode *node; 576 effect_uuid_t uuid; 577 effect_descriptor_t *d; 578 lib_entry_t *l; 579 list_elem_t *e; 580 node = config_find(root, LIBRARY_TAG); 581 if (node == NULL) { 582 return -EINVAL; 583 } 584 l = getLibrary(node->value); 585 if (l == NULL) { 586 ALOGW("addSubEffect() could not get library %s", node->value); 587 return -EINVAL; 588 } 589 node = config_find(root, UUID_TAG); 590 if (node == NULL) { 591 return -EINVAL; 592 } 593 if (stringToUuid(node->value, &uuid) != 0) { 594 ALOGW("addSubEffect() invalid uuid %s", node->value); 595 return -EINVAL; 596 } 597 d = malloc(sizeof(effect_descriptor_t)); 598 if (l->desc->get_descriptor(&uuid, d) != 0) { 599 char s[40]; 600 uuidToString(&uuid, s, 40); 601 ALOGW("Error querying effect %s on lib %s", s, l->name); 602 free(d); 603 return -EINVAL; 604 } 605#if (LOG_NDEBUG==0) 606 char s[256]; 607 dumpEffectDescriptor(d, s, 256); 608 ALOGV("addSubEffect() read descriptor %p:%s",d, s); 609#endif 610 if (EFFECT_API_VERSION_MAJOR(d->apiVersion) != 611 EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) { 612 ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name); 613 free(d); 614 return -EINVAL; 615 } 616 sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t)); 617 sub_effect->object = d; 618 // lib_entry_t is stored since the sub effects are not linked to the library 619 sub_effect->lib = l; 620 e = malloc(sizeof(list_elem_t)); 621 e->object = sub_effect; 622 e->next = gSubEffectList->sub_elem; 623 gSubEffectList->sub_elem = e; 624 ALOGV("addSubEffect end"); 625 return 0; 626} 627 628int loadEffects(cnode *root) 629{ 630 cnode *node; 631 632 node = config_find(root, EFFECTS_TAG); 633 if (node == NULL) { 634 return -ENOENT; 635 } 636 node = node->first_child; 637 while (node) { 638 loadEffect(node); 639 node = node->next; 640 } 641 return 0; 642} 643 644int loadEffect(cnode *root) 645{ 646 cnode *node; 647 effect_uuid_t uuid; 648 lib_entry_t *l; 649 effect_descriptor_t *d; 650 list_elem_t *e; 651 652 node = config_find(root, LIBRARY_TAG); 653 if (node == NULL) { 654 return -EINVAL; 655 } 656 657 l = getLibrary(node->value); 658 if (l == NULL) { 659 ALOGW("loadEffect() could not get library %s", node->value); 660 return -EINVAL; 661 } 662 663 node = config_find(root, UUID_TAG); 664 if (node == NULL) { 665 return -EINVAL; 666 } 667 if (stringToUuid(node->value, &uuid) != 0) { 668 ALOGW("loadEffect() invalid uuid %s", node->value); 669 return -EINVAL; 670 } 671 672 d = malloc(sizeof(effect_descriptor_t)); 673 if (l->desc->get_descriptor(&uuid, d) != 0) { 674 char s[40]; 675 uuidToString(&uuid, s, 40); 676 ALOGW("Error querying effect %s on lib %s", s, l->name); 677 free(d); 678 return -EINVAL; 679 } 680#if (LOG_NDEBUG==0) 681 char s[256]; 682 dumpEffectDescriptor(d, s, 256); 683 ALOGV("loadEffect() read descriptor %p:%s",d, s); 684#endif 685 if (EFFECT_API_VERSION_MAJOR(d->apiVersion) != 686 EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) { 687 ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name); 688 free(d); 689 return -EINVAL; 690 } 691 e = malloc(sizeof(list_elem_t)); 692 e->object = d; 693 e->next = l->effects; 694 l->effects = e; 695 696 // After the UUID node in the config_tree, if node->next is valid, 697 // that would be sub effect node. 698 // Find the sub effects and add them to the gSubEffectList 699 node = node->next; 700 int count = 2; 701 bool hwSubefx = false, swSubefx = false; 702 list_sub_elem_t *sube = NULL; 703 if (node != NULL) { 704 ALOGV("Adding the effect to gEffectSubList as there are sub effects"); 705 sube = malloc(sizeof(list_sub_elem_t)); 706 sube->object = d; 707 sube->sub_elem = NULL; 708 sube->next = gSubEffectList; 709 gSubEffectList = sube; 710 } 711 while (node != NULL && count) { 712 if (addSubEffect(node)) { 713 ALOGW("loadEffect() could not add subEffect %s", node->value); 714 // Change the gSubEffectList to point to older list; 715 gSubEffectList = sube->next; 716 free(sube->sub_elem);// Free an already added sub effect 717 sube->sub_elem = NULL; 718 free(sube); 719 return -ENOENT; 720 } 721 sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object; 722 effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object); 723 // Since we return a dummy descriptor for the proxy during 724 // get_descriptor call,we replace it with the correspoding 725 // sw effect descriptor, but with Proxy UUID 726 // check for Sw desc 727 if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) == 728 EFFECT_FLAG_HW_ACC_TUNNEL)) { 729 swSubefx = true; 730 *d = *subEffectDesc; 731 d->uuid = uuid; 732 ALOGV("loadEffect() Changed the Proxy desc"); 733 } else 734 hwSubefx = true; 735 count--; 736 node = node->next; 737 } 738 // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc 739 if (hwSubefx && swSubefx) { 740 d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED; 741 } 742 return 0; 743} 744 745// Searches the sub effect matching to the specified uuid 746// in the gSubEffectList. It gets the lib_entry_t for 747// the matched sub_effect . Used in EffectCreate of sub effects 748int findSubEffect(const effect_uuid_t *uuid, 749 lib_entry_t **lib, 750 effect_descriptor_t **desc) 751{ 752 list_sub_elem_t *e = gSubEffectList; 753 list_elem_t *subefx; 754 sub_effect_entry_t *effect; 755 lib_entry_t *l = NULL; 756 effect_descriptor_t *d = NULL; 757 int found = 0; 758 int ret = 0; 759 760 if (uuid == NULL) 761 return -EINVAL; 762 763 while (e != NULL && !found) { 764 subefx = (list_elem_t*)(e->sub_elem); 765 while (subefx != NULL) { 766 effect = (sub_effect_entry_t*)subefx->object; 767 l = (lib_entry_t *)effect->lib; 768 d = (effect_descriptor_t *)effect->object; 769 if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 770 ALOGV("uuid matched"); 771 found = 1; 772 break; 773 } 774 subefx = subefx->next; 775 } 776 e = e->next; 777 } 778 if (!found) { 779 ALOGV("findSubEffect() effect not found"); 780 ret = -ENOENT; 781 } else { 782 ALOGV("findSubEffect() found effect: %s in lib %s", d->name, l->name); 783 *lib = l; 784 if (desc != NULL) { 785 *desc = d; 786 } 787 } 788 return ret; 789} 790 791lib_entry_t *getLibrary(const char *name) 792{ 793 list_elem_t *e; 794 795 if (gCachedLibrary && 796 !strncmp(gCachedLibrary->name, name, PATH_MAX)) { 797 return gCachedLibrary; 798 } 799 800 e = gLibraryList; 801 while (e) { 802 lib_entry_t *l = (lib_entry_t *)e->object; 803 if (!strcmp(l->name, name)) { 804 gCachedLibrary = l; 805 return l; 806 } 807 e = e->next; 808 } 809 810 return NULL; 811} 812 813 814void resetEffectEnumeration() 815{ 816 gCurLib = gLibraryList; 817 gCurEffect = NULL; 818 if (gCurLib) { 819 gCurEffect = ((lib_entry_t *)gCurLib->object)->effects; 820 } 821 gCurEffectIdx = 0; 822} 823 824uint32_t updateNumEffects() { 825 list_elem_t *e; 826 uint32_t cnt = 0; 827 828 resetEffectEnumeration(); 829 830 e = gLibraryList; 831 while (e) { 832 lib_entry_t *l = (lib_entry_t *)e->object; 833 list_elem_t *efx = l->effects; 834 while (efx) { 835 cnt++; 836 efx = efx->next; 837 } 838 e = e->next; 839 } 840 gNumEffects = cnt; 841 gCanQueryEffect = 0; 842 return cnt; 843} 844 845int findEffect(const effect_uuid_t *type, 846 const effect_uuid_t *uuid, 847 lib_entry_t **lib, 848 effect_descriptor_t **desc) 849{ 850 list_elem_t *e = gLibraryList; 851 lib_entry_t *l = NULL; 852 effect_descriptor_t *d = NULL; 853 int found = 0; 854 int ret = 0; 855 856 while (e && !found) { 857 l = (lib_entry_t *)e->object; 858 list_elem_t *efx = l->effects; 859 while (efx) { 860 d = (effect_descriptor_t *)efx->object; 861 if (type != NULL && memcmp(&d->type, type, sizeof(effect_uuid_t)) == 0) { 862 found = 1; 863 break; 864 } 865 if (uuid != NULL && memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 866 found = 1; 867 break; 868 } 869 efx = efx->next; 870 } 871 e = e->next; 872 } 873 if (!found) { 874 ALOGV("findEffect() effect not found"); 875 ret = -ENOENT; 876 } else { 877 ALOGV("findEffect() found effect: %s in lib %s", d->name, l->name); 878 *lib = l; 879 if (desc) { 880 *desc = d; 881 } 882 } 883 884 return ret; 885} 886 887void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) { 888 char s[256]; 889 890 snprintf(str, len, "\nEffect Descriptor %p:\n", desc); 891 strncat(str, "- TYPE: ", len); 892 uuidToString(&desc->uuid, s, 256); 893 snprintf(str, len, "- UUID: %s\n", s); 894 uuidToString(&desc->type, s, 256); 895 snprintf(str, len, "- TYPE: %s\n", s); 896 sprintf(s, "- apiVersion: %08X\n- flags: %08X\n", 897 desc->apiVersion, desc->flags); 898 strncat(str, s, len); 899 sprintf(s, "- name: %s\n", desc->name); 900 strncat(str, s, len); 901 sprintf(s, "- implementor: %s\n", desc->implementor); 902 strncat(str, s, len); 903} 904 905int stringToUuid(const char *str, effect_uuid_t *uuid) 906{ 907 int tmp[10]; 908 909 if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", 910 tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) { 911 return -EINVAL; 912 } 913 uuid->timeLow = (uint32_t)tmp[0]; 914 uuid->timeMid = (uint16_t)tmp[1]; 915 uuid->timeHiAndVersion = (uint16_t)tmp[2]; 916 uuid->clockSeq = (uint16_t)tmp[3]; 917 uuid->node[0] = (uint8_t)tmp[4]; 918 uuid->node[1] = (uint8_t)tmp[5]; 919 uuid->node[2] = (uint8_t)tmp[6]; 920 uuid->node[3] = (uint8_t)tmp[7]; 921 uuid->node[4] = (uint8_t)tmp[8]; 922 uuid->node[5] = (uint8_t)tmp[9]; 923 924 return 0; 925} 926 927int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen) 928{ 929 930 snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", 931 uuid->timeLow, 932 uuid->timeMid, 933 uuid->timeHiAndVersion, 934 uuid->clockSeq, 935 uuid->node[0], 936 uuid->node[1], 937 uuid->node[2], 938 uuid->node[3], 939 uuid->node[4], 940 uuid->node[5]); 941 942 return 0; 943} 944 945