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.
158 lines
4.6 KiB
158 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 <cutils/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); |
|
}
|
|
|