blob: 487080d2bc8788fc71dd76c51d96e2a88c0fae3a [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// 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.
#include "starboard/shared/pulse/pulse_dynamic_load_dispatcher.h"
#include <dlfcn.h>
#include "starboard/log.h"
#include "starboard/once.h"
namespace starboard {
namespace shared {
namespace pulse {
namespace {
const char kPulseLibraryName[] = "libpulse.so";
void* pulse_lib_handle = NULL;
} // namespace
int (*pa_context_connect)(pa_context*,
const char*,
pa_context_flags_t,
const pa_spawn_api*) = NULL;
void (*pa_context_disconnect)(pa_context*) = NULL;
pa_context_state_t (*pa_context_get_state)(pa_context*) = NULL;
pa_context* (*pa_context_new)(pa_mainloop_api*, const char*) = NULL;
void (*pa_context_set_state_callback)(pa_context*,
pa_context_notify_cb_t,
void*) = NULL;
void (*pa_context_unref)(pa_context*) = NULL;
size_t (*pa_frame_size)(const pa_sample_spec*) = NULL;
void (*pa_mainloop_free)(pa_mainloop*);
pa_mainloop_api* (*pa_mainloop_get_api)(pa_mainloop*) = NULL;
int (*pa_mainloop_iterate)(pa_mainloop*, int, int*) = NULL;
pa_mainloop* (*pa_mainloop_new)(void) = NULL;
void (*pa_operation_unref)(pa_operation*) = NULL;
int (*pa_stream_connect_playback)(pa_stream*,
const char*,
const pa_buffer_attr*,
pa_stream_flags_t,
const pa_cvolume*,
pa_stream*) = NULL;
pa_operation* (*pa_stream_cork)(pa_stream*,
int,
pa_stream_success_cb_t,
void*) = NULL;
int (*pa_stream_disconnect)(pa_stream*) = NULL;
pa_stream_state_t (*pa_stream_get_state)(pa_stream*) = NULL;
int (*pa_stream_get_time)(pa_stream*, pa_usec_t*) = NULL;
int (*pa_stream_is_corked)(pa_stream*) = NULL;
pa_stream* (*pa_stream_new)(pa_context*,
const char*,
const pa_sample_spec*,
const pa_channel_map*) = NULL;
void (*pa_stream_set_underflow_callback)(pa_stream*,
pa_stream_notify_cb_t,
void*) = NULL;
void (*pa_stream_set_write_callback)(pa_stream*,
pa_stream_request_cb_t,
void*) = NULL;
void (*pa_stream_unref)(pa_stream*) = NULL;
size_t (*pa_stream_writable_size)(pa_stream*) = NULL;
int (*pa_stream_write)(pa_stream*,
const void*,
size_t,
pa_free_cb_t,
int64_t,
pa_seek_mode_t) = NULL;
void ReportSymbolError() {
SB_LOG(ERROR) << "Pulse audio error: " << dlerror();
dlclose(pulse_lib_handle);
pulse_lib_handle = NULL;
}
bool pulse_load_library() {
SB_DCHECK(!pulse_lib_handle);
pulse_lib_handle = dlopen(kPulseLibraryName, RTLD_LAZY);
if (!pulse_lib_handle) {
return false;
}
#define INITSYMBOL(symbol) \
symbol = \
reinterpret_cast<decltype(symbol)>(dlsym(pulse_lib_handle, #symbol)); \
if (!symbol) { \
ReportSymbolError(); \
return false; \
}
INITSYMBOL(pa_context_connect);
INITSYMBOL(pa_context_disconnect);
INITSYMBOL(pa_context_get_state);
INITSYMBOL(pa_context_new);
INITSYMBOL(pa_context_set_state_callback);
INITSYMBOL(pa_context_unref);
INITSYMBOL(pa_frame_size);
INITSYMBOL(pa_mainloop_free);
INITSYMBOL(pa_mainloop_get_api);
INITSYMBOL(pa_mainloop_iterate);
INITSYMBOL(pa_mainloop_new);
INITSYMBOL(pa_operation_unref);
INITSYMBOL(pa_stream_connect_playback);
INITSYMBOL(pa_stream_cork);
INITSYMBOL(pa_stream_disconnect);
INITSYMBOL(pa_stream_get_state);
INITSYMBOL(pa_stream_get_time);
INITSYMBOL(pa_stream_is_corked);
INITSYMBOL(pa_stream_new);
INITSYMBOL(pa_stream_set_underflow_callback);
INITSYMBOL(pa_stream_set_write_callback);
INITSYMBOL(pa_stream_unref);
INITSYMBOL(pa_stream_writable_size);
INITSYMBOL(pa_stream_write);
return true;
}
void pulse_unload_library() {
SB_DCHECK(pulse_lib_handle);
dlclose(pulse_lib_handle);
pulse_lib_handle = NULL;
}
} // namespace pulse
} // namespace shared
} // namespace starboard