Rework support

Load the mapper from the support plugin
Move the support setup in pw_init
This commit is contained in:
Wim Taymans 2017-06-14 11:48:41 +02:00
parent b9c719ac7e
commit f55f1739e1
18 changed files with 192 additions and 278 deletions

View file

@ -445,12 +445,9 @@ struct pw_context *pw_context_new(struct pw_loop *loop,
spa_debug_set_type_map(this->type.map);
impl->support[0].type = SPA_TYPE__TypeMap;
impl->support[0].data = this->type.map;
impl->support[1].type = SPA_TYPE_LOOP__MainLoop;
impl->support[1].data = this->loop->loop;
impl->support[2].type = SPA_TYPE__Log;
impl->support[2].data = pw_log_get(impl->support, 2);
impl->support[0] = SPA_SUPPORT_INIT (SPA_TYPE__TypeMap, this->type.map);
impl->support[1] = SPA_SUPPORT_INIT (SPA_TYPE_LOOP__MainLoop, this->loop->loop);
impl->support[2] = SPA_SUPPORT_INIT (SPA_TYPE__Log, pw_log_get());
this->support = impl->support;
this->n_support = 3;

View file

@ -17,11 +17,6 @@
* Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <spa/log.h>
#include <pipewire/client/log.h>
@ -33,87 +28,23 @@ enum spa_log_level pw_log_level = DEFAULT_LOG_LEVEL;
static struct spa_log *global_log = NULL;
struct spa_log *pw_spa_log_load(const char *lib,
const char *factory_name,
struct spa_support *support,
uint32_t n_support)
/** Set the global log interface
* \param log the global log to set
* \memberof pw_log
*/
void pw_log_set(struct spa_log *log)
{
int res;
struct spa_handle *handle;
void *hnd;
uint32_t index, type_log;
spa_handle_factory_enum_func_t enum_func;
const struct spa_handle_factory *factory;
void *iface;
struct spa_type_map *map = NULL;
for (index = 0; index < n_support; index++) {
if (strcmp(support[index].type, SPA_TYPE__TypeMap) == 0)
map = support[index].data;
}
if (map == NULL) {
fprintf(stderr, "no type map\n");
return NULL;
}
type_log = spa_type_map_get_id(map, SPA_TYPE__Log);
if ((hnd = dlopen(lib, RTLD_NOW)) == NULL) {
fprintf(stderr, "can't load %s: %s\n", lib, dlerror());
return NULL;
}
if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
fprintf(stderr, "can't find enum function\n");
goto no_symbol;
}
for (index = 0;; index++) {
if ((res = enum_func(&factory, index)) < 0) {
if (res != SPA_RESULT_ENUM_END)
fprintf(stderr, "can't enumerate factories: %d\n", res);
goto enum_failed;
}
if (strcmp(factory->name, factory_name) == 0)
break;
}
handle = calloc(1, factory->size);
if ((res = spa_handle_factory_init(factory,
handle, NULL, support, n_support)) < 0) {
fprintf(stderr, "can't make factory instance: %d\n", res);
goto init_failed;
}
if ((res = spa_handle_get_interface(handle, type_log, &iface)) < 0) {
fprintf(stderr, "can't get log interface %d\n", res);
goto interface_failed;
}
return iface;
interface_failed:
spa_handle_clear(handle);
init_failed:
free(handle);
enum_failed:
no_symbol:
dlclose(hnd);
return NULL;
global_log = log;
if (global_log)
global_log->level = pw_log_level;
}
/** Get the global log interface
* \return the global log
* \memberof pw_log
*/
struct spa_log *pw_log_get(struct spa_support *support,
uint32_t n_support)
struct spa_log *pw_log_get(void)
{
if (global_log == NULL) {
global_log = pw_spa_log_load("build/spa/plugins/logger/libspa-logger.so",
"logger",
support,
n_support);
if (global_log)
global_log->level = pw_log_level;
}
return global_log;
}

View file

@ -39,7 +39,8 @@ extern "C" {
/** The global log level */
extern enum spa_log_level pw_log_level;
struct spa_log *pw_log_get(struct spa_support *support, uint32_t n_support);
void pw_log_set(struct spa_log *log);
struct spa_log *pw_log_get(void);
void
pw_log_set_level(enum spa_log_level level);

View file

@ -577,6 +577,37 @@ static void loop_destroy_source(struct spa_source *source)
spa_list_insert(&loop_impl->destroy_list, &impl->link);
}
static const struct spa_loop loop_impl = {
sizeof(struct spa_loop),
loop_add_source,
loop_update_source,
loop_remove_source,
loop_invoke,
};
static const struct spa_loop_control loop_control_impl = {
sizeof(struct spa_loop_control),
loop_get_fd,
loop_set_hooks,
loop_enter,
loop_leave,
loop_iterate,
};
static const struct spa_loop_utils loop_utils_impl = {
sizeof(struct spa_loop_utils),
loop_add_io,
loop_update_io,
loop_add_idle,
loop_enable_idle,
loop_add_event,
loop_signal_event,
loop_add_timer,
loop_update_timer,
loop_add_signal,
loop_destroy_source,
};
/** Create a new loop
* \returns a newly allocated loop
* \memberof pw_loop
@ -602,32 +633,13 @@ struct pw_loop *pw_loop_new(void)
pw_signal_init(&this->before_iterate);
pw_signal_init(&this->destroy_signal);
impl->loop.size = sizeof(struct spa_loop);
impl->loop.add_source = loop_add_source;
impl->loop.update_source = loop_update_source;
impl->loop.remove_source = loop_remove_source;
impl->loop.invoke = loop_invoke;
impl->loop = loop_impl;
this->loop = &impl->loop;
impl->control.size = sizeof(struct spa_loop_control);
impl->control.get_fd = loop_get_fd;
impl->control.set_hooks = loop_set_hooks;
impl->control.enter = loop_enter;
impl->control.leave = loop_leave;
impl->control.iterate = loop_iterate;
impl->control = loop_control_impl;
this->control = &impl->control;
impl->utils.size = sizeof(struct spa_loop_utils);
impl->utils.add_io = loop_add_io;
impl->utils.update_io = loop_update_io;
impl->utils.add_idle = loop_add_idle;
impl->utils.enable_idle = loop_enable_idle;
impl->utils.add_event = loop_add_event;
impl->utils.signal_event = loop_signal_event;
impl->utils.add_timer = loop_add_timer;
impl->utils.update_timer = loop_update_timer;
impl->utils.add_signal = loop_add_signal;
impl->utils.destroy_source = loop_destroy_source;
impl->utils = loop_utils_impl;
this->utils = &impl->utils;
spa_ringbuffer_init(&impl->buffer, DATAS_SIZE);

View file

@ -1,97 +0,0 @@
/* PipeWire
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <spa/type-map.h>
#include <pipewire/client/map.h>
/** \cond */
struct impl {
struct spa_type_map map;
struct pw_map types;
struct pw_array strings;
};
/** \endcond */
static uint32_t type_map_get_id(struct spa_type_map *map, const char *type)
{
struct impl *this = SPA_CONTAINER_OF(map, struct impl, map);
uint32_t i = 0, len;
void *p;
off_t o;
if (type != NULL) {
for (i = 0; i < pw_map_get_size(&this->types); i++) {
o = (off_t) pw_map_lookup_unchecked(&this->types, i);
if (strcmp(SPA_MEMBER(this->strings.data, o, char), type) == 0)
return i;
}
len = strlen(type);
p = pw_array_add(&this->strings, SPA_ROUND_UP_N(len + 1, 2));
memcpy(p, type, len + 1);
o = (p - this->strings.data);
i = pw_map_insert_new(&this->types, (void *) o);
}
return i;
}
static const char *type_map_get_type(const struct spa_type_map *map, uint32_t id)
{
struct impl *this = SPA_CONTAINER_OF(map, struct impl, map);
if (id == SPA_ID_INVALID)
return NULL;
if (SPA_LIKELY(pw_map_check_id(&this->types, id))) {
off_t o = (off_t) pw_map_lookup_unchecked(&this->types, id);
return SPA_MEMBER(this->strings.data, o, char);
}
return NULL;
}
static size_t type_map_get_size(const struct spa_type_map *map)
{
struct impl *this = SPA_CONTAINER_OF(map, struct impl, map);
return pw_map_get_size(&this->types);
}
static struct impl default_type_map = {
{sizeof(struct spa_type_map),
NULL,
type_map_get_id,
type_map_get_type,
type_map_get_size,
},
PW_MAP_INIT(128),
PW_ARRAY_INIT(4096)
};
/** Get the default type map
* \return the default type map
* \memberof pw_pipewire
*/
struct spa_type_map *pw_type_map_get_default(void)
{
return &default_type_map.map;
}

View file

@ -28,7 +28,6 @@ pipewire_sources = [
'introspect.c',
'log.c',
'loop.c',
'mapper.c',
'mem.c',
'properties.c',
'protocol-native.c',

View file

@ -22,11 +22,95 @@
#include <stdio.h>
#include <sys/prctl.h>
#include <pwd.h>
#include <errno.h>
#include <dlfcn.h>
#include "pipewire/client/pipewire.h"
static char **categories = NULL;
static struct support_info {
void *hnd;
spa_handle_factory_enum_func_t enum_func;
struct spa_support support[4];
uint32_t n_support;
} support_info;
static void * find_support(struct support_info *info, const char *type)
{
int i;
for (i = 0; i < info->n_support; i++) {
if (strcmp(info->support->type, type) == 0)
return info->support->data;
}
return NULL;
}
static bool
open_support(const char *lib,
struct support_info *info)
{
if ((info->hnd = dlopen(lib, RTLD_NOW)) == NULL) {
fprintf(stderr, "can't load %s: %s\n", lib, dlerror());
return false;
}
if ((info->enum_func = dlsym(info->hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
fprintf(stderr, "can't find enum function\n");
goto no_symbol;
}
return true;
no_symbol:
dlclose(info->hnd);
return false;
}
static void *
load_interface(struct support_info *info,
const char *factory_name,
const char *type)
{
int res;
struct spa_handle *handle;
uint32_t index, type_id;
const struct spa_handle_factory *factory;
void *iface;
struct spa_type_map *map = NULL;
map = find_support(info, SPA_TYPE__TypeMap);
type_id = map ? spa_type_map_get_id(map, type) : 0;
for (index = 0;; index++) {
if ((res = info->enum_func(&factory, index)) < 0) {
if (res != SPA_RESULT_ENUM_END)
fprintf(stderr, "can't enumerate factories: %d\n", res);
goto enum_failed;
}
if (strcmp(factory->name, factory_name) == 0)
break;
}
handle = calloc(1, factory->size);
if ((res = spa_handle_factory_init(factory,
handle, NULL, info->support, info->n_support)) < 0) {
fprintf(stderr, "can't make factory instance: %d\n", res);
goto init_failed;
}
if ((res = spa_handle_get_interface(handle, type_id, &iface)) < 0) {
fprintf(stderr, "can't get %s interface %d\n", type, res);
goto interface_failed;
}
return iface;
interface_failed:
spa_handle_clear(handle);
init_failed:
free(handle);
enum_failed:
return NULL;
}
static void configure_debug(const char *str)
{
char **level;
@ -40,6 +124,32 @@ static void configure_debug(const char *str)
categories = pw_split_strv(level[1], ",", INT_MAX, &n_tokens);
}
static void configure_support(struct support_info *info)
{
void *iface;
iface = load_interface(info, "mapper", SPA_TYPE__TypeMap);
if (iface != NULL) {
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface);
}
iface = load_interface(info, "logger", SPA_TYPE__Log);
if (iface != NULL) {
info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface);
pw_log_set(iface);
}
}
/** Get a support interface
* \param type the interface type
* \return the interface or NULL when not configured
*/
void *pw_get_support(const char *type)
{
return find_support(&support_info, type);
}
/** Initialize PipeWire
*
* \param argc pointer to argc
@ -58,6 +168,9 @@ void pw_init(int *argc, char **argv[])
if ((str = getenv("PIPEWIRE_DEBUG")))
configure_debug(str);
if (open_support("build/spa/plugins/support/libspa-support.so", &support_info))
configure_support(&support_info);
}
/** Check if a debug category is enabled

View file

@ -119,8 +119,8 @@ pw_fill_stream_properties(struct pw_properties *properties);
enum pw_direction
pw_direction_reverse(enum pw_direction direction);
struct spa_type_map *
pw_type_map_get_default(void);
void *
pw_get_support(const char *type);
#ifdef __cplusplus
}

View file

@ -37,7 +37,7 @@
*/
void pw_type_init(struct pw_type *type)
{
type->map = pw_type_map_get_default();
type->map = pw_get_support(SPA_TYPE__TypeMap);
type->core = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Core);
type->registry = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Registry);

View file

@ -287,14 +287,10 @@ struct pw_core *pw_core_new(struct pw_main_loop *main_loop, struct pw_properties
spa_debug_set_type_map(this->type.map);
impl->support[0].type = SPA_TYPE__TypeMap;
impl->support[0].data = this->type.map;
impl->support[1].type = SPA_TYPE_LOOP__DataLoop;
impl->support[1].data = this->data_loop->loop->loop;
impl->support[2].type = SPA_TYPE_LOOP__MainLoop;
impl->support[2].data = this->main_loop->loop->loop;
impl->support[3].type = SPA_TYPE__Log;
impl->support[3].data = pw_log_get(impl->support, 3);
impl->support[0] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, this->type.map);
impl->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__DataLoop, this->data_loop->loop->loop);
impl->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__MainLoop, this->main_loop->loop->loop);
impl->support[3] = SPA_SUPPORT_INIT(SPA_TYPE__Log, pw_log_get());
this->support = impl->support;
this->n_support = 4;

View file

@ -85,6 +85,8 @@ struct spa_support {
void *data;
};
#define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) }
struct spa_handle_factory {
/**
* spa_handle_factory::name

View file

@ -1,9 +0,0 @@
spa_logger_sources = ['logger.c', 'plugin.c']
spa_logger_lib = shared_library('spa-logger',
spa_logger_sources,
include_directories : [ spa_inc, spa_libinc],
dependencies : threads_dep,
link_with : spalib,
install : true,
install_dir : '@0@/spa'.format(get_option('libdir')))

View file

@ -1,38 +0,0 @@
/* Spa Video Test Source plugin
* Copyright (C) 2016 Axis Communications AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <spa/plugin.h>
#include <spa/node.h>
extern const struct spa_handle_factory spa_logger_factory;
int
spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t index)
{
spa_return_val_if_fail(factory != NULL, SPA_RESULT_INVALID_ARGUMENTS);
switch (index) {
case 0:
*factory = &spa_logger_factory;
break;
default:
return SPA_RESULT_ENUM_END;
}
return SPA_RESULT_OK;
}

View file

@ -2,7 +2,6 @@ subdir('alsa')
subdir('audiomixer')
subdir('audiotestsrc')
subdir('ffmpeg')
subdir('logger')
subdir('support')
subdir('test')
subdir('videotestsrc')

View file

@ -77,11 +77,13 @@ static uint32_t
impl_type_map_get_id(struct spa_type_map *map, const char *type)
{
struct impl *impl = SPA_CONTAINER_OF(map, struct impl, map);
uint32_t i = 0, len;
uint32_t i, len;
void *p;
off_t o, *off;
if (type != NULL) {
if (type == NULL)
return SPA_ID_INVALID;
for (i = 0; i < impl->types.size / sizeof(off_t); i++) {
o = ((off_t *)impl->types.data)[i];
if (strcmp(SPA_MEMBER(impl->strings.data, o, char), type) == 0)
@ -94,7 +96,7 @@ impl_type_map_get_id(struct spa_type_map *map, const char *type)
off = alloc_size(&impl->types, sizeof(off_t), 128);
*off = SPA_PTRDIFF(p, impl->strings.data);
i = SPA_PTRDIFF(off, impl->types.data) / sizeof(off_t);
}
return i;
}

View file

@ -1,4 +1,6 @@
spa_support_sources = ['mapper.c', 'plugin.c']
spa_support_sources = ['mapper.c',
'logger.c',
'plugin.c']
spa_support_lib = shared_library('spa-support',
spa_support_sources,

View file

@ -20,6 +20,7 @@
#include <spa/plugin.h>
#include <spa/node.h>
extern const struct spa_handle_factory spa_logger_factory;
extern const struct spa_handle_factory spa_type_map_factory;
int
@ -31,6 +32,9 @@ spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t inde
case 0:
*factory = &spa_type_map_factory;
break;
case 1:
*factory = &spa_logger_factory;
break;
default:
return SPA_RESULT_ENUM_END;
}