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