440 lines
12 KiB
C++
440 lines
12 KiB
C++
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
*/
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <glib.h>
|
|
#include "mozilla/Types.h"
|
|
#include "prlink.h"
|
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
#define GET_FUNC(func, lib) \
|
|
func##_fn = \
|
|
(decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \
|
|
|
|
#define IS_FUNC_LOADED(func) \
|
|
(func != nullptr) \
|
|
|
|
struct GUnixFDList;
|
|
|
|
extern "C" gint
|
|
g_unix_fd_list_get(struct GUnixFDList *list,
|
|
gint index_,
|
|
GError **error)
|
|
{
|
|
static PRLibrary* gioLib = nullptr;
|
|
static bool gioInitialized = false;
|
|
static gint (*g_unix_fd_list_get_fn)(struct GUnixFDList *list,
|
|
gint index_, GError **error) = nullptr;
|
|
|
|
if (!gioInitialized) {
|
|
gioInitialized = true;
|
|
gioLib = PR_LoadLibrary("libgio-2.0.so.0");
|
|
if (!gioLib) {
|
|
return -1;
|
|
}
|
|
GET_FUNC(g_unix_fd_list_get, gioLib);
|
|
}
|
|
|
|
if (!g_unix_fd_list_get_fn) {
|
|
return -1;
|
|
}
|
|
|
|
return g_unix_fd_list_get_fn(list, index_, error);
|
|
}
|
|
|
|
static struct pw_core * (*pw_context_connect_fn)(struct pw_context *context,
|
|
struct pw_properties *properties,
|
|
size_t user_data_size);
|
|
static struct pw_core * (*pw_context_connect_fd_fn)(struct pw_context *context,
|
|
int fd,
|
|
struct pw_properties *properties,
|
|
size_t user_data_size);
|
|
static void (*pw_context_destroy_fn)(struct pw_context *context);
|
|
struct pw_context * (*pw_context_new_fn)(struct pw_loop *main_loop,
|
|
struct pw_properties *props,
|
|
size_t user_data_size);
|
|
static int (*pw_core_disconnect_fn)(struct pw_core *core);
|
|
static void (*pw_init_fn)(int *argc, char **argv[]);
|
|
static void (*pw_proxy_destroy_fn)(struct pw_proxy *proxy);
|
|
static void (*pw_stream_add_listener_fn)(struct pw_stream *stream,
|
|
struct spa_hook *listener,
|
|
const struct pw_stream_events *events,
|
|
void *data);
|
|
static int (*pw_stream_connect_fn)(struct pw_stream *stream,
|
|
enum pw_direction direction,
|
|
uint32_t target_id,
|
|
enum pw_stream_flags flags,
|
|
const struct spa_pod **params,
|
|
uint32_t n_params);
|
|
static int (*pw_stream_disconnect_fn)(struct pw_stream *stream);
|
|
static struct pw_buffer* (*pw_stream_dequeue_buffer_fn)(struct pw_stream *stream);
|
|
static void (*pw_stream_destroy_fn)(struct pw_stream *stream);
|
|
static struct pw_stream* (*pw_stream_new_fn)(struct pw_core *core,
|
|
const char *name,
|
|
struct pw_properties *props);
|
|
|
|
static int (*pw_stream_queue_buffer_fn)(struct pw_stream *stream,
|
|
struct pw_buffer *buffer);
|
|
static const char * (*pw_stream_state_as_string_fn)(enum pw_stream_state state);
|
|
static int (*pw_stream_update_params_fn)(struct pw_stream *stream,
|
|
const struct spa_pod **params,
|
|
uint32_t n_params);
|
|
static void (*pw_thread_loop_destroy_fn)(struct pw_thread_loop *loop);
|
|
static struct pw_loop* (*pw_thread_loop_get_loop_fn)(struct pw_thread_loop *loop);
|
|
static struct pw_thread_loop* (*pw_thread_loop_new_fn)(const char *name,
|
|
const struct spa_dict *props);
|
|
static int (*pw_thread_loop_start_fn)(struct pw_thread_loop *loop);
|
|
static void (*pw_thread_loop_stop_fn)(struct pw_thread_loop *loop);
|
|
static void (*pw_thread_loop_lock_fn)(struct pw_thread_loop *loop);
|
|
static void (*pw_thread_loop_unlock_fn)(struct pw_thread_loop *loop);
|
|
static void (*pw_thread_loop_wait_fn)(struct pw_thread_loop *loop);
|
|
static void (*pw_thread_loop_signal_fn)(struct pw_thread_loop *loop, bool wait_for_accept);
|
|
static struct pw_properties* (*pw_properties_new_string_fn)(const char *str);
|
|
static const char* (*pw_get_library_version_fn)();
|
|
|
|
bool IsPwLibraryLoaded() {
|
|
static bool isLoaded =
|
|
(IS_FUNC_LOADED(pw_context_connect_fn) &&
|
|
IS_FUNC_LOADED(pw_context_connect_fd_fn) &&
|
|
IS_FUNC_LOADED(pw_context_destroy_fn) &&
|
|
IS_FUNC_LOADED(pw_context_new_fn) &&
|
|
IS_FUNC_LOADED(pw_core_disconnect_fn) &&
|
|
IS_FUNC_LOADED(pw_init_fn) &&
|
|
IS_FUNC_LOADED(pw_proxy_destroy_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_add_listener_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_connect_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_disconnect_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_dequeue_buffer_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_destroy_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_new_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_queue_buffer_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_state_as_string_fn) &&
|
|
IS_FUNC_LOADED(pw_stream_update_params_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_destroy_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_get_loop_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_new_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_start_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_stop_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_lock_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_unlock_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_signal_fn) &&
|
|
IS_FUNC_LOADED(pw_thread_loop_wait_fn) &&
|
|
IS_FUNC_LOADED(pw_properties_new_string_fn) &&
|
|
IS_FUNC_LOADED(pw_get_library_version_fn));
|
|
|
|
return isLoaded;
|
|
}
|
|
|
|
bool LoadPWLibrary() {
|
|
static PRLibrary* pwLib = nullptr;
|
|
static bool pwInitialized = false;
|
|
|
|
//TODO Thread safe
|
|
if (!pwInitialized) {
|
|
pwInitialized = true;
|
|
pwLib = PR_LoadLibrary("libpipewire-0.3.so.0");
|
|
if (!pwLib) {
|
|
return false;
|
|
}
|
|
|
|
GET_FUNC(pw_context_connect, pwLib);
|
|
GET_FUNC(pw_context_connect_fd, pwLib);
|
|
GET_FUNC(pw_context_destroy, pwLib);
|
|
GET_FUNC(pw_context_new, pwLib);
|
|
GET_FUNC(pw_core_disconnect, pwLib);
|
|
GET_FUNC(pw_init, pwLib);
|
|
GET_FUNC(pw_stream_add_listener, pwLib);
|
|
GET_FUNC(pw_stream_connect, pwLib);
|
|
GET_FUNC(pw_stream_disconnect, pwLib);
|
|
GET_FUNC(pw_stream_dequeue_buffer, pwLib);
|
|
GET_FUNC(pw_stream_destroy, pwLib);
|
|
GET_FUNC(pw_stream_new, pwLib);
|
|
GET_FUNC(pw_stream_queue_buffer, pwLib);
|
|
GET_FUNC(pw_stream_update_params, pwLib);
|
|
GET_FUNC(pw_stream_state_as_string, pwLib);
|
|
GET_FUNC(pw_thread_loop_destroy, pwLib);
|
|
GET_FUNC(pw_thread_loop_get_loop, pwLib);
|
|
GET_FUNC(pw_thread_loop_new, pwLib);
|
|
GET_FUNC(pw_thread_loop_start, pwLib);
|
|
GET_FUNC(pw_thread_loop_stop, pwLib);
|
|
GET_FUNC(pw_thread_loop_lock, pwLib);
|
|
GET_FUNC(pw_thread_loop_unlock, pwLib);
|
|
GET_FUNC(pw_thread_loop_signal, pwLib);
|
|
GET_FUNC(pw_thread_loop_wait, pwLib);
|
|
GET_FUNC(pw_properties_new_string, pwLib);
|
|
GET_FUNC(pw_get_library_version, pwLib);
|
|
GET_FUNC(pw_proxy_destroy, pwLib);
|
|
}
|
|
|
|
return IsPwLibraryLoaded();
|
|
}
|
|
|
|
struct pw_core *
|
|
pw_context_connect(struct pw_context *context,
|
|
struct pw_properties *properties,
|
|
size_t user_data_size)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_context_connect_fn(context, properties, user_data_size);
|
|
}
|
|
|
|
struct pw_core *
|
|
pw_context_connect_fd(struct pw_context *context,
|
|
int fd,
|
|
struct pw_properties *properties,
|
|
size_t user_data_size)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_context_connect_fd_fn(context, fd, properties, user_data_size);
|
|
}
|
|
|
|
void
|
|
pw_context_destroy(struct pw_context *context)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
pw_context_destroy_fn(context);
|
|
}
|
|
|
|
struct pw_context *
|
|
pw_context_new(struct pw_loop *main_loop,
|
|
struct pw_properties *props,
|
|
size_t user_data_size)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_context_new_fn(main_loop, props, user_data_size);
|
|
}
|
|
|
|
int
|
|
pw_core_disconnect(struct pw_core *core)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_core_disconnect_fn(core);
|
|
}
|
|
|
|
void
|
|
pw_init(int *argc, char **argv[])
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_init_fn(argc, argv);
|
|
}
|
|
|
|
void
|
|
pw_proxy_destroy(struct pw_proxy *proxy)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_proxy_destroy_fn(proxy);
|
|
}
|
|
|
|
void
|
|
pw_stream_add_listener(struct pw_stream *stream,
|
|
struct spa_hook *listener,
|
|
const struct pw_stream_events *events,
|
|
void *data)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_stream_add_listener_fn(stream, listener, events, data);
|
|
}
|
|
|
|
int
|
|
pw_stream_connect(struct pw_stream *stream,
|
|
enum pw_direction direction,
|
|
uint32_t target_id,
|
|
enum pw_stream_flags flags,
|
|
const struct spa_pod **params,
|
|
uint32_t n_params)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_stream_connect_fn(stream, direction, target_id, flags,
|
|
params, n_params);
|
|
}
|
|
|
|
int
|
|
pw_stream_disconnect(struct pw_stream *stream)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_stream_disconnect_fn(stream);
|
|
}
|
|
|
|
struct pw_buffer *
|
|
pw_stream_dequeue_buffer(struct pw_stream *stream)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_stream_dequeue_buffer_fn(stream);
|
|
}
|
|
|
|
void
|
|
pw_stream_destroy(struct pw_stream *stream)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_stream_destroy_fn(stream);
|
|
}
|
|
|
|
struct pw_stream *
|
|
pw_stream_new(struct pw_core *core,
|
|
const char *name,
|
|
struct pw_properties *props)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_stream_new_fn(core, name, props);
|
|
}
|
|
|
|
int
|
|
pw_stream_queue_buffer(struct pw_stream *stream,
|
|
struct pw_buffer *buffer)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_stream_queue_buffer_fn(stream, buffer);
|
|
}
|
|
|
|
const char *
|
|
pw_stream_state_as_string(enum pw_stream_state state)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_stream_state_as_string_fn(state);
|
|
}
|
|
|
|
int
|
|
pw_stream_update_params(struct pw_stream *stream,
|
|
const struct spa_pod **params,
|
|
uint32_t n_params)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_stream_update_params_fn(stream, params, n_params);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_destroy(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_destroy_fn(loop);
|
|
}
|
|
|
|
struct pw_loop *
|
|
pw_thread_loop_get_loop(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_thread_loop_get_loop_fn(loop);
|
|
}
|
|
|
|
struct pw_thread_loop *
|
|
pw_thread_loop_new(const char *name,
|
|
const struct spa_dict *props)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_thread_loop_new_fn(name, props);
|
|
}
|
|
|
|
int
|
|
pw_thread_loop_start(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return 0;
|
|
}
|
|
return pw_thread_loop_start_fn(loop);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_stop(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_stop_fn(loop);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_lock(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_lock_fn(loop);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_unlock(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_unlock_fn(loop);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_signal_fn(loop, wait_for_accept);
|
|
}
|
|
|
|
void
|
|
pw_thread_loop_wait(struct pw_thread_loop *loop)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return;
|
|
}
|
|
return pw_thread_loop_wait_fn(loop);
|
|
}
|
|
|
|
struct pw_properties *
|
|
pw_properties_new_string(const char *str)
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_properties_new_string_fn(str);
|
|
}
|
|
|
|
const char*
|
|
pw_get_library_version()
|
|
{
|
|
if (!LoadPWLibrary()) {
|
|
return nullptr;
|
|
}
|
|
return pw_get_library_version_fn();
|
|
}
|
|
|