LADI
/
spa
1
Fork 0
spa/src/pipewire/loop.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;
}