1b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
2b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Copyright (C) 2011 The Android Open Source Project
3b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande *
4b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Licensed under the Apache License, Version 2.0 (the "License");
5b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * you may not use this file except in compliance with the License.
6b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * You may obtain a copy of the License at
7b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande *
8b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande *      http://www.apache.org/licenses/LICENSE-2.0
9b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande *
10b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Unless required by applicable law or agreed to in writing, software
11b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * distributed under the License is distributed on an "AS IS" BASIS,
12b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * See the License for the specific language governing permissions and
14b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * limitations under the License.
15b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
16b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
17b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define LOG_TAG "nv_offload_visualizer"
18b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande//#define LOG_NDEBUG 1
19b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <assert.h>
20b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <math.h>
21b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <stdlib.h>
22b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <string.h>
23b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <time.h>
24b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <sys/prctl.h>
25b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
26b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <cutils/list.h>
27b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <cutils/log.h>
28b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <system/thread_defs.h>
29b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <tinyalsa/asoundlib.h>
30b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#include <audio_effects/effect_visualizer.h>
31b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
32b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
33b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeenum {
34b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    EFFECT_STATE_UNINITIALIZED,
35b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    EFFECT_STATE_INITIALIZED,
36b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    EFFECT_STATE_ACTIVE,
37b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
38b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
39b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct effect_context_s effect_context_t;
40b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct output_context_s output_context_t;
41b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
42b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* effect specific operations. Only the init() and process() operations must be defined.
43b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Others are optional.
44b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
45b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct effect_ops_s {
46b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*init)(effect_context_t *context);
47b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*release)(effect_context_t *context);
48b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*reset)(effect_context_t *context);
49b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*enable)(effect_context_t *context);
50b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*disable)(effect_context_t *context);
51b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*start)(effect_context_t *context, output_context_t *output);
52b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*stop)(effect_context_t *context, output_context_t *output);
53b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*process)(effect_context_t *context, audio_buffer_t *in, audio_buffer_t *out);
54b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*set_parameter)(effect_context_t *context, effect_param_t *param, uint32_t size);
55b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*get_parameter)(effect_context_t *context, effect_param_t *param, uint32_t *size);
56b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int (*command)(effect_context_t *context, uint32_t cmdCode, uint32_t cmdSize,
57b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            void *pCmdData, uint32_t *replySize, void *pReplyData);
58b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande} effect_ops_t;
59b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
60b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandestruct effect_context_s {
61b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    const struct effect_interface_s *itfe;
62b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode effects_list_node;
63b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode output_node;
64b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_config_t config;
65b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    const effect_descriptor_t *desc;
66b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    audio_io_handle_t out_handle;  /* io handle of the output the effect is attached to */
67b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t state;
68b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    bool offload_enabled;  /* when offload is enabled we process VISUALIZER_CMD_CAPTURE command.
69b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                              Otherwise non offloaded visualizer has already processed the command
70b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                              and we must not overwrite the reply. */
71b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_ops_t ops;
72b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
73b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
74b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct output_context_s {
75b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode outputs_list_node;  /* node in active_outputs_list */
76b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    audio_io_handle_t handle; /* io handle */
77b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode effects_list; /* list of effects attached to this output */
78b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande} output_context_t;
79b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
80b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
81b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* maximum time since last capture buffer update before resetting capture buffer. This means
82b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande  that the framework has stopped playing audio and we must start returning silence */
83b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define MAX_STALL_TIME_MS 1000
84b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
85b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define CAPTURE_BUF_SIZE 65536 /* "64k should be enough for everyone" */
86b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
87b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define DISCARD_MEASUREMENTS_TIME_MS 2000 /* discard measurements older than this number of ms */
88b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
89b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* maximum number of buffers for which we keep track of the measurements */
90b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 /* note: buffer index is stored in uint8_t */
91b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
92b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct buffer_stats_s {
93b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    bool is_valid;
94b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint16_t peak_u16; /* the positive peak of the absolute value of the samples in a buffer */
95b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    float rms_squared; /* the average square of the samples in a buffer */
96b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande} buffer_stats_t;
97b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
98b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandetypedef struct visualizer_context_s {
99b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t common;
100b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
101b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t capture_idx;
102b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t capture_size;
103b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t scaling_mode;
104b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t last_capture_idx;
105b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t latency;
106b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct timespec buffer_update_time;
107b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint8_t capture_buf[CAPTURE_BUF_SIZE];
108b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    /* for measurements */
109b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint8_t channel_count; /* to avoid recomputing it every time a buffer is processed */
110b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t meas_mode;
111b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint8_t meas_wndw_size_in_buffers;
112b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint8_t meas_buffer_idx;
113b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    buffer_stats_t past_meas[MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS];
114b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande} visualizer_context_t;
115b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
116b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
117b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeextern const struct effect_interface_s effect_interface;
118b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
119b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* Visualizer UUID: 09f673c0-10bc-11e4-9589-0002a5d5c51b */
120b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeconst effect_descriptor_t visualizer_descriptor = {
121b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
122b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        {0x09f673c0, 0x10bc, 0x11e4, 0x9589, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
123b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        EFFECT_CONTROL_API_VERSION,
124b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_HW_ACC_TUNNEL ),
125b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        0,
126b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        1,
127b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        "Nvidia offload visualizer",
128b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        "The Android Open Source Project",
129b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
130b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
131b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeconst effect_descriptor_t *descriptors[] = {
132b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        &visualizer_descriptor,
133b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        NULL,
134b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
135b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
136b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
137b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandepthread_once_t once = PTHREAD_ONCE_INIT;
138b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint init_status;
139b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
140b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* list of created effects. Updated by visualizer_hal_start_output()
141b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * and visualizer_hal_stop_output() */
142b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandestruct listnode created_effects_list;
143b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* list of active output streams. Updated by visualizer_hal_start_output()
144b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * and visualizer_hal_stop_output() */
145b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandestruct listnode active_outputs_list;
146b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
147b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* thread capturing PCM from Proxy port and calling the process function on each enabled effect
148b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * attached to an active output stream */
149b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandepthread_t capture_thread;
150b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* lock must be held when modifying or accessing created_effects_list or active_outputs_list */
151b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandepthread_mutex_t lock;
152b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* thread_lock must be held when starting or stopping the capture thread.
153b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Locking order: thread_lock -> lock */
154b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandepthread_mutex_t thread_lock;
155b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* cond is signaled when an output is started or stopped or an effect is enabled or disable: the
156b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * capture thread will reevaluate the capture and effect rocess conditions. */
157b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandepthread_cond_t cond;
158b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* true when requesting the capture thread to exit */
159b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandebool exit_thread;
160b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* 0 if the capture thread was created successfully */
161b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint thread_status;
162b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
163fdd377e0329fd38076966332c14d5dd6d0750f59Xia Yang#define SOUND_CARD 0
164b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define CAPTURE_DEVICE 8 /* Effects capture node */
165b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
166b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define AUDIO_CAPTURE_CHANNEL_COUNT 2
167b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define AUDIO_CAPTURE_SMP_RATE 48000
168b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande#define AUDIO_CAPTURE_PERIOD_SIZE 1024
169b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandestruct pcm_config pcm_config_capture = {
170b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .channels = AUDIO_CAPTURE_CHANNEL_COUNT,
171b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .rate = AUDIO_CAPTURE_SMP_RATE,
172b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .period_size = AUDIO_CAPTURE_PERIOD_SIZE,
173b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .period_count = 4,
174b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .format = PCM_FORMAT_S16_LE,
175b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .start_threshold = 4095,
176b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .stop_threshold = 4096,
177b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    .avail_min = 1,
178b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
179b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
180b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
181b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande *  Local functions
182b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
183b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
184b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandestatic void init_once() {
185b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_init(&created_effects_list);
186b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_init(&active_outputs_list);
187b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
188b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_init(&lock, NULL);
189b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_init(&thread_lock, NULL);
190b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_cond_init(&cond, NULL);
191b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    exit_thread = false;
192b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    thread_status = -1;
193b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
194b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    init_status = 0;
195b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
196b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
197b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint lib_init() {
198b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_once(&once, init_once);
199b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return init_status;
200b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
201b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
202b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandebool effect_exists(effect_context_t *context) {
203b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *node;
204b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
205b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(node, &created_effects_list) {
206b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_context_t *fx_ctxt = node_to_item(node,
207b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effect_context_t,
208b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effects_list_node);
209b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (fx_ctxt == context) {
210b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return true;
211b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
212b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
213b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return false;
214b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
215b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
216b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeoutput_context_t *get_output(audio_io_handle_t output) {
217b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *node;
218b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
219b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(node, &active_outputs_list) {
220b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        output_context_t *out_ctxt = node_to_item(node,
221b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                  output_context_t,
222b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                  outputs_list_node);
223b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (out_ctxt->handle == output) {
224b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return out_ctxt;
225b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
226b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
227b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return NULL;
228b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
229b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
230b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandevoid add_effect_to_output(output_context_t * output, effect_context_t *context) {
231b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *fx_node;
232b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
233b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(fx_node, &output->effects_list) {
234b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_context_t *fx_ctxt = node_to_item(fx_node,
235b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effect_context_t,
236b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     output_node);
237b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (fx_ctxt == context)
238b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return;
239b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
240b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_add_tail(&output->effects_list, &context->output_node);
241b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (context->ops.start)
242b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.start(context, output);
243b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
244b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
245b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandevoid remove_effect_from_output(output_context_t * output, effect_context_t *context) {
246b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *fx_node;
247b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
248b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(fx_node, &output->effects_list) {
249b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_context_t *fx_ctxt = node_to_item(fx_node,
250b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effect_context_t,
251b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     output_node);
252b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (fx_ctxt == context) {
253b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (context->ops.stop)
254b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                context->ops.stop(context, output);
255b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            list_remove(&context->output_node);
256b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return;
257b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
258b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
259b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
260b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
261b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandebool effects_enabled() {
262b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *out_node;
263b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
264b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(out_node, &active_outputs_list) {
265b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        struct listnode *fx_node;
266b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        output_context_t *out_ctxt = node_to_item(out_node,
267b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                  output_context_t,
268b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                  outputs_list_node);
269b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
270b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        list_for_each(fx_node, &out_ctxt->effects_list) {
271b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            effect_context_t *fx_ctxt = node_to_item(fx_node,
272b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                         effect_context_t,
273b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                         output_node);
274b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (fx_ctxt->state == EFFECT_STATE_ACTIVE && fx_ctxt->ops.process != NULL)
275b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                return true;
276b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
277b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
278b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return false;
279b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
280b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
281b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandevoid *effects_capture_thread_loop(void *arg __unused)
282b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
283b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int16_t data[AUDIO_CAPTURE_PERIOD_SIZE * AUDIO_CAPTURE_CHANNEL_COUNT * sizeof(int16_t)];
284b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    audio_buffer_t buf;
285b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    buf.frameCount = AUDIO_CAPTURE_PERIOD_SIZE;
286b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    buf.s16 = data;
287b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    bool capture_enabled = false;
288b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct pcm *pcm = NULL;
289b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int ret;
290b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int retry_num = 0;
291b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
292b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    prctl(PR_SET_NAME, (unsigned long)"visualizer capture", 0, 0, 0);
293b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
294b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
295b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
296b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    for (;;) {
297b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (exit_thread) {
298b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            break;
299b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
300b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (effects_enabled()) {
301b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (!capture_enabled) {
302b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    pcm = pcm_open(SOUND_CARD, CAPTURE_DEVICE,
303b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                   PCM_IN, &pcm_config_capture);
304b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    if (pcm && !pcm_is_ready(pcm)) {
305b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        ALOGW("%s: %s", __func__, pcm_get_error(pcm));
306b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        pcm_close(pcm);
307b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        pcm = NULL;
308b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    } else {
309b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        capture_enabled = true;
310b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        ALOGD("%s: capture ENABLED", __func__);
311b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    }
312b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
313b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
314b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (capture_enabled) {
315b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                if (pcm != NULL) {
316b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    ALOGD("%s:Closing pcm\n", __func__);
317b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    pcm_close(pcm);
318b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                }
319b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                ALOGD("%s: capture DISABLED", __func__);
320b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                capture_enabled = false;
321b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
322b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pthread_cond_wait(&cond, &lock);
323b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
324b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (!capture_enabled)
325b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            continue;
326b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
327b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        pthread_mutex_unlock(&lock);
328b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ret = pcm_read(pcm, data, sizeof(data));
329b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        pthread_mutex_lock(&lock);
330b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
331b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (ret == 0) {
332b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            struct listnode *out_node;
333b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
334b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            list_for_each(out_node, &active_outputs_list) {
335b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                output_context_t *out_ctxt = node_to_item(out_node,
336b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                          output_context_t,
337b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                          outputs_list_node);
338b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                struct listnode *fx_node;
339b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
340b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                list_for_each(fx_node, &out_ctxt->effects_list) {
341b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    effect_context_t *fx_ctxt = node_to_item(fx_node,
342b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                                effect_context_t,
343b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                                output_node);
344b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    if (fx_ctxt->ops.process != NULL)
345b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        fx_ctxt->ops.process(fx_ctxt, &buf, &buf);
346b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                }
347b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
348b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
349b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            ALOGW("%s: read status %d %s", __func__, ret, pcm_get_error(pcm));
350b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
351b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
352b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
353b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (capture_enabled) {
354b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pcm != NULL)
355b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pcm_close(pcm);
356b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
357b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
358b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
359b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ALOGD("thread exit");
360b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
361b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return NULL;
362b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
363b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
364b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
365b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Interface from audio HAL
366b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
367b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
368b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande__attribute__ ((visibility ("default")))
369b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_hal_start_output(audio_io_handle_t output, int pcm_id) {
370b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int ret;
371b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *node;
372b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
373b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
374b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
375b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (lib_init() != 0)
376b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return init_status;
377b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
378b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&thread_lock);
379b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
380b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (get_output(output) != NULL) {
381b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGE("%s output already started", __func__);
382b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ret = -ENOSYS;
383b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
384b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
385b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
386b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    output_context_t *out_ctxt = (output_context_t *)malloc(sizeof(output_context_t));
387b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    out_ctxt->handle = output;
388b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_init(&out_ctxt->effects_list);
389b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
390b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(node, &created_effects_list) {
391b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_context_t *fx_ctxt = node_to_item(node,
392b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effect_context_t,
393b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                     effects_list_node);
394b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (fx_ctxt->out_handle == output) {
395b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (fx_ctxt->ops.start)
396b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                fx_ctxt->ops.start(fx_ctxt, out_ctxt);
397b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            list_add_tail(&out_ctxt->effects_list, &fx_ctxt->output_node);
398b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
399b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
400b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (list_empty(&active_outputs_list)) {
401b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        exit_thread = false;
402b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        thread_status = pthread_create(&capture_thread, (const pthread_attr_t *) NULL,
403b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        effects_capture_thread_loop, NULL);
404b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
405b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_add_tail(&active_outputs_list, &out_ctxt->outputs_list_node);
406b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_cond_signal(&cond);
407b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
408b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeexit:
409b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
410b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&thread_lock);
411b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return ret;
412b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
413b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
414b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande__attribute__ ((visibility ("default")))
415b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_hal_stop_output(audio_io_handle_t output, int pcm_id) {
416b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int ret;
417b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *node;
418b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    struct listnode *fx_node;
419b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    output_context_t *out_ctxt;
420b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
421b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
422b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
423b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (lib_init() != 0)
424b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return init_status;
425b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
426b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&thread_lock);
427b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
428b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
429b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    out_ctxt = get_output(output);
430b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (out_ctxt == NULL) {
431b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGW("%s output not started", __func__);
432b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ret = -ENOSYS;
433b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
434b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
435b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_for_each(fx_node, &out_ctxt->effects_list) {
436b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_context_t *fx_ctxt = node_to_item(fx_node,
437b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                 effect_context_t,
438b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                 output_node);
439b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (fx_ctxt->ops.stop)
440b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
441b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
442b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_remove(&out_ctxt->outputs_list_node);
443b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_cond_signal(&cond);
444b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
445b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (list_empty(&active_outputs_list)) {
446b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (thread_status == 0) {
447b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            exit_thread = true;
448b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pthread_cond_signal(&cond);
449b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pthread_mutex_unlock(&lock);
450b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pthread_join(capture_thread, (void **) NULL);
451b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pthread_mutex_lock(&lock);
452b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            thread_status = -1;
453b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
454b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
455b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
456b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    free(out_ctxt);
457b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
458b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeexit:
459b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
460b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&thread_lock);
461b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return ret;
462b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
463b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
464b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
465b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
466b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Effect operations
467b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
468b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
469b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint set_config(effect_context_t *context, effect_config_t *config)
470b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
471b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate) return -EINVAL;
472b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->inputCfg.channels != config->outputCfg.channels) return -EINVAL;
473b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->inputCfg.format != config->outputCfg.format) return -EINVAL;
474b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL;
475b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
476b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            config->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
477b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
478b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
479b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config = *config;
480b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
481b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (context->ops.reset)
482b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.reset(context);
483b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
484b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
485b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
486b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
487b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandevoid get_config(effect_context_t *context, effect_config_t *config)
488b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
489b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    *config = context->config;
490b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
491b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
492b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
493b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
494b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Visualizer operations
495b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
496b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
497b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeuint32_t visualizer_get_delta_time_ms_from_updated_time(visualizer_context_t* visu_ctxt) {
498b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t delta_ms = 0;
499b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (visu_ctxt->buffer_update_time.tv_sec != 0) {
500b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        struct timespec ts;
501b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
502b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            time_t secs = ts.tv_sec - visu_ctxt->buffer_update_time.tv_sec;
503b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            long nsec = ts.tv_nsec - visu_ctxt->buffer_update_time.tv_nsec;
504b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (nsec < 0) {
505b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                --secs;
506b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                nsec += 1000000000;
507b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
508b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            delta_ms = secs * 1000 + nsec / 1000000;
509b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
510b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
511b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return delta_ms;
512b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
513b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
514b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_reset(effect_context_t *context)
515b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
516b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
517b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
518b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->capture_idx = 0;
519b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->last_capture_idx = 0;
520b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->buffer_update_time.tv_sec = 0;
521b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->latency = 0;
522b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    memset(visu_ctxt->capture_buf, 0x80, CAPTURE_BUF_SIZE);
523b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
524b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
525b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
526b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_init(effect_context_t *context)
527b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
528b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int32_t i;
529b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
530b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
531b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
532b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
533b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
534b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
535b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.samplingRate = 44100;
536b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.bufferProvider.getBuffer = NULL;
537b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.bufferProvider.releaseBuffer = NULL;
538b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.bufferProvider.cookie = NULL;
539b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.inputCfg.mask = EFFECT_CONFIG_ALL;
540b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
541b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
542b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
543b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.samplingRate = 44100;
544b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.bufferProvider.getBuffer = NULL;
545b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.bufferProvider.releaseBuffer = NULL;
546b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.bufferProvider.cookie = NULL;
547b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
548b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
549b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->capture_size = VISUALIZER_CAPTURE_SIZE_MAX;
550b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->scaling_mode = VISUALIZER_SCALING_MODE_NORMALIZED;
551b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
552b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    // measurement initialization
553b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->channel_count = popcount(context->config.inputCfg.channels);
554b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->meas_mode = MEASUREMENT_MODE_NONE;
555b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->meas_wndw_size_in_buffers = MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS;
556b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->meas_buffer_idx = 0;
557b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    for (i=0 ; i<visu_ctxt->meas_wndw_size_in_buffers ; i++) {
558b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[i].is_valid = false;
559b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[i].peak_u16 = 0;
560b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[i].rms_squared = 0;
561b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
562b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
563b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    set_config(context, &context->config);
564b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
565b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
566b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
567b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
568b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_get_parameter(effect_context_t *context, effect_param_t *p, uint32_t *size)
569b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
570b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
571b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
572b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    p->status = 0;
573b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    *size = sizeof(effect_param_t) + sizeof(uint32_t);
574b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (p->psize != sizeof(uint32_t)) {
575b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        p->status = -EINVAL;
576b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return 0;
577b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
578b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    switch (*(uint32_t *)p->data) {
579b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_CAPTURE_SIZE:
580b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s get capture_size = %d", __func__, visu_ctxt->capture_size);
581b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *((uint32_t *)p->data + 1) = visu_ctxt->capture_size;
582b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        p->vsize = sizeof(uint32_t);
583b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *size += sizeof(uint32_t);
584b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
585b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_SCALING_MODE:
586b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s get scaling_mode = %d", __func__, visu_ctxt->scaling_mode);
587b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *((uint32_t *)p->data + 1) = visu_ctxt->scaling_mode;
588b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        p->vsize = sizeof(uint32_t);
589b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *size += sizeof(uint32_t);
590b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
591b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_MEASUREMENT_MODE:
592b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s get meas_mode = %d", __func__, visu_ctxt->meas_mode);
593b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *((uint32_t *)p->data + 1) = visu_ctxt->meas_mode;
594b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        p->vsize = sizeof(uint32_t);
595b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *size += sizeof(uint32_t);
596b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
597b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    default:
598b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        p->status = -EINVAL;
599b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
600b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
601b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
602b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
603b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_set_parameter(effect_context_t *context, effect_param_t *p, uint32_t size __unused)
604b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
605b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
606b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
607b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t))
608b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
609b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
610b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    switch (*(uint32_t *)p->data) {
611b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_CAPTURE_SIZE:
612b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->capture_size = *((uint32_t *)p->data + 1);
613b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s set capture_size = %d", __func__, visu_ctxt->capture_size);
614b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
615b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_SCALING_MODE:
616b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->scaling_mode = *((uint32_t *)p->data + 1);
617b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s set scaling_mode = %d", __func__, visu_ctxt->scaling_mode);
618b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
619b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_LATENCY:
620b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s set latency = %d", __func__, visu_ctxt->latency);
621b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
622b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_PARAM_MEASUREMENT_MODE:
623b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->meas_mode = *((uint32_t *)p->data + 1);
624b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s set meas_mode = %d", __func__, visu_ctxt->meas_mode);
625b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
626b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    default:
627b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
628b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
629b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
630b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
631b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
632b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* Real process function called from capture thread. Called with lock held */
633b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_process(effect_context_t *context,
634b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       audio_buffer_t *inBuffer,
635b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       audio_buffer_t *outBuffer)
636b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
637b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
638b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
639b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (!effect_exists(context))
640b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
641b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
642b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (inBuffer == NULL || inBuffer->raw == NULL ||
643b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        outBuffer == NULL || outBuffer->raw == NULL ||
644b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        inBuffer->frameCount != outBuffer->frameCount ||
645b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        inBuffer->frameCount == 0) {
646b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
647b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
648b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
649b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    // perform measurements if needed
650b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (visu_ctxt->meas_mode & MEASUREMENT_MODE_PEAK_RMS) {
651b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        // find the peak and RMS squared for the new buffer
652b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        uint32_t inIdx;
653b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        int16_t max_sample = 0;
654b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        float rms_squared_acc = 0;
655b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        for (inIdx = 0 ; inIdx < inBuffer->frameCount * visu_ctxt->channel_count ; inIdx++) {
656b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (inBuffer->s16[inIdx] > max_sample) {
657b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                max_sample = inBuffer->s16[inIdx];
658b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            } else if (-inBuffer->s16[inIdx] > max_sample) {
659b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                max_sample = -inBuffer->s16[inIdx];
660b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
661b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            rms_squared_acc += (inBuffer->s16[inIdx] * inBuffer->s16[inIdx]);
662b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
663b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        // store the measurement
664b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].peak_u16 = (uint16_t)max_sample;
665b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].rms_squared =
666b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                rms_squared_acc / (inBuffer->frameCount * visu_ctxt->channel_count);
667b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].is_valid = true;
668b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (++visu_ctxt->meas_buffer_idx >= visu_ctxt->meas_wndw_size_in_buffers) {
669b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            visu_ctxt->meas_buffer_idx = 0;
670b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
671b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
672b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
673b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    /* all code below assumes stereo 16 bit PCM output and input */
674b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int32_t shift;
675b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
676b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (visu_ctxt->scaling_mode == VISUALIZER_SCALING_MODE_NORMALIZED) {
677b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* derive capture scaling factor from peak value in current buffer
678b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         * this gives more interesting captures for display. */
679b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        shift = 32;
680b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        int len = inBuffer->frameCount * 2;
681b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        int i;
682b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        for (i = 0; i < len; i++) {
683b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            int32_t smp = inBuffer->s16[i];
684b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (smp < 0) smp = -smp - 1; /* take care to keep the max negative in range */
685b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            int32_t clz = __builtin_clz(smp);
686b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (shift > clz) shift = clz;
687b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
688b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* A maximum amplitude signal will have 17 leading zeros, which we want to
689b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         * translate to a shift of 8 (for converting 16 bit to 8 bit) */
690b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        shift = 25 - shift;
691b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* Never scale by less than 8 to avoid returning unaltered PCM signal. */
692b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (shift < 3) {
693b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            shift = 3;
694b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
695b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* add one to combine the division by 2 needed after summing
696b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         * left and right channels below */
697b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        shift++;
698b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    } else {
699b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        assert(visu_ctxt->scaling_mode == VISUALIZER_SCALING_MODE_AS_PLAYED);
700b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        shift = 9;
701b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
702b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
703b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t capt_idx;
704b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint32_t in_idx;
705b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    uint8_t *buf = visu_ctxt->capture_buf;
706b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    for (in_idx = 0, capt_idx = visu_ctxt->capture_idx;
707b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         in_idx < inBuffer->frameCount;
708b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         in_idx++, capt_idx++) {
709b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (capt_idx >= CAPTURE_BUF_SIZE) {
710b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            /* wrap around */
711b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            capt_idx = 0;
712b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
713b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        int32_t smp = inBuffer->s16[2 * in_idx] + inBuffer->s16[2 * in_idx + 1];
714b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        smp = smp >> shift;
715b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        buf[capt_idx] = ((uint8_t)smp)^0x80;
716b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
717b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
718b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    /* XXX the following two should really be atomic, though it probably doesn't
719b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande     * matter much for visualization purposes */
720b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visu_ctxt->capture_idx = capt_idx;
721b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    /* update last buffer update time stamp */
722b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (clock_gettime(CLOCK_MONOTONIC, &visu_ctxt->buffer_update_time) < 0) {
723b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visu_ctxt->buffer_update_time.tv_sec = 0;
724b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
725b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
726b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (context->state != EFFECT_STATE_ACTIVE) {
727b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s DONE inactive", __func__);
728b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -ENODATA;
729b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
730b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
731b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
732b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
733b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
734b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint visualizer_command(effect_context_t * context, uint32_t cmdCode, uint32_t cmdSize __unused,
735b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        void *pCmdData __unused, uint32_t *replySize, void *pReplyData)
736b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
737b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
738b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
739b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    switch (cmdCode) {
740b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_CMD_CAPTURE:
741b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pReplyData == NULL || *replySize != visu_ctxt->capture_size) {
742b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            ALOGV("%s VISUALIZER_CMD_CAPTURE error *replySize %d context->capture_size %d",
743b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                  __func__, *replySize, visu_ctxt->capture_size);
744b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return -EINVAL;
745b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
746b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
747b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (!context->offload_enabled)
748b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            break;
749b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
750b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->state == EFFECT_STATE_ACTIVE) {
751b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            int32_t latency_ms = visu_ctxt->latency;
752b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            const uint32_t delta_ms = visualizer_get_delta_time_ms_from_updated_time(visu_ctxt);
753b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            latency_ms -= delta_ms;
754b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (latency_ms < 0) {
755b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                latency_ms = 0;
756b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
757b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            const uint32_t delta_smp = context->config.inputCfg.samplingRate * latency_ms / 1000;
758b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
759b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            int32_t capture_point = visu_ctxt->capture_idx - visu_ctxt->capture_size - delta_smp;
760b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            int32_t capture_size = visu_ctxt->capture_size;
761b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if (capture_point < 0) {
762b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                int32_t size = -capture_point;
763b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                if (size > capture_size)
764b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    size = capture_size;
765b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
766b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                memcpy(pReplyData,
767b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       visu_ctxt->capture_buf + CAPTURE_BUF_SIZE + capture_point,
768b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       size);
769b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                pReplyData = (void *)((size_t)pReplyData + size);
770b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                capture_size -= size;
771b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                capture_point = 0;
772b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
773b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            memcpy(pReplyData,
774b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                   visu_ctxt->capture_buf + capture_point,
775b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                   capture_size);
776b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
777b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
778b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            /* if audio framework has stopped playing audio although the effect is still
779b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande             * active we must clear the capture buffer to return silence */
780b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            if ((visu_ctxt->last_capture_idx == visu_ctxt->capture_idx) &&
781b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    (visu_ctxt->buffer_update_time.tv_sec != 0)) {
782b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                if (delta_ms > MAX_STALL_TIME_MS) {
783b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    ALOGV("%s capture going to idle", __func__);
784b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    visu_ctxt->buffer_update_time.tv_sec = 0;
785b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    memset(pReplyData, 0x80, visu_ctxt->capture_size);
786b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                }
787b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
788b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            visu_ctxt->last_capture_idx = visu_ctxt->capture_idx;
789b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
790b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            memset(pReplyData, 0x80, visu_ctxt->capture_size);
791b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
792b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
793b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
794b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case VISUALIZER_CMD_MEASURE: {
795b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        uint16_t peak_u16 = 0;
796b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        float sum_rms_squared = 0.0f;
797b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        uint8_t nb_valid_meas = 0;
798b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* reset measurements if last measurement was too long ago (which implies stored
799b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande         * measurements aren't relevant anymore and shouldn't bias the new one) */
800b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        const int32_t delay_ms = visualizer_get_delta_time_ms_from_updated_time(visu_ctxt);
801b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (delay_ms > DISCARD_MEASUREMENTS_TIME_MS) {
802b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            uint32_t i;
803b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            ALOGV("Discarding measurements, last measurement is %dms old", delay_ms);
804b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            for (i=0 ; i<visu_ctxt->meas_wndw_size_in_buffers ; i++) {
805b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                visu_ctxt->past_meas[i].is_valid = false;
806b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                visu_ctxt->past_meas[i].peak_u16 = 0;
807b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                visu_ctxt->past_meas[i].rms_squared = 0;
808b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
809b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            visu_ctxt->meas_buffer_idx = 0;
810b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
811b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            /* only use actual measurements, otherwise the first RMS measure happening before
812b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande             * MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
813b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande             * low */
814b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            uint32_t i;
815b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            for (i=0 ; i < visu_ctxt->meas_wndw_size_in_buffers ; i++) {
816b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                if (visu_ctxt->past_meas[i].is_valid) {
817b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    if (visu_ctxt->past_meas[i].peak_u16 > peak_u16) {
818b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                        peak_u16 = visu_ctxt->past_meas[i].peak_u16;
819b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    }
820b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    sum_rms_squared += visu_ctxt->past_meas[i].rms_squared;
821b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                    nb_valid_meas++;
822b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                }
823b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            }
824b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
825b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        float rms = nb_valid_meas == 0 ? 0.0f : sqrtf(sum_rms_squared / nb_valid_meas);
826b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        int32_t* p_int_reply_data = (int32_t*)pReplyData;
827b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        /* convert from I16 sample values to mB and write results */
828b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (rms < 0.000016f) {
829b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            p_int_reply_data[MEASUREMENT_IDX_RMS] = -9600; //-96dB
830b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
831b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            p_int_reply_data[MEASUREMENT_IDX_RMS] = (int32_t) (2000 * log10(rms / 32767.0f));
832b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
833b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (peak_u16 == 0) {
834b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            p_int_reply_data[MEASUREMENT_IDX_PEAK] = -9600; //-96dB
835b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } else {
836b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            p_int_reply_data[MEASUREMENT_IDX_PEAK] = (int32_t) (2000 * log10(peak_u16 / 32767.0f));
837b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
838b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("VISUALIZER_CMD_MEASURE peak=%d (%dmB), rms=%.1f (%dmB)",
839b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                peak_u16, p_int_reply_data[MEASUREMENT_IDX_PEAK],
840b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                rms, p_int_reply_data[MEASUREMENT_IDX_RMS]);
841b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
842b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
843b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
844b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    default:
845b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGW("%s invalid command %d", __func__, cmdCode);
846b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
847b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
848b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
849b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
850b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
851b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
852b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
853b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Effect Library Interface Implementation
854b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
855b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
856b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_lib_create(const effect_uuid_t *uuid,
857b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                         int32_t sessionId __unused,
858b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                         int32_t ioId,
859b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                         effect_handle_t *pHandle) {
860b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int ret;
861b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int i;
862b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
863b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (lib_init() != 0)
864b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return init_status;
865b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
866b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (pHandle == NULL || uuid == NULL)
867b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
868b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
869b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    for (i = 0; descriptors[i] != NULL; i++) {
870b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0)
871b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            break;
872b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
873b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
874b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (descriptors[i] == NULL)
875b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
876b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
877b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t *context;
878b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (memcmp(uuid, &visualizer_descriptor.uuid, sizeof(effect_uuid_t)) == 0) {
879b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        visualizer_context_t *visu_ctxt = (visualizer_context_t *)calloc(1,
880b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                                                     sizeof(visualizer_context_t));
881b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context = (effect_context_t *)visu_ctxt;
882b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.init = visualizer_init;
883b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.reset = visualizer_reset;
884b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.process = visualizer_process;
885b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.set_parameter = visualizer_set_parameter;
886b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.get_parameter = visualizer_get_parameter;
887b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->ops.command = visualizer_command;
888b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->desc = &visualizer_descriptor;
889b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    } else {
890b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
891b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
892b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
893b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->itfe = &effect_interface;
894b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->state = EFFECT_STATE_UNINITIALIZED;
895b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->out_handle = (audio_io_handle_t)ioId;
896b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
897b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ret = context->ops.init(context);
898b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (ret < 0) {
899b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGW("%s init failed", __func__);
900b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        free(context);
901b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return ret;
902b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
903b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
904b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    context->state = EFFECT_STATE_INITIALIZED;
905b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
906b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
907b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    list_add_tail(&created_effects_list, &context->effects_list_node);
908b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    output_context_t *out_ctxt = get_output(ioId);
909b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (out_ctxt != NULL)
910b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        add_effect_to_output(out_ctxt, context);
911b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
912b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
913b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    *pHandle = (effect_handle_t)context;
914b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
915b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ALOGV("%s created context %p", __func__, context);
916b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
917b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
918b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
919b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
920b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
921b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_lib_release(effect_handle_t handle) {
922b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t *context = (effect_context_t *)handle;
923b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int status;
924b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
925b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (lib_init() != 0)
926b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return init_status;
927b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
928b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    ALOGV("%s context %p", __func__, handle);
929b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
930b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    status = -EINVAL;
931b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (effect_exists(context)) {
932b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        output_context_t *out_ctxt = get_output(context->out_handle);
933b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (out_ctxt != NULL)
934b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            remove_effect_from_output(out_ctxt, context);
935b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        list_remove(&context->effects_list_node);
936b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.release)
937b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            context->ops.release(context);
938b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        free(context);
939b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        status = 0;
940b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
941b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
942b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
943b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return status;
944b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
945b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
946b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_lib_get_descriptor(const effect_uuid_t *uuid,
947b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                effect_descriptor_t *descriptor) {
948b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int i;
949b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
950b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (lib_init() != 0)
951b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return init_status;
952b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
953b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (descriptor == NULL || uuid == NULL) {
954b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s called with NULL pointer", __func__);
955b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
956b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
957b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
958b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    for (i = 0; descriptors[i] != NULL; i++) {
959b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
960b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *descriptor = *descriptors[i];
961b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            return 0;
962b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
963b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
964b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
965b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return  -EINVAL;
966b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
967b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
968b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/*
969b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande * Effect Control Interface Implementation
970b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande */
971b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
972b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande /* Stub function for effect interface: never called for offloaded effects */
973b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_process(effect_handle_t self,
974b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       audio_buffer_t *inBuffer __unused,
975b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                       audio_buffer_t *outBuffer __unused)
976b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
977b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t * context = (effect_context_t *)self;
978b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int status = 0;
979b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
980b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    //ALOGW("%s Called ?????", __func__);
981b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
982b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
983b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (!effect_exists(context)) {
984b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        status = -EINVAL;
985b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
986b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
987b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
988b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (context->state != EFFECT_STATE_ACTIVE) {
989b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        status = -EINVAL;
990b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
991b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
992b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
993b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeexit:
994b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
995b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return status;
996b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
997b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
998b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
999b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        void *pCmdData, uint32_t *replySize, void *pReplyData)
1000b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
1001b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1002b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t * context = (effect_context_t *)self;
1003b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int retsize;
1004b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    int status = 0;
1005b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1006b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_lock(&lock);
1007b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1008b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (!effect_exists(context)) {
1009b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        status = -EINVAL;
1010b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
1011b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
1012b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1013b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
1014b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        status = -EINVAL;
1015b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        goto exit;
1016b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
1017b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1018b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande//    ALOGV_IF(cmdCode != VISUALIZER_CMD_CAPTURE,
1019b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande//             "%s command %d cmdSize %d", __func__, cmdCode, cmdSize);
1020b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1021b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    switch (cmdCode) {
1022b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_INIT:
1023b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pReplyData == NULL || *replySize != sizeof(int)) {
1024b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1025b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1026b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1027b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.init)
1028b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *(int *) pReplyData = context->ops.init(context);
1029b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        else
1030b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *(int *) pReplyData = 0;
1031b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1032b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_SET_CONFIG:
1033b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
1034b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                || pReplyData == NULL || *replySize != sizeof(int)) {
1035b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1036b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1037b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1038b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *(int *) pReplyData = set_config(context, (effect_config_t *) pCmdData);
1039b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1040b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_GET_CONFIG:
1041b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pReplyData == NULL ||
1042b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *replySize != sizeof(effect_config_t)) {
1043b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1044b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1045b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1046b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (!context->offload_enabled) {
1047b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1048b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1049b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1050b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1051b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        get_config(context, (effect_config_t *)pReplyData);
1052b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1053b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_RESET:
1054b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.reset)
1055b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            context->ops.reset(context);
1056b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1057b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_ENABLE:
1058b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pReplyData == NULL || *replySize != sizeof(int)) {
1059b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1060b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1061b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1062b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->state != EFFECT_STATE_INITIALIZED) {
1063b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -ENOSYS;
1064b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1065b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1066b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->state = EFFECT_STATE_ACTIVE;
1067b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.enable) {
1068b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            context->ops.enable(context);
1069b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1070b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        pthread_cond_signal(&cond);
1071b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *(int *)pReplyData = 0;
1072b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1073b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_DISABLE:
1074b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pReplyData == NULL || *replySize != sizeof(int)) {
1075b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1076b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1077b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1078b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->state != EFFECT_STATE_ACTIVE) {
1079b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -ENOSYS;
1080b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1081b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1082b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->state = EFFECT_STATE_INITIALIZED;
1083b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.disable)
1084b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            context->ops.disable(context);
1085b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        pthread_cond_signal(&cond);
1086b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s EFFECT_CMD_DISABLE", __func__);
1087b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *(int *)pReplyData = 0;
1088b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1089b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_GET_PARAM: {
1090b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pCmdData == NULL ||
1091b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
1092b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pReplyData == NULL ||
1093b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) {
1094b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1095b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1096b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1097b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (!context->offload_enabled) {
1098b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1099b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1100b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1101b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t));
1102b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_param_t *p = (effect_param_t *)pReplyData;
1103b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.get_parameter)
1104b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            context->ops.get_parameter(context, p, replySize);
1105b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } break;
1106b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_SET_PARAM: {
1107b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (pCmdData == NULL ||
1108b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) ||
1109b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            pReplyData == NULL || *replySize != sizeof(int32_t)) {
1110b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1111b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            goto exit;
1112b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1113b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *(int32_t *)pReplyData = 0;
1114b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_param_t *p = (effect_param_t *)pCmdData;
1115b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->ops.set_parameter)
1116b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            *(int32_t *)pReplyData = context->ops.set_parameter(context, p, *replySize);
1117b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1118b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } break;
1119b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_SET_DEVICE:
1120b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_SET_VOLUME:
1121b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_SET_AUDIO_MODE:
1122b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1123b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1124b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    case EFFECT_CMD_OFFLOAD: {
1125b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        output_context_t *out_ctxt;
1126b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1127b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (cmdSize != sizeof(effect_offload_param_t) || pCmdData == NULL
1128b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                || pReplyData == NULL || *replySize != sizeof(int)) {
1129b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            ALOGV("%s EFFECT_CMD_OFFLOAD bad format", __func__);
1130b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1131b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            break;
1132b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1133b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1134b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_offload_param_t* offload_param = (effect_offload_param_t*)pCmdData;
1135b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1136b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        ALOGV("%s EFFECT_CMD_OFFLOAD offload %d output %d",
1137b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande              __func__, offload_param->isOffload, offload_param->ioHandle);
1138b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1139b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        *(int *)pReplyData = 0;
1140b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1141b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->offload_enabled = offload_param->isOffload;
1142b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (context->out_handle == offload_param->ioHandle)
1143b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            break;
1144b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1145b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        out_ctxt = get_output(context->out_handle);
1146b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (out_ctxt != NULL)
1147b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            remove_effect_from_output(out_ctxt, context);
1148b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1149b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        context->out_handle = offload_param->ioHandle;
1150b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        out_ctxt = get_output(offload_param->ioHandle);
1151b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (out_ctxt != NULL)
1152b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            add_effect_to_output(out_ctxt, context);
1153b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1154b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        } break;
1155b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1156b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1157b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    default:
1158b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
1159b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = context->ops.command(context, cmdCode, cmdSize,
1160b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                          pCmdData, replySize, pReplyData);
1161b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        else {
1162b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            ALOGW("%s invalid command %d", __func__, cmdCode);
1163b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande            status = -EINVAL;
1164b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        }
1165b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        break;
1166b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    }
1167b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1168b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeexit:
1169b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    pthread_mutex_unlock(&lock);
1170b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1171b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande//    ALOGV_IF(cmdCode != VISUALIZER_CMD_CAPTURE,"%s DONE", __func__);
1172b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return status;
1173b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
1174b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1175b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* Effect Control Interface Implementation: get_descriptor */
1176b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeint effect_get_descriptor(effect_handle_t   self,
1177b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande                                    effect_descriptor_t *descriptor)
1178b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande{
1179b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    effect_context_t *context = (effect_context_t *)self;
1180b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1181b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (!effect_exists(context))
1182b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
1183b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1184b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    if (descriptor == NULL)
1185b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        return -EINVAL;
1186b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1187b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    *descriptor = *context->desc;
1188b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1189b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    return 0;
1190b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande}
1191b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1192b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande/* effect_handle_t interface implementation for visualizer effect */
1193b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeconst struct effect_interface_s effect_interface = {
1194b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_process,
1195b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_command,
1196b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        effect_get_descriptor,
1197b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande        NULL,
1198b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
1199b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande
1200b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande__attribute__ ((visibility ("default")))
1201b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhandeaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1202b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    tag : AUDIO_EFFECT_LIBRARY_TAG,
1203b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    version : EFFECT_LIBRARY_API_VERSION,
1204b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    name : "Visualizer Library",
1205b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    implementor : "Nvidia",
1206b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    create_effect : effect_lib_create,
1207b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    release_effect : effect_lib_release,
1208b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande    get_descriptor : effect_lib_get_descriptor,
1209b3249fa6053a9973b159edcf9dcc02fc44aaffa0Ravindra Lokhande};
1210