174 lines
4.1 KiB
C
174 lines
4.1 KiB
C
/* PipeWire */
|
|
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
|
/* SPDX-License-Identifier: MIT */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <spa/support/loop.h>
|
|
#include <spa/utils/names.h>
|
|
#include <spa/utils/result.h>
|
|
|
|
#include <pipewire/pipewire.h>
|
|
#include <pipewire/private.h>
|
|
#include <pipewire/loop.h>
|
|
#include <pipewire/log.h>
|
|
#include <pipewire/type.h>
|
|
|
|
PW_LOG_TOPIC_EXTERN(log_loop);
|
|
#define PW_LOG_TOPIC_DEFAULT log_loop
|
|
|
|
/** \cond */
|
|
|
|
struct impl {
|
|
struct pw_loop this;
|
|
|
|
struct spa_handle *system_handle;
|
|
struct spa_handle *loop_handle;
|
|
|
|
void *user_data;
|
|
const struct pw_loop_callbacks *cb;
|
|
};
|
|
/** \endcond */
|
|
|
|
/** Create a new loop
|
|
* \returns a newly allocated loop
|
|
*/
|
|
SPA_EXPORT
|
|
struct pw_loop *pw_loop_new(const struct spa_dict *props)
|
|
{
|
|
int res;
|
|
struct impl *impl;
|
|
struct pw_loop *this;
|
|
void *iface;
|
|
struct spa_support support[32];
|
|
uint32_t n_support;
|
|
const char *lib;
|
|
|
|
n_support = pw_get_support(support, 32);
|
|
|
|
impl = calloc(1, sizeof(struct impl));
|
|
if (impl == NULL) {
|
|
res = -errno;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
this = &impl->this;
|
|
|
|
if (props)
|
|
lib = spa_dict_lookup(props, PW_KEY_LIBRARY_NAME_SYSTEM);
|
|
else
|
|
lib = NULL;
|
|
|
|
impl->system_handle = pw_load_spa_handle(lib,
|
|
SPA_NAME_SUPPORT_SYSTEM,
|
|
props, n_support, support);
|
|
if (impl->system_handle == NULL) {
|
|
res = -errno;
|
|
pw_log_error("%p: can't make "SPA_NAME_SUPPORT_SYSTEM" handle: %m", this);
|
|
goto error_free;
|
|
}
|
|
|
|
if ((res = spa_handle_get_interface(impl->system_handle,
|
|
SPA_TYPE_INTERFACE_System,
|
|
&iface)) < 0) {
|
|
pw_log_error("%p: can't get System interface: %s", this, spa_strerror(res));
|
|
goto error_unload_system;
|
|
}
|
|
this->system = iface;
|
|
|
|
support[n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_System, iface);
|
|
|
|
if (props)
|
|
lib = spa_dict_lookup(props, PW_KEY_LIBRARY_NAME_LOOP);
|
|
else
|
|
lib = NULL;
|
|
|
|
impl->loop_handle = pw_load_spa_handle(lib,
|
|
SPA_NAME_SUPPORT_LOOP, props,
|
|
n_support, support);
|
|
if (impl->loop_handle == NULL) {
|
|
res = -errno;
|
|
pw_log_error("%p: can't make "SPA_NAME_SUPPORT_LOOP" handle: %m", this);
|
|
goto error_unload_system;
|
|
}
|
|
|
|
if ((res = spa_handle_get_interface(impl->loop_handle,
|
|
SPA_TYPE_INTERFACE_Loop,
|
|
&iface)) < 0) {
|
|
pw_log_error("%p: can't get Loop interface: %s",
|
|
this, spa_strerror(res));
|
|
goto error_unload_loop;
|
|
}
|
|
this->loop = iface;
|
|
|
|
if ((res = spa_handle_get_interface(impl->loop_handle,
|
|
SPA_TYPE_INTERFACE_LoopControl,
|
|
&iface)) < 0) {
|
|
pw_log_error("%p: can't get LoopControl interface: %s",
|
|
this, spa_strerror(res));
|
|
goto error_unload_loop;
|
|
}
|
|
this->control = iface;
|
|
if (!spa_interface_callback_check(&this->control->iface,
|
|
struct spa_loop_control_methods, iterate, 0)) {
|
|
res = -EINVAL;
|
|
pw_log_error("%p: loop does not support iterate", this);
|
|
goto error_unload_loop;
|
|
}
|
|
|
|
if ((res = spa_handle_get_interface(impl->loop_handle,
|
|
SPA_TYPE_INTERFACE_LoopUtils,
|
|
&iface)) < 0) {
|
|
pw_log_error("%p: can't get LoopUtils interface: %s",
|
|
this, spa_strerror(res));
|
|
goto error_unload_loop;
|
|
}
|
|
this->utils = iface;
|
|
|
|
return this;
|
|
|
|
error_unload_loop:
|
|
pw_unload_spa_handle(impl->loop_handle);
|
|
error_unload_system:
|
|
pw_unload_spa_handle(impl->system_handle);
|
|
error_free:
|
|
free(impl);
|
|
error_cleanup:
|
|
errno = -res;
|
|
return NULL;
|
|
}
|
|
|
|
/** Destroy a loop
|
|
* \param loop a loop to destroy
|
|
*/
|
|
SPA_EXPORT
|
|
void pw_loop_destroy(struct pw_loop *loop)
|
|
{
|
|
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
|
|
|
pw_unload_spa_handle(impl->loop_handle);
|
|
pw_unload_spa_handle(impl->system_handle);
|
|
free(impl);
|
|
}
|
|
|
|
void
|
|
pw_loop_set_callbacks(struct pw_loop *loop, const struct pw_loop_callbacks *cb, void *data)
|
|
{
|
|
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
|
|
|
impl->user_data = data;
|
|
impl->cb = cb;
|
|
}
|
|
|
|
SPA_EXPORT
|
|
int pw_loop_check(struct pw_loop *loop)
|
|
{
|
|
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
|
int res;
|
|
if (impl->cb && impl->cb->check)
|
|
res = impl->cb->check(impl->user_data, loop);
|
|
else
|
|
res = spa_loop_control_check(loop->control);
|
|
return res;
|
|
}
|