You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.6 KiB
159 lines
4.6 KiB
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "ext_speaker"
|
|
/*#define LOG_NDEBUG 0*/
|
|
#include <log/log.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <audio_hw.h>
|
|
#include <dlfcn.h>
|
|
|
|
#ifdef __LP64__
|
|
#define LIB_SPEAKER_BUNDLE "/vendor/lib64/soundfx/libspeakerbundle.so"
|
|
#else
|
|
#define LIB_SPEAKER_BUNDLE "/vendor/lib/soundfx/libspeakerbundle.so"
|
|
#endif
|
|
|
|
typedef void (*set_mode_t)(int);
|
|
typedef void (*set_speaker_on_t)(bool);
|
|
typedef void (*set_earpiece_on_t)(bool);
|
|
typedef void (*set_voice_vol_t)(float);
|
|
|
|
struct speaker_data {
|
|
struct audio_device *adev;
|
|
void *speaker_bundle;
|
|
set_mode_t set_mode;
|
|
set_speaker_on_t set_speaker_on;
|
|
set_earpiece_on_t set_earpiece_on;
|
|
set_voice_vol_t set_voice_vol;
|
|
};
|
|
|
|
static struct speaker_data* open_speaker_bundle()
|
|
{
|
|
struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
|
|
|
|
sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
|
|
if (sd->speaker_bundle == NULL) {
|
|
ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
|
|
goto error;
|
|
} else {
|
|
ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
|
|
|
|
sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
|
|
"set_mode");
|
|
if (sd->set_mode == NULL) {
|
|
ALOGE("%s: dlsym error %s for set_mode", __func__,
|
|
dlerror());
|
|
goto error;
|
|
}
|
|
sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
|
|
"set_speaker_on");
|
|
if (sd->set_speaker_on == NULL) {
|
|
ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
|
|
dlerror());
|
|
goto error;
|
|
}
|
|
sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
|
|
"set_earpiece_on");
|
|
if (sd->set_earpiece_on == NULL) {
|
|
ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
|
|
dlerror());
|
|
goto error;
|
|
}
|
|
sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
|
|
"set_voice_volume");
|
|
if (sd->set_voice_vol == NULL) {
|
|
ALOGE("%s: dlsym error %s for set_voice_volume",
|
|
__func__, dlerror());
|
|
goto error;
|
|
}
|
|
}
|
|
return sd;
|
|
|
|
error:
|
|
free(sd);
|
|
return 0;
|
|
}
|
|
|
|
static void close_speaker_bundle(struct speaker_data *sd)
|
|
{
|
|
if (sd != NULL) {
|
|
dlclose(sd->speaker_bundle);
|
|
free(sd);
|
|
sd = NULL;
|
|
}
|
|
}
|
|
|
|
void *audio_extn_extspk_init(struct audio_device *adev)
|
|
{
|
|
struct speaker_data *data = open_speaker_bundle();
|
|
|
|
if (data)
|
|
data->adev = adev;
|
|
|
|
return data;
|
|
}
|
|
|
|
void audio_extn_extspk_deinit(void *extn)
|
|
{
|
|
struct speaker_data *data = (struct speaker_data*)extn;
|
|
close_speaker_bundle(data);
|
|
}
|
|
|
|
void audio_extn_extspk_update(void* extn)
|
|
{
|
|
struct speaker_data *data = (struct speaker_data*)extn;
|
|
|
|
if (data) {
|
|
bool speaker_on = false;
|
|
bool earpiece_on = false;
|
|
struct listnode *node;
|
|
struct audio_usecase *usecase;
|
|
list_for_each(node, &data->adev->usecase_list) {
|
|
usecase = node_to_item(node, struct audio_usecase, list);
|
|
if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
|
|
if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
|
|
earpiece_on = true;
|
|
}
|
|
}
|
|
if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
|
|
if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
|
|
speaker_on = true;
|
|
}
|
|
}
|
|
}
|
|
data->set_earpiece_on(earpiece_on);
|
|
data->set_speaker_on(speaker_on);
|
|
}
|
|
}
|
|
|
|
void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
|
|
{
|
|
struct speaker_data *data = (struct speaker_data*)extn;
|
|
|
|
if (data)
|
|
data->set_mode(mode);
|
|
}
|
|
|
|
void audio_extn_extspk_set_voice_vol(void* extn, float vol)
|
|
{
|
|
struct speaker_data *data = (struct speaker_data*)extn;
|
|
|
|
if (data)
|
|
data->set_voice_vol(vol);
|
|
}
|