blob: b11a7006fcdbf55b2834b52bd4129c1b8f70c0d9 [file] [log] [blame]
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -08001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "offload_effect_bundle"
21#define LOG_NDEBUG 0
22
23#include <cutils/list.h>
24#include <cutils/log.h>
25#include <system/thread_defs.h>
26#include <tinyalsa/asoundlib.h>
27#include <hardware/audio_effect.h>
28
29#include "bundle.h"
30#include "equalizer.h"
31#include "bass_boost.h"
32#include "virtualizer.h"
33#include "reverb.h"
34
35enum {
36 EFFECT_STATE_UNINITIALIZED,
37 EFFECT_STATE_INITIALIZED,
38 EFFECT_STATE_ACTIVE,
39};
40
41const effect_descriptor_t *descriptors[] = {
42 &equalizer_descriptor,
43 &bassboost_descriptor,
44 &virtualizer_descriptor,
45 &aux_env_reverb_descriptor,
46 &ins_env_reverb_descriptor,
47 &aux_preset_reverb_descriptor,
48 &ins_preset_reverb_descriptor,
49 NULL,
50};
51
52pthread_once_t once = PTHREAD_ONCE_INIT;
53int init_status;
54/*
55 * list of created effects.
56 * Updated by offload_effects_bundle_hal_start_output()
57 * and offload_effects_bundle_hal_stop_output()
58 */
59struct listnode created_effects_list;
60/*
61 * list of active output streams.
62 * Updated by offload_effects_bundle_hal_start_output()
63 * and offload_effects_bundle_hal_stop_output()
64 */
65struct listnode active_outputs_list;
66/*
67 * lock must be held when modifying or accessing
68 * created_effects_list or active_outputs_list
69 */
70pthread_mutex_t lock;
71
72
73/*
74 * Local functions
75 */
76static void init_once() {
77 list_init(&created_effects_list);
78 list_init(&active_outputs_list);
79
80 pthread_mutex_init(&lock, NULL);
81
82 init_status = 0;
83}
84
85int lib_init()
86{
87 pthread_once(&once, init_once);
88 return init_status;
89}
90
91bool effect_exists(effect_context_t *context)
92{
93 struct listnode *node;
94
95 list_for_each(node, &created_effects_list) {
96 effect_context_t *fx_ctxt = node_to_item(node,
97 effect_context_t,
98 effects_list_node);
99 if (fx_ctxt == context) {
100 return true;
101 }
102 }
103 return false;
104}
105
106output_context_t *get_output(audio_io_handle_t output)
107{
108 struct listnode *node;
109
110 list_for_each(node, &active_outputs_list) {
111 output_context_t *out_ctxt = node_to_item(node,
112 output_context_t,
113 outputs_list_node);
114 if (out_ctxt->handle == output)
115 return out_ctxt;
116 }
117 return NULL;
118}
119
120void add_effect_to_output(output_context_t * output, effect_context_t *context)
121{
122 struct listnode *fx_node;
123
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530124 ALOGV("%s: e_ctxt %p, o_ctxt %p", __func__, context, output);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800125 list_for_each(fx_node, &output->effects_list) {
126 effect_context_t *fx_ctxt = node_to_item(fx_node,
127 effect_context_t,
128 output_node);
129 if (fx_ctxt == context)
130 return;
131 }
132 list_add_tail(&output->effects_list, &context->output_node);
133 if (context->ops.start)
134 context->ops.start(context, output);
135
136}
137
138void remove_effect_from_output(output_context_t * output,
139 effect_context_t *context)
140{
141 struct listnode *fx_node;
142
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530143 ALOGV("%s: e_ctxt %p, o_ctxt %p", __func__, context, output);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800144 list_for_each(fx_node, &output->effects_list) {
145 effect_context_t *fx_ctxt = node_to_item(fx_node,
146 effect_context_t,
147 output_node);
148 if (fx_ctxt == context) {
149 if (context->ops.stop)
150 context->ops.stop(context, output);
151 list_remove(&context->output_node);
152 return;
153 }
154 }
155}
156
157bool effects_enabled()
158{
159 struct listnode *out_node;
160
161 list_for_each(out_node, &active_outputs_list) {
162 struct listnode *fx_node;
163 output_context_t *out_ctxt = node_to_item(out_node,
164 output_context_t,
165 outputs_list_node);
166
167 list_for_each(fx_node, &out_ctxt->effects_list) {
168 effect_context_t *fx_ctxt = node_to_item(fx_node,
169 effect_context_t,
170 output_node);
171 if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
172 (fx_ctxt->ops.process != NULL))
173 return true;
174 }
175 }
176 return false;
177}
178
179
180/*
181 * Interface from audio HAL
182 */
183__attribute__ ((visibility ("default")))
184int offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id)
185{
186 int ret = 0;
187 struct listnode *node;
188 char mixer_string[128];
189
190 ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
191
192 if (lib_init() != 0)
193 return init_status;
194
195 pthread_mutex_lock(&lock);
196 if (get_output(output) != NULL) {
197 ALOGW("%s output already started", __func__);
198 ret = -ENOSYS;
199 goto exit;
200 }
201
202 output_context_t *out_ctxt = (output_context_t *)
203 malloc(sizeof(output_context_t));
204 out_ctxt->handle = output;
205 out_ctxt->pcm_device_id = pcm_id;
206
207 /* populate the mixer control to send offload parameters */
208 snprintf(mixer_string, sizeof(mixer_string),
209 "%s %d", "Audio Effects Config", out_ctxt->pcm_device_id);
210 out_ctxt->mixer = mixer_open(MIXER_CARD);
211 if (!out_ctxt->mixer) {
212 ALOGE("Failed to open mixer");
213 out_ctxt->ctl = NULL;
214 ret = -EINVAL;
215 goto exit;
216 } else {
217 out_ctxt->ctl = mixer_get_ctl_by_name(out_ctxt->mixer, mixer_string);
218 if (!out_ctxt->ctl) {
219 ALOGE("mixer_get_ctl_by_name failed");
220 mixer_close(out_ctxt->mixer);
221 out_ctxt->mixer = NULL;
222 ret = -EINVAL;
223 goto exit;
224 }
225 }
226
227 list_init(&out_ctxt->effects_list);
228
229 list_for_each(node, &created_effects_list) {
230 effect_context_t *fx_ctxt = node_to_item(node,
231 effect_context_t,
232 effects_list_node);
233 if (fx_ctxt->out_handle == output) {
234 if (fx_ctxt->ops.start)
235 fx_ctxt->ops.start(fx_ctxt, out_ctxt);
236 list_add_tail(&out_ctxt->effects_list, &fx_ctxt->output_node);
237 }
238 }
239 list_add_tail(&active_outputs_list, &out_ctxt->outputs_list_node);
240exit:
241 pthread_mutex_unlock(&lock);
242 return ret;
243}
244
245__attribute__ ((visibility ("default")))
246int offload_effects_bundle_hal_stop_output(audio_io_handle_t output, int pcm_id)
247{
248 int ret;
249 struct listnode *node;
250 struct listnode *fx_node;
251 output_context_t *out_ctxt;
252
253 ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
254
255 if (lib_init() != 0)
256 return init_status;
257
258 pthread_mutex_lock(&lock);
259
260 out_ctxt = get_output(output);
261 if (out_ctxt == NULL) {
262 ALOGW("%s output not started", __func__);
263 ret = -ENOSYS;
264 goto exit;
265 }
266
267 if (out_ctxt->mixer)
268 mixer_close(out_ctxt->mixer);
269
270 list_for_each(fx_node, &out_ctxt->effects_list) {
271 effect_context_t *fx_ctxt = node_to_item(fx_node,
272 effect_context_t,
273 output_node);
274 if (fx_ctxt->ops.stop)
275 fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
276 }
277
278 list_remove(&out_ctxt->outputs_list_node);
279
280 free(out_ctxt);
281
282exit:
283 pthread_mutex_unlock(&lock);
284 return ret;
285}
286
287
288/*
289 * Effect operations
290 */
291int set_config(effect_context_t *context, effect_config_t *config)
292{
293 context->config = *config;
294
295 if (context->ops.reset)
296 context->ops.reset(context);
297
298 return 0;
299}
300
301void get_config(effect_context_t *context, effect_config_t *config)
302{
303 *config = context->config;
304}
305
306
307/*
308 * Effect Library Interface Implementation
309 */
310int effect_lib_create(const effect_uuid_t *uuid,
311 int32_t sessionId,
312 int32_t ioId,
313 effect_handle_t *pHandle) {
314 int ret;
315 int i;
316
317 ALOGV("%s: sessionId: %d, ioId: %d", __func__, sessionId, ioId);
318 if (lib_init() != 0)
319 return init_status;
320
321 if (pHandle == NULL || uuid == NULL)
322 return -EINVAL;
323
324 for (i = 0; descriptors[i] != NULL; i++) {
325 if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0)
326 break;
327 }
328
329 if (descriptors[i] == NULL)
330 return -EINVAL;
331
332 effect_context_t *context;
333 if (memcmp(uuid, &equalizer_descriptor.uuid,
334 sizeof(effect_uuid_t)) == 0) {
335 equalizer_context_t *eq_ctxt = (equalizer_context_t *)
336 calloc(1, sizeof(equalizer_context_t));
337 context = (effect_context_t *)eq_ctxt;
338 context->ops.init = equalizer_init;
339 context->ops.reset = equalizer_reset;
340 context->ops.set_parameter = equalizer_set_parameter;
341 context->ops.get_parameter = equalizer_get_parameter;
342 context->ops.set_device = equalizer_set_device;
343 context->ops.enable = equalizer_enable;
344 context->ops.disable = equalizer_disable;
345 context->ops.start = equalizer_start;
346 context->ops.stop = equalizer_stop;
347
348 context->desc = &equalizer_descriptor;
349 eq_ctxt->ctl = NULL;
350 } else if (memcmp(uuid, &bassboost_descriptor.uuid,
351 sizeof(effect_uuid_t)) == 0) {
352 bassboost_context_t *bass_ctxt = (bassboost_context_t *)
353 calloc(1, sizeof(bassboost_context_t));
354 context = (effect_context_t *)bass_ctxt;
355 context->ops.init = bassboost_init;
356 context->ops.reset = bassboost_reset;
357 context->ops.set_parameter = bassboost_set_parameter;
358 context->ops.get_parameter = bassboost_get_parameter;
359 context->ops.set_device = bassboost_set_device;
360 context->ops.enable = bassboost_enable;
361 context->ops.disable = bassboost_disable;
362 context->ops.start = bassboost_start;
363 context->ops.stop = bassboost_stop;
364
365 context->desc = &bassboost_descriptor;
366 bass_ctxt->ctl = NULL;
367 } else if (memcmp(uuid, &virtualizer_descriptor.uuid,
368 sizeof(effect_uuid_t)) == 0) {
369 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
370 calloc(1, sizeof(virtualizer_context_t));
371 context = (effect_context_t *)virt_ctxt;
372 context->ops.init = virtualizer_init;
373 context->ops.reset = virtualizer_reset;
374 context->ops.set_parameter = virtualizer_set_parameter;
375 context->ops.get_parameter = virtualizer_get_parameter;
376 context->ops.set_device = virtualizer_set_device;
377 context->ops.enable = virtualizer_enable;
378 context->ops.disable = virtualizer_disable;
379 context->ops.start = virtualizer_start;
380 context->ops.stop = virtualizer_stop;
381
382 context->desc = &virtualizer_descriptor;
383 virt_ctxt->ctl = NULL;
384 } else if ((memcmp(uuid, &aux_env_reverb_descriptor.uuid,
385 sizeof(effect_uuid_t)) == 0) ||
386 (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
387 sizeof(effect_uuid_t)) == 0) ||
388 (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
389 sizeof(effect_uuid_t)) == 0) ||
390 (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
391 sizeof(effect_uuid_t)) == 0)) {
392 reverb_context_t *reverb_ctxt = (reverb_context_t *)
393 calloc(1, sizeof(reverb_context_t));
394 context = (effect_context_t *)reverb_ctxt;
395 context->ops.init = reverb_init;
396 context->ops.reset = reverb_reset;
397 context->ops.set_parameter = reverb_set_parameter;
398 context->ops.get_parameter = reverb_get_parameter;
399 context->ops.set_device = reverb_set_device;
400 context->ops.enable = reverb_enable;
401 context->ops.disable = reverb_disable;
402 context->ops.start = reverb_start;
403 context->ops.stop = reverb_stop;
404
405 if (memcmp(uuid, &aux_env_reverb_descriptor.uuid,
406 sizeof(effect_uuid_t)) == 0) {
407 context->desc = &aux_env_reverb_descriptor;
408 reverb_auxiliary_init(reverb_ctxt);
409 } else if (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
410 sizeof(effect_uuid_t)) == 0) {
411 context->desc = &ins_env_reverb_descriptor;
412 reverb_preset_init(reverb_ctxt);
413 } else if (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
414 sizeof(effect_uuid_t)) == 0) {
415 context->desc = &aux_preset_reverb_descriptor;
416 reverb_auxiliary_init(reverb_ctxt);
417 } else if (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
418 sizeof(effect_uuid_t)) == 0) {
419 context->desc = &ins_preset_reverb_descriptor;
420 reverb_preset_init(reverb_ctxt);
421 }
422 reverb_ctxt->ctl = NULL;
423 } else {
424 return -EINVAL;
425 }
426
427 context->itfe = &effect_interface;
428 context->state = EFFECT_STATE_UNINITIALIZED;
429 context->out_handle = (audio_io_handle_t)ioId;
430
431 ret = context->ops.init(context);
432 if (ret < 0) {
433 ALOGW("%s init failed", __func__);
434 free(context);
435 return ret;
436 }
437
438 context->state = EFFECT_STATE_INITIALIZED;
439
440 pthread_mutex_lock(&lock);
441 list_add_tail(&created_effects_list, &context->effects_list_node);
442 output_context_t *out_ctxt = get_output(ioId);
443 if (out_ctxt != NULL)
444 add_effect_to_output(out_ctxt, context);
445 pthread_mutex_unlock(&lock);
446
447 *pHandle = (effect_handle_t)context;
448
449 ALOGV("%s created context %p", __func__, context);
450
451 return 0;
452
453}
454
455int effect_lib_release(effect_handle_t handle)
456{
457 effect_context_t *context = (effect_context_t *)handle;
458 int status;
459
460 if (lib_init() != 0)
461 return init_status;
462
463 ALOGV("%s context %p", __func__, handle);
464 pthread_mutex_lock(&lock);
465 status = -EINVAL;
466 if (effect_exists(context)) {
467 output_context_t *out_ctxt = get_output(context->out_handle);
468 if (out_ctxt != NULL)
469 remove_effect_from_output(out_ctxt, context);
470 list_remove(&context->effects_list_node);
471 if (context->ops.release)
472 context->ops.release(context);
473 free(context);
474 status = 0;
475 }
476 pthread_mutex_unlock(&lock);
477
478 return status;
479}
480
481int effect_lib_get_descriptor(const effect_uuid_t *uuid,
482 effect_descriptor_t *descriptor)
483{
484 int i;
485
486 if (lib_init() != 0)
487 return init_status;
488
489 if (descriptor == NULL || uuid == NULL) {
490 ALOGV("%s called with NULL pointer", __func__);
491 return -EINVAL;
492 }
493
494 for (i = 0; descriptors[i] != NULL; i++) {
495 if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
496 *descriptor = *descriptors[i];
497 return 0;
498 }
499 }
500
501 return -EINVAL;
502}
503
504
505/*
506 * Effect Control Interface Implementation
507 */
508
509/* Stub function for effect interface: never called for offloaded effects */
510int effect_process(effect_handle_t self,
511 audio_buffer_t *inBuffer,
512 audio_buffer_t *outBuffer)
513{
514 effect_context_t * context = (effect_context_t *)self;
515 int status = 0;
516
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530517 ALOGW("%s: ctxt %p, Called ?????", __func__, context);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800518
519 pthread_mutex_lock(&lock);
520 if (!effect_exists(context)) {
521 status = -EINVAL;
522 goto exit;
523 }
524
525 if (context->state != EFFECT_STATE_ACTIVE) {
526 status = -EINVAL;
527 goto exit;
528 }
529
530exit:
531 pthread_mutex_unlock(&lock);
532 return status;
533}
534
535int effect_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
536 void *pCmdData, uint32_t *replySize, void *pReplyData)
537{
538
539 effect_context_t * context = (effect_context_t *)self;
540 int retsize;
541 int status = 0;
542
543 pthread_mutex_lock(&lock);
544
545 if (!effect_exists(context)) {
546 status = -EINVAL;
547 goto exit;
548 }
549
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530550 ALOGV("%s: ctxt %p, cmd %d", __func__, context, cmdCode);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800551 if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
552 status = -EINVAL;
553 goto exit;
554 }
555
556 switch (cmdCode) {
557 case EFFECT_CMD_INIT:
558 if (pReplyData == NULL || *replySize != sizeof(int)) {
559 status = -EINVAL;
560 goto exit;
561 }
562 if (context->ops.init)
563 *(int *) pReplyData = context->ops.init(context);
564 else
565 *(int *) pReplyData = 0;
566 break;
567 case EFFECT_CMD_SET_CONFIG:
568 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
569 || pReplyData == NULL || *replySize != sizeof(int)) {
570 status = -EINVAL;
571 goto exit;
572 }
573 *(int *) pReplyData = set_config(context, (effect_config_t *) pCmdData);
574 break;
575 case EFFECT_CMD_GET_CONFIG:
576 if (pReplyData == NULL ||
577 *replySize != sizeof(effect_config_t)) {
578 status = -EINVAL;
579 goto exit;
580 }
581 if (!context->offload_enabled) {
582 status = -EINVAL;
583 goto exit;
584 }
585
586 get_config(context, (effect_config_t *)pReplyData);
587 break;
588 case EFFECT_CMD_RESET:
589 if (context->ops.reset)
590 context->ops.reset(context);
591 break;
592 case EFFECT_CMD_ENABLE:
593 if (pReplyData == NULL || *replySize != sizeof(int)) {
594 status = -EINVAL;
595 goto exit;
596 }
597 if (context->state != EFFECT_STATE_INITIALIZED) {
598 status = -ENOSYS;
599 goto exit;
600 }
601 context->state = EFFECT_STATE_ACTIVE;
602 if (context->ops.enable)
603 context->ops.enable(context);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800604 *(int *)pReplyData = 0;
605 break;
606 case EFFECT_CMD_DISABLE:
607 if (pReplyData == NULL || *replySize != sizeof(int)) {
608 status = -EINVAL;
609 goto exit;
610 }
611 if (context->state != EFFECT_STATE_ACTIVE) {
612 status = -ENOSYS;
613 goto exit;
614 }
615 context->state = EFFECT_STATE_INITIALIZED;
616 if (context->ops.disable)
617 context->ops.disable(context);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800618 *(int *)pReplyData = 0;
619 break;
620 case EFFECT_CMD_GET_PARAM: {
621 if (pCmdData == NULL ||
622 cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
623 pReplyData == NULL ||
624 *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
625 sizeof(uint16_t))) {
626 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530627 ALOGW("EFFECT_CMD_GET_PARAM invalid command cmdSize %d *replySize %d",
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800628 cmdSize, *replySize);
629 goto exit;
630 }
631 if (!context->offload_enabled) {
632 status = -EINVAL;
633 goto exit;
634 }
635 effect_param_t *q = (effect_param_t *)pCmdData;
636 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + q->psize);
637 effect_param_t *p = (effect_param_t *)pReplyData;
638 if (context->ops.get_parameter)
639 context->ops.get_parameter(context, p, replySize);
640 } break;
641 case EFFECT_CMD_SET_PARAM: {
642 if (pCmdData == NULL ||
643 cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
644 sizeof(uint16_t)) ||
645 pReplyData == NULL || *replySize != sizeof(int32_t)) {
646 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530647 ALOGW("EFFECT_CMD_SET_PARAM invalid command cmdSize %d *replySize %d",
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800648 cmdSize, *replySize);
649 goto exit;
650 }
651 *(int32_t *)pReplyData = 0;
652 effect_param_t *p = (effect_param_t *)pCmdData;
653 if (context->ops.set_parameter)
654 *(int32_t *)pReplyData = context->ops.set_parameter(context, p,
655 *replySize);
656
657 } break;
658 case EFFECT_CMD_SET_DEVICE: {
659 uint32_t device;
660 ALOGV("\t EFFECT_CMD_SET_DEVICE start");
661 if (pCmdData == NULL || cmdSize < sizeof(uint32_t)) {
662 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530663 ALOGW("EFFECT_CMD_SET_DEVICE invalid command cmdSize %d", cmdSize);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800664 goto exit;
665 }
666 device = *(uint32_t *)pCmdData;
667 if (context->ops.set_device)
668 context->ops.set_device(context, device);
669 } break;
670 case EFFECT_CMD_SET_VOLUME:
671 case EFFECT_CMD_SET_AUDIO_MODE:
672 break;
673
674 case EFFECT_CMD_OFFLOAD: {
675 output_context_t *out_ctxt;
676
677 if (cmdSize != sizeof(effect_offload_param_t) || pCmdData == NULL
678 || pReplyData == NULL || *replySize != sizeof(int)) {
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530679 ALOGW("%s EFFECT_CMD_OFFLOAD bad format", __func__);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800680 status = -EINVAL;
681 break;
682 }
683
684 effect_offload_param_t* offload_param = (effect_offload_param_t*)pCmdData;
685
686 ALOGV("%s EFFECT_CMD_OFFLOAD offload %d output %d", __func__,
687 offload_param->isOffload, offload_param->ioHandle);
688
689 *(int *)pReplyData = 0;
690
691 context->offload_enabled = offload_param->isOffload;
692 if (context->out_handle == offload_param->ioHandle)
693 break;
694
695 out_ctxt = get_output(context->out_handle);
696 if (out_ctxt != NULL)
697 remove_effect_from_output(out_ctxt, context);
698
699 context->out_handle = offload_param->ioHandle;
700 out_ctxt = get_output(context->out_handle);
701 if (out_ctxt != NULL)
702 add_effect_to_output(out_ctxt, context);
703
704 } break;
705
706
707 default:
708 if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
709 status = context->ops.command(context, cmdCode, cmdSize,
710 pCmdData, replySize, pReplyData);
711 else {
712 ALOGW("%s invalid command %d", __func__, cmdCode);
713 status = -EINVAL;
714 }
715 break;
716 }
717
718exit:
719 pthread_mutex_unlock(&lock);
720
721 return status;
722}
723
724/* Effect Control Interface Implementation: get_descriptor */
725int effect_get_descriptor(effect_handle_t self,
726 effect_descriptor_t *descriptor)
727{
728 effect_context_t *context = (effect_context_t *)self;
729
730 if (!effect_exists(context) || (descriptor == NULL))
731 return -EINVAL;
732
733 *descriptor = *context->desc;
734
735 return 0;
736}
737
738
739/* effect_handle_t interface implementation for offload effects */
740const struct effect_interface_s effect_interface = {
741 effect_process,
742 effect_command,
743 effect_get_descriptor,
744 NULL,
745};
746
747__attribute__ ((visibility ("default")))
748audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
749 tag : AUDIO_EFFECT_LIBRARY_TAG,
750 version : EFFECT_LIBRARY_API_VERSION,
751 name : "Offload Effects Bundle Library",
752 implementor : "The Linux Foundation",
753 create_effect : effect_lib_create,
754 release_effect : effect_lib_release,
755 get_descriptor : effect_lib_get_descriptor,
756};