blob: 4c996e28b9490c9e54c5ae6fdfe4a94fa7d1a7fd [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/media/audio/lib/effects_loader/effects_module.h"
#include <dlfcn.h>
#include "src/lib/fxl/logging.h"
namespace media::audio::internal {
namespace {
bool TryLoad(void* lib, const char* export_name, void** export_ptr) {
FXL_DCHECK(lib != nullptr);
FXL_DCHECK(export_name != nullptr);
FXL_DCHECK(export_ptr != nullptr);
*export_ptr = dlsym(lib, export_name);
if (*export_ptr == nullptr) {
FXL_LOG(ERROR) << "Failed to load .SO export [" << export_name << "]";
return false;
}
return true;
}
template <typename ModuleImpl>
constexpr const char* ExportSymbolName() = delete;
template <>
constexpr const char* ExportSymbolName<fuchsia_audio_effects_module_v1>() {
return "fuchsia_audio_effects_module_v1_instance";
}
} // namespace
template <typename ModuleImpl>
EffectsModule<ModuleImpl> EffectsModule<ModuleImpl>::Open(const char* name) {
void* lib = dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
if (lib == nullptr) {
return {};
}
ModuleImpl* module = nullptr;
if (!TryLoad(lib, ExportSymbolName<ModuleImpl>(), reinterpret_cast<void**>(&module))) {
return {};
}
// We use the shared_ptr to handle the basic ref counting. We provide a custom deleter as we
// don't actually own the module pointer (it's just some data within the loaded module), but
// instead we want to unload the module when the refcount reaches 0.
return EffectsModule<ModuleImpl>(std::shared_ptr<ModuleImpl>(
module, [lib](ModuleImpl* ptr) { FXL_DCHECK(dlclose(lib) == 0); }));
}
template <typename ModuleImpl>
EffectsModule<ModuleImpl>::EffectsModule(std::shared_ptr<ModuleImpl> module)
: module_(std::move(module)) {}
template class EffectsModule<fuchsia_audio_effects_module_v1>;
} // namespace media::audio::internal