mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-13 08:56:39 -05:00
indent
This commit is contained in:
parent
d1a06ae247
commit
5b037661d9
154 changed files with 21017 additions and 23044 deletions
|
|
@ -27,16 +27,16 @@ extern "C" {
|
|||
#include <spa/defs.h>
|
||||
|
||||
struct pw_array {
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t alloc;
|
||||
size_t extend;
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t alloc;
|
||||
size_t extend;
|
||||
};
|
||||
|
||||
#define PW_ARRAY_INIT(extend) { NULL, 0, 0, extend }
|
||||
|
||||
#define pw_array_get_len_s(a,s) ((a)->size / (s))
|
||||
#define pw_array_get_unchecked_s(a,idx,s,t) SPA_MEMBER ((a)->data,(idx)*(s),t)
|
||||
#define pw_array_get_unchecked_s(a,idx,s,t) SPA_MEMBER((a)->data,(idx)*(s),t)
|
||||
#define pw_array_check_index_s(a,idx,s) ((idx) < pw_array_get_len(a,s))
|
||||
|
||||
#define pw_array_get_len(a,t) pw_array_get_len_s(a,sizeof(t))
|
||||
|
|
@ -44,78 +44,70 @@ struct pw_array {
|
|||
#define pw_array_check_index(a,idx,t) pw_array_check_index_s(a,idx,sizeof(t))
|
||||
|
||||
#define pw_array_for_each(pos, array) \
|
||||
for (pos = (array)->data; \
|
||||
(const uint8_t *) pos < ((const uint8_t *) (array)->data + (array)->size); \
|
||||
(pos)++)
|
||||
for (pos = (array)->data; \
|
||||
(const uint8_t *) pos < ((const uint8_t *) (array)->data + (array)->size); \
|
||||
(pos)++)
|
||||
|
||||
static inline void
|
||||
pw_array_init (struct pw_array *arr, size_t extend)
|
||||
static inline void pw_array_init(struct pw_array *arr, size_t extend)
|
||||
{
|
||||
arr->data = NULL;
|
||||
arr->size = arr->alloc = 0;
|
||||
arr->extend = extend;
|
||||
arr->data = NULL;
|
||||
arr->size = arr->alloc = 0;
|
||||
arr->extend = extend;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pw_array_clear (struct pw_array *arr)
|
||||
static inline void pw_array_clear(struct pw_array *arr)
|
||||
{
|
||||
free (arr->data);
|
||||
free(arr->data);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pw_array_ensure_size (struct pw_array *arr,
|
||||
size_t size)
|
||||
static inline bool pw_array_ensure_size(struct pw_array *arr, size_t size)
|
||||
{
|
||||
size_t alloc, need;
|
||||
size_t alloc, need;
|
||||
|
||||
alloc = arr->alloc;
|
||||
need = arr->size + size;
|
||||
alloc = arr->alloc;
|
||||
need = arr->size + size;
|
||||
|
||||
if (SPA_UNLIKELY (alloc < need)) {
|
||||
void *data;
|
||||
alloc = SPA_MAX (alloc, arr->extend);
|
||||
while (alloc < need)
|
||||
alloc *= 2;
|
||||
if (SPA_UNLIKELY ((data = realloc (arr->data, alloc)) == NULL))
|
||||
return false;
|
||||
arr->data = data;
|
||||
arr->alloc = alloc;
|
||||
}
|
||||
return true;
|
||||
if (SPA_UNLIKELY(alloc < need)) {
|
||||
void *data;
|
||||
alloc = SPA_MAX(alloc, arr->extend);
|
||||
while (alloc < need)
|
||||
alloc *= 2;
|
||||
if (SPA_UNLIKELY((data = realloc(arr->data, alloc)) == NULL))
|
||||
return false;
|
||||
arr->data = data;
|
||||
arr->alloc = alloc;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
pw_array_add (struct pw_array *arr,
|
||||
size_t size)
|
||||
static inline void *pw_array_add(struct pw_array *arr, size_t size)
|
||||
{
|
||||
void *p;
|
||||
void *p;
|
||||
|
||||
if (!pw_array_ensure_size (arr, size))
|
||||
return NULL;
|
||||
if (!pw_array_ensure_size(arr, size))
|
||||
return NULL;
|
||||
|
||||
p = arr->data + arr->size;
|
||||
arr->size += size;
|
||||
p = arr->data + arr->size;
|
||||
arr->size += size;
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
pw_array_add_fixed (struct pw_array *arr,
|
||||
size_t size)
|
||||
static inline void *pw_array_add_fixed(struct pw_array *arr, size_t size)
|
||||
{
|
||||
void *p;
|
||||
void *p;
|
||||
|
||||
if (SPA_UNLIKELY (arr->alloc < arr->size + size))
|
||||
return NULL;
|
||||
if (SPA_UNLIKELY(arr->alloc < arr->size + size))
|
||||
return NULL;
|
||||
|
||||
p = arr->data + arr->size;
|
||||
arr->size += size;
|
||||
p = arr->data + arr->size;
|
||||
arr->size += size;
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
||||
#define pw_array_add_ptr(a,p) \
|
||||
*((void**) pw_array_add (a, sizeof (void*))) = (p)
|
||||
*((void**) pw_array_add(a, sizeof(void*))) = (p)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -32,181 +32,172 @@
|
|||
#define MAX_FDS 28
|
||||
|
||||
struct buffer {
|
||||
uint8_t *buffer_data;
|
||||
size_t buffer_size;
|
||||
size_t buffer_maxsize;
|
||||
int fds[MAX_FDS];
|
||||
uint32_t n_fds;
|
||||
uint8_t *buffer_data;
|
||||
size_t buffer_size;
|
||||
size_t buffer_maxsize;
|
||||
int fds[MAX_FDS];
|
||||
uint32_t n_fds;
|
||||
|
||||
off_t offset;
|
||||
void *data;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
void *data;
|
||||
size_t size;
|
||||
|
||||
bool update;
|
||||
bool update;
|
||||
};
|
||||
|
||||
struct pw_connection_impl {
|
||||
struct pw_connection this;
|
||||
struct pw_connection this;
|
||||
|
||||
struct buffer in, out;
|
||||
struct buffer in, out;
|
||||
};
|
||||
|
||||
int
|
||||
pw_connection_get_fd (struct pw_connection *conn,
|
||||
uint32_t index)
|
||||
int pw_connection_get_fd(struct pw_connection *conn, uint32_t index)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
|
||||
if (index < 0 || index >= impl->in.n_fds)
|
||||
return -1;
|
||||
if (index < 0 || index >= impl->in.n_fds)
|
||||
return -1;
|
||||
|
||||
return impl->in.fds[index];
|
||||
return impl->in.fds[index];
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pw_connection_add_fd (struct pw_connection *conn,
|
||||
int fd)
|
||||
uint32_t pw_connection_add_fd(struct pw_connection * conn, int fd)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
uint32_t index, i;
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
uint32_t index, i;
|
||||
|
||||
for (i = 0; i < impl->out.n_fds; i++) {
|
||||
if (impl->out.fds[i] == fd)
|
||||
return i;
|
||||
}
|
||||
for (i = 0; i < impl->out.n_fds; i++) {
|
||||
if (impl->out.fds[i] == fd)
|
||||
return i;
|
||||
}
|
||||
|
||||
index = impl->out.n_fds;
|
||||
if (index >= MAX_FDS) {
|
||||
pw_log_error ("connection %p: too many fds", conn);
|
||||
return -1;
|
||||
}
|
||||
index = impl->out.n_fds;
|
||||
if (index >= MAX_FDS) {
|
||||
pw_log_error("connection %p: too many fds", conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
impl->out.fds[index] = fd;
|
||||
impl->out.n_fds++;
|
||||
impl->out.fds[index] = fd;
|
||||
impl->out.n_fds++;
|
||||
|
||||
return index;
|
||||
return index;
|
||||
}
|
||||
|
||||
static void *
|
||||
connection_ensure_size (struct pw_connection *conn, struct buffer *buf, size_t size)
|
||||
static void *connection_ensure_size(struct pw_connection *conn, struct buffer *buf, size_t size)
|
||||
{
|
||||
if (buf->buffer_size + size > buf->buffer_maxsize) {
|
||||
buf->buffer_maxsize = SPA_ROUND_UP_N (buf->buffer_size + size, MAX_BUFFER_SIZE);
|
||||
buf->buffer_data = realloc (buf->buffer_data, buf->buffer_maxsize);
|
||||
if (buf->buffer_size + size > buf->buffer_maxsize) {
|
||||
buf->buffer_maxsize = SPA_ROUND_UP_N(buf->buffer_size + size, MAX_BUFFER_SIZE);
|
||||
buf->buffer_data = realloc(buf->buffer_data, buf->buffer_maxsize);
|
||||
|
||||
pw_log_warn ("connection %p: resize buffer to %zd %zd %zd",
|
||||
conn, buf->buffer_size, size, buf->buffer_maxsize);
|
||||
}
|
||||
return (uint8_t *) buf->buffer_data + buf->buffer_size;
|
||||
pw_log_warn("connection %p: resize buffer to %zd %zd %zd",
|
||||
conn, buf->buffer_size, size, buf->buffer_maxsize);
|
||||
}
|
||||
return (uint8_t *) buf->buffer_data + buf->buffer_size;
|
||||
}
|
||||
|
||||
static bool
|
||||
refill_buffer (struct pw_connection *conn, struct buffer *buf)
|
||||
static bool refill_buffer(struct pw_connection *conn, struct buffer *buf)
|
||||
{
|
||||
ssize_t len;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))];
|
||||
ssize_t len;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg = { 0 };
|
||||
struct iovec iov[1];
|
||||
char cmsgbuf[CMSG_SPACE(MAX_FDS * sizeof(int))];
|
||||
|
||||
iov[0].iov_base = buf->buffer_data + buf->buffer_size;
|
||||
iov[0].iov_len = buf->buffer_maxsize - buf->buffer_size;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof (cmsgbuf);
|
||||
msg.msg_flags = MSG_CMSG_CLOEXEC;
|
||||
iov[0].iov_base = buf->buffer_data + buf->buffer_size;
|
||||
iov[0].iov_len = buf->buffer_maxsize - buf->buffer_size;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
msg.msg_flags = MSG_CMSG_CLOEXEC;
|
||||
|
||||
while (true) {
|
||||
len = recvmsg (conn->fd, &msg, msg.msg_flags);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto recv_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (true) {
|
||||
len = recvmsg(conn->fd, &msg, msg.msg_flags);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto recv_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buf->buffer_size += len;
|
||||
buf->buffer_size += len;
|
||||
|
||||
/* handle control messages */
|
||||
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
/* handle control messages */
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
buf->n_fds = (cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) / sizeof (int);
|
||||
memcpy (buf->fds, CMSG_DATA (cmsg), buf->n_fds * sizeof (int));
|
||||
}
|
||||
pw_log_trace ("connection %p: %d read %zd bytes and %d fds", conn, conn->fd, len, buf->n_fds);
|
||||
buf->n_fds =
|
||||
(cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) / sizeof(int);
|
||||
memcpy(buf->fds, CMSG_DATA(cmsg), buf->n_fds * sizeof(int));
|
||||
}
|
||||
pw_log_trace("connection %p: %d read %zd bytes and %d fds", conn, conn->fd, len,
|
||||
buf->n_fds);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
|
||||
/* ERRORS */
|
||||
recv_error:
|
||||
{
|
||||
pw_log_error ("could not recvmsg on fd %d: %s", conn->fd, strerror (errno));
|
||||
return false;
|
||||
}
|
||||
/* ERRORS */
|
||||
recv_error:
|
||||
pw_log_error("could not recvmsg on fd %d: %s", conn->fd, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_buffer (struct buffer *buf)
|
||||
static void clear_buffer(struct buffer *buf)
|
||||
{
|
||||
buf->n_fds = 0;
|
||||
buf->offset = 0;
|
||||
buf->size = 0;
|
||||
buf->buffer_size = 0;
|
||||
buf->n_fds = 0;
|
||||
buf->offset = 0;
|
||||
buf->size = 0;
|
||||
buf->buffer_size = 0;
|
||||
}
|
||||
|
||||
struct pw_connection *
|
||||
pw_connection_new (int fd)
|
||||
struct pw_connection *pw_connection_new(int fd)
|
||||
{
|
||||
struct pw_connection_impl *impl;
|
||||
struct pw_connection *this;
|
||||
struct pw_connection_impl *impl;
|
||||
struct pw_connection *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct pw_connection_impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct pw_connection_impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this = &impl->this;
|
||||
|
||||
pw_log_debug ("connection %p: new", this);
|
||||
pw_log_debug("connection %p: new", this);
|
||||
|
||||
this->fd = fd;
|
||||
pw_signal_init (&this->need_flush);
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
this->fd = fd;
|
||||
pw_signal_init(&this->need_flush);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
impl->out.buffer_data = malloc (MAX_BUFFER_SIZE);
|
||||
impl->out.buffer_maxsize = MAX_BUFFER_SIZE;
|
||||
impl->in.buffer_data = malloc (MAX_BUFFER_SIZE);
|
||||
impl->in.buffer_maxsize = MAX_BUFFER_SIZE;
|
||||
impl->in.update = true;
|
||||
impl->out.buffer_data = malloc(MAX_BUFFER_SIZE);
|
||||
impl->out.buffer_maxsize = MAX_BUFFER_SIZE;
|
||||
impl->in.buffer_data = malloc(MAX_BUFFER_SIZE);
|
||||
impl->in.buffer_maxsize = MAX_BUFFER_SIZE;
|
||||
impl->in.update = true;
|
||||
|
||||
if (impl->out.buffer_data == NULL || impl->in.buffer_data == NULL)
|
||||
goto no_mem;
|
||||
if (impl->out.buffer_data == NULL || impl->in.buffer_data == NULL)
|
||||
goto no_mem;
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
no_mem:
|
||||
free (impl->out.buffer_data);
|
||||
free (impl->in.buffer_data);
|
||||
free (impl);
|
||||
return NULL;
|
||||
no_mem:
|
||||
free(impl->out.buffer_data);
|
||||
free(impl->in.buffer_data);
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_connection_destroy (struct pw_connection *conn)
|
||||
void pw_connection_destroy(struct pw_connection *conn)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
|
||||
pw_log_debug ("connection %p: destroy", conn);
|
||||
pw_log_debug("connection %p: destroy", conn);
|
||||
|
||||
pw_signal_emit (&conn->destroy_signal, conn);
|
||||
pw_signal_emit(&conn->destroy_signal, conn);
|
||||
|
||||
free (impl->out.buffer_data);
|
||||
free (impl->in.buffer_data);
|
||||
free (impl);
|
||||
free(impl->out.buffer_data);
|
||||
free(impl->in.buffer_data);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -218,179 +209,169 @@ pw_connection_destroy (struct pw_connection *conn)
|
|||
* Returns: %true if more packets are available.
|
||||
*/
|
||||
bool
|
||||
pw_connection_get_next (struct pw_connection *conn,
|
||||
uint8_t *opcode,
|
||||
uint32_t *dest_id,
|
||||
void **dt,
|
||||
uint32_t *sz)
|
||||
pw_connection_get_next(struct pw_connection *conn,
|
||||
uint8_t * opcode,
|
||||
uint32_t * dest_id,
|
||||
void **dt,
|
||||
uint32_t * sz)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
size_t len, size;
|
||||
uint8_t *data;
|
||||
struct buffer *buf;
|
||||
uint32_t *p;
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
size_t len, size;
|
||||
uint8_t *data;
|
||||
struct buffer *buf;
|
||||
uint32_t *p;
|
||||
|
||||
buf = &impl->in;
|
||||
buf = &impl->in;
|
||||
|
||||
/* move to next packet */
|
||||
buf->offset += buf->size;
|
||||
/* move to next packet */
|
||||
buf->offset += buf->size;
|
||||
|
||||
again:
|
||||
if (buf->update) {
|
||||
if (!refill_buffer (conn, buf))
|
||||
return false;
|
||||
buf->update = false;
|
||||
}
|
||||
again:
|
||||
if (buf->update) {
|
||||
if (!refill_buffer(conn, buf))
|
||||
return false;
|
||||
buf->update = false;
|
||||
}
|
||||
|
||||
/* now read packet */
|
||||
data = buf->buffer_data;
|
||||
size = buf->buffer_size;
|
||||
/* now read packet */
|
||||
data = buf->buffer_data;
|
||||
size = buf->buffer_size;
|
||||
|
||||
if (buf->offset >= size) {
|
||||
clear_buffer (buf);
|
||||
buf->update = true;
|
||||
return false;
|
||||
}
|
||||
if (buf->offset >= size) {
|
||||
clear_buffer(buf);
|
||||
buf->update = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
data += buf->offset;
|
||||
size -= buf->offset;
|
||||
data += buf->offset;
|
||||
size -= buf->offset;
|
||||
|
||||
if (size < 8) {
|
||||
connection_ensure_size (conn, buf, 8);
|
||||
buf->update = true;
|
||||
goto again;
|
||||
}
|
||||
p = (uint32_t *) data;
|
||||
data += 8;
|
||||
size -= 8;
|
||||
if (size < 8) {
|
||||
connection_ensure_size(conn, buf, 8);
|
||||
buf->update = true;
|
||||
goto again;
|
||||
}
|
||||
p = (uint32_t *) data;
|
||||
data += 8;
|
||||
size -= 8;
|
||||
|
||||
*dest_id = p[0];
|
||||
*opcode = p[1] >> 24;
|
||||
len = p[1] & 0xffffff;
|
||||
*dest_id = p[0];
|
||||
*opcode = p[1] >> 24;
|
||||
len = p[1] & 0xffffff;
|
||||
|
||||
if (len > size) {
|
||||
connection_ensure_size (conn, buf, len);
|
||||
buf->update = true;
|
||||
goto again;
|
||||
}
|
||||
buf->size = len;
|
||||
buf->data = data;
|
||||
buf->offset += 8;
|
||||
if (len > size) {
|
||||
connection_ensure_size(conn, buf, len);
|
||||
buf->update = true;
|
||||
goto again;
|
||||
}
|
||||
buf->size = len;
|
||||
buf->data = data;
|
||||
buf->offset += 8;
|
||||
|
||||
*dt = buf->data;
|
||||
*sz = buf->size;
|
||||
*dt = buf->data;
|
||||
*sz = buf->size;
|
||||
|
||||
// spa_debug_pod (data);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
pw_connection_begin_write (struct pw_connection *conn,
|
||||
uint32_t size)
|
||||
void *pw_connection_begin_write(struct pw_connection *conn, uint32_t size)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
uint32_t *p;
|
||||
struct buffer *buf = &impl->out;
|
||||
/* 4 for dest_id, 1 for opcode, 3 for size and size for payload */
|
||||
p = connection_ensure_size (conn, buf, 8 + size);
|
||||
return p + 2;
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
uint32_t *p;
|
||||
struct buffer *buf = &impl->out;
|
||||
/* 4 for dest_id, 1 for opcode, 3 for size and size for payload */
|
||||
p = connection_ensure_size(conn, buf, 8 + size);
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
void
|
||||
pw_connection_end_write (struct pw_connection *conn,
|
||||
uint32_t dest_id,
|
||||
uint8_t opcode,
|
||||
uint32_t size)
|
||||
pw_connection_end_write(struct pw_connection *conn, uint32_t dest_id, uint8_t opcode, uint32_t size)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
uint32_t *p;
|
||||
struct buffer *buf = &impl->out;
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
uint32_t *p;
|
||||
struct buffer *buf = &impl->out;
|
||||
|
||||
p = connection_ensure_size (conn, buf, 8 + size);
|
||||
*p++ = dest_id;
|
||||
*p++ = (opcode << 24) | (size & 0xffffff);
|
||||
p = connection_ensure_size(conn, buf, 8 + size);
|
||||
*p++ = dest_id;
|
||||
*p++ = (opcode << 24) | (size & 0xffffff);
|
||||
|
||||
buf->buffer_size += 8 + size;
|
||||
buf->buffer_size += 8 + size;
|
||||
|
||||
// spa_debug_pod (p);
|
||||
|
||||
pw_signal_emit (&conn->need_flush, conn);
|
||||
pw_signal_emit(&conn->need_flush, conn);
|
||||
}
|
||||
|
||||
bool
|
||||
pw_connection_flush (struct pw_connection *conn)
|
||||
bool pw_connection_flush(struct pw_connection *conn)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
ssize_t len;
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg;
|
||||
char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))];
|
||||
int *cm, i, fds_len;
|
||||
struct buffer *buf;
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
ssize_t len;
|
||||
struct msghdr msg = { 0 };
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg;
|
||||
char cmsgbuf[CMSG_SPACE(MAX_FDS * sizeof(int))];
|
||||
int *cm, i, fds_len;
|
||||
struct buffer *buf;
|
||||
|
||||
buf = &impl->out;
|
||||
buf = &impl->out;
|
||||
|
||||
if (buf->buffer_size == 0)
|
||||
return true;
|
||||
if (buf->buffer_size == 0)
|
||||
return true;
|
||||
|
||||
fds_len = buf->n_fds * sizeof (int);
|
||||
fds_len = buf->n_fds * sizeof(int);
|
||||
|
||||
iov[0].iov_base = buf->buffer_data;
|
||||
iov[0].iov_len = buf->buffer_size;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
iov[0].iov_base = buf->buffer_data;
|
||||
iov[0].iov_len = buf->buffer_size;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
if (buf->n_fds > 0) {
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = CMSG_SPACE (fds_len);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN (fds_len);
|
||||
cm = (int*)CMSG_DATA (cmsg);
|
||||
for (i = 0; i < buf->n_fds; i++)
|
||||
cm[i] = buf->fds[i] > 0 ? buf->fds[i] : -buf->fds[i];
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
} else {
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
}
|
||||
if (buf->n_fds > 0) {
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = CMSG_SPACE(fds_len);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(fds_len);
|
||||
cm = (int *) CMSG_DATA(cmsg);
|
||||
for (i = 0; i < buf->n_fds; i++)
|
||||
cm[i] = buf->fds[i] > 0 ? buf->fds[i] : -buf->fds[i];
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
} else {
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
len = sendmsg (conn->fd, &msg, MSG_NOSIGNAL);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto send_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pw_log_trace ("connection %p: %d written %zd bytes and %u fds", conn, conn->fd, len, buf->n_fds);
|
||||
while (true) {
|
||||
len = sendmsg(conn->fd, &msg, MSG_NOSIGNAL);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto send_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pw_log_trace("connection %p: %d written %zd bytes and %u fds", conn, conn->fd, len,
|
||||
buf->n_fds);
|
||||
|
||||
buf->buffer_size -= len;
|
||||
buf->n_fds = 0;
|
||||
buf->buffer_size -= len;
|
||||
buf->n_fds = 0;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
|
||||
/* ERRORS */
|
||||
send_error:
|
||||
{
|
||||
pw_log_error ("could not sendmsg: %s", strerror (errno));
|
||||
return false;
|
||||
}
|
||||
/* ERRORS */
|
||||
send_error:
|
||||
pw_log_error("could not sendmsg: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
pw_connection_clear (struct pw_connection *conn)
|
||||
bool pw_connection_clear(struct pw_connection * conn)
|
||||
{
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF (conn, struct pw_connection_impl, this);
|
||||
struct pw_connection_impl *impl = SPA_CONTAINER_OF(conn, struct pw_connection_impl, this);
|
||||
|
||||
clear_buffer (&impl->out);
|
||||
clear_buffer (&impl->in);
|
||||
impl->in.update = true;
|
||||
clear_buffer(&impl->out);
|
||||
clear_buffer(&impl->in);
|
||||
impl->in.update = true;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,37 +28,42 @@ extern "C" {
|
|||
#include <pipewire/client/sig.h>
|
||||
|
||||
struct pw_connection {
|
||||
int fd;
|
||||
int fd;
|
||||
|
||||
PW_SIGNAL (need_flush, (struct pw_listener *listener,
|
||||
struct pw_connection *conn));
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_connection *conn));
|
||||
PW_SIGNAL(need_flush, (struct pw_listener * listener, struct pw_connection * conn));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_connection * conn));
|
||||
};
|
||||
|
||||
struct pw_connection * pw_connection_new (int fd);
|
||||
void pw_connection_destroy (struct pw_connection *conn);
|
||||
struct pw_connection *
|
||||
pw_connection_new(int fd);
|
||||
|
||||
uint32_t pw_connection_add_fd (struct pw_connection *conn,
|
||||
int fd);
|
||||
int pw_connection_get_fd (struct pw_connection *conn,
|
||||
uint32_t index);
|
||||
void
|
||||
pw_connection_destroy(struct pw_connection *conn);
|
||||
|
||||
bool pw_connection_get_next (struct pw_connection *conn,
|
||||
uint8_t *opcode,
|
||||
uint32_t *dest_id,
|
||||
void **data,
|
||||
uint32_t *size);
|
||||
uint32_t
|
||||
pw_connection_add_fd(struct pw_connection *conn, int fd);
|
||||
|
||||
void * pw_connection_begin_write (struct pw_connection *conn,
|
||||
uint32_t size);
|
||||
void pw_connection_end_write (struct pw_connection *conn,
|
||||
uint32_t dest_id,
|
||||
uint8_t opcode,
|
||||
uint32_t size);
|
||||
int
|
||||
pw_connection_get_fd(struct pw_connection *conn, uint32_t index);
|
||||
|
||||
bool pw_connection_flush (struct pw_connection *conn);
|
||||
bool pw_connection_clear (struct pw_connection *conn);
|
||||
bool
|
||||
pw_connection_get_next(struct pw_connection *conn,
|
||||
uint8_t *opcode,
|
||||
uint32_t *dest_id,
|
||||
void **data, uint32_t *size);
|
||||
|
||||
void *
|
||||
pw_connection_begin_write(struct pw_connection *conn, uint32_t size);
|
||||
|
||||
void
|
||||
pw_connection_end_write(struct pw_connection *conn,
|
||||
uint32_t dest_id, uint8_t opcode, uint32_t size);
|
||||
|
||||
bool
|
||||
pw_connection_flush(struct pw_connection *conn);
|
||||
|
||||
bool
|
||||
pw_connection_clear(struct pw_connection *conn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -41,18 +41,18 @@ extern "C" {
|
|||
* The state of a pw_context
|
||||
*/
|
||||
enum pw_context_state {
|
||||
PW_CONTEXT_STATE_ERROR = -1,
|
||||
PW_CONTEXT_STATE_UNCONNECTED = 0,
|
||||
PW_CONTEXT_STATE_CONNECTING = 1,
|
||||
PW_CONTEXT_STATE_CONNECTED = 2,
|
||||
PW_CONTEXT_STATE_ERROR = -1,
|
||||
PW_CONTEXT_STATE_UNCONNECTED = 0,
|
||||
PW_CONTEXT_STATE_CONNECTING = 1,
|
||||
PW_CONTEXT_STATE_CONNECTED = 2,
|
||||
};
|
||||
|
||||
const char * pw_context_state_as_string (enum pw_context_state state);
|
||||
const char *pw_context_state_as_string(enum pw_context_state state);
|
||||
|
||||
enum pw_context_flags {
|
||||
PW_CONTEXT_FLAG_NONE = 0,
|
||||
PW_CONTEXT_FLAG_NO_REGISTRY = (1 << 0),
|
||||
PW_CONTEXT_FLAG_NO_PROXY = (1 << 1),
|
||||
PW_CONTEXT_FLAG_NONE = 0,
|
||||
PW_CONTEXT_FLAG_NO_REGISTRY = (1 << 0),
|
||||
PW_CONTEXT_FLAG_NO_PROXY = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -61,52 +61,51 @@ enum pw_context_flags {
|
|||
* PipeWire context object class.
|
||||
*/
|
||||
struct pw_context {
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct pw_type type;
|
||||
struct pw_type type;
|
||||
|
||||
struct pw_loop *loop;
|
||||
struct pw_loop *loop;
|
||||
|
||||
struct pw_proxy *core_proxy;
|
||||
struct pw_proxy *registry_proxy;
|
||||
struct pw_proxy *core_proxy;
|
||||
struct pw_proxy *registry_proxy;
|
||||
|
||||
struct pw_map objects;
|
||||
uint32_t n_types;
|
||||
struct pw_map types;
|
||||
struct pw_map objects;
|
||||
uint32_t n_types;
|
||||
struct pw_map types;
|
||||
|
||||
struct spa_list global_list;
|
||||
struct spa_list stream_list;
|
||||
struct spa_list proxy_list;
|
||||
struct spa_list global_list;
|
||||
struct spa_list stream_list;
|
||||
struct spa_list proxy_list;
|
||||
|
||||
void *protocol_private;
|
||||
void *protocol_private;
|
||||
|
||||
enum pw_context_state state;
|
||||
char *error;
|
||||
PW_SIGNAL (state_changed, (struct pw_listener *listener,
|
||||
struct pw_context *context));
|
||||
enum pw_context_state state;
|
||||
char *error;
|
||||
PW_SIGNAL(state_changed, (struct pw_listener * listener, struct pw_context * context));
|
||||
|
||||
PW_SIGNAL (subscription, (struct pw_listener *listener,
|
||||
struct pw_context *context,
|
||||
enum pw_subscription_event event,
|
||||
uint32_t type,
|
||||
uint32_t id));
|
||||
PW_SIGNAL(subscription, (struct pw_listener * listener,
|
||||
struct pw_context * context,
|
||||
enum pw_subscription_event event, uint32_t type, uint32_t id));
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_context *context));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_context * context));
|
||||
};
|
||||
|
||||
struct pw_context * pw_context_new (struct pw_loop *loop,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
void pw_context_destroy (struct pw_context *context);
|
||||
struct pw_context *
|
||||
pw_context_new(struct pw_loop *loop,
|
||||
const char *name, struct pw_properties *properties);
|
||||
void
|
||||
pw_context_destroy(struct pw_context *context);
|
||||
|
||||
bool pw_context_connect (struct pw_context *context,
|
||||
enum pw_context_flags flags);
|
||||
bool pw_context_connect_fd (struct pw_context *context,
|
||||
enum pw_context_flags flags,
|
||||
int fd);
|
||||
bool pw_context_disconnect (struct pw_context *context);
|
||||
bool
|
||||
pw_context_connect(struct pw_context *context, enum pw_context_flags flags);
|
||||
|
||||
bool
|
||||
pw_context_connect_fd(struct pw_context *context, enum pw_context_flags flags, int fd);
|
||||
|
||||
bool
|
||||
pw_context_disconnect(struct pw_context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,25 +41,17 @@ extern "C" {
|
|||
#define PW_CORE_METHOD_NUM 6
|
||||
|
||||
struct pw_core_methods {
|
||||
void (*client_update) (void *object,
|
||||
const struct spa_dict *props);
|
||||
void (*sync) (void *object,
|
||||
uint32_t seq);
|
||||
void (*get_registry) (void *object,
|
||||
uint32_t new_id);
|
||||
void (*create_node) (void *object,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
const struct spa_dict *props,
|
||||
uint32_t new_id);
|
||||
void (*create_client_node) (void *object,
|
||||
const char *name,
|
||||
const struct spa_dict *props,
|
||||
uint32_t new_id);
|
||||
void (*update_types) (void *object,
|
||||
uint32_t first_id,
|
||||
uint32_t n_types,
|
||||
const char **types);
|
||||
void (*client_update) (void *object, const struct spa_dict * props);
|
||||
void (*sync) (void *object, uint32_t seq);
|
||||
void (*get_registry) (void *object, uint32_t new_id);
|
||||
void (*create_node) (void *object,
|
||||
const char *factory_name,
|
||||
const char *name, const struct spa_dict * props, uint32_t new_id);
|
||||
void (*create_client_node) (void *object,
|
||||
const char *name,
|
||||
const struct spa_dict * props, uint32_t new_id);
|
||||
void (*update_types) (void *object,
|
||||
uint32_t first_id, uint32_t n_types, const char **types);
|
||||
};
|
||||
|
||||
#define pw_core_do_client_update(r,...) ((struct pw_core_methods*)r->iface->methods)->client_update(r,__VA_ARGS__)
|
||||
|
|
@ -77,20 +69,12 @@ struct pw_core_methods {
|
|||
#define PW_CORE_EVENT_NUM 5
|
||||
|
||||
struct pw_core_events {
|
||||
void (*info) (void *object,
|
||||
struct pw_core_info *info);
|
||||
void (*done) (void *object,
|
||||
uint32_t seq);
|
||||
void (*error) (void *object,
|
||||
uint32_t id,
|
||||
int res,
|
||||
const char *error, ...);
|
||||
void (*remove_id) (void *object,
|
||||
uint32_t id);
|
||||
void (*update_types) (void *object,
|
||||
uint32_t first_id,
|
||||
uint32_t n_types,
|
||||
const char **types);
|
||||
void (*info) (void *object, struct pw_core_info * info);
|
||||
void (*done) (void *object, uint32_t seq);
|
||||
void (*error) (void *object, uint32_t id, int res, const char *error, ...);
|
||||
void (*remove_id) (void *object, uint32_t id);
|
||||
void (*update_types) (void *object,
|
||||
uint32_t first_id, uint32_t n_types, const char **types);
|
||||
};
|
||||
|
||||
#define pw_core_notify_info(r,...) ((struct pw_core_events*)r->iface->events)->info(r,__VA_ARGS__)
|
||||
|
|
@ -104,9 +88,7 @@ struct pw_core_events {
|
|||
#define PW_REGISTRY_METHOD_NUM 1
|
||||
|
||||
struct pw_registry_methods {
|
||||
void (*bind) (void *object,
|
||||
uint32_t id,
|
||||
uint32_t new_id);
|
||||
void (*bind) (void *object, uint32_t id, uint32_t new_id);
|
||||
};
|
||||
|
||||
#define pw_registry_do_bind(r,...) ((struct pw_registry_methods*)r->iface->methods)->bind(r,__VA_ARGS__)
|
||||
|
|
@ -116,11 +98,8 @@ struct pw_registry_methods {
|
|||
#define PW_REGISTRY_EVENT_NUM 2
|
||||
|
||||
struct pw_registry_events {
|
||||
void (*global) (void *object,
|
||||
uint32_t id,
|
||||
const char *type);
|
||||
void (*global_remove) (void *object,
|
||||
uint32_t id);
|
||||
void (*global) (void *object, uint32_t id, const char *type);
|
||||
void (*global_remove) (void *object, uint32_t id);
|
||||
};
|
||||
|
||||
#define pw_registry_notify_global(r,...) ((struct pw_registry_events*)r->iface->events)->global(r,__VA_ARGS__)
|
||||
|
|
@ -130,8 +109,7 @@ struct pw_registry_events {
|
|||
#define PW_MODULE_EVENT_NUM 1
|
||||
|
||||
struct pw_module_events {
|
||||
void (*info) (void *object,
|
||||
struct pw_module_info *info);
|
||||
void (*info) (void *object, struct pw_module_info * info);
|
||||
};
|
||||
|
||||
#define pw_module_notify_info(r,...) ((struct pw_module_events*)r->iface->events)->info(r,__VA_ARGS__)
|
||||
|
|
@ -140,17 +118,16 @@ struct pw_module_events {
|
|||
#define PW_NODE_EVENT_NUM 1
|
||||
|
||||
struct pw_node_events {
|
||||
void (*info) (void *object,
|
||||
struct pw_node_info *info);
|
||||
void (*info) (void *object, struct pw_node_info * info);
|
||||
};
|
||||
|
||||
#define pw_node_notify_info(r,...) ((struct pw_node_events*)r->iface->events)->info(r,__VA_ARGS__)
|
||||
|
||||
struct pw_client_node_buffer {
|
||||
uint32_t mem_id;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
struct spa_buffer *buffer;
|
||||
uint32_t mem_id;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
struct spa_buffer *buffer;
|
||||
};
|
||||
|
||||
#define PW_CLIENT_NODE_METHOD_UPDATE 0
|
||||
|
|
@ -160,32 +137,27 @@ struct pw_client_node_buffer {
|
|||
#define PW_CLIENT_NODE_METHOD_NUM 4
|
||||
|
||||
struct pw_client_node_methods {
|
||||
void (*update) (void *object,
|
||||
void (*update) (void *object,
|
||||
#define PW_MESSAGE_NODE_UPDATE_MAX_INPUTS (1 << 0)
|
||||
#define PW_MESSAGE_NODE_UPDATE_MAX_OUTPUTS (1 << 1)
|
||||
#define PW_MESSAGE_NODE_UPDATE_PROPS (1 << 2)
|
||||
uint32_t change_mask,
|
||||
uint32_t max_input_ports,
|
||||
uint32_t max_output_ports,
|
||||
const struct spa_props *props);
|
||||
uint32_t change_mask,
|
||||
uint32_t max_input_ports,
|
||||
uint32_t max_output_ports, const struct spa_props * props);
|
||||
|
||||
void (*port_update) (void *object,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
void (*port_update) (void *object, enum spa_direction direction, uint32_t port_id,
|
||||
#define PW_MESSAGE_PORT_UPDATE_POSSIBLE_FORMATS (1 << 0)
|
||||
#define PW_MESSAGE_PORT_UPDATE_FORMAT (1 << 1)
|
||||
#define PW_MESSAGE_PORT_UPDATE_PARAMS (1 << 2)
|
||||
#define PW_MESSAGE_PORT_UPDATE_INFO (1 << 3)
|
||||
uint32_t change_mask,
|
||||
uint32_t n_possible_formats,
|
||||
const struct spa_format **possible_formats,
|
||||
const struct spa_format *format,
|
||||
uint32_t n_params,
|
||||
const struct spa_param **params,
|
||||
const struct spa_port_info *info);
|
||||
void (*event) (void *object,
|
||||
struct spa_event *event);
|
||||
void (*destroy) (void *object);
|
||||
uint32_t change_mask,
|
||||
uint32_t n_possible_formats,
|
||||
const struct spa_format ** possible_formats,
|
||||
const struct spa_format * format,
|
||||
uint32_t n_params,
|
||||
const struct spa_param ** params, const struct spa_port_info * info);
|
||||
void (*event) (void *object, struct spa_event * event);
|
||||
void (*destroy) (void *object);
|
||||
};
|
||||
|
||||
#define pw_client_node_do_update(r,...) ((struct pw_client_node_methods*)r->iface->methods)->update(r,__VA_ARGS__)
|
||||
|
|
@ -207,55 +179,31 @@ struct pw_client_node_methods {
|
|||
#define PW_CLIENT_NODE_EVENT_NUM 11
|
||||
|
||||
struct pw_client_node_events {
|
||||
void (*done) (void *object,
|
||||
int readfd,
|
||||
int writefd);
|
||||
void (*event) (void *object,
|
||||
const struct spa_event *event);
|
||||
void (*add_port) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id);
|
||||
void (*remove_port) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id);
|
||||
void (*set_format) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t flags,
|
||||
const struct spa_format *format);
|
||||
void (*set_property) (void *object,
|
||||
uint32_t seq,
|
||||
uint32_t id,
|
||||
uint32_t size,
|
||||
const void *value);
|
||||
void (*add_mem) (void *object,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t mem_id,
|
||||
uint32_t type,
|
||||
int memfd,
|
||||
uint32_t flags,
|
||||
uint32_t offset,
|
||||
uint32_t size);
|
||||
void (*use_buffers) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t n_buffers,
|
||||
struct pw_client_node_buffer *buffers);
|
||||
void (*node_command) (void *object,
|
||||
uint32_t seq,
|
||||
const struct spa_command *command);
|
||||
void (*port_command) (void *object,
|
||||
uint32_t port_id,
|
||||
const struct spa_command *command);
|
||||
void (*transport) (void *object,
|
||||
int memfd,
|
||||
uint32_t offset,
|
||||
uint32_t size);
|
||||
void (*done) (void *object, int readfd, int writefd);
|
||||
void (*event) (void *object, const struct spa_event * event);
|
||||
void (*add_port) (void *object,
|
||||
uint32_t seq, enum spa_direction direction, uint32_t port_id);
|
||||
void (*remove_port) (void *object,
|
||||
uint32_t seq, enum spa_direction direction, uint32_t port_id);
|
||||
void (*set_format) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id, uint32_t flags, const struct spa_format * format);
|
||||
void (*set_property) (void *object,
|
||||
uint32_t seq, uint32_t id, uint32_t size, const void *value);
|
||||
void (*add_mem) (void *object,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t mem_id,
|
||||
uint32_t type, int memfd, uint32_t flags, uint32_t offset, uint32_t size);
|
||||
void (*use_buffers) (void *object,
|
||||
uint32_t seq,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t n_buffers, struct pw_client_node_buffer * buffers);
|
||||
void (*node_command) (void *object, uint32_t seq, const struct spa_command * command);
|
||||
void (*port_command) (void *object, uint32_t port_id, const struct spa_command * command);
|
||||
void (*transport) (void *object, int memfd, uint32_t offset, uint32_t size);
|
||||
};
|
||||
|
||||
#define pw_client_node_notify_done(r,...) ((struct pw_client_node_events*)r->iface->events)->done(r,__VA_ARGS__)
|
||||
|
|
@ -274,8 +222,7 @@ struct pw_client_node_events {
|
|||
#define PW_CLIENT_EVENT_NUM 1
|
||||
|
||||
struct pw_client_events {
|
||||
void (*info) (void *object,
|
||||
struct pw_client_info *info);
|
||||
void (*info) (void *object, struct pw_client_info * info);
|
||||
};
|
||||
|
||||
#define pw_client_notify_info(r,...) ((struct pw_client_events*)r->iface->events)->info(r,__VA_ARGS__)
|
||||
|
|
@ -284,8 +231,7 @@ struct pw_client_events {
|
|||
#define PW_LINK_EVENT_NUM 1
|
||||
|
||||
struct pw_link_events {
|
||||
void (*info) (void *object,
|
||||
struct pw_link_info *info);
|
||||
void (*info) (void *object, struct pw_link_info * info);
|
||||
};
|
||||
|
||||
#define pw_link_notify_info(r,...) ((struct pw_link_events*)r->iface->events)->info(r,__VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -32,22 +32,21 @@
|
|||
*
|
||||
* Returns: the string representation of @state.
|
||||
*/
|
||||
const char *
|
||||
pw_node_state_as_string (enum pw_node_state state)
|
||||
const char *pw_node_state_as_string(enum pw_node_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case PW_NODE_STATE_ERROR:
|
||||
return "error";
|
||||
case PW_NODE_STATE_CREATING:
|
||||
return "creating";
|
||||
case PW_NODE_STATE_SUSPENDED:
|
||||
return "suspended";
|
||||
case PW_NODE_STATE_IDLE:
|
||||
return "idle";
|
||||
case PW_NODE_STATE_RUNNING:
|
||||
return "running";
|
||||
}
|
||||
return "invalid-state";
|
||||
switch (state) {
|
||||
case PW_NODE_STATE_ERROR:
|
||||
return "error";
|
||||
case PW_NODE_STATE_CREATING:
|
||||
return "creating";
|
||||
case PW_NODE_STATE_SUSPENDED:
|
||||
return "suspended";
|
||||
case PW_NODE_STATE_IDLE:
|
||||
return "idle";
|
||||
case PW_NODE_STATE_RUNNING:
|
||||
return "running";
|
||||
}
|
||||
return "invalid-state";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -58,18 +57,17 @@ pw_node_state_as_string (enum pw_node_state state)
|
|||
*
|
||||
* Returns: the string representation of @direction.
|
||||
*/
|
||||
const char *
|
||||
pw_direction_as_string (enum pw_direction direction)
|
||||
const char *pw_direction_as_string(enum pw_direction direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case PW_DIRECTION_INPUT:
|
||||
return "input";
|
||||
case PW_DIRECTION_OUTPUT:
|
||||
return "output";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
return "invalid-direction";
|
||||
switch (direction) {
|
||||
case PW_DIRECTION_INPUT:
|
||||
return "input";
|
||||
case PW_DIRECTION_OUTPUT:
|
||||
return "output";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
return "invalid-direction";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -80,371 +78,362 @@ pw_direction_as_string (enum pw_direction direction)
|
|||
*
|
||||
* Returns: the string representation of @state.
|
||||
*/
|
||||
const char *
|
||||
pw_link_state_as_string (enum pw_link_state state)
|
||||
const char *pw_link_state_as_string(enum pw_link_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case PW_LINK_STATE_ERROR:
|
||||
return "error";
|
||||
case PW_LINK_STATE_UNLINKED:
|
||||
return "unlinked";
|
||||
case PW_LINK_STATE_INIT:
|
||||
return "init";
|
||||
case PW_LINK_STATE_NEGOTIATING:
|
||||
return "negotiating";
|
||||
case PW_LINK_STATE_ALLOCATING:
|
||||
return "allocating";
|
||||
case PW_LINK_STATE_PAUSED:
|
||||
return "paused";
|
||||
case PW_LINK_STATE_RUNNING:
|
||||
return "running";
|
||||
}
|
||||
return "invalid-state";
|
||||
switch (state) {
|
||||
case PW_LINK_STATE_ERROR:
|
||||
return "error";
|
||||
case PW_LINK_STATE_UNLINKED:
|
||||
return "unlinked";
|
||||
case PW_LINK_STATE_INIT:
|
||||
return "init";
|
||||
case PW_LINK_STATE_NEGOTIATING:
|
||||
return "negotiating";
|
||||
case PW_LINK_STATE_ALLOCATING:
|
||||
return "allocating";
|
||||
case PW_LINK_STATE_PAUSED:
|
||||
return "paused";
|
||||
case PW_LINK_STATE_RUNNING:
|
||||
return "running";
|
||||
}
|
||||
return "invalid-state";
|
||||
}
|
||||
|
||||
static void
|
||||
pw_spa_dict_destroy (struct spa_dict *dict)
|
||||
static void pw_spa_dict_destroy(struct spa_dict *dict)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
struct spa_dict_item *item;
|
||||
|
||||
spa_dict_for_each (item, dict) {
|
||||
free ((void *)item->key);
|
||||
free ((void *)item->value);
|
||||
}
|
||||
free (dict->items);
|
||||
free (dict);
|
||||
spa_dict_for_each(item, dict) {
|
||||
free((void *) item->key);
|
||||
free((void *) item->value);
|
||||
}
|
||||
free(dict->items);
|
||||
free(dict);
|
||||
}
|
||||
|
||||
static struct spa_dict *
|
||||
pw_spa_dict_copy (struct spa_dict *dict)
|
||||
static struct spa_dict *pw_spa_dict_copy(struct spa_dict *dict)
|
||||
{
|
||||
struct spa_dict *copy;
|
||||
uint32_t i;
|
||||
struct spa_dict *copy;
|
||||
uint32_t i;
|
||||
|
||||
if (dict == NULL)
|
||||
return NULL;
|
||||
if (dict == NULL)
|
||||
return NULL;
|
||||
|
||||
copy = calloc (1, sizeof (struct spa_dict));
|
||||
if (copy == NULL)
|
||||
goto no_mem;
|
||||
copy->items = calloc (dict->n_items, sizeof (struct spa_dict_item));
|
||||
if (copy->items == NULL)
|
||||
goto no_items;
|
||||
copy->n_items = dict->n_items;
|
||||
copy = calloc(1, sizeof(struct spa_dict));
|
||||
if (copy == NULL)
|
||||
goto no_mem;
|
||||
copy->items = calloc(dict->n_items, sizeof(struct spa_dict_item));
|
||||
if (copy->items == NULL)
|
||||
goto no_items;
|
||||
copy->n_items = dict->n_items;
|
||||
|
||||
for (i = 0; i < dict->n_items; i++) {
|
||||
copy->items[i].key = strdup (dict->items[i].key);
|
||||
copy->items[i].value = strdup (dict->items[i].value);
|
||||
}
|
||||
return copy;
|
||||
for (i = 0; i < dict->n_items; i++) {
|
||||
copy->items[i].key = strdup(dict->items[i].key);
|
||||
copy->items[i].value = strdup(dict->items[i].value);
|
||||
}
|
||||
return copy;
|
||||
|
||||
no_items:
|
||||
free (copy);
|
||||
no_mem:
|
||||
return NULL;
|
||||
no_items:
|
||||
free(copy);
|
||||
no_mem:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pw_core_info *
|
||||
pw_core_info_update (struct pw_core_info *info,
|
||||
const struct pw_core_info *update)
|
||||
struct pw_core_info *pw_core_info_update(struct pw_core_info *info,
|
||||
const struct pw_core_info *update)
|
||||
{
|
||||
uint64_t change_mask;
|
||||
uint64_t change_mask;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc (1, sizeof (struct pw_core_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_core_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->user_name)
|
||||
free ((void*)info->user_name);
|
||||
info->user_name = update->user_name ? strdup (update->user_name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1)) {
|
||||
if (info->host_name)
|
||||
free ((void*)info->host_name);
|
||||
info->host_name = update->host_name ? strdup (update->host_name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
if (info->version)
|
||||
free ((void*)info->version);
|
||||
info->version = update->version ? strdup (update->version) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 3)) {
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
info->name = update->name ? strdup (update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 4))
|
||||
info->cookie = update->cookie;
|
||||
if (update->change_mask & (1 << 5)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
info->props = pw_spa_dict_copy (update->props);
|
||||
}
|
||||
return info;
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->user_name)
|
||||
free((void *) info->user_name);
|
||||
info->user_name = update->user_name ? strdup(update->user_name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1)) {
|
||||
if (info->host_name)
|
||||
free((void *) info->host_name);
|
||||
info->host_name = update->host_name ? strdup(update->host_name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
if (info->version)
|
||||
free((void *) info->version);
|
||||
info->version = update->version ? strdup(update->version) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 3)) {
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
info->name = update->name ? strdup(update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 4))
|
||||
info->cookie = update->cookie;
|
||||
if (update->change_mask & (1 << 5)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
info->props = pw_spa_dict_copy(update->props);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
pw_core_info_free (struct pw_core_info *info)
|
||||
void pw_core_info_free(struct pw_core_info *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
if (info->user_name)
|
||||
free ((void*)info->user_name);
|
||||
if (info->host_name)
|
||||
free ((void*)info->host_name);
|
||||
if (info->version)
|
||||
free ((void*)info->version);
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
free (info);
|
||||
if (info->user_name)
|
||||
free((void *) info->user_name);
|
||||
if (info->host_name)
|
||||
free((void *) info->host_name);
|
||||
if (info->version)
|
||||
free((void *) info->version);
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
free(info);
|
||||
}
|
||||
|
||||
struct pw_node_info *
|
||||
pw_node_info_update (struct pw_node_info *info,
|
||||
const struct pw_node_info *update)
|
||||
struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
|
||||
const struct pw_node_info *update)
|
||||
{
|
||||
uint64_t change_mask;
|
||||
int i;
|
||||
uint64_t change_mask;
|
||||
int i;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc (1, sizeof (struct pw_node_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_node_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
info->name = update->name ? strdup (update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1))
|
||||
info->max_inputs = update->max_inputs;
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
free (info->input_formats[i]);
|
||||
info->n_input_formats = update->n_input_formats;
|
||||
if (info->n_input_formats)
|
||||
info->input_formats = realloc (info->input_formats, info->n_input_formats * sizeof (struct spa_format *));
|
||||
else {
|
||||
free (info->input_formats);
|
||||
info->input_formats = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_input_formats; i++) {
|
||||
info->input_formats[i] = spa_format_copy (update->input_formats[i]);
|
||||
}
|
||||
}
|
||||
if (update->change_mask & (1 << 3))
|
||||
info->max_outputs = update->max_outputs;
|
||||
if (update->change_mask & (1 << 4)) {
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
free (info->output_formats[i]);
|
||||
info->n_output_formats = update->n_output_formats;
|
||||
if (info->n_output_formats)
|
||||
info->output_formats = realloc (info->output_formats, info->n_output_formats * sizeof (struct spa_format *));
|
||||
else {
|
||||
free (info->output_formats);
|
||||
info->output_formats = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_output_formats; i++) {
|
||||
info->output_formats[i] = spa_format_copy (update->output_formats[i]);
|
||||
}
|
||||
}
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
info->name = update->name ? strdup(update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1))
|
||||
info->max_inputs = update->max_inputs;
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
free(info->input_formats[i]);
|
||||
info->n_input_formats = update->n_input_formats;
|
||||
if (info->n_input_formats)
|
||||
info->input_formats =
|
||||
realloc(info->input_formats,
|
||||
info->n_input_formats * sizeof(struct spa_format *));
|
||||
else {
|
||||
free(info->input_formats);
|
||||
info->input_formats = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_input_formats; i++) {
|
||||
info->input_formats[i] = spa_format_copy(update->input_formats[i]);
|
||||
}
|
||||
}
|
||||
if (update->change_mask & (1 << 3))
|
||||
info->max_outputs = update->max_outputs;
|
||||
if (update->change_mask & (1 << 4)) {
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
free(info->output_formats[i]);
|
||||
info->n_output_formats = update->n_output_formats;
|
||||
if (info->n_output_formats)
|
||||
info->output_formats =
|
||||
realloc(info->output_formats,
|
||||
info->n_output_formats * sizeof(struct spa_format *));
|
||||
else {
|
||||
free(info->output_formats);
|
||||
info->output_formats = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_output_formats; i++) {
|
||||
info->output_formats[i] = spa_format_copy(update->output_formats[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (update->change_mask & (1 << 5)) {
|
||||
info->state = update->state;
|
||||
if (info->error)
|
||||
free ((void*)info->error);
|
||||
info->error = update->error ? strdup (update->error) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 6)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
info->props = pw_spa_dict_copy (update->props);
|
||||
}
|
||||
return info;
|
||||
if (update->change_mask & (1 << 5)) {
|
||||
info->state = update->state;
|
||||
if (info->error)
|
||||
free((void *) info->error);
|
||||
info->error = update->error ? strdup(update->error) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 6)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
info->props = pw_spa_dict_copy(update->props);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
pw_node_info_free (struct pw_node_info *info)
|
||||
void pw_node_info_free(struct pw_node_info *info)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
if (info->input_formats) {
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
free (info->input_formats[i]);
|
||||
free (info->input_formats);
|
||||
}
|
||||
if (info->output_formats) {
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
free (info->output_formats[i]);
|
||||
free (info->output_formats);
|
||||
}
|
||||
if (info->error)
|
||||
free ((void*)info->error);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
free (info);
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
if (info->input_formats) {
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
free(info->input_formats[i]);
|
||||
free(info->input_formats);
|
||||
}
|
||||
if (info->output_formats) {
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
free(info->output_formats[i]);
|
||||
free(info->output_formats);
|
||||
}
|
||||
if (info->error)
|
||||
free((void *) info->error);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
free(info);
|
||||
}
|
||||
|
||||
struct pw_module_info *
|
||||
pw_module_info_update (struct pw_module_info *info,
|
||||
const struct pw_module_info *update)
|
||||
struct pw_module_info *pw_module_info_update(struct pw_module_info *info,
|
||||
const struct pw_module_info *update)
|
||||
{
|
||||
uint64_t change_mask;
|
||||
uint64_t change_mask;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc (1, sizeof (struct pw_module_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_module_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
info->name = update->name ? strdup (update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1)) {
|
||||
if (info->filename)
|
||||
free ((void*)info->filename);
|
||||
info->filename = update->filename ? strdup (update->filename) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
if (info->args)
|
||||
free ((void*)info->args);
|
||||
info->args = update->args ? strdup (update->args) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 3)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
info->props = pw_spa_dict_copy (update->props);
|
||||
}
|
||||
return info;
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
info->name = update->name ? strdup(update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 1)) {
|
||||
if (info->filename)
|
||||
free((void *) info->filename);
|
||||
info->filename = update->filename ? strdup(update->filename) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 2)) {
|
||||
if (info->args)
|
||||
free((void *) info->args);
|
||||
info->args = update->args ? strdup(update->args) : NULL;
|
||||
}
|
||||
if (update->change_mask & (1 << 3)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
info->props = pw_spa_dict_copy(update->props);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
pw_module_info_free (struct pw_module_info *info)
|
||||
void pw_module_info_free(struct pw_module_info *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
if (info->name)
|
||||
free ((void*)info->name);
|
||||
if (info->filename)
|
||||
free ((void*)info->filename);
|
||||
if (info->args)
|
||||
free ((void*)info->args);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
free (info);
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
if (info->filename)
|
||||
free((void *) info->filename);
|
||||
if (info->args)
|
||||
free((void *) info->args);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
free(info);
|
||||
}
|
||||
|
||||
|
||||
struct pw_client_info *
|
||||
pw_client_info_update (struct pw_client_info *info,
|
||||
const struct pw_client_info *update)
|
||||
struct pw_client_info *pw_client_info_update(struct pw_client_info *info,
|
||||
const struct pw_client_info *update)
|
||||
{
|
||||
uint64_t change_mask;
|
||||
uint64_t change_mask;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc (1, sizeof (struct pw_client_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_client_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
info->props = pw_spa_dict_copy (update->props);
|
||||
}
|
||||
return info;
|
||||
if (update->change_mask & (1 << 0)) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
info->props = pw_spa_dict_copy(update->props);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
pw_client_info_free (struct pw_client_info *info)
|
||||
void pw_client_info_free(struct pw_client_info *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy (info->props);
|
||||
free (info);
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
free(info);
|
||||
}
|
||||
|
||||
struct pw_link_info *
|
||||
pw_link_info_update (struct pw_link_info *info,
|
||||
const struct pw_link_info *update)
|
||||
struct pw_link_info *pw_link_info_update(struct pw_link_info *info,
|
||||
const struct pw_link_info *update)
|
||||
{
|
||||
uint64_t change_mask;
|
||||
uint64_t change_mask;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc (1, sizeof (struct pw_link_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_link_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
change_mask = ~0;
|
||||
} else {
|
||||
change_mask = info->change_mask | update->change_mask;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = change_mask;
|
||||
|
||||
if (update->change_mask & (1 << 0))
|
||||
info->output_node_id = update->output_node_id;
|
||||
if (update->change_mask & (1 << 1))
|
||||
info->output_port_id = update->output_port_id;
|
||||
if (update->change_mask & (1 << 2))
|
||||
info->input_node_id = update->input_node_id;
|
||||
if (update->change_mask & (1 << 3))
|
||||
info->input_port_id = update->input_port_id;
|
||||
if (update->change_mask & (1 << 0))
|
||||
info->output_node_id = update->output_node_id;
|
||||
if (update->change_mask & (1 << 1))
|
||||
info->output_port_id = update->output_port_id;
|
||||
if (update->change_mask & (1 << 2))
|
||||
info->input_node_id = update->input_node_id;
|
||||
if (update->change_mask & (1 << 3))
|
||||
info->input_port_id = update->input_port_id;
|
||||
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
pw_link_info_free (struct pw_link_info *info)
|
||||
void pw_link_info_free(struct pw_link_info *info)
|
||||
{
|
||||
free (info);
|
||||
free(info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,14 +45,15 @@ struct pw_context;
|
|||
* The different node states
|
||||
*/
|
||||
enum pw_node_state {
|
||||
PW_NODE_STATE_ERROR = -1,
|
||||
PW_NODE_STATE_CREATING = 0,
|
||||
PW_NODE_STATE_SUSPENDED = 1,
|
||||
PW_NODE_STATE_IDLE = 2,
|
||||
PW_NODE_STATE_RUNNING = 3,
|
||||
PW_NODE_STATE_ERROR = -1,
|
||||
PW_NODE_STATE_CREATING = 0,
|
||||
PW_NODE_STATE_SUSPENDED = 1,
|
||||
PW_NODE_STATE_IDLE = 2,
|
||||
PW_NODE_STATE_RUNNING = 3,
|
||||
};
|
||||
|
||||
const char * pw_node_state_as_string (enum pw_node_state state);
|
||||
const char *
|
||||
pw_node_state_as_string(enum pw_node_state state);
|
||||
|
||||
/**
|
||||
* pw_direction:
|
||||
|
|
@ -63,11 +64,12 @@ const char * pw_node_state_as_string (enum pw_node_state state);
|
|||
* The direction of a port
|
||||
*/
|
||||
enum pw_direction {
|
||||
PW_DIRECTION_INPUT = SPA_DIRECTION_INPUT,
|
||||
PW_DIRECTION_OUTPUT = SPA_DIRECTION_OUTPUT
|
||||
PW_DIRECTION_INPUT = SPA_DIRECTION_INPUT,
|
||||
PW_DIRECTION_OUTPUT = SPA_DIRECTION_OUTPUT
|
||||
};
|
||||
|
||||
const char * pw_direction_as_string (enum pw_direction direction);
|
||||
const char *
|
||||
pw_direction_as_string(enum pw_direction direction);
|
||||
|
||||
/**
|
||||
* pw_link_state:
|
||||
|
|
@ -82,16 +84,17 @@ const char * pw_direction_as_string (enum pw_direction direction);
|
|||
* The different link states
|
||||
*/
|
||||
enum pw_link_state {
|
||||
PW_LINK_STATE_ERROR = -2,
|
||||
PW_LINK_STATE_UNLINKED = -1,
|
||||
PW_LINK_STATE_INIT = 0,
|
||||
PW_LINK_STATE_NEGOTIATING = 1,
|
||||
PW_LINK_STATE_ALLOCATING = 2,
|
||||
PW_LINK_STATE_PAUSED = 3,
|
||||
PW_LINK_STATE_RUNNING = 4,
|
||||
PW_LINK_STATE_ERROR = -2,
|
||||
PW_LINK_STATE_UNLINKED = -1,
|
||||
PW_LINK_STATE_INIT = 0,
|
||||
PW_LINK_STATE_NEGOTIATING = 1,
|
||||
PW_LINK_STATE_ALLOCATING = 2,
|
||||
PW_LINK_STATE_PAUSED = 3,
|
||||
PW_LINK_STATE_RUNNING = 4,
|
||||
};
|
||||
|
||||
const char * pw_link_state_as_string (enum pw_link_state state);
|
||||
const char *
|
||||
pw_link_state_as_string(enum pw_link_state state);
|
||||
|
||||
/**
|
||||
* pw_core_info:
|
||||
|
|
@ -108,8 +111,8 @@ const char * pw_link_state_as_string (enum pw_link_state state);
|
|||
* versions.
|
||||
*/
|
||||
struct pw_core_info {
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
#define PW_CORE_CHANGE_MASK_USER_NAME (1 << 0)
|
||||
#define PW_CORE_CHANGE_MASK_HOST_NAME (1 << 1)
|
||||
#define PW_CORE_CHANGE_MASK_VERSION (1 << 2)
|
||||
|
|
@ -117,17 +120,20 @@ struct pw_core_info {
|
|||
#define PW_CORE_CHANGE_MASK_COOKIE (1 << 4)
|
||||
#define PW_CORE_CHANGE_MASK_PROPS (1 << 5)
|
||||
#define PW_CORE_CHANGE_MASK_ALL (~0)
|
||||
const char *user_name;
|
||||
const char *host_name;
|
||||
const char *version;
|
||||
const char *name;
|
||||
uint32_t cookie;
|
||||
struct spa_dict *props;
|
||||
const char *user_name;
|
||||
const char *host_name;
|
||||
const char *version;
|
||||
const char *name;
|
||||
uint32_t cookie;
|
||||
struct spa_dict *props;
|
||||
};
|
||||
|
||||
struct pw_core_info * pw_core_info_update (struct pw_core_info *info,
|
||||
const struct pw_core_info *update);
|
||||
void pw_core_info_free (struct pw_core_info *info);
|
||||
struct pw_core_info *
|
||||
pw_core_info_update(struct pw_core_info *info,
|
||||
const struct pw_core_info *update);
|
||||
|
||||
void
|
||||
pw_core_info_free(struct pw_core_info *info);
|
||||
|
||||
/**
|
||||
* pw_core_info_cb_t:
|
||||
|
|
@ -137,14 +143,11 @@ void pw_core_info_free (struct pw_core_info *info);
|
|||
*
|
||||
* Callback with information about the PipeWire core in @info.
|
||||
*/
|
||||
typedef void (*pw_core_info_cb_t) (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_core_info *info,
|
||||
void *user_data);
|
||||
typedef void (*pw_core_info_cb_t) (struct pw_context * c,
|
||||
int res, const struct pw_core_info * info, void *user_data);
|
||||
|
||||
void pw_context_get_core_info (struct pw_context *context,
|
||||
pw_core_info_cb_t cb,
|
||||
void *user_data);
|
||||
void
|
||||
pw_context_get_core_info(struct pw_context *context, pw_core_info_cb_t cb, void *user_data);
|
||||
|
||||
/**
|
||||
* pw_module_info:
|
||||
|
|
@ -156,17 +159,20 @@ void pw_context_get_core_info (struct pw_context *context,
|
|||
* versions.
|
||||
*/
|
||||
struct pw_module_info {
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
const char *name;
|
||||
const char *filename;
|
||||
const char *args;
|
||||
struct spa_dict *props;
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
const char *name;
|
||||
const char *filename;
|
||||
const char *args;
|
||||
struct spa_dict *props;
|
||||
};
|
||||
|
||||
struct pw_module_info * pw_module_info_update (struct pw_module_info *info,
|
||||
const struct pw_module_info *update);
|
||||
void pw_module_info_free (struct pw_module_info *info);
|
||||
struct pw_module_info *
|
||||
pw_module_info_update(struct pw_module_info *info,
|
||||
const struct pw_module_info *update);
|
||||
|
||||
void
|
||||
pw_module_info_free(struct pw_module_info *info);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -177,18 +183,15 @@ void pw_module_info_free (struct pw_module_info *inf
|
|||
*
|
||||
* Callback with information about the PipeWire module in @info.
|
||||
*/
|
||||
typedef void (*pw_module_info_cb_t) (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_module_info *info,
|
||||
void *user_data);
|
||||
typedef void (*pw_module_info_cb_t) (struct pw_context * c,
|
||||
int res, const struct pw_module_info * info, void *user_data);
|
||||
|
||||
void pw_context_list_module_info (struct pw_context *context,
|
||||
pw_module_info_cb_t cb,
|
||||
void *user_data);
|
||||
void pw_context_get_module_info_by_id (struct pw_context *context,
|
||||
uint32_t id,
|
||||
pw_module_info_cb_t cb,
|
||||
void *user_data);
|
||||
void
|
||||
pw_context_list_module_info(struct pw_context *context,
|
||||
pw_module_info_cb_t cb, void *user_data);
|
||||
void
|
||||
pw_context_get_module_info_by_id(struct pw_context *context,
|
||||
uint32_t id, pw_module_info_cb_t cb, void *user_data);
|
||||
|
||||
/**
|
||||
* pw_client_info:
|
||||
|
|
@ -200,14 +203,17 @@ void pw_context_get_module_info_by_id (struct pw_context *context,
|
|||
* versions.
|
||||
*/
|
||||
struct pw_client_info {
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
struct spa_dict *props;
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
struct spa_dict *props;
|
||||
};
|
||||
|
||||
struct pw_client_info * pw_client_info_update (struct pw_client_info *info,
|
||||
const struct pw_client_info *update);
|
||||
void pw_client_info_free (struct pw_client_info *info);
|
||||
struct pw_client_info *
|
||||
pw_client_info_update(struct pw_client_info *info,
|
||||
const struct pw_client_info *update);
|
||||
|
||||
void
|
||||
pw_client_info_free(struct pw_client_info *info);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -218,18 +224,16 @@ void pw_client_info_free (struct pw_client_info *inf
|
|||
*
|
||||
* Callback with information about the PipeWire client in @info.
|
||||
*/
|
||||
typedef void (*pw_client_info_cb_t) (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_client_info *info,
|
||||
void *user_data);
|
||||
typedef void (*pw_client_info_cb_t) (struct pw_context * c,
|
||||
int res, const struct pw_client_info * info, void *user_data);
|
||||
|
||||
void pw_context_list_client_info (struct pw_context *context,
|
||||
pw_client_info_cb_t cb,
|
||||
void *user_data);
|
||||
void pw_context_get_client_info_by_id (struct pw_context *context,
|
||||
uint32_t id,
|
||||
pw_client_info_cb_t cb,
|
||||
void *user_data);
|
||||
void
|
||||
pw_context_list_client_info(struct pw_context *context,
|
||||
pw_client_info_cb_t cb, void *user_data);
|
||||
|
||||
void
|
||||
pw_context_get_client_info_by_id(struct pw_context *context,
|
||||
uint32_t id, pw_client_info_cb_t cb, void *user_data);
|
||||
|
||||
/**
|
||||
* pw_node_info:
|
||||
|
|
@ -244,25 +248,28 @@ void pw_context_get_client_info_by_id (struct pw_context *context,
|
|||
* versions.
|
||||
*/
|
||||
struct pw_node_info {
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
const char *name;
|
||||
uint32_t max_inputs;
|
||||
uint32_t n_inputs;
|
||||
uint32_t n_input_formats;
|
||||
struct spa_format **input_formats;
|
||||
uint32_t max_outputs;
|
||||
uint32_t n_outputs;
|
||||
uint32_t n_output_formats;
|
||||
struct spa_format **output_formats;
|
||||
enum pw_node_state state;
|
||||
const char *error;
|
||||
struct spa_dict *props;
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
const char *name;
|
||||
uint32_t max_inputs;
|
||||
uint32_t n_inputs;
|
||||
uint32_t n_input_formats;
|
||||
struct spa_format **input_formats;
|
||||
uint32_t max_outputs;
|
||||
uint32_t n_outputs;
|
||||
uint32_t n_output_formats;
|
||||
struct spa_format **output_formats;
|
||||
enum pw_node_state state;
|
||||
const char *error;
|
||||
struct spa_dict *props;
|
||||
};
|
||||
|
||||
struct pw_node_info * pw_node_info_update (struct pw_node_info *info,
|
||||
const struct pw_node_info *update);
|
||||
void pw_node_info_free (struct pw_node_info *info);
|
||||
struct pw_node_info *
|
||||
pw_node_info_update(struct pw_node_info *info,
|
||||
const struct pw_node_info *update);
|
||||
|
||||
void
|
||||
pw_node_info_free(struct pw_node_info *info);
|
||||
|
||||
/**
|
||||
* pw_node_info_cb_t:
|
||||
|
|
@ -272,18 +279,15 @@ void pw_node_info_free (struct pw_node_info *info);
|
|||
*
|
||||
* Callback with information about the PipeWire node in @info.
|
||||
*/
|
||||
typedef void (*pw_node_info_cb_t) (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_node_info *info,
|
||||
void *user_data);
|
||||
typedef void (*pw_node_info_cb_t) (struct pw_context * c,
|
||||
int res, const struct pw_node_info * info, void *user_data);
|
||||
|
||||
void pw_context_list_node_info (struct pw_context *context,
|
||||
pw_node_info_cb_t cb,
|
||||
void *user_data);
|
||||
void pw_context_get_node_info_by_id (struct pw_context *context,
|
||||
uint32_t id,
|
||||
pw_node_info_cb_t cb,
|
||||
void *user_data);
|
||||
void
|
||||
pw_context_list_node_info(struct pw_context *context, pw_node_info_cb_t cb, void *user_data);
|
||||
|
||||
void
|
||||
pw_context_get_node_info_by_id(struct pw_context *context,
|
||||
uint32_t id, pw_node_info_cb_t cb, void *user_data);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -299,17 +303,20 @@ void pw_context_get_node_info_by_id (struct pw_context *context,
|
|||
* versions.
|
||||
*/
|
||||
struct pw_link_info {
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
uint32_t output_node_id;
|
||||
uint32_t output_port_id;
|
||||
uint32_t input_node_id;
|
||||
uint32_t input_port_id;
|
||||
uint32_t id;
|
||||
uint64_t change_mask;
|
||||
uint32_t output_node_id;
|
||||
uint32_t output_port_id;
|
||||
uint32_t input_node_id;
|
||||
uint32_t input_port_id;
|
||||
};
|
||||
|
||||
struct pw_link_info * pw_link_info_update (struct pw_link_info *info,
|
||||
const struct pw_link_info *update);
|
||||
void pw_link_info_free (struct pw_link_info *info);
|
||||
struct pw_link_info *
|
||||
pw_link_info_update(struct pw_link_info *info,
|
||||
const struct pw_link_info *update);
|
||||
|
||||
void
|
||||
pw_link_info_free(struct pw_link_info *info);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -320,18 +327,15 @@ void pw_link_info_free (struct pw_link_info *info);
|
|||
*
|
||||
* Callback with information about the PipeWire link in @info.
|
||||
*/
|
||||
typedef void (*pw_link_info_cb_t) (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_link_info *info,
|
||||
void *user_data);
|
||||
typedef void (*pw_link_info_cb_t) (struct pw_context * c,
|
||||
int res, const struct pw_link_info * info, void *user_data);
|
||||
|
||||
void pw_context_list_link_info (struct pw_context *context,
|
||||
pw_link_info_cb_t cb,
|
||||
void *user_data);
|
||||
void pw_context_get_link_info_by_id (struct pw_context *context,
|
||||
uint32_t id,
|
||||
pw_link_info_cb_t cb,
|
||||
void *user_data);
|
||||
void
|
||||
pw_context_list_link_info(struct pw_context *context, pw_link_info_cb_t cb, void *user_data);
|
||||
|
||||
void
|
||||
pw_context_get_link_info_by_id(struct pw_context *context,
|
||||
uint32_t id, pw_link_info_cb_t cb, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,148 +32,128 @@ enum spa_log_level pw_log_level = DEFAULT_LOG_LEVEL;
|
|||
#define TRACE_BUFFER (16*1024)
|
||||
|
||||
struct debug_log {
|
||||
struct spa_log log;
|
||||
struct spa_ringbuffer trace_rb;
|
||||
uint8_t trace_data[TRACE_BUFFER];
|
||||
struct spa_source *source;
|
||||
struct spa_log log;
|
||||
struct spa_ringbuffer trace_rb;
|
||||
uint8_t trace_data[TRACE_BUFFER];
|
||||
struct spa_source *source;
|
||||
};
|
||||
|
||||
static void
|
||||
do_logv (struct spa_log *log,
|
||||
enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
va_list args)
|
||||
do_logv(struct spa_log *log,
|
||||
enum spa_log_level level,
|
||||
const char *file, int line, const char *func, const char *fmt, va_list args)
|
||||
{
|
||||
struct debug_log *l = SPA_CONTAINER_OF (log, struct debug_log, log);
|
||||
char text[1024], location[1024];
|
||||
static const char *levels[] = { "-", "E", "W", "I", "D", "T", "*T*"};
|
||||
int size;
|
||||
bool do_trace = (level == SPA_LOG_LEVEL_TRACE && l->source);
|
||||
struct debug_log *l = SPA_CONTAINER_OF(log, struct debug_log, log);
|
||||
char text[1024], location[1024];
|
||||
static const char *levels[] = { "-", "E", "W", "I", "D", "T", "*T*" };
|
||||
int size;
|
||||
bool do_trace = (level == SPA_LOG_LEVEL_TRACE && l->source);
|
||||
|
||||
vsnprintf (text, sizeof(text), fmt, args);
|
||||
vsnprintf(text, sizeof(text), fmt, args);
|
||||
|
||||
if ((do_trace = (level == SPA_LOG_LEVEL_TRACE && l->source)))
|
||||
level++;
|
||||
if ((do_trace = (level == SPA_LOG_LEVEL_TRACE && l->source)))
|
||||
level++;
|
||||
|
||||
size = snprintf (location, sizeof(location), "[%s][%s:%i %s()] %s\n",
|
||||
levels[level], strrchr (file, '/')+1, line, func, text);
|
||||
size = snprintf(location, sizeof(location), "[%s][%s:%i %s()] %s\n",
|
||||
levels[level], strrchr(file, '/') + 1, line, func, text);
|
||||
|
||||
if (SPA_UNLIKELY (do_trace)) {
|
||||
uint32_t index;
|
||||
uint64_t count = 1;
|
||||
if (SPA_UNLIKELY(do_trace)) {
|
||||
uint32_t index;
|
||||
uint64_t count = 1;
|
||||
|
||||
spa_ringbuffer_get_write_index (&l->trace_rb, &index);
|
||||
spa_ringbuffer_write_data (&l->trace_rb, l->trace_data,
|
||||
index & l->trace_rb.mask,
|
||||
location, size);
|
||||
spa_ringbuffer_write_update (&l->trace_rb, index + size);
|
||||
spa_ringbuffer_get_write_index(&l->trace_rb, &index);
|
||||
spa_ringbuffer_write_data(&l->trace_rb, l->trace_data,
|
||||
index & l->trace_rb.mask, location, size);
|
||||
spa_ringbuffer_write_update(&l->trace_rb, index + size);
|
||||
|
||||
write (l->source->fd, &count, sizeof(uint64_t));
|
||||
} else
|
||||
fputs (location, stdout);
|
||||
write(l->source->fd, &count, sizeof(uint64_t));
|
||||
} else
|
||||
fputs(location, stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
do_log (struct spa_log *log,
|
||||
enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt, ...)
|
||||
do_log(struct spa_log *log,
|
||||
enum spa_log_level level, const char *file, int line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
do_logv (log, level, file, line, func, fmt, args);
|
||||
va_end (args);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
do_logv(log, level, file, line, func, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static struct debug_log log = {
|
||||
{ sizeof (struct spa_log),
|
||||
NULL,
|
||||
DEFAULT_LOG_LEVEL,
|
||||
do_log,
|
||||
do_logv,
|
||||
},
|
||||
{ 0, 0, TRACE_BUFFER, TRACE_BUFFER - 1 },
|
||||
{sizeof(struct spa_log),
|
||||
NULL,
|
||||
DEFAULT_LOG_LEVEL,
|
||||
do_log,
|
||||
do_logv,
|
||||
},
|
||||
{0, 0, TRACE_BUFFER, TRACE_BUFFER - 1},
|
||||
};
|
||||
|
||||
struct spa_log *
|
||||
pw_log_get (void)
|
||||
struct spa_log *pw_log_get(void)
|
||||
{
|
||||
return &log.log;
|
||||
return &log.log;
|
||||
}
|
||||
|
||||
void pw_log_set_level(enum spa_log_level level)
|
||||
{
|
||||
pw_log_level = level;
|
||||
log.log.level = level;
|
||||
}
|
||||
|
||||
static void on_trace_event(struct spa_source *source)
|
||||
{
|
||||
int32_t avail;
|
||||
uint32_t index;
|
||||
uint64_t count;
|
||||
|
||||
if (read(source->fd, &count, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
fprintf(stderr, "failed to read event fd: %s", strerror(errno));
|
||||
|
||||
while ((avail = spa_ringbuffer_get_read_index(&log.trace_rb, &index)) > 0) {
|
||||
uint32_t offset, first;
|
||||
|
||||
if (avail > log.trace_rb.size) {
|
||||
fprintf(stderr, "\n** trace overflow ** %d\n", avail);
|
||||
index += avail - log.trace_rb.size;
|
||||
avail = log.trace_rb.size;
|
||||
}
|
||||
offset = index & log.trace_rb.mask;
|
||||
first = SPA_MIN(avail, log.trace_rb.size - offset);
|
||||
|
||||
fwrite(log.trace_data + offset, first, 1, stderr);
|
||||
if (SPA_UNLIKELY(avail > first)) {
|
||||
fwrite(log.trace_data, avail - first, 1, stderr);
|
||||
}
|
||||
spa_ringbuffer_read_update(&log.trace_rb, index + avail);
|
||||
}
|
||||
}
|
||||
|
||||
void pw_log_set_trace_event(struct spa_source *source)
|
||||
{
|
||||
log.source = source;
|
||||
log.source->func = on_trace_event;
|
||||
log.source->data = &log;
|
||||
}
|
||||
|
||||
void
|
||||
pw_log_set_level (enum spa_log_level level)
|
||||
pw_log_log(enum spa_log_level level,
|
||||
const char *file, int line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
pw_log_level = level;
|
||||
log.log.level = level;
|
||||
}
|
||||
|
||||
static void
|
||||
on_trace_event (struct spa_source *source)
|
||||
{
|
||||
int32_t avail;
|
||||
uint32_t index;
|
||||
uint64_t count;
|
||||
|
||||
if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
fprintf (stderr, "failed to read event fd: %s", strerror (errno));
|
||||
|
||||
while ((avail = spa_ringbuffer_get_read_index (&log.trace_rb, &index)) > 0) {
|
||||
uint32_t offset, first;
|
||||
|
||||
if (avail > log.trace_rb.size) {
|
||||
fprintf (stderr, "\n** trace overflow ** %d\n", avail);
|
||||
index += avail - log.trace_rb.size;
|
||||
avail = log.trace_rb.size;
|
||||
}
|
||||
offset = index & log.trace_rb.mask;
|
||||
first = SPA_MIN (avail, log.trace_rb.size - offset);
|
||||
|
||||
fwrite (log.trace_data + offset, first, 1, stderr);
|
||||
if (SPA_UNLIKELY (avail > first)) {
|
||||
fwrite (log.trace_data, avail - first, 1, stderr);
|
||||
}
|
||||
spa_ringbuffer_read_update (&log.trace_rb, index + avail);
|
||||
}
|
||||
if (SPA_UNLIKELY(pw_log_level_enabled(level))) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
do_logv(&log.log, level, file, line, func, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pw_log_set_trace_event (struct spa_source *source)
|
||||
pw_log_logv(enum spa_log_level level,
|
||||
const char *file, int line, const char *func, const char *fmt, va_list args)
|
||||
{
|
||||
log.source = source;
|
||||
log.source->func = on_trace_event;
|
||||
log.source->data = &log;
|
||||
}
|
||||
|
||||
void
|
||||
pw_log_log (enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
if (SPA_UNLIKELY (pw_log_level_enabled (level))) {
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
do_logv (&log.log, level, file, line, func, fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pw_log_logv (enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
if (SPA_UNLIKELY (pw_log_level_enabled (level))) {
|
||||
do_logv (&log.log, level, file, line, func, fmt, args);
|
||||
}
|
||||
if (SPA_UNLIKELY(pw_log_level_enabled(level))) {
|
||||
do_logv(&log.log, level, file, line, func, fmt, args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,31 +29,34 @@ extern "C" {
|
|||
|
||||
extern enum spa_log_level pw_log_level;
|
||||
|
||||
struct spa_log* pw_log_get (void);
|
||||
struct spa_log *pw_log_get(void);
|
||||
|
||||
void pw_log_set_level (enum spa_log_level level);
|
||||
void pw_log_set_trace_event (struct spa_source *source);
|
||||
void
|
||||
pw_log_set_level(enum spa_log_level level);
|
||||
|
||||
void
|
||||
pw_log_set_trace_event(struct spa_source *source);
|
||||
|
||||
|
||||
void pw_log_log (enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt, ...) SPA_PRINTF_FUNC(5, 6);
|
||||
void pw_log_logv (enum spa_log_level level,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
va_list args) SPA_PRINTF_FUNC(5, 0);
|
||||
void
|
||||
pw_log_log(enum spa_log_level level,
|
||||
const char *file,
|
||||
int line, const char *func,
|
||||
const char *fmt, ...) SPA_PRINTF_FUNC(5, 6);
|
||||
|
||||
void
|
||||
pw_log_logv(enum spa_log_level level,
|
||||
const char *file,
|
||||
int line, const char *func,
|
||||
const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0);
|
||||
|
||||
#define pw_log_level_enabled(lev) (pw_log_level >= (lev))
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
|
||||
#define pw_log_logc(lev,...) \
|
||||
if (SPA_UNLIKELY (pw_log_level_enabled (lev))) \
|
||||
pw_log_log(lev,__VA_ARGS__)
|
||||
#define pw_log_logc(lev,...) \
|
||||
if (SPA_UNLIKELY(pw_log_level_enabled (lev))) \
|
||||
pw_log_log(lev,__VA_ARGS__)
|
||||
|
||||
#define pw_log_error(...) pw_log_logc(SPA_LOG_LEVEL_ERROR,__FILE__,__LINE__,__func__,__VA_ARGS__)
|
||||
#define pw_log_warn(...) pw_log_logc(SPA_LOG_LEVEL_WARN,__FILE__,__LINE__,__func__,__VA_ARGS__)
|
||||
|
|
@ -65,16 +68,17 @@ void pw_log_logv (enum spa_log_level level,
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define PW_LOG_FUNC(name,lev) \
|
||||
static inline void pw_log_##name (const char *format, ...) \
|
||||
{ \
|
||||
if (SPA_UNLIKELY (pw_log_level_enabled (lev))) { \
|
||||
va_list varargs; \
|
||||
va_start (varargs, format); \
|
||||
pw_log_logv (lev,__FILE__,__LINE__,__func__,format,varargs); \
|
||||
va_end (varargs); \
|
||||
} \
|
||||
#define PW_LOG_FUNC(name,lev) \
|
||||
static inline void pw_log_##name (const char *format, ...) \
|
||||
{ \
|
||||
if (SPA_UNLIKELY(pw_log_level_enabled(lev))) { \
|
||||
va_list varargs; \
|
||||
va_start(varargs, format); \
|
||||
pw_log_logv(lev,__FILE__,__LINE__,__func__,format,varargs); \
|
||||
va_end(varargs); \
|
||||
} \
|
||||
}
|
||||
|
||||
PW_LOG_FUNC(error, SPA_LOG_LEVEL_ERROR)
|
||||
PW_LOG_FUNC(warn, SPA_LOG_LEVEL_WARN)
|
||||
PW_LOG_FUNC(info, SPA_LOG_LEVEL_INFO)
|
||||
|
|
@ -86,5 +90,4 @@ PW_LOG_FUNC(trace, SPA_LOG_LEVEL_TRACE)
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_LOG_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,18 +34,19 @@ extern "C" {
|
|||
* PipeWire loop interface.
|
||||
*/
|
||||
struct pw_loop {
|
||||
struct spa_loop *loop;
|
||||
struct spa_loop_control *control;
|
||||
struct spa_loop_utils *utils;
|
||||
struct spa_loop *loop;
|
||||
struct spa_loop_control *control;
|
||||
struct spa_loop_utils *utils;
|
||||
|
||||
PW_SIGNAL (before_iterate, (struct pw_listener *listener,
|
||||
struct pw_loop *loop));
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_loop *loop));
|
||||
PW_SIGNAL(before_iterate, (struct pw_listener * listener, struct pw_loop * loop));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_loop * loop));
|
||||
};
|
||||
|
||||
struct pw_loop * pw_loop_new (void);
|
||||
void pw_loop_destroy (struct pw_loop *loop);
|
||||
struct pw_loop *
|
||||
pw_loop_new(void);
|
||||
|
||||
void
|
||||
pw_loop_destroy(struct pw_loop *loop);
|
||||
|
||||
#define pw_loop_add_source(l,...) spa_loop_add_source((l)->loop,__VA_ARGS__)
|
||||
#define pw_loop_update_source(l,...) spa_loop_update_source(__VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -31,117 +31,101 @@ extern "C" {
|
|||
#include <pipewire/client/array.h>
|
||||
#include <pipewire/client/log.h>
|
||||
|
||||
union pw_map_item{
|
||||
uint32_t next;
|
||||
void *data;
|
||||
union pw_map_item {
|
||||
uint32_t next;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct pw_map {
|
||||
struct pw_array items;
|
||||
uint32_t free_list;
|
||||
struct pw_array items;
|
||||
uint32_t free_list;
|
||||
};
|
||||
|
||||
#define PW_MAP_INIT(extend) { PW_ARRAY_INIT(extend), 0 }
|
||||
|
||||
#define pw_map_get_size(m) pw_array_get_len (&(m)->items, union pw_map_item)
|
||||
#define pw_map_get_size(m) pw_array_get_len(&(m)->items, union pw_map_item)
|
||||
#define pw_map_get_item(m,id) pw_array_get_unchecked(&(m)->items,id,union pw_map_item)
|
||||
#define pw_map_item_is_free(item) ((item)->next & 0x1)
|
||||
#define pw_map_id_is_free(m,id) (pw_map_item_is_free (pw_map_get_item(m,id)))
|
||||
#define pw_map_check_id(m,id) ((id) < pw_map_get_size (m))
|
||||
#define pw_map_id_is_free(m,id) (pw_map_item_is_free(pw_map_get_item(m,id)))
|
||||
#define pw_map_check_id(m,id) ((id) < pw_map_get_size(m))
|
||||
#define pw_map_has_item(m,id) (pw_map_check_id(m,id) && !pw_map_id_is_free(m, id))
|
||||
#define pw_map_lookup_unchecked(m,id) pw_map_get_item(m,id)->data
|
||||
|
||||
#define PW_MAP_ID_TO_PTR(id) (SPA_UINT32_TO_PTR((id)<<1))
|
||||
#define PW_MAP_PTR_TO_ID(p) (SPA_PTR_TO_UINT32(p)>>1)
|
||||
|
||||
static inline void
|
||||
pw_map_init (struct pw_map *map,
|
||||
size_t size,
|
||||
size_t extend)
|
||||
static inline void pw_map_init(struct pw_map *map, size_t size, size_t extend)
|
||||
{
|
||||
pw_array_init (&map->items, extend);
|
||||
pw_array_ensure_size (&map->items, size * sizeof (union pw_map_item));
|
||||
map->free_list = 0;
|
||||
pw_array_init(&map->items, extend);
|
||||
pw_array_ensure_size(&map->items, size * sizeof(union pw_map_item));
|
||||
map->free_list = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pw_map_clear (struct pw_map *map)
|
||||
static inline void pw_map_clear(struct pw_map *map)
|
||||
{
|
||||
pw_array_clear (&map->items);
|
||||
pw_array_clear(&map->items);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
pw_map_insert_new (struct pw_map *map,
|
||||
void *data)
|
||||
static inline uint32_t pw_map_insert_new(struct pw_map *map, void *data)
|
||||
{
|
||||
union pw_map_item *start, *item;
|
||||
uint32_t id;
|
||||
union pw_map_item *start, *item;
|
||||
uint32_t id;
|
||||
|
||||
if (map->free_list) {
|
||||
start = map->items.data;
|
||||
item = &start[map->free_list >> 1];
|
||||
map->free_list = item->next;
|
||||
} else {
|
||||
item = pw_array_add (&map->items, sizeof (union pw_map_item));
|
||||
if (!item)
|
||||
return SPA_ID_INVALID;
|
||||
start = map->items.data;
|
||||
}
|
||||
item->data = data;
|
||||
id = (item - start);
|
||||
return id;
|
||||
if (map->free_list) {
|
||||
start = map->items.data;
|
||||
item = &start[map->free_list >> 1];
|
||||
map->free_list = item->next;
|
||||
} else {
|
||||
item = pw_array_add(&map->items, sizeof(union pw_map_item));
|
||||
if (!item)
|
||||
return SPA_ID_INVALID;
|
||||
start = map->items.data;
|
||||
}
|
||||
item->data = data;
|
||||
id = (item - start);
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pw_map_insert_at (struct pw_map *map,
|
||||
uint32_t id,
|
||||
void *data)
|
||||
static inline bool pw_map_insert_at(struct pw_map *map, uint32_t id, void *data)
|
||||
{
|
||||
size_t size = pw_map_get_size (map);
|
||||
union pw_map_item *item;
|
||||
size_t size = pw_map_get_size(map);
|
||||
union pw_map_item *item;
|
||||
|
||||
if (id > size)
|
||||
return false;
|
||||
else if (id == size)
|
||||
item = pw_array_add (&map->items, sizeof (union pw_map_item));
|
||||
else
|
||||
item = pw_map_get_item (map, id);
|
||||
if (id > size)
|
||||
return false;
|
||||
else if (id == size)
|
||||
item = pw_array_add(&map->items, sizeof(union pw_map_item));
|
||||
else
|
||||
item = pw_map_get_item(map, id);
|
||||
|
||||
item->data = data;
|
||||
return true;
|
||||
item->data = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pw_map_remove (struct pw_map *map,
|
||||
uint32_t id)
|
||||
static inline void pw_map_remove(struct pw_map *map, uint32_t id)
|
||||
{
|
||||
pw_map_get_item (map, id)->next = map->free_list;
|
||||
map->free_list = (id << 1) | 1;
|
||||
pw_map_get_item(map, id)->next = map->free_list;
|
||||
map->free_list = (id << 1) | 1;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
pw_map_lookup (struct pw_map *map,
|
||||
uint32_t id)
|
||||
static inline void *pw_map_lookup(struct pw_map *map, uint32_t id)
|
||||
{
|
||||
if (SPA_LIKELY (pw_map_check_id (map, id))) {
|
||||
union pw_map_item *item = pw_map_get_item (map, id);
|
||||
if (!pw_map_item_is_free (item))
|
||||
return item->data;
|
||||
}
|
||||
return NULL;
|
||||
if (SPA_LIKELY(pw_map_check_id(map, id))) {
|
||||
union pw_map_item *item = pw_map_get_item(map, id);
|
||||
if (!pw_map_item_is_free(item))
|
||||
return item->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pw_map_for_each (struct pw_map *map,
|
||||
void (*func) (void *, void *),
|
||||
void *data)
|
||||
static inline void pw_map_for_each(struct pw_map *map, void (*func) (void *, void *), void *data)
|
||||
{
|
||||
union pw_map_item *item;
|
||||
union pw_map_item *item;
|
||||
|
||||
pw_array_for_each (item, &map->items) {
|
||||
if (item->data && !pw_map_item_is_free (item))
|
||||
func (item->data, data);
|
||||
}
|
||||
pw_array_for_each(item, &map->items) {
|
||||
if (item->data && !pw_map_item_is_free(item))
|
||||
func(item->data, data);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -28,70 +28,66 @@
|
|||
#include <pipewire/client/map.h>
|
||||
|
||||
struct impl {
|
||||
struct spa_type_map map;
|
||||
struct pw_map types;
|
||||
struct pw_array strings;
|
||||
struct spa_type_map map;
|
||||
struct pw_map types;
|
||||
struct pw_array strings;
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
type_map_get_id (struct spa_type_map *map, const char *type)
|
||||
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;
|
||||
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;
|
||||
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)
|
||||
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);
|
||||
struct impl *this = SPA_CONTAINER_OF(map, struct impl, map);
|
||||
|
||||
if (id == SPA_ID_INVALID)
|
||||
return NULL;
|
||||
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;
|
||||
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)
|
||||
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);
|
||||
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)
|
||||
{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)
|
||||
};
|
||||
|
||||
struct spa_type_map *
|
||||
pw_type_map_get_default (void)
|
||||
struct spa_type_map *pw_type_map_get_default(void)
|
||||
{
|
||||
spa_type_map_set_default (&default_type_map.map);
|
||||
return &default_type_map.map;
|
||||
spa_type_map_set_default(&default_type_map.map);
|
||||
return &default_type_map.map;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,9 @@
|
|||
* a whole conflicts with the original glibc header <fnctl.h>.
|
||||
*/
|
||||
|
||||
static inline int memfd_create(const char *name, unsigned int flags) {
|
||||
return syscall(SYS_memfd_create, name, flags);
|
||||
static inline int memfd_create(const char *name, unsigned int flags)
|
||||
{
|
||||
return syscall(SYS_memfd_create, name, flags);
|
||||
}
|
||||
|
||||
/* memfd_create(2) flags */
|
||||
|
|
@ -66,137 +67,138 @@ static inline int memfd_create(const char *name, unsigned int flags) {
|
|||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#endif
|
||||
|
||||
|
||||
#undef USE_MEMFD
|
||||
|
||||
int
|
||||
pw_memblock_map (struct pw_memblock *mem)
|
||||
int pw_memblock_map(struct pw_memblock *mem)
|
||||
{
|
||||
if (mem->ptr != NULL)
|
||||
return SPA_RESULT_OK;
|
||||
if (mem->ptr != NULL)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_READWRITE) {
|
||||
int prot = 0;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_READWRITE) {
|
||||
int prot = 0;
|
||||
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_READ)
|
||||
prot |= PROT_READ;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_WRITE)
|
||||
prot |= PROT_WRITE;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_READ)
|
||||
prot |= PROT_READ;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_WRITE)
|
||||
prot |= PROT_WRITE;
|
||||
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_TWICE) {
|
||||
void *ptr;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_MAP_TWICE) {
|
||||
void *ptr;
|
||||
|
||||
mem->ptr = mmap (NULL, mem->size << 1, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (mem->ptr == MAP_FAILED)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
mem->ptr =
|
||||
mmap(NULL, mem->size << 1, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1,
|
||||
0);
|
||||
if (mem->ptr == MAP_FAILED)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
|
||||
ptr = mmap (mem->ptr, mem->size, prot, MAP_FIXED | MAP_SHARED, mem->fd, mem->offset);
|
||||
if (ptr != mem->ptr) {
|
||||
munmap (mem->ptr, mem->size << 1);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
ptr =
|
||||
mmap(mem->ptr, mem->size, prot, MAP_FIXED | MAP_SHARED, mem->fd,
|
||||
mem->offset);
|
||||
if (ptr != mem->ptr) {
|
||||
munmap(mem->ptr, mem->size << 1);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
|
||||
ptr = mmap (mem->ptr + mem->size, mem->size, prot, MAP_FIXED | MAP_SHARED, mem->fd, mem->offset);
|
||||
if (ptr != mem->ptr + mem->size) {
|
||||
munmap (mem->ptr, mem->size << 1);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
mem->ptr = mmap (NULL, mem->size, prot, MAP_SHARED, mem->fd, 0);
|
||||
if (mem->ptr == MAP_FAILED)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
mem->ptr = NULL;
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
ptr =
|
||||
mmap(mem->ptr + mem->size, mem->size, prot, MAP_FIXED | MAP_SHARED,
|
||||
mem->fd, mem->offset);
|
||||
if (ptr != mem->ptr + mem->size) {
|
||||
munmap(mem->ptr, mem->size << 1);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
mem->ptr = mmap(NULL, mem->size, prot, MAP_SHARED, mem->fd, 0);
|
||||
if (mem->ptr == MAP_FAILED)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
mem->ptr = NULL;
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pw_memblock_alloc (enum pw_memblock_flags flags,
|
||||
size_t size,
|
||||
struct pw_memblock *mem)
|
||||
int pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock *mem)
|
||||
{
|
||||
bool use_fd;
|
||||
bool use_fd;
|
||||
|
||||
if (mem == NULL || size == 0)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (mem == NULL || size == 0)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
mem->offset = 0;
|
||||
mem->flags = flags;
|
||||
mem->size = size;
|
||||
mem->offset = 0;
|
||||
mem->flags = flags;
|
||||
mem->size = size;
|
||||
|
||||
use_fd = !!(flags & (PW_MEMBLOCK_FLAG_MAP_TWICE | PW_MEMBLOCK_FLAG_WITH_FD));
|
||||
use_fd = ! !(flags & (PW_MEMBLOCK_FLAG_MAP_TWICE | PW_MEMBLOCK_FLAG_WITH_FD));
|
||||
|
||||
if (use_fd) {
|
||||
if (use_fd) {
|
||||
#ifdef USE_MEMFD
|
||||
mem->fd = memfd_create ("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
if (mem->fd == -1) {
|
||||
pw_log_error ("Failed to create memfd: %s\n", strerror (errno));
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
mem->fd = memfd_create("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
if (mem->fd == -1) {
|
||||
pw_log_error("Failed to create memfd: %s\n", strerror(errno));
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
#else
|
||||
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
|
||||
mem->fd = mkostemp (filename, O_CLOEXEC);
|
||||
if (mem->fd == -1) {
|
||||
pw_log_error ("Failed to create temporary file: %s\n", strerror (errno));
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
unlink (filename);
|
||||
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
|
||||
mem->fd = mkostemp(filename, O_CLOEXEC);
|
||||
if (mem->fd == -1) {
|
||||
pw_log_error("Failed to create temporary file: %s\n", strerror(errno));
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
unlink(filename);
|
||||
#endif
|
||||
|
||||
if (ftruncate (mem->fd, size) < 0) {
|
||||
pw_log_warn ("Failed to truncate temporary file: %s", strerror (errno));
|
||||
close (mem->fd);
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
if (ftruncate(mem->fd, size) < 0) {
|
||||
pw_log_warn("Failed to truncate temporary file: %s", strerror(errno));
|
||||
close(mem->fd);
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
#ifdef USE_MEMFD
|
||||
if (flags & PW_MEMBLOCK_FLAG_SEAL) {
|
||||
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
|
||||
if (fcntl (mem->fd, F_ADD_SEALS, seals) == -1) {
|
||||
pw_log_warn ("Failed to add seals: %s", strerror (errno));
|
||||
}
|
||||
}
|
||||
if (flags & PW_MEMBLOCK_FLAG_SEAL) {
|
||||
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
|
||||
if (fcntl(mem->fd, F_ADD_SEALS, seals) == -1) {
|
||||
pw_log_warn("Failed to add seals: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (pw_memblock_map (mem) != SPA_RESULT_OK)
|
||||
goto mmap_failed;
|
||||
} else {
|
||||
mem->ptr = malloc (size);
|
||||
if (mem->ptr == NULL)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
mem->fd = -1;
|
||||
}
|
||||
if (!(flags & PW_MEMBLOCK_FLAG_WITH_FD) && mem->fd != -1) {
|
||||
close (mem->fd);
|
||||
mem->fd = -1;
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
if (pw_memblock_map(mem) != SPA_RESULT_OK)
|
||||
goto mmap_failed;
|
||||
} else {
|
||||
mem->ptr = malloc(size);
|
||||
if (mem->ptr == NULL)
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
mem->fd = -1;
|
||||
}
|
||||
if (!(flags & PW_MEMBLOCK_FLAG_WITH_FD) && mem->fd != -1) {
|
||||
close(mem->fd);
|
||||
mem->fd = -1;
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
mmap_failed:
|
||||
close (mem->fd);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
mmap_failed:
|
||||
close(mem->fd);
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
pw_memblock_free (struct pw_memblock *mem)
|
||||
void pw_memblock_free(struct pw_memblock *mem)
|
||||
{
|
||||
if (mem == NULL)
|
||||
return;
|
||||
if (mem == NULL)
|
||||
return;
|
||||
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_WITH_FD) {
|
||||
if (mem->ptr)
|
||||
munmap (mem->ptr, mem->size);
|
||||
if (mem->fd != -1)
|
||||
close (mem->fd);
|
||||
} else {
|
||||
free (mem->ptr);
|
||||
}
|
||||
mem->ptr = NULL;
|
||||
mem->fd = -1;
|
||||
if (mem->flags & PW_MEMBLOCK_FLAG_WITH_FD) {
|
||||
if (mem->ptr)
|
||||
munmap(mem->ptr, mem->size);
|
||||
if (mem->fd != -1)
|
||||
close(mem->fd);
|
||||
} else {
|
||||
free(mem->ptr);
|
||||
}
|
||||
mem->ptr = NULL;
|
||||
mem->fd = -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,29 +27,32 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
enum pw_memblock_flags {
|
||||
PW_MEMBLOCK_FLAG_NONE = 0,
|
||||
PW_MEMBLOCK_FLAG_WITH_FD = (1 << 0),
|
||||
PW_MEMBLOCK_FLAG_SEAL = (1 << 1),
|
||||
PW_MEMBLOCK_FLAG_MAP_READ = (1 << 2),
|
||||
PW_MEMBLOCK_FLAG_MAP_WRITE = (1 << 3),
|
||||
PW_MEMBLOCK_FLAG_MAP_TWICE = (1 << 4),
|
||||
PW_MEMBLOCK_FLAG_NONE = 0,
|
||||
PW_MEMBLOCK_FLAG_WITH_FD = (1 << 0),
|
||||
PW_MEMBLOCK_FLAG_SEAL = (1 << 1),
|
||||
PW_MEMBLOCK_FLAG_MAP_READ = (1 << 2),
|
||||
PW_MEMBLOCK_FLAG_MAP_WRITE = (1 << 3),
|
||||
PW_MEMBLOCK_FLAG_MAP_TWICE = (1 << 4),
|
||||
};
|
||||
|
||||
#define PW_MEMBLOCK_FLAG_MAP_READWRITE (PW_MEMBLOCK_FLAG_MAP_READ | PW_MEMBLOCK_FLAG_MAP_WRITE)
|
||||
|
||||
struct pw_memblock {
|
||||
enum pw_memblock_flags flags;
|
||||
int fd;
|
||||
off_t offset;
|
||||
void *ptr;
|
||||
size_t size;
|
||||
enum pw_memblock_flags flags;
|
||||
int fd;
|
||||
off_t offset;
|
||||
void *ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
int pw_memblock_alloc (enum pw_memblock_flags flags,
|
||||
size_t size,
|
||||
struct pw_memblock *mem);
|
||||
int pw_memblock_map (struct pw_memblock *mem);
|
||||
void pw_memblock_free (struct pw_memblock *mem);
|
||||
int
|
||||
pw_memblock_alloc(enum pw_memblock_flags flags, size_t size, struct pw_memblock *mem);
|
||||
|
||||
int
|
||||
pw_memblock_map(struct pw_memblock *mem);
|
||||
|
||||
void
|
||||
pw_memblock_free(struct pw_memblock *mem);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,9 @@
|
|||
* a whole conflicts with the original glibc header <fnctl.h>.
|
||||
*/
|
||||
|
||||
static inline int memfd_create(const char *name, unsigned int flags) {
|
||||
return syscall(SYS_memfd_create, name, flags);
|
||||
static inline int
|
||||
memfd_create(const char *name, unsigned int flags) {
|
||||
return syscall(SYS_memfd_create, name, flags);
|
||||
}
|
||||
|
||||
/* memfd_create(2) flags */
|
||||
|
|
|
|||
|
|
@ -32,54 +32,49 @@
|
|||
* initialize the PipeWire system, parse and modify any parameters given
|
||||
* by @argc and @argv.
|
||||
*/
|
||||
void
|
||||
pw_init (int *argc, char **argv[])
|
||||
void pw_init(int *argc, char **argv[])
|
||||
{
|
||||
const char *str;
|
||||
const char *str;
|
||||
|
||||
if ((str = getenv ("PIPEWIRE_DEBUG")))
|
||||
pw_log_set_level (atoi (str));
|
||||
if ((str = getenv("PIPEWIRE_DEBUG")))
|
||||
pw_log_set_level(atoi(str));
|
||||
}
|
||||
|
||||
const char *
|
||||
pw_get_application_name (void)
|
||||
const char *pw_get_application_name(void)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
pw_get_prgname (void)
|
||||
const char *pw_get_prgname(void)
|
||||
{
|
||||
static char tcomm[16+1];
|
||||
spa_zero(tcomm);
|
||||
static char tcomm[16 + 1];
|
||||
spa_zero(tcomm);
|
||||
|
||||
if (prctl (PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0)
|
||||
return tcomm;
|
||||
if (prctl(PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0)
|
||||
return tcomm;
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
pw_get_user_name (void)
|
||||
const char *pw_get_user_name(void)
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = getpwuid (getuid ())))
|
||||
return pw->pw_name;
|
||||
if ((pw = getpwuid(getuid())))
|
||||
return pw->pw_name;
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
pw_get_host_name (void)
|
||||
const char *pw_get_host_name(void)
|
||||
{
|
||||
static char hname[256];
|
||||
static char hname[256];
|
||||
|
||||
if (gethostname (hname, 256) < 0)
|
||||
return NULL;
|
||||
if (gethostname(hname, 256) < 0)
|
||||
return NULL;
|
||||
|
||||
hname[255] = 0;
|
||||
return hname;
|
||||
hname[255] = 0;
|
||||
return hname;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,20 +82,19 @@ pw_get_host_name (void)
|
|||
*
|
||||
* Make a new PipeWire client name that can be used to construct a context.
|
||||
*/
|
||||
char *
|
||||
pw_client_name (void)
|
||||
char *pw_client_name(void)
|
||||
{
|
||||
char *c;
|
||||
const char *cc;
|
||||
char *c;
|
||||
const char *cc;
|
||||
|
||||
if ((cc = pw_get_application_name ()))
|
||||
return strdup (cc);
|
||||
else if ((cc = pw_get_prgname ()))
|
||||
return strdup (cc);
|
||||
else {
|
||||
asprintf (&c, "pipewire-pid-%zd", (size_t) getpid ());
|
||||
return c;
|
||||
}
|
||||
if ((cc = pw_get_application_name()))
|
||||
return strdup(cc);
|
||||
else if ((cc = pw_get_prgname()))
|
||||
return strdup(cc);
|
||||
else {
|
||||
asprintf(&c, "pipewire-pid-%zd", (size_t) getpid());
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,30 +103,30 @@ pw_client_name (void)
|
|||
*
|
||||
* Fill @properties with a set of default context properties.
|
||||
*/
|
||||
void
|
||||
pw_fill_context_properties (struct pw_properties *properties)
|
||||
void pw_fill_context_properties(struct pw_properties *properties)
|
||||
{
|
||||
if (!pw_properties_get (properties, "application.name"))
|
||||
pw_properties_set (properties, "application.name", pw_get_application_name ());
|
||||
if (!pw_properties_get(properties, "application.name"))
|
||||
pw_properties_set(properties, "application.name", pw_get_application_name());
|
||||
|
||||
if (!pw_properties_get (properties, "application.prgname"))
|
||||
pw_properties_set (properties, "application.prgname", pw_get_prgname ());
|
||||
if (!pw_properties_get(properties, "application.prgname"))
|
||||
pw_properties_set(properties, "application.prgname", pw_get_prgname());
|
||||
|
||||
if (!pw_properties_get (properties, "application.language")) {
|
||||
pw_properties_set (properties, "application.language", getenv ("LANG"));
|
||||
}
|
||||
if (!pw_properties_get (properties, "application.process.id")) {
|
||||
pw_properties_setf (properties, "application.process.id", "%zd", (size_t) getpid ());
|
||||
}
|
||||
if (!pw_properties_get (properties, "application.process.user"))
|
||||
pw_properties_set (properties, "application.process.user", pw_get_user_name ());
|
||||
if (!pw_properties_get(properties, "application.language")) {
|
||||
pw_properties_set(properties, "application.language", getenv("LANG"));
|
||||
}
|
||||
if (!pw_properties_get(properties, "application.process.id")) {
|
||||
pw_properties_setf(properties, "application.process.id", "%zd", (size_t) getpid());
|
||||
}
|
||||
if (!pw_properties_get(properties, "application.process.user"))
|
||||
pw_properties_set(properties, "application.process.user", pw_get_user_name());
|
||||
|
||||
if (!pw_properties_get (properties, "application.process.host"))
|
||||
pw_properties_set (properties, "application.process.host", pw_get_host_name ());
|
||||
if (!pw_properties_get(properties, "application.process.host"))
|
||||
pw_properties_set(properties, "application.process.host", pw_get_host_name());
|
||||
|
||||
if (!pw_properties_get (properties, "application.process.session_id")) {
|
||||
pw_properties_set (properties, "application.process.session_id", getenv ("XDG_SESSION_ID"));
|
||||
}
|
||||
if (!pw_properties_get(properties, "application.process.session_id")) {
|
||||
pw_properties_set(properties, "application.process.session_id",
|
||||
getenv("XDG_SESSION_ID"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -141,17 +135,15 @@ pw_fill_context_properties (struct pw_properties *properties)
|
|||
*
|
||||
* Fill @properties with a set of default stream properties.
|
||||
*/
|
||||
void
|
||||
pw_fill_stream_properties (struct pw_properties *properties)
|
||||
void pw_fill_stream_properties(struct pw_properties *properties)
|
||||
{
|
||||
}
|
||||
|
||||
enum pw_direction
|
||||
pw_direction_reverse (enum pw_direction direction)
|
||||
enum pw_direction pw_direction_reverse(enum pw_direction direction)
|
||||
{
|
||||
if (direction == PW_DIRECTION_INPUT)
|
||||
return PW_DIRECTION_OUTPUT;
|
||||
else if (direction == PW_DIRECTION_OUTPUT)
|
||||
return PW_DIRECTION_INPUT;
|
||||
return direction;
|
||||
if (direction == PW_DIRECTION_INPUT)
|
||||
return PW_DIRECTION_OUTPUT;
|
||||
else if (direction == PW_DIRECTION_OUTPUT)
|
||||
return PW_DIRECTION_INPUT;
|
||||
return direction;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,24 +37,37 @@ extern "C" {
|
|||
|
||||
#include <spa/type-map.h>
|
||||
|
||||
void pw_init (int *argc, char **argv[]);
|
||||
void
|
||||
pw_init(int *argc, char **argv[]);
|
||||
|
||||
const char * pw_get_application_name (void);
|
||||
const char * pw_get_prgname (void);
|
||||
const char * pw_get_user_name (void);
|
||||
const char * pw_get_host_name (void);
|
||||
const char *
|
||||
pw_get_application_name(void);
|
||||
|
||||
char * pw_client_name (void);
|
||||
const char *
|
||||
pw_get_prgname(void);
|
||||
|
||||
void pw_fill_context_properties (struct pw_properties *properties);
|
||||
void pw_fill_stream_properties (struct pw_properties *properties);
|
||||
const char *
|
||||
pw_get_user_name(void);
|
||||
|
||||
enum pw_direction pw_direction_reverse (enum pw_direction direction);
|
||||
const char *
|
||||
pw_get_host_name(void);
|
||||
|
||||
struct spa_type_map * pw_type_map_get_default (void);
|
||||
char *
|
||||
pw_client_name(void);
|
||||
|
||||
void
|
||||
pw_fill_context_properties(struct pw_properties *properties);
|
||||
|
||||
void
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_H__ */
|
||||
|
|
|
|||
|
|
@ -21,44 +21,42 @@
|
|||
#include "pipewire/client/properties.h"
|
||||
|
||||
struct properties {
|
||||
struct pw_properties this;
|
||||
struct pw_properties this;
|
||||
|
||||
struct pw_array items;
|
||||
struct pw_array items;
|
||||
};
|
||||
|
||||
static void
|
||||
add_func (struct pw_properties *this, char *key, char *value)
|
||||
static void add_func(struct pw_properties *this, char *key, char *value)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
struct properties *impl = SPA_CONTAINER_OF (this, struct properties, this);
|
||||
struct spa_dict_item *item;
|
||||
struct properties *impl = SPA_CONTAINER_OF(this, struct properties, this);
|
||||
|
||||
item = pw_array_add (&impl->items, sizeof (struct spa_dict_item));
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
item = pw_array_add(&impl->items, sizeof(struct spa_dict_item));
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
|
||||
this->dict.items = impl->items.data;
|
||||
this->dict.n_items = pw_array_get_len (&impl->items, struct spa_dict_item);
|
||||
this->dict.items = impl->items.data;
|
||||
this->dict.n_items = pw_array_get_len(&impl->items, struct spa_dict_item);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_item (struct spa_dict_item *item)
|
||||
static void clear_item(struct spa_dict_item *item)
|
||||
{
|
||||
free ((char*)item->key);
|
||||
free ((char*)item->value);
|
||||
free((char *) item->key);
|
||||
free((char *) item->value);
|
||||
}
|
||||
|
||||
static int
|
||||
find_index (struct pw_properties *this, const char *key)
|
||||
static int find_index(struct pw_properties *this, const char *key)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (this, struct properties, this);
|
||||
int i, len = pw_array_get_len (&impl->items, struct spa_dict_item);
|
||||
struct properties *impl = SPA_CONTAINER_OF(this, struct properties, this);
|
||||
int i, len = pw_array_get_len(&impl->items, struct spa_dict_item);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
struct spa_dict_item *item = pw_array_get_unchecked (&impl->items, i, struct spa_dict_item);
|
||||
if (strcmp (item->key, key) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
for (i = 0; i < len; i++) {
|
||||
struct spa_dict_item *item =
|
||||
pw_array_get_unchecked(&impl->items, i, struct spa_dict_item);
|
||||
if (strcmp(item->key, key) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,28 +68,27 @@ find_index (struct pw_properties *this, const char *key)
|
|||
*
|
||||
* Returns: a new #struct pw_properties
|
||||
*/
|
||||
struct pw_properties *
|
||||
pw_properties_new (const char *key, ...)
|
||||
struct pw_properties *pw_properties_new(const char *key, ...)
|
||||
{
|
||||
struct properties *impl;
|
||||
va_list varargs;
|
||||
const char *value;
|
||||
struct properties *impl;
|
||||
va_list varargs;
|
||||
const char *value;
|
||||
|
||||
impl = calloc (1, sizeof (struct properties));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct properties));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_array_init (&impl->items, 16);
|
||||
pw_array_init(&impl->items, 16);
|
||||
|
||||
va_start (varargs, key);
|
||||
while (key != NULL) {
|
||||
value = va_arg (varargs, char *);
|
||||
add_func (&impl->this, strdup (key), strdup (value));
|
||||
key = va_arg (varargs, char *);
|
||||
}
|
||||
va_end (varargs);
|
||||
va_start(varargs, key);
|
||||
while (key != NULL) {
|
||||
value = va_arg(varargs, char *);
|
||||
add_func(&impl->this, strdup(key), strdup(value));
|
||||
key = va_arg(varargs, char *);
|
||||
}
|
||||
va_end(varargs);
|
||||
|
||||
return &impl->this;
|
||||
return &impl->this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -102,22 +99,21 @@ pw_properties_new (const char *key, ...)
|
|||
*
|
||||
* Returns: a new #struct pw_properties
|
||||
*/
|
||||
struct pw_properties *
|
||||
pw_properties_new_dict (const struct spa_dict *dict)
|
||||
struct pw_properties *pw_properties_new_dict(const struct spa_dict *dict)
|
||||
{
|
||||
uint32_t i;
|
||||
struct properties *impl;
|
||||
uint32_t i;
|
||||
struct properties *impl;
|
||||
|
||||
impl = calloc (1, sizeof (struct properties));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct properties));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_array_init (&impl->items, 16);
|
||||
pw_array_init(&impl->items, 16);
|
||||
|
||||
for (i = 0; i < dict->n_items; i++)
|
||||
add_func (&impl->this, strdup (dict->items[i].key), strdup (dict->items[i].value));
|
||||
for (i = 0; i < dict->n_items; i++)
|
||||
add_func(&impl->this, strdup(dict->items[i].key), strdup(dict->items[i].value));
|
||||
|
||||
return &impl->this;
|
||||
return &impl->this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,51 +124,47 @@ pw_properties_new_dict (const struct spa_dict *dict)
|
|||
*
|
||||
* Returns: a copy of @properties
|
||||
*/
|
||||
struct pw_properties *
|
||||
pw_properties_copy (struct pw_properties *properties)
|
||||
struct pw_properties *pw_properties_copy(struct pw_properties *properties)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (properties, struct properties, this);
|
||||
struct pw_properties *copy;
|
||||
struct spa_dict_item *item;
|
||||
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
|
||||
struct pw_properties *copy;
|
||||
struct spa_dict_item *item;
|
||||
|
||||
copy = pw_properties_new (NULL, NULL);
|
||||
if (copy == NULL)
|
||||
return NULL;
|
||||
copy = pw_properties_new(NULL, NULL);
|
||||
if (copy == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_array_for_each (item, &impl->items)
|
||||
add_func (copy, strdup (item->key), strdup (item->value));
|
||||
pw_array_for_each(item, &impl->items)
|
||||
add_func(copy, strdup(item->key), strdup(item->value));
|
||||
|
||||
return copy;
|
||||
return copy;
|
||||
}
|
||||
|
||||
struct pw_properties *
|
||||
pw_properties_merge (struct pw_properties *oldprops,
|
||||
struct pw_properties *newprops)
|
||||
struct pw_properties *pw_properties_merge(struct pw_properties *oldprops,
|
||||
struct pw_properties *newprops)
|
||||
{
|
||||
struct pw_properties *res = NULL;
|
||||
struct pw_properties *res = NULL;
|
||||
|
||||
if (oldprops == NULL) {
|
||||
if (newprops == NULL)
|
||||
res = NULL;
|
||||
else
|
||||
res = pw_properties_copy (newprops);
|
||||
} else if (newprops == NULL) {
|
||||
res = pw_properties_copy (oldprops);
|
||||
} else {
|
||||
const char *key;
|
||||
void * state = NULL;
|
||||
if (oldprops == NULL) {
|
||||
if (newprops == NULL)
|
||||
res = NULL;
|
||||
else
|
||||
res = pw_properties_copy(newprops);
|
||||
} else if (newprops == NULL) {
|
||||
res = pw_properties_copy(oldprops);
|
||||
} else {
|
||||
const char *key;
|
||||
void *state = NULL;
|
||||
|
||||
res = pw_properties_copy (oldprops);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
res = pw_properties_copy(oldprops);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((key = pw_properties_iterate (newprops, &state))) {
|
||||
pw_properties_set (res,
|
||||
key,
|
||||
pw_properties_get (newprops, key));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
while ((key = pw_properties_iterate(newprops, &state))) {
|
||||
pw_properties_set(res, key, pw_properties_get(newprops, key));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,45 +173,45 @@ pw_properties_merge (struct pw_properties *oldprops,
|
|||
*
|
||||
* Free @properties
|
||||
*/
|
||||
void
|
||||
pw_properties_free (struct pw_properties *properties)
|
||||
void pw_properties_free(struct pw_properties *properties)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (properties, struct properties, this);
|
||||
struct spa_dict_item *item;
|
||||
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
|
||||
struct spa_dict_item *item;
|
||||
|
||||
pw_array_for_each (item, &impl->items)
|
||||
clear_item (item);
|
||||
pw_array_for_each(item, &impl->items)
|
||||
clear_item(item);
|
||||
|
||||
pw_array_clear (&impl->items);
|
||||
free (impl);
|
||||
pw_array_clear(&impl->items);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
static void
|
||||
do_replace (struct pw_properties *properties,
|
||||
char *key,
|
||||
char *value)
|
||||
static void do_replace(struct pw_properties *properties, char *key, char *value)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (properties, struct properties, this);
|
||||
int index = find_index (properties, key);
|
||||
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
|
||||
int index = find_index(properties, key);
|
||||
|
||||
if (index == -1) {
|
||||
add_func (properties, key, value);
|
||||
} else {
|
||||
struct spa_dict_item *item = pw_array_get_unchecked (&impl->items, index, struct spa_dict_item);
|
||||
if (index == -1) {
|
||||
add_func(properties, key, value);
|
||||
} else {
|
||||
struct spa_dict_item *item =
|
||||
pw_array_get_unchecked(&impl->items, index, struct spa_dict_item);
|
||||
|
||||
clear_item (item);
|
||||
if (value == NULL) {
|
||||
struct spa_dict_item *other = pw_array_get_unchecked (&impl->items,
|
||||
pw_array_get_len (&impl->items, struct spa_dict_item) - 1,
|
||||
struct spa_dict_item);
|
||||
item->key = other->key;
|
||||
item->value = other->value;
|
||||
impl->items.size -= sizeof (struct spa_dict_item);
|
||||
} else {
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
}
|
||||
}
|
||||
clear_item(item);
|
||||
if (value == NULL) {
|
||||
struct spa_dict_item *other = pw_array_get_unchecked(&impl->items,
|
||||
pw_array_get_len
|
||||
(&impl->items,
|
||||
struct spa_dict_item)
|
||||
- 1,
|
||||
struct spa_dict_item);
|
||||
item->key = other->key;
|
||||
item->value = other->value;
|
||||
impl->items.size -= sizeof(struct spa_dict_item);
|
||||
} else {
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -232,12 +224,9 @@ do_replace (struct pw_properties *properties,
|
|||
* of @key will be overwritten. When @value is %NULL, the key will be
|
||||
* removed.
|
||||
*/
|
||||
void
|
||||
pw_properties_set (struct pw_properties *properties,
|
||||
const char *key,
|
||||
const char *value)
|
||||
void pw_properties_set(struct pw_properties *properties, const char *key, const char *value)
|
||||
{
|
||||
do_replace (properties, strdup (key), value ? strdup (value) : NULL);
|
||||
do_replace(properties, strdup(key), value ? strdup(value) : NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -250,20 +239,16 @@ pw_properties_set (struct pw_properties *properties,
|
|||
* Set the property in @properties with @key to the value in printf style @format
|
||||
* Any previous value of @key will be overwritten.
|
||||
*/
|
||||
void
|
||||
pw_properties_setf (struct pw_properties *properties,
|
||||
const char *key,
|
||||
const char *format,
|
||||
...)
|
||||
void pw_properties_setf(struct pw_properties *properties, const char *key, const char *format, ...)
|
||||
{
|
||||
va_list varargs;
|
||||
char *value;
|
||||
va_list varargs;
|
||||
char *value;
|
||||
|
||||
va_start (varargs, format);
|
||||
vasprintf (&value, format, varargs);
|
||||
va_end (varargs);
|
||||
va_start(varargs, format);
|
||||
vasprintf(&value, format, varargs);
|
||||
va_end(varargs);
|
||||
|
||||
do_replace (properties, strdup (key), value);
|
||||
do_replace(properties, strdup(key), value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,17 +260,15 @@ pw_properties_setf (struct pw_properties *properties,
|
|||
*
|
||||
* Returns: the property for @key or %NULL when the key was not found
|
||||
*/
|
||||
const char *
|
||||
pw_properties_get (struct pw_properties *properties,
|
||||
const char *key)
|
||||
const char *pw_properties_get(struct pw_properties *properties, const char *key)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (properties, struct properties, this);
|
||||
int index = find_index (properties, key);
|
||||
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
|
||||
int index = find_index(properties, key);
|
||||
|
||||
if (index == -1)
|
||||
return NULL;
|
||||
if (index == -1)
|
||||
return NULL;
|
||||
|
||||
return pw_array_get_unchecked (&impl->items, index, struct spa_dict_item)->value;
|
||||
return pw_array_get_unchecked(&impl->items, index, struct spa_dict_item)->value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -302,22 +285,20 @@ pw_properties_get (struct pw_properties *properties,
|
|||
*
|
||||
* Returns: The next key or %NULL when there are no more keys to iterate.
|
||||
*/
|
||||
const char *
|
||||
pw_properties_iterate (struct pw_properties *properties,
|
||||
void **state)
|
||||
const char *pw_properties_iterate(struct pw_properties *properties, void **state)
|
||||
{
|
||||
struct properties *impl = SPA_CONTAINER_OF (properties, struct properties, this);
|
||||
uint32_t index;
|
||||
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
|
||||
uint32_t index;
|
||||
|
||||
if (*state == NULL)
|
||||
index = 0;
|
||||
else
|
||||
index = SPA_PTR_TO_INT (*state);
|
||||
if (*state == NULL)
|
||||
index = 0;
|
||||
else
|
||||
index = SPA_PTR_TO_INT(*state);
|
||||
|
||||
if (!pw_array_check_index (&impl->items, index, struct spa_dict_item))
|
||||
return NULL;
|
||||
if (!pw_array_check_index(&impl->items, index, struct spa_dict_item))
|
||||
return NULL;
|
||||
|
||||
*state = SPA_INT_TO_PTR (index + 1);
|
||||
*state = SPA_INT_TO_PTR(index + 1);
|
||||
|
||||
return pw_array_get_unchecked (&impl->items, index, struct spa_dict_item)->key;
|
||||
return pw_array_get_unchecked(&impl->items, index, struct spa_dict_item)->key;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,34 +21,42 @@
|
|||
#define __PIPEWIRE_PROPERTIES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
//extern "C" {
|
||||
#endif
|
||||
|
||||
#include <spa/dict.h>
|
||||
|
||||
struct pw_properties {
|
||||
struct spa_dict dict;
|
||||
struct spa_dict dict;
|
||||
};
|
||||
|
||||
struct pw_properties * pw_properties_new (const char *key, ...);
|
||||
struct pw_properties * pw_properties_new_dict (const struct spa_dict *dict);
|
||||
struct pw_properties * pw_properties_copy (struct pw_properties *properties);
|
||||
struct pw_properties * pw_properties_merge (struct pw_properties *oldprops,
|
||||
struct pw_properties *newprops);
|
||||
void pw_properties_free (struct pw_properties *properties);
|
||||
struct pw_properties *
|
||||
pw_properties_new(const char *key, ...);
|
||||
|
||||
void pw_properties_set (struct pw_properties *properties,
|
||||
const char *key,
|
||||
const char *value);
|
||||
void pw_properties_setf (struct pw_properties *properties,
|
||||
const char *key,
|
||||
const char *format,
|
||||
...) SPA_PRINTF_FUNC (3, 4);
|
||||
const char * pw_properties_get (struct pw_properties *properties,
|
||||
const char *key);
|
||||
struct pw_properties *
|
||||
pw_properties_new_dict(const struct spa_dict *dict);
|
||||
|
||||
const char * pw_properties_iterate (struct pw_properties *properties,
|
||||
void **state);
|
||||
struct pw_properties *
|
||||
pw_properties_copy(struct pw_properties *properties);
|
||||
|
||||
struct pw_properties *
|
||||
pw_properties_merge(struct pw_properties *oldprops,
|
||||
struct pw_properties *newprops);
|
||||
|
||||
void
|
||||
pw_properties_free(struct pw_properties *properties);
|
||||
|
||||
void
|
||||
pw_properties_set(struct pw_properties *properties, const char *key, const char *value);
|
||||
|
||||
void
|
||||
pw_properties_setf(struct pw_properties *properties,
|
||||
const char *key, const char *format, ...) SPA_PRINTF_FUNC(3, 4);
|
||||
const char *
|
||||
pw_properties_get(struct pw_properties *properties, const char *key);
|
||||
|
||||
const char *
|
||||
pw_properties_iterate(struct pw_properties *properties, void **state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -20,4 +20,5 @@
|
|||
#include "pipewire/client/pipewire.h"
|
||||
#include "pipewire/client/interfaces.h"
|
||||
|
||||
bool pw_protocol_native_client_setup (struct pw_proxy *proxy);
|
||||
bool
|
||||
pw_protocol_native_client_setup(struct pw_proxy *proxy);
|
||||
|
|
|
|||
|
|
@ -22,58 +22,54 @@
|
|||
#include <pipewire/client/protocol-native.h>
|
||||
|
||||
struct proxy {
|
||||
struct pw_proxy this;
|
||||
struct pw_proxy this;
|
||||
};
|
||||
|
||||
struct pw_proxy *
|
||||
pw_proxy_new (struct pw_context *context,
|
||||
uint32_t id,
|
||||
uint32_t type)
|
||||
struct pw_proxy *pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t type)
|
||||
{
|
||||
struct proxy *impl;
|
||||
struct pw_proxy *this;
|
||||
struct proxy *impl;
|
||||
struct pw_proxy *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct proxy));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct proxy));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this->context = context;
|
||||
this->type = type;
|
||||
this = &impl->this;
|
||||
this->context = context;
|
||||
this->type = type;
|
||||
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
if (id == SPA_ID_INVALID) {
|
||||
id = pw_map_insert_new (&context->objects, this);
|
||||
} else if (!pw_map_insert_at (&context->objects, id, this))
|
||||
goto in_use;
|
||||
if (id == SPA_ID_INVALID) {
|
||||
id = pw_map_insert_new(&context->objects, this);
|
||||
} else if (!pw_map_insert_at(&context->objects, id, this))
|
||||
goto in_use;
|
||||
|
||||
this->id = id;
|
||||
this->id = id;
|
||||
|
||||
pw_protocol_native_client_setup (this);
|
||||
pw_protocol_native_client_setup(this);
|
||||
|
||||
spa_list_insert (&this->context->proxy_list, &this->link);
|
||||
spa_list_insert(&this->context->proxy_list, &this->link);
|
||||
|
||||
pw_log_trace ("proxy %p: new %u", this, this->id);
|
||||
pw_log_trace("proxy %p: new %u", this, this->id);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
in_use:
|
||||
pw_log_error ("proxy %p: id %u in use for context %p", this, id, context);
|
||||
free (impl);
|
||||
return NULL;
|
||||
in_use:
|
||||
pw_log_error("proxy %p: id %u in use for context %p", this, id, context);
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_proxy_destroy (struct pw_proxy *proxy)
|
||||
void pw_proxy_destroy(struct pw_proxy *proxy)
|
||||
{
|
||||
struct proxy *impl = SPA_CONTAINER_OF (proxy, struct proxy, this);
|
||||
struct proxy *impl = SPA_CONTAINER_OF(proxy, struct proxy, this);
|
||||
|
||||
pw_log_trace ("proxy %p: destroy %u", proxy, proxy->id);
|
||||
pw_signal_emit (&proxy->destroy_signal, proxy);
|
||||
pw_log_trace("proxy %p: destroy %u", proxy, proxy->id);
|
||||
pw_signal_emit(&proxy->destroy_signal, proxy);
|
||||
|
||||
pw_map_remove (&proxy->context->objects, proxy->id);
|
||||
spa_list_remove (&proxy->link);
|
||||
pw_map_remove(&proxy->context->objects, proxy->id);
|
||||
spa_list_remove(&proxy->link);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,25 +29,25 @@ extern "C" {
|
|||
#include <pipewire/client/type.h>
|
||||
|
||||
struct pw_proxy {
|
||||
struct pw_context *context;
|
||||
struct spa_list link;
|
||||
struct pw_context *context;
|
||||
struct spa_list link;
|
||||
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
|
||||
const struct pw_interface *iface;
|
||||
const void *implementation;
|
||||
const struct pw_interface *iface;
|
||||
const void *implementation;
|
||||
|
||||
void *user_data;
|
||||
void *user_data;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_proxy *proxy));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_proxy * proxy));
|
||||
};
|
||||
|
||||
struct pw_proxy * pw_proxy_new (struct pw_context *context,
|
||||
uint32_t id,
|
||||
uint32_t type);
|
||||
void pw_proxy_destroy (struct pw_proxy *proxy);
|
||||
struct pw_proxy *
|
||||
pw_proxy_new(struct pw_context *context, uint32_t id, uint32_t type);
|
||||
|
||||
void
|
||||
pw_proxy_destroy(struct pw_proxy *proxy);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,41 +52,39 @@
|
|||
#include "rtkit.h"
|
||||
|
||||
struct pw_rtkit_bus {
|
||||
DBusConnection *bus;
|
||||
DBusConnection *bus;
|
||||
};
|
||||
|
||||
struct pw_rtkit_bus *
|
||||
pw_rtkit_bus_get_system (void)
|
||||
struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
|
||||
{
|
||||
struct pw_rtkit_bus *bus;
|
||||
DBusError error;
|
||||
struct pw_rtkit_bus *bus;
|
||||
DBusError error;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_error_init(&error);
|
||||
|
||||
bus = calloc (1, sizeof (struct pw_rtkit_bus));
|
||||
if (bus == NULL)
|
||||
return NULL;
|
||||
bus = calloc(1, sizeof(struct pw_rtkit_bus));
|
||||
if (bus == NULL)
|
||||
return NULL;
|
||||
|
||||
bus->bus = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
|
||||
if (bus->bus == NULL)
|
||||
goto error;
|
||||
bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
|
||||
if (bus->bus == NULL)
|
||||
goto error;
|
||||
|
||||
dbus_connection_set_exit_on_disconnect (bus->bus, false);
|
||||
dbus_connection_set_exit_on_disconnect(bus->bus, false);
|
||||
|
||||
return bus;
|
||||
return bus;
|
||||
|
||||
error:
|
||||
pw_log_error ("Failed to connect to system bus: %s", error.message);
|
||||
dbus_error_free (&error);
|
||||
return NULL;
|
||||
error:
|
||||
pw_log_error("Failed to connect to system bus: %s", error.message);
|
||||
dbus_error_free(&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_rtkit_bus_free (struct pw_rtkit_bus *system_bus)
|
||||
void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
|
||||
{
|
||||
dbus_connection_close (system_bus->bus);
|
||||
dbus_connection_unref (system_bus->bus);
|
||||
free (system_bus);
|
||||
dbus_connection_close(system_bus->bus);
|
||||
dbus_connection_unref(system_bus->bus);
|
||||
free(system_bus);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
|
|
@ -105,277 +103,274 @@ pw_rtkit_bus_free (struct pw_rtkit_bus *system_bus)
|
|||
#include <sys/syscall.h>
|
||||
|
||||
|
||||
static pid_t _gettid(void) {
|
||||
return (pid_t) syscall(SYS_gettid);
|
||||
}
|
||||
|
||||
static int translate_error(const char *name) {
|
||||
if (0 == strcmp (name, DBUS_ERROR_NO_MEMORY))
|
||||
return -ENOMEM;
|
||||
if (0 == strcmp (name, DBUS_ERROR_SERVICE_UNKNOWN) ||
|
||||
0 == strcmp (name, DBUS_ERROR_NAME_HAS_NO_OWNER))
|
||||
return -ENOENT;
|
||||
if (0 == strcmp (name, DBUS_ERROR_ACCESS_DENIED) ||
|
||||
0 == strcmp (name, DBUS_ERROR_AUTH_FAILED))
|
||||
return -EACCES;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static long long rtkit_get_int_property(struct pw_rtkit_bus *connection, const char* propname, long long* propval) {
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
DBusMessageIter iter, subiter;
|
||||
dbus_int64_t i64;
|
||||
dbus_int32_t i32;
|
||||
DBusError error;
|
||||
int current_type;
|
||||
long long ret;
|
||||
const char * interfacestr = "org.freedesktop.RealtimeKit1";
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_STRING, &interfacestr,
|
||||
DBUS_TYPE_STRING, &propname,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = -EBADMSG;
|
||||
dbus_message_iter_init(r, &iter);
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_VARIANT) {
|
||||
dbus_message_iter_recurse(&iter, &subiter);
|
||||
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_INT32) {
|
||||
dbus_message_iter_get_basic(&subiter, &i32);
|
||||
*propval = i32;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (current_type == DBUS_TYPE_INT64) {
|
||||
dbus_message_iter_get_basic(&subiter, &i64);
|
||||
*propval = i64;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dbus_message_iter_next (&subiter);
|
||||
}
|
||||
}
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int* min_nice_level) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MinNiceLevel", &retval);
|
||||
if (err >= 0)
|
||||
*min_nice_level = retval;
|
||||
return err;
|
||||
}
|
||||
|
||||
long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "RTTimeUSecMax", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int
|
||||
pw_rtkit_make_realtime (struct pw_rtkit_bus *connection,
|
||||
pid_t thread,
|
||||
int priority)
|
||||
static pid_t _gettid(void)
|
||||
{
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_uint32_t u32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtime"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
u32 = (dbus_uint32_t) priority;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_UINT32, &u32,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
return (pid_t) syscall(SYS_gettid);
|
||||
}
|
||||
|
||||
int
|
||||
pw_rtkit_make_high_priority (struct pw_rtkit_bus *connection,
|
||||
pid_t thread,
|
||||
int nice_level)
|
||||
static int translate_error(const char *name)
|
||||
{
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_int32_t s32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
if (0 == strcmp(name, DBUS_ERROR_NO_MEMORY))
|
||||
return -ENOMEM;
|
||||
if (0 == strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) ||
|
||||
0 == strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER))
|
||||
return -ENOENT;
|
||||
if (0 == strcmp(name, DBUS_ERROR_ACCESS_DENIED) ||
|
||||
0 == strcmp(name, DBUS_ERROR_AUTH_FAILED))
|
||||
return -EACCES;
|
||||
|
||||
dbus_error_init(&error);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
static long long rtkit_get_int_property(struct pw_rtkit_bus *connection, const char *propname,
|
||||
long long *propval)
|
||||
{
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
DBusMessageIter iter, subiter;
|
||||
dbus_int64_t i64;
|
||||
dbus_int32_t i32;
|
||||
DBusError error;
|
||||
int current_type;
|
||||
long long ret;
|
||||
const char *interfacestr = "org.freedesktop.RealtimeKit1";
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadHighPriority"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
dbus_error_init(&error);
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
s32 = (dbus_int32_t) nice_level;
|
||||
if (!(m = dbus_message_new_method_call(RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.DBus.Properties", "Get"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_INT32, &s32,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
if (!dbus_message_append_args(m,
|
||||
DBUS_TYPE_STRING, &interfacestr,
|
||||
DBUS_TYPE_STRING, &propname, DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = -EBADMSG;
|
||||
dbus_message_iter_init(r, &iter);
|
||||
while ((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_VARIANT) {
|
||||
dbus_message_iter_recurse(&iter, &subiter);
|
||||
|
||||
while ((current_type =
|
||||
dbus_message_iter_get_arg_type(&subiter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_INT32) {
|
||||
dbus_message_iter_get_basic(&subiter, &i32);
|
||||
*propval = i32;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (current_type == DBUS_TYPE_INT64) {
|
||||
dbus_message_iter_get_basic(&subiter, &i64);
|
||||
*propval = i64;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dbus_message_iter_next(&subiter);
|
||||
}
|
||||
}
|
||||
dbus_message_iter_next(&iter);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection)
|
||||
{
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int *min_nice_level)
|
||||
{
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MinNiceLevel", &retval);
|
||||
if (err >= 0)
|
||||
*min_nice_level = retval;
|
||||
return err;
|
||||
}
|
||||
|
||||
long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection)
|
||||
{
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "RTTimeUSecMax", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority)
|
||||
{
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_uint32_t u32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
|
||||
if (!(m = dbus_message_new_method_call(RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtime"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
u32 = (dbus_uint32_t) priority;
|
||||
|
||||
if (!dbus_message_append_args(m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_UINT32, &u32, DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, int nice_level)
|
||||
{
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_int32_t s32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
|
||||
if (!(m = dbus_message_new_method_call(RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadHighPriority"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
s32 = (dbus_int32_t) nice_level;
|
||||
|
||||
if (!dbus_message_append_args(m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_INT32, &s32, DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority) {
|
||||
return -ENOTSUP;
|
||||
int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, int nice_level) {
|
||||
return -ENOTSUP;
|
||||
int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, int nice_level)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection) {
|
||||
return -ENOTSUP;
|
||||
int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int* min_nice_level) {
|
||||
return -ENOTSUP;
|
||||
int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int *min_nice_level)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection) {
|
||||
return -ENOTSUP;
|
||||
long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,11 @@ extern "C" {
|
|||
#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
|
||||
#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
|
||||
|
||||
struct pw_rtkit_bus * pw_rtkit_bus_get_system (void);
|
||||
void pw_rtkit_bus_free (struct pw_rtkit_bus *system_bus);
|
||||
struct pw_rtkit_bus *
|
||||
pw_rtkit_bus_get_system(void);
|
||||
|
||||
void
|
||||
pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus);
|
||||
|
||||
|
||||
/* This is mostly equivalent to sched_setparam(thread, SCHED_RR, {
|
||||
|
|
@ -39,9 +42,8 @@ void pw_rtkit_bus_free (struct pw_rtkit_bus *system_bu
|
|||
* id as returned by gettid(), not a pthread_t! If 'thread' is 0 the
|
||||
* current thread is used. The returned value is a negative errno
|
||||
* style error code, or 0 on success. */
|
||||
int pw_rtkit_make_realtime (struct pw_rtkit_bus *system_bus,
|
||||
pid_t thread,
|
||||
int priority);
|
||||
int
|
||||
pw_rtkit_make_realtime(struct pw_rtkit_bus *system_bus, pid_t thread, int priority);
|
||||
|
||||
|
||||
/* This is mostly equivalent to setpriority(PRIO_PROCESS, thread,
|
||||
|
|
@ -49,25 +51,26 @@ int pw_rtkit_make_realtime (struct pw_rtkit_bus *system
|
|||
* gettid(), not a pthread_t! If 'thread' is 0 the current thread is
|
||||
* used. The returned value is a negative errno style error code, or
|
||||
* 0 on success. */
|
||||
int pw_rtkit_make_high_priority (struct pw_rtkit_bus *system_bus,
|
||||
pid_t thread,
|
||||
int nice_level);
|
||||
int
|
||||
pw_rtkit_make_high_priority(struct pw_rtkit_bus *system_bus, pid_t thread, int nice_level);
|
||||
|
||||
/* Return the maximum value of realtime priority available. Realtime requests
|
||||
* above this value will fail. A negative value is an errno style error code.
|
||||
*/
|
||||
int pw_rtkit_get_max_realtime_priority (struct pw_rtkit_bus *system_bus);
|
||||
int
|
||||
pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *system_bus);
|
||||
|
||||
/* Retreive the minimum value of nice level available. High prio requests
|
||||
* below this value will fail. The returned value is a negative errno
|
||||
* style error code, or 0 on success.*/
|
||||
int pw_rtkit_get_min_nice_level (struct pw_rtkit_bus *system_bus,
|
||||
int *min_nice_level);
|
||||
int
|
||||
pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *system_bus, int *min_nice_level);
|
||||
|
||||
/* Return the maximum value of RLIMIT_RTTIME to set before attempting a
|
||||
* realtime request. A negative value is an errno style error code.
|
||||
*/
|
||||
long long pw_rtkit_get_rttime_usec_max (struct pw_rtkit_bus *system_bus);
|
||||
long long
|
||||
pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *system_bus);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,38 +27,37 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct pw_listener {
|
||||
struct spa_list link;
|
||||
void (*notify) (void *);
|
||||
struct spa_list link;
|
||||
void (*notify) (void *);
|
||||
};
|
||||
|
||||
#define PW_SIGNAL(name,func) \
|
||||
union { \
|
||||
struct spa_list listeners; \
|
||||
void (*notify) func; \
|
||||
} name;
|
||||
#define PW_SIGNAL(name,func) \
|
||||
union { \
|
||||
struct spa_list listeners; \
|
||||
void (*notify) func; \
|
||||
} name;
|
||||
|
||||
#define pw_signal_init(signal) \
|
||||
spa_list_init (&(signal)->listeners);
|
||||
#define pw_signal_init(signal) \
|
||||
spa_list_init(&(signal)->listeners);
|
||||
|
||||
#define pw_signal_add(signal,listener,func) \
|
||||
do { \
|
||||
__typeof__((signal)->notify) n = (func); \
|
||||
(listener)->notify = (void (*) (void *)) n; \
|
||||
spa_list_insert ((signal)->listeners.prev, &(listener)->link); \
|
||||
} while (false);
|
||||
#define pw_signal_add(signal,listener,func) \
|
||||
do { \
|
||||
__typeof__((signal)->notify) n = (func); \
|
||||
(listener)->notify = (void(*)(void *)) n; \
|
||||
spa_list_insert((signal)->listeners.prev, &(listener)->link); \
|
||||
} while (false);
|
||||
|
||||
static inline void
|
||||
pw_signal_remove (struct pw_listener *listener)
|
||||
static inline void pw_signal_remove(struct pw_listener *listener)
|
||||
{
|
||||
spa_list_remove (&listener->link);
|
||||
spa_list_remove(&listener->link);
|
||||
}
|
||||
|
||||
#define pw_signal_emit(signal,...) \
|
||||
do { \
|
||||
struct pw_listener *l, *next; \
|
||||
spa_list_for_each_safe (l, next, &(signal)->listeners, link) \
|
||||
((__typeof__((signal)->notify))l->notify) (l,__VA_ARGS__); \
|
||||
} while (false);
|
||||
#define pw_signal_emit(signal,...) \
|
||||
do { \
|
||||
struct pw_listener *l, *next; \
|
||||
spa_list_for_each_safe(l, next, &(signal)->listeners, link) \
|
||||
((__typeof__((signal)->notify))l->notify)(l,__VA_ARGS__); \
|
||||
} while (false);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,32 +30,33 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
enum pw_stream_state {
|
||||
PW_STREAM_STATE_ERROR = -1,
|
||||
PW_STREAM_STATE_UNCONNECTED = 0,
|
||||
PW_STREAM_STATE_CONNECTING = 1,
|
||||
PW_STREAM_STATE_CONFIGURE = 2,
|
||||
PW_STREAM_STATE_READY = 3,
|
||||
PW_STREAM_STATE_PAUSED = 4,
|
||||
PW_STREAM_STATE_STREAMING = 5
|
||||
PW_STREAM_STATE_ERROR = -1,
|
||||
PW_STREAM_STATE_UNCONNECTED = 0,
|
||||
PW_STREAM_STATE_CONNECTING = 1,
|
||||
PW_STREAM_STATE_CONFIGURE = 2,
|
||||
PW_STREAM_STATE_READY = 3,
|
||||
PW_STREAM_STATE_PAUSED = 4,
|
||||
PW_STREAM_STATE_STREAMING = 5
|
||||
};
|
||||
|
||||
const char * pw_stream_state_as_string (enum pw_stream_state state);
|
||||
const char *
|
||||
pw_stream_state_as_string(enum pw_stream_state state);
|
||||
|
||||
enum pw_stream_flags {
|
||||
PW_STREAM_FLAG_NONE = 0,
|
||||
PW_STREAM_FLAG_AUTOCONNECT = (1 << 0),
|
||||
PW_STREAM_FLAG_CLOCK_UPDATE = (1 << 1),
|
||||
PW_STREAM_FLAG_NONE = 0,
|
||||
PW_STREAM_FLAG_AUTOCONNECT = (1 << 0),
|
||||
PW_STREAM_FLAG_CLOCK_UPDATE = (1 << 1),
|
||||
};
|
||||
|
||||
enum pw_stream_mode {
|
||||
PW_STREAM_MODE_BUFFER = 0,
|
||||
PW_STREAM_MODE_RINGBUFFER = 1,
|
||||
PW_STREAM_MODE_BUFFER = 0,
|
||||
PW_STREAM_MODE_RINGBUFFER = 1,
|
||||
};
|
||||
|
||||
struct pw_time{
|
||||
int64_t now;
|
||||
int64_t ticks;
|
||||
int32_t rate;
|
||||
struct pw_time {
|
||||
int64_t now;
|
||||
int64_t ticks;
|
||||
int32_t rate;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -64,66 +65,66 @@ struct pw_time{
|
|||
* PipeWire stream object class.
|
||||
*/
|
||||
struct pw_stream {
|
||||
struct pw_context *context;
|
||||
struct spa_list link;
|
||||
struct pw_context *context;
|
||||
struct spa_list link;
|
||||
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_stream *stream));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_stream * stream));
|
||||
|
||||
enum pw_stream_state state;
|
||||
char *error;
|
||||
PW_SIGNAL (state_changed, (struct pw_listener *listener,
|
||||
struct pw_stream *stream));
|
||||
enum pw_stream_state state;
|
||||
char *error;
|
||||
PW_SIGNAL(state_changed, (struct pw_listener * listener, struct pw_stream * stream));
|
||||
|
||||
PW_SIGNAL (format_changed, (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
struct spa_format *format));
|
||||
PW_SIGNAL(format_changed, (struct pw_listener * listener,
|
||||
struct pw_stream * stream, struct spa_format * format));
|
||||
|
||||
PW_SIGNAL (add_buffer, (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
uint32_t id));
|
||||
PW_SIGNAL (remove_buffer, (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
uint32_t id));
|
||||
PW_SIGNAL (new_buffer, (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
uint32_t id));
|
||||
PW_SIGNAL (need_buffer, (struct pw_listener *listener,
|
||||
struct pw_stream *stream));
|
||||
PW_SIGNAL(add_buffer, (struct pw_listener * listener,
|
||||
struct pw_stream * stream, uint32_t id));
|
||||
PW_SIGNAL(remove_buffer, (struct pw_listener * listener,
|
||||
struct pw_stream * stream, uint32_t id));
|
||||
PW_SIGNAL(new_buffer, (struct pw_listener * listener,
|
||||
struct pw_stream * stream, uint32_t id));
|
||||
PW_SIGNAL(need_buffer, (struct pw_listener * listener, struct pw_stream * stream));
|
||||
};
|
||||
|
||||
struct pw_stream * pw_stream_new (struct pw_context *context,
|
||||
const char *name,
|
||||
struct pw_properties *props);
|
||||
void pw_stream_destroy (struct pw_stream *stream);
|
||||
struct pw_stream *
|
||||
pw_stream_new(struct pw_context *context,
|
||||
const char *name, struct pw_properties *props);
|
||||
void
|
||||
pw_stream_destroy(struct pw_stream *stream);
|
||||
|
||||
bool pw_stream_connect (struct pw_stream *stream,
|
||||
enum pw_direction direction,
|
||||
enum pw_stream_mode mode,
|
||||
const char *port_path,
|
||||
enum pw_stream_flags flags,
|
||||
uint32_t n_possible_formats,
|
||||
struct spa_format **possible_formats);
|
||||
bool pw_stream_disconnect (struct pw_stream *stream);
|
||||
bool
|
||||
pw_stream_connect(struct pw_stream *stream,
|
||||
enum pw_direction direction,
|
||||
enum pw_stream_mode mode,
|
||||
const char *port_path,
|
||||
enum pw_stream_flags flags,
|
||||
uint32_t n_possible_formats,
|
||||
struct spa_format **possible_formats);
|
||||
bool
|
||||
pw_stream_disconnect(struct pw_stream *stream);
|
||||
|
||||
bool pw_stream_finish_format (struct pw_stream *stream,
|
||||
int res,
|
||||
struct spa_param **params,
|
||||
uint32_t n_params);
|
||||
bool
|
||||
pw_stream_finish_format(struct pw_stream *stream,
|
||||
int res, struct spa_param **params, uint32_t n_params);
|
||||
|
||||
bool pw_stream_get_time (struct pw_stream *stream,
|
||||
struct pw_time *time);
|
||||
bool
|
||||
pw_stream_get_time(struct pw_stream *stream, struct pw_time *time);
|
||||
|
||||
uint32_t
|
||||
pw_stream_get_empty_buffer(struct pw_stream *stream);
|
||||
|
||||
bool
|
||||
pw_stream_recycle_buffer(struct pw_stream *stream, uint32_t id);
|
||||
|
||||
struct spa_buffer *
|
||||
pw_stream_peek_buffer(struct pw_stream *stream, uint32_t id);
|
||||
|
||||
bool
|
||||
pw_stream_send_buffer(struct pw_stream *stream, uint32_t id);
|
||||
|
||||
uint32_t pw_stream_get_empty_buffer (struct pw_stream *stream);
|
||||
bool pw_stream_recycle_buffer (struct pw_stream *stream,
|
||||
uint32_t id);
|
||||
struct spa_buffer *pw_stream_peek_buffer (struct pw_stream *stream,
|
||||
uint32_t id);
|
||||
bool pw_stream_send_buffer (struct pw_stream *stream,
|
||||
uint32_t id);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ extern "C" {
|
|||
#define PIPEWIRE_TYPE_MODULE_BASE PIPEWIRE_TYPE__Module ":"
|
||||
|
||||
enum pw_subscription_event {
|
||||
PW_SUBSCRIPTION_EVENT_NEW = 0,
|
||||
PW_SUBSCRIPTION_EVENT_CHANGE = 1,
|
||||
PW_SUBSCRIPTION_EVENT_REMOVE = 2,
|
||||
PW_SUBSCRIPTION_EVENT_NEW = 0,
|
||||
PW_SUBSCRIPTION_EVENT_CHANGE = 1,
|
||||
PW_SUBSCRIPTION_EVENT_REMOVE = 2,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -23,46 +23,39 @@
|
|||
#include "thread-mainloop.h"
|
||||
|
||||
struct thread_main_loop {
|
||||
struct pw_thread_main_loop this;
|
||||
struct pw_thread_main_loop this;
|
||||
|
||||
char *name;
|
||||
char *name;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_t accept_cond;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_t accept_cond;
|
||||
|
||||
bool running;
|
||||
pthread_t thread;
|
||||
bool running;
|
||||
pthread_t thread;
|
||||
|
||||
struct spa_source *event;
|
||||
struct spa_source *event;
|
||||
|
||||
int n_waiting;
|
||||
int n_waiting_for_accept;
|
||||
int n_waiting;
|
||||
int n_waiting_for_accept;
|
||||
};
|
||||
|
||||
static void
|
||||
pre_hook (struct spa_loop_control *ctrl,
|
||||
void *data)
|
||||
static void pre_hook(struct spa_loop_control *ctrl, void *data)
|
||||
{
|
||||
struct thread_main_loop *impl = data;
|
||||
pthread_mutex_unlock (&impl->lock);
|
||||
struct thread_main_loop *impl = data;
|
||||
pthread_mutex_unlock(&impl->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
post_hook (struct spa_loop_control *ctrl,
|
||||
void *data)
|
||||
static void post_hook(struct spa_loop_control *ctrl, void *data)
|
||||
{
|
||||
struct thread_main_loop *impl = data;
|
||||
pthread_mutex_lock (&impl->lock);
|
||||
struct thread_main_loop *impl = data;
|
||||
pthread_mutex_lock(&impl->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
do_stop (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
void *data)
|
||||
static void do_stop(struct spa_loop_utils *utils, struct spa_source *source, void *data)
|
||||
{
|
||||
struct thread_main_loop *impl = data;
|
||||
impl->running = false;
|
||||
struct thread_main_loop *impl = data;
|
||||
impl->running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -75,82 +68,73 @@ do_stop (struct spa_loop_utils *utils,
|
|||
*
|
||||
* Returns: a #struct pw_thread_main_loop
|
||||
*/
|
||||
struct pw_thread_main_loop *
|
||||
pw_thread_main_loop_new (struct pw_loop *loop,
|
||||
const char *name)
|
||||
struct pw_thread_main_loop *pw_thread_main_loop_new(struct pw_loop *loop, const char *name)
|
||||
{
|
||||
struct thread_main_loop *impl;
|
||||
struct pw_thread_main_loop *this;
|
||||
pthread_mutexattr_t attr;
|
||||
struct thread_main_loop *impl;
|
||||
struct pw_thread_main_loop *this;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
impl = calloc (1, sizeof (struct thread_main_loop));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct thread_main_loop));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
pw_log_debug ("thread-mainloop %p: new", impl);
|
||||
this = &impl->this;
|
||||
pw_log_debug("thread-mainloop %p: new", impl);
|
||||
|
||||
this->loop = loop;
|
||||
this->name = name ? strdup (name) : NULL;
|
||||
this->loop = loop;
|
||||
this->name = name ? strdup(name) : NULL;
|
||||
|
||||
pw_loop_set_hooks (loop,
|
||||
pre_hook,
|
||||
post_hook,
|
||||
impl);
|
||||
pw_loop_set_hooks(loop, pre_hook, post_hook, impl);
|
||||
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
pthread_mutexattr_init (&attr);
|
||||
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init (&impl->lock, &attr);
|
||||
pthread_cond_init (&impl->cond, NULL);
|
||||
pthread_cond_init (&impl->accept_cond, NULL);
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&impl->lock, &attr);
|
||||
pthread_cond_init(&impl->cond, NULL);
|
||||
pthread_cond_init(&impl->accept_cond, NULL);
|
||||
|
||||
impl->event = pw_loop_add_event (this->loop,
|
||||
do_stop,
|
||||
impl);
|
||||
impl->event = pw_loop_add_event(this->loop, do_stop, impl);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
pw_thread_main_loop_destroy (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_destroy(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
pw_signal_emit (&loop->destroy_signal, loop);
|
||||
pw_signal_emit(&loop->destroy_signal, loop);
|
||||
|
||||
pw_thread_main_loop_stop (loop);
|
||||
pw_thread_main_loop_stop(loop);
|
||||
|
||||
if (loop->name)
|
||||
free (loop->name);
|
||||
pthread_mutex_destroy (&impl->lock);
|
||||
pthread_cond_destroy (&impl->cond);
|
||||
pthread_cond_destroy (&impl->accept_cond);
|
||||
if (loop->name)
|
||||
free(loop->name);
|
||||
pthread_mutex_destroy(&impl->lock);
|
||||
pthread_cond_destroy(&impl->cond);
|
||||
pthread_cond_destroy(&impl->accept_cond);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
static void *
|
||||
do_loop (void *user_data)
|
||||
static void *do_loop(void *user_data)
|
||||
{
|
||||
struct thread_main_loop *impl = user_data;
|
||||
struct pw_thread_main_loop *this = &impl->this;
|
||||
int res;
|
||||
struct thread_main_loop *impl = user_data;
|
||||
struct pw_thread_main_loop *this = &impl->this;
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock (&impl->lock);
|
||||
pw_log_debug ("thread-mainloop %p: enter thread", this);
|
||||
pw_loop_enter (this->loop);
|
||||
pthread_mutex_lock(&impl->lock);
|
||||
pw_log_debug("thread-mainloop %p: enter thread", this);
|
||||
pw_loop_enter(this->loop);
|
||||
|
||||
while (impl->running) {
|
||||
if ((res = pw_loop_iterate (this->loop, -1)) < 0)
|
||||
pw_log_warn ("thread-mainloop %p: iterate error %d", this, res);
|
||||
}
|
||||
pw_log_debug ("thread-mainloop %p: leave thread", this);
|
||||
pw_loop_leave (this->loop);
|
||||
pthread_mutex_unlock (&impl->lock);
|
||||
while (impl->running) {
|
||||
if ((res = pw_loop_iterate(this->loop, -1)) < 0)
|
||||
pw_log_warn("thread-mainloop %p: iterate error %d", this, res);
|
||||
}
|
||||
pw_log_debug("thread-mainloop %p: leave thread", this);
|
||||
pw_loop_leave(this->loop);
|
||||
pthread_mutex_unlock(&impl->lock);
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,22 +145,22 @@ do_loop (void *user_data)
|
|||
*
|
||||
* Returns: %SPA_RESULT_OK on success.
|
||||
*/
|
||||
int
|
||||
pw_thread_main_loop_start (struct pw_thread_main_loop *loop)
|
||||
int pw_thread_main_loop_start(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
if (!impl->running) {
|
||||
int err;
|
||||
if (!impl->running) {
|
||||
int err;
|
||||
|
||||
impl->running = true;
|
||||
if ((err = pthread_create (&impl->thread, NULL, do_loop, impl)) != 0) {
|
||||
pw_log_warn ("thread-mainloop %p: can't create thread: %s", impl, strerror (err));
|
||||
impl->running = false;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
impl->running = true;
|
||||
if ((err = pthread_create(&impl->thread, NULL, do_loop, impl)) != 0) {
|
||||
pw_log_warn("thread-mainloop %p: can't create thread: %s", impl,
|
||||
strerror(err));
|
||||
impl->running = false;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -185,21 +169,20 @@ pw_thread_main_loop_start (struct pw_thread_main_loop *loop)
|
|||
*
|
||||
* Quit the main loop and stop its thread.
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_stop (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_stop(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
pw_log_debug ("thread-mainloop: %p stopping", impl);
|
||||
if (impl->running) {
|
||||
pw_log_debug ("thread-mainloop: %p signal", impl);
|
||||
pw_loop_signal_event (loop->loop, impl->event);
|
||||
pw_log_debug ("thread-mainloop: %p join", impl);
|
||||
pthread_join (impl->thread, NULL);
|
||||
pw_log_debug ("thread-mainloop: %p joined", impl);
|
||||
impl->running = false;
|
||||
}
|
||||
pw_log_debug ("thread-mainloop: %p stopped", impl);
|
||||
pw_log_debug("thread-mainloop: %p stopping", impl);
|
||||
if (impl->running) {
|
||||
pw_log_debug("thread-mainloop: %p signal", impl);
|
||||
pw_loop_signal_event(loop->loop, impl->event);
|
||||
pw_log_debug("thread-mainloop: %p join", impl);
|
||||
pthread_join(impl->thread, NULL);
|
||||
pw_log_debug("thread-mainloop: %p joined", impl);
|
||||
impl->running = false;
|
||||
}
|
||||
pw_log_debug("thread-mainloop: %p stopped", impl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -208,11 +191,10 @@ pw_thread_main_loop_stop (struct pw_thread_main_loop *loop)
|
|||
*
|
||||
* Lock the mutex associated with @loop.
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_lock (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_lock(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
pthread_mutex_lock (&impl->lock);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
pthread_mutex_lock(&impl->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -221,11 +203,10 @@ pw_thread_main_loop_lock (struct pw_thread_main_loop *loop)
|
|||
*
|
||||
* Unlock the mutex associated with @loop.
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_unlock (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_unlock(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
pthread_mutex_unlock (&impl->lock);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
pthread_mutex_unlock(&impl->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,21 +216,19 @@ pw_thread_main_loop_unlock (struct pw_thread_main_loop *loop)
|
|||
* Signal the main thread of @loop. If @wait_for_accept is %TRUE,
|
||||
* this function waits until pw_thread_main_loop_accept() is called.
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_signal (struct pw_thread_main_loop *loop,
|
||||
bool wait_for_accept)
|
||||
void pw_thread_main_loop_signal(struct pw_thread_main_loop *loop, bool wait_for_accept)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
if (impl->n_waiting > 0)
|
||||
pthread_cond_broadcast (&impl->cond);
|
||||
if (impl->n_waiting > 0)
|
||||
pthread_cond_broadcast(&impl->cond);
|
||||
|
||||
if (wait_for_accept) {
|
||||
impl->n_waiting_for_accept++;
|
||||
if (wait_for_accept) {
|
||||
impl->n_waiting_for_accept++;
|
||||
|
||||
while (impl->n_waiting_for_accept > 0)
|
||||
pthread_cond_wait (&impl->accept_cond, &impl->lock);
|
||||
}
|
||||
while (impl->n_waiting_for_accept > 0)
|
||||
pthread_cond_wait(&impl->accept_cond, &impl->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -258,15 +237,14 @@ pw_thread_main_loop_signal (struct pw_thread_main_loop *loop,
|
|||
*
|
||||
* Wait for the loop thread to call pw_thread_main_loop_signal().
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_wait (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_wait(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
impl->n_waiting++;
|
||||
impl->n_waiting++;
|
||||
|
||||
pthread_cond_wait (&impl->cond, &impl->lock);
|
||||
impl->n_waiting --;
|
||||
pthread_cond_wait(&impl->cond, &impl->lock);
|
||||
impl->n_waiting--;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,13 +253,12 @@ pw_thread_main_loop_wait (struct pw_thread_main_loop *loop)
|
|||
*
|
||||
* Signal the loop thread waiting for accept with pw_thread_main_loop_signal().
|
||||
*/
|
||||
void
|
||||
pw_thread_main_loop_accept (struct pw_thread_main_loop *loop)
|
||||
void pw_thread_main_loop_accept(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
|
||||
impl->n_waiting_for_accept--;
|
||||
pthread_cond_signal (&impl->accept_cond);
|
||||
impl->n_waiting_for_accept--;
|
||||
pthread_cond_signal(&impl->accept_cond);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -292,9 +269,8 @@ pw_thread_main_loop_accept (struct pw_thread_main_loop *loop)
|
|||
*
|
||||
* Returns: %TRUE when called inside the thread of @loop.
|
||||
*/
|
||||
bool
|
||||
pw_thread_main_loop_in_thread (struct pw_thread_main_loop *loop)
|
||||
bool pw_thread_main_loop_in_thread(struct pw_thread_main_loop *loop)
|
||||
{
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF (loop, struct thread_main_loop, this);
|
||||
return pthread_self() == impl->thread;
|
||||
struct thread_main_loop *impl = SPA_CONTAINER_OF(loop, struct thread_main_loop, this);
|
||||
return pthread_self() == impl->thread;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,29 +32,42 @@ extern "C" {
|
|||
* PipeWire main loop object class.
|
||||
*/
|
||||
struct pw_thread_main_loop {
|
||||
struct pw_loop *loop;
|
||||
char *name;
|
||||
struct pw_loop *loop;
|
||||
char *name;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_thread_main_loop *loop));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener,
|
||||
struct pw_thread_main_loop * loop));
|
||||
};
|
||||
|
||||
struct pw_thread_main_loop * pw_thread_main_loop_new (struct pw_loop *loop,
|
||||
const char *name);
|
||||
void pw_thread_main_loop_destroy (struct pw_thread_main_loop *loop);
|
||||
struct pw_thread_main_loop *
|
||||
pw_thread_main_loop_new(struct pw_loop *loop, const char *name);
|
||||
|
||||
int pw_thread_main_loop_start (struct pw_thread_main_loop *loop);
|
||||
void pw_thread_main_loop_stop (struct pw_thread_main_loop *loop);
|
||||
void
|
||||
pw_thread_main_loop_destroy(struct pw_thread_main_loop *loop);
|
||||
|
||||
void pw_thread_main_loop_lock (struct pw_thread_main_loop *loop);
|
||||
void pw_thread_main_loop_unlock (struct pw_thread_main_loop *loop);
|
||||
int
|
||||
pw_thread_main_loop_start(struct pw_thread_main_loop *loop);
|
||||
|
||||
void pw_thread_main_loop_wait (struct pw_thread_main_loop *loop);
|
||||
void pw_thread_main_loop_signal (struct pw_thread_main_loop *loop,
|
||||
bool wait_for_accept);
|
||||
void pw_thread_main_loop_accept (struct pw_thread_main_loop *loop);
|
||||
void
|
||||
pw_thread_main_loop_stop(struct pw_thread_main_loop *loop);
|
||||
|
||||
bool pw_thread_main_loop_in_thread (struct pw_thread_main_loop *loop);
|
||||
void
|
||||
pw_thread_main_loop_lock(struct pw_thread_main_loop *loop);
|
||||
|
||||
void
|
||||
pw_thread_main_loop_unlock(struct pw_thread_main_loop *loop);
|
||||
|
||||
void
|
||||
pw_thread_main_loop_wait(struct pw_thread_main_loop *loop);
|
||||
|
||||
void
|
||||
pw_thread_main_loop_signal(struct pw_thread_main_loop *loop, bool wait_for_accept);
|
||||
|
||||
void
|
||||
pw_thread_main_loop_accept(struct pw_thread_main_loop *loop);
|
||||
|
||||
bool
|
||||
pw_thread_main_loop_in_thread(struct pw_thread_main_loop *loop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,249 +33,227 @@
|
|||
#define CMD_PROCESS_SYNC (1<<2)
|
||||
|
||||
struct transport {
|
||||
struct pw_transport trans;
|
||||
struct pw_transport trans;
|
||||
|
||||
struct pw_memblock mem;
|
||||
size_t offset;
|
||||
struct pw_memblock mem;
|
||||
size_t offset;
|
||||
|
||||
struct spa_event current;
|
||||
uint32_t current_index;
|
||||
struct spa_event current;
|
||||
uint32_t current_index;
|
||||
};
|
||||
|
||||
static size_t
|
||||
transport_area_get_size (struct pw_transport_area *area)
|
||||
static size_t transport_area_get_size(struct pw_transport_area *area)
|
||||
{
|
||||
size_t size;
|
||||
size = sizeof (struct pw_transport_area);
|
||||
size += area->max_inputs * sizeof (struct spa_port_io);
|
||||
size += area->max_outputs * sizeof (struct spa_port_io);
|
||||
size += sizeof (struct spa_ringbuffer);
|
||||
size += INPUT_BUFFER_SIZE;
|
||||
size += sizeof (struct spa_ringbuffer);
|
||||
size += OUTPUT_BUFFER_SIZE;
|
||||
return size;
|
||||
size_t size;
|
||||
size = sizeof(struct pw_transport_area);
|
||||
size += area->max_inputs * sizeof(struct spa_port_io);
|
||||
size += area->max_outputs * sizeof(struct spa_port_io);
|
||||
size += sizeof(struct spa_ringbuffer);
|
||||
size += INPUT_BUFFER_SIZE;
|
||||
size += sizeof(struct spa_ringbuffer);
|
||||
size += OUTPUT_BUFFER_SIZE;
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
transport_setup_area (void *p, struct pw_transport *trans)
|
||||
static void transport_setup_area(void *p, struct pw_transport *trans)
|
||||
{
|
||||
struct pw_transport_area *a;
|
||||
struct pw_transport_area *a;
|
||||
|
||||
trans->area = a = p;
|
||||
p = SPA_MEMBER (p, sizeof (struct pw_transport_area), struct spa_port_io);
|
||||
trans->area = a = p;
|
||||
p = SPA_MEMBER(p, sizeof(struct pw_transport_area), struct spa_port_io);
|
||||
|
||||
trans->inputs = p;
|
||||
p = SPA_MEMBER (p, a->max_inputs * sizeof (struct spa_port_io), void);
|
||||
trans->inputs = p;
|
||||
p = SPA_MEMBER(p, a->max_inputs * sizeof(struct spa_port_io), void);
|
||||
|
||||
trans->outputs = p;
|
||||
p = SPA_MEMBER (p, a->max_outputs * sizeof (struct spa_port_io), void);
|
||||
trans->outputs = p;
|
||||
p = SPA_MEMBER(p, a->max_outputs * sizeof(struct spa_port_io), void);
|
||||
|
||||
trans->input_buffer = p;
|
||||
p = SPA_MEMBER (p, sizeof (struct spa_ringbuffer), void);
|
||||
trans->input_buffer = p;
|
||||
p = SPA_MEMBER(p, sizeof(struct spa_ringbuffer), void);
|
||||
|
||||
trans->input_data = p;
|
||||
p = SPA_MEMBER (p, INPUT_BUFFER_SIZE, void);
|
||||
trans->input_data = p;
|
||||
p = SPA_MEMBER(p, INPUT_BUFFER_SIZE, void);
|
||||
|
||||
trans->output_buffer = p;
|
||||
p = SPA_MEMBER (p, sizeof (struct spa_ringbuffer), void);
|
||||
trans->output_buffer = p;
|
||||
p = SPA_MEMBER(p, sizeof(struct spa_ringbuffer), void);
|
||||
|
||||
trans->output_data = p;
|
||||
p = SPA_MEMBER (p, OUTPUT_BUFFER_SIZE, void);
|
||||
trans->output_data = p;
|
||||
p = SPA_MEMBER(p, OUTPUT_BUFFER_SIZE, void);
|
||||
}
|
||||
|
||||
static void
|
||||
transport_reset_area (struct pw_transport *trans)
|
||||
static void transport_reset_area(struct pw_transport *trans)
|
||||
{
|
||||
int i;
|
||||
struct pw_transport_area *a = trans->area;
|
||||
int i;
|
||||
struct pw_transport_area *a = trans->area;
|
||||
|
||||
for (i = 0; i < a->max_inputs; i++) {
|
||||
trans->inputs[i].status = SPA_RESULT_OK;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
for (i = 0; i < a->max_outputs; i++) {
|
||||
trans->outputs[i].status = SPA_RESULT_OK;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
spa_ringbuffer_init (trans->input_buffer, INPUT_BUFFER_SIZE);
|
||||
spa_ringbuffer_init (trans->output_buffer, OUTPUT_BUFFER_SIZE);
|
||||
for (i = 0; i < a->max_inputs; i++) {
|
||||
trans->inputs[i].status = SPA_RESULT_OK;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
for (i = 0; i < a->max_outputs; i++) {
|
||||
trans->outputs[i].status = SPA_RESULT_OK;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
spa_ringbuffer_init(trans->input_buffer, INPUT_BUFFER_SIZE);
|
||||
spa_ringbuffer_init(trans->output_buffer, OUTPUT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
struct pw_transport *
|
||||
pw_transport_new (uint32_t max_inputs,
|
||||
uint32_t max_outputs)
|
||||
struct pw_transport *pw_transport_new(uint32_t max_inputs, uint32_t max_outputs)
|
||||
{
|
||||
struct transport *impl;
|
||||
struct pw_transport *trans;
|
||||
struct pw_transport_area area;
|
||||
struct transport *impl;
|
||||
struct pw_transport *trans;
|
||||
struct pw_transport_area area;
|
||||
|
||||
area.max_inputs = max_inputs;
|
||||
area.n_inputs = 0;
|
||||
area.max_outputs = max_outputs;
|
||||
area.n_outputs = 0;
|
||||
area.max_inputs = max_inputs;
|
||||
area.n_inputs = 0;
|
||||
area.max_outputs = max_outputs;
|
||||
area.n_outputs = 0;
|
||||
|
||||
impl = calloc (1, sizeof (struct transport));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct transport));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
impl->offset = 0;
|
||||
impl->offset = 0;
|
||||
|
||||
trans = &impl->trans;
|
||||
pw_signal_init (&trans->destroy_signal);
|
||||
trans = &impl->trans;
|
||||
pw_signal_init(&trans->destroy_signal);
|
||||
|
||||
pw_memblock_alloc (PW_MEMBLOCK_FLAG_WITH_FD |
|
||||
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL,
|
||||
transport_area_get_size (&area),
|
||||
&impl->mem);
|
||||
pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
|
||||
PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL, transport_area_get_size(&area), &impl->mem);
|
||||
|
||||
memcpy (impl->mem.ptr, &area, sizeof (struct pw_transport_area));
|
||||
transport_setup_area (impl->mem.ptr, trans);
|
||||
transport_reset_area (trans);
|
||||
memcpy(impl->mem.ptr, &area, sizeof(struct pw_transport_area));
|
||||
transport_setup_area(impl->mem.ptr, trans);
|
||||
transport_reset_area(trans);
|
||||
|
||||
return trans;
|
||||
return trans;
|
||||
}
|
||||
|
||||
struct pw_transport *
|
||||
pw_transport_new_from_info (struct pw_transport_info *info)
|
||||
struct pw_transport *pw_transport_new_from_info(struct pw_transport_info *info)
|
||||
{
|
||||
struct transport *impl;
|
||||
struct pw_transport *trans;
|
||||
void *tmp;
|
||||
struct transport *impl;
|
||||
struct pw_transport *trans;
|
||||
void *tmp;
|
||||
|
||||
impl = calloc (1, sizeof (struct transport));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct transport));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
trans = &impl->trans;
|
||||
pw_signal_init (&trans->destroy_signal);
|
||||
trans = &impl->trans;
|
||||
pw_signal_init(&trans->destroy_signal);
|
||||
|
||||
impl->mem.flags = PW_MEMBLOCK_FLAG_MAP_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_WITH_FD;
|
||||
impl->mem.fd = info->memfd;
|
||||
impl->mem.offset = info->offset;
|
||||
impl->mem.size = info->size;
|
||||
if (pw_memblock_map (&impl->mem) != SPA_RESULT_OK) {
|
||||
pw_log_warn ("transport %p: failed to map fd %d: %s", impl, info->memfd, strerror (errno));
|
||||
goto mmap_failed;
|
||||
}
|
||||
impl->mem.flags = PW_MEMBLOCK_FLAG_MAP_READWRITE | PW_MEMBLOCK_FLAG_WITH_FD;
|
||||
impl->mem.fd = info->memfd;
|
||||
impl->mem.offset = info->offset;
|
||||
impl->mem.size = info->size;
|
||||
if (pw_memblock_map(&impl->mem) != SPA_RESULT_OK) {
|
||||
pw_log_warn("transport %p: failed to map fd %d: %s", impl, info->memfd,
|
||||
strerror(errno));
|
||||
goto mmap_failed;
|
||||
}
|
||||
|
||||
impl->offset = info->offset;
|
||||
impl->offset = info->offset;
|
||||
|
||||
transport_setup_area (impl->mem.ptr, trans);
|
||||
transport_setup_area(impl->mem.ptr, trans);
|
||||
|
||||
tmp = trans->output_buffer;
|
||||
trans->output_buffer = trans->input_buffer;
|
||||
trans->input_buffer = tmp;
|
||||
tmp = trans->output_buffer;
|
||||
trans->output_buffer = trans->input_buffer;
|
||||
trans->input_buffer = tmp;
|
||||
|
||||
tmp = trans->output_data;
|
||||
trans->output_data = trans->input_data;
|
||||
trans->input_data = tmp;
|
||||
tmp = trans->output_data;
|
||||
trans->output_data = trans->input_data;
|
||||
trans->input_data = tmp;
|
||||
|
||||
return trans;
|
||||
return trans;
|
||||
|
||||
mmap_failed:
|
||||
free (impl);
|
||||
return NULL;
|
||||
mmap_failed:
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pw_transport_destroy (struct pw_transport *trans)
|
||||
void pw_transport_destroy(struct pw_transport *trans)
|
||||
{
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
|
||||
pw_log_debug ("transport %p: destroy", trans);
|
||||
pw_log_debug("transport %p: destroy", trans);
|
||||
|
||||
pw_signal_emit (&trans->destroy_signal, trans);
|
||||
pw_signal_emit(&trans->destroy_signal, trans);
|
||||
|
||||
pw_memblock_free (&impl->mem);
|
||||
free (impl);
|
||||
pw_memblock_free(&impl->mem);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
int
|
||||
pw_transport_get_info (struct pw_transport *trans,
|
||||
struct pw_transport_info *info)
|
||||
int pw_transport_get_info(struct pw_transport *trans, struct pw_transport_info *info)
|
||||
{
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
|
||||
info->memfd = impl->mem.fd;
|
||||
info->offset = impl->offset;
|
||||
info->size = impl->mem.size;
|
||||
info->memfd = impl->mem.fd;
|
||||
info->offset = impl->offset;
|
||||
info->size = impl->mem.size;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pw_transport_add_event (struct pw_transport *trans,
|
||||
struct spa_event *event)
|
||||
int pw_transport_add_event(struct pw_transport *trans, struct spa_event *event)
|
||||
{
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
int32_t filled, avail;
|
||||
uint32_t size, index;
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
int32_t filled, avail;
|
||||
uint32_t size, index;
|
||||
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
filled = spa_ringbuffer_get_write_index (trans->output_buffer, &index);
|
||||
avail = trans->output_buffer->size - filled;
|
||||
size = SPA_POD_SIZE (event);
|
||||
if (avail < size)
|
||||
return SPA_RESULT_ERROR;
|
||||
filled = spa_ringbuffer_get_write_index(trans->output_buffer, &index);
|
||||
avail = trans->output_buffer->size - filled;
|
||||
size = SPA_POD_SIZE(event);
|
||||
if (avail < size)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
||||
spa_ringbuffer_write_data (trans->output_buffer,
|
||||
trans->output_data,
|
||||
index & trans->output_buffer->mask,
|
||||
event,
|
||||
size);
|
||||
spa_ringbuffer_write_update (trans->output_buffer, index + size);
|
||||
spa_ringbuffer_write_data(trans->output_buffer,
|
||||
trans->output_data,
|
||||
index & trans->output_buffer->mask, event, size);
|
||||
spa_ringbuffer_write_update(trans->output_buffer, index + size);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pw_transport_next_event (struct pw_transport *trans,
|
||||
struct spa_event *event)
|
||||
int pw_transport_next_event(struct pw_transport *trans, struct spa_event *event)
|
||||
{
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
int32_t avail;
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
int32_t avail;
|
||||
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
avail = spa_ringbuffer_get_read_index (trans->input_buffer, &impl->current_index);
|
||||
if (avail < sizeof (struct spa_event))
|
||||
return SPA_RESULT_ENUM_END;
|
||||
avail = spa_ringbuffer_get_read_index(trans->input_buffer, &impl->current_index);
|
||||
if (avail < sizeof(struct spa_event))
|
||||
return SPA_RESULT_ENUM_END;
|
||||
|
||||
spa_ringbuffer_read_data (trans->input_buffer,
|
||||
trans->input_data,
|
||||
impl->current_index & trans->input_buffer->mask,
|
||||
&impl->current,
|
||||
sizeof (struct spa_event));
|
||||
spa_ringbuffer_read_data(trans->input_buffer,
|
||||
trans->input_data,
|
||||
impl->current_index & trans->input_buffer->mask,
|
||||
&impl->current, sizeof(struct spa_event));
|
||||
|
||||
*event = impl->current;
|
||||
*event = impl->current;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pw_transport_parse_event (struct pw_transport *trans,
|
||||
void *event)
|
||||
int pw_transport_parse_event(struct pw_transport *trans, void *event)
|
||||
{
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
uint32_t size;
|
||||
struct transport *impl = (struct transport *) trans;
|
||||
uint32_t size;
|
||||
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
if (impl == NULL || event == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
size = SPA_POD_SIZE (&impl->current);
|
||||
size = SPA_POD_SIZE(&impl->current);
|
||||
|
||||
spa_ringbuffer_read_data (trans->input_buffer,
|
||||
trans->input_data,
|
||||
impl->current_index & trans->input_buffer->mask,
|
||||
event,
|
||||
size);
|
||||
spa_ringbuffer_read_update (trans->input_buffer, impl->current_index + size);
|
||||
spa_ringbuffer_read_data(trans->input_buffer,
|
||||
trans->input_data,
|
||||
impl->current_index & trans->input_buffer->mask, event, size);
|
||||
spa_ringbuffer_read_update(trans->input_buffer, impl->current_index + size);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ extern "C" {
|
|||
#include <pipewire/client/sig.h>
|
||||
|
||||
struct pw_transport_info {
|
||||
int memfd;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
int memfd;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -44,41 +44,44 @@ struct pw_transport_info {
|
|||
* Shared structure between client and server
|
||||
*/
|
||||
struct pw_transport_area {
|
||||
uint32_t max_inputs;
|
||||
uint32_t n_inputs;
|
||||
uint32_t max_outputs;
|
||||
uint32_t n_outputs;
|
||||
uint32_t max_inputs;
|
||||
uint32_t n_inputs;
|
||||
uint32_t max_outputs;
|
||||
uint32_t n_outputs;
|
||||
};
|
||||
|
||||
struct pw_transport {
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_transport *trans));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_transport * trans));
|
||||
|
||||
struct pw_transport_area *area;
|
||||
struct spa_port_io *inputs;
|
||||
struct spa_port_io *outputs;
|
||||
void *input_data;
|
||||
struct spa_ringbuffer *input_buffer;
|
||||
void *output_data;
|
||||
struct spa_ringbuffer *output_buffer;
|
||||
struct pw_transport_area *area;
|
||||
struct spa_port_io *inputs;
|
||||
struct spa_port_io *outputs;
|
||||
void *input_data;
|
||||
struct spa_ringbuffer *input_buffer;
|
||||
void *output_data;
|
||||
struct spa_ringbuffer *output_buffer;
|
||||
};
|
||||
|
||||
struct pw_transport * pw_transport_new (uint32_t max_inputs,
|
||||
uint32_t max_outputs);
|
||||
struct pw_transport * pw_transport_new_from_info (struct pw_transport_info *info);
|
||||
struct pw_transport *
|
||||
pw_transport_new(uint32_t max_inputs, uint32_t max_outputs);
|
||||
|
||||
void pw_transport_destroy (struct pw_transport *trans);
|
||||
struct pw_transport *
|
||||
pw_transport_new_from_info(struct pw_transport_info *info);
|
||||
|
||||
int pw_transport_get_info (struct pw_transport *trans,
|
||||
struct pw_transport_info *info);
|
||||
void
|
||||
pw_transport_destroy(struct pw_transport *trans);
|
||||
|
||||
int pw_transport_add_event (struct pw_transport *trans,
|
||||
struct spa_event *event);
|
||||
int
|
||||
pw_transport_get_info(struct pw_transport *trans, struct pw_transport_info *info);
|
||||
|
||||
int pw_transport_next_event (struct pw_transport *trans,
|
||||
struct spa_event *event);
|
||||
int pw_transport_parse_event (struct pw_transport *trans,
|
||||
void *event);
|
||||
int
|
||||
pw_transport_add_event(struct pw_transport *trans, struct spa_event *event);
|
||||
|
||||
int
|
||||
pw_transport_next_event(struct pw_transport *trans, struct spa_event *event);
|
||||
|
||||
int
|
||||
pw_transport_parse_event(struct pw_transport *trans, void *event);
|
||||
|
||||
#define PIPEWIRE_TYPE_EVENT__Transport SPA_TYPE_EVENT_BASE "Transport"
|
||||
#define PIPEWIRE_TYPE_EVENT_TRANSPORT_BASE PIPEWIRE_TYPE_EVENT__Transport ":"
|
||||
|
|
@ -88,41 +91,41 @@ int pw_transport_parse_event (struct pw_transport *trans,
|
|||
#define PIPEWIRE_TYPE_EVENT_TRANSPORT__ReuseBuffer PIPEWIRE_TYPE_EVENT_TRANSPORT_BASE "ReuseBuffer"
|
||||
|
||||
struct pw_type_event_transport {
|
||||
uint32_t HaveOutput;
|
||||
uint32_t NeedInput;
|
||||
uint32_t ReuseBuffer;
|
||||
uint32_t HaveOutput;
|
||||
uint32_t NeedInput;
|
||||
uint32_t ReuseBuffer;
|
||||
};
|
||||
|
||||
static inline void
|
||||
pw_type_event_transport_map (struct spa_type_map *map, struct pw_type_event_transport *type)
|
||||
pw_type_event_transport_map(struct spa_type_map *map, struct pw_type_event_transport *type)
|
||||
{
|
||||
if (type->HaveOutput == 0) {
|
||||
type->HaveOutput = spa_type_map_get_id (map, PIPEWIRE_TYPE_EVENT_TRANSPORT__HaveOutput);
|
||||
type->NeedInput = spa_type_map_get_id (map, PIPEWIRE_TYPE_EVENT_TRANSPORT__NeedInput);
|
||||
type->ReuseBuffer = spa_type_map_get_id (map, PIPEWIRE_TYPE_EVENT_TRANSPORT__ReuseBuffer);
|
||||
}
|
||||
if (type->HaveOutput == 0) {
|
||||
type->HaveOutput = spa_type_map_get_id(map, PIPEWIRE_TYPE_EVENT_TRANSPORT__HaveOutput);
|
||||
type->NeedInput = spa_type_map_get_id(map, PIPEWIRE_TYPE_EVENT_TRANSPORT__NeedInput);
|
||||
type->ReuseBuffer = spa_type_map_get_id(map, PIPEWIRE_TYPE_EVENT_TRANSPORT__ReuseBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
struct pw_event_transport_reuse_buffer_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_int port_id;
|
||||
struct spa_pod_int buffer_id;
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_int port_id;
|
||||
struct spa_pod_int buffer_id;
|
||||
};
|
||||
|
||||
struct pw_event_transport_reuse_buffer {
|
||||
struct spa_pod pod;
|
||||
struct pw_event_transport_reuse_buffer_body body;
|
||||
struct spa_pod pod;
|
||||
struct pw_event_transport_reuse_buffer_body body;
|
||||
};
|
||||
|
||||
#define PW_EVENT_TRANSPORT_REUSE_BUFFER_INIT(type,port_id,buffer_id) \
|
||||
SPA_EVENT_INIT_COMPLEX (struct pw_event_transport_reuse_buffer, \
|
||||
sizeof (struct pw_event_transport_reuse_buffer_body), type, \
|
||||
SPA_POD_INT_INIT (port_id), \
|
||||
SPA_POD_INT_INIT (buffer_id))
|
||||
#define PW_EVENT_TRANSPORT_REUSE_BUFFER_INIT(type,port_id,buffer_id) \
|
||||
SPA_EVENT_INIT_COMPLEX(struct pw_event_transport_reuse_buffer, \
|
||||
sizeof(struct pw_event_transport_reuse_buffer_body), type, \
|
||||
SPA_POD_INT_INIT(port_id), \
|
||||
SPA_POD_INT_INIT(buffer_id))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_TRANSPORT_H__ */
|
||||
|
|
|
|||
|
|
@ -31,93 +31,92 @@
|
|||
|
||||
#include "spa/monitor.h"
|
||||
|
||||
void
|
||||
pw_type_init (struct pw_type *type)
|
||||
void pw_type_init(struct pw_type *type)
|
||||
{
|
||||
type->map = pw_type_map_get_default();
|
||||
type->map = pw_type_map_get_default();
|
||||
|
||||
type->core = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Core);
|
||||
type->registry = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Registry);
|
||||
type->node = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Node);
|
||||
type->node_factory = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__NodeFactory);
|
||||
type->link = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Link);
|
||||
type->client = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Client);
|
||||
type->client_node = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__ClientNode);
|
||||
type->module = spa_type_map_get_id (type->map, PIPEWIRE_TYPE__Module);
|
||||
type->core = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Core);
|
||||
type->registry = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Registry);
|
||||
type->node = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Node);
|
||||
type->node_factory = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__NodeFactory);
|
||||
type->link = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Link);
|
||||
type->client = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Client);
|
||||
type->client_node = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__ClientNode);
|
||||
type->module = spa_type_map_get_id(type->map, PIPEWIRE_TYPE__Module);
|
||||
|
||||
type->spa_node = spa_type_map_get_id (type->map, SPA_TYPE__Node);
|
||||
type->spa_clock = spa_type_map_get_id (type->map, SPA_TYPE__Clock);
|
||||
type->spa_monitor = spa_type_map_get_id (type->map, SPA_TYPE__Monitor);
|
||||
type->spa_format = spa_type_map_get_id (type->map, SPA_TYPE__Format);
|
||||
type->spa_props = spa_type_map_get_id (type->map, SPA_TYPE__Props);
|
||||
type->spa_node = spa_type_map_get_id(type->map, SPA_TYPE__Node);
|
||||
type->spa_clock = spa_type_map_get_id(type->map, SPA_TYPE__Clock);
|
||||
type->spa_monitor = spa_type_map_get_id(type->map, SPA_TYPE__Monitor);
|
||||
type->spa_format = spa_type_map_get_id(type->map, SPA_TYPE__Format);
|
||||
type->spa_props = spa_type_map_get_id(type->map, SPA_TYPE__Props);
|
||||
|
||||
spa_type_meta_map (type->map, &type->meta);
|
||||
spa_type_data_map (type->map, &type->data);
|
||||
spa_type_event_node_map (type->map, &type->event_node);
|
||||
spa_type_command_node_map (type->map, &type->command_node);
|
||||
spa_type_monitor_map (type->map, &type->monitor);
|
||||
spa_type_param_alloc_buffers_map (type->map, &type->param_alloc_buffers);
|
||||
spa_type_param_alloc_meta_enable_map (type->map, &type->param_alloc_meta_enable);
|
||||
spa_type_param_alloc_video_padding_map (type->map, &type->param_alloc_video_padding);
|
||||
spa_type_meta_map(type->map, &type->meta);
|
||||
spa_type_data_map(type->map, &type->data);
|
||||
spa_type_event_node_map(type->map, &type->event_node);
|
||||
spa_type_command_node_map(type->map, &type->command_node);
|
||||
spa_type_monitor_map(type->map, &type->monitor);
|
||||
spa_type_param_alloc_buffers_map(type->map, &type->param_alloc_buffers);
|
||||
spa_type_param_alloc_meta_enable_map(type->map, &type->param_alloc_meta_enable);
|
||||
spa_type_param_alloc_video_padding_map(type->map, &type->param_alloc_video_padding);
|
||||
|
||||
pw_type_event_transport_map (type->map, &type->event_transport);
|
||||
pw_type_event_transport_map(type->map, &type->event_transport);
|
||||
}
|
||||
|
||||
bool
|
||||
pw_pod_remap_data (uint32_t type, void * body, uint32_t size, struct pw_map *types)
|
||||
bool pw_pod_remap_data(uint32_t type, void *body, uint32_t size, struct pw_map *types)
|
||||
{
|
||||
void *t;
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_ID:
|
||||
if ((t = pw_map_lookup (types, *(int32_t*)body)) == NULL)
|
||||
return false;
|
||||
*(int32_t*)body = PW_MAP_PTR_TO_ID (t);
|
||||
break;
|
||||
void *t;
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_ID:
|
||||
if ((t = pw_map_lookup(types, *(int32_t *) body)) == NULL)
|
||||
return false;
|
||||
*(int32_t *) body = PW_MAP_PTR_TO_ID(t);
|
||||
break;
|
||||
|
||||
case SPA_POD_TYPE_PROP:
|
||||
{
|
||||
struct spa_pod_prop_body *b = body;
|
||||
case SPA_POD_TYPE_PROP:
|
||||
{
|
||||
struct spa_pod_prop_body *b = body;
|
||||
|
||||
if ((t = pw_map_lookup (types, b->key)) == NULL)
|
||||
return false;
|
||||
b->key = PW_MAP_PTR_TO_ID (t);
|
||||
if ((t = pw_map_lookup(types, b->key)) == NULL)
|
||||
return false;
|
||||
b->key = PW_MAP_PTR_TO_ID(t);
|
||||
|
||||
if (b->value.type == SPA_POD_TYPE_ID) {
|
||||
void *alt;
|
||||
if (!pw_pod_remap_data (b->value.type, SPA_POD_BODY (&b->value), b->value.size, types))
|
||||
return false;
|
||||
if (b->value.type == SPA_POD_TYPE_ID) {
|
||||
void *alt;
|
||||
if (!pw_pod_remap_data
|
||||
(b->value.type, SPA_POD_BODY(&b->value), b->value.size, types))
|
||||
return false;
|
||||
|
||||
SPA_POD_PROP_ALTERNATIVE_FOREACH (b, size, alt)
|
||||
if (!pw_pod_remap_data (b->value.type, alt, b->value.size, types))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_OBJECT:
|
||||
{
|
||||
struct spa_pod_object_body *b = body;
|
||||
struct spa_pod *p;
|
||||
SPA_POD_PROP_ALTERNATIVE_FOREACH(b, size, alt)
|
||||
if (!pw_pod_remap_data(b->value.type, alt, b->value.size, types))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_OBJECT:
|
||||
{
|
||||
struct spa_pod_object_body *b = body;
|
||||
struct spa_pod *p;
|
||||
|
||||
if ((t = pw_map_lookup (types, b->type)) == NULL)
|
||||
return false;
|
||||
b->type = PW_MAP_PTR_TO_ID (t);
|
||||
if ((t = pw_map_lookup(types, b->type)) == NULL)
|
||||
return false;
|
||||
b->type = PW_MAP_PTR_TO_ID(t);
|
||||
|
||||
SPA_POD_OBJECT_BODY_FOREACH (b, size, p)
|
||||
if (!pw_pod_remap_data (p->type, SPA_POD_BODY (p), p->size, types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_STRUCT:
|
||||
{
|
||||
struct spa_pod *b = body, *p;
|
||||
SPA_POD_OBJECT_BODY_FOREACH(b, size, p)
|
||||
if (!pw_pod_remap_data(p->type, SPA_POD_BODY(p), p->size, types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_STRUCT:
|
||||
{
|
||||
struct spa_pod *b = body, *p;
|
||||
|
||||
SPA_POD_FOREACH (b, size, p)
|
||||
if (!pw_pod_remap_data (p->type, SPA_POD_BODY (p), p->size, types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
SPA_POD_FOREACH(b, size, p)
|
||||
if (!pw_pod_remap_data(p->type, SPA_POD_BODY(p), p->size, types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ extern "C" {
|
|||
#include <pipewire/client/transport.h>
|
||||
|
||||
struct pw_interface {
|
||||
uint32_t n_methods;
|
||||
const void *methods;
|
||||
uint32_t n_events;
|
||||
const void *events;
|
||||
uint32_t n_methods;
|
||||
const void *methods;
|
||||
uint32_t n_events;
|
||||
const void *events;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -46,42 +46,44 @@ struct pw_interface {
|
|||
* PipeWire Type support struct.
|
||||
*/
|
||||
struct pw_type {
|
||||
struct spa_type_map *map;
|
||||
struct spa_type_map *map;
|
||||
|
||||
uint32_t core;
|
||||
uint32_t registry;
|
||||
uint32_t node;
|
||||
uint32_t node_factory;
|
||||
uint32_t link;
|
||||
uint32_t client;
|
||||
uint32_t client_node;
|
||||
uint32_t module;
|
||||
uint32_t core;
|
||||
uint32_t registry;
|
||||
uint32_t node;
|
||||
uint32_t node_factory;
|
||||
uint32_t link;
|
||||
uint32_t client;
|
||||
uint32_t client_node;
|
||||
uint32_t module;
|
||||
|
||||
uint32_t spa_node;
|
||||
uint32_t spa_clock;
|
||||
uint32_t spa_monitor;
|
||||
uint32_t spa_format;
|
||||
uint32_t spa_props;
|
||||
uint32_t spa_node;
|
||||
uint32_t spa_clock;
|
||||
uint32_t spa_monitor;
|
||||
uint32_t spa_format;
|
||||
uint32_t spa_props;
|
||||
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_event_node event_node;
|
||||
struct spa_type_command_node command_node;
|
||||
struct spa_type_monitor monitor;
|
||||
struct spa_type_param_alloc_buffers param_alloc_buffers;
|
||||
struct spa_type_param_alloc_meta_enable param_alloc_meta_enable;
|
||||
struct spa_type_param_alloc_video_padding param_alloc_video_padding;
|
||||
struct pw_type_event_transport event_transport;
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_event_node event_node;
|
||||
struct spa_type_command_node command_node;
|
||||
struct spa_type_monitor monitor;
|
||||
struct spa_type_param_alloc_buffers param_alloc_buffers;
|
||||
struct spa_type_param_alloc_meta_enable param_alloc_meta_enable;
|
||||
struct spa_type_param_alloc_video_padding param_alloc_video_padding;
|
||||
struct pw_type_event_transport event_transport;
|
||||
};
|
||||
|
||||
void pw_type_init (struct pw_type *type);
|
||||
void
|
||||
pw_type_init(struct pw_type *type);
|
||||
|
||||
bool pw_pod_remap_data (uint32_t type, void *body, uint32_t size, struct pw_map *types);
|
||||
bool
|
||||
pw_pod_remap_data(uint32_t type, void *body, uint32_t size, struct pw_map *types);
|
||||
|
||||
static inline bool
|
||||
pw_pod_remap (struct spa_pod *pod, struct pw_map *types)
|
||||
pw_pod_remap(struct spa_pod *pod, struct pw_map *types)
|
||||
{
|
||||
return pw_pod_remap_data (pod->type, SPA_POD_BODY (pod), pod->size, types);
|
||||
return pw_pod_remap_data(pod->type, SPA_POD_BODY(pod), pod->size, types);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -23,81 +23,70 @@
|
|||
#include <pipewire/client/log.h>
|
||||
#include <pipewire/client/utils.h>
|
||||
|
||||
const char *
|
||||
pw_split_walk (const char *str,
|
||||
const char *delimiter,
|
||||
size_t *len,
|
||||
const char **state)
|
||||
const char *pw_split_walk(const char *str, const char *delimiter, size_t * len, const char **state)
|
||||
{
|
||||
const char *s = *state ? *state : str;
|
||||
const char *s = *state ? *state : str;
|
||||
|
||||
if (*s == '\0')
|
||||
return NULL;
|
||||
if (*s == '\0')
|
||||
return NULL;
|
||||
|
||||
*len = strcspn (s, delimiter);
|
||||
*len = strcspn(s, delimiter);
|
||||
|
||||
*state = s + *len;
|
||||
*state += strspn (*state, delimiter);
|
||||
*state = s + *len;
|
||||
*state += strspn(*state, delimiter);
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
char **
|
||||
pw_split_strv (const char *str,
|
||||
const char *delimiter,
|
||||
int max_tokens,
|
||||
int *n_tokens)
|
||||
char **pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens)
|
||||
{
|
||||
const char *state = NULL, *s = NULL;
|
||||
struct pw_array arr;
|
||||
size_t len;
|
||||
int n = 0;
|
||||
const char *state = NULL, *s = NULL;
|
||||
struct pw_array arr;
|
||||
size_t len;
|
||||
int n = 0;
|
||||
|
||||
pw_array_init (&arr, 16);
|
||||
pw_array_init(&arr, 16);
|
||||
|
||||
s = pw_split_walk (str, delimiter, &len, &state);
|
||||
while (s && n + 1 < max_tokens) {
|
||||
pw_array_add_ptr (&arr, strndup (s, len));
|
||||
s = pw_split_walk (str, delimiter, &len, &state);
|
||||
n++;
|
||||
}
|
||||
if (s) {
|
||||
pw_array_add_ptr (&arr, strdup (s));
|
||||
n++;
|
||||
}
|
||||
pw_array_add_ptr (&arr, NULL);
|
||||
s = pw_split_walk(str, delimiter, &len, &state);
|
||||
while (s && n + 1 < max_tokens) {
|
||||
pw_array_add_ptr(&arr, strndup(s, len));
|
||||
s = pw_split_walk(str, delimiter, &len, &state);
|
||||
n++;
|
||||
}
|
||||
if (s) {
|
||||
pw_array_add_ptr(&arr, strdup(s));
|
||||
n++;
|
||||
}
|
||||
pw_array_add_ptr(&arr, NULL);
|
||||
|
||||
*n_tokens = n;
|
||||
*n_tokens = n;
|
||||
|
||||
return arr.data;
|
||||
return arr.data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pw_free_strv (char **str)
|
||||
void pw_free_strv(char **str)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; str[i]; i++)
|
||||
free (str[i]);
|
||||
free (str);
|
||||
int i;
|
||||
for (i = 0; str[i]; i++)
|
||||
free(str[i]);
|
||||
free(str);
|
||||
}
|
||||
|
||||
char *
|
||||
pw_strip (char *str,
|
||||
const char *whitespace)
|
||||
char *pw_strip(char *str, const char *whitespace)
|
||||
{
|
||||
char *e, *l = NULL;
|
||||
char *e, *l = NULL;
|
||||
|
||||
str += strspn (str, whitespace);
|
||||
str += strspn(str, whitespace);
|
||||
|
||||
for (e = str; *e; e++)
|
||||
if (!strchr (whitespace, *e))
|
||||
l = e;
|
||||
for (e = str; *e; e++)
|
||||
if (!strchr(whitespace, *e))
|
||||
l = e;
|
||||
|
||||
if (l)
|
||||
*(l+1) = '\0';
|
||||
else
|
||||
*str = '\0';
|
||||
if (l)
|
||||
*(l + 1) = '\0';
|
||||
else
|
||||
*str = '\0';
|
||||
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,23 +27,22 @@ extern "C" {
|
|||
#include <spa/defs.h>
|
||||
#include <spa/pod-utils.h>
|
||||
|
||||
const char * pw_split_walk (const char *str,
|
||||
const char *delimiter,
|
||||
size_t *len,
|
||||
const char **state);
|
||||
char ** pw_split_strv (const char *str,
|
||||
const char *delimiter,
|
||||
int max_tokens,
|
||||
int *n_tokens);
|
||||
void pw_free_strv (char **str);
|
||||
const char *
|
||||
pw_split_walk(const char *str, const char *delimiter, size_t * len, const char **state);
|
||||
|
||||
char * pw_strip (char *str,
|
||||
const char *whitespace);
|
||||
char **
|
||||
pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens);
|
||||
|
||||
void
|
||||
pw_free_strv(char **str);
|
||||
|
||||
char *
|
||||
pw_strip(char *str, const char *whitespace);
|
||||
|
||||
static inline struct spa_pod *
|
||||
pw_spa_pod_copy (const struct spa_pod *pod)
|
||||
pw_spa_pod_copy(const struct spa_pod *pod)
|
||||
{
|
||||
return pod ? memcpy (malloc (SPA_POD_SIZE (pod)), pod, SPA_POD_SIZE (pod)) : NULL;
|
||||
return pod ? memcpy(malloc(SPA_POD_SIZE(pod)), pod, SPA_POD_SIZE(pod)) : NULL;
|
||||
}
|
||||
|
||||
#define spa_format_copy(f) ((struct spa_format*)pw_spa_pod_copy(&(f)->pod))
|
||||
|
|
@ -51,7 +50,7 @@ pw_spa_pod_copy (const struct spa_pod *pod)
|
|||
#define spa_param_copy(p) ((struct spa_param*)pw_spa_pod_copy(&(p)->object.pod))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -33,36 +33,33 @@
|
|||
#define DEFAULT_CONFIG_FILE PIPEWIRE_CONFIG_DIR "/pipewire.conf"
|
||||
|
||||
static bool
|
||||
parse_line (struct pw_daemon_config *config,
|
||||
const char *filename,
|
||||
char *line,
|
||||
unsigned int lineno,
|
||||
char **err)
|
||||
parse_line(struct pw_daemon_config *config,
|
||||
const char *filename, char *line, unsigned int lineno, char **err)
|
||||
{
|
||||
struct pw_command *command = NULL;
|
||||
char *p;
|
||||
bool ret = true;
|
||||
char *local_err = NULL;
|
||||
struct pw_command *command = NULL;
|
||||
char *p;
|
||||
bool ret = true;
|
||||
char *local_err = NULL;
|
||||
|
||||
/* search for comments */
|
||||
if ((p = strchr (line, '#')))
|
||||
*p = '\0';
|
||||
/* search for comments */
|
||||
if ((p = strchr(line, '#')))
|
||||
*p = '\0';
|
||||
|
||||
/* remove whitespaces */
|
||||
pw_strip (line, "\n\r \t");
|
||||
/* remove whitespaces */
|
||||
pw_strip(line, "\n\r \t");
|
||||
|
||||
if (*line == '\0') /* empty line */
|
||||
return true;
|
||||
if (*line == '\0') /* empty line */
|
||||
return true;
|
||||
|
||||
if ((command = pw_command_parse (line, &local_err)) == NULL) {
|
||||
asprintf (err, "%s:%u: %s", filename, lineno, local_err);
|
||||
free (local_err);
|
||||
ret = false;
|
||||
} else {
|
||||
spa_list_insert (config->commands.prev, &command->link);
|
||||
}
|
||||
if ((command = pw_command_parse(line, &local_err)) == NULL) {
|
||||
asprintf(err, "%s:%u: %s", filename, lineno, local_err);
|
||||
free(local_err);
|
||||
ret = false;
|
||||
} else {
|
||||
spa_list_insert(config->commands.prev, &command->link);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,15 +67,14 @@ parse_line (struct pw_daemon_config *config,
|
|||
*
|
||||
* Returns a new empty #struct pw_daemon_config.
|
||||
*/
|
||||
struct pw_daemon_config *
|
||||
pw_daemon_config_new (void)
|
||||
struct pw_daemon_config *pw_daemon_config_new(void)
|
||||
{
|
||||
struct pw_daemon_config *config;
|
||||
struct pw_daemon_config *config;
|
||||
|
||||
config = calloc (1, sizeof (struct pw_daemon_config));
|
||||
spa_list_init (&config->commands);
|
||||
config = calloc(1, sizeof(struct pw_daemon_config));
|
||||
spa_list_init(&config->commands);
|
||||
|
||||
return config;
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,15 +83,14 @@ pw_daemon_config_new (void)
|
|||
*
|
||||
* Free all resources associated to @config.
|
||||
*/
|
||||
void
|
||||
pw_daemon_config_free (struct pw_daemon_config * config)
|
||||
void pw_daemon_config_free(struct pw_daemon_config *config)
|
||||
{
|
||||
struct pw_command *cmd, *tmp;
|
||||
struct pw_command *cmd, *tmp;
|
||||
|
||||
spa_list_for_each_safe (cmd, tmp, &config->commands, link)
|
||||
pw_command_free (cmd);
|
||||
spa_list_for_each_safe(cmd, tmp, &config->commands, link)
|
||||
pw_command_free(cmd);
|
||||
|
||||
free (config);
|
||||
free(config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -108,47 +103,46 @@ pw_daemon_config_free (struct pw_daemon_config * config)
|
|||
*
|
||||
* Returns: %true on success, otherwise %false and @err is set.
|
||||
*/
|
||||
bool
|
||||
pw_daemon_config_load_file (struct pw_daemon_config *config,
|
||||
const char *filename,
|
||||
char **err)
|
||||
bool pw_daemon_config_load_file(struct pw_daemon_config *config, const char *filename, char **err)
|
||||
{
|
||||
unsigned int line;
|
||||
FILE *f;
|
||||
char buf[4096];
|
||||
unsigned int line;
|
||||
FILE *f;
|
||||
char buf[4096];
|
||||
|
||||
pw_log_debug ("deamon-config %p: loading configuration file '%s'", config, filename);
|
||||
pw_log_debug("deamon-config %p: loading configuration file '%s'", config, filename);
|
||||
|
||||
if ((f = fopen (filename, "r")) == NULL) {
|
||||
asprintf (err, "failed to open configuration file '%s': %s", filename, strerror (errno));
|
||||
goto open_error;
|
||||
}
|
||||
if ((f = fopen(filename, "r")) == NULL) {
|
||||
asprintf(err, "failed to open configuration file '%s': %s", filename,
|
||||
strerror(errno));
|
||||
goto open_error;
|
||||
}
|
||||
|
||||
line = 0;
|
||||
line = 0;
|
||||
|
||||
while (!feof(f)) {
|
||||
if (!fgets(buf, sizeof (buf), f)) {
|
||||
if (feof(f))
|
||||
break;
|
||||
while (!feof(f)) {
|
||||
if (!fgets(buf, sizeof(buf), f)) {
|
||||
if (feof(f))
|
||||
break;
|
||||
|
||||
asprintf (err, "failed to read configuration file '%s': %s", filename, strerror (errno));
|
||||
goto read_error;
|
||||
}
|
||||
asprintf(err, "failed to read configuration file '%s': %s",
|
||||
filename, strerror(errno));
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
line++;
|
||||
line++;
|
||||
|
||||
if (!parse_line (config, filename, buf, line, err))
|
||||
goto parse_failed;
|
||||
}
|
||||
fclose (f);
|
||||
if (!parse_line(config, filename, buf, line, err))
|
||||
goto parse_failed;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
|
||||
parse_failed:
|
||||
read_error:
|
||||
fclose (f);
|
||||
open_error:
|
||||
return false;
|
||||
parse_failed:
|
||||
read_error:
|
||||
fclose(f);
|
||||
open_error:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,19 +155,17 @@ open_error:
|
|||
*
|
||||
* Return: %true on success, otherwise %false and @err is set.
|
||||
*/
|
||||
bool
|
||||
pw_daemon_config_load (struct pw_daemon_config *config,
|
||||
char **err)
|
||||
bool pw_daemon_config_load(struct pw_daemon_config * config, char **err)
|
||||
{
|
||||
const char *filename;
|
||||
const char *filename;
|
||||
|
||||
filename = getenv ("PIPEWIRE_CONFIG_FILE");
|
||||
if (filename != NULL && *filename != '\0') {
|
||||
pw_log_debug ("PIPEWIRE_CONFIG_FILE set to: %s", filename);
|
||||
} else {
|
||||
filename = DEFAULT_CONFIG_FILE;
|
||||
}
|
||||
return pw_daemon_config_load_file (config, filename, err);
|
||||
filename = getenv("PIPEWIRE_CONFIG_FILE");
|
||||
if (filename != NULL && *filename != '\0') {
|
||||
pw_log_debug("PIPEWIRE_CONFIG_FILE set to: %s", filename);
|
||||
} else {
|
||||
filename = DEFAULT_CONFIG_FILE;
|
||||
}
|
||||
return pw_daemon_config_load_file(config, filename, err);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -186,25 +178,23 @@ pw_daemon_config_load (struct pw_daemon_config *config,
|
|||
*
|
||||
* Returns: %true if all commands where executed with success, otherwise %false.
|
||||
*/
|
||||
bool
|
||||
pw_daemon_config_run_commands (struct pw_daemon_config *config,
|
||||
struct pw_core *core)
|
||||
bool pw_daemon_config_run_commands(struct pw_daemon_config * config, struct pw_core * core)
|
||||
{
|
||||
char *err = NULL;
|
||||
bool ret = true;
|
||||
struct pw_command *command, *tmp;
|
||||
char *err = NULL;
|
||||
bool ret = true;
|
||||
struct pw_command *command, *tmp;
|
||||
|
||||
spa_list_for_each (command, &config->commands, link) {
|
||||
if (!pw_command_run (command, core, &err)) {
|
||||
pw_log_warn ("could not run command %s: %s", command->name, err);
|
||||
free (err);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
spa_list_for_each(command, &config->commands, link) {
|
||||
if (!pw_command_run(command, core, &err)) {
|
||||
pw_log_warn("could not run command %s: %s", command->name, err);
|
||||
free(err);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
spa_list_for_each_safe (command, tmp, &config->commands, link) {
|
||||
pw_command_free (command);
|
||||
}
|
||||
spa_list_for_each_safe(command, tmp, &config->commands, link) {
|
||||
pw_command_free(command);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,21 +28,26 @@ extern "C" {
|
|||
#include <pipewire/server/core.h>
|
||||
|
||||
struct pw_daemon_config {
|
||||
struct spa_list commands;
|
||||
struct spa_list commands;
|
||||
};
|
||||
|
||||
struct pw_daemon_config * pw_daemon_config_new (void);
|
||||
void pw_daemon_config_free (struct pw_daemon_config *config);
|
||||
bool pw_daemon_config_load_file (struct pw_daemon_config *config,
|
||||
const char *filename,
|
||||
char **err);
|
||||
bool pw_daemon_config_load (struct pw_daemon_config *config,
|
||||
char **err);
|
||||
bool pw_daemon_config_run_commands (struct pw_daemon_config *config,
|
||||
struct pw_core *core);
|
||||
struct pw_daemon_config *
|
||||
pw_daemon_config_new(void);
|
||||
|
||||
void
|
||||
pw_daemon_config_free(struct pw_daemon_config *config);
|
||||
|
||||
bool
|
||||
pw_daemon_config_load_file(struct pw_daemon_config *config, const char *filename, char **err);
|
||||
|
||||
bool
|
||||
pw_daemon_config_load(struct pw_daemon_config *config, char **err);
|
||||
|
||||
bool
|
||||
pw_daemon_config_run_commands(struct pw_daemon_config *config, struct pw_core *core);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __PIPEWIRE_DAEMON_CONFIG_H__ */
|
||||
|
|
|
|||
|
|
@ -23,42 +23,41 @@
|
|||
|
||||
#include "daemon-config.h"
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct pw_core *core;
|
||||
struct pw_main_loop *loop;
|
||||
struct pw_daemon_config *config;
|
||||
char *err = NULL;
|
||||
struct pw_core *core;
|
||||
struct pw_main_loop *loop;
|
||||
struct pw_daemon_config *config;
|
||||
char *err = NULL;
|
||||
|
||||
pw_init (&argc, &argv);
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
/* parse configuration */
|
||||
config = pw_daemon_config_new ();
|
||||
if (!pw_daemon_config_load (config, &err)) {
|
||||
pw_log_error ("failed to parse config: %s", err);
|
||||
free (err);
|
||||
return -1;
|
||||
}
|
||||
/* parse configuration */
|
||||
config = pw_daemon_config_new();
|
||||
if (!pw_daemon_config_load(config, &err)) {
|
||||
pw_log_error("failed to parse config: %s", err);
|
||||
free(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
loop = pw_main_loop_new ();
|
||||
loop = pw_main_loop_new();
|
||||
#if 1
|
||||
{
|
||||
struct spa_source *source;
|
||||
source = pw_loop_add_event (loop->loop, NULL, NULL);
|
||||
pw_log_set_trace_event (source);
|
||||
}
|
||||
{
|
||||
struct spa_source *source;
|
||||
source = pw_loop_add_event(loop->loop, NULL, NULL);
|
||||
pw_log_set_trace_event(source);
|
||||
}
|
||||
#endif
|
||||
|
||||
core = pw_core_new (loop, NULL);
|
||||
core = pw_core_new(loop, NULL);
|
||||
|
||||
pw_daemon_config_run_commands (config, core);
|
||||
pw_daemon_config_run_commands(config, core);
|
||||
|
||||
pw_main_loop_run (loop);
|
||||
pw_main_loop_run(loop);
|
||||
|
||||
pw_main_loop_destroy (loop);
|
||||
pw_main_loop_destroy(loop);
|
||||
|
||||
pw_core_destroy (core);
|
||||
pw_core_destroy(core);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,27 +33,26 @@
|
|||
#include <spa/lib/debug.h>
|
||||
|
||||
struct type {
|
||||
uint32_t format;
|
||||
uint32_t props;
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_media_type media_type;
|
||||
struct spa_type_media_subtype media_subtype;
|
||||
struct spa_type_format_video format_video;
|
||||
struct spa_type_video_format video_format;
|
||||
uint32_t format;
|
||||
uint32_t props;
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_media_type media_type;
|
||||
struct spa_type_media_subtype media_subtype;
|
||||
struct spa_type_format_video format_video;
|
||||
struct spa_type_video_format video_format;
|
||||
};
|
||||
|
||||
static inline void
|
||||
init_type (struct type *type, struct spa_type_map *map)
|
||||
static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||
{
|
||||
type->format = spa_type_map_get_id (map, SPA_TYPE__Format);
|
||||
type->props = spa_type_map_get_id (map, SPA_TYPE__Props);
|
||||
spa_type_meta_map (map, &type->meta);
|
||||
spa_type_data_map (map, &type->data);
|
||||
spa_type_media_type_map (map, &type->media_type);
|
||||
spa_type_media_subtype_map (map, &type->media_subtype);
|
||||
spa_type_format_video_map (map, &type->format_video);
|
||||
spa_type_video_format_map (map, &type->video_format);
|
||||
type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
|
||||
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
|
||||
spa_type_meta_map(map, &type->meta);
|
||||
spa_type_data_map(map, &type->data);
|
||||
spa_type_media_type_map(map, &type->media_type);
|
||||
spa_type_media_subtype_map(map, &type->media_subtype);
|
||||
spa_type_format_video_map(map, &type->format_video);
|
||||
spa_type_video_format_map(map, &type->video_format);
|
||||
}
|
||||
|
||||
#define WIDTH 640
|
||||
|
|
@ -61,363 +60,351 @@ init_type (struct type *type, struct spa_type_map *map)
|
|||
#define BPP 3
|
||||
|
||||
struct data {
|
||||
struct type type;
|
||||
struct type type;
|
||||
|
||||
const char *path;
|
||||
const char *path;
|
||||
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Window *window;
|
||||
SDL_Texture *texture;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Window *window;
|
||||
SDL_Texture *texture;
|
||||
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *timer;
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *timer;
|
||||
|
||||
struct pw_context *context;
|
||||
struct pw_listener on_state_changed;
|
||||
struct pw_context *context;
|
||||
struct pw_listener on_state_changed;
|
||||
|
||||
struct pw_stream *stream;
|
||||
struct pw_listener on_stream_state_changed;
|
||||
struct pw_listener on_stream_format_changed;
|
||||
struct pw_listener on_stream_new_buffer;
|
||||
struct pw_stream *stream;
|
||||
struct pw_listener on_stream_state_changed;
|
||||
struct pw_listener on_stream_format_changed;
|
||||
struct pw_listener on_stream_new_buffer;
|
||||
|
||||
struct spa_video_info_raw format;
|
||||
int32_t stride;
|
||||
struct spa_video_info_raw format;
|
||||
int32_t stride;
|
||||
|
||||
uint8_t params_buffer[1024];
|
||||
int counter;
|
||||
uint8_t params_buffer[1024];
|
||||
int counter;
|
||||
};
|
||||
|
||||
static void
|
||||
handle_events (struct data *data)
|
||||
static void handle_events(struct data *data)
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent (&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
exit (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_new_buffer (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
uint32_t id)
|
||||
on_stream_new_buffer(struct pw_listener *listener, struct pw_stream *stream, uint32_t id)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_stream_new_buffer);
|
||||
struct spa_buffer *buf;
|
||||
uint8_t *map;
|
||||
void *sdata, *ddata;
|
||||
int sstride, dstride, ostride;
|
||||
int i;
|
||||
uint8_t *src, *dst;
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_stream_new_buffer);
|
||||
struct spa_buffer *buf;
|
||||
uint8_t *map;
|
||||
void *sdata, *ddata;
|
||||
int sstride, dstride, ostride;
|
||||
int i;
|
||||
uint8_t *src, *dst;
|
||||
|
||||
buf = pw_stream_peek_buffer (data->stream, id);
|
||||
buf = pw_stream_peek_buffer(data->stream, id);
|
||||
|
||||
if (buf->datas[0].type == data->type.data.MemFd) {
|
||||
map = mmap (NULL, buf->datas[0].maxsize + buf->datas[0].mapoffset, PROT_READ,
|
||||
MAP_PRIVATE, buf->datas[0].fd, 0);
|
||||
sdata = SPA_MEMBER (map, buf->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buf->datas[0].type == data->type.data.MemPtr) {
|
||||
map = NULL;
|
||||
sdata = buf->datas[0].data;
|
||||
} else
|
||||
return;
|
||||
if (buf->datas[0].type == data->type.data.MemFd) {
|
||||
map = mmap(NULL, buf->datas[0].maxsize + buf->datas[0].mapoffset, PROT_READ,
|
||||
MAP_PRIVATE, buf->datas[0].fd, 0);
|
||||
sdata = SPA_MEMBER(map, buf->datas[0].mapoffset, uint8_t);
|
||||
} else if (buf->datas[0].type == data->type.data.MemPtr) {
|
||||
map = NULL;
|
||||
sdata = buf->datas[0].data;
|
||||
} else
|
||||
return;
|
||||
|
||||
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
|
||||
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
sstride = buf->datas[0].chunk->stride;
|
||||
ostride = SPA_MIN (sstride, dstride);
|
||||
if (SDL_LockTexture(data->texture, NULL, &ddata, &dstride) < 0) {
|
||||
fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
sstride = buf->datas[0].chunk->stride;
|
||||
ostride = SPA_MIN(sstride, dstride);
|
||||
|
||||
src = sdata;
|
||||
dst = ddata;
|
||||
for (i = 0; i < data->format.size.height; i++) {
|
||||
memcpy (dst, src, ostride);
|
||||
src += sstride;
|
||||
dst += dstride;
|
||||
}
|
||||
SDL_UnlockTexture(data->texture);
|
||||
src = sdata;
|
||||
dst = ddata;
|
||||
for (i = 0; i < data->format.size.height; i++) {
|
||||
memcpy(dst, src, ostride);
|
||||
src += sstride;
|
||||
dst += dstride;
|
||||
}
|
||||
SDL_UnlockTexture(data->texture);
|
||||
|
||||
SDL_RenderClear (data->renderer);
|
||||
SDL_RenderCopy (data->renderer, data->texture, NULL, NULL);
|
||||
SDL_RenderPresent (data->renderer);
|
||||
SDL_RenderClear(data->renderer);
|
||||
SDL_RenderCopy(data->renderer, data->texture, NULL, NULL);
|
||||
SDL_RenderPresent(data->renderer);
|
||||
|
||||
if (map)
|
||||
munmap (map, buf->datas[0].maxsize);
|
||||
if (map)
|
||||
munmap(map, buf->datas[0].maxsize);
|
||||
|
||||
pw_stream_recycle_buffer (data->stream, id);
|
||||
pw_stream_recycle_buffer(data->stream, id);
|
||||
|
||||
handle_events (data);
|
||||
handle_events(data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_state_changed (struct pw_listener *listener,
|
||||
struct pw_stream *stream)
|
||||
static void on_stream_state_changed(struct pw_listener *listener, struct pw_stream *stream)
|
||||
{
|
||||
printf ("stream state: \"%s\"\n", pw_stream_state_as_string (stream->state));
|
||||
printf("stream state: \"%s\"\n", pw_stream_state_as_string(stream->state));
|
||||
}
|
||||
|
||||
static struct {
|
||||
Uint32 format;
|
||||
uint32_t id;
|
||||
Uint32 format;
|
||||
uint32_t id;
|
||||
} video_formats[] = {
|
||||
{ SDL_PIXELFORMAT_UNKNOWN, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX1LSB, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_UNKNOWN, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX1LSB, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX1MSB, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX4LSB, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX4MSB, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_INDEX8, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGB332, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGB444, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGB555, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_BGR555, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_ARGB4444, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGBA4444, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_ABGR4444, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_BGRA4444, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_ARGB1555, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGBA5551, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_ABGR1555, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_BGRA5551, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGB565, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_BGR565, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGB24, offsetof (struct spa_type_video_format, RGB), },
|
||||
{ SDL_PIXELFORMAT_RGB888, offsetof (struct spa_type_video_format, RGB), },
|
||||
{ SDL_PIXELFORMAT_RGBX8888, offsetof (struct spa_type_video_format, RGBx), },
|
||||
{ SDL_PIXELFORMAT_BGR24, offsetof (struct spa_type_video_format, BGR), },
|
||||
{ SDL_PIXELFORMAT_BGR888, offsetof (struct spa_type_video_format, BGR), },
|
||||
{ SDL_PIXELFORMAT_BGRX8888, offsetof (struct spa_type_video_format, BGRx), },
|
||||
{ SDL_PIXELFORMAT_ARGB2101010, offsetof (struct spa_type_video_format, UNKNOWN), },
|
||||
{ SDL_PIXELFORMAT_RGBA8888, offsetof (struct spa_type_video_format, RGBA), },
|
||||
{ SDL_PIXELFORMAT_ARGB8888, offsetof (struct spa_type_video_format, ARGB), },
|
||||
{ SDL_PIXELFORMAT_BGRA8888, offsetof (struct spa_type_video_format, BGRA), },
|
||||
{ SDL_PIXELFORMAT_ABGR8888, offsetof (struct spa_type_video_format, ABGR), },
|
||||
{ SDL_PIXELFORMAT_YV12, offsetof (struct spa_type_video_format, YV12), },
|
||||
{ SDL_PIXELFORMAT_IYUV, offsetof (struct spa_type_video_format, I420), },
|
||||
{ SDL_PIXELFORMAT_YUY2, offsetof (struct spa_type_video_format, YUY2), },
|
||||
{ SDL_PIXELFORMAT_UYVY, offsetof (struct spa_type_video_format, UYVY), },
|
||||
{ SDL_PIXELFORMAT_YVYU, offsetof (struct spa_type_video_format, YVYU), },
|
||||
{ SDL_PIXELFORMAT_NV12, offsetof (struct spa_type_video_format, NV12), },
|
||||
{ SDL_PIXELFORMAT_NV21, offsetof (struct spa_type_video_format, NV21), }
|
||||
};
|
||||
{
|
||||
SDL_PIXELFORMAT_UNKNOWN, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX1LSB, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_UNKNOWN, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX1LSB, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX1MSB, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX4LSB, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX4MSB, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_INDEX8, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGB332, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGB444, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGB555, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_BGR555, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_ARGB4444, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGBA4444, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_ABGR4444, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_BGRA4444, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_ARGB1555, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGBA5551, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_ABGR1555, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_BGRA5551, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGB565, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_BGR565, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGB24, offsetof(struct spa_type_video_format, RGB),}, {
|
||||
SDL_PIXELFORMAT_RGB888, offsetof(struct spa_type_video_format, RGB),}, {
|
||||
SDL_PIXELFORMAT_RGBX8888, offsetof(struct spa_type_video_format, RGBx),}, {
|
||||
SDL_PIXELFORMAT_BGR24, offsetof(struct spa_type_video_format, BGR),}, {
|
||||
SDL_PIXELFORMAT_BGR888, offsetof(struct spa_type_video_format, BGR),}, {
|
||||
SDL_PIXELFORMAT_BGRX8888, offsetof(struct spa_type_video_format, BGRx),}, {
|
||||
SDL_PIXELFORMAT_ARGB2101010, offsetof(struct spa_type_video_format, UNKNOWN),}, {
|
||||
SDL_PIXELFORMAT_RGBA8888, offsetof(struct spa_type_video_format, RGBA),}, {
|
||||
SDL_PIXELFORMAT_ARGB8888, offsetof(struct spa_type_video_format, ARGB),}, {
|
||||
SDL_PIXELFORMAT_BGRA8888, offsetof(struct spa_type_video_format, BGRA),}, {
|
||||
SDL_PIXELFORMAT_ABGR8888, offsetof(struct spa_type_video_format, ABGR),}, {
|
||||
SDL_PIXELFORMAT_YV12, offsetof(struct spa_type_video_format, YV12),}, {
|
||||
SDL_PIXELFORMAT_IYUV, offsetof(struct spa_type_video_format, I420),}, {
|
||||
SDL_PIXELFORMAT_YUY2, offsetof(struct spa_type_video_format, YUY2),}, {
|
||||
SDL_PIXELFORMAT_UYVY, offsetof(struct spa_type_video_format, UYVY),}, {
|
||||
SDL_PIXELFORMAT_YVYU, offsetof(struct spa_type_video_format, YVYU),}, {
|
||||
SDL_PIXELFORMAT_NV12, offsetof(struct spa_type_video_format, NV12),}, {
|
||||
SDL_PIXELFORMAT_NV21, offsetof(struct spa_type_video_format, NV21),}};
|
||||
|
||||
static uint32_t
|
||||
sdl_format_to_id (struct data *data, Uint32 format)
|
||||
static uint32_t sdl_format_to_id(struct data *data, Uint32 format)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (video_formats); i++) {
|
||||
if (video_formats[i].format == format)
|
||||
return *SPA_MEMBER (&data->type.video_format, video_formats[i].id, uint32_t);
|
||||
}
|
||||
return data->type.video_format.UNKNOWN;
|
||||
for (i = 0; i < SPA_N_ELEMENTS(video_formats); i++) {
|
||||
if (video_formats[i].format == format)
|
||||
return *SPA_MEMBER(&data->type.video_format, video_formats[i].id, uint32_t);
|
||||
}
|
||||
return data->type.video_format.UNKNOWN;
|
||||
}
|
||||
|
||||
static Uint32
|
||||
id_to_sdl_format (struct data *data, uint32_t id)
|
||||
static Uint32 id_to_sdl_format(struct data *data, uint32_t id)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SPA_N_ELEMENTS (video_formats); i++) {
|
||||
if (*SPA_MEMBER (&data->type.video_format, video_formats[i].id, uint32_t) == id)
|
||||
return video_formats[i].format;
|
||||
}
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
for (i = 0; i < SPA_N_ELEMENTS(video_formats); i++) {
|
||||
if (*SPA_MEMBER(&data->type.video_format, video_formats[i].id, uint32_t) == id)
|
||||
return video_formats[i].format;
|
||||
}
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_U_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_U_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
|
||||
static void
|
||||
on_stream_format_changed (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
struct spa_format *format)
|
||||
on_stream_format_changed(struct pw_listener *listener,
|
||||
struct pw_stream *stream, struct spa_format *format)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_stream_format_changed);
|
||||
struct pw_context *ctx = stream->context;
|
||||
struct spa_pod_builder b = { NULL };
|
||||
struct spa_pod_frame f[2];
|
||||
struct spa_param *params[2];
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_stream_format_changed);
|
||||
struct pw_context *ctx = stream->context;
|
||||
struct spa_pod_builder b = { NULL };
|
||||
struct spa_pod_frame f[2];
|
||||
struct spa_param *params[2];
|
||||
Uint32 sdl_format;
|
||||
void *d;
|
||||
|
||||
if (format) {
|
||||
Uint32 sdl_format;
|
||||
void *d;
|
||||
if (format == NULL) {
|
||||
pw_stream_finish_format(stream, SPA_RESULT_OK, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
spa_debug_format (format, data->context->type.map);
|
||||
spa_debug_format(format, data->context->type.map);
|
||||
|
||||
spa_format_video_raw_parse (format, &data->format, &data->type.format_video);
|
||||
spa_format_video_raw_parse(format, &data->format, &data->type.format_video);
|
||||
|
||||
sdl_format = id_to_sdl_format (data, data->format.format);
|
||||
if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
pw_stream_finish_format (stream, SPA_RESULT_ERROR, NULL, 0);
|
||||
return;
|
||||
}
|
||||
sdl_format = id_to_sdl_format(data, data->format.format);
|
||||
if (sdl_format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
pw_stream_finish_format(stream, SPA_RESULT_ERROR, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
data->texture = SDL_CreateTexture (data->renderer,
|
||||
sdl_format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
data->format.size.width,
|
||||
data->format.size.height);
|
||||
SDL_LockTexture (data->texture, NULL, &d, &data->stride);
|
||||
SDL_UnlockTexture (data->texture);
|
||||
data->texture = SDL_CreateTexture(data->renderer,
|
||||
sdl_format,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
data->format.size.width,
|
||||
data->format.size.height);
|
||||
SDL_LockTexture(data->texture, NULL, &d, &data->stride);
|
||||
SDL_UnlockTexture(data->texture);
|
||||
|
||||
spa_pod_builder_init (&b, data->params_buffer, sizeof (data->params_buffer));
|
||||
spa_pod_builder_object (&b, &f[0], 0, ctx->type.param_alloc_buffers.Buffers,
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
data->stride * data->format.size.height),
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, data->stride),
|
||||
PROP_U_MM (&f[1], ctx->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32),
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
|
||||
params[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
|
||||
spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer));
|
||||
spa_pod_builder_object(&b, &f[0], 0, ctx->type.param_alloc_buffers.Buffers,
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
data->stride * data->format.size.height),
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
|
||||
data->stride),
|
||||
PROP_U_MM(&f[1], ctx->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
|
||||
32,
|
||||
2, 32),
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
|
||||
16));
|
||||
params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
|
||||
|
||||
spa_pod_builder_object (&b, &f[0], 0, ctx->type.param_alloc_meta_enable.MetaEnable,
|
||||
PROP (&f[1], ctx->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, ctx->type.meta.Header),
|
||||
PROP (&f[1], ctx->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header)));
|
||||
params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
|
||||
spa_pod_builder_object(&b, &f[0], 0, ctx->type.param_alloc_meta_enable.MetaEnable,
|
||||
PROP(&f[1], ctx->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
|
||||
ctx->type.meta.Header),
|
||||
PROP(&f[1], ctx->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
|
||||
sizeof(struct spa_meta_header)));
|
||||
params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
|
||||
|
||||
pw_stream_finish_format (stream, SPA_RESULT_OK, params, 2);
|
||||
}
|
||||
else {
|
||||
pw_stream_finish_format (stream, SPA_RESULT_OK, NULL, 0);
|
||||
}
|
||||
}
|
||||
static void
|
||||
on_state_changed (struct pw_listener *listener,
|
||||
struct pw_context *context)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_state_changed);
|
||||
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf ("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
|
||||
case PW_CONTEXT_STATE_CONNECTED:
|
||||
{
|
||||
struct spa_format *formats[1];
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
struct spa_pod_frame f[2];
|
||||
SDL_RendererInfo info;
|
||||
int i, c;
|
||||
|
||||
printf ("context state: \"%s\"\n", pw_context_state_as_string (context->state));
|
||||
|
||||
data->stream = pw_stream_new (context, "video-play", NULL);
|
||||
|
||||
SDL_GetRendererInfo(data->renderer, &info);
|
||||
|
||||
spa_pod_builder_push_format (&b, &f[0], data->type.format,
|
||||
data->type.media_type.video, data->type.media_subtype.raw);
|
||||
|
||||
spa_pod_builder_push_prop (&b, &f[1], data->type.format_video.format,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_ENUM);
|
||||
for (i = 0, c = 0; i < info.num_texture_formats; i++) {
|
||||
uint32_t id = sdl_format_to_id (data, info.texture_formats[i]);
|
||||
if (id == 0)
|
||||
continue;
|
||||
if (c++ == 0)
|
||||
spa_pod_builder_id (&b, id);
|
||||
spa_pod_builder_id (&b, id);
|
||||
}
|
||||
for (i = 0; i < SPA_N_ELEMENTS (video_formats); i++) {
|
||||
uint32_t id = *SPA_MEMBER (&data->type.video_format, video_formats[i].id, uint32_t);
|
||||
if (id != data->type.video_format.UNKNOWN)
|
||||
spa_pod_builder_id (&b, id);
|
||||
}
|
||||
spa_pod_builder_pop (&b, &f[1]);
|
||||
spa_pod_builder_add (&b,
|
||||
PROP_U_MM (&f[1], data->type.format_video.size,
|
||||
SPA_POD_TYPE_RECTANGLE, WIDTH, HEIGHT,
|
||||
1, 1,
|
||||
info.max_texture_width, info.max_texture_height),
|
||||
PROP_U_MM (&f[1], data->type.format_video.framerate,
|
||||
SPA_POD_TYPE_FRACTION, 25, 1,
|
||||
0, 1,
|
||||
30, 1),
|
||||
0);
|
||||
|
||||
spa_pod_builder_pop (&b, &f[0]);
|
||||
formats[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format);
|
||||
|
||||
printf ("supported formats:\n");
|
||||
spa_debug_format (formats[0], data->context->type.map);
|
||||
|
||||
pw_signal_add (&data->stream->state_changed,
|
||||
&data->on_stream_state_changed,
|
||||
on_stream_state_changed);
|
||||
pw_signal_add (&data->stream->format_changed,
|
||||
&data->on_stream_format_changed,
|
||||
on_stream_format_changed);
|
||||
pw_signal_add (&data->stream->new_buffer,
|
||||
&data->on_stream_new_buffer,
|
||||
on_stream_new_buffer);
|
||||
|
||||
pw_stream_connect (data->stream,
|
||||
PW_DIRECTION_INPUT,
|
||||
PW_STREAM_MODE_BUFFER,
|
||||
data->path,
|
||||
PW_STREAM_FLAG_AUTOCONNECT,
|
||||
1,
|
||||
formats);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf ("context state: \"%s\"\n", pw_context_state_as_string (context->state));
|
||||
break;
|
||||
}
|
||||
pw_stream_finish_format(stream, SPA_RESULT_OK, params, 2);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
static void on_state_changed(struct pw_listener *listener, struct pw_context *context)
|
||||
{
|
||||
struct data data = { 0, };
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_state_changed);
|
||||
|
||||
pw_init (&argc, &argv);
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
|
||||
data.loop = pw_loop_new ();
|
||||
data.running = true;
|
||||
data.context = pw_context_new (data.loop, "video-play", NULL);
|
||||
data.path = argc > 1 ? argv[1] : NULL;
|
||||
case PW_CONTEXT_STATE_CONNECTED:
|
||||
{
|
||||
struct spa_format *formats[1];
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||
struct spa_pod_frame f[2];
|
||||
SDL_RendererInfo info;
|
||||
int i, c;
|
||||
|
||||
init_type (&data.type, data.context->type.map);
|
||||
printf("context state: \"%s\"\n",
|
||||
pw_context_state_as_string(context->state));
|
||||
|
||||
if (SDL_Init (SDL_INIT_VIDEO) < 0) {
|
||||
printf ("can't initialize SDL: %s\n", SDL_GetError ());
|
||||
return -1;
|
||||
}
|
||||
data->stream = pw_stream_new(context, "video-play", NULL);
|
||||
|
||||
if (SDL_CreateWindowAndRenderer (WIDTH, HEIGHT, SDL_WINDOW_RESIZABLE, &data.window, &data.renderer)) {
|
||||
printf ("can't create window: %s\n", SDL_GetError ());
|
||||
return -1;
|
||||
}
|
||||
SDL_GetRendererInfo(data->renderer, &info);
|
||||
|
||||
pw_signal_add (&data.context->state_changed,
|
||||
&data.on_state_changed,
|
||||
on_state_changed);
|
||||
spa_pod_builder_push_format(&b, &f[0], data->type.format,
|
||||
data->type.media_type.video,
|
||||
data->type.media_subtype.raw);
|
||||
|
||||
pw_context_connect (data.context, PW_CONTEXT_FLAG_NO_REGISTRY);
|
||||
spa_pod_builder_push_prop(&b, &f[1], data->type.format_video.format,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_ENUM);
|
||||
for (i = 0, c = 0; i < info.num_texture_formats; i++) {
|
||||
uint32_t id = sdl_format_to_id(data, info.texture_formats[i]);
|
||||
if (id == 0)
|
||||
continue;
|
||||
if (c++ == 0)
|
||||
spa_pod_builder_id(&b, id);
|
||||
spa_pod_builder_id(&b, id);
|
||||
}
|
||||
for (i = 0; i < SPA_N_ELEMENTS(video_formats); i++) {
|
||||
uint32_t id =
|
||||
*SPA_MEMBER(&data->type.video_format, video_formats[i].id,
|
||||
uint32_t);
|
||||
if (id != data->type.video_format.UNKNOWN)
|
||||
spa_pod_builder_id(&b, id);
|
||||
}
|
||||
spa_pod_builder_pop(&b, &f[1]);
|
||||
spa_pod_builder_add(&b,
|
||||
PROP_U_MM(&f[1], data->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
|
||||
WIDTH, HEIGHT,
|
||||
1, 1, info.max_texture_width, info.max_texture_height),
|
||||
PROP_U_MM(&f[1], data->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
|
||||
25, 1,
|
||||
0, 1, 30, 1),
|
||||
0);
|
||||
spa_pod_builder_pop(&b, &f[0]);
|
||||
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
|
||||
|
||||
pw_loop_enter (data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate (data.loop, -1);
|
||||
}
|
||||
pw_loop_leave (data.loop);
|
||||
printf("supported formats:\n");
|
||||
spa_debug_format(formats[0], data->context->type.map);
|
||||
|
||||
pw_context_destroy (data.context);
|
||||
pw_loop_destroy (data.loop);
|
||||
pw_signal_add(&data->stream->state_changed,
|
||||
&data->on_stream_state_changed, on_stream_state_changed);
|
||||
pw_signal_add(&data->stream->format_changed,
|
||||
&data->on_stream_format_changed, on_stream_format_changed);
|
||||
pw_signal_add(&data->stream->new_buffer,
|
||||
&data->on_stream_new_buffer, on_stream_new_buffer);
|
||||
|
||||
return 0;
|
||||
pw_stream_connect(data->stream,
|
||||
PW_DIRECTION_INPUT,
|
||||
PW_STREAM_MODE_BUFFER,
|
||||
data->path, PW_STREAM_FLAG_AUTOCONNECT, 1, formats);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("context state: \"%s\"\n", pw_context_state_as_string(context->state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct data data = { 0, };
|
||||
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
data.loop = pw_loop_new();
|
||||
data.running = true;
|
||||
data.context = pw_context_new(data.loop, "video-play", NULL);
|
||||
data.path = argc > 1 ? argv[1] : NULL;
|
||||
|
||||
init_type(&data.type, data.context->type.map);
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
printf("can't initialize SDL: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDL_CreateWindowAndRenderer
|
||||
(WIDTH, HEIGHT, SDL_WINDOW_RESIZABLE, &data.window, &data.renderer)) {
|
||||
printf("can't create window: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
pw_signal_add(&data.context->state_changed, &data.on_state_changed, on_state_changed);
|
||||
|
||||
pw_context_connect(data.context, PW_CONTEXT_FLAG_NO_REGISTRY);
|
||||
|
||||
pw_loop_enter(data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate(data.loop, -1);
|
||||
}
|
||||
pw_loop_leave(data.loop);
|
||||
|
||||
pw_context_destroy(data.context);
|
||||
pw_loop_destroy(data.loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,274 +33,257 @@
|
|||
#include <spa/lib/debug.h>
|
||||
|
||||
struct type {
|
||||
uint32_t format;
|
||||
uint32_t props;
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_media_type media_type;
|
||||
struct spa_type_media_subtype media_subtype;
|
||||
struct spa_type_format_video format_video;
|
||||
struct spa_type_video_format video_format;
|
||||
uint32_t format;
|
||||
uint32_t props;
|
||||
struct spa_type_meta meta;
|
||||
struct spa_type_data data;
|
||||
struct spa_type_media_type media_type;
|
||||
struct spa_type_media_subtype media_subtype;
|
||||
struct spa_type_format_video format_video;
|
||||
struct spa_type_video_format video_format;
|
||||
};
|
||||
|
||||
static inline void
|
||||
init_type (struct type *type, struct spa_type_map *map)
|
||||
static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||
{
|
||||
type->format = spa_type_map_get_id (map, SPA_TYPE__Format);
|
||||
type->props = spa_type_map_get_id (map, SPA_TYPE__Props);
|
||||
spa_type_meta_map (map, &type->meta);
|
||||
spa_type_data_map (map, &type->data);
|
||||
spa_type_media_type_map (map, &type->media_type);
|
||||
spa_type_media_subtype_map (map, &type->media_subtype);
|
||||
spa_type_format_video_map (map, &type->format_video);
|
||||
spa_type_video_format_map (map, &type->video_format);
|
||||
type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
|
||||
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
|
||||
spa_type_meta_map(map, &type->meta);
|
||||
spa_type_data_map(map, &type->data);
|
||||
spa_type_media_type_map(map, &type->media_type);
|
||||
spa_type_media_subtype_map(map, &type->media_subtype);
|
||||
spa_type_format_video_map(map, &type->format_video);
|
||||
spa_type_video_format_map(map, &type->video_format);
|
||||
}
|
||||
|
||||
#define BPP 3
|
||||
|
||||
struct data {
|
||||
struct type type;
|
||||
struct type type;
|
||||
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *timer;
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *timer;
|
||||
|
||||
struct pw_context *context;
|
||||
struct pw_listener on_state_changed;
|
||||
struct pw_context *context;
|
||||
struct pw_listener on_state_changed;
|
||||
|
||||
struct pw_stream *stream;
|
||||
struct pw_listener on_stream_state_changed;
|
||||
struct pw_listener on_stream_format_changed;
|
||||
struct pw_stream *stream;
|
||||
struct pw_listener on_stream_state_changed;
|
||||
struct pw_listener on_stream_format_changed;
|
||||
|
||||
struct spa_video_info_raw format;
|
||||
int32_t stride;
|
||||
struct spa_video_info_raw format;
|
||||
int32_t stride;
|
||||
|
||||
uint8_t params_buffer[1024];
|
||||
int counter;
|
||||
uint32_t seq;
|
||||
uint8_t params_buffer[1024];
|
||||
int counter;
|
||||
uint32_t seq;
|
||||
};
|
||||
|
||||
static void
|
||||
on_timeout (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
void *userdata)
|
||||
static void on_timeout(struct spa_loop_utils *utils, struct spa_source *source, void *userdata)
|
||||
{
|
||||
struct data *data = userdata;
|
||||
uint32_t id;
|
||||
struct spa_buffer *buf;
|
||||
int i, j;
|
||||
uint8_t *p, *map;
|
||||
struct spa_meta_header *h;
|
||||
struct data *data = userdata;
|
||||
uint32_t id;
|
||||
struct spa_buffer *buf;
|
||||
int i, j;
|
||||
uint8_t *p, *map;
|
||||
struct spa_meta_header *h;
|
||||
|
||||
id = pw_stream_get_empty_buffer (data->stream);
|
||||
if (id == SPA_ID_INVALID)
|
||||
return;
|
||||
id = pw_stream_get_empty_buffer(data->stream);
|
||||
if (id == SPA_ID_INVALID)
|
||||
return;
|
||||
|
||||
buf = pw_stream_peek_buffer (data->stream, id);
|
||||
buf = pw_stream_peek_buffer(data->stream, id);
|
||||
|
||||
if (buf->datas[0].type == data->type.data.MemFd) {
|
||||
map = mmap (NULL, buf->datas[0].maxsize + buf->datas[0].mapoffset, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, buf->datas[0].fd, 0);
|
||||
if (map == MAP_FAILED) {
|
||||
printf ("failed to mmap: %s\n", strerror (errno));
|
||||
return;
|
||||
}
|
||||
p = SPA_MEMBER (map, buf->datas[0].mapoffset, uint8_t);
|
||||
}
|
||||
else if (buf->datas[0].type == data->type.data.MemPtr) {
|
||||
map = NULL;
|
||||
p = buf->datas[0].data;
|
||||
} else
|
||||
return;
|
||||
if (buf->datas[0].type == data->type.data.MemFd) {
|
||||
map =
|
||||
mmap(NULL, buf->datas[0].maxsize + buf->datas[0].mapoffset,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, buf->datas[0].fd, 0);
|
||||
if (map == MAP_FAILED) {
|
||||
printf("failed to mmap: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
p = SPA_MEMBER(map, buf->datas[0].mapoffset, uint8_t);
|
||||
} else if (buf->datas[0].type == data->type.data.MemPtr) {
|
||||
map = NULL;
|
||||
p = buf->datas[0].data;
|
||||
} else
|
||||
return;
|
||||
|
||||
if ((h = spa_buffer_find_meta (buf, data->type.meta.Header))) {
|
||||
struct timespec now;
|
||||
h->flags = 0;
|
||||
h->seq = data->seq++;
|
||||
clock_gettime (CLOCK_MONOTONIC, &now);
|
||||
h->pts = SPA_TIMESPEC_TO_TIME (&now);
|
||||
h->dts_offset = 0;
|
||||
}
|
||||
if ((h = spa_buffer_find_meta(buf, data->type.meta.Header))) {
|
||||
struct timespec now;
|
||||
h->flags = 0;
|
||||
h->seq = data->seq++;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
h->pts = SPA_TIMESPEC_TO_TIME(&now);
|
||||
h->dts_offset = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->format.size.height; i++) {
|
||||
for (j = 0; j < data->format.size.width * BPP; j++) {
|
||||
p[j] = data->counter + j * i;
|
||||
}
|
||||
p += buf->datas[0].chunk->stride;
|
||||
data->counter += 13;
|
||||
}
|
||||
for (i = 0; i < data->format.size.height; i++) {
|
||||
for (j = 0; j < data->format.size.width * BPP; j++) {
|
||||
p[j] = data->counter + j * i;
|
||||
}
|
||||
p += buf->datas[0].chunk->stride;
|
||||
data->counter += 13;
|
||||
}
|
||||
|
||||
if (map)
|
||||
munmap (map, buf->datas[0].maxsize + buf->datas[0].mapoffset);
|
||||
if (map)
|
||||
munmap(map, buf->datas[0].maxsize + buf->datas[0].mapoffset);
|
||||
|
||||
pw_stream_send_buffer (data->stream, id);
|
||||
pw_stream_send_buffer(data->stream, id);
|
||||
}
|
||||
|
||||
static void on_stream_state_changed(struct pw_listener *listener, struct pw_stream *stream)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_stream_state_changed);
|
||||
|
||||
printf("stream state: \"%s\"\n", pw_stream_state_as_string(stream->state));
|
||||
|
||||
switch (stream->state) {
|
||||
case PW_STREAM_STATE_PAUSED:
|
||||
pw_loop_update_timer(data->loop, data->timer, NULL, NULL, false);
|
||||
break;
|
||||
|
||||
case PW_STREAM_STATE_STREAMING:
|
||||
{
|
||||
struct timespec timeout, interval;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 1;
|
||||
interval.tv_sec = 0;
|
||||
interval.tv_nsec = 40 * SPA_NSEC_PER_MSEC;
|
||||
|
||||
pw_loop_update_timer(data->loop, data->timer, &timeout, &interval, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_U_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
|
||||
static void
|
||||
on_stream_state_changed (struct pw_listener *listener,
|
||||
struct pw_stream *stream)
|
||||
on_stream_format_changed(struct pw_listener *listener,
|
||||
struct pw_stream *stream, struct spa_format *format)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_stream_state_changed);
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_stream_format_changed);
|
||||
struct pw_context *ctx = stream->context;
|
||||
struct spa_pod_builder b = { NULL };
|
||||
struct spa_pod_frame f[2];
|
||||
struct spa_param *params[2];
|
||||
|
||||
printf ("stream state: \"%s\"\n", pw_stream_state_as_string (stream->state));
|
||||
if (format == NULL) {
|
||||
pw_stream_finish_format(stream, SPA_RESULT_OK, NULL, 0);
|
||||
return;
|
||||
}
|
||||
spa_format_video_raw_parse(format, &data->format, &data->type.format_video);
|
||||
|
||||
switch (stream->state) {
|
||||
case PW_STREAM_STATE_PAUSED:
|
||||
pw_loop_update_timer (data->loop,
|
||||
data->timer,
|
||||
NULL,
|
||||
NULL,
|
||||
false);
|
||||
break;
|
||||
data->stride = SPA_ROUND_UP_N(data->format.size.width * BPP, 4);
|
||||
|
||||
case PW_STREAM_STATE_STREAMING:
|
||||
{
|
||||
struct timespec timeout, interval;
|
||||
spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer));
|
||||
spa_pod_builder_object(&b, &f[0], 0, ctx->type.param_alloc_buffers.Buffers,
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
data->stride * data->format.size.height),
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
|
||||
data->stride),
|
||||
PROP_U_MM(&f[1], ctx->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
|
||||
32,
|
||||
2, 32),
|
||||
PROP(&f[1], ctx->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
|
||||
16));
|
||||
params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 1;
|
||||
interval.tv_sec = 0;
|
||||
interval.tv_nsec = 40 * SPA_NSEC_PER_MSEC;
|
||||
spa_pod_builder_object(&b, &f[0], 0, ctx->type.param_alloc_meta_enable.MetaEnable,
|
||||
PROP(&f[1], ctx->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
|
||||
ctx->type.meta.Header),
|
||||
PROP(&f[1], ctx->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
|
||||
sizeof(struct spa_meta_header)));
|
||||
params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
|
||||
|
||||
pw_loop_update_timer (data->loop,
|
||||
data->timer,
|
||||
&timeout,
|
||||
&interval,
|
||||
false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pw_stream_finish_format(stream, SPA_RESULT_OK, params, 2);
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_U_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
|
||||
static void
|
||||
on_stream_format_changed (struct pw_listener *listener,
|
||||
struct pw_stream *stream,
|
||||
struct spa_format *format)
|
||||
static void on_state_changed(struct pw_listener *listener, struct pw_context *context)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_stream_format_changed);
|
||||
struct pw_context *ctx = stream->context;
|
||||
struct spa_pod_builder b = { NULL };
|
||||
struct spa_pod_frame f[2];
|
||||
struct spa_param *params[2];
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_state_changed);
|
||||
|
||||
if (format) {
|
||||
spa_format_video_raw_parse (format, &data->format, &data->type.format_video);
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
|
||||
data->stride = SPA_ROUND_UP_N (data->format.size.width * BPP, 4);
|
||||
case PW_CONTEXT_STATE_CONNECTED:
|
||||
{
|
||||
struct spa_format *formats[1];
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||
struct spa_pod_frame f[2];
|
||||
|
||||
spa_pod_builder_init (&b, data->params_buffer, sizeof (data->params_buffer));
|
||||
spa_pod_builder_object (&b, &f[0], 0, ctx->type.param_alloc_buffers.Buffers,
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
data->stride * data->format.size.height),
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, data->stride),
|
||||
PROP_U_MM (&f[1], ctx->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 32, 2, 32),
|
||||
PROP (&f[1], ctx->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
|
||||
params[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
|
||||
printf("context state: \"%s\"\n",
|
||||
pw_context_state_as_string(context->state));
|
||||
|
||||
spa_pod_builder_object (&b, &f[0], 0, ctx->type.param_alloc_meta_enable.MetaEnable,
|
||||
PROP (&f[1], ctx->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID, ctx->type.meta.Header),
|
||||
PROP (&f[1], ctx->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header)));
|
||||
params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
|
||||
data->stream = pw_stream_new(context, "video-src", NULL);
|
||||
|
||||
pw_stream_finish_format (stream, SPA_RESULT_OK, params, 2);
|
||||
}
|
||||
else {
|
||||
pw_stream_finish_format (stream, SPA_RESULT_OK, NULL, 0);
|
||||
}
|
||||
spa_pod_builder_format(&b, &f[0], data->type.format,
|
||||
data->type.media_type.video,
|
||||
data->type.media_subtype.raw,
|
||||
PROP(&f[1], data->type.format_video.format, SPA_POD_TYPE_ID,
|
||||
data->type.video_format.RGB),
|
||||
PROP_U_MM(&f[1], data->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
|
||||
320, 240,
|
||||
1, 1, 4096, 4096),
|
||||
PROP(&f[1], data->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
|
||||
25, 1));
|
||||
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
|
||||
|
||||
pw_signal_add(&data->stream->state_changed,
|
||||
&data->on_stream_state_changed, on_stream_state_changed);
|
||||
pw_signal_add(&data->stream->format_changed,
|
||||
&data->on_stream_format_changed, on_stream_format_changed);
|
||||
|
||||
pw_stream_connect(data->stream,
|
||||
PW_DIRECTION_OUTPUT,
|
||||
PW_STREAM_MODE_BUFFER,
|
||||
NULL, PW_STREAM_FLAG_NONE, 1, formats);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("context state: \"%s\"\n", pw_context_state_as_string(context->state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_state_changed (struct pw_listener *listener,
|
||||
struct pw_context *context)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_state_changed);
|
||||
struct data data = { 0, };
|
||||
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf ("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
case PW_CONTEXT_STATE_CONNECTED:
|
||||
{
|
||||
struct spa_format *formats[1];
|
||||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
struct spa_pod_frame f[2];
|
||||
data.loop = pw_loop_new();
|
||||
data.running = true;
|
||||
data.context = pw_context_new(data.loop, "video-src", NULL);
|
||||
|
||||
printf ("context state: \"%s\"\n", pw_context_state_as_string (context->state));
|
||||
init_type(&data.type, data.context->type.map);
|
||||
|
||||
data->stream = pw_stream_new (context, "video-src", NULL);
|
||||
data.timer = pw_loop_add_timer(data.loop, on_timeout, &data);
|
||||
|
||||
spa_pod_builder_format (&b, &f[0], data->type.format,
|
||||
data->type.media_type.video, data->type.media_subtype.raw,
|
||||
PROP (&f[1], data->type.format_video.format, SPA_POD_TYPE_ID, data->type.video_format.RGB),
|
||||
PROP_U_MM (&f[1], data->type.format_video.size, SPA_POD_TYPE_RECTANGLE, 320, 240,
|
||||
1, 1,
|
||||
4096, 4096),
|
||||
PROP (&f[1], data->type.format_video.framerate, SPA_POD_TYPE_FRACTION, 25, 1));
|
||||
formats[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_format);
|
||||
pw_signal_add(&data.context->state_changed, &data.on_state_changed, on_state_changed);
|
||||
|
||||
pw_signal_add (&data->stream->state_changed,
|
||||
&data->on_stream_state_changed,
|
||||
on_stream_state_changed);
|
||||
pw_signal_add (&data->stream->format_changed,
|
||||
&data->on_stream_format_changed,
|
||||
on_stream_format_changed);
|
||||
pw_context_connect(data.context, PW_CONTEXT_FLAG_NO_REGISTRY);
|
||||
|
||||
pw_stream_connect (data->stream,
|
||||
PW_DIRECTION_OUTPUT,
|
||||
PW_STREAM_MODE_BUFFER,
|
||||
NULL,
|
||||
PW_STREAM_FLAG_NONE,
|
||||
1,
|
||||
formats);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf ("context state: \"%s\"\n", pw_context_state_as_string (context->state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
struct data data = { 0, };
|
||||
|
||||
pw_init (&argc, &argv);
|
||||
|
||||
data.loop = pw_loop_new ();
|
||||
data.running = true;
|
||||
data.context = pw_context_new (data.loop, "video-src", NULL);
|
||||
|
||||
init_type (&data.type, data.context->type.map);
|
||||
|
||||
data.timer = pw_loop_add_timer (data.loop, on_timeout, &data);
|
||||
|
||||
pw_signal_add (&data.context->state_changed,
|
||||
&data.on_state_changed,
|
||||
on_state_changed);
|
||||
|
||||
pw_context_connect (data.context,
|
||||
PW_CONTEXT_FLAG_NO_REGISTRY);
|
||||
|
||||
pw_loop_enter (data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate (data.loop, -1);
|
||||
}
|
||||
pw_loop_leave (data.loop);
|
||||
|
||||
pw_context_destroy (data.context);
|
||||
pw_loop_destroy (data.loop);
|
||||
|
||||
return 0;
|
||||
pw_loop_enter(data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate(data.loop, -1);
|
||||
}
|
||||
pw_loop_leave(data.loop);
|
||||
|
||||
pw_context_destroy(data.context);
|
||||
pw_loop_destroy(data.loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,362 +29,324 @@
|
|||
#include "pipewire/server/client-node.h"
|
||||
|
||||
struct impl {
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct pw_listener global_added;
|
||||
struct pw_listener global_removed;
|
||||
struct pw_listener global_added;
|
||||
struct pw_listener global_removed;
|
||||
|
||||
struct spa_list client_list;
|
||||
struct spa_list client_list;
|
||||
};
|
||||
|
||||
struct client_info {
|
||||
struct impl *impl;
|
||||
struct pw_client *client;
|
||||
struct spa_list link;
|
||||
struct pw_listener resource_added;
|
||||
struct pw_listener resource_removed;
|
||||
struct spa_list node_list;
|
||||
struct impl *impl;
|
||||
struct pw_client *client;
|
||||
struct spa_list link;
|
||||
struct pw_listener resource_added;
|
||||
struct pw_listener resource_removed;
|
||||
struct spa_list node_list;
|
||||
};
|
||||
|
||||
struct node_info {
|
||||
struct impl *impl;
|
||||
struct client_info *info;
|
||||
struct pw_node *node;
|
||||
struct pw_resource *resource;
|
||||
struct spa_list link;
|
||||
struct pw_listener state_changed;
|
||||
struct pw_listener port_added;
|
||||
struct pw_listener port_removed;
|
||||
struct pw_listener port_unlinked;
|
||||
struct pw_listener link_state_changed;
|
||||
struct impl *impl;
|
||||
struct client_info *info;
|
||||
struct pw_node *node;
|
||||
struct pw_resource *resource;
|
||||
struct spa_list link;
|
||||
struct pw_listener state_changed;
|
||||
struct pw_listener port_added;
|
||||
struct pw_listener port_removed;
|
||||
struct pw_listener port_unlinked;
|
||||
struct pw_listener link_state_changed;
|
||||
};
|
||||
|
||||
static struct node_info *
|
||||
find_node_info (struct client_info *cinfo, struct pw_node *node)
|
||||
static struct node_info *find_node_info(struct client_info *cinfo, struct pw_node *node)
|
||||
{
|
||||
struct node_info *info;
|
||||
struct node_info *info;
|
||||
|
||||
spa_list_for_each (info, &cinfo->node_list, link) {
|
||||
if (info->node == node)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
spa_list_for_each(info, &cinfo->node_list, link) {
|
||||
if (info->node == node)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct client_info *
|
||||
find_client_info (struct impl *impl, struct pw_client *client)
|
||||
static struct client_info *find_client_info(struct impl *impl, struct pw_client *client)
|
||||
{
|
||||
struct client_info *info;
|
||||
struct client_info *info;
|
||||
|
||||
spa_list_for_each (info, &impl->client_list, link) {
|
||||
if (info->client == client)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
spa_list_for_each(info, &impl->client_list, link) {
|
||||
if (info->client == client)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void node_info_free(struct node_info *info)
|
||||
{
|
||||
spa_list_remove(&info->link);
|
||||
pw_signal_remove(&info->state_changed);
|
||||
pw_signal_remove(&info->port_added);
|
||||
pw_signal_remove(&info->port_removed);
|
||||
pw_signal_remove(&info->port_unlinked);
|
||||
pw_signal_remove(&info->link_state_changed);
|
||||
free(info);
|
||||
}
|
||||
|
||||
static void client_info_free(struct client_info *cinfo)
|
||||
{
|
||||
struct node_info *info, *tmp;
|
||||
|
||||
spa_list_remove(&cinfo->link);
|
||||
pw_signal_remove(&cinfo->resource_added);
|
||||
pw_signal_remove(&cinfo->resource_removed);
|
||||
|
||||
spa_list_for_each_safe(info, tmp, &cinfo->node_list, link)
|
||||
node_info_free(info);
|
||||
|
||||
free(cinfo);
|
||||
}
|
||||
|
||||
static void try_link_port(struct pw_node *node, struct pw_port *port, struct node_info *info);
|
||||
|
||||
static void
|
||||
on_link_port_unlinked(struct pw_listener *listener, struct pw_link *link, struct pw_port *port)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, port_unlinked);
|
||||
struct impl *impl = info->impl;
|
||||
|
||||
pw_log_debug("module %p: link %p: port %p unlinked", impl, link, port);
|
||||
if (port->direction == PW_DIRECTION_OUTPUT && link->input)
|
||||
try_link_port(link->input->node, link->input, info);
|
||||
}
|
||||
|
||||
static void
|
||||
node_info_free (struct node_info *info)
|
||||
on_link_state_changed(struct pw_listener *listener,
|
||||
struct pw_link *link, enum pw_link_state old, enum pw_link_state state)
|
||||
{
|
||||
spa_list_remove (&info->link);
|
||||
pw_signal_remove (&info->state_changed);
|
||||
pw_signal_remove (&info->port_added);
|
||||
pw_signal_remove (&info->port_removed);
|
||||
pw_signal_remove (&info->port_unlinked);
|
||||
pw_signal_remove (&info->link_state_changed);
|
||||
free (info);
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, link_state_changed);
|
||||
struct impl *impl = info->impl;
|
||||
|
||||
switch (state) {
|
||||
case PW_LINK_STATE_ERROR:
|
||||
{
|
||||
struct pw_resource *resource;
|
||||
|
||||
pw_log_debug("module %p: link %p: state error: %s", impl, link,
|
||||
link->error);
|
||||
|
||||
spa_list_for_each(resource, &link->resource_list, link) {
|
||||
pw_core_notify_error(resource->client->core_resource,
|
||||
resource->id, SPA_RESULT_ERROR, link->error);
|
||||
}
|
||||
if (info->info->client) {
|
||||
pw_core_notify_error(info->info->client->core_resource,
|
||||
info->resource->id,
|
||||
SPA_RESULT_ERROR, link->error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PW_LINK_STATE_UNLINKED:
|
||||
pw_log_debug("module %p: link %p: unlinked", impl, link);
|
||||
break;
|
||||
|
||||
case PW_LINK_STATE_INIT:
|
||||
case PW_LINK_STATE_NEGOTIATING:
|
||||
case PW_LINK_STATE_ALLOCATING:
|
||||
case PW_LINK_STATE_PAUSED:
|
||||
case PW_LINK_STATE_RUNNING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void try_link_port(struct pw_node *node, struct pw_port *port, struct node_info *info)
|
||||
{
|
||||
struct impl *impl = info->impl;
|
||||
struct pw_properties *props;
|
||||
const char *str;
|
||||
uint32_t path_id;
|
||||
char *error = NULL;
|
||||
struct pw_link *link;
|
||||
struct pw_port *target;
|
||||
|
||||
props = node->properties;
|
||||
if (props == NULL) {
|
||||
pw_log_debug("module %p: node has no properties", impl);
|
||||
return;
|
||||
}
|
||||
|
||||
str = pw_properties_get(props, "pipewire.target.node");
|
||||
if (str != NULL)
|
||||
path_id = atoi(str);
|
||||
else {
|
||||
str = pw_properties_get(props, "pipewire.autoconnect");
|
||||
if (str == NULL || atoi(str) == 0) {
|
||||
pw_log_debug("module %p: node does not need autoconnect", impl);
|
||||
return;
|
||||
}
|
||||
path_id = SPA_ID_INVALID;
|
||||
}
|
||||
|
||||
pw_log_debug("module %p: try to find and link to node '%d'", impl, path_id);
|
||||
|
||||
target = pw_core_find_port(impl->core, port, path_id, NULL, 0, NULL, &error);
|
||||
if (target == NULL)
|
||||
goto error;
|
||||
|
||||
if (port->direction == PW_DIRECTION_OUTPUT)
|
||||
link = pw_port_link(port, target, NULL, NULL, &error);
|
||||
else
|
||||
link = pw_port_link(target, port, NULL, NULL, &error);
|
||||
|
||||
if (link == NULL)
|
||||
goto error;
|
||||
|
||||
pw_signal_add(&link->port_unlinked, &info->port_unlinked, on_link_port_unlinked);
|
||||
pw_signal_add(&link->state_changed, &info->link_state_changed, on_link_state_changed);
|
||||
|
||||
pw_link_activate(link);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
pw_log_error("module %p: can't link node '%s'", impl, error);
|
||||
if (info->info->client && info->info->client->core_resource) {
|
||||
pw_core_notify_error(info->info->client->core_resource,
|
||||
info->resource->id, SPA_RESULT_ERROR, error);
|
||||
}
|
||||
free(error);
|
||||
return;
|
||||
}
|
||||
|
||||
static void on_port_added(struct pw_listener *listener, struct pw_node *node, struct pw_port *port)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, port_added);
|
||||
|
||||
try_link_port(node, port, info);
|
||||
}
|
||||
|
||||
static void
|
||||
client_info_free (struct client_info *cinfo)
|
||||
{
|
||||
struct node_info *info, *tmp;
|
||||
|
||||
spa_list_remove (&cinfo->link);
|
||||
pw_signal_remove (&cinfo->resource_added);
|
||||
pw_signal_remove (&cinfo->resource_removed);
|
||||
|
||||
spa_list_for_each_safe (info, tmp, &cinfo->node_list, link)
|
||||
node_info_free (info);
|
||||
|
||||
free (cinfo);
|
||||
}
|
||||
|
||||
static void try_link_port (struct pw_node *node, struct pw_port *port, struct node_info *info);
|
||||
|
||||
static void
|
||||
on_link_port_unlinked (struct pw_listener *listener,
|
||||
struct pw_link *link,
|
||||
struct pw_port *port)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, port_unlinked);
|
||||
struct impl *impl = info->impl;
|
||||
|
||||
pw_log_debug ("module %p: link %p: port %p unlinked", impl, link, port);
|
||||
if (port->direction == PW_DIRECTION_OUTPUT && link->input)
|
||||
try_link_port (link->input->node, link->input, info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_link_state_changed (struct pw_listener *listener,
|
||||
struct pw_link *link,
|
||||
enum pw_link_state old,
|
||||
enum pw_link_state state)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, link_state_changed);
|
||||
struct impl *impl = info->impl;
|
||||
|
||||
switch (state) {
|
||||
case PW_LINK_STATE_ERROR:
|
||||
{
|
||||
struct pw_resource *resource;
|
||||
|
||||
pw_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
|
||||
|
||||
spa_list_for_each (resource, &link->resource_list, link) {
|
||||
pw_core_notify_error (resource->client->core_resource,
|
||||
resource->id,
|
||||
SPA_RESULT_ERROR,
|
||||
link->error);
|
||||
}
|
||||
if (info->info->client) {
|
||||
pw_core_notify_error (info->info->client->core_resource,
|
||||
info->resource->id,
|
||||
SPA_RESULT_ERROR,
|
||||
link->error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PW_LINK_STATE_UNLINKED:
|
||||
pw_log_debug ("module %p: link %p: unlinked", impl, link);
|
||||
break;
|
||||
|
||||
case PW_LINK_STATE_INIT:
|
||||
case PW_LINK_STATE_NEGOTIATING:
|
||||
case PW_LINK_STATE_ALLOCATING:
|
||||
case PW_LINK_STATE_PAUSED:
|
||||
case PW_LINK_STATE_RUNNING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
try_link_port (struct pw_node *node,
|
||||
struct pw_port *port,
|
||||
struct node_info *info)
|
||||
{
|
||||
struct impl *impl = info->impl;
|
||||
struct pw_properties *props;
|
||||
const char *str;
|
||||
uint32_t path_id;
|
||||
char *error = NULL;
|
||||
struct pw_link *link;
|
||||
struct pw_port *target;
|
||||
|
||||
props = node->properties;
|
||||
if (props == NULL) {
|
||||
pw_log_debug ("module %p: node has no properties", impl);
|
||||
return;
|
||||
}
|
||||
|
||||
str = pw_properties_get (props, "pipewire.target.node");
|
||||
if (str != NULL)
|
||||
path_id = atoi (str);
|
||||
else {
|
||||
str = pw_properties_get (props, "pipewire.autoconnect");
|
||||
if (str == NULL || atoi (str) == 0) {
|
||||
pw_log_debug ("module %p: node does not need autoconnect", impl);
|
||||
return;
|
||||
}
|
||||
path_id = SPA_ID_INVALID;
|
||||
}
|
||||
|
||||
pw_log_debug ("module %p: try to find and link to node '%d'", impl, path_id);
|
||||
|
||||
target = pw_core_find_port (impl->core,
|
||||
port,
|
||||
path_id,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&error);
|
||||
if (target == NULL)
|
||||
goto error;
|
||||
|
||||
if (port->direction == PW_DIRECTION_OUTPUT)
|
||||
link = pw_port_link (port, target, NULL, NULL, &error);
|
||||
else
|
||||
link = pw_port_link (target, port, NULL, NULL, &error);
|
||||
|
||||
if (link == NULL)
|
||||
goto error;
|
||||
|
||||
pw_signal_add (&link->port_unlinked, &info->port_unlinked, on_link_port_unlinked);
|
||||
pw_signal_add (&link->state_changed, &info->link_state_changed, on_link_state_changed);
|
||||
|
||||
pw_link_activate (link);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
{
|
||||
pw_log_error ("module %p: can't link node '%s'", impl, error);
|
||||
if (info->info->client && info->info->client->core_resource) {
|
||||
pw_core_notify_error (info->info->client->core_resource,
|
||||
info->resource->id,
|
||||
SPA_RESULT_ERROR,
|
||||
error);
|
||||
}
|
||||
free (error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_port_added (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
struct pw_port *port)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, port_added);
|
||||
|
||||
try_link_port (node, port, info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_port_removed (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
struct pw_port *port)
|
||||
on_port_removed(struct pw_listener *listener, struct pw_node *node, struct pw_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_created (struct pw_node *node,
|
||||
struct node_info *info)
|
||||
static void on_node_created(struct pw_node *node, struct node_info *info)
|
||||
{
|
||||
struct pw_port *port;
|
||||
struct pw_port *port;
|
||||
|
||||
spa_list_for_each (port, &node->input_ports, link)
|
||||
on_port_added (&info->port_added, node, port);
|
||||
spa_list_for_each(port, &node->input_ports, link)
|
||||
on_port_added(&info->port_added, node, port);
|
||||
|
||||
spa_list_for_each (port, &node->output_ports, link)
|
||||
on_port_added (&info->port_added, node, port);
|
||||
spa_list_for_each(port, &node->output_ports, link)
|
||||
on_port_added(&info->port_added, node, port);
|
||||
}
|
||||
|
||||
static void
|
||||
on_state_changed (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
enum pw_node_state old,
|
||||
enum pw_node_state state)
|
||||
on_state_changed(struct pw_listener *listener,
|
||||
struct pw_node *node, enum pw_node_state old, enum pw_node_state state)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, state_changed);
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, state_changed);
|
||||
|
||||
if (old == PW_NODE_STATE_CREATING && state == PW_NODE_STATE_SUSPENDED)
|
||||
on_node_created (node, info);
|
||||
if (old == PW_NODE_STATE_CREATING && state == PW_NODE_STATE_SUSPENDED)
|
||||
on_node_created(node, info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_added (struct impl *impl,
|
||||
struct pw_node *node,
|
||||
struct pw_resource *resource,
|
||||
struct client_info *cinfo)
|
||||
on_node_added(struct impl *impl,
|
||||
struct pw_node *node, struct pw_resource *resource, struct client_info *cinfo)
|
||||
{
|
||||
struct node_info *info;
|
||||
struct node_info *info;
|
||||
|
||||
info = calloc (1, sizeof (struct node_info));
|
||||
info->impl = impl;
|
||||
info->node = node;
|
||||
info->resource = resource;
|
||||
info->info = cinfo;
|
||||
spa_list_insert (cinfo->node_list.prev, &info->link);
|
||||
info = calloc(1, sizeof(struct node_info));
|
||||
info->impl = impl;
|
||||
info->node = node;
|
||||
info->resource = resource;
|
||||
info->info = cinfo;
|
||||
spa_list_insert(cinfo->node_list.prev, &info->link);
|
||||
|
||||
spa_list_init (&info->port_unlinked.link);
|
||||
spa_list_init (&info->link_state_changed.link);
|
||||
pw_signal_add (&node->port_added, &info->port_added, on_port_added);
|
||||
pw_signal_add (&node->port_removed, &info->port_removed, on_port_removed);
|
||||
pw_signal_add (&node->state_changed, &info->state_changed, on_state_changed);
|
||||
spa_list_init(&info->port_unlinked.link);
|
||||
spa_list_init(&info->link_state_changed.link);
|
||||
pw_signal_add(&node->port_added, &info->port_added, on_port_added);
|
||||
pw_signal_add(&node->port_removed, &info->port_removed, on_port_removed);
|
||||
pw_signal_add(&node->state_changed, &info->state_changed, on_state_changed);
|
||||
|
||||
pw_log_debug ("module %p: node %p added", impl, node);
|
||||
pw_log_debug("module %p: node %p added", impl, node);
|
||||
|
||||
if (node->state > PW_NODE_STATE_CREATING)
|
||||
on_node_created (node, info);
|
||||
if (node->state > PW_NODE_STATE_CREATING)
|
||||
on_node_created(node, info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_resource_added (struct pw_listener *listener,
|
||||
struct pw_client *client,
|
||||
struct pw_resource *resource)
|
||||
on_resource_added(struct pw_listener *listener,
|
||||
struct pw_client *client, struct pw_resource *resource)
|
||||
{
|
||||
struct client_info *cinfo = SPA_CONTAINER_OF (listener, struct client_info, resource_added);
|
||||
struct impl *impl = cinfo->impl;
|
||||
struct client_info *cinfo = SPA_CONTAINER_OF(listener, struct client_info, resource_added);
|
||||
struct impl *impl = cinfo->impl;
|
||||
|
||||
if (resource->type == impl->core->type.client_node) {
|
||||
struct pw_client_node *cnode = resource->object;
|
||||
on_node_added (impl, cnode->node, resource, cinfo);
|
||||
}
|
||||
if (resource->type == impl->core->type.client_node) {
|
||||
struct pw_client_node *cnode = resource->object;
|
||||
on_node_added(impl, cnode->node, resource, cinfo);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_resource_removed (struct pw_listener *listener,
|
||||
struct pw_client *client,
|
||||
struct pw_resource *resource)
|
||||
on_resource_removed(struct pw_listener *listener,
|
||||
struct pw_client *client, struct pw_resource *resource)
|
||||
{
|
||||
struct client_info *cinfo = SPA_CONTAINER_OF (listener, struct client_info, resource_removed);
|
||||
struct impl *impl = cinfo->impl;
|
||||
struct client_info *cinfo =
|
||||
SPA_CONTAINER_OF(listener, struct client_info, resource_removed);
|
||||
struct impl *impl = cinfo->impl;
|
||||
|
||||
if (resource->type == impl->core->type.client_node) {
|
||||
struct pw_client_node *cnode = resource->object;
|
||||
struct node_info *ninfo;
|
||||
if (resource->type == impl->core->type.client_node) {
|
||||
struct pw_client_node *cnode = resource->object;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if ((ninfo = find_node_info (cinfo, cnode->node)))
|
||||
node_info_free (ninfo);
|
||||
if ((ninfo = find_node_info(cinfo, cnode->node)))
|
||||
node_info_free(ninfo);
|
||||
|
||||
pw_log_debug ("module %p: node %p removed", impl, cnode->node);
|
||||
}
|
||||
pw_log_debug("module %p: node %p removed", impl, cnode->node);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_global_added (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global)
|
||||
on_global_added(struct pw_listener *listener, struct pw_core *core, struct pw_global *global)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (listener, struct impl, global_added);
|
||||
struct impl *impl = SPA_CONTAINER_OF(listener, struct impl, global_added);
|
||||
|
||||
if (global->type == impl->core->type.client) {
|
||||
struct pw_client *client = global->object;
|
||||
struct client_info *cinfo;
|
||||
if (global->type == impl->core->type.client) {
|
||||
struct pw_client *client = global->object;
|
||||
struct client_info *cinfo;
|
||||
|
||||
cinfo = calloc (1, sizeof (struct client_info));
|
||||
cinfo->impl = impl;
|
||||
cinfo->client = global->object;
|
||||
spa_list_init (&cinfo->node_list);
|
||||
cinfo = calloc(1, sizeof(struct client_info));
|
||||
cinfo->impl = impl;
|
||||
cinfo->client = global->object;
|
||||
spa_list_init(&cinfo->node_list);
|
||||
|
||||
spa_list_insert (impl->client_list.prev, &cinfo->link);
|
||||
spa_list_insert(impl->client_list.prev, &cinfo->link);
|
||||
|
||||
pw_signal_add (&client->resource_added, &cinfo->resource_added, on_resource_added);
|
||||
pw_signal_add (&client->resource_removed, &cinfo->resource_removed, on_resource_removed);
|
||||
pw_signal_add(&client->resource_added, &cinfo->resource_added, on_resource_added);
|
||||
pw_signal_add(&client->resource_removed, &cinfo->resource_removed,
|
||||
on_resource_removed);
|
||||
|
||||
pw_log_debug ("module %p: client %p added", impl, cinfo->client);
|
||||
}
|
||||
pw_log_debug("module %p: client %p added", impl, cinfo->client);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_global_removed (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global)
|
||||
on_global_removed(struct pw_listener *listener, struct pw_core *core, struct pw_global *global)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (listener, struct impl, global_removed);
|
||||
struct impl *impl = SPA_CONTAINER_OF(listener, struct impl, global_removed);
|
||||
|
||||
if (global->type == impl->core->type.client) {
|
||||
struct pw_client *client = global->object;
|
||||
struct client_info *cinfo;
|
||||
if (global->type == impl->core->type.client) {
|
||||
struct pw_client *client = global->object;
|
||||
struct client_info *cinfo;
|
||||
|
||||
if ((cinfo = find_client_info (impl, client)))
|
||||
client_info_free (cinfo);
|
||||
if ((cinfo = find_client_info(impl, client)))
|
||||
client_info_free(cinfo);
|
||||
|
||||
pw_log_debug ("module %p: client %p removed", impl, client);
|
||||
}
|
||||
pw_log_debug("module %p: client %p removed", impl, client);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -396,47 +358,43 @@ on_global_removed (struct pw_listener *listener,
|
|||
*
|
||||
* Returns: a new #struct impl
|
||||
*/
|
||||
static struct impl *
|
||||
module_new (struct pw_core *core,
|
||||
struct pw_properties *properties)
|
||||
static struct impl *module_new(struct pw_core *core, struct pw_properties *properties)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct impl *impl;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
pw_log_debug ("module %p: new", impl);
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
pw_log_debug("module %p: new", impl);
|
||||
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
|
||||
spa_list_init (&impl->client_list);
|
||||
spa_list_init(&impl->client_list);
|
||||
|
||||
pw_signal_add (&core->global_added, &impl->global_added, on_global_added);
|
||||
pw_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
|
||||
pw_signal_add(&core->global_added, &impl->global_added, on_global_added);
|
||||
pw_signal_add(&core->global_removed, &impl->global_removed, on_global_removed);
|
||||
|
||||
return impl;
|
||||
return impl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
module_destroy (struct impl *impl)
|
||||
static void module_destroy(struct impl *impl)
|
||||
{
|
||||
pw_log_debug ("module %p: destroy", impl);
|
||||
pw_log_debug("module %p: destroy", impl);
|
||||
|
||||
pw_global_destroy (impl->global);
|
||||
pw_global_destroy(impl->global);
|
||||
|
||||
pw_signal_remove (&impl->global_added);
|
||||
pw_signal_remove (&impl->global_removed);
|
||||
pw_signal_remove (&impl->port_added);
|
||||
pw_signal_remove (&impl->port_removed);
|
||||
pw_signal_remove (&impl->port_unlinked);
|
||||
pw_signal_remove (&impl->link_state_changed);
|
||||
free (impl);
|
||||
pw_signal_remove(&impl->global_added);
|
||||
pw_signal_remove(&impl->global_removed);
|
||||
pw_signal_remove(&impl->port_added);
|
||||
pw_signal_remove(&impl->port_removed);
|
||||
pw_signal_remove(&impl->port_unlinked);
|
||||
pw_signal_remove(&impl->link_state_changed);
|
||||
free(impl);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
pipewire__module_init (struct pw_module * module, const char * args)
|
||||
bool pipewire__module_init(struct pw_module *module, const char *args)
|
||||
{
|
||||
module->user_data = module_new (module->core, NULL);
|
||||
return true;
|
||||
module->user_data = module_new(module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,157 +30,139 @@
|
|||
#define AUDIOMIXER_LIB "build/spa/plugins/audiomixer/libspa-audiomixer.so"
|
||||
|
||||
struct impl {
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
|
||||
void *hnd;
|
||||
const struct spa_handle_factory *factory;
|
||||
void *hnd;
|
||||
const struct spa_handle_factory *factory;
|
||||
};
|
||||
|
||||
static const struct spa_handle_factory *
|
||||
find_factory (struct impl *impl)
|
||||
static const struct spa_handle_factory *find_factory(struct impl *impl)
|
||||
{
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
uint32_t index;
|
||||
const struct spa_handle_factory *factory = NULL;
|
||||
int res;
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
uint32_t index;
|
||||
const struct spa_handle_factory *factory = NULL;
|
||||
int res;
|
||||
|
||||
if ((impl->hnd = dlopen (AUDIOMIXER_LIB, RTLD_NOW)) == NULL) {
|
||||
pw_log_error ("can't load %s: %s", AUDIOMIXER_LIB, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym (impl->hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error ("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
if ((impl->hnd = dlopen(AUDIOMIXER_LIB, RTLD_NOW)) == NULL) {
|
||||
pw_log_error("can't load %s: %s", AUDIOMIXER_LIB, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym(impl->hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
|
||||
for (index = 0; ; index++) {
|
||||
if ((res = enum_func (&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error ("can't enumerate factories: %d", res);
|
||||
goto enum_failed;
|
||||
}
|
||||
if (strcmp (factory->name, "audiomixer") == 0)
|
||||
break;
|
||||
}
|
||||
return factory;
|
||||
for (index = 0;; index++) {
|
||||
if ((res = enum_func(&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error("can't enumerate factories: %d", res);
|
||||
goto enum_failed;
|
||||
}
|
||||
if (strcmp(factory->name, "audiomixer") == 0)
|
||||
break;
|
||||
}
|
||||
return factory;
|
||||
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose (impl->hnd);
|
||||
impl->hnd = NULL;
|
||||
return NULL;
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose(impl->hnd);
|
||||
impl->hnd = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pw_node *
|
||||
make_node (struct impl *impl)
|
||||
static struct pw_node *make_node(struct impl *impl)
|
||||
{
|
||||
struct spa_handle *handle;
|
||||
int res;
|
||||
void *iface;
|
||||
struct spa_node *spa_node;
|
||||
struct spa_clock *spa_clock;
|
||||
struct pw_node *node;
|
||||
struct spa_handle *handle;
|
||||
int res;
|
||||
void *iface;
|
||||
struct spa_node *spa_node;
|
||||
struct spa_clock *spa_clock;
|
||||
struct pw_node *node;
|
||||
|
||||
handle = calloc (1, impl->factory->size);
|
||||
if ((res = spa_handle_factory_init (impl->factory,
|
||||
handle,
|
||||
NULL,
|
||||
impl->core->support,
|
||||
impl->core->n_support)) < 0) {
|
||||
pw_log_error ("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
impl->core->type.spa_node,
|
||||
&iface)) < 0) {
|
||||
pw_log_error ("can't get interface %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
spa_node = iface;
|
||||
handle = calloc(1, impl->factory->size);
|
||||
if ((res = spa_handle_factory_init(impl->factory,
|
||||
handle,
|
||||
NULL, impl->core->support, impl->core->n_support)) < 0) {
|
||||
pw_log_error("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface(handle, impl->core->type.spa_node, &iface)) < 0) {
|
||||
pw_log_error("can't get interface %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
spa_node = iface;
|
||||
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
impl->core->type.spa_clock,
|
||||
&iface)) < 0) {
|
||||
iface = NULL;
|
||||
}
|
||||
spa_clock = iface;
|
||||
if ((res = spa_handle_get_interface(handle, impl->core->type.spa_clock, &iface)) < 0) {
|
||||
iface = NULL;
|
||||
}
|
||||
spa_clock = iface;
|
||||
|
||||
node = pw_node_new (impl->core,
|
||||
NULL,
|
||||
"audiomixer",
|
||||
false,
|
||||
spa_node,
|
||||
spa_clock,
|
||||
NULL);
|
||||
return node;
|
||||
node = pw_node_new(impl->core, NULL, "audiomixer", false, spa_node, spa_clock, NULL);
|
||||
return node;
|
||||
|
||||
interface_failed:
|
||||
spa_handle_clear (handle);
|
||||
init_failed:
|
||||
free (handle);
|
||||
return NULL;
|
||||
interface_failed:
|
||||
spa_handle_clear(handle);
|
||||
init_failed:
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct impl *
|
||||
module_new (struct pw_core *core,
|
||||
struct pw_properties *properties)
|
||||
static struct impl *module_new(struct pw_core *core, struct pw_properties *properties)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_node *n;
|
||||
struct impl *impl;
|
||||
struct pw_node *n;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
pw_log_debug ("module %p: new", impl);
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
pw_log_debug("module %p: new", impl);
|
||||
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
|
||||
impl->factory = find_factory (impl);
|
||||
impl->factory = find_factory(impl);
|
||||
|
||||
spa_list_for_each (n, &core->node_list, link) {
|
||||
const char *str;
|
||||
char *error;
|
||||
struct pw_node *node;
|
||||
struct pw_port *ip, *op;
|
||||
spa_list_for_each(n, &core->node_list, link) {
|
||||
const char *str;
|
||||
char *error;
|
||||
struct pw_node *node;
|
||||
struct pw_port *ip, *op;
|
||||
|
||||
if (n->global == NULL)
|
||||
continue;
|
||||
if (n->global == NULL)
|
||||
continue;
|
||||
|
||||
if (n->properties == NULL)
|
||||
continue;
|
||||
if (n->properties == NULL)
|
||||
continue;
|
||||
|
||||
if ((str = pw_properties_get (n->properties, "media.class")) == NULL)
|
||||
continue;
|
||||
if ((str = pw_properties_get(n->properties, "media.class")) == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp (str, "Audio/Sink") != 0)
|
||||
continue;
|
||||
if (strcmp(str, "Audio/Sink") != 0)
|
||||
continue;
|
||||
|
||||
if ((ip = pw_node_get_free_port (n, PW_DIRECTION_INPUT)) == NULL)
|
||||
continue;
|
||||
if ((ip = pw_node_get_free_port(n, PW_DIRECTION_INPUT)) == NULL)
|
||||
continue;
|
||||
|
||||
node = make_node (impl);
|
||||
op = pw_node_get_free_port (node, PW_DIRECTION_OUTPUT);
|
||||
if (op == NULL)
|
||||
continue;
|
||||
node = make_node(impl);
|
||||
op = pw_node_get_free_port(node, PW_DIRECTION_OUTPUT);
|
||||
if (op == NULL)
|
||||
continue;
|
||||
|
||||
pw_port_link (op, ip, NULL, NULL, &error);
|
||||
}
|
||||
return impl;
|
||||
pw_port_link(op, ip, NULL, NULL, &error);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
module_destroy (struct impl *impl)
|
||||
static void module_destroy(struct impl *impl)
|
||||
{
|
||||
pw_log_debug ("module %p: destroy", impl);
|
||||
pw_log_debug("module %p: destroy", impl);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
pipewire__module_init (struct pw_module * module, const char * args)
|
||||
bool pipewire__module_init(struct pw_module *module, const char *args)
|
||||
{
|
||||
module_new (module->core, NULL);
|
||||
return true;
|
||||
module_new(module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -52,422 +52,387 @@
|
|||
#define LOCK_SUFFIX ".lock"
|
||||
#define LOCK_SUFFIXLEN 5
|
||||
|
||||
typedef bool (*demarshal_func_t) (void *object, void *data, size_t size);
|
||||
typedef bool(*demarshal_func_t) (void *object, void *data, size_t size);
|
||||
|
||||
struct socket {
|
||||
int fd;
|
||||
int fd_lock;
|
||||
struct sockaddr_un addr;
|
||||
char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
|
||||
int fd;
|
||||
int fd_lock;
|
||||
struct sockaddr_un addr;
|
||||
char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
|
||||
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *source;
|
||||
char *core_name;
|
||||
struct spa_list link;
|
||||
struct pw_loop *loop;
|
||||
struct spa_source *source;
|
||||
char *core_name;
|
||||
struct spa_list link;
|
||||
};
|
||||
|
||||
struct impl {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
|
||||
struct pw_properties *properties;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct spa_list socket_list;
|
||||
struct spa_list client_list;
|
||||
struct spa_list socket_list;
|
||||
struct spa_list client_list;
|
||||
|
||||
struct pw_listener before_iterate;
|
||||
struct pw_listener before_iterate;
|
||||
};
|
||||
|
||||
struct native_client {
|
||||
struct impl *impl;
|
||||
struct spa_list link;
|
||||
struct pw_client *client;
|
||||
int fd;
|
||||
struct spa_source *source;
|
||||
struct pw_connection *connection;
|
||||
struct pw_listener resource_added;
|
||||
struct impl *impl;
|
||||
struct spa_list link;
|
||||
struct pw_client *client;
|
||||
int fd;
|
||||
struct spa_source *source;
|
||||
struct pw_connection *connection;
|
||||
struct pw_listener resource_added;
|
||||
};
|
||||
|
||||
static void
|
||||
client_destroy (struct native_client *this)
|
||||
static void client_destroy(struct native_client *this)
|
||||
{
|
||||
pw_loop_destroy_source (this->impl->core->main_loop->loop,
|
||||
this->source);
|
||||
pw_client_destroy (this->client);
|
||||
spa_list_remove (&this->link);
|
||||
pw_loop_destroy_source(this->impl->core->main_loop->loop, this->source);
|
||||
pw_client_destroy(this->client);
|
||||
spa_list_remove(&this->link);
|
||||
|
||||
pw_connection_destroy (this->connection);
|
||||
close (this->fd);
|
||||
free (this);
|
||||
pw_connection_destroy(this->connection);
|
||||
close(this->fd);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static void
|
||||
on_resource_added (struct pw_listener *listener,
|
||||
struct pw_client *client,
|
||||
struct pw_resource *resource)
|
||||
on_resource_added(struct pw_listener *listener,
|
||||
struct pw_client *client, struct pw_resource *resource)
|
||||
{
|
||||
pw_protocol_native_server_setup (resource);
|
||||
pw_protocol_native_server_setup(resource);
|
||||
}
|
||||
|
||||
static void on_before_iterate(struct pw_listener *listener, struct pw_loop *loop)
|
||||
{
|
||||
struct impl *this = SPA_CONTAINER_OF(listener, struct impl, before_iterate);
|
||||
struct native_client *client, *tmp;
|
||||
|
||||
spa_list_for_each_safe(client, tmp, &this->client_list, link)
|
||||
pw_connection_flush(client->connection);
|
||||
}
|
||||
|
||||
static void
|
||||
on_before_iterate (struct pw_listener *listener,
|
||||
struct pw_loop *loop)
|
||||
connection_data(struct spa_loop_utils *utils,
|
||||
struct spa_source *source, int fd, enum spa_io mask, void *data)
|
||||
{
|
||||
struct impl *this = SPA_CONTAINER_OF (listener, struct impl, before_iterate);
|
||||
struct native_client *client, *tmp;
|
||||
struct native_client *client = data;
|
||||
struct pw_connection *conn = client->connection;
|
||||
uint8_t opcode;
|
||||
uint32_t id;
|
||||
uint32_t size;
|
||||
struct pw_client *c = client->client;
|
||||
void *message;
|
||||
|
||||
spa_list_for_each_safe (client, tmp, &this->client_list, link)
|
||||
pw_connection_flush (client->connection);
|
||||
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
|
||||
pw_log_error("protocol-native %p: got connection error", client->impl);
|
||||
client_destroy(client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask & SPA_IO_IN) {
|
||||
while (pw_connection_get_next(conn, &opcode, &id, &message, &size)) {
|
||||
struct pw_resource *resource;
|
||||
const demarshal_func_t *demarshal;
|
||||
|
||||
pw_log_trace("protocol-native %p: got message %d from %u", client->impl,
|
||||
opcode, id);
|
||||
|
||||
resource = pw_map_lookup(&c->objects, id);
|
||||
if (resource == NULL) {
|
||||
pw_log_error("protocol-native %p: unknown resource %u",
|
||||
client->impl, id);
|
||||
continue;
|
||||
}
|
||||
if (opcode >= resource->iface->n_methods) {
|
||||
pw_log_error("protocol-native %p: invalid method %u", client->impl,
|
||||
opcode);
|
||||
client_destroy(client);
|
||||
break;
|
||||
}
|
||||
demarshal = resource->iface->methods;
|
||||
if (!demarshal[opcode] || !demarshal[opcode] (resource, message, size)) {
|
||||
pw_log_error("protocol-native %p: invalid message received",
|
||||
client->impl);
|
||||
client_destroy(client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct native_client *client_new(struct impl *impl, int fd)
|
||||
{
|
||||
struct native_client *this;
|
||||
struct pw_client *client;
|
||||
socklen_t len;
|
||||
struct ucred ucred, *ucredp;
|
||||
|
||||
this = calloc(1, sizeof(struct native_client));
|
||||
if (this == NULL)
|
||||
goto no_native_client;
|
||||
|
||||
this->impl = impl;
|
||||
this->fd = fd;
|
||||
this->source = pw_loop_add_io(impl->core->main_loop->loop,
|
||||
this->fd,
|
||||
SPA_IO_ERR | SPA_IO_HUP, false, connection_data, this);
|
||||
if (this->source == NULL)
|
||||
goto no_source;
|
||||
|
||||
this->connection = pw_connection_new(fd);
|
||||
if (this->connection == NULL)
|
||||
goto no_connection;
|
||||
|
||||
len = sizeof(ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
|
||||
pw_log_error("no peercred: %m");
|
||||
ucredp = NULL;
|
||||
} else {
|
||||
ucredp = &ucred;
|
||||
}
|
||||
|
||||
client = pw_client_new(impl->core, ucredp, NULL);
|
||||
if (client == NULL)
|
||||
goto no_client;
|
||||
|
||||
client->protocol_private = this->connection;
|
||||
|
||||
this->client = client;
|
||||
|
||||
spa_list_insert(impl->client_list.prev, &this->link);
|
||||
|
||||
pw_signal_add(&client->resource_added, &this->resource_added, on_resource_added);
|
||||
|
||||
pw_global_bind(impl->core->global, client, 0, 0);
|
||||
return this;
|
||||
|
||||
no_client:
|
||||
pw_connection_destroy(this->connection);
|
||||
no_connection:
|
||||
pw_loop_destroy_source(impl->core->main_loop->loop, this->source);
|
||||
no_source:
|
||||
free(this);
|
||||
no_native_client:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct socket *create_socket(void)
|
||||
{
|
||||
struct socket *s;
|
||||
|
||||
if ((s = calloc(1, sizeof(struct socket))) == NULL)
|
||||
return NULL;
|
||||
|
||||
s->fd = -1;
|
||||
s->fd_lock = -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void destroy_socket(struct socket *s)
|
||||
{
|
||||
if (s->source)
|
||||
pw_loop_destroy_source(s->loop, s->source);
|
||||
if (s->addr.sun_path[0])
|
||||
unlink(s->addr.sun_path);
|
||||
if (s->fd >= 0)
|
||||
close(s->fd);
|
||||
if (s->lock_addr[0])
|
||||
unlink(s->lock_addr);
|
||||
if (s->fd_lock >= 0)
|
||||
close(s->fd_lock);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static bool init_socket_name(struct socket *s, const char *name)
|
||||
{
|
||||
int name_size;
|
||||
const char *runtime_dir;
|
||||
|
||||
if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) {
|
||||
pw_log_error("XDG_RUNTIME_DIR not set in the environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
s->addr.sun_family = AF_LOCAL;
|
||||
name_size = snprintf(s->addr.sun_path, sizeof(s->addr.sun_path),
|
||||
"%s/%s", runtime_dir, name) + 1;
|
||||
|
||||
s->core_name = (s->addr.sun_path + name_size - 1) - strlen(name);
|
||||
|
||||
if (name_size > (int) sizeof(s->addr.sun_path)) {
|
||||
pw_log_error("socket path \"%s/%s\" plus null terminator exceeds 108 bytes",
|
||||
runtime_dir, name);
|
||||
*s->addr.sun_path = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lock_socket(struct socket *s)
|
||||
{
|
||||
struct stat socket_stat;
|
||||
|
||||
snprintf(s->lock_addr, sizeof(s->lock_addr), "%s%s", s->addr.sun_path, LOCK_SUFFIX);
|
||||
|
||||
s->fd_lock = open(s->lock_addr, O_CREAT | O_CLOEXEC,
|
||||
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
|
||||
|
||||
if (s->fd_lock < 0) {
|
||||
pw_log_error("unable to open lockfile %s check permissions", s->lock_addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (flock(s->fd_lock, LOCK_EX | LOCK_NB) < 0) {
|
||||
pw_log_error("unable to lock lockfile %s, maybe another daemon is running",
|
||||
s->lock_addr);
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
if (stat(s->addr.sun_path, &socket_stat) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
pw_log_error("did not manage to stat file %s\n", s->addr.sun_path);
|
||||
goto err_fd;
|
||||
}
|
||||
} else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) {
|
||||
unlink(s->addr.sun_path);
|
||||
}
|
||||
return true;
|
||||
|
||||
err_fd:
|
||||
close(s->fd_lock);
|
||||
s->fd_lock = -1;
|
||||
err:
|
||||
*s->lock_addr = 0;
|
||||
*s->addr.sun_path = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
connection_data (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
int fd,
|
||||
enum spa_io mask,
|
||||
void *data)
|
||||
socket_data(struct spa_loop_utils *utils,
|
||||
struct spa_source *source, int fd, enum spa_io mask, void *data)
|
||||
{
|
||||
struct native_client *client = data;
|
||||
struct pw_connection *conn = client->connection;
|
||||
uint8_t opcode;
|
||||
uint32_t id;
|
||||
uint32_t size;
|
||||
struct pw_client *c = client->client;
|
||||
void *message;
|
||||
struct impl *impl = data;
|
||||
struct native_client *client;
|
||||
struct sockaddr_un name;
|
||||
socklen_t length;
|
||||
int client_fd;
|
||||
|
||||
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
|
||||
pw_log_error ("protocol-native %p: got connection error", client->impl);
|
||||
client_destroy (client);
|
||||
return;
|
||||
}
|
||||
length = sizeof(name);
|
||||
client_fd = accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
|
||||
if (client_fd < 0) {
|
||||
pw_log_error("failed to accept: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask & SPA_IO_IN) {
|
||||
while (pw_connection_get_next (conn, &opcode, &id, &message, &size)) {
|
||||
struct pw_resource *resource;
|
||||
const demarshal_func_t *demarshal;
|
||||
client = client_new(impl, client_fd);
|
||||
if (client == NULL) {
|
||||
pw_log_error("failed to create client");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
pw_log_trace ("protocol-native %p: got message %d from %u", client->impl, opcode, id);
|
||||
|
||||
resource = pw_map_lookup (&c->objects, id);
|
||||
if (resource == NULL) {
|
||||
pw_log_error ("protocol-native %p: unknown resource %u", client->impl, id);
|
||||
continue;
|
||||
}
|
||||
if (opcode >= resource->iface->n_methods) {
|
||||
pw_log_error ("protocol-native %p: invalid method %u", client->impl, opcode);
|
||||
client_destroy (client);
|
||||
break;
|
||||
}
|
||||
demarshal = resource->iface->methods;
|
||||
if (!demarshal[opcode] || !demarshal[opcode] (resource, message, size)) {
|
||||
pw_log_error ("protocol-native %p: invalid message received", client->impl);
|
||||
client_destroy (client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pw_loop_update_io(impl->core->main_loop->loop,
|
||||
client->source, SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP);
|
||||
}
|
||||
|
||||
static struct native_client *
|
||||
client_new (struct impl *impl,
|
||||
int fd)
|
||||
static bool add_socket(struct impl *impl, struct socket *s)
|
||||
{
|
||||
struct native_client *this;
|
||||
struct pw_client *client;
|
||||
socklen_t len;
|
||||
struct ucred ucred, *ucredp;
|
||||
socklen_t size;
|
||||
|
||||
this = calloc (1, sizeof (struct native_client));
|
||||
if (this == NULL)
|
||||
goto no_native_client;
|
||||
if ((s->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0)
|
||||
return false;
|
||||
|
||||
this->impl = impl;
|
||||
this->fd = fd;
|
||||
this->source = pw_loop_add_io (impl->core->main_loop->loop,
|
||||
this->fd,
|
||||
SPA_IO_ERR | SPA_IO_HUP,
|
||||
false,
|
||||
connection_data,
|
||||
this);
|
||||
if (this->source == NULL)
|
||||
goto no_source;
|
||||
size = offsetof(struct sockaddr_un, sun_path) +strlen(s->addr.sun_path);
|
||||
if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
|
||||
pw_log_error("bind() failed with error: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->connection = pw_connection_new (fd);
|
||||
if (this->connection == NULL)
|
||||
goto no_connection;
|
||||
if (listen(s->fd, 128) < 0) {
|
||||
pw_log_error("listen() failed with error: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
len = sizeof (ucred);
|
||||
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
|
||||
pw_log_error ("no peercred: %m");
|
||||
ucredp = NULL;
|
||||
} else {
|
||||
ucredp = &ucred;
|
||||
}
|
||||
s->loop = impl->core->main_loop->loop;
|
||||
s->source = pw_loop_add_io(s->loop, s->fd, SPA_IO_IN, false, socket_data, impl);
|
||||
if (s->source == NULL)
|
||||
return false;
|
||||
|
||||
client = pw_client_new (impl->core, ucredp, NULL);
|
||||
if (client == NULL)
|
||||
goto no_client;
|
||||
spa_list_insert(impl->socket_list.prev, &s->link);
|
||||
|
||||
client->protocol_private = this->connection;
|
||||
|
||||
this->client = client;
|
||||
|
||||
spa_list_insert (impl->client_list.prev, &this->link);
|
||||
|
||||
pw_signal_add (&client->resource_added,
|
||||
&this->resource_added,
|
||||
on_resource_added);
|
||||
|
||||
pw_global_bind (impl->core->global,
|
||||
client,
|
||||
0,
|
||||
0);
|
||||
return this;
|
||||
|
||||
no_client:
|
||||
pw_connection_destroy (this->connection);
|
||||
no_connection:
|
||||
pw_loop_destroy_source (impl->core->main_loop->loop,
|
||||
this->source);
|
||||
no_source:
|
||||
free (this);
|
||||
no_native_client:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct socket *
|
||||
create_socket (void)
|
||||
{
|
||||
struct socket *s;
|
||||
|
||||
if ((s = calloc(1, sizeof (struct socket))) == NULL)
|
||||
return NULL;
|
||||
|
||||
s->fd = -1;
|
||||
s->fd_lock = -1;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_socket (struct socket *s)
|
||||
{
|
||||
if (s->source)
|
||||
pw_loop_destroy_source (s->loop, s->source);
|
||||
if (s->addr.sun_path[0])
|
||||
unlink (s->addr.sun_path);
|
||||
if (s->fd >= 0)
|
||||
close (s->fd);
|
||||
if (s->lock_addr[0])
|
||||
unlink (s->lock_addr);
|
||||
if (s->fd_lock >= 0)
|
||||
close (s->fd_lock);
|
||||
free (s);
|
||||
}
|
||||
|
||||
static bool
|
||||
init_socket_name (struct socket *s, const char *name)
|
||||
{
|
||||
int name_size;
|
||||
const char *runtime_dir;
|
||||
|
||||
if ((runtime_dir = getenv ("XDG_RUNTIME_DIR")) == NULL) {
|
||||
pw_log_error ("XDG_RUNTIME_DIR not set in the environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
s->addr.sun_family = AF_LOCAL;
|
||||
name_size = snprintf (s->addr.sun_path, sizeof (s->addr.sun_path),
|
||||
"%s/%s", runtime_dir, name) + 1;
|
||||
|
||||
s->core_name = (s->addr.sun_path + name_size - 1) - strlen (name);
|
||||
|
||||
if (name_size > (int)sizeof (s->addr.sun_path)) {
|
||||
pw_log_error ("socket path \"%s/%s\" plus null terminator exceeds 108 bytes",
|
||||
runtime_dir, name);
|
||||
*s->addr.sun_path = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
lock_socket (struct socket *s)
|
||||
{
|
||||
struct stat socket_stat;
|
||||
|
||||
snprintf (s->lock_addr, sizeof (s->lock_addr),
|
||||
"%s%s", s->addr.sun_path, LOCK_SUFFIX);
|
||||
|
||||
s->fd_lock = open (s->lock_addr, O_CREAT | O_CLOEXEC,
|
||||
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
|
||||
|
||||
if (s->fd_lock < 0) {
|
||||
pw_log_error ("unable to open lockfile %s check permissions", s->lock_addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (flock (s->fd_lock, LOCK_EX | LOCK_NB) < 0) {
|
||||
pw_log_error ("unable to lock lockfile %s, maybe another daemon is running", s->lock_addr);
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
if (stat (s->addr.sun_path, &socket_stat) < 0 ) {
|
||||
if (errno != ENOENT) {
|
||||
pw_log_error ("did not manage to stat file %s\n", s->addr.sun_path);
|
||||
goto err_fd;
|
||||
}
|
||||
} else if (socket_stat.st_mode & S_IWUSR ||
|
||||
socket_stat.st_mode & S_IWGRP) {
|
||||
unlink (s->addr.sun_path);
|
||||
}
|
||||
return true;
|
||||
|
||||
err_fd:
|
||||
close (s->fd_lock);
|
||||
s->fd_lock = -1;
|
||||
err:
|
||||
*s->lock_addr = 0;
|
||||
*s->addr.sun_path = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
socket_data (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
int fd,
|
||||
enum spa_io mask,
|
||||
void *data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
struct native_client *client;
|
||||
struct sockaddr_un name;
|
||||
socklen_t length;
|
||||
int client_fd;
|
||||
|
||||
length = sizeof (name);
|
||||
client_fd = accept4 (fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
|
||||
if (client_fd < 0) {
|
||||
pw_log_error ("failed to accept: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
client = client_new (impl, client_fd);
|
||||
if (client == NULL) {
|
||||
pw_log_error ("failed to create client");
|
||||
close (client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
pw_loop_update_io (impl->core->main_loop->loop,
|
||||
client->source,
|
||||
SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP);
|
||||
}
|
||||
|
||||
static bool
|
||||
add_socket (struct impl *impl, struct socket *s)
|
||||
{
|
||||
socklen_t size;
|
||||
|
||||
if ((s->fd = socket (PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0)
|
||||
return false;
|
||||
|
||||
size = offsetof (struct sockaddr_un, sun_path) + strlen (s->addr.sun_path);
|
||||
if (bind (s->fd, (struct sockaddr *) &s->addr, size) < 0) {
|
||||
pw_log_error ("bind() failed with error: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listen (s->fd, 128) < 0) {
|
||||
pw_log_error ("listen() failed with error: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
s->loop = impl->core->main_loop->loop;
|
||||
s->source = pw_loop_add_io (s->loop,
|
||||
s->fd,
|
||||
SPA_IO_IN,
|
||||
false,
|
||||
socket_data,
|
||||
impl);
|
||||
if (s->source == NULL)
|
||||
return false;
|
||||
|
||||
spa_list_insert (impl->socket_list.prev, &s->link);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static struct impl *
|
||||
pw_protocol_native_new (struct pw_core *core,
|
||||
struct pw_properties *properties)
|
||||
static struct impl *pw_protocol_native_new(struct pw_core *core, struct pw_properties *properties)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct socket *s;
|
||||
const char *name;
|
||||
struct impl *impl;
|
||||
struct socket *s;
|
||||
const char *name;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
pw_log_debug ("protocol-native %p: new", impl);
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
pw_log_debug("protocol-native %p: new", impl);
|
||||
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
|
||||
name = NULL;
|
||||
if (impl->properties)
|
||||
name = pw_properties_get (impl->properties, "pipewire.core.name");
|
||||
if (name == NULL)
|
||||
name = getenv ("PIPEWIRE_CORE");
|
||||
if (name == NULL)
|
||||
name = "pipewire-0";
|
||||
name = NULL;
|
||||
if (impl->properties)
|
||||
name = pw_properties_get(impl->properties, "pipewire.core.name");
|
||||
if (name == NULL)
|
||||
name = getenv("PIPEWIRE_CORE");
|
||||
if (name == NULL)
|
||||
name = "pipewire-0";
|
||||
|
||||
s = create_socket ();
|
||||
s = create_socket();
|
||||
|
||||
spa_list_init (&impl->socket_list);
|
||||
spa_list_init (&impl->client_list);
|
||||
spa_list_init(&impl->socket_list);
|
||||
spa_list_init(&impl->client_list);
|
||||
|
||||
if (!init_socket_name (s, name))
|
||||
goto error;
|
||||
if (!init_socket_name(s, name))
|
||||
goto error;
|
||||
|
||||
if (!lock_socket (s))
|
||||
goto error;
|
||||
if (!lock_socket(s))
|
||||
goto error;
|
||||
|
||||
if (!add_socket (impl, s))
|
||||
goto error;
|
||||
if (!add_socket(impl, s))
|
||||
goto error;
|
||||
|
||||
pw_signal_add (&impl->core->main_loop->loop->before_iterate,
|
||||
&impl->before_iterate,
|
||||
on_before_iterate);
|
||||
pw_signal_add(&impl->core->main_loop->loop->before_iterate,
|
||||
&impl->before_iterate, on_before_iterate);
|
||||
|
||||
return impl;
|
||||
return impl;
|
||||
|
||||
error:
|
||||
destroy_socket (s);
|
||||
free (impl);
|
||||
return NULL;
|
||||
error:
|
||||
destroy_socket(s);
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
pw_protocol_native_destroy (struct impl *impl)
|
||||
static void pw_protocol_native_destroy(struct impl *impl)
|
||||
{
|
||||
struct impl *object, *tmp;
|
||||
struct impl *object, *tmp;
|
||||
|
||||
pw_log_debug ("protocol-native %p: destroy", impl);
|
||||
pw_log_debug("protocol-native %p: destroy", impl);
|
||||
|
||||
pw_signal_remove (&impl->before_iterate);
|
||||
pw_signal_remove(&impl->before_iterate);
|
||||
|
||||
pw_global_destroy (impl->global);
|
||||
pw_global_destroy(impl->global);
|
||||
|
||||
spa_list_for_each_safe (object, tmp, &impl->object_list, link)
|
||||
object_destroy (object);
|
||||
spa_list_for_each_safe(object, tmp, &impl->object_list, link)
|
||||
object_destroy(object);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
pipewire__module_init (struct pw_module * module, const char * args)
|
||||
bool pipewire__module_init(struct pw_module *module, const char *args)
|
||||
{
|
||||
pw_protocol_native_new (module->core, NULL);
|
||||
return true;
|
||||
pw_protocol_native_new(module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,142 +27,126 @@
|
|||
#include "pipewire/server/module.h"
|
||||
|
||||
struct impl {
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
struct pw_core *core;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct pw_listener global_added;
|
||||
struct pw_listener global_removed;
|
||||
struct pw_listener global_added;
|
||||
struct pw_listener global_removed;
|
||||
|
||||
struct spa_list node_list;
|
||||
struct spa_list node_list;
|
||||
};
|
||||
|
||||
struct node_info {
|
||||
struct impl *impl;
|
||||
struct pw_node *node;
|
||||
struct spa_list link;
|
||||
struct pw_listener node_state_request;
|
||||
struct pw_listener node_state_changed;
|
||||
struct spa_source *idle_timeout;
|
||||
struct impl *impl;
|
||||
struct pw_node *node;
|
||||
struct spa_list link;
|
||||
struct pw_listener node_state_request;
|
||||
struct pw_listener node_state_changed;
|
||||
struct spa_source *idle_timeout;
|
||||
};
|
||||
|
||||
static struct node_info *
|
||||
find_node_info (struct impl *impl, struct pw_node *node)
|
||||
static struct node_info *find_node_info(struct impl *impl, struct pw_node *node)
|
||||
{
|
||||
struct node_info *info;
|
||||
struct node_info *info;
|
||||
|
||||
spa_list_for_each (info, &impl->node_list, link) {
|
||||
if (info->node == node)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
spa_list_for_each(info, &impl->node_list, link) {
|
||||
if (info->node == node)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void remove_idle_timeout(struct node_info *info)
|
||||
{
|
||||
if (info->idle_timeout) {
|
||||
pw_loop_destroy_source(info->impl->core->main_loop->loop, info->idle_timeout);
|
||||
info->idle_timeout = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void node_info_free(struct node_info *info)
|
||||
{
|
||||
spa_list_remove(&info->link);
|
||||
remove_idle_timeout(info);
|
||||
pw_signal_remove(&info->node_state_request);
|
||||
pw_signal_remove(&info->node_state_changed);
|
||||
free(info);
|
||||
}
|
||||
|
||||
static void idle_timeout(struct spa_loop_utils *utils, struct spa_source *source, void *data)
|
||||
{
|
||||
struct node_info *info = data;
|
||||
|
||||
pw_log_debug("module %p: node %p idle timeout", info->impl, info->node);
|
||||
remove_idle_timeout(info);
|
||||
pw_node_set_state(info->node, PW_NODE_STATE_SUSPENDED);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_idle_timeout (struct node_info *info)
|
||||
on_node_state_request(struct pw_listener *listener, struct pw_node *node, enum pw_node_state state)
|
||||
{
|
||||
if (info->idle_timeout) {
|
||||
pw_loop_destroy_source (info->impl->core->main_loop->loop, info->idle_timeout);
|
||||
info->idle_timeout = NULL;
|
||||
}
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, node_state_request);
|
||||
remove_idle_timeout(info);
|
||||
}
|
||||
|
||||
static void
|
||||
node_info_free (struct node_info *info)
|
||||
on_node_state_changed(struct pw_listener *listener,
|
||||
struct pw_node *node, enum pw_node_state old, enum pw_node_state state)
|
||||
{
|
||||
spa_list_remove (&info->link);
|
||||
remove_idle_timeout (info);
|
||||
pw_signal_remove (&info->node_state_request);
|
||||
pw_signal_remove (&info->node_state_changed);
|
||||
free (info);
|
||||
struct node_info *info = SPA_CONTAINER_OF(listener, struct node_info, node_state_changed);
|
||||
struct impl *impl = info->impl;
|
||||
|
||||
if (state != PW_NODE_STATE_IDLE) {
|
||||
remove_idle_timeout(info);
|
||||
} else {
|
||||
struct timespec value;
|
||||
|
||||
pw_log_debug("module %p: node %p became idle", impl, node);
|
||||
info->idle_timeout = pw_loop_add_timer(impl->core->main_loop->loop,
|
||||
idle_timeout, info);
|
||||
value.tv_sec = 3;
|
||||
value.tv_nsec = 0;
|
||||
pw_loop_update_timer(impl->core->main_loop->loop,
|
||||
info->idle_timeout, &value, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
idle_timeout (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
void *data)
|
||||
on_global_added(struct pw_listener *listener, struct pw_core *core, struct pw_global *global)
|
||||
{
|
||||
struct node_info *info = data;
|
||||
struct impl *impl = SPA_CONTAINER_OF(listener, struct impl, global_added);
|
||||
|
||||
pw_log_debug ("module %p: node %p idle timeout", info->impl, info->node);
|
||||
remove_idle_timeout (info);
|
||||
pw_node_set_state (info->node, PW_NODE_STATE_SUSPENDED);
|
||||
if (global->type == impl->core->type.node) {
|
||||
struct pw_node *node = global->object;
|
||||
struct node_info *info;
|
||||
|
||||
info = calloc(1, sizeof(struct node_info));
|
||||
info->impl = impl;
|
||||
info->node = node;
|
||||
spa_list_insert(impl->node_list.prev, &info->link);
|
||||
pw_signal_add(&node->state_request, &info->node_state_request,
|
||||
on_node_state_request);
|
||||
pw_signal_add(&node->state_changed, &info->node_state_changed,
|
||||
on_node_state_changed);
|
||||
|
||||
pw_log_debug("module %p: node %p added", impl, node);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_state_request (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
enum pw_node_state state)
|
||||
on_global_removed(struct pw_listener *listener, struct pw_core *core, struct pw_global *global)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, node_state_request);
|
||||
remove_idle_timeout (info);
|
||||
}
|
||||
struct impl *impl = SPA_CONTAINER_OF(listener, struct impl, global_removed);
|
||||
|
||||
static void
|
||||
on_node_state_changed (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
enum pw_node_state old,
|
||||
enum pw_node_state state)
|
||||
{
|
||||
struct node_info *info = SPA_CONTAINER_OF (listener, struct node_info, node_state_changed);
|
||||
struct impl *impl = info->impl;
|
||||
if (global->type == impl->core->type.node) {
|
||||
struct pw_node *node = global->object;
|
||||
struct node_info *info;
|
||||
|
||||
if (state != PW_NODE_STATE_IDLE) {
|
||||
remove_idle_timeout (info);
|
||||
} else {
|
||||
struct timespec value;
|
||||
if ((info = find_node_info(impl, node)))
|
||||
node_info_free(info);
|
||||
|
||||
pw_log_debug ("module %p: node %p became idle", impl, node);
|
||||
info->idle_timeout = pw_loop_add_timer (impl->core->main_loop->loop,
|
||||
idle_timeout,
|
||||
info);
|
||||
value.tv_sec = 3;
|
||||
value.tv_nsec = 0;
|
||||
pw_loop_update_timer (impl->core->main_loop->loop,
|
||||
info->idle_timeout,
|
||||
&value,
|
||||
NULL,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_global_added (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (listener, struct impl, global_added);
|
||||
|
||||
if (global->type == impl->core->type.node) {
|
||||
struct pw_node *node = global->object;
|
||||
struct node_info *info;
|
||||
|
||||
info = calloc (1, sizeof (struct node_info));
|
||||
info->impl = impl;
|
||||
info->node = node;
|
||||
spa_list_insert (impl->node_list.prev, &info->link);
|
||||
pw_signal_add (&node->state_request, &info->node_state_request, on_node_state_request);
|
||||
pw_signal_add (&node->state_changed, &info->node_state_changed, on_node_state_changed);
|
||||
|
||||
pw_log_debug ("module %p: node %p added", impl, node);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_global_removed (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (listener, struct impl, global_removed);
|
||||
|
||||
if (global->type == impl->core->type.node) {
|
||||
struct pw_node *node = global->object;
|
||||
struct node_info *info;
|
||||
|
||||
if ((info = find_node_info (impl, node)))
|
||||
node_info_free (info);
|
||||
|
||||
pw_log_debug ("module %p: node %p removed", impl, node);
|
||||
}
|
||||
pw_log_debug("module %p: node %p removed", impl, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -175,41 +159,37 @@ on_global_removed (struct pw_listener *listener,
|
|||
*
|
||||
* Returns: a new #struct impl
|
||||
*/
|
||||
static struct impl *
|
||||
module_new (struct pw_core *core,
|
||||
struct pw_properties *properties)
|
||||
static struct impl *module_new(struct pw_core *core, struct pw_properties *properties)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct impl *impl;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
pw_log_debug ("module %p: new", impl);
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
pw_log_debug("module %p: new", impl);
|
||||
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
|
||||
spa_list_init (&impl->node_list);
|
||||
spa_list_init(&impl->node_list);
|
||||
|
||||
pw_signal_add (&core->global_added, &impl->global_added, on_global_added);
|
||||
pw_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
|
||||
pw_signal_add(&core->global_added, &impl->global_added, on_global_added);
|
||||
pw_signal_add(&core->global_removed, &impl->global_removed, on_global_removed);
|
||||
|
||||
return impl;
|
||||
return impl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
module_destroy (struct impl *impl)
|
||||
static void module_destroy(struct impl *impl)
|
||||
{
|
||||
pw_log_debug ("module %p: destroy", impl);
|
||||
pw_log_debug("module %p: destroy", impl);
|
||||
|
||||
pw_global_destroy (impl->global);
|
||||
pw_global_destroy(impl->global);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
pipewire__module_init (struct pw_module * module, const char * args)
|
||||
bool pipewire__module_init(struct pw_module *module, const char *args)
|
||||
{
|
||||
module_new (module->core, NULL);
|
||||
return true;
|
||||
module_new(module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,111 +31,105 @@
|
|||
#include "spa-node.h"
|
||||
|
||||
static int
|
||||
setup_video_node (struct pw_core *core, struct spa_node *spa_node, struct pw_properties *pw_props) {
|
||||
int res;
|
||||
struct spa_props *props;
|
||||
struct spa_pod_prop *prop;
|
||||
const char *pattern, *pattern_type;
|
||||
|
||||
/* Retrieve pattern property */
|
||||
pattern = pw_properties_get (pw_props, "pattern");
|
||||
if (strcmp (pattern, "smpte-snow") == 0) {
|
||||
pattern_type = SPA_TYPE_PROPS__patternType ":smpte-snow";
|
||||
} else if (strcmp (pattern, "snow") == 0) {
|
||||
pattern_type = SPA_TYPE_PROPS__patternType ":snow";
|
||||
} else {
|
||||
pw_log_debug ("Unrecognized pattern");
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if ((res = spa_node_get_props (spa_node, &props)) != SPA_RESULT_OK) {
|
||||
pw_log_debug ("spa_node_get_props failed: %d", res);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if ((prop = spa_pod_object_find_prop (&props->object, spa_type_map_get_id (core->type.map, SPA_TYPE_PROPS__patternType)))) {
|
||||
if (prop->body.value.type == SPA_POD_TYPE_ID)
|
||||
SPA_POD_VALUE (struct spa_pod_id, &prop->body.value) = spa_type_map_get_id (core->type.map, pattern_type);
|
||||
}
|
||||
|
||||
if ((res = spa_node_set_props (spa_node, props)) != SPA_RESULT_OK) {
|
||||
pw_log_debug ("spa_node_set_props failed: %d", res);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
pipewire__module_init (struct pw_module * module, const char * args)
|
||||
setup_video_node(struct pw_core *core, struct spa_node *spa_node, struct pw_properties *pw_props)
|
||||
{
|
||||
struct pw_properties *video_props = NULL, *audio_props = NULL;
|
||||
int res;
|
||||
struct spa_props *props;
|
||||
struct spa_pod_prop *prop;
|
||||
const char *pattern, *pattern_type;
|
||||
|
||||
if (args != NULL) {
|
||||
char **tmp_argv;
|
||||
char **argv;
|
||||
int n_tokens;
|
||||
int opt = 0;
|
||||
/* Retrieve pattern property */
|
||||
pattern = pw_properties_get(pw_props, "pattern");
|
||||
if (strcmp(pattern, "smpte-snow") == 0) {
|
||||
pattern_type = SPA_TYPE_PROPS__patternType ":smpte-snow";
|
||||
} else if (strcmp(pattern, "snow") == 0) {
|
||||
pattern_type = SPA_TYPE_PROPS__patternType ":snow";
|
||||
} else {
|
||||
pw_log_debug("Unrecognized pattern");
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
tmp_argv = pw_split_strv (args, " \t", INT_MAX, &n_tokens);
|
||||
if ((res = spa_node_get_props(spa_node, &props)) != SPA_RESULT_OK) {
|
||||
pw_log_debug("spa_node_get_props failed: %d", res);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
argv = malloc ((n_tokens+1) * sizeof (char *));
|
||||
/* getopt expects name of executable on the first place of argv */
|
||||
argv[0] = "videotestsrc";
|
||||
if ((prop =
|
||||
spa_pod_object_find_prop(&props->object,
|
||||
spa_type_map_get_id(core->type.map,
|
||||
SPA_TYPE_PROPS__patternType)))) {
|
||||
if (prop->body.value.type == SPA_POD_TYPE_ID)
|
||||
SPA_POD_VALUE(struct spa_pod_id, &prop->body.value) =
|
||||
spa_type_map_get_id(core->type.map, pattern_type);
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n_tokens; i++) {
|
||||
argv[i] = tmp_argv[i-1];
|
||||
}
|
||||
if ((res = spa_node_set_props(spa_node, props)) != SPA_RESULT_OK) {
|
||||
pw_log_debug("spa_node_set_props failed: %d", res);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
video_props = pw_properties_new ("media.class", "Video/Source", NULL);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"filter", required_argument, 0, 'f' },
|
||||
{"pattern", required_argument, 0, 'p' },
|
||||
{"resolution", required_argument, 0, 'r' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long (n_tokens+1, argv, "p:r:f:", long_options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
pw_properties_set (video_props, "filter", optarg);
|
||||
break;
|
||||
case 'p':
|
||||
pw_properties_set (video_props, "pattern", optarg);
|
||||
break;
|
||||
case 'r':
|
||||
pw_properties_set (video_props, "resolution", optarg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free (argv);
|
||||
pw_free_strv (tmp_argv);
|
||||
}
|
||||
|
||||
pw_spa_monitor_load (module->core,
|
||||
"build/spa/plugins/alsa/libspa-alsa.so",
|
||||
"alsa-monitor",
|
||||
"alsa");
|
||||
pw_spa_monitor_load (module->core,
|
||||
"build/spa/plugins/v4l2/libspa-v4l2.so",
|
||||
"v4l2-monitor",
|
||||
"v4l2");
|
||||
audio_props = pw_properties_new ("media.class", "Audio/Source", NULL);
|
||||
pw_spa_node_load (module->core,
|
||||
"build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so",
|
||||
"audiotestsrc",
|
||||
"audiotestsrc",
|
||||
audio_props,
|
||||
NULL);
|
||||
pw_spa_node_load (module->core,
|
||||
"build/spa/plugins/videotestsrc/libspa-videotestsrc.so",
|
||||
"videotestsrc",
|
||||
"videotestsrc",
|
||||
video_props,
|
||||
setup_video_node);
|
||||
|
||||
return true;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
bool pipewire__module_init(struct pw_module * module, const char *args)
|
||||
{
|
||||
struct pw_properties *video_props = NULL, *audio_props = NULL;
|
||||
|
||||
if (args != NULL) {
|
||||
char **tmp_argv;
|
||||
char **argv;
|
||||
int n_tokens;
|
||||
int opt = 0;
|
||||
|
||||
tmp_argv = pw_split_strv(args, " \t", INT_MAX, &n_tokens);
|
||||
|
||||
argv = malloc((n_tokens + 1) * sizeof(char *));
|
||||
/* getopt expects name of executable on the first place of argv */
|
||||
argv[0] = "videotestsrc";
|
||||
|
||||
for (int i = 1; i <= n_tokens; i++) {
|
||||
argv[i] = tmp_argv[i - 1];
|
||||
}
|
||||
|
||||
video_props = pw_properties_new("media.class", "Video/Source", NULL);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"filter", required_argument, 0, 'f'},
|
||||
{"pattern", required_argument, 0, 'p'},
|
||||
{"resolution", required_argument, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(n_tokens + 1, argv, "p:r:f:", long_options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
pw_properties_set(video_props, "filter", optarg);
|
||||
break;
|
||||
case 'p':
|
||||
pw_properties_set(video_props, "pattern", optarg);
|
||||
break;
|
||||
case 'r':
|
||||
pw_properties_set(video_props, "resolution", optarg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(argv);
|
||||
pw_free_strv(tmp_argv);
|
||||
}
|
||||
|
||||
pw_spa_monitor_load(module->core,
|
||||
"build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor", "alsa");
|
||||
pw_spa_monitor_load(module->core,
|
||||
"build/spa/plugins/v4l2/libspa-v4l2.so", "v4l2-monitor", "v4l2");
|
||||
audio_props = pw_properties_new("media.class", "Audio/Source", NULL);
|
||||
pw_spa_node_load(module->core,
|
||||
"build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so",
|
||||
"audiotestsrc", "audiotestsrc", audio_props, NULL);
|
||||
pw_spa_node_load(module->core,
|
||||
"build/spa/plugins/videotestsrc/libspa-videotestsrc.so",
|
||||
"videotestsrc", "videotestsrc", video_props, setup_video_node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,303 +34,273 @@
|
|||
|
||||
#include "spa-monitor.h"
|
||||
|
||||
struct monitor_item
|
||||
{
|
||||
char *id;
|
||||
struct spa_list link;
|
||||
struct pw_node *node;
|
||||
struct monitor_item {
|
||||
char *id;
|
||||
struct spa_list link;
|
||||
struct pw_node *node;
|
||||
};
|
||||
|
||||
struct impl {
|
||||
struct pw_spa_monitor this;
|
||||
struct pw_spa_monitor this;
|
||||
|
||||
struct pw_core *core;
|
||||
struct pw_core *core;
|
||||
|
||||
void *hnd;
|
||||
void *hnd;
|
||||
|
||||
struct spa_list item_list;
|
||||
struct spa_list item_list;
|
||||
};
|
||||
|
||||
static void
|
||||
add_item (struct pw_spa_monitor *this, struct spa_monitor_item *item)
|
||||
static void add_item(struct pw_spa_monitor *this, struct spa_monitor_item *item)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (this, struct impl, this);
|
||||
int res;
|
||||
struct spa_handle *handle;
|
||||
struct monitor_item *mitem;
|
||||
void *node_iface;
|
||||
void *clock_iface;
|
||||
struct pw_properties *props = NULL;
|
||||
const char *name, *id, *klass;
|
||||
struct spa_handle_factory *factory;
|
||||
struct spa_pod *info = NULL;
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
int res;
|
||||
struct spa_handle *handle;
|
||||
struct monitor_item *mitem;
|
||||
void *node_iface;
|
||||
void *clock_iface;
|
||||
struct pw_properties *props = NULL;
|
||||
const char *name, *id, *klass;
|
||||
struct spa_handle_factory *factory;
|
||||
struct spa_pod *info = NULL;
|
||||
|
||||
spa_pod_object_query (&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name,
|
||||
impl->core->type.monitor.id, SPA_POD_TYPE_STRING, &id,
|
||||
impl->core->type.monitor.klass, SPA_POD_TYPE_STRING, &klass,
|
||||
impl->core->type.monitor.factory, SPA_POD_TYPE_POINTER, &factory,
|
||||
impl->core->type.monitor.info, SPA_POD_TYPE_STRUCT, &info,
|
||||
0);
|
||||
spa_pod_object_query(&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name,
|
||||
impl->core->type.monitor.id, SPA_POD_TYPE_STRING, &id,
|
||||
impl->core->type.monitor.klass, SPA_POD_TYPE_STRING, &klass,
|
||||
impl->core->type.monitor.factory, SPA_POD_TYPE_POINTER, &factory,
|
||||
impl->core->type.monitor.info, SPA_POD_TYPE_STRUCT, &info, 0);
|
||||
|
||||
pw_log_debug ("monitor %p: add: \"%s\" (%s)", this, name, id);
|
||||
pw_log_debug("monitor %p: add: \"%s\" (%s)", this, name, id);
|
||||
|
||||
props = pw_properties_new (NULL, NULL);
|
||||
props = pw_properties_new(NULL, NULL);
|
||||
|
||||
if (info) {
|
||||
struct spa_pod_iter it;
|
||||
if (info) {
|
||||
struct spa_pod_iter it;
|
||||
|
||||
spa_pod_iter_pod (&it, info);
|
||||
while (true) {
|
||||
const char *key, *val;
|
||||
if (!spa_pod_iter_get (&it, SPA_POD_TYPE_STRING, &key, SPA_POD_TYPE_STRING, &val, 0))
|
||||
break;
|
||||
pw_properties_set (props, key, val);
|
||||
}
|
||||
}
|
||||
pw_properties_set (props, "media.class", klass);
|
||||
spa_pod_iter_pod(&it, info);
|
||||
while (true) {
|
||||
const char *key, *val;
|
||||
if (!spa_pod_iter_get
|
||||
(&it, SPA_POD_TYPE_STRING, &key, SPA_POD_TYPE_STRING, &val, 0))
|
||||
break;
|
||||
pw_properties_set(props, key, val);
|
||||
}
|
||||
}
|
||||
pw_properties_set(props, "media.class", klass);
|
||||
|
||||
handle = calloc (1, factory->size);
|
||||
if ((res = spa_handle_factory_init (factory,
|
||||
handle,
|
||||
&props->dict,
|
||||
impl->core->support,
|
||||
impl->core->n_support)) < 0) {
|
||||
pw_log_error ("can't make factory instance: %d", res);
|
||||
return;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle, impl->core->type.spa_node, &node_iface)) < 0) {
|
||||
pw_log_error ("can't get NODE interface: %d", res);
|
||||
return;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle, impl->core->type.spa_clock, &clock_iface)) < 0) {
|
||||
pw_log_info ("no CLOCK interface: %d", res);
|
||||
}
|
||||
handle = calloc(1, factory->size);
|
||||
if ((res = spa_handle_factory_init(factory,
|
||||
handle,
|
||||
&props->dict,
|
||||
impl->core->support, impl->core->n_support)) < 0) {
|
||||
pw_log_error("can't make factory instance: %d", res);
|
||||
return;
|
||||
}
|
||||
if ((res = spa_handle_get_interface(handle, impl->core->type.spa_node, &node_iface)) < 0) {
|
||||
pw_log_error("can't get NODE interface: %d", res);
|
||||
return;
|
||||
}
|
||||
if ((res = spa_handle_get_interface(handle, impl->core->type.spa_clock, &clock_iface)) < 0) {
|
||||
pw_log_info("no CLOCK interface: %d", res);
|
||||
}
|
||||
|
||||
|
||||
mitem = calloc (1, sizeof (struct monitor_item));
|
||||
mitem->id = strdup (id);
|
||||
mitem->node = pw_node_new (impl->core,
|
||||
NULL,
|
||||
name,
|
||||
false,
|
||||
node_iface,
|
||||
clock_iface,
|
||||
props);
|
||||
mitem = calloc(1, sizeof(struct monitor_item));
|
||||
mitem->id = strdup(id);
|
||||
mitem->node = pw_node_new(impl->core, NULL, name, false, node_iface, clock_iface, props);
|
||||
|
||||
spa_list_insert (impl->item_list.prev, &mitem->link);
|
||||
spa_list_insert(impl->item_list.prev, &mitem->link);
|
||||
}
|
||||
|
||||
static struct monitor_item *
|
||||
find_item (struct pw_spa_monitor *this,
|
||||
const char *id)
|
||||
static struct monitor_item *find_item(struct pw_spa_monitor *this, const char *id)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (this, struct impl, this);
|
||||
struct monitor_item *mitem;
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
struct monitor_item *mitem;
|
||||
|
||||
spa_list_for_each (mitem, &impl->item_list, link) {
|
||||
if (strcmp (mitem->id, id) == 0) {
|
||||
return mitem;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
spa_list_for_each(mitem, &impl->item_list, link) {
|
||||
if (strcmp(mitem->id, id) == 0) {
|
||||
return mitem;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
destroy_item (struct monitor_item *mitem)
|
||||
void destroy_item(struct monitor_item *mitem)
|
||||
{
|
||||
pw_node_destroy (mitem->node);
|
||||
spa_list_remove (&mitem->link);
|
||||
free (mitem->id);
|
||||
free (mitem);
|
||||
pw_node_destroy(mitem->node);
|
||||
spa_list_remove(&mitem->link);
|
||||
free(mitem->id);
|
||||
free(mitem);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_item (struct pw_spa_monitor *this, struct spa_monitor_item *item)
|
||||
static void remove_item(struct pw_spa_monitor *this, struct spa_monitor_item *item)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (this, struct impl, this);
|
||||
struct monitor_item *mitem;
|
||||
const char *name, *id;
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
struct monitor_item *mitem;
|
||||
const char *name, *id;
|
||||
|
||||
spa_pod_object_query (&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name,
|
||||
impl->core->type.monitor.id, SPA_POD_TYPE_STRING, &id,
|
||||
0);
|
||||
spa_pod_object_query(&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name,
|
||||
impl->core->type.monitor.id, SPA_POD_TYPE_STRING, &id, 0);
|
||||
|
||||
pw_log_debug ("monitor %p: remove: \"%s\" (%s)", this, name, id);
|
||||
mitem = find_item (this, id);
|
||||
if (mitem)
|
||||
destroy_item (mitem);
|
||||
pw_log_debug("monitor %p: remove: \"%s\" (%s)", this, name, id);
|
||||
mitem = find_item(this, id);
|
||||
if (mitem)
|
||||
destroy_item(mitem);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitor_event (struct spa_monitor *monitor,
|
||||
struct spa_event *event,
|
||||
void *user_data)
|
||||
static void on_monitor_event(struct spa_monitor *monitor, struct spa_event *event, void *user_data)
|
||||
{
|
||||
struct pw_spa_monitor *this = user_data;
|
||||
struct impl *impl = SPA_CONTAINER_OF (this, struct impl, this);
|
||||
struct pw_spa_monitor *this = user_data;
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
|
||||
if (SPA_EVENT_TYPE (event) == impl->core->type.monitor.Added) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS (struct spa_event, event);
|
||||
add_item (this, item);
|
||||
}
|
||||
else if (SPA_EVENT_TYPE (event) == impl->core->type.monitor.Removed) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS (struct spa_event, event);
|
||||
remove_item (this, item);
|
||||
}
|
||||
else if (SPA_EVENT_TYPE (event) == impl->core->type.monitor.Changed) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS (struct spa_event, event);
|
||||
const char *name;
|
||||
if (SPA_EVENT_TYPE(event) == impl->core->type.monitor.Added) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS(struct spa_event, event);
|
||||
add_item(this, item);
|
||||
} else if (SPA_EVENT_TYPE(event) == impl->core->type.monitor.Removed) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS(struct spa_event, event);
|
||||
remove_item(this, item);
|
||||
} else if (SPA_EVENT_TYPE(event) == impl->core->type.monitor.Changed) {
|
||||
struct spa_monitor_item *item = SPA_POD_CONTENTS(struct spa_event, event);
|
||||
const char *name;
|
||||
|
||||
spa_pod_object_query (&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name,
|
||||
0);
|
||||
spa_pod_object_query(&item->object,
|
||||
impl->core->type.monitor.name, SPA_POD_TYPE_STRING, &name, 0);
|
||||
|
||||
pw_log_debug ("monitor %p: changed: \"%s\"", this, name);
|
||||
}
|
||||
pw_log_debug("monitor %p: changed: \"%s\"", this, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_monitor (struct pw_core *core,
|
||||
const char *name)
|
||||
static void update_monitor(struct pw_core *core, const char *name)
|
||||
{
|
||||
const char *monitors;
|
||||
struct spa_dict_item item;
|
||||
struct spa_dict dict = SPA_DICT_INIT(1, &item);
|
||||
const char *monitors;
|
||||
struct spa_dict_item item;
|
||||
struct spa_dict dict = SPA_DICT_INIT(1, &item);
|
||||
|
||||
if (core->properties)
|
||||
monitors = pw_properties_get (core->properties, "monitors");
|
||||
else
|
||||
monitors = NULL;
|
||||
if (core->properties)
|
||||
monitors = pw_properties_get(core->properties, "monitors");
|
||||
else
|
||||
monitors = NULL;
|
||||
|
||||
item.key = "monitors";
|
||||
if (monitors == NULL)
|
||||
item.value = name;
|
||||
else
|
||||
asprintf ((char**)&item.value, "%s,%s", monitors, name);
|
||||
item.key = "monitors";
|
||||
if (monitors == NULL)
|
||||
item.value = name;
|
||||
else
|
||||
asprintf((char **) &item.value, "%s,%s", monitors, name);
|
||||
|
||||
pw_core_update_properties (core, &dict);
|
||||
pw_core_update_properties(core, &dict);
|
||||
|
||||
if (monitors != NULL)
|
||||
free ((void*)item.value);
|
||||
if (monitors != NULL)
|
||||
free((void *) item.value);
|
||||
}
|
||||
|
||||
static const struct spa_monitor_callbacks callbacks = {
|
||||
on_monitor_event,
|
||||
on_monitor_event,
|
||||
};
|
||||
|
||||
struct pw_spa_monitor *
|
||||
pw_spa_monitor_load (struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *system_name)
|
||||
struct pw_spa_monitor *pw_spa_monitor_load(struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name, const char *system_name)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_spa_monitor *this;
|
||||
struct spa_handle *handle;
|
||||
int res;
|
||||
void *iface;
|
||||
void *hnd;
|
||||
uint32_t index;
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
const struct spa_handle_factory *factory;
|
||||
struct impl *impl;
|
||||
struct pw_spa_monitor *this;
|
||||
struct spa_handle *handle;
|
||||
int res;
|
||||
void *iface;
|
||||
void *hnd;
|
||||
uint32_t index;
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
const struct spa_handle_factory *factory;
|
||||
|
||||
if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) {
|
||||
pw_log_error ("can't load %s: %s", lib, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym (hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error ("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
if ((hnd = dlopen(lib, RTLD_NOW)) == NULL) {
|
||||
pw_log_error("can't load %s: %s", lib, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
|
||||
for (index = 0;; index++) {
|
||||
if ((res = enum_func (&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error ("can't enumerate factories: %d", 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,
|
||||
core->support,
|
||||
core->n_support)) < 0) {
|
||||
pw_log_error ("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
core->type.spa_monitor,
|
||||
&iface)) < 0) {
|
||||
free (handle);
|
||||
pw_log_error ("can't get MONITOR interface: %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
for (index = 0;; index++) {
|
||||
if ((res = enum_func(&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error("can't enumerate factories: %d", 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, core->support, core->n_support)) < 0) {
|
||||
pw_log_error("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface(handle, core->type.spa_monitor, &iface)) < 0) {
|
||||
free(handle);
|
||||
pw_log_error("can't get MONITOR interface: %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
impl->core = core;
|
||||
impl->hnd = hnd;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
impl->core = core;
|
||||
impl->hnd = hnd;
|
||||
|
||||
this = &impl->this;
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
this->monitor = iface;
|
||||
this->lib = strdup (lib);
|
||||
this->factory_name = strdup (factory_name);
|
||||
this->system_name = strdup (system_name);
|
||||
this->handle = handle;
|
||||
this = &impl->this;
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
this->monitor = iface;
|
||||
this->lib = strdup(lib);
|
||||
this->factory_name = strdup(factory_name);
|
||||
this->system_name = strdup(system_name);
|
||||
this->handle = handle;
|
||||
|
||||
update_monitor (core, this->system_name);
|
||||
update_monitor(core, this->system_name);
|
||||
|
||||
spa_list_init (&impl->item_list);
|
||||
spa_list_init(&impl->item_list);
|
||||
|
||||
for (index = 0;; index++) {
|
||||
struct spa_monitor_item *item;
|
||||
int res;
|
||||
for (index = 0;; index++) {
|
||||
struct spa_monitor_item *item;
|
||||
int res;
|
||||
|
||||
if ((res = spa_monitor_enum_items (this->monitor, &item, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_debug ("spa_monitor_enum_items: got error %d\n", res);
|
||||
break;
|
||||
}
|
||||
add_item (this, item);
|
||||
}
|
||||
spa_monitor_set_callbacks (this->monitor, &callbacks, sizeof (callbacks), this);
|
||||
if ((res = spa_monitor_enum_items(this->monitor, &item, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_debug("spa_monitor_enum_items: got error %d\n", res);
|
||||
break;
|
||||
}
|
||||
add_item(this, item);
|
||||
}
|
||||
spa_monitor_set_callbacks(this->monitor, &callbacks, sizeof(callbacks), this);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
interface_failed:
|
||||
spa_handle_clear (handle);
|
||||
init_failed:
|
||||
free (handle);
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose (hnd);
|
||||
return NULL;
|
||||
interface_failed:
|
||||
spa_handle_clear(handle);
|
||||
init_failed:
|
||||
free(handle);
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose(hnd);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
pw_spa_monitor_destroy (struct pw_spa_monitor * monitor)
|
||||
void pw_spa_monitor_destroy(struct pw_spa_monitor *monitor)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (monitor, struct impl, this);
|
||||
struct monitor_item *mitem, *tmp;
|
||||
struct impl *impl = SPA_CONTAINER_OF(monitor, struct impl, this);
|
||||
struct monitor_item *mitem, *tmp;
|
||||
|
||||
pw_log_debug ("spa-monitor %p: dispose", impl);
|
||||
pw_signal_emit (&monitor->destroy_signal, monitor);
|
||||
pw_log_debug("spa-monitor %p: dispose", impl);
|
||||
pw_signal_emit(&monitor->destroy_signal, monitor);
|
||||
|
||||
spa_list_for_each_safe (mitem, tmp, &impl->item_list, link)
|
||||
destroy_item (mitem);
|
||||
spa_list_for_each_safe(mitem, tmp, &impl->item_list, link)
|
||||
destroy_item(mitem);
|
||||
|
||||
spa_handle_clear (monitor->handle);
|
||||
free (monitor->handle);
|
||||
free (monitor->lib);
|
||||
free (monitor->factory_name);
|
||||
free (monitor->system_name);
|
||||
spa_handle_clear(monitor->handle);
|
||||
free(monitor->handle);
|
||||
free(monitor->lib);
|
||||
free(monitor->factory_name);
|
||||
free(monitor->system_name);
|
||||
|
||||
dlclose (impl->hnd);
|
||||
free (impl);
|
||||
dlclose(impl->hnd);
|
||||
free(impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,21 +28,22 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct pw_spa_monitor {
|
||||
struct spa_monitor *monitor;
|
||||
struct spa_monitor *monitor;
|
||||
|
||||
char *lib;
|
||||
char *factory_name;
|
||||
char *system_name;
|
||||
struct spa_handle *handle;
|
||||
char *lib;
|
||||
char *factory_name;
|
||||
char *system_name;
|
||||
struct spa_handle *handle;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener, struct pw_spa_monitor *monitor));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_spa_monitor * monitor));
|
||||
};
|
||||
|
||||
struct pw_spa_monitor * pw_spa_monitor_load (struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *system_name);
|
||||
void pw_spa_monitor_destroy (struct pw_spa_monitor *monitor);
|
||||
struct pw_spa_monitor *
|
||||
pw_spa_monitor_load(struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name, const char *system_name);
|
||||
void
|
||||
pw_spa_monitor_destroy(struct pw_spa_monitor *monitor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,123 +26,107 @@
|
|||
#include "spa-node.h"
|
||||
|
||||
struct impl {
|
||||
struct pw_spa_node this;
|
||||
struct pw_core *core;
|
||||
struct pw_spa_node this;
|
||||
struct pw_core *core;
|
||||
|
||||
void *hnd;
|
||||
void *hnd;
|
||||
};
|
||||
|
||||
struct pw_spa_node *
|
||||
pw_spa_node_load (struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
struct pw_properties *properties,
|
||||
setup_node_t setup_func)
|
||||
struct pw_spa_node *pw_spa_node_load(struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
struct pw_properties *properties, setup_node_t setup_func)
|
||||
{
|
||||
struct pw_spa_node *this;
|
||||
struct impl *impl;
|
||||
struct spa_node *spa_node;
|
||||
struct spa_clock *spa_clock;
|
||||
int res;
|
||||
struct spa_handle *handle;
|
||||
void *hnd;
|
||||
uint32_t index;
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
const struct spa_handle_factory *factory;
|
||||
void *iface;
|
||||
struct pw_spa_node *this;
|
||||
struct impl *impl;
|
||||
struct spa_node *spa_node;
|
||||
struct spa_clock *spa_clock;
|
||||
int res;
|
||||
struct spa_handle *handle;
|
||||
void *hnd;
|
||||
uint32_t index;
|
||||
spa_handle_factory_enum_func_t enum_func;
|
||||
const struct spa_handle_factory *factory;
|
||||
void *iface;
|
||||
|
||||
if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) {
|
||||
pw_log_error ("can't load %s: %s", lib, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym (hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error ("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
if ((hnd = dlopen(lib, RTLD_NOW)) == NULL) {
|
||||
pw_log_error("can't load %s: %s", lib, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
|
||||
pw_log_error("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
|
||||
for (index = 0; ; index++) {
|
||||
if ((res = enum_func (&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error ("can't enumerate factories: %d", res);
|
||||
goto enum_failed;
|
||||
}
|
||||
if (strcmp (factory->name, factory_name) == 0)
|
||||
break;
|
||||
}
|
||||
for (index = 0;; index++) {
|
||||
if ((res = enum_func(&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pw_log_error("can't enumerate factories: %d", 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,
|
||||
core->support,
|
||||
core->n_support)) < 0) {
|
||||
pw_log_error ("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
core->type.spa_node,
|
||||
&iface)) < 0) {
|
||||
pw_log_error ("can't get interface %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
spa_node = iface;
|
||||
handle = calloc(1, factory->size);
|
||||
if ((res = spa_handle_factory_init(factory,
|
||||
handle, NULL, core->support, core->n_support)) < 0) {
|
||||
pw_log_error("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface(handle, core->type.spa_node, &iface)) < 0) {
|
||||
pw_log_error("can't get interface %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
spa_node = iface;
|
||||
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
core->type.spa_clock,
|
||||
&iface)) < 0) {
|
||||
iface = NULL;
|
||||
}
|
||||
spa_clock = iface;
|
||||
if ((res = spa_handle_get_interface(handle, core->type.spa_clock, &iface)) < 0) {
|
||||
iface = NULL;
|
||||
}
|
||||
spa_clock = iface;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
impl->core = core;
|
||||
impl->hnd = hnd;
|
||||
this = &impl->this;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
impl->core = core;
|
||||
impl->hnd = hnd;
|
||||
this = &impl->this;
|
||||
|
||||
if (setup_func != NULL) {
|
||||
if (setup_func (core, spa_node, properties) != SPA_RESULT_OK) {
|
||||
pw_log_debug ("Unrecognized properties");
|
||||
}
|
||||
}
|
||||
if (setup_func != NULL) {
|
||||
if (setup_func(core, spa_node, properties) != SPA_RESULT_OK) {
|
||||
pw_log_debug("Unrecognized properties");
|
||||
}
|
||||
}
|
||||
|
||||
this->node = pw_node_new (core,
|
||||
NULL,
|
||||
name,
|
||||
false,
|
||||
spa_node,
|
||||
spa_clock,
|
||||
properties);
|
||||
this->lib = strdup (lib);
|
||||
this->factory_name = strdup (factory_name);
|
||||
this->handle = handle;
|
||||
this->node = pw_node_new(core, NULL, name, false, spa_node, spa_clock, properties);
|
||||
this->lib = strdup(lib);
|
||||
this->factory_name = strdup(factory_name);
|
||||
this->handle = handle;
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
interface_failed:
|
||||
spa_handle_clear (handle);
|
||||
init_failed:
|
||||
free (handle);
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose (hnd);
|
||||
return NULL;
|
||||
interface_failed:
|
||||
spa_handle_clear(handle);
|
||||
init_failed:
|
||||
free(handle);
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose(hnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_spa_node_destroy (struct pw_spa_node * node)
|
||||
void pw_spa_node_destroy(struct pw_spa_node *node)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (node, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
||||
|
||||
pw_log_debug ("spa-node %p: destroy", impl);
|
||||
pw_signal_emit (&node->destroy_signal, node);
|
||||
pw_log_debug("spa-node %p: destroy", impl);
|
||||
pw_signal_emit(&node->destroy_signal, node);
|
||||
|
||||
pw_node_destroy (node->node);
|
||||
pw_node_destroy(node->node);
|
||||
|
||||
spa_handle_clear (node->handle);
|
||||
free (node->handle);
|
||||
free (node->lib);
|
||||
free (node->factory_name);
|
||||
dlclose (impl->hnd);
|
||||
free (impl);
|
||||
spa_handle_clear(node->handle);
|
||||
free(node->handle);
|
||||
free(node->lib);
|
||||
free(node->factory_name);
|
||||
dlclose(impl->hnd);
|
||||
free(impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,25 +28,24 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct pw_spa_node {
|
||||
struct pw_node *node;
|
||||
struct pw_node *node;
|
||||
|
||||
char *lib;
|
||||
char *factory_name;
|
||||
struct spa_handle *handle;
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_spa_node *node));
|
||||
char *lib;
|
||||
char *factory_name;
|
||||
struct spa_handle *handle;
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_spa_node * node));
|
||||
};
|
||||
|
||||
typedef int (*setup_node_t) (struct pw_core *core,
|
||||
struct spa_node *spa_node,
|
||||
struct pw_properties *pw_props);
|
||||
typedef int (*setup_node_t) (struct pw_core * core,
|
||||
struct spa_node * spa_node, struct pw_properties * pw_props);
|
||||
|
||||
struct pw_spa_node * pw_spa_node_load (struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
struct pw_properties *properties,
|
||||
setup_node_t setup_func);
|
||||
struct pw_spa_node *
|
||||
pw_spa_node_load(struct pw_core *core,
|
||||
const char *lib,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
struct pw_properties *properties,
|
||||
setup_node_t setup_func);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ extern "C" {
|
|||
#include <pipewire/server/resource.h>
|
||||
|
||||
struct pw_access_data {
|
||||
int res;
|
||||
struct pw_resource *resource;
|
||||
int res;
|
||||
struct pw_resource *resource;
|
||||
|
||||
void * (*async_copy) (struct pw_access_data *data, size_t size);
|
||||
void (*complete_cb) (struct pw_access_data *data);
|
||||
void (*free_cb) (struct pw_access_data *data);
|
||||
void * user_data;
|
||||
void *(*async_copy) (struct pw_access_data * data, size_t size);
|
||||
void (*complete_cb) (struct pw_access_data * data);
|
||||
void (*free_cb) (struct pw_access_data * data);
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -48,18 +48,15 @@ struct pw_access_data {
|
|||
* PipeWire Access support struct.
|
||||
*/
|
||||
struct pw_access {
|
||||
int (*view_global) (struct pw_access *access,
|
||||
struct pw_client *client,
|
||||
struct pw_global *global);
|
||||
int (*create_node) (struct pw_access *access,
|
||||
struct pw_access_data *data,
|
||||
const char *factory_name,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
int (*create_client_node) (struct pw_access *access,
|
||||
struct pw_access_data *data,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
int (*view_global) (struct pw_access * access,
|
||||
struct pw_client * client, struct pw_global * global);
|
||||
int (*create_node) (struct pw_access * access,
|
||||
struct pw_access_data * data,
|
||||
const char *factory_name,
|
||||
const char *name, struct pw_properties * properties);
|
||||
int (*create_client_node) (struct pw_access * access,
|
||||
struct pw_access_data * data,
|
||||
const char *name, struct pw_properties * properties);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -35,24 +35,25 @@ extern "C" {
|
|||
* PipeWire client node interface
|
||||
*/
|
||||
struct pw_client_node {
|
||||
struct pw_node *node;
|
||||
struct pw_node *node;
|
||||
|
||||
struct pw_client *client;
|
||||
struct pw_resource *resource;
|
||||
struct pw_client *client;
|
||||
struct pw_resource *resource;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_client_node *node));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_client_node * node));
|
||||
};
|
||||
|
||||
struct pw_client_node * pw_client_node_new (struct pw_client *client,
|
||||
uint32_t id,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
void pw_client_node_destroy (struct pw_client_node *node);
|
||||
struct pw_client_node *
|
||||
pw_client_node_new(struct pw_client *client,
|
||||
uint32_t id,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
|
||||
int pw_client_node_get_fds (struct pw_client_node *node,
|
||||
int *readfd,
|
||||
int *writefd);
|
||||
void
|
||||
pw_client_node_destroy(struct pw_client_node *node);
|
||||
|
||||
int
|
||||
pw_client_node_get_fds(struct pw_client_node *node, int *readfd, int *writefd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,51 +25,40 @@
|
|||
#include "pipewire/server/client.h"
|
||||
#include "pipewire/server/resource.h"
|
||||
|
||||
struct impl
|
||||
{
|
||||
struct pw_client this;
|
||||
struct impl {
|
||||
struct pw_client this;
|
||||
};
|
||||
|
||||
static void
|
||||
client_unbind_func (void *data)
|
||||
static void client_unbind_func(void *data)
|
||||
{
|
||||
struct pw_resource *resource = data;
|
||||
spa_list_remove (&resource->link);
|
||||
struct pw_resource *resource = data;
|
||||
spa_list_remove(&resource->link);
|
||||
}
|
||||
|
||||
static int
|
||||
client_bind_func (struct pw_global *global,
|
||||
struct pw_client *client,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
client_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id)
|
||||
{
|
||||
struct pw_client *this = global->object;
|
||||
struct pw_resource *resource;
|
||||
struct pw_client *this = global->object;
|
||||
struct pw_resource *resource;
|
||||
|
||||
resource = pw_resource_new (client,
|
||||
id,
|
||||
global->type,
|
||||
global->object,
|
||||
client_unbind_func);
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
resource = pw_resource_new(client, id, global->type, global->object, client_unbind_func);
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
|
||||
pw_log_debug ("client %p: bound to %d", global->object, resource->id);
|
||||
pw_log_debug("client %p: bound to %d", global->object, resource->id);
|
||||
|
||||
spa_list_insert (this->resource_list.prev, &resource->link);
|
||||
spa_list_insert(this->resource_list.prev, &resource->link);
|
||||
|
||||
this->info.change_mask = ~0;
|
||||
pw_client_notify_info (resource, &this->info);
|
||||
this->info.change_mask = ~0;
|
||||
pw_client_notify_info(resource, &this->info);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
no_mem:
|
||||
pw_log_error ("can't create client resource");
|
||||
pw_core_notify_error (client->core_resource,
|
||||
client->core_resource->id,
|
||||
SPA_RESULT_NO_MEMORY,
|
||||
"no memory");
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
no_mem:
|
||||
pw_log_error("can't create client resource");
|
||||
pw_core_notify_error(client->core_resource,
|
||||
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,56 +70,46 @@ no_mem:
|
|||
*
|
||||
* Returns: a new #struct pw_client
|
||||
*/
|
||||
struct pw_client *
|
||||
pw_client_new (struct pw_core *core,
|
||||
struct ucred *ucred,
|
||||
struct pw_properties *properties)
|
||||
struct pw_client *pw_client_new(struct pw_core *core,
|
||||
struct ucred *ucred, struct pw_properties *properties)
|
||||
{
|
||||
struct pw_client *this;
|
||||
struct impl *impl;
|
||||
struct pw_client *this;
|
||||
struct impl *impl;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_log_debug ("client %p: new", impl);
|
||||
pw_log_debug("client %p: new", impl);
|
||||
|
||||
this = &impl->this;
|
||||
this->core = core;
|
||||
if ((this->ucred_valid = (ucred != NULL)))
|
||||
this->ucred = *ucred;
|
||||
this->properties = properties;
|
||||
this = &impl->this;
|
||||
this->core = core;
|
||||
if ((this->ucred_valid = (ucred != NULL)))
|
||||
this->ucred = *ucred;
|
||||
this->properties = properties;
|
||||
|
||||
spa_list_init (&this->resource_list);
|
||||
pw_signal_init (&this->properties_changed);
|
||||
pw_signal_init (&this->resource_added);
|
||||
pw_signal_init (&this->resource_removed);
|
||||
spa_list_init(&this->resource_list);
|
||||
pw_signal_init(&this->properties_changed);
|
||||
pw_signal_init(&this->resource_added);
|
||||
pw_signal_init(&this->resource_removed);
|
||||
|
||||
pw_map_init (&this->objects, 0, 32);
|
||||
pw_map_init (&this->types, 0, 32);
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_map_init(&this->objects, 0, 32);
|
||||
pw_map_init(&this->types, 0, 32);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
spa_list_insert (core->client_list.prev, &this->link);
|
||||
spa_list_insert(core->client_list.prev, &this->link);
|
||||
|
||||
pw_core_add_global (core,
|
||||
this,
|
||||
core->type.client,
|
||||
0,
|
||||
this,
|
||||
client_bind_func,
|
||||
&this->global);
|
||||
pw_core_add_global(core, this, core->type.client, 0, this, client_bind_func, &this->global);
|
||||
|
||||
this->info.id = this->global->id;
|
||||
this->info.props = this->properties ? &this->properties->dict : NULL;
|
||||
this->info.id = this->global->id;
|
||||
this->info.props = this->properties ? &this->properties->dict : NULL;
|
||||
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_resource (void *object,
|
||||
void *data)
|
||||
static void destroy_resource(void *object, void *data)
|
||||
{
|
||||
pw_resource_destroy (object);
|
||||
pw_resource_destroy(object);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -139,56 +118,52 @@ destroy_resource (void *object,
|
|||
*
|
||||
* Trigger removal of @client
|
||||
*/
|
||||
void
|
||||
pw_client_destroy (struct pw_client * client)
|
||||
void pw_client_destroy(struct pw_client *client)
|
||||
{
|
||||
struct pw_resource *resource, *tmp;
|
||||
struct impl *impl = SPA_CONTAINER_OF (client, struct impl, this);
|
||||
struct pw_resource *resource, *tmp;
|
||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||
|
||||
pw_log_debug ("client %p: destroy", client);
|
||||
pw_signal_emit (&client->destroy_signal, client);
|
||||
pw_log_debug("client %p: destroy", client);
|
||||
pw_signal_emit(&client->destroy_signal, client);
|
||||
|
||||
spa_list_remove (&client->link);
|
||||
pw_global_destroy (client->global);
|
||||
spa_list_remove(&client->link);
|
||||
pw_global_destroy(client->global);
|
||||
|
||||
spa_list_for_each_safe (resource, tmp, &client->resource_list, link)
|
||||
pw_resource_destroy (resource);
|
||||
spa_list_for_each_safe(resource, tmp, &client->resource_list, link)
|
||||
pw_resource_destroy(resource);
|
||||
|
||||
pw_map_for_each (&client->objects, destroy_resource, client);
|
||||
pw_map_for_each(&client->objects, destroy_resource, client);
|
||||
|
||||
pw_log_debug ("client %p: free", impl);
|
||||
pw_map_clear (&client->objects);
|
||||
pw_log_debug("client %p: free", impl);
|
||||
pw_map_clear(&client->objects);
|
||||
|
||||
if (client->properties)
|
||||
pw_properties_free (client->properties);
|
||||
if (client->properties)
|
||||
pw_properties_free(client->properties);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
void
|
||||
pw_client_update_properties (struct pw_client *client,
|
||||
const struct spa_dict *dict)
|
||||
void pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict)
|
||||
{
|
||||
struct pw_resource *resource;
|
||||
struct pw_resource *resource;
|
||||
|
||||
if (client->properties == NULL) {
|
||||
if (dict)
|
||||
client->properties = pw_properties_new_dict (dict);
|
||||
} else {
|
||||
uint32_t i;
|
||||
if (client->properties == NULL) {
|
||||
if (dict)
|
||||
client->properties = pw_properties_new_dict(dict);
|
||||
} else {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dict->n_items; i++)
|
||||
pw_properties_set (client->properties,
|
||||
dict->items[i].key,
|
||||
dict->items[i].value);
|
||||
}
|
||||
for (i = 0; i < dict->n_items; i++)
|
||||
pw_properties_set(client->properties,
|
||||
dict->items[i].key, dict->items[i].value);
|
||||
}
|
||||
|
||||
client->info.change_mask = 1 << 0;
|
||||
client->info.props = client->properties ? &client->properties->dict : NULL;
|
||||
client->info.change_mask = 1 << 0;
|
||||
client->info.props = client->properties ? &client->properties->dict : NULL;
|
||||
|
||||
pw_signal_emit (&client->properties_changed, client);
|
||||
pw_signal_emit(&client->properties_changed, client);
|
||||
|
||||
spa_list_for_each (resource, &client->resource_list, link) {
|
||||
pw_client_notify_info (resource, &client->info);
|
||||
}
|
||||
spa_list_for_each(resource, &client->resource_list, link) {
|
||||
pw_client_notify_info(resource, &client->info);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,45 +39,43 @@ extern "C" {
|
|||
* PipeWire client object class.
|
||||
*/
|
||||
struct pw_client {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
|
||||
struct pw_properties *properties;
|
||||
PW_SIGNAL (properties_changed, (struct pw_listener *listener,
|
||||
struct pw_client *client));
|
||||
struct pw_properties *properties;
|
||||
PW_SIGNAL(properties_changed, (struct pw_listener * listener, struct pw_client * client));
|
||||
|
||||
struct pw_client_info info;
|
||||
bool ucred_valid;
|
||||
struct ucred ucred;
|
||||
struct pw_client_info info;
|
||||
bool ucred_valid;
|
||||
struct ucred ucred;
|
||||
|
||||
void *protocol_private;
|
||||
void *protocol_private;
|
||||
|
||||
struct pw_resource *core_resource;
|
||||
struct pw_resource *core_resource;
|
||||
|
||||
struct pw_map objects;
|
||||
uint32_t n_types;
|
||||
struct pw_map types;
|
||||
struct pw_map objects;
|
||||
uint32_t n_types;
|
||||
struct pw_map types;
|
||||
|
||||
struct spa_list resource_list;
|
||||
PW_SIGNAL (resource_added, (struct pw_listener *listener,
|
||||
struct pw_client *client,
|
||||
struct pw_resource *resource));
|
||||
PW_SIGNAL (resource_removed, (struct pw_listener *listener,
|
||||
struct pw_client *client,
|
||||
struct pw_resource *resource));
|
||||
struct spa_list resource_list;
|
||||
PW_SIGNAL(resource_added, (struct pw_listener * listener,
|
||||
struct pw_client * client, struct pw_resource * resource));
|
||||
PW_SIGNAL(resource_removed, (struct pw_listener * listener,
|
||||
struct pw_client * client, struct pw_resource * resource));
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_client *client));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_client * client));
|
||||
};
|
||||
|
||||
struct pw_client * pw_client_new (struct pw_core *core,
|
||||
struct ucred *ucred,
|
||||
struct pw_properties *properties);
|
||||
void pw_client_destroy (struct pw_client *client);
|
||||
struct pw_client *
|
||||
pw_client_new(struct pw_core *core,
|
||||
struct ucred *ucred, struct pw_properties *properties);
|
||||
|
||||
void pw_client_update_properties (struct pw_client *client,
|
||||
const struct spa_dict *dict);
|
||||
void
|
||||
pw_client_destroy(struct pw_client *client);
|
||||
|
||||
void
|
||||
pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,80 +26,68 @@
|
|||
|
||||
#include "command.h"
|
||||
|
||||
typedef bool (*pw_command_func_t) (struct pw_command *command,
|
||||
struct pw_core *core,
|
||||
char **err);
|
||||
typedef bool(*pw_command_func_t) (struct pw_command * command, struct pw_core * core, char **err);
|
||||
|
||||
static bool execute_command_module_load (struct pw_command *command,
|
||||
struct pw_core *core,
|
||||
char **err);
|
||||
static bool execute_command_module_load(struct pw_command *command,
|
||||
struct pw_core *core, char **err);
|
||||
|
||||
typedef struct pw_command * (*pw_command_parse_func_t) (const char *line,
|
||||
char **err);
|
||||
typedef struct pw_command *(*pw_command_parse_func_t) (const char *line, char **err);
|
||||
|
||||
static struct pw_command * parse_command_module_load (const char *line,
|
||||
char **err);
|
||||
static struct pw_command *parse_command_module_load(const char *line, char **err);
|
||||
|
||||
struct impl {
|
||||
struct pw_command this;
|
||||
struct pw_command this;
|
||||
|
||||
pw_command_func_t func;
|
||||
char **args;
|
||||
int n_args;
|
||||
pw_command_func_t func;
|
||||
char **args;
|
||||
int n_args;
|
||||
};
|
||||
|
||||
struct command_parse
|
||||
{
|
||||
const char *name;
|
||||
pw_command_parse_func_t func;
|
||||
struct command_parse {
|
||||
const char *name;
|
||||
pw_command_parse_func_t func;
|
||||
};
|
||||
|
||||
static const struct command_parse parsers[] = {
|
||||
{"load-module", parse_command_module_load},
|
||||
{NULL, NULL}
|
||||
{"load-module", parse_command_module_load},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const char whitespace[] = " \t";
|
||||
|
||||
static struct pw_command *
|
||||
parse_command_module_load (const char * line, char ** err)
|
||||
static struct pw_command *parse_command_module_load(const char *line, char **err)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct impl *impl;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
goto no_mem;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
goto no_mem;
|
||||
|
||||
impl->func = execute_command_module_load;
|
||||
impl->args = pw_split_strv (line, whitespace, 3, &impl->n_args);
|
||||
impl->func = execute_command_module_load;
|
||||
impl->args = pw_split_strv(line, whitespace, 3, &impl->n_args);
|
||||
|
||||
if (impl->args[1] == NULL)
|
||||
goto no_module;
|
||||
if (impl->args[1] == NULL)
|
||||
goto no_module;
|
||||
|
||||
impl->this.name = impl->args[0];
|
||||
impl->this.name = impl->args[0];
|
||||
|
||||
return &impl->this;
|
||||
return &impl->this;
|
||||
|
||||
no_module:
|
||||
asprintf (err, "%s requires a module name", impl->args[0]);
|
||||
pw_free_strv (impl->args);
|
||||
return NULL;
|
||||
no_mem:
|
||||
asprintf (err, "no memory");
|
||||
return NULL;
|
||||
no_module:
|
||||
asprintf(err, "%s requires a module name", impl->args[0]);
|
||||
pw_free_strv(impl->args);
|
||||
return NULL;
|
||||
no_mem:
|
||||
asprintf(err, "no memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_command_module_load (struct pw_command *command,
|
||||
struct pw_core *core,
|
||||
char **err)
|
||||
execute_command_module_load(struct pw_command *command, struct pw_core *core, char **err)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (command, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(command, struct impl, this);
|
||||
|
||||
return pw_module_load (core,
|
||||
impl->args[1],
|
||||
impl->args[2],
|
||||
err) != NULL;
|
||||
return pw_module_load(core, impl->args[1], impl->args[2], err) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -108,14 +96,13 @@ execute_command_module_load (struct pw_command *command,
|
|||
*
|
||||
* Free all resources assicated with @command.
|
||||
*/
|
||||
void
|
||||
pw_command_free (struct pw_command * command)
|
||||
void pw_command_free(struct pw_command *command)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (command, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(command, struct impl, this);
|
||||
|
||||
spa_list_remove (&command->link);
|
||||
pw_free_strv (impl->args);
|
||||
free (impl);
|
||||
spa_list_remove(&command->link);
|
||||
pw_free_strv(impl->args);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,30 +115,28 @@ pw_command_free (struct pw_command * command)
|
|||
*
|
||||
* Returns: The command or %NULL when @err is set.
|
||||
*/
|
||||
struct pw_command *
|
||||
pw_command_parse (const char *line,
|
||||
char **err)
|
||||
struct pw_command *pw_command_parse(const char *line, char **err)
|
||||
{
|
||||
struct pw_command *command = NULL;
|
||||
const struct command_parse *parse;
|
||||
char *name;
|
||||
size_t len;
|
||||
struct pw_command *command = NULL;
|
||||
const struct command_parse *parse;
|
||||
char *name;
|
||||
size_t len;
|
||||
|
||||
len = strcspn (line, whitespace);
|
||||
len = strcspn(line, whitespace);
|
||||
|
||||
name = strndup (line, len);
|
||||
name = strndup(line, len);
|
||||
|
||||
for (parse = parsers; parse->name != NULL; parse++) {
|
||||
if (strcmp (name, parse->name) == 0) {
|
||||
command = parse->func (line, err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
for (parse = parsers; parse->name != NULL; parse++) {
|
||||
if (strcmp(name, parse->name) == 0) {
|
||||
command = parse->func(line, err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
asprintf (err, "Command \"%s\" does not exist", name);
|
||||
out:
|
||||
free (name);
|
||||
return command;
|
||||
asprintf(err, "Command \"%s\" does not exist", name);
|
||||
out:
|
||||
free(name);
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -164,14 +149,11 @@ out:
|
|||
*
|
||||
* Returns: %true if @command was executed successfully, %false otherwise.
|
||||
*/
|
||||
bool
|
||||
pw_command_run (struct pw_command *command,
|
||||
struct pw_core *core,
|
||||
char **err)
|
||||
bool pw_command_run(struct pw_command * command, struct pw_core * core, char **err)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (command, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(command, struct impl, this);
|
||||
|
||||
return impl->func (command, core, err);
|
||||
return impl->func(command, core, err);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,10 +164,9 @@ pw_command_run (struct pw_command *command,
|
|||
*
|
||||
* Returns: The name of @command.
|
||||
*/
|
||||
const char *
|
||||
pw_command_get_name (struct pw_command * command)
|
||||
const char *pw_command_get_name(struct pw_command *command)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (command, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(command, struct impl, this);
|
||||
|
||||
return impl->args[0];
|
||||
return impl->args[0];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,18 +28,21 @@ extern "C" {
|
|||
#include <pipewire/server/core.h>
|
||||
|
||||
struct pw_command {
|
||||
struct spa_list link;
|
||||
struct spa_list link;
|
||||
|
||||
const char *name;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
||||
struct pw_command * pw_command_parse (const char *line,
|
||||
char **err);
|
||||
void pw_command_free (struct pw_command *command);
|
||||
bool pw_command_run (struct pw_command *command,
|
||||
struct pw_core *core,
|
||||
char **err);
|
||||
struct pw_command *
|
||||
pw_command_parse(const char *line, char **err);
|
||||
|
||||
void
|
||||
pw_command_free(struct pw_command *command);
|
||||
|
||||
bool
|
||||
pw_command_run(struct pw_command *command, struct pw_core *core, char **err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -36,23 +36,20 @@ struct pw_global;
|
|||
#include <pipewire/server/link.h>
|
||||
#include <pipewire/server/node-factory.h>
|
||||
|
||||
typedef int (*pw_bind_func_t) (struct pw_global *global,
|
||||
struct pw_client *client,
|
||||
uint32_t version,
|
||||
uint32_t id);
|
||||
typedef int (*pw_bind_func_t) (struct pw_global * global,
|
||||
struct pw_client * client, uint32_t version, uint32_t id);
|
||||
|
||||
struct pw_global {
|
||||
struct pw_core *core;
|
||||
struct pw_client *owner;
|
||||
struct pw_core *core;
|
||||
struct pw_client *owner;
|
||||
|
||||
struct spa_list link;
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
uint32_t version;
|
||||
void *object;
|
||||
struct spa_list link;
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
uint32_t version;
|
||||
void *object;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_global *global));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_global * global));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -61,81 +58,83 @@ struct pw_global {
|
|||
* PipeWire core object class.
|
||||
*/
|
||||
struct pw_core {
|
||||
struct pw_global *global;
|
||||
struct pw_global *global;
|
||||
|
||||
struct pw_core_info info;
|
||||
struct pw_core_info info;
|
||||
|
||||
struct pw_properties *properties;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct pw_type type;
|
||||
struct pw_access *access;
|
||||
struct pw_type type;
|
||||
struct pw_access *access;
|
||||
|
||||
struct pw_map objects;
|
||||
struct pw_map objects;
|
||||
|
||||
struct spa_list resource_list;
|
||||
struct spa_list registry_resource_list;
|
||||
struct spa_list global_list;
|
||||
struct spa_list client_list;
|
||||
struct spa_list node_list;
|
||||
struct spa_list node_factory_list;
|
||||
struct spa_list link_list;
|
||||
struct spa_list resource_list;
|
||||
struct spa_list registry_resource_list;
|
||||
struct spa_list global_list;
|
||||
struct spa_list client_list;
|
||||
struct spa_list node_list;
|
||||
struct spa_list node_factory_list;
|
||||
struct spa_list link_list;
|
||||
|
||||
struct pw_main_loop *main_loop;
|
||||
struct pw_data_loop *data_loop;
|
||||
struct pw_main_loop *main_loop;
|
||||
struct pw_data_loop *data_loop;
|
||||
|
||||
struct spa_support *support;
|
||||
uint32_t n_support;
|
||||
struct spa_support *support;
|
||||
uint32_t n_support;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_core *core));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_core * core));
|
||||
|
||||
PW_SIGNAL (global_added, (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global));
|
||||
PW_SIGNAL (global_removed, (struct pw_listener *listener,
|
||||
struct pw_core *core,
|
||||
struct pw_global *global));
|
||||
PW_SIGNAL(global_added, (struct pw_listener * listener,
|
||||
struct pw_core * core, struct pw_global * global));
|
||||
PW_SIGNAL(global_removed, (struct pw_listener * listener,
|
||||
struct pw_core * core, struct pw_global * global));
|
||||
};
|
||||
|
||||
struct pw_core * pw_core_new (struct pw_main_loop *main_loop,
|
||||
struct pw_properties *props);
|
||||
void pw_core_destroy (struct pw_core *core);
|
||||
struct pw_core *
|
||||
pw_core_new(struct pw_main_loop *main_loop, struct pw_properties *props);
|
||||
|
||||
void pw_core_update_properties (struct pw_core *core,
|
||||
const struct spa_dict *dict);
|
||||
void
|
||||
pw_core_destroy(struct pw_core *core);
|
||||
|
||||
bool pw_core_add_global (struct pw_core *core,
|
||||
struct pw_client *owner,
|
||||
uint32_t type,
|
||||
uint32_t version,
|
||||
void *object,
|
||||
pw_bind_func_t bind,
|
||||
struct pw_global **global);
|
||||
void
|
||||
pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict);
|
||||
|
||||
int pw_global_bind (struct pw_global *global,
|
||||
struct pw_client *client,
|
||||
uint32_t version,
|
||||
uint32_t id);
|
||||
void pw_global_destroy (struct pw_global *global);
|
||||
bool
|
||||
pw_core_add_global(struct pw_core *core,
|
||||
struct pw_client *owner,
|
||||
uint32_t type,
|
||||
uint32_t version,
|
||||
void *object, pw_bind_func_t bind,
|
||||
struct pw_global **global);
|
||||
|
||||
struct spa_format * pw_core_find_format (struct pw_core *core,
|
||||
struct pw_port *output,
|
||||
struct pw_port *input,
|
||||
struct pw_properties *props,
|
||||
uint32_t n_format_filters,
|
||||
struct spa_format **format_filters,
|
||||
char **error);
|
||||
int
|
||||
pw_global_bind(struct pw_global *global,
|
||||
struct pw_client *client, uint32_t version, uint32_t id);
|
||||
|
||||
struct pw_port * pw_core_find_port (struct pw_core *core,
|
||||
struct pw_port *other_port,
|
||||
uint32_t id,
|
||||
struct pw_properties *props,
|
||||
uint32_t n_format_filters,
|
||||
struct spa_format **format_filters,
|
||||
char **error);
|
||||
void
|
||||
pw_global_destroy(struct pw_global *global);
|
||||
|
||||
struct pw_node_factory * pw_core_find_node_factory (struct pw_core *core,
|
||||
const char *name);
|
||||
struct spa_format *
|
||||
pw_core_find_format(struct pw_core *core,
|
||||
struct pw_port *output,
|
||||
struct pw_port *input,
|
||||
struct pw_properties *props,
|
||||
uint32_t n_format_filters,
|
||||
struct spa_format **format_filters,
|
||||
char **error);
|
||||
|
||||
struct pw_port *
|
||||
pw_core_find_port(struct pw_core *core,
|
||||
struct pw_port *other_port,
|
||||
uint32_t id,
|
||||
struct pw_properties *props,
|
||||
uint32_t n_format_filters,
|
||||
struct spa_format **format_filters,
|
||||
char **error);
|
||||
|
||||
struct pw_node_factory *
|
||||
pw_core_find_node_factory(struct pw_core *core, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,90 +32,84 @@
|
|||
#include "pipewire/client/rtkit.h"
|
||||
#include "pipewire/server/data-loop.h"
|
||||
|
||||
struct impl
|
||||
{
|
||||
struct pw_data_loop this;
|
||||
struct impl {
|
||||
struct pw_data_loop this;
|
||||
|
||||
struct spa_source *event;
|
||||
struct spa_source *event;
|
||||
|
||||
bool running;
|
||||
pthread_t thread;
|
||||
bool running;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
static void
|
||||
make_realtime (struct pw_data_loop *this)
|
||||
static void make_realtime(struct pw_data_loop *this)
|
||||
{
|
||||
struct sched_param sp;
|
||||
struct pw_rtkit_bus *system_bus;
|
||||
struct rlimit rl;
|
||||
int r, rtprio;
|
||||
long long rttime;
|
||||
struct sched_param sp;
|
||||
struct pw_rtkit_bus *system_bus;
|
||||
struct rlimit rl;
|
||||
int r, rtprio;
|
||||
long long rttime;
|
||||
|
||||
rtprio = 20;
|
||||
rttime = 20000;
|
||||
rtprio = 20;
|
||||
rttime = 20000;
|
||||
|
||||
spa_zero (sp);
|
||||
sp.sched_priority = rtprio;
|
||||
spa_zero(sp);
|
||||
sp.sched_priority = rtprio;
|
||||
|
||||
if (pthread_setschedparam (pthread_self(), SCHED_OTHER|SCHED_RESET_ON_FORK, &sp) == 0) {
|
||||
pw_log_debug ("SCHED_OTHER|SCHED_RESET_ON_FORK worked.");
|
||||
return;
|
||||
}
|
||||
system_bus = pw_rtkit_bus_get_system ();
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_OTHER | SCHED_RESET_ON_FORK, &sp) == 0) {
|
||||
pw_log_debug("SCHED_OTHER|SCHED_RESET_ON_FORK worked.");
|
||||
return;
|
||||
}
|
||||
system_bus = pw_rtkit_bus_get_system();
|
||||
|
||||
rl.rlim_cur = rl.rlim_max = rttime;
|
||||
if ((r = setrlimit (RLIMIT_RTTIME, &rl)) < 0)
|
||||
pw_log_debug ("setrlimit() failed: %s", strerror (errno));
|
||||
rl.rlim_cur = rl.rlim_max = rttime;
|
||||
if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0)
|
||||
pw_log_debug("setrlimit() failed: %s", strerror(errno));
|
||||
|
||||
if (rttime >= 0) {
|
||||
r = getrlimit (RLIMIT_RTTIME, &rl);
|
||||
if (r >= 0 && (long long) rl.rlim_max > rttime) {
|
||||
pw_log_debug ("Clamping rlimit-rttime to %lld for RealtimeKit", rttime);
|
||||
rl.rlim_cur = rl.rlim_max = rttime;
|
||||
if (rttime >= 0) {
|
||||
r = getrlimit(RLIMIT_RTTIME, &rl);
|
||||
if (r >= 0 && (long long) rl.rlim_max > rttime) {
|
||||
pw_log_debug("Clamping rlimit-rttime to %lld for RealtimeKit", rttime);
|
||||
rl.rlim_cur = rl.rlim_max = rttime;
|
||||
|
||||
if ((r = setrlimit (RLIMIT_RTTIME, &rl)) < 0)
|
||||
pw_log_debug ("setrlimit() failed: %s", strerror (errno));
|
||||
}
|
||||
}
|
||||
if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0)
|
||||
pw_log_debug("setrlimit() failed: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if ((r = pw_rtkit_make_realtime (system_bus, 0, rtprio)) < 0) {
|
||||
pw_log_debug ("could not make thread realtime: %s", strerror (r));
|
||||
} else {
|
||||
pw_log_debug ("thread made realtime");
|
||||
}
|
||||
pw_rtkit_bus_free (system_bus);
|
||||
if ((r = pw_rtkit_make_realtime(system_bus, 0, rtprio)) < 0) {
|
||||
pw_log_debug("could not make thread realtime: %s", strerror(r));
|
||||
} else {
|
||||
pw_log_debug("thread made realtime");
|
||||
}
|
||||
pw_rtkit_bus_free(system_bus);
|
||||
}
|
||||
|
||||
static void *
|
||||
do_loop (void *user_data)
|
||||
static void *do_loop(void *user_data)
|
||||
{
|
||||
struct impl *impl = user_data;
|
||||
struct pw_data_loop *this = &impl->this;
|
||||
int res;
|
||||
struct impl *impl = user_data;
|
||||
struct pw_data_loop *this = &impl->this;
|
||||
int res;
|
||||
|
||||
make_realtime (this);
|
||||
make_realtime(this);
|
||||
|
||||
pw_log_debug ("data-loop %p: enter thread", this);
|
||||
pw_loop_enter (impl->this.loop);
|
||||
pw_log_debug("data-loop %p: enter thread", this);
|
||||
pw_loop_enter(impl->this.loop);
|
||||
|
||||
while (impl->running) {
|
||||
if ((res = pw_loop_iterate (this->loop, -1)) < 0)
|
||||
pw_log_warn ("data-loop %p: iterate error %d", this, res);
|
||||
}
|
||||
pw_log_debug ("data-loop %p: leave thread", this);
|
||||
pw_loop_leave (impl->this.loop);
|
||||
while (impl->running) {
|
||||
if ((res = pw_loop_iterate(this->loop, -1)) < 0)
|
||||
pw_log_warn("data-loop %p: iterate error %d", this, res);
|
||||
}
|
||||
pw_log_debug("data-loop %p: leave thread", this);
|
||||
pw_loop_leave(impl->this.loop);
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_stop (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
void *data)
|
||||
static void do_stop(struct spa_loop_utils *utils, struct spa_source *source, void *data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
impl->running = false;
|
||||
struct impl *impl = data;
|
||||
impl->running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,84 +119,77 @@ do_stop (struct spa_loop_utils *utils,
|
|||
*
|
||||
* Returns: a new #struct pw_data_loop
|
||||
*/
|
||||
struct pw_data_loop *
|
||||
pw_data_loop_new (void)
|
||||
struct pw_data_loop *pw_data_loop_new(void)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_data_loop *this;
|
||||
struct impl *impl;
|
||||
struct pw_data_loop *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_log_debug ("data-loop %p: new", impl);
|
||||
pw_log_debug("data-loop %p: new", impl);
|
||||
|
||||
this = &impl->this;
|
||||
this->loop = pw_loop_new ();
|
||||
if (this->loop == NULL)
|
||||
goto no_loop;
|
||||
this = &impl->this;
|
||||
this->loop = pw_loop_new();
|
||||
if (this->loop == NULL)
|
||||
goto no_loop;
|
||||
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
impl->event = pw_loop_add_event (this->loop,
|
||||
do_stop,
|
||||
impl);
|
||||
return this;
|
||||
impl->event = pw_loop_add_event(this->loop, do_stop, impl);
|
||||
return this;
|
||||
|
||||
no_loop:
|
||||
free (impl);
|
||||
return NULL;
|
||||
no_loop:
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_data_loop_destroy (struct pw_data_loop *loop)
|
||||
void pw_data_loop_destroy(struct pw_data_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
|
||||
pw_log_debug ("data-loop %p: destroy", impl);
|
||||
pw_signal_emit (&loop->destroy_signal, loop);
|
||||
pw_log_debug("data-loop %p: destroy", impl);
|
||||
pw_signal_emit(&loop->destroy_signal, loop);
|
||||
|
||||
pw_data_loop_stop (loop);
|
||||
pw_data_loop_stop(loop);
|
||||
|
||||
pw_loop_destroy_source (loop->loop, impl->event);
|
||||
pw_loop_destroy (loop->loop);
|
||||
free (impl);
|
||||
pw_loop_destroy_source(loop->loop, impl->event);
|
||||
pw_loop_destroy(loop->loop);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
int
|
||||
pw_data_loop_start (struct pw_data_loop *loop)
|
||||
int pw_data_loop_start(struct pw_data_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
|
||||
if (!impl->running) {
|
||||
int err;
|
||||
if (!impl->running) {
|
||||
int err;
|
||||
|
||||
impl->running = true;
|
||||
if ((err = pthread_create (&impl->thread, NULL, do_loop, impl)) != 0) {
|
||||
pw_log_warn ("data-loop %p: can't create thread: %s", impl, strerror (err));
|
||||
impl->running = false;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
impl->running = true;
|
||||
if ((err = pthread_create(&impl->thread, NULL, do_loop, impl)) != 0) {
|
||||
pw_log_warn("data-loop %p: can't create thread: %s", impl, strerror(err));
|
||||
impl->running = false;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pw_data_loop_stop (struct pw_data_loop *loop)
|
||||
int pw_data_loop_stop(struct pw_data_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
|
||||
if (impl->running) {
|
||||
pw_loop_signal_event (impl->this.loop, impl->event);
|
||||
if (impl->running) {
|
||||
pw_loop_signal_event(impl->this.loop, impl->event);
|
||||
|
||||
pthread_join (impl->thread, NULL);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
pthread_join(impl->thread, NULL);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
pw_data_loop_in_thread (struct pw_data_loop *loop)
|
||||
bool pw_data_loop_in_thread(struct pw_data_loop * loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
return pthread_equal (impl->thread, pthread_self());
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
return pthread_equal(impl->thread, pthread_self());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,19 +32,25 @@ extern "C" {
|
|||
* PipeWire rt-loop object.
|
||||
*/
|
||||
struct pw_data_loop {
|
||||
struct pw_loop *loop;
|
||||
struct pw_loop *loop;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_data_loop *loop));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_data_loop * loop));
|
||||
};
|
||||
|
||||
struct pw_data_loop * pw_data_loop_new (void);
|
||||
void pw_data_loop_destroy (struct pw_data_loop *loop);
|
||||
struct pw_data_loop *
|
||||
pw_data_loop_new(void);
|
||||
|
||||
int pw_data_loop_start (struct pw_data_loop *loop);
|
||||
int pw_data_loop_stop (struct pw_data_loop *loop);
|
||||
void
|
||||
pw_data_loop_destroy(struct pw_data_loop *loop);
|
||||
|
||||
bool pw_data_loop_in_thread (struct pw_data_loop *loop);
|
||||
int
|
||||
pw_data_loop_start(struct pw_data_loop *loop);
|
||||
|
||||
int
|
||||
pw_data_loop_stop(struct pw_data_loop *loop);
|
||||
|
||||
bool
|
||||
pw_data_loop_in_thread(struct pw_data_loop *loop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -38,53 +38,55 @@ extern "C" {
|
|||
* PipeWire link interface.
|
||||
*/
|
||||
struct pw_link {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
|
||||
struct pw_properties *properties;
|
||||
struct pw_properties *properties;
|
||||
|
||||
enum pw_link_state state;
|
||||
char *error;
|
||||
PW_SIGNAL (state_changed, (struct pw_listener *listener,
|
||||
struct pw_link *link,
|
||||
enum pw_link_state old,
|
||||
enum pw_link_state state));
|
||||
enum pw_link_state state;
|
||||
char *error;
|
||||
PW_SIGNAL(state_changed, (struct pw_listener * listener,
|
||||
struct pw_link * link,
|
||||
enum pw_link_state old, enum pw_link_state state));
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *,
|
||||
struct pw_link *));
|
||||
PW_SIGNAL (free_signal, (struct pw_listener *,
|
||||
struct pw_link *));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener *, struct pw_link *));
|
||||
PW_SIGNAL(free_signal, (struct pw_listener *, struct pw_link *));
|
||||
|
||||
struct spa_list resource_list;
|
||||
struct spa_list resource_list;
|
||||
|
||||
struct pw_port *output;
|
||||
struct spa_list output_link;
|
||||
struct pw_port *input;
|
||||
struct spa_list input_link;
|
||||
PW_SIGNAL (port_unlinked, (struct pw_listener *listener,
|
||||
struct pw_link *link,
|
||||
struct pw_port *port));
|
||||
struct pw_port *output;
|
||||
struct spa_list output_link;
|
||||
struct pw_port *input;
|
||||
struct spa_list input_link;
|
||||
PW_SIGNAL(port_unlinked, (struct pw_listener * listener,
|
||||
struct pw_link * link, struct pw_port * port));
|
||||
|
||||
struct {
|
||||
uint32_t in_ready;
|
||||
struct pw_port *input;
|
||||
struct pw_port *output;
|
||||
struct spa_list input_link;
|
||||
struct spa_list output_link;
|
||||
} rt;
|
||||
struct {
|
||||
uint32_t in_ready;
|
||||
struct pw_port *input;
|
||||
struct pw_port *output;
|
||||
struct spa_list input_link;
|
||||
struct spa_list output_link;
|
||||
} rt;
|
||||
};
|
||||
|
||||
|
||||
struct pw_link * pw_link_new (struct pw_core *core,
|
||||
struct pw_port *output,
|
||||
struct pw_port *input,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties);
|
||||
void pw_link_destroy (struct pw_link *link);
|
||||
struct pw_link *
|
||||
pw_link_new(struct pw_core *core,
|
||||
struct pw_port *output,
|
||||
struct pw_port *input,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties);
|
||||
|
||||
bool pw_link_activate (struct pw_link *link);
|
||||
bool pw_link_deactivate (struct pw_link *link);
|
||||
void
|
||||
pw_link_destroy(struct pw_link *link);
|
||||
|
||||
bool
|
||||
pw_link_activate(struct pw_link *link);
|
||||
|
||||
bool
|
||||
pw_link_deactivate(struct pw_link *link);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@
|
|||
#include "pipewire/server/main-loop.h"
|
||||
|
||||
struct impl {
|
||||
struct pw_main_loop this;
|
||||
struct pw_main_loop this;
|
||||
|
||||
bool running;
|
||||
bool running;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -40,43 +40,41 @@ struct impl {
|
|||
*
|
||||
* Returns: a new #struct pw_main_loop
|
||||
*/
|
||||
struct pw_main_loop *
|
||||
pw_main_loop_new (void)
|
||||
struct pw_main_loop *pw_main_loop_new(void)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_main_loop *this;
|
||||
struct impl *impl;
|
||||
struct pw_main_loop *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
pw_log_debug ("main-loop %p: new", impl);
|
||||
this = &impl->this;
|
||||
pw_log_debug("main-loop %p: new", impl);
|
||||
this = &impl->this;
|
||||
|
||||
this->loop = pw_loop_new ();
|
||||
if (this->loop == NULL)
|
||||
goto no_loop;
|
||||
this->loop = pw_loop_new();
|
||||
if (this->loop == NULL)
|
||||
goto no_loop;
|
||||
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
no_loop:
|
||||
free (impl);
|
||||
return NULL;
|
||||
no_loop:
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_main_loop_destroy (struct pw_main_loop *loop)
|
||||
void pw_main_loop_destroy(struct pw_main_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
|
||||
pw_log_debug ("main-loop %p: destroy", impl);
|
||||
pw_signal_emit (&loop->destroy_signal, loop);
|
||||
pw_log_debug("main-loop %p: destroy", impl);
|
||||
pw_signal_emit(&loop->destroy_signal, loop);
|
||||
|
||||
pw_loop_destroy (loop->loop);
|
||||
pw_loop_destroy(loop->loop);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,12 +83,11 @@ pw_main_loop_destroy (struct pw_main_loop *loop)
|
|||
*
|
||||
* Stop the running @loop.
|
||||
*/
|
||||
void
|
||||
pw_main_loop_quit (struct pw_main_loop *loop)
|
||||
void pw_main_loop_quit(struct pw_main_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
pw_log_debug ("main-loop %p: quit", impl);
|
||||
impl->running = false;
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
pw_log_debug("main-loop %p: quit", impl);
|
||||
impl->running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -100,17 +97,16 @@ pw_main_loop_quit (struct pw_main_loop *loop)
|
|||
* Start running @loop. This function blocks until pw_main_loop_quit()
|
||||
* has been called.
|
||||
*/
|
||||
void
|
||||
pw_main_loop_run (struct pw_main_loop *loop)
|
||||
void pw_main_loop_run(struct pw_main_loop *loop)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (loop, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(loop, struct impl, this);
|
||||
|
||||
pw_log_debug ("main-loop %p: run", impl);
|
||||
pw_log_debug("main-loop %p: run", impl);
|
||||
|
||||
impl->running = true;
|
||||
pw_loop_enter (loop->loop);
|
||||
while (impl->running) {
|
||||
pw_loop_iterate (loop->loop, -1);
|
||||
}
|
||||
pw_loop_leave (loop->loop);
|
||||
impl->running = true;
|
||||
pw_loop_enter(loop->loop);
|
||||
while (impl->running) {
|
||||
pw_loop_iterate(loop->loop, -1);
|
||||
}
|
||||
pw_loop_leave(loop->loop);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,17 +33,22 @@ extern "C" {
|
|||
* PipeWire main-loop interface.
|
||||
*/
|
||||
struct pw_main_loop {
|
||||
struct pw_loop *loop;
|
||||
struct pw_loop *loop;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_main_loop *loop));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_main_loop * loop));
|
||||
};
|
||||
|
||||
struct pw_main_loop * pw_main_loop_new (void);
|
||||
void pw_main_loop_destroy (struct pw_main_loop *loop);
|
||||
struct pw_main_loop *
|
||||
pw_main_loop_new(void);
|
||||
|
||||
void pw_main_loop_run (struct pw_main_loop *loop);
|
||||
void pw_main_loop_quit (struct pw_main_loop *loop);
|
||||
void
|
||||
pw_main_loop_destroy(struct pw_main_loop *loop);
|
||||
|
||||
void
|
||||
pw_main_loop_run(struct pw_main_loop *loop);
|
||||
|
||||
void
|
||||
pw_main_loop_quit(struct pw_main_loop *loop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,90 +36,79 @@
|
|||
#define PIPEWIRE_SYMBOL_MODULE_INIT "pipewire__module_init"
|
||||
|
||||
struct impl {
|
||||
struct pw_module this;
|
||||
void *hnd;
|
||||
struct pw_module this;
|
||||
void *hnd;
|
||||
};
|
||||
|
||||
static char *
|
||||
find_module (const char * path, const char *name)
|
||||
static char *find_module(const char *path, const char *name)
|
||||
{
|
||||
char *filename;
|
||||
struct dirent *entry;
|
||||
struct stat s;
|
||||
DIR *dir;
|
||||
char *filename;
|
||||
struct dirent *entry;
|
||||
struct stat s;
|
||||
DIR *dir;
|
||||
|
||||
asprintf (&filename, "%s/%s.so", path, name);
|
||||
asprintf(&filename, "%s/%s.so", path, name);
|
||||
|
||||
if (stat (filename, &s) == 0 && S_ISREG (s.st_mode)) {
|
||||
/* found a regular file with name */
|
||||
return filename;
|
||||
}
|
||||
if (stat(filename, &s) == 0 && S_ISREG(s.st_mode)) {
|
||||
/* found a regular file with name */
|
||||
return filename;
|
||||
}
|
||||
|
||||
free (filename);
|
||||
filename = NULL;
|
||||
free(filename);
|
||||
filename = NULL;
|
||||
|
||||
/* now recurse down in subdirectories and look for it there */
|
||||
/* now recurse down in subdirectories and look for it there */
|
||||
|
||||
dir = opendir (path);
|
||||
if (dir == NULL) {
|
||||
pw_log_warn ("could not open %s: %s", path, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
pw_log_warn("could not open %s: %s", path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((entry = readdir (dir))) {
|
||||
char *newpath;
|
||||
while ((entry = readdir(dir))) {
|
||||
char *newpath;
|
||||
|
||||
if (strcmp (entry->d_name, ".") == 0 ||
|
||||
strcmp (entry->d_name, "..") == 0)
|
||||
continue;
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
asprintf (&newpath, "%s/%s", path, entry->d_name);
|
||||
asprintf(&newpath, "%s/%s", path, entry->d_name);
|
||||
|
||||
if (stat (newpath, &s) == 0 && S_ISDIR (s.st_mode)) {
|
||||
filename = find_module (newpath, name);
|
||||
}
|
||||
free (newpath);
|
||||
if (stat(newpath, &s) == 0 && S_ISDIR(s.st_mode)) {
|
||||
filename = find_module(newpath, name);
|
||||
}
|
||||
free(newpath);
|
||||
|
||||
if (filename != NULL)
|
||||
break;
|
||||
}
|
||||
if (filename != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
closedir (dir);
|
||||
closedir(dir);
|
||||
|
||||
return filename;
|
||||
return filename;
|
||||
}
|
||||
|
||||
static int
|
||||
module_bind_func (struct pw_global *global,
|
||||
struct pw_client *client,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
module_bind_func(struct pw_global *global, struct pw_client *client, uint32_t version, uint32_t id)
|
||||
{
|
||||
struct pw_module *this = global->object;
|
||||
struct pw_resource *resource;
|
||||
struct pw_module *this = global->object;
|
||||
struct pw_resource *resource;
|
||||
|
||||
resource = pw_resource_new (client,
|
||||
id,
|
||||
global->type,
|
||||
global->object,
|
||||
NULL);
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
resource = pw_resource_new(client, id, global->type, global->object, NULL);
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
|
||||
pw_log_debug ("module %p: bound to %d", global->object, resource->id);
|
||||
pw_log_debug("module %p: bound to %d", global->object, resource->id);
|
||||
|
||||
this->info.change_mask = ~0;
|
||||
pw_module_notify_info (resource, &this->info);
|
||||
this->info.change_mask = ~0;
|
||||
pw_module_notify_info(resource, &this->info);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
no_mem:
|
||||
pw_log_error ("can't create module resource");
|
||||
pw_core_notify_error (client->core_resource,
|
||||
client->core_resource->id,
|
||||
SPA_RESULT_NO_MEMORY,
|
||||
"no memory");
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
no_mem:
|
||||
pw_log_error("can't create module resource");
|
||||
pw_core_notify_error(client->core_resource,
|
||||
client->core_resource->id, SPA_RESULT_NO_MEMORY, "no memory");
|
||||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,122 +122,104 @@ no_mem:
|
|||
*
|
||||
* Returns: A #struct pw_module if the module could be loaded, or %NULL on failure.
|
||||
*/
|
||||
struct pw_module *
|
||||
pw_module_load (struct pw_core *core,
|
||||
const char *name,
|
||||
const char *args,
|
||||
char **err)
|
||||
struct pw_module *pw_module_load(struct pw_core *core,
|
||||
const char *name, const char *args, char **err)
|
||||
{
|
||||
struct pw_module *this;
|
||||
struct impl *impl;
|
||||
void *hnd;
|
||||
char *filename = NULL;
|
||||
const char *module_dir;
|
||||
pw_module_init_func_t init_func;
|
||||
struct pw_module *this;
|
||||
struct impl *impl;
|
||||
void *hnd;
|
||||
char *filename = NULL;
|
||||
const char *module_dir;
|
||||
pw_module_init_func_t init_func;
|
||||
|
||||
module_dir = getenv ("PIPEWIRE_MODULE_DIR");
|
||||
if (module_dir != NULL) {
|
||||
char **l;
|
||||
int i, n_paths;
|
||||
module_dir = getenv("PIPEWIRE_MODULE_DIR");
|
||||
if (module_dir != NULL) {
|
||||
char **l;
|
||||
int i, n_paths;
|
||||
|
||||
pw_log_debug ("PIPEWIRE_MODULE_DIR set to: %s", module_dir);
|
||||
pw_log_debug("PIPEWIRE_MODULE_DIR set to: %s", module_dir);
|
||||
|
||||
l = pw_split_strv (module_dir, "/", 0, &n_paths);
|
||||
for (i = 0; l[i] != NULL; i++) {
|
||||
filename = find_module (l[i], name);
|
||||
if (filename != NULL)
|
||||
break;
|
||||
}
|
||||
pw_free_strv (l);
|
||||
} else {
|
||||
pw_log_debug ("moduledir set to: %s", MODULEDIR);
|
||||
l = pw_split_strv(module_dir, "/", 0, &n_paths);
|
||||
for (i = 0; l[i] != NULL; i++) {
|
||||
filename = find_module(l[i], name);
|
||||
if (filename != NULL)
|
||||
break;
|
||||
}
|
||||
pw_free_strv(l);
|
||||
} else {
|
||||
pw_log_debug("moduledir set to: %s", MODULEDIR);
|
||||
|
||||
filename = find_module (MODULEDIR, name);
|
||||
}
|
||||
filename = find_module(MODULEDIR, name);
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
goto not_found;
|
||||
if (filename == NULL)
|
||||
goto not_found;
|
||||
|
||||
pw_log_debug ("trying to load module: %s (%s)", name, filename);
|
||||
pw_log_debug("trying to load module: %s (%s)", name, filename);
|
||||
|
||||
hnd = dlopen (filename, RTLD_NOW | RTLD_LOCAL);
|
||||
hnd = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (hnd == NULL)
|
||||
goto open_failed;
|
||||
if (hnd == NULL)
|
||||
goto open_failed;
|
||||
|
||||
if ((init_func = dlsym (hnd, PIPEWIRE_SYMBOL_MODULE_INIT)) == NULL)
|
||||
goto no_pw_module;
|
||||
if ((init_func = dlsym(hnd, PIPEWIRE_SYMBOL_MODULE_INIT)) == NULL)
|
||||
goto no_pw_module;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
goto no_mem;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
goto no_mem;
|
||||
|
||||
impl->hnd = hnd;
|
||||
impl->hnd = hnd;
|
||||
|
||||
this = &impl->this;
|
||||
this->core = core;
|
||||
this = &impl->this;
|
||||
this->core = core;
|
||||
|
||||
if (!init_func (this, (char *) args))
|
||||
goto init_failed;
|
||||
if (!init_func(this, (char *) args))
|
||||
goto init_failed;
|
||||
|
||||
pw_core_add_global (core,
|
||||
NULL,
|
||||
core->type.module,
|
||||
0,
|
||||
impl,
|
||||
module_bind_func,
|
||||
&this->global);
|
||||
pw_core_add_global(core, NULL, core->type.module, 0, impl, module_bind_func, &this->global);
|
||||
|
||||
this->info.id = this->global->id;
|
||||
this->info.name = name ? strdup (name) : NULL;
|
||||
this->info.filename = filename;
|
||||
this->info.args = args ? strdup (args) : NULL;
|
||||
this->info.props = NULL;
|
||||
this->info.id = this->global->id;
|
||||
this->info.name = name ? strdup(name) : NULL;
|
||||
this->info.filename = filename;
|
||||
this->info.args = args ? strdup(args) : NULL;
|
||||
this->info.props = NULL;
|
||||
|
||||
pw_log_debug ("loaded module: %s", this->info.name);
|
||||
pw_log_debug("loaded module: %s", this->info.name);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
not_found:
|
||||
{
|
||||
asprintf (err, "No module \"%s\" was found", name);
|
||||
return NULL;
|
||||
}
|
||||
open_failed:
|
||||
{
|
||||
asprintf (err, "Failed to open module: \"%s\" %s", filename, dlerror ());
|
||||
free (filename);
|
||||
return NULL;
|
||||
}
|
||||
no_mem:
|
||||
no_pw_module:
|
||||
{
|
||||
asprintf (err, "\"%s\" is not a pipewire module", name);
|
||||
dlclose (hnd);
|
||||
free (filename);
|
||||
return NULL;
|
||||
}
|
||||
init_failed:
|
||||
{
|
||||
asprintf (err, "\"%s\" failed to initialize", name);
|
||||
pw_module_destroy (this);
|
||||
return NULL;
|
||||
}
|
||||
not_found:
|
||||
asprintf(err, "No module \"%s\" was found", name);
|
||||
return NULL;
|
||||
open_failed:
|
||||
asprintf(err, "Failed to open module: \"%s\" %s", filename, dlerror());
|
||||
free(filename);
|
||||
return NULL;
|
||||
no_mem:
|
||||
no_pw_module:
|
||||
asprintf(err, "\"%s\" is not a pipewire module", name);
|
||||
dlclose(hnd);
|
||||
free(filename);
|
||||
return NULL;
|
||||
init_failed:
|
||||
asprintf(err, "\"%s\" failed to initialize", name);
|
||||
pw_module_destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_module_destroy (struct pw_module *this)
|
||||
void pw_module_destroy(struct pw_module *this)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (this, struct impl, this);
|
||||
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
|
||||
|
||||
pw_signal_emit (&this->destroy_signal, this);
|
||||
pw_signal_emit(&this->destroy_signal, this);
|
||||
|
||||
if (this->info.name)
|
||||
free ((char*)this->info.name);
|
||||
if (this->info.filename)
|
||||
free ((char*)this->info.filename);
|
||||
if (this->info.args)
|
||||
free ((char*)this->info.args);
|
||||
dlclose (impl->hnd);
|
||||
free (impl);
|
||||
if (this->info.name)
|
||||
free((char *) this->info.name);
|
||||
if (this->info.filename)
|
||||
free((char *) this->info.filename);
|
||||
if (this->info.args)
|
||||
free((char *) this->info.args);
|
||||
dlclose(impl->hnd);
|
||||
free(impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,15 @@ extern "C" {
|
|||
#include <pipewire/server/core.h>
|
||||
|
||||
struct pw_module {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
|
||||
struct pw_module_info info;
|
||||
struct pw_module_info info;
|
||||
|
||||
void *user_data;
|
||||
void *user_data;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_module *module));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_module * module));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -50,13 +49,14 @@ struct pw_module {
|
|||
*
|
||||
* Returns: %true on success, %false otherwise
|
||||
*/
|
||||
typedef bool (*pw_module_init_func_t) (struct pw_module *module, char *args);
|
||||
typedef bool (*pw_module_init_func_t) (struct pw_module * module, char *args);
|
||||
|
||||
struct pw_module * pw_module_load (struct pw_core *core,
|
||||
const char *name,
|
||||
const char *args,
|
||||
char **err);
|
||||
void pw_module_destroy (struct pw_module *module);
|
||||
struct pw_module *
|
||||
pw_module_load(struct pw_core *core,
|
||||
const char *name, const char *args, char **err);
|
||||
|
||||
void
|
||||
pw_module_destroy(struct pw_module *module);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,19 +36,18 @@ extern "C" {
|
|||
* PipeWire node factory interface.
|
||||
*/
|
||||
struct pw_node_factory {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
|
||||
const char *name;
|
||||
const char *name;
|
||||
|
||||
struct pw_node * (*create_node) (struct pw_node_factory *factory,
|
||||
struct pw_client *client,
|
||||
const char *name,
|
||||
struct pw_properties *properties);
|
||||
struct pw_node *(*create_node) (struct pw_node_factory * factory,
|
||||
struct pw_client * client,
|
||||
const char *name, struct pw_properties * properties);
|
||||
};
|
||||
|
||||
#define pw_node_factory_create_node(f,...) (f)->create_node((f),__VA_ARGS__)
|
||||
#define pw_node_factory_create_node(f,...) (f)->create_node((f),__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -45,92 +45,84 @@ extern "C" {
|
|||
* PipeWire node class.
|
||||
*/
|
||||
struct pw_node {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_global *global;
|
||||
|
||||
struct pw_client *owner;
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
enum pw_node_state state;
|
||||
char *error;
|
||||
PW_SIGNAL (state_request, (struct pw_listener *listener,
|
||||
struct pw_node *object,
|
||||
enum pw_node_state state));
|
||||
PW_SIGNAL (state_changed, (struct pw_listener *listener,
|
||||
struct pw_node *object,
|
||||
enum pw_node_state old,
|
||||
enum pw_node_state state));
|
||||
struct pw_client *owner;
|
||||
char *name;
|
||||
struct pw_properties *properties;
|
||||
enum pw_node_state state;
|
||||
char *error;
|
||||
PW_SIGNAL(state_request, (struct pw_listener * listener,
|
||||
struct pw_node * object, enum pw_node_state state));
|
||||
PW_SIGNAL(state_changed, (struct pw_listener * listener,
|
||||
struct pw_node * object,
|
||||
enum pw_node_state old, enum pw_node_state state));
|
||||
|
||||
struct spa_handle *handle;
|
||||
struct spa_node *node;
|
||||
bool live;
|
||||
struct spa_clock *clock;
|
||||
struct spa_handle *handle;
|
||||
struct spa_node *node;
|
||||
bool live;
|
||||
struct spa_clock *clock;
|
||||
|
||||
struct spa_list resource_list;
|
||||
struct spa_list resource_list;
|
||||
|
||||
PW_SIGNAL (initialized, (struct pw_listener *listener,
|
||||
struct pw_node *object));
|
||||
PW_SIGNAL(initialized, (struct pw_listener * listener, struct pw_node * object));
|
||||
|
||||
uint32_t max_input_ports;
|
||||
uint32_t n_input_ports;
|
||||
struct spa_list input_ports;
|
||||
struct pw_port **input_port_map;
|
||||
uint32_t n_used_input_links;
|
||||
uint32_t max_input_ports;
|
||||
uint32_t n_input_ports;
|
||||
struct spa_list input_ports;
|
||||
struct pw_port **input_port_map;
|
||||
uint32_t n_used_input_links;
|
||||
|
||||
uint32_t max_output_ports;
|
||||
uint32_t n_output_ports;
|
||||
struct spa_list output_ports;
|
||||
struct pw_port **output_port_map;
|
||||
uint32_t n_used_output_links;
|
||||
uint32_t max_output_ports;
|
||||
uint32_t n_output_ports;
|
||||
struct spa_list output_ports;
|
||||
struct pw_port **output_port_map;
|
||||
uint32_t n_used_output_links;
|
||||
|
||||
PW_SIGNAL (port_added, (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
struct pw_port *port));
|
||||
PW_SIGNAL (port_removed, (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
struct pw_port *port));
|
||||
PW_SIGNAL(port_added, (struct pw_listener * listener,
|
||||
struct pw_node * node, struct pw_port * port));
|
||||
PW_SIGNAL(port_removed, (struct pw_listener * listener,
|
||||
struct pw_node * node, struct pw_port * port));
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_node *object));
|
||||
PW_SIGNAL (free_signal, (struct pw_listener *listener,
|
||||
struct pw_node *object));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_node * object));
|
||||
PW_SIGNAL(free_signal, (struct pw_listener * listener, struct pw_node * object));
|
||||
|
||||
PW_SIGNAL (async_complete, (struct pw_listener *listener,
|
||||
struct pw_node *node,
|
||||
uint32_t seq,
|
||||
int res));
|
||||
PW_SIGNAL(async_complete, (struct pw_listener * listener,
|
||||
struct pw_node * node, uint32_t seq, int res));
|
||||
|
||||
struct pw_data_loop *data_loop;
|
||||
PW_SIGNAL (loop_changed, (struct pw_listener *listener,
|
||||
struct pw_node *object));
|
||||
struct pw_data_loop *data_loop;
|
||||
PW_SIGNAL(loop_changed, (struct pw_listener * listener, struct pw_node * object));
|
||||
};
|
||||
|
||||
struct pw_node * pw_node_new (struct pw_core *core,
|
||||
struct pw_client *owner,
|
||||
const char *name,
|
||||
bool async,
|
||||
struct spa_node *node,
|
||||
struct spa_clock *clock,
|
||||
struct pw_properties *properties);
|
||||
void pw_node_destroy (struct pw_node *node);
|
||||
struct pw_node *
|
||||
pw_node_new(struct pw_core *core,
|
||||
struct pw_client *owner,
|
||||
const char *name,
|
||||
bool async,
|
||||
struct spa_node *node,
|
||||
struct spa_clock *clock,
|
||||
struct pw_properties *properties);
|
||||
|
||||
void
|
||||
pw_node_destroy(struct pw_node *node);
|
||||
|
||||
|
||||
void pw_node_set_data_loop (struct pw_node *node,
|
||||
struct pw_data_loop *loop);
|
||||
void
|
||||
pw_node_set_data_loop(struct pw_node *node, struct pw_data_loop *loop);
|
||||
|
||||
struct pw_port * pw_node_get_free_port (struct pw_node *node,
|
||||
enum pw_direction direction);
|
||||
struct pw_port *
|
||||
pw_node_get_free_port(struct pw_node *node, enum pw_direction direction);
|
||||
|
||||
int pw_node_set_state (struct pw_node *node,
|
||||
enum pw_node_state state);
|
||||
void pw_node_update_state (struct pw_node *node,
|
||||
enum pw_node_state state,
|
||||
char *error);
|
||||
int
|
||||
pw_node_set_state(struct pw_node *node, enum pw_node_state state);
|
||||
|
||||
void
|
||||
pw_node_update_state(struct pw_node *node, enum pw_node_state state, char *error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __PIPEWIRE_NODE_H__ */
|
||||
|
|
|
|||
|
|
@ -25,92 +25,79 @@
|
|||
|
||||
#include "pipewire/server/port.h"
|
||||
|
||||
struct impl
|
||||
{
|
||||
struct pw_port this;
|
||||
struct impl {
|
||||
struct pw_port this;
|
||||
|
||||
uint32_t seq;
|
||||
uint32_t seq;
|
||||
};
|
||||
|
||||
struct pw_port *
|
||||
pw_port_new (struct pw_node *node,
|
||||
enum pw_direction direction,
|
||||
uint32_t port_id)
|
||||
struct pw_port *pw_port_new(struct pw_node *node, enum pw_direction direction, uint32_t port_id)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_port *this;
|
||||
struct impl *impl;
|
||||
struct pw_port *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this->node = node;
|
||||
this->direction = direction;
|
||||
this->port_id = port_id;
|
||||
this->state = PW_PORT_STATE_CONFIGURE;
|
||||
this->io.status = SPA_RESULT_OK;
|
||||
this->io.buffer_id = SPA_ID_INVALID;
|
||||
this = &impl->this;
|
||||
this->node = node;
|
||||
this->direction = direction;
|
||||
this->port_id = port_id;
|
||||
this->state = PW_PORT_STATE_CONFIGURE;
|
||||
this->io.status = SPA_RESULT_OK;
|
||||
this->io.buffer_id = SPA_ID_INVALID;
|
||||
|
||||
spa_list_init (&this->links);
|
||||
spa_list_init (&this->rt.links);
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
spa_list_init(&this->links);
|
||||
spa_list_init(&this->rt.links);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
pw_port_destroy (struct pw_port *port)
|
||||
void pw_port_destroy(struct pw_port *port)
|
||||
{
|
||||
pw_log_debug ("port %p: destroy", port);
|
||||
pw_log_debug("port %p: destroy", port);
|
||||
|
||||
pw_signal_emit (&port->destroy_signal, port);
|
||||
pw_signal_emit(&port->destroy_signal, port);
|
||||
|
||||
spa_list_remove (&port->link);
|
||||
spa_list_remove(&port->link);
|
||||
|
||||
free (port);
|
||||
free(port);
|
||||
}
|
||||
|
||||
static int
|
||||
do_add_link (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
do_add_link(struct spa_loop *loop,
|
||||
bool async, uint32_t seq, size_t size, void *data, void *user_data)
|
||||
{
|
||||
struct pw_port *this = user_data;
|
||||
struct pw_link *link = ((struct pw_link**)data)[0];
|
||||
struct pw_port *this = user_data;
|
||||
struct pw_link *link = ((struct pw_link **) data)[0];
|
||||
|
||||
if (this->direction == PW_DIRECTION_INPUT) {
|
||||
spa_list_insert (this->rt.links.prev, &link->rt.input_link);
|
||||
link->rt.input = this;
|
||||
}
|
||||
else {
|
||||
spa_list_insert (this->rt.links.prev, &link->rt.output_link);
|
||||
link->rt.output = this;
|
||||
}
|
||||
if (this->direction == PW_DIRECTION_INPUT) {
|
||||
spa_list_insert(this->rt.links.prev, &link->rt.input_link);
|
||||
link->rt.input = this;
|
||||
} else {
|
||||
spa_list_insert(this->rt.links.prev, &link->rt.output_link);
|
||||
link->rt.output = this;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static struct pw_link *
|
||||
find_link (struct pw_port *output_port, struct pw_port *input_port)
|
||||
static struct pw_link *find_link(struct pw_port *output_port, struct pw_port *input_port)
|
||||
{
|
||||
struct pw_link *pl;
|
||||
struct pw_link *pl;
|
||||
|
||||
spa_list_for_each (pl, &output_port->links, output_link) {
|
||||
if (pl->input == input_port)
|
||||
return pl;
|
||||
}
|
||||
return NULL;
|
||||
spa_list_for_each(pl, &output_port->links, output_link) {
|
||||
if (pl->input == input_port)
|
||||
return pl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pw_link *
|
||||
pw_port_get_link (struct pw_port *output_port,
|
||||
struct pw_port *input_port)
|
||||
struct pw_link *pw_port_get_link(struct pw_port *output_port, struct pw_port *input_port)
|
||||
{
|
||||
return find_link (output_port, input_port);
|
||||
return find_link(output_port, input_port);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -127,251 +114,204 @@ pw_port_get_link (struct pw_port *output_port,
|
|||
*
|
||||
* Returns: a new #struct pw_link or %NULL and @error is set.
|
||||
*/
|
||||
struct pw_link *
|
||||
pw_port_link (struct pw_port *output_port,
|
||||
struct pw_port *input_port,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties,
|
||||
char **error)
|
||||
struct pw_link *pw_port_link(struct pw_port *output_port,
|
||||
struct pw_port *input_port,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties, char **error)
|
||||
{
|
||||
struct pw_node *input_node, *output_node;
|
||||
struct pw_link *link;
|
||||
struct pw_node *input_node, *output_node;
|
||||
struct pw_link *link;
|
||||
|
||||
output_node = output_port->node;
|
||||
input_node = input_port->node;
|
||||
output_node = output_port->node;
|
||||
input_node = input_port->node;
|
||||
|
||||
pw_log_debug ("port link %p:%u -> %p:%u", output_node, output_port->port_id, input_node, input_port->port_id);
|
||||
pw_log_debug("port link %p:%u -> %p:%u", output_node, output_port->port_id, input_node,
|
||||
input_port->port_id);
|
||||
|
||||
if (output_node == input_node)
|
||||
goto same_node;
|
||||
if (output_node == input_node)
|
||||
goto same_node;
|
||||
|
||||
if (!spa_list_is_empty (&input_port->links))
|
||||
goto was_linked;
|
||||
if (!spa_list_is_empty(&input_port->links))
|
||||
goto was_linked;
|
||||
|
||||
link = find_link (output_port, input_port);
|
||||
link = find_link(output_port, input_port);
|
||||
|
||||
if (link == NULL) {
|
||||
input_node->live = output_node->live;
|
||||
if (output_node->clock)
|
||||
input_node->clock = output_node->clock;
|
||||
pw_log_debug ("node %p: clock %p, live %d", output_node, output_node->clock, output_node->live);
|
||||
if (link == NULL) {
|
||||
input_node->live = output_node->live;
|
||||
if (output_node->clock)
|
||||
input_node->clock = output_node->clock;
|
||||
pw_log_debug("node %p: clock %p, live %d", output_node, output_node->clock,
|
||||
output_node->live);
|
||||
|
||||
link = pw_link_new (output_node->core,
|
||||
output_port,
|
||||
input_port,
|
||||
format_filter,
|
||||
properties);
|
||||
if (link == NULL)
|
||||
goto no_mem;
|
||||
link = pw_link_new(output_node->core,
|
||||
output_port, input_port, format_filter, properties);
|
||||
if (link == NULL)
|
||||
goto no_mem;
|
||||
|
||||
spa_list_insert (output_port->links.prev, &link->output_link);
|
||||
spa_list_insert (input_port->links.prev, &link->input_link);
|
||||
spa_list_insert(output_port->links.prev, &link->output_link);
|
||||
spa_list_insert(input_port->links.prev, &link->input_link);
|
||||
|
||||
output_node->n_used_output_links++;
|
||||
input_node->n_used_input_links++;
|
||||
output_node->n_used_output_links++;
|
||||
input_node->n_used_input_links++;
|
||||
|
||||
pw_loop_invoke (output_node->data_loop->loop,
|
||||
do_add_link,
|
||||
SPA_ID_INVALID,
|
||||
sizeof (struct pw_link *),
|
||||
&link,
|
||||
output_port);
|
||||
pw_loop_invoke (input_node->data_loop->loop,
|
||||
do_add_link,
|
||||
SPA_ID_INVALID,
|
||||
sizeof (struct pw_link *),
|
||||
&link,
|
||||
input_port);
|
||||
}
|
||||
return link;
|
||||
pw_loop_invoke(output_node->data_loop->loop,
|
||||
do_add_link,
|
||||
SPA_ID_INVALID, sizeof(struct pw_link *), &link, output_port);
|
||||
pw_loop_invoke(input_node->data_loop->loop,
|
||||
do_add_link,
|
||||
SPA_ID_INVALID, sizeof(struct pw_link *), &link, input_port);
|
||||
}
|
||||
return link;
|
||||
|
||||
same_node:
|
||||
{
|
||||
asprintf (error, "can't link a node to itself");
|
||||
return NULL;
|
||||
}
|
||||
was_linked:
|
||||
{
|
||||
asprintf (error, "input port was already linked");
|
||||
return NULL;
|
||||
}
|
||||
no_mem:
|
||||
return NULL;
|
||||
same_node:
|
||||
{
|
||||
asprintf(error, "can't link a node to itself");
|
||||
return NULL;
|
||||
}
|
||||
was_linked:
|
||||
{
|
||||
asprintf(error, "input port was already linked");
|
||||
return NULL;
|
||||
}
|
||||
no_mem:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
pw_port_pause_rt (struct pw_port *port)
|
||||
int pw_port_pause_rt(struct pw_port *port)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (port->state <= PW_PORT_STATE_PAUSED)
|
||||
return SPA_RESULT_OK;
|
||||
if (port->state <= PW_PORT_STATE_PAUSED)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
res = spa_node_port_send_command (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
&SPA_COMMAND_INIT (port->node->core->type.command_node.Pause));
|
||||
port->state = PW_PORT_STATE_PAUSED;
|
||||
pw_log_debug ("port %p: state PAUSED", port);
|
||||
return res;
|
||||
res = spa_node_port_send_command(port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
&SPA_COMMAND_INIT(port->node->core->type.command_node.
|
||||
Pause));
|
||||
port->state = PW_PORT_STATE_PAUSED;
|
||||
pw_log_debug("port %p: state PAUSED", port);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
do_remove_link_done (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
do_remove_link_done(struct spa_loop *loop,
|
||||
bool async, uint32_t seq, size_t size, void *data, void *user_data)
|
||||
{
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *node = port->node;
|
||||
struct pw_link *link = ((struct pw_link**)data)[0];
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *node = port->node;
|
||||
struct pw_link *link = ((struct pw_link **) data)[0];
|
||||
|
||||
pw_log_debug ("port %p: finish unlink", port);
|
||||
if (port->direction == PW_DIRECTION_OUTPUT) {
|
||||
if (link->output) {
|
||||
spa_list_remove (&link->output_link);
|
||||
node->n_used_output_links--;
|
||||
link->output = NULL;
|
||||
}
|
||||
} else {
|
||||
if (link->input) {
|
||||
spa_list_remove (&link->input_link);
|
||||
node->n_used_input_links--;
|
||||
link->input = NULL;
|
||||
}
|
||||
}
|
||||
pw_log_debug("port %p: finish unlink", port);
|
||||
if (port->direction == PW_DIRECTION_OUTPUT) {
|
||||
if (link->output) {
|
||||
spa_list_remove(&link->output_link);
|
||||
node->n_used_output_links--;
|
||||
link->output = NULL;
|
||||
}
|
||||
} else {
|
||||
if (link->input) {
|
||||
spa_list_remove(&link->input_link);
|
||||
node->n_used_input_links--;
|
||||
link->input = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!port->allocated && port->state > PW_PORT_STATE_READY) {
|
||||
pw_log_debug ("port %p: clear buffers on port", port);
|
||||
spa_node_port_use_buffers (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = PW_PORT_STATE_READY;
|
||||
pw_log_debug ("port %p: state READY", port);
|
||||
}
|
||||
if (!port->allocated && port->state > PW_PORT_STATE_READY) {
|
||||
pw_log_debug("port %p: clear buffers on port", port);
|
||||
spa_node_port_use_buffers(port->node->node,
|
||||
port->direction, port->port_id, NULL, 0);
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = PW_PORT_STATE_READY;
|
||||
pw_log_debug("port %p: state READY", port);
|
||||
}
|
||||
|
||||
if (node->n_used_output_links == 0 &&
|
||||
node->n_used_input_links == 0) {
|
||||
pw_node_update_state (node, PW_NODE_STATE_IDLE, NULL);
|
||||
}
|
||||
if (node->n_used_output_links == 0 && node->n_used_input_links == 0) {
|
||||
pw_node_update_state(node, PW_NODE_STATE_IDLE, NULL);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
do_remove_link (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
do_remove_link(struct spa_loop *loop,
|
||||
bool async, uint32_t seq, size_t size, void *data, void *user_data)
|
||||
{
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *this = port->node;
|
||||
struct pw_link *link = ((struct pw_link**)data)[0];
|
||||
int res;
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *this = port->node;
|
||||
struct pw_link *link = ((struct pw_link **) data)[0];
|
||||
int res;
|
||||
|
||||
if (port->direction == PW_DIRECTION_INPUT) {
|
||||
pw_port_pause_rt (link->rt.input);
|
||||
spa_list_remove (&link->rt.input_link);
|
||||
link->rt.input = NULL;
|
||||
} else {
|
||||
pw_port_pause_rt (link->rt.output);
|
||||
spa_list_remove (&link->rt.output_link);
|
||||
link->rt.output = NULL;
|
||||
}
|
||||
if (port->direction == PW_DIRECTION_INPUT) {
|
||||
pw_port_pause_rt(link->rt.input);
|
||||
spa_list_remove(&link->rt.input_link);
|
||||
link->rt.input = NULL;
|
||||
} else {
|
||||
pw_port_pause_rt(link->rt.output);
|
||||
spa_list_remove(&link->rt.output_link);
|
||||
link->rt.output = NULL;
|
||||
}
|
||||
|
||||
res = pw_loop_invoke (this->core->main_loop->loop,
|
||||
do_remove_link_done,
|
||||
seq,
|
||||
sizeof (struct pw_link *),
|
||||
&link,
|
||||
port);
|
||||
return res;
|
||||
res = pw_loop_invoke(this->core->main_loop->loop,
|
||||
do_remove_link_done, seq, sizeof(struct pw_link *), &link, port);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
pw_port_unlink (struct pw_port *port, struct pw_link *link)
|
||||
int pw_port_unlink(struct pw_port *port, struct pw_link *link)
|
||||
{
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF (port, struct impl, this);
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF(port, struct impl, this);
|
||||
|
||||
pw_log_debug ("port %p: start unlink %p", port, link);
|
||||
pw_log_debug("port %p: start unlink %p", port, link);
|
||||
|
||||
res = pw_loop_invoke (port->node->data_loop->loop,
|
||||
do_remove_link,
|
||||
impl->seq++,
|
||||
sizeof (struct pw_link *),
|
||||
&link,
|
||||
port);
|
||||
return res;
|
||||
res = pw_loop_invoke(port->node->data_loop->loop,
|
||||
do_remove_link, impl->seq++, sizeof(struct pw_link *), &link, port);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
do_clear_buffers_done (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
do_clear_buffers_done(struct spa_loop *loop,
|
||||
bool async, uint32_t seq, size_t size, void *data, void *user_data)
|
||||
{
|
||||
struct pw_port *port = user_data;
|
||||
int res;
|
||||
struct pw_port *port = user_data;
|
||||
int res;
|
||||
|
||||
if (port->state <= PW_PORT_STATE_READY)
|
||||
return SPA_RESULT_OK;
|
||||
if (port->state <= PW_PORT_STATE_READY)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pw_log_debug ("port %p: clear buffers finish", port);
|
||||
res = spa_node_port_use_buffers (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = PW_PORT_STATE_READY;
|
||||
pw_log_debug ("port %p: state READY", port);
|
||||
pw_log_debug("port %p: clear buffers finish", port);
|
||||
res = spa_node_port_use_buffers(port->node->node, port->direction, port->port_id, NULL, 0);
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = PW_PORT_STATE_READY;
|
||||
pw_log_debug("port %p: state READY", port);
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
do_clear_buffers (struct spa_loop *loop,
|
||||
bool async,
|
||||
uint32_t seq,
|
||||
size_t size,
|
||||
void *data,
|
||||
void *user_data)
|
||||
do_clear_buffers(struct spa_loop *loop,
|
||||
bool async, uint32_t seq, size_t size, void *data, void *user_data)
|
||||
{
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *node = port->node;
|
||||
int res;
|
||||
struct pw_port *port = user_data;
|
||||
struct pw_node *node = port->node;
|
||||
int res;
|
||||
|
||||
pw_port_pause_rt (port);
|
||||
pw_port_pause_rt(port);
|
||||
|
||||
res = pw_loop_invoke (node->core->main_loop->loop,
|
||||
do_clear_buffers_done,
|
||||
seq,
|
||||
0, NULL,
|
||||
port);
|
||||
return res;
|
||||
res = pw_loop_invoke(node->core->main_loop->loop,
|
||||
do_clear_buffers_done, seq, 0, NULL, port);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
pw_port_clear_buffers (struct pw_port *port)
|
||||
int pw_port_clear_buffers(struct pw_port *port)
|
||||
{
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF (port, struct impl, this);
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF(port, struct impl, this);
|
||||
|
||||
pw_log_debug ("port %p: clear buffers", port);
|
||||
res = pw_loop_invoke (port->node->data_loop->loop,
|
||||
do_clear_buffers,
|
||||
impl->seq++,
|
||||
0, NULL,
|
||||
port);
|
||||
return res;
|
||||
pw_log_debug("port %p: clear buffers", port);
|
||||
res = pw_loop_invoke(port->node->data_loop->loop,
|
||||
do_clear_buffers, impl->seq++, 0, NULL, port);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,54 +36,59 @@ extern "C" {
|
|||
#include <pipewire/server/link.h>
|
||||
|
||||
enum pw_port_state {
|
||||
PW_PORT_STATE_ERROR = -1,
|
||||
PW_PORT_STATE_INIT = 0,
|
||||
PW_PORT_STATE_CONFIGURE = 1,
|
||||
PW_PORT_STATE_READY = 2,
|
||||
PW_PORT_STATE_PAUSED = 3,
|
||||
PW_PORT_STATE_STREAMING = 4,
|
||||
PW_PORT_STATE_ERROR = -1,
|
||||
PW_PORT_STATE_INIT = 0,
|
||||
PW_PORT_STATE_CONFIGURE = 1,
|
||||
PW_PORT_STATE_READY = 2,
|
||||
PW_PORT_STATE_PAUSED = 3,
|
||||
PW_PORT_STATE_STREAMING = 4,
|
||||
};
|
||||
|
||||
struct pw_port {
|
||||
struct spa_list link;
|
||||
struct spa_list link;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener, struct pw_port *));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_port *));
|
||||
|
||||
struct pw_node *node;
|
||||
enum pw_direction direction;
|
||||
uint32_t port_id;
|
||||
enum pw_port_state state;
|
||||
struct spa_port_io io;
|
||||
struct pw_node *node;
|
||||
enum pw_direction direction;
|
||||
uint32_t port_id;
|
||||
enum pw_port_state state;
|
||||
struct spa_port_io io;
|
||||
|
||||
bool allocated;
|
||||
struct pw_memblock buffer_mem;
|
||||
struct spa_buffer **buffers;
|
||||
uint32_t n_buffers;
|
||||
bool allocated;
|
||||
struct pw_memblock buffer_mem;
|
||||
struct spa_buffer **buffers;
|
||||
uint32_t n_buffers;
|
||||
|
||||
struct spa_list links;
|
||||
struct spa_list links;
|
||||
|
||||
struct {
|
||||
struct spa_list links;
|
||||
} rt;
|
||||
struct {
|
||||
struct spa_list links;
|
||||
} rt;
|
||||
};
|
||||
|
||||
struct pw_port * pw_port_new (struct pw_node *node,
|
||||
enum pw_direction direction,
|
||||
uint32_t port_id);
|
||||
void pw_port_destroy (struct pw_port *port);
|
||||
struct pw_port *
|
||||
pw_port_new(struct pw_node *node, enum pw_direction direction, uint32_t port_id);
|
||||
|
||||
void
|
||||
pw_port_destroy(struct pw_port *port);
|
||||
|
||||
|
||||
struct pw_link * pw_port_link (struct pw_port *output_port,
|
||||
struct pw_port *input_port,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties,
|
||||
char **error);
|
||||
int pw_port_unlink (struct pw_port *port,
|
||||
struct pw_link *link);
|
||||
struct pw_link *
|
||||
pw_port_link(struct pw_port *output_port,
|
||||
struct pw_port *input_port,
|
||||
struct spa_format **format_filter,
|
||||
struct pw_properties *properties,
|
||||
char **error);
|
||||
|
||||
int pw_port_pause_rt (struct pw_port *port);
|
||||
int pw_port_clear_buffers (struct pw_port *port);
|
||||
int
|
||||
pw_port_unlink(struct pw_port *port, struct pw_link *link);
|
||||
|
||||
int
|
||||
pw_port_pause_rt(struct pw_port *port);
|
||||
|
||||
int
|
||||
pw_port_clear_buffers(struct pw_port *port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -19,4 +19,4 @@
|
|||
|
||||
#include "pipewire/client/pipewire.h"
|
||||
|
||||
bool pw_protocol_native_server_setup (struct pw_resource *resource);
|
||||
bool pw_protocol_native_server_setup(struct pw_resource *resource);
|
||||
|
|
|
|||
|
|
@ -23,66 +23,61 @@
|
|||
#include "pipewire/server/resource.h"
|
||||
|
||||
struct impl {
|
||||
struct pw_resource this;
|
||||
struct pw_resource this;
|
||||
};
|
||||
|
||||
struct pw_resource *
|
||||
pw_resource_new (struct pw_client *client,
|
||||
uint32_t id,
|
||||
uint32_t type,
|
||||
void *object,
|
||||
pw_destroy_t destroy)
|
||||
struct pw_resource *pw_resource_new(struct pw_client *client,
|
||||
uint32_t id, uint32_t type, void *object, pw_destroy_t destroy)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_resource *this;
|
||||
struct impl *impl;
|
||||
struct pw_resource *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this->core = client->core;
|
||||
this->client = client;
|
||||
this->type = type;
|
||||
this->object = object;
|
||||
this->destroy = destroy;
|
||||
this = &impl->this;
|
||||
this->core = client->core;
|
||||
this->client = client;
|
||||
this->type = type;
|
||||
this->object = object;
|
||||
this->destroy = destroy;
|
||||
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
if (id == SPA_ID_INVALID) {
|
||||
this->id = pw_map_insert_new (&client->objects, this);
|
||||
} else if (!pw_map_insert_at (&client->objects, id, this))
|
||||
goto in_use;
|
||||
if (id == SPA_ID_INVALID) {
|
||||
this->id = pw_map_insert_new(&client->objects, this);
|
||||
} else if (!pw_map_insert_at(&client->objects, id, this))
|
||||
goto in_use;
|
||||
|
||||
this->id = id;
|
||||
this->id = id;
|
||||
|
||||
pw_log_debug ("resource %p: new for client %p id %u", this, client, this->id);
|
||||
pw_signal_emit (&client->resource_added, client, this);
|
||||
pw_log_debug("resource %p: new for client %p id %u", this, client, this->id);
|
||||
pw_signal_emit(&client->resource_added, client, this);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
|
||||
in_use:
|
||||
pw_log_debug ("resource %p: id %u in use for client %p", this, id, client);
|
||||
free (impl);
|
||||
return NULL;
|
||||
in_use:
|
||||
pw_log_debug("resource %p: id %u in use for client %p", this, id, client);
|
||||
free(impl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pw_resource_destroy (struct pw_resource *resource)
|
||||
void pw_resource_destroy(struct pw_resource *resource)
|
||||
{
|
||||
struct pw_client *client = resource->client;
|
||||
struct pw_client *client = resource->client;
|
||||
|
||||
pw_log_trace ("resource %p: destroy %u", resource, resource->id);
|
||||
pw_signal_emit (&resource->destroy_signal, resource);
|
||||
pw_log_trace("resource %p: destroy %u", resource, resource->id);
|
||||
pw_signal_emit(&resource->destroy_signal, resource);
|
||||
|
||||
pw_map_insert_at (&client->objects, resource->id, NULL);
|
||||
pw_signal_emit (&client->resource_removed, client, resource);
|
||||
pw_map_insert_at(&client->objects, resource->id, NULL);
|
||||
pw_signal_emit(&client->resource_removed, client, resource);
|
||||
|
||||
if (resource->destroy)
|
||||
resource->destroy (resource);
|
||||
if (resource->destroy)
|
||||
resource->destroy(resource);
|
||||
|
||||
if (client->core_resource)
|
||||
pw_core_notify_remove_id (client->core_resource, resource->id);
|
||||
if (client->core_resource)
|
||||
pw_core_notify_remove_id(client->core_resource, resource->id);
|
||||
|
||||
free (resource);
|
||||
free(resource);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,32 +32,31 @@ extern "C" {
|
|||
#include <pipewire/client/sig.h>
|
||||
#include <pipewire/server/core.h>
|
||||
|
||||
typedef void (*pw_destroy_t) (void *object);
|
||||
typedef void (*pw_destroy_t) (void *object);
|
||||
|
||||
struct pw_resource {
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
struct pw_core *core;
|
||||
struct spa_list link;
|
||||
|
||||
struct pw_client *client;
|
||||
struct pw_client *client;
|
||||
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
void *object;
|
||||
pw_destroy_t destroy;
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
void *object;
|
||||
pw_destroy_t destroy;
|
||||
|
||||
const struct pw_interface *iface;
|
||||
const void *implementation;
|
||||
const struct pw_interface *iface;
|
||||
const void *implementation;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_resource *resource));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_resource * resource));
|
||||
};
|
||||
|
||||
struct pw_resource * pw_resource_new (struct pw_client *client,
|
||||
uint32_t id,
|
||||
uint32_t type,
|
||||
void *object,
|
||||
pw_destroy_t destroy);
|
||||
void pw_resource_destroy (struct pw_resource *resource);
|
||||
struct pw_resource *
|
||||
pw_resource_new(struct pw_client *client,
|
||||
uint32_t id, uint32_t type, void *object, pw_destroy_t destroy);
|
||||
|
||||
void
|
||||
pw_resource_destroy(struct pw_resource *resource);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,60 +24,57 @@
|
|||
#include "pipewire/server/work-queue.h"
|
||||
|
||||
struct work_item {
|
||||
uint32_t id;
|
||||
void *obj;
|
||||
uint32_t seq;
|
||||
int res;
|
||||
pw_work_func_t func;
|
||||
void *data;
|
||||
struct spa_list link;
|
||||
uint32_t id;
|
||||
void *obj;
|
||||
uint32_t seq;
|
||||
int res;
|
||||
pw_work_func_t func;
|
||||
void *data;
|
||||
struct spa_list link;
|
||||
};
|
||||
|
||||
struct impl {
|
||||
struct pw_work_queue this;
|
||||
struct pw_work_queue this;
|
||||
|
||||
struct spa_source *wakeup;
|
||||
uint32_t counter;
|
||||
struct spa_source *wakeup;
|
||||
uint32_t counter;
|
||||
|
||||
struct spa_list work_list;
|
||||
struct spa_list free_list;
|
||||
int n_queued;
|
||||
struct spa_list work_list;
|
||||
struct spa_list free_list;
|
||||
int n_queued;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
process_work_queue (struct spa_loop_utils *utils,
|
||||
struct spa_source *source,
|
||||
void *data)
|
||||
static void process_work_queue(struct spa_loop_utils *utils, struct spa_source *source, void *data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
struct pw_work_queue *this = &impl->this;
|
||||
struct work_item *item, *tmp;
|
||||
struct impl *impl = data;
|
||||
struct pw_work_queue *this = &impl->this;
|
||||
struct work_item *item, *tmp;
|
||||
|
||||
spa_list_for_each_safe (item, tmp, &impl->work_list, link) {
|
||||
if (item->seq != SPA_ID_INVALID) {
|
||||
pw_log_debug ("work-queue %p: %d waiting for item %p %d", this, impl->n_queued,
|
||||
item->obj, item->seq);
|
||||
continue;
|
||||
}
|
||||
spa_list_for_each_safe(item, tmp, &impl->work_list, link) {
|
||||
if (item->seq != SPA_ID_INVALID) {
|
||||
pw_log_debug("work-queue %p: %d waiting for item %p %d", this,
|
||||
impl->n_queued, item->obj, item->seq);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item->res == SPA_RESULT_WAIT_SYNC &&
|
||||
item != spa_list_first (&impl->work_list, struct work_item, link)) {
|
||||
pw_log_debug ("work-queue %p: %d sync item %p not head", this, impl->n_queued,
|
||||
item->obj);
|
||||
continue;
|
||||
}
|
||||
if (item->res == SPA_RESULT_WAIT_SYNC &&
|
||||
item != spa_list_first(&impl->work_list, struct work_item, link)) {
|
||||
pw_log_debug("work-queue %p: %d sync item %p not head", this,
|
||||
impl->n_queued, item->obj);
|
||||
continue;
|
||||
}
|
||||
|
||||
spa_list_remove (&item->link);
|
||||
impl->n_queued--;
|
||||
spa_list_remove(&item->link);
|
||||
impl->n_queued--;
|
||||
|
||||
if (item->func) {
|
||||
pw_log_debug ("work-queue %p: %d process work item %p %d %d", this, impl->n_queued,
|
||||
item->obj, item->seq, item->res);
|
||||
item->func (item->obj, item->data, item->res, item->id);
|
||||
}
|
||||
spa_list_insert (impl->free_list.prev, &item->link);
|
||||
}
|
||||
if (item->func) {
|
||||
pw_log_debug("work-queue %p: %d process work item %p %d %d", this,
|
||||
impl->n_queued, item->obj, item->seq, item->res);
|
||||
item->func(item->obj, item->data, item->res, item->id);
|
||||
}
|
||||
spa_list_insert(impl->free_list.prev, &item->link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,142 +84,129 @@ process_work_queue (struct spa_loop_utils *utils,
|
|||
*
|
||||
* Returns: a new #struct pw_work_queue
|
||||
*/
|
||||
struct pw_work_queue *
|
||||
pw_work_queue_new (struct pw_loop *loop)
|
||||
struct pw_work_queue *pw_work_queue_new(struct pw_loop *loop)
|
||||
{
|
||||
struct impl *impl;
|
||||
struct pw_work_queue *this;
|
||||
struct impl *impl;
|
||||
struct pw_work_queue *this;
|
||||
|
||||
impl = calloc (1, sizeof (struct impl));
|
||||
pw_log_debug ("work-queue %p: new", impl);
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
pw_log_debug("work-queue %p: new", impl);
|
||||
|
||||
this = &impl->this;
|
||||
this->loop = loop;
|
||||
pw_signal_init (&this->destroy_signal);
|
||||
this = &impl->this;
|
||||
this->loop = loop;
|
||||
pw_signal_init(&this->destroy_signal);
|
||||
|
||||
impl->wakeup = pw_loop_add_event (this->loop,
|
||||
process_work_queue,
|
||||
impl);
|
||||
impl->wakeup = pw_loop_add_event(this->loop, process_work_queue, impl);
|
||||
|
||||
spa_list_init (&impl->work_list);
|
||||
spa_list_init (&impl->free_list);
|
||||
spa_list_init(&impl->work_list);
|
||||
spa_list_init(&impl->free_list);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
pw_work_queue_destroy (struct pw_work_queue * queue)
|
||||
void pw_work_queue_destroy(struct pw_work_queue *queue)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (queue, struct impl, this);
|
||||
struct work_item *item, *tmp;
|
||||
struct impl *impl = SPA_CONTAINER_OF(queue, struct impl, this);
|
||||
struct work_item *item, *tmp;
|
||||
|
||||
pw_log_debug ("work-queue %p: destroy", impl);
|
||||
pw_signal_emit (&queue->destroy_signal, queue);
|
||||
pw_log_debug("work-queue %p: destroy", impl);
|
||||
pw_signal_emit(&queue->destroy_signal, queue);
|
||||
|
||||
pw_loop_destroy_source (queue->loop, impl->wakeup);
|
||||
pw_loop_destroy_source(queue->loop, impl->wakeup);
|
||||
|
||||
spa_list_for_each_safe (item, tmp, &impl->work_list, link) {
|
||||
pw_log_warn ("work-queue %p: cancel work item %p %d %d", queue,
|
||||
item->obj, item->seq, item->res);
|
||||
free (item);
|
||||
}
|
||||
spa_list_for_each_safe (item, tmp, &impl->free_list, link)
|
||||
free (item);
|
||||
spa_list_for_each_safe(item, tmp, &impl->work_list, link) {
|
||||
pw_log_warn("work-queue %p: cancel work item %p %d %d", queue,
|
||||
item->obj, item->seq, item->res);
|
||||
free(item);
|
||||
}
|
||||
spa_list_for_each_safe(item, tmp, &impl->free_list, link)
|
||||
free(item);
|
||||
|
||||
free (impl);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pw_work_queue_add (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
int res,
|
||||
pw_work_func_t func,
|
||||
void *data)
|
||||
pw_work_queue_add(struct pw_work_queue *queue, void *obj, int res, pw_work_func_t func, void *data)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (queue, struct impl, this);
|
||||
struct work_item *item;
|
||||
bool have_work = false;
|
||||
struct impl *impl = SPA_CONTAINER_OF(queue, struct impl, this);
|
||||
struct work_item *item;
|
||||
bool have_work = false;
|
||||
|
||||
if (!spa_list_is_empty (&impl->free_list)) {
|
||||
item = spa_list_first (&impl->free_list, struct work_item, link);
|
||||
spa_list_remove (&item->link);
|
||||
} else {
|
||||
item = malloc (sizeof (struct work_item));
|
||||
if (item == NULL)
|
||||
return SPA_ID_INVALID;
|
||||
}
|
||||
item->id = ++impl->counter;
|
||||
item->obj = obj;
|
||||
item->func = func;
|
||||
item->data = data;
|
||||
if (!spa_list_is_empty(&impl->free_list)) {
|
||||
item = spa_list_first(&impl->free_list, struct work_item, link);
|
||||
spa_list_remove(&item->link);
|
||||
} else {
|
||||
item = malloc(sizeof(struct work_item));
|
||||
if (item == NULL)
|
||||
return SPA_ID_INVALID;
|
||||
}
|
||||
item->id = ++impl->counter;
|
||||
item->obj = obj;
|
||||
item->func = func;
|
||||
item->data = data;
|
||||
|
||||
if (SPA_RESULT_IS_ASYNC (res)) {
|
||||
item->seq = SPA_RESULT_ASYNC_SEQ (res);
|
||||
item->res = res;
|
||||
pw_log_debug ("work-queue %p: defer async %d for object %p", queue, item->seq, obj);
|
||||
} else if (res == SPA_RESULT_WAIT_SYNC) {
|
||||
pw_log_debug ("work-queue %p: wait sync object %p", queue, obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
} else {
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
pw_log_debug ("work-queue %p: defer object %p", queue, obj);
|
||||
}
|
||||
spa_list_insert (impl->work_list.prev, &item->link);
|
||||
impl->n_queued++;
|
||||
if (SPA_RESULT_IS_ASYNC(res)) {
|
||||
item->seq = SPA_RESULT_ASYNC_SEQ(res);
|
||||
item->res = res;
|
||||
pw_log_debug("work-queue %p: defer async %d for object %p", queue, item->seq, obj);
|
||||
} else if (res == SPA_RESULT_WAIT_SYNC) {
|
||||
pw_log_debug("work-queue %p: wait sync object %p", queue, obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
} else {
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
pw_log_debug("work-queue %p: defer object %p", queue, obj);
|
||||
}
|
||||
spa_list_insert(impl->work_list.prev, &item->link);
|
||||
impl->n_queued++;
|
||||
|
||||
if (have_work)
|
||||
pw_loop_signal_event (impl->this.loop, impl->wakeup);
|
||||
if (have_work)
|
||||
pw_loop_signal_event(impl->this.loop, impl->wakeup);
|
||||
|
||||
return item->id;
|
||||
return item->id;
|
||||
}
|
||||
|
||||
void
|
||||
pw_work_queue_cancel (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
uint32_t id)
|
||||
void pw_work_queue_cancel(struct pw_work_queue *queue, void *obj, uint32_t id)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF (queue, struct impl, this);
|
||||
bool have_work = false;
|
||||
struct work_item *item;
|
||||
struct impl *impl = SPA_CONTAINER_OF(queue, struct impl, this);
|
||||
bool have_work = false;
|
||||
struct work_item *item;
|
||||
|
||||
spa_list_for_each (item, &impl->work_list, link) {
|
||||
if ((id == SPA_ID_INVALID || item->id == id) && (obj == NULL || item->obj == obj)) {
|
||||
pw_log_debug ("work-queue %p: cancel defer %d for object %p", queue, item->seq, item->obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->func = NULL;
|
||||
have_work = true;
|
||||
}
|
||||
}
|
||||
if (have_work)
|
||||
pw_loop_signal_event (impl->this.loop, impl->wakeup);
|
||||
spa_list_for_each(item, &impl->work_list, link) {
|
||||
if ((id == SPA_ID_INVALID || item->id == id) && (obj == NULL || item->obj == obj)) {
|
||||
pw_log_debug("work-queue %p: cancel defer %d for object %p", queue,
|
||||
item->seq, item->obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->func = NULL;
|
||||
have_work = true;
|
||||
}
|
||||
}
|
||||
if (have_work)
|
||||
pw_loop_signal_event(impl->this.loop, impl->wakeup);
|
||||
}
|
||||
|
||||
bool
|
||||
pw_work_queue_complete (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
uint32_t seq,
|
||||
int res)
|
||||
bool pw_work_queue_complete(struct pw_work_queue *queue, void *obj, uint32_t seq, int res)
|
||||
{
|
||||
struct work_item *item;
|
||||
struct impl *impl = SPA_CONTAINER_OF (queue, struct impl, this);
|
||||
bool have_work = false;
|
||||
struct work_item *item;
|
||||
struct impl *impl = SPA_CONTAINER_OF(queue, struct impl, this);
|
||||
bool have_work = false;
|
||||
|
||||
spa_list_for_each (item, &impl->work_list, link) {
|
||||
if (item->obj == obj && item->seq == seq) {
|
||||
pw_log_debug ("work-queue %p: found defered %d for object %p", queue, seq, obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
}
|
||||
}
|
||||
if (!have_work) {
|
||||
pw_log_debug ("work-queue %p: no defered %d found for object %p", queue, seq, obj);
|
||||
} else {
|
||||
pw_loop_signal_event (impl->this.loop, impl->wakeup);
|
||||
}
|
||||
return have_work;
|
||||
spa_list_for_each(item, &impl->work_list, link) {
|
||||
if (item->obj == obj && item->seq == seq) {
|
||||
pw_log_debug("work-queue %p: found defered %d for object %p", queue, seq,
|
||||
obj);
|
||||
item->seq = SPA_ID_INVALID;
|
||||
item->res = res;
|
||||
have_work = true;
|
||||
}
|
||||
}
|
||||
if (!have_work) {
|
||||
pw_log_debug("work-queue %p: no defered %d found for object %p", queue, seq, obj);
|
||||
} else {
|
||||
pw_loop_signal_event(impl->this.loop, impl->wakeup);
|
||||
}
|
||||
return have_work;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ extern "C" {
|
|||
|
||||
#include <pipewire/client/loop.h>
|
||||
|
||||
typedef void (*pw_work_func_t) (void *obj,
|
||||
void *data,
|
||||
int res,
|
||||
uint32_t id);
|
||||
typedef void (*pw_work_func_t) (void *obj, void *data, int res, uint32_t id);
|
||||
|
||||
/**
|
||||
* pw_work_queue:
|
||||
|
|
@ -37,30 +34,30 @@ typedef void (*pw_work_func_t) (void *obj,
|
|||
* PipeWire work queue object.
|
||||
*/
|
||||
struct pw_work_queue {
|
||||
struct pw_loop *loop;
|
||||
struct pw_loop *loop;
|
||||
|
||||
PW_SIGNAL (destroy_signal, (struct pw_listener *listener,
|
||||
struct pw_work_queue *queue));
|
||||
PW_SIGNAL(destroy_signal, (struct pw_listener * listener, struct pw_work_queue * queue));
|
||||
};
|
||||
|
||||
struct pw_work_queue * pw_work_queue_new (struct pw_loop *loop);
|
||||
void pw_work_queue_destroy (struct pw_work_queue *queue);
|
||||
struct pw_work_queue *
|
||||
pw_work_queue_new(struct pw_loop *loop);
|
||||
|
||||
uint32_t pw_work_queue_add (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
int res,
|
||||
pw_work_func_t func,
|
||||
void *data);
|
||||
void pw_work_queue_cancel (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
uint32_t id);
|
||||
bool pw_work_queue_complete (struct pw_work_queue *queue,
|
||||
void *obj,
|
||||
uint32_t seq,
|
||||
int res);
|
||||
void
|
||||
pw_work_queue_destroy(struct pw_work_queue *queue);
|
||||
|
||||
uint32_t
|
||||
pw_work_queue_add(struct pw_work_queue *queue,
|
||||
void *obj, int res,
|
||||
pw_work_func_t func, void *data);
|
||||
|
||||
void
|
||||
pw_work_queue_cancel(struct pw_work_queue *queue, void *obj, uint32_t id);
|
||||
|
||||
bool
|
||||
pw_work_queue_complete(struct pw_work_queue *queue, void *obj, uint32_t seq, int res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PIPEWIRE_WORK_QUEUE_H__ */
|
||||
#endif /* __PIPEWIRE_WORK_QUEUE_H__ */
|
||||
|
|
|
|||
|
|
@ -24,280 +24,238 @@
|
|||
#include <spa/lib/debug.h>
|
||||
|
||||
struct data {
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct pw_context *context;
|
||||
bool running;
|
||||
struct pw_loop *loop;
|
||||
struct pw_context *context;
|
||||
|
||||
struct pw_listener on_state_changed;
|
||||
struct pw_listener on_subscription;
|
||||
struct pw_listener on_state_changed;
|
||||
struct pw_listener on_subscription;
|
||||
};
|
||||
|
||||
static void
|
||||
print_properties (struct spa_dict *props, char mark)
|
||||
static void print_properties(struct spa_dict *props, char mark)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
struct spa_dict_item *item;
|
||||
|
||||
if (props == NULL)
|
||||
return;
|
||||
if (props == NULL)
|
||||
return;
|
||||
|
||||
printf ("%c\tproperties:\n", mark);
|
||||
spa_dict_for_each (item, props) {
|
||||
printf ("%c\t\t%s = \"%s\"\n", mark, item->key, item->value);
|
||||
}
|
||||
printf("%c\tproperties:\n", mark);
|
||||
spa_dict_for_each(item, props) {
|
||||
printf("%c\t\t%s = \"%s\"\n", mark, item->key, item->value);
|
||||
}
|
||||
}
|
||||
|
||||
struct dumpdata {
|
||||
bool print_mark;
|
||||
bool print_all;
|
||||
bool print_mark;
|
||||
bool print_all;
|
||||
};
|
||||
|
||||
#define MARK_CHANGE(f) ((data->print_mark && ((info)->change_mask & (1 << (f)))) ? '*' : ' ')
|
||||
|
||||
static void
|
||||
dump_core_info (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_core_info *info,
|
||||
void *user_data)
|
||||
dump_core_info(struct pw_context *c, int res, const struct pw_core_info *info, void *user_data)
|
||||
{
|
||||
struct dumpdata *data = user_data;
|
||||
struct dumpdata *data = user_data;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
printf ("\tid: %u\n", info->id);
|
||||
printf ("\ttype: %s\n", PIPEWIRE_TYPE__Core);
|
||||
if (data->print_all) {
|
||||
printf ("%c\tuser-name: \"%s\"\n", MARK_CHANGE (0), info->user_name);
|
||||
printf ("%c\thost-name: \"%s\"\n", MARK_CHANGE (1), info->host_name);
|
||||
printf ("%c\tversion: \"%s\"\n", MARK_CHANGE (2), info->version);
|
||||
printf ("%c\tname: \"%s\"\n", MARK_CHANGE (3), info->name);
|
||||
printf ("%c\tcookie: %u\n", MARK_CHANGE (4), info->cookie);
|
||||
print_properties (info->props, MARK_CHANGE (5));
|
||||
}
|
||||
printf("\tid: %u\n", info->id);
|
||||
printf("\ttype: %s\n", PIPEWIRE_TYPE__Core);
|
||||
if (data->print_all) {
|
||||
printf("%c\tuser-name: \"%s\"\n", MARK_CHANGE(0), info->user_name);
|
||||
printf("%c\thost-name: \"%s\"\n", MARK_CHANGE(1), info->host_name);
|
||||
printf("%c\tversion: \"%s\"\n", MARK_CHANGE(2), info->version);
|
||||
printf("%c\tname: \"%s\"\n", MARK_CHANGE(3), info->name);
|
||||
printf("%c\tcookie: %u\n", MARK_CHANGE(4), info->cookie);
|
||||
print_properties(info->props, MARK_CHANGE(5));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_client_info (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_client_info *info,
|
||||
void *user_data)
|
||||
dump_client_info(struct pw_context *c, int res, const struct pw_client_info *info, void *user_data)
|
||||
{
|
||||
struct dumpdata *data = user_data;
|
||||
struct dumpdata *data = user_data;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
printf ("\tid: %u\n", info->id);
|
||||
printf ("\ttype: %s\n", PIPEWIRE_TYPE__Client);
|
||||
if (data->print_all) {
|
||||
print_properties (info->props, MARK_CHANGE (0));
|
||||
}
|
||||
printf("\tid: %u\n", info->id);
|
||||
printf("\ttype: %s\n", PIPEWIRE_TYPE__Client);
|
||||
if (data->print_all) {
|
||||
print_properties(info->props, MARK_CHANGE(0));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_node_info (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_node_info *info,
|
||||
void *user_data)
|
||||
dump_node_info(struct pw_context *c, int res, const struct pw_node_info *info, void *user_data)
|
||||
{
|
||||
struct dumpdata *data = user_data;
|
||||
struct dumpdata *data = user_data;
|
||||
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf ("\tError introspecting node: %d\n", res);
|
||||
return;
|
||||
}
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf("\tError introspecting node: %d\n", res);
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("\tid: %u\n", info->id);
|
||||
printf ("\ttype: %s\n", PIPEWIRE_TYPE__Node);
|
||||
if (data->print_all) {
|
||||
int i;
|
||||
printf("\tid: %u\n", info->id);
|
||||
printf("\ttype: %s\n", PIPEWIRE_TYPE__Node);
|
||||
if (data->print_all) {
|
||||
int i;
|
||||
|
||||
printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name);
|
||||
printf ("%c\tinputs: %u/%u\n", MARK_CHANGE (1), info->n_inputs, info->max_inputs);
|
||||
printf ("%c\tinput formats:\n", MARK_CHANGE (2));
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
spa_debug_format (info->input_formats[i], c->type.map);
|
||||
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
printf("%c\tinputs: %u/%u\n", MARK_CHANGE(1), info->n_inputs, info->max_inputs);
|
||||
printf("%c\tinput formats:\n", MARK_CHANGE(2));
|
||||
for (i = 0; i < info->n_input_formats; i++)
|
||||
spa_debug_format(info->input_formats[i], c->type.map);
|
||||
|
||||
printf ("%c\toutputs: %u/%u\n", MARK_CHANGE (3), info->n_outputs, info->max_outputs);
|
||||
printf ("%c\toutput formats:\n", MARK_CHANGE (4));
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
spa_debug_format (info->output_formats[i], c->type.map);
|
||||
printf("%c\toutputs: %u/%u\n", MARK_CHANGE(3), info->n_outputs, info->max_outputs);
|
||||
printf("%c\toutput formats:\n", MARK_CHANGE(4));
|
||||
for (i = 0; i < info->n_output_formats; i++)
|
||||
spa_debug_format(info->output_formats[i], c->type.map);
|
||||
|
||||
printf ("%c\tstate: \"%s\"", MARK_CHANGE (5), pw_node_state_as_string (info->state));
|
||||
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
||||
printf (" \"%s\"\n", info->error);
|
||||
else
|
||||
printf ("\n");
|
||||
print_properties (info->props, MARK_CHANGE (6));
|
||||
}
|
||||
printf("%c\tstate: \"%s\"", MARK_CHANGE(5), pw_node_state_as_string(info->state));
|
||||
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
||||
printf(" \"%s\"\n", info->error);
|
||||
else
|
||||
printf("\n");
|
||||
print_properties(info->props, MARK_CHANGE(6));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_module_info (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_module_info *info,
|
||||
void *user_data)
|
||||
dump_module_info(struct pw_context *c, int res, const struct pw_module_info *info, void *user_data)
|
||||
{
|
||||
struct dumpdata *data = user_data;
|
||||
struct dumpdata *data = user_data;
|
||||
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf ("\tError introspecting module: %d\n", res);
|
||||
return;
|
||||
}
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf("\tError introspecting module: %d\n", res);
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("\tid: %u\n", info->id);
|
||||
printf ("\ttype: %s\n", PIPEWIRE_TYPE__Module);
|
||||
if (data->print_all) {
|
||||
printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name);
|
||||
printf ("%c\tfilename: \"%s\"\n", MARK_CHANGE (1), info->filename);
|
||||
printf ("%c\targs: \"%s\"\n", MARK_CHANGE (2), info->args);
|
||||
print_properties (info->props, MARK_CHANGE (3));
|
||||
}
|
||||
printf("\tid: %u\n", info->id);
|
||||
printf("\ttype: %s\n", PIPEWIRE_TYPE__Module);
|
||||
if (data->print_all) {
|
||||
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
printf("%c\tfilename: \"%s\"\n", MARK_CHANGE(1), info->filename);
|
||||
printf("%c\targs: \"%s\"\n", MARK_CHANGE(2), info->args);
|
||||
print_properties(info->props, MARK_CHANGE(3));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_link_info (struct pw_context *c,
|
||||
int res,
|
||||
const struct pw_link_info *info,
|
||||
void *user_data)
|
||||
dump_link_info(struct pw_context *c, int res, const struct pw_link_info *info, void *user_data)
|
||||
{
|
||||
struct dumpdata *data = user_data;
|
||||
struct dumpdata *data = user_data;
|
||||
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf ("\tError introspecting link: %d\n", res);
|
||||
return;
|
||||
}
|
||||
if (info == NULL) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
printf("\tError introspecting link: %d\n", res);
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("\tid: %u\n", info->id);
|
||||
printf ("\ttype: %s\n", PIPEWIRE_TYPE__Link);
|
||||
if (data->print_all) {
|
||||
printf ("%c\toutput-node-id: %u\n", MARK_CHANGE (0), info->output_node_id);
|
||||
printf ("%c\toutput-port-id: %u\n", MARK_CHANGE (1), info->output_port_id);
|
||||
printf ("%c\tinput-node-id: %u\n", MARK_CHANGE (2), info->input_node_id);
|
||||
printf ("%c\tinput-port-id: %u\n", MARK_CHANGE (3), info->input_port_id);
|
||||
}
|
||||
printf("\tid: %u\n", info->id);
|
||||
printf("\ttype: %s\n", PIPEWIRE_TYPE__Link);
|
||||
if (data->print_all) {
|
||||
printf("%c\toutput-node-id: %u\n", MARK_CHANGE(0), info->output_node_id);
|
||||
printf("%c\toutput-port-id: %u\n", MARK_CHANGE(1), info->output_port_id);
|
||||
printf("%c\tinput-node-id: %u\n", MARK_CHANGE(2), info->input_node_id);
|
||||
printf("%c\tinput-port-id: %u\n", MARK_CHANGE(3), info->input_port_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_object (struct pw_context *context,
|
||||
uint32_t type,
|
||||
uint32_t id,
|
||||
struct dumpdata *data)
|
||||
dump_object(struct pw_context *context, uint32_t type, uint32_t id, struct dumpdata *data)
|
||||
{
|
||||
if (type == context->type.core) {
|
||||
pw_context_get_core_info (context,
|
||||
dump_core_info,
|
||||
data);
|
||||
} else if (type == context->type.node) {
|
||||
pw_context_get_node_info_by_id (context,
|
||||
id,
|
||||
dump_node_info,
|
||||
data);
|
||||
} else if (type == context->type.module) {
|
||||
pw_context_get_module_info_by_id (context,
|
||||
id,
|
||||
dump_module_info,
|
||||
data);
|
||||
} else if (type == context->type.client) {
|
||||
pw_context_get_client_info_by_id (context,
|
||||
id,
|
||||
dump_client_info,
|
||||
data);
|
||||
} else if (type == context->type.link) {
|
||||
pw_context_get_link_info_by_id (context,
|
||||
id,
|
||||
dump_link_info,
|
||||
data);
|
||||
} else {
|
||||
printf ("\tid: %u\n", id);
|
||||
}
|
||||
if (type == context->type.core) {
|
||||
pw_context_get_core_info(context, dump_core_info, data);
|
||||
} else if (type == context->type.node) {
|
||||
pw_context_get_node_info_by_id(context, id, dump_node_info, data);
|
||||
} else if (type == context->type.module) {
|
||||
pw_context_get_module_info_by_id(context, id, dump_module_info, data);
|
||||
} else if (type == context->type.client) {
|
||||
pw_context_get_client_info_by_id(context, id, dump_client_info, data);
|
||||
} else if (type == context->type.link) {
|
||||
pw_context_get_link_info_by_id(context, id, dump_link_info, data);
|
||||
} else {
|
||||
printf("\tid: %u\n", id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_subscription (struct pw_listener *listener,
|
||||
struct pw_context *context,
|
||||
enum pw_subscription_event event,
|
||||
uint32_t type,
|
||||
uint32_t id)
|
||||
on_subscription(struct pw_listener *listener,
|
||||
struct pw_context *context,
|
||||
enum pw_subscription_event event, uint32_t type, uint32_t id)
|
||||
{
|
||||
struct dumpdata dd;
|
||||
struct dumpdata dd;
|
||||
|
||||
switch (event) {
|
||||
case PW_SUBSCRIPTION_EVENT_NEW:
|
||||
printf ("added:\n");
|
||||
dd.print_mark = false;
|
||||
dd.print_all = true;
|
||||
dump_object (context, type, id, &dd);
|
||||
break;
|
||||
switch (event) {
|
||||
case PW_SUBSCRIPTION_EVENT_NEW:
|
||||
printf("added:\n");
|
||||
dd.print_mark = false;
|
||||
dd.print_all = true;
|
||||
dump_object(context, type, id, &dd);
|
||||
break;
|
||||
|
||||
case PW_SUBSCRIPTION_EVENT_CHANGE:
|
||||
printf ("changed:\n");
|
||||
dd.print_mark = true;
|
||||
dd.print_all = true;
|
||||
dump_object (context, type, id, &dd);
|
||||
break;
|
||||
case PW_SUBSCRIPTION_EVENT_CHANGE:
|
||||
printf("changed:\n");
|
||||
dd.print_mark = true;
|
||||
dd.print_all = true;
|
||||
dump_object(context, type, id, &dd);
|
||||
break;
|
||||
|
||||
case PW_SUBSCRIPTION_EVENT_REMOVE:
|
||||
printf ("removed:\n");
|
||||
dd.print_mark = false;
|
||||
dd.print_all = false;
|
||||
dump_object (context, type, id, &dd);
|
||||
break;
|
||||
}
|
||||
case PW_SUBSCRIPTION_EVENT_REMOVE:
|
||||
printf("removed:\n");
|
||||
dd.print_mark = false;
|
||||
dd.print_all = false;
|
||||
dump_object(context, type, id, &dd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_state_changed (struct pw_listener *listener,
|
||||
struct pw_context *context)
|
||||
static void on_state_changed(struct pw_listener *listener, struct pw_context *context)
|
||||
{
|
||||
struct data *data = SPA_CONTAINER_OF (listener, struct data, on_state_changed);
|
||||
struct data *data = SPA_CONTAINER_OF(listener, struct data, on_state_changed);
|
||||
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf ("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
switch (context->state) {
|
||||
case PW_CONTEXT_STATE_ERROR:
|
||||
printf("context error: %s\n", context->error);
|
||||
data->running = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("context state: \"%s\"\n", pw_context_state_as_string (context->state));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("context state: \"%s\"\n", pw_context_state_as_string(context->state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct data data;
|
||||
struct data data;
|
||||
|
||||
pw_init (&argc, &argv);
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
data.loop = pw_loop_new ();
|
||||
data.running = true;
|
||||
data.context = pw_context_new (data.loop, "pipewire-monitor", NULL);
|
||||
data.loop = pw_loop_new();
|
||||
data.running = true;
|
||||
data.context = pw_context_new(data.loop, "pipewire-monitor", NULL);
|
||||
|
||||
pw_signal_add (&data.context->state_changed,
|
||||
&data.on_state_changed,
|
||||
on_state_changed);
|
||||
pw_signal_add(&data.context->state_changed, &data.on_state_changed, on_state_changed);
|
||||
|
||||
pw_signal_add (&data.context->subscription,
|
||||
&data.on_subscription,
|
||||
on_subscription);
|
||||
pw_signal_add(&data.context->subscription, &data.on_subscription, on_subscription);
|
||||
|
||||
pw_context_connect (data.context, 0);
|
||||
pw_context_connect(data.context, 0);
|
||||
|
||||
pw_loop_enter (data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate (data.loop, -1);
|
||||
}
|
||||
pw_loop_leave (data.loop);
|
||||
pw_loop_enter(data.loop);
|
||||
while (data.running) {
|
||||
pw_loop_iterate(data.loop, -1);
|
||||
}
|
||||
pw_loop_leave(data.loop);
|
||||
|
||||
pw_context_destroy (data.context);
|
||||
pw_loop_destroy (data.loop);
|
||||
pw_context_destroy(data.context);
|
||||
pw_loop_destroy(data.loop);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,41 +29,39 @@ extern "C" {
|
|||
#include <spa/audio/raw-utils.h>
|
||||
|
||||
struct spa_type_format_audio {
|
||||
uint32_t format;
|
||||
uint32_t flags;
|
||||
uint32_t layout;
|
||||
uint32_t rate;
|
||||
uint32_t channels;
|
||||
uint32_t channel_mask;
|
||||
uint32_t format;
|
||||
uint32_t flags;
|
||||
uint32_t layout;
|
||||
uint32_t rate;
|
||||
uint32_t channels;
|
||||
uint32_t channel_mask;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_format_audio_map (struct spa_type_map *map, struct spa_type_format_audio *type)
|
||||
spa_type_format_audio_map(struct spa_type_map *map, struct spa_type_format_audio *type)
|
||||
{
|
||||
if (type->format == 0) {
|
||||
type->format = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__format);
|
||||
type->flags = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__flags);
|
||||
type->layout = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__layout);
|
||||
type->rate = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__rate);
|
||||
type->channels = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__channels);
|
||||
type->channel_mask = spa_type_map_get_id (map, SPA_TYPE_FORMAT_AUDIO__channelMask);
|
||||
}
|
||||
if (type->format == 0) {
|
||||
type->format = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__format);
|
||||
type->flags = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__flags);
|
||||
type->layout = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__layout);
|
||||
type->rate = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__rate);
|
||||
type->channels = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__channels);
|
||||
type->channel_mask = spa_type_map_get_id(map, SPA_TYPE_FORMAT_AUDIO__channelMask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
spa_format_audio_raw_parse (const struct spa_format *format,
|
||||
struct spa_audio_info_raw *info,
|
||||
struct spa_type_format_audio *type)
|
||||
spa_format_audio_raw_parse(const struct spa_format *format,
|
||||
struct spa_audio_info_raw *info, struct spa_type_format_audio *type)
|
||||
{
|
||||
spa_format_query (format,
|
||||
type->format, SPA_POD_TYPE_ID, &info->format,
|
||||
type->flags, SPA_POD_TYPE_INT, &info->flags,
|
||||
type->layout, SPA_POD_TYPE_INT, &info->layout,
|
||||
type->rate, SPA_POD_TYPE_INT, &info->rate,
|
||||
type->channels, SPA_POD_TYPE_INT, &info->channels,
|
||||
type->channel_mask, SPA_POD_TYPE_INT, &info->channel_mask,
|
||||
0);
|
||||
return true;
|
||||
spa_format_query(format,
|
||||
type->format, SPA_POD_TYPE_ID, &info->format,
|
||||
type->flags, SPA_POD_TYPE_INT, &info->flags,
|
||||
type->layout, SPA_POD_TYPE_INT, &info->layout,
|
||||
type->rate, SPA_POD_TYPE_INT, &info->rate,
|
||||
type->channels, SPA_POD_TYPE_INT, &info->channels,
|
||||
type->channel_mask, SPA_POD_TYPE_INT, &info->channel_mask, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ extern "C" {
|
|||
#define SPA_TYPE_FORMAT_AUDIO__channelMask SPA_TYPE_FORMAT_AUDIO_BASE "channel-mask"
|
||||
|
||||
struct spa_audio_info {
|
||||
uint32_t media_type;
|
||||
uint32_t media_subtype;
|
||||
union {
|
||||
struct spa_audio_info_raw raw;
|
||||
} info;
|
||||
uint32_t media_type;
|
||||
uint32_t media_subtype;
|
||||
union {
|
||||
struct spa_audio_info_raw raw;
|
||||
} info;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -36,80 +36,80 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct spa_type_audio_format {
|
||||
uint32_t UNKNOWN;
|
||||
uint32_t ENCODED;
|
||||
uint32_t S8;
|
||||
uint32_t U8;
|
||||
uint32_t S16;
|
||||
uint32_t U16;
|
||||
uint32_t S24_32;
|
||||
uint32_t U24_32;
|
||||
uint32_t S32;
|
||||
uint32_t U32;
|
||||
uint32_t S24;
|
||||
uint32_t U24;
|
||||
uint32_t S20;
|
||||
uint32_t U20;
|
||||
uint32_t S18;
|
||||
uint32_t U18;
|
||||
uint32_t F32;
|
||||
uint32_t F64;
|
||||
uint32_t S16_OE;
|
||||
uint32_t U16_OE;
|
||||
uint32_t S24_32_OE;
|
||||
uint32_t U24_32_OE;
|
||||
uint32_t S32_OE;
|
||||
uint32_t U32_OE;
|
||||
uint32_t S24_OE;
|
||||
uint32_t U24_OE;
|
||||
uint32_t S20_OE;
|
||||
uint32_t U20_OE;
|
||||
uint32_t S18_OE;
|
||||
uint32_t U18_OE;
|
||||
uint32_t F32_OE;
|
||||
uint32_t F64_OE;
|
||||
uint32_t UNKNOWN;
|
||||
uint32_t ENCODED;
|
||||
uint32_t S8;
|
||||
uint32_t U8;
|
||||
uint32_t S16;
|
||||
uint32_t U16;
|
||||
uint32_t S24_32;
|
||||
uint32_t U24_32;
|
||||
uint32_t S32;
|
||||
uint32_t U32;
|
||||
uint32_t S24;
|
||||
uint32_t U24;
|
||||
uint32_t S20;
|
||||
uint32_t U20;
|
||||
uint32_t S18;
|
||||
uint32_t U18;
|
||||
uint32_t F32;
|
||||
uint32_t F64;
|
||||
uint32_t S16_OE;
|
||||
uint32_t U16_OE;
|
||||
uint32_t S24_32_OE;
|
||||
uint32_t U24_32_OE;
|
||||
uint32_t S32_OE;
|
||||
uint32_t U32_OE;
|
||||
uint32_t S24_OE;
|
||||
uint32_t U24_OE;
|
||||
uint32_t S20_OE;
|
||||
uint32_t U20_OE;
|
||||
uint32_t S18_OE;
|
||||
uint32_t U18_OE;
|
||||
uint32_t F32_OE;
|
||||
uint32_t F64_OE;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_audio_format_map (struct spa_type_map *map, struct spa_type_audio_format *type)
|
||||
spa_type_audio_format_map(struct spa_type_map *map, struct spa_type_audio_format *type)
|
||||
{
|
||||
if (type->ENCODED == 0) {
|
||||
type->UNKNOWN = 0;
|
||||
type->ENCODED = spa_type_map_get_id (map, SPA_TYPE_AUDIO_FORMAT__ENCODED);
|
||||
if (type->ENCODED == 0) {
|
||||
type->UNKNOWN = 0;
|
||||
type->ENCODED = spa_type_map_get_id(map, SPA_TYPE_AUDIO_FORMAT__ENCODED);
|
||||
|
||||
type->S8 = spa_type_map_get_id (map, SPA_TYPE_AUDIO_FORMAT__S8);
|
||||
type->U8 = spa_type_map_get_id (map, SPA_TYPE_AUDIO_FORMAT__U8);
|
||||
type->S8 = spa_type_map_get_id(map, SPA_TYPE_AUDIO_FORMAT__S8);
|
||||
type->U8 = spa_type_map_get_id(map, SPA_TYPE_AUDIO_FORMAT__U8);
|
||||
|
||||
type->S16 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S16"));
|
||||
type->U16 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U16"));
|
||||
type->S24_32 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S24_32"));
|
||||
type->U24_32 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U24_32"));
|
||||
type->S32 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S32"));
|
||||
type->U32 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U32"));
|
||||
type->S24 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S24"));
|
||||
type->U24 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U24"));
|
||||
type->S20 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S20"));
|
||||
type->U20 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U20"));
|
||||
type->S18 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("S18"));
|
||||
type->U18 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("U18"));
|
||||
type->F32 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("F32"));
|
||||
type->F64 = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_NE ("F64"));
|
||||
type->S16 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S16"));
|
||||
type->U16 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U16"));
|
||||
type->S24_32 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S24_32"));
|
||||
type->U24_32 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U24_32"));
|
||||
type->S32 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S32"));
|
||||
type->U32 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U32"));
|
||||
type->S24 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S24"));
|
||||
type->U24 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U24"));
|
||||
type->S20 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S20"));
|
||||
type->U20 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U20"));
|
||||
type->S18 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("S18"));
|
||||
type->U18 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("U18"));
|
||||
type->F32 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("F32"));
|
||||
type->F64 = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_NE("F64"));
|
||||
|
||||
type->S16_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S16"));
|
||||
type->U16_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U16"));
|
||||
type->S24_32_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S24_32"));
|
||||
type->U24_32_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U24_32"));
|
||||
type->S32_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S32"));
|
||||
type->U32_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U32"));
|
||||
type->S24_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S24"));
|
||||
type->U24_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U24"));
|
||||
type->S20_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S20"));
|
||||
type->U20_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U20"));
|
||||
type->S18_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("S18"));
|
||||
type->U18_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("U18"));
|
||||
type->F32_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("F32"));
|
||||
type->F64_OE = spa_type_map_get_id (map, _SPA_TYPE_AUDIO_FORMAT_OE ("F64"));
|
||||
}
|
||||
type->S16_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S16"));
|
||||
type->U16_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U16"));
|
||||
type->S24_32_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S24_32"));
|
||||
type->U24_32_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U24_32"));
|
||||
type->S32_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S32"));
|
||||
type->U32_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U32"));
|
||||
type->S24_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S24"));
|
||||
type->U24_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U24"));
|
||||
type->S20_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S20"));
|
||||
type->U20_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U20"));
|
||||
type->S18_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("S18"));
|
||||
type->U18_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("U18"));
|
||||
type->F32_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("F32"));
|
||||
type->F64_OE = spa_type_map_get_id(map, _SPA_TYPE_AUDIO_FORMAT_OE("F64"));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ extern "C" {
|
|||
* Extra audio flags
|
||||
*/
|
||||
enum spa_audio_flags {
|
||||
SPA_AUDIO_FLAG_NONE = 0,
|
||||
SPA_AUDIO_FLAG_UNPOSITIONED = (1 << 0)
|
||||
SPA_AUDIO_FLAG_NONE = 0,
|
||||
SPA_AUDIO_FLAG_UNPOSITIONED = (1 << 0)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -83,8 +83,8 @@ enum spa_audio_flags {
|
|||
* Layout of the audio samples for the different channels.
|
||||
*/
|
||||
enum spa_audio_layout {
|
||||
SPA_AUDIO_LAYOUT_INTERLEAVED = 0,
|
||||
SPA_AUDIO_LAYOUT_NON_INTERLEAVED
|
||||
SPA_AUDIO_LAYOUT_INTERLEAVED = 0,
|
||||
SPA_AUDIO_LAYOUT_NON_INTERLEAVED
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -97,12 +97,12 @@ enum spa_audio_layout {
|
|||
* @channel_mask: the channel mask
|
||||
*/
|
||||
struct spa_audio_info_raw {
|
||||
uint32_t format;
|
||||
enum spa_audio_flags flags;
|
||||
enum spa_audio_layout layout;
|
||||
uint32_t rate;
|
||||
uint32_t channels;
|
||||
uint32_t channel_mask;
|
||||
uint32_t format;
|
||||
enum spa_audio_flags flags;
|
||||
enum spa_audio_layout layout;
|
||||
uint32_t rate;
|
||||
uint32_t channels;
|
||||
uint32_t channel_mask;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -40,21 +40,20 @@ extern "C" {
|
|||
#define SPA_TYPE_DATA__Id SPA_TYPE_DATA_BASE "Id"
|
||||
|
||||
struct spa_type_data {
|
||||
uint32_t MemPtr;
|
||||
uint32_t MemFd;
|
||||
uint32_t DmaBuf;
|
||||
uint32_t Id;
|
||||
uint32_t MemPtr;
|
||||
uint32_t MemFd;
|
||||
uint32_t DmaBuf;
|
||||
uint32_t Id;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_data_map (struct spa_type_map *map, struct spa_type_data *type)
|
||||
static inline void spa_type_data_map(struct spa_type_map *map, struct spa_type_data *type)
|
||||
{
|
||||
if (type->MemPtr == 0) {
|
||||
type->MemPtr = spa_type_map_get_id (map, SPA_TYPE_DATA__MemPtr);
|
||||
type->MemFd = spa_type_map_get_id (map, SPA_TYPE_DATA__MemFd);
|
||||
type->DmaBuf = spa_type_map_get_id (map, SPA_TYPE_DATA__DmaBuf);
|
||||
type->Id = spa_type_map_get_id (map, SPA_TYPE_DATA__Id);
|
||||
}
|
||||
if (type->MemPtr == 0) {
|
||||
type->MemPtr = spa_type_map_get_id(map, SPA_TYPE_DATA__MemPtr);
|
||||
type->MemFd = spa_type_map_get_id(map, SPA_TYPE_DATA__MemFd);
|
||||
type->DmaBuf = spa_type_map_get_id(map, SPA_TYPE_DATA__DmaBuf);
|
||||
type->Id = spa_type_map_get_id(map, SPA_TYPE_DATA__Id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,9 +63,9 @@ spa_type_data_map (struct spa_type_map *map, struct spa_type_data *type)
|
|||
* @stride: stride of data if applicable
|
||||
*/
|
||||
struct spa_chunk {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
int32_t stride;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
int32_t stride;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -80,13 +79,13 @@ struct spa_chunk {
|
|||
* @chunk: pointer to chunk with valid offset
|
||||
*/
|
||||
struct spa_data {
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
int fd;
|
||||
uint32_t mapoffset;
|
||||
uint32_t maxsize;
|
||||
void *data;
|
||||
struct spa_chunk *chunk;
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
int fd;
|
||||
uint32_t mapoffset;
|
||||
uint32_t maxsize;
|
||||
void *data;
|
||||
struct spa_chunk *chunk;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -98,27 +97,26 @@ struct spa_data {
|
|||
* @datas: offset of array of @n_datas data pointers
|
||||
*/
|
||||
struct spa_buffer {
|
||||
uint32_t id;
|
||||
uint32_t n_metas;
|
||||
struct spa_meta *metas;
|
||||
uint32_t n_datas;
|
||||
struct spa_data *datas;
|
||||
uint32_t id;
|
||||
uint32_t n_metas;
|
||||
struct spa_meta *metas;
|
||||
uint32_t n_datas;
|
||||
struct spa_data *datas;
|
||||
};
|
||||
|
||||
static inline void *
|
||||
spa_buffer_find_meta (struct spa_buffer *b, uint32_t type)
|
||||
static inline void *spa_buffer_find_meta(struct spa_buffer *b, uint32_t type)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < b->n_metas; i++)
|
||||
if (b->metas[i].type == type)
|
||||
return b->metas[i].data;
|
||||
for (i = 0; i < b->n_metas; i++)
|
||||
if (b->metas[i].type == type)
|
||||
return b->metas[i].data;
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SPA_BUFFER_H__ */
|
||||
#endif /* __SPA_BUFFER_H__ */
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ extern "C" {
|
|||
* @SPA_CLOCK_STATE_RUNNING: the clock is running
|
||||
*/
|
||||
enum spa_clock_state {
|
||||
SPA_CLOCK_STATE_STOPPED,
|
||||
SPA_CLOCK_STATE_PAUSED,
|
||||
SPA_CLOCK_STATE_RUNNING,
|
||||
SPA_CLOCK_STATE_STOPPED,
|
||||
SPA_CLOCK_STATE_PAUSED,
|
||||
SPA_CLOCK_STATE_RUNNING,
|
||||
};
|
||||
|
||||
#include <spa/defs.h>
|
||||
|
|
@ -49,68 +49,64 @@ enum spa_clock_state {
|
|||
* A time provider.
|
||||
*/
|
||||
struct spa_clock {
|
||||
/* the total size of this clock. This can be used to expand this
|
||||
* structure in the future */
|
||||
size_t size;
|
||||
/**
|
||||
* spa_clock::info
|
||||
*
|
||||
* Extra information about the clock
|
||||
*/
|
||||
const struct spa_dict *info;
|
||||
/**
|
||||
* spa_clock::state:
|
||||
*
|
||||
* The current state of the clock
|
||||
*/
|
||||
enum spa_clock_state state;
|
||||
/**
|
||||
* spa_clock::get_props:
|
||||
* @clock: a #spa_clock
|
||||
* @props: a location for a #struct spa_props pointer
|
||||
*
|
||||
* Get the configurable properties of @clock.
|
||||
*
|
||||
* The returned @props is a snapshot of the current configuration and
|
||||
* can be modified. The modifications will take effect after a call
|
||||
* to spa_clock::set_props.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when clock or props are %NULL
|
||||
* #SPA_RESULT_NOT_IMPLEMENTED when there are no properties
|
||||
* implemented on @clock
|
||||
*/
|
||||
int (*get_props) (struct spa_clock *clock,
|
||||
struct spa_props **props);
|
||||
/**
|
||||
* spa_clock::set_props:
|
||||
* @clock: a #spa_clock
|
||||
* @props: a #struct spa_props
|
||||
*
|
||||
* Set the configurable properties in @clock.
|
||||
*
|
||||
* Usually, @props will be obtained from spa_clock::get_props and then
|
||||
* modified but it is also possible to set another #struct spa_props object
|
||||
* as long as its keys and types match those of struct spa_props::get_props.
|
||||
*
|
||||
* Properties with keys that are not known are ignored.
|
||||
*
|
||||
* If @props is NULL, all the properties are reset to their defaults.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when clock is %NULL
|
||||
* #SPA_RESULT_NOT_IMPLEMENTED when no properties can be
|
||||
* modified on @clock.
|
||||
* #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong
|
||||
* type.
|
||||
*/
|
||||
int (*set_props) (struct spa_clock *clock,
|
||||
const struct spa_props *props);
|
||||
/* the total size of this clock. This can be used to expand this
|
||||
* structure in the future */
|
||||
size_t size;
|
||||
|
||||
int (*get_time) (struct spa_clock *clock,
|
||||
int32_t *rate,
|
||||
int64_t *ticks,
|
||||
int64_t *monotonic_time);
|
||||
const struct spa_dict *info;
|
||||
/**
|
||||
* spa_clock::state:
|
||||
*
|
||||
* The current state of the clock
|
||||
*/
|
||||
enum spa_clock_state state;
|
||||
/**
|
||||
* spa_clock::get_props:
|
||||
* @clock: a #spa_clock
|
||||
* @props: a location for a #struct spa_props pointer
|
||||
*
|
||||
* Get the configurable properties of @clock.
|
||||
*
|
||||
* The returned @props is a snapshot of the current configuration and
|
||||
* can be modified. The modifications will take effect after a call
|
||||
* to spa_clock::set_props.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when clock or props are %NULL
|
||||
* #SPA_RESULT_NOT_IMPLEMENTED when there are no properties
|
||||
* implemented on @clock
|
||||
*/
|
||||
int (*get_props) (struct spa_clock *clock,
|
||||
struct spa_props **props);
|
||||
/**
|
||||
* spa_clock::set_props:
|
||||
* @clock: a #spa_clock
|
||||
* @props: a #struct spa_props
|
||||
*
|
||||
* Set the configurable properties in @clock.
|
||||
*
|
||||
* Usually, @props will be obtained from spa_clock::get_props and then
|
||||
* modified but it is also possible to set another #struct spa_props object
|
||||
* as long as its keys and types match those of struct spa_props::get_props.
|
||||
*
|
||||
* Properties with keys that are not known are ignored.
|
||||
*
|
||||
* If @props is NULL, all the properties are reset to their defaults.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when clock is %NULL
|
||||
* #SPA_RESULT_NOT_IMPLEMENTED when no properties can be
|
||||
* modified on @clock.
|
||||
* #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong
|
||||
* type.
|
||||
*/
|
||||
int (*set_props) (struct spa_clock *clock,
|
||||
const struct spa_props *props);
|
||||
|
||||
int (*get_time) (struct spa_clock *clock,
|
||||
int32_t *rate,
|
||||
int64_t *ticks,
|
||||
int64_t *monotonic_time);
|
||||
};
|
||||
|
||||
#define spa_clock_get_props(n,...) (n)->get_props((n),__VA_ARGS__)
|
||||
|
|
@ -121,4 +117,4 @@ struct spa_clock {
|
|||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SPA_CLOCK_H__ */
|
||||
#endif /* __SPA_CLOCK_H__ */
|
||||
|
|
|
|||
|
|
@ -38,25 +38,25 @@ extern "C" {
|
|||
#define SPA_TYPE_COMMAND_NODE__ClockUpdate SPA_TYPE_COMMAND_NODE_BASE "ClockUpdate"
|
||||
|
||||
struct spa_type_command_node {
|
||||
uint32_t Pause;
|
||||
uint32_t Start;
|
||||
uint32_t Flush;
|
||||
uint32_t Drain;
|
||||
uint32_t Marker;
|
||||
uint32_t ClockUpdate;
|
||||
uint32_t Pause;
|
||||
uint32_t Start;
|
||||
uint32_t Flush;
|
||||
uint32_t Drain;
|
||||
uint32_t Marker;
|
||||
uint32_t ClockUpdate;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_command_node_map (struct spa_type_map *map, struct spa_type_command_node *type)
|
||||
spa_type_command_node_map(struct spa_type_map *map, struct spa_type_command_node *type)
|
||||
{
|
||||
if (type->Pause == 0) {
|
||||
type->Pause = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__Pause);
|
||||
type->Start = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__Start);
|
||||
type->Flush = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__Flush);
|
||||
type->Drain = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__Drain);
|
||||
type->Marker = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__Marker);
|
||||
type->ClockUpdate = spa_type_map_get_id (map, SPA_TYPE_COMMAND_NODE__ClockUpdate);
|
||||
}
|
||||
if (type->Pause == 0) {
|
||||
type->Pause = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__Pause);
|
||||
type->Start = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__Start);
|
||||
type->Flush = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__Flush);
|
||||
type->Drain = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__Drain);
|
||||
type->Marker = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__Marker);
|
||||
type->ClockUpdate = spa_type_map_get_id(map, SPA_TYPE_COMMAND_NODE__ClockUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,43 +72,43 @@ spa_type_command_node_map (struct spa_type_map *map, struct spa_type_command_nod
|
|||
* @state: the new clock state, when @change_mask = 1<<2
|
||||
*/
|
||||
struct spa_command_node_clock_update_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_object_body body;
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_TIME (1 << 0)
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_SCALE (1 << 1)
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_STATE (1 << 2)
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_LATENCY (1 << 3)
|
||||
struct spa_pod_int change_mask SPA_ALIGNED (8);
|
||||
struct spa_pod_int rate SPA_ALIGNED (8);
|
||||
struct spa_pod_long ticks SPA_ALIGNED (8);
|
||||
struct spa_pod_long monotonic_time SPA_ALIGNED (8);
|
||||
struct spa_pod_long offset SPA_ALIGNED (8);
|
||||
struct spa_pod_int scale SPA_ALIGNED (8);
|
||||
struct spa_pod_int state SPA_ALIGNED (8);
|
||||
struct spa_pod_int change_mask SPA_ALIGNED(8);
|
||||
struct spa_pod_int rate SPA_ALIGNED(8);
|
||||
struct spa_pod_long ticks SPA_ALIGNED(8);
|
||||
struct spa_pod_long monotonic_time SPA_ALIGNED(8);
|
||||
struct spa_pod_long offset SPA_ALIGNED(8);
|
||||
struct spa_pod_int scale SPA_ALIGNED(8);
|
||||
struct spa_pod_int state SPA_ALIGNED(8);
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_FLAG_LIVE (1 << 0)
|
||||
struct spa_pod_int flags SPA_ALIGNED (8);
|
||||
struct spa_pod_long latency SPA_ALIGNED (8);
|
||||
struct spa_pod_int flags SPA_ALIGNED(8);
|
||||
struct spa_pod_long latency SPA_ALIGNED(8);
|
||||
};
|
||||
|
||||
struct spa_command_node_clock_update {
|
||||
struct spa_pod pod;
|
||||
struct spa_command_node_clock_update_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_command_node_clock_update_body body;
|
||||
};
|
||||
|
||||
#define SPA_COMMAND_NODE_CLOCK_UPDATE_INIT(type,change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency) \
|
||||
SPA_COMMAND_INIT_COMPLEX (struct spa_command_node_clock_update, \
|
||||
sizeof (struct spa_command_node_clock_update_body), type, \
|
||||
SPA_POD_INT_INIT (change_mask), \
|
||||
SPA_POD_INT_INIT (rate), \
|
||||
SPA_POD_LONG_INIT (ticks), \
|
||||
SPA_POD_LONG_INIT (monotonic_time), \
|
||||
SPA_POD_LONG_INIT (offset), \
|
||||
SPA_POD_INT_INIT (scale), \
|
||||
SPA_POD_INT_INIT (state), \
|
||||
SPA_POD_INT_INIT (flags), \
|
||||
SPA_POD_LONG_INIT (latency))
|
||||
SPA_COMMAND_INIT_COMPLEX(struct spa_command_node_clock_update, \
|
||||
sizeof(struct spa_command_node_clock_update_body), type, \
|
||||
SPA_POD_INT_INIT(change_mask), \
|
||||
SPA_POD_INT_INIT(rate), \
|
||||
SPA_POD_LONG_INIT(ticks), \
|
||||
SPA_POD_LONG_INIT(monotonic_time), \
|
||||
SPA_POD_LONG_INIT(offset), \
|
||||
SPA_POD_INT_INIT(scale), \
|
||||
SPA_POD_INT_INIT(state), \
|
||||
SPA_POD_INT_INIT(flags), \
|
||||
SPA_POD_LONG_INIT(latency))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SPA_COMMAND_NODE_H__ */
|
||||
#endif /* _SPA_COMMAND_NODE_H__ */
|
||||
|
|
|
|||
|
|
@ -31,23 +31,23 @@ extern "C" {
|
|||
#define SPA_TYPE_COMMAND_BASE SPA_TYPE__Command ":"
|
||||
|
||||
struct spa_command_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_object_body body;
|
||||
};
|
||||
|
||||
struct spa_command {
|
||||
struct spa_pod pod;
|
||||
struct spa_command_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_command_body body;
|
||||
};
|
||||
|
||||
#define SPA_COMMAND_TYPE(cmd) ((cmd)->body.body.type)
|
||||
|
||||
#define SPA_COMMAND_INIT(type) (struct spa_command) \
|
||||
{ { sizeof (struct spa_command_body), SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type } } } \
|
||||
#define SPA_COMMAND_INIT(type) (struct spa_command) \
|
||||
{ { sizeof(struct spa_command_body), SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type } } } \
|
||||
|
||||
#define SPA_COMMAND_INIT_COMPLEX(t,size,type,...) (t) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, __VA_ARGS__ } } \
|
||||
#define SPA_COMMAND_INIT_COMPLEX(t,size,type,...) (t) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, __VA_ARGS__ } } \
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -31,46 +31,46 @@ extern "C" {
|
|||
#include <stddef.h>
|
||||
|
||||
enum {
|
||||
SPA_RESULT_ASYNC = (1 << 30),
|
||||
SPA_RESULT_WAIT_SYNC = 2,
|
||||
SPA_RESULT_MODIFIED = 1,
|
||||
SPA_RESULT_OK = 0,
|
||||
SPA_RESULT_ERROR = -1,
|
||||
SPA_RESULT_ERRNO = -2,
|
||||
SPA_RESULT_INACTIVE = -3,
|
||||
SPA_RESULT_NO_FORMAT = -4,
|
||||
SPA_RESULT_INVALID_COMMAND = -5,
|
||||
SPA_RESULT_INVALID_PORT = -6,
|
||||
SPA_RESULT_HAVE_BUFFER = -7,
|
||||
SPA_RESULT_NEED_BUFFER = -8,
|
||||
SPA_RESULT_PORTS_CHANGED = -9,
|
||||
SPA_RESULT_FORMAT_CHANGED = -10,
|
||||
SPA_RESULT_PROPERTIES_CHANGED = -11,
|
||||
SPA_RESULT_NOT_IMPLEMENTED = -12,
|
||||
SPA_RESULT_INVALID_PROPERTY_INDEX = -13,
|
||||
SPA_RESULT_PROPERTY_UNSET = -14,
|
||||
SPA_RESULT_ENUM_END = -15,
|
||||
SPA_RESULT_WRONG_PROPERTY_TYPE = -16,
|
||||
SPA_RESULT_WRONG_PROPERTY_SIZE = -17,
|
||||
SPA_RESULT_INVALID_MEDIA_TYPE = -18,
|
||||
SPA_RESULT_INVALID_FORMAT_PROPERTIES = -19,
|
||||
SPA_RESULT_FORMAT_INCOMPLETE = -20,
|
||||
SPA_RESULT_INVALID_ARGUMENTS = -21,
|
||||
SPA_RESULT_UNKNOWN_INTERFACE = -22,
|
||||
SPA_RESULT_INVALID_DIRECTION = -23,
|
||||
SPA_RESULT_TOO_MANY_PORTS = -24,
|
||||
SPA_RESULT_INVALID_PROPERTY_ACCESS = -25,
|
||||
SPA_RESULT_UNEXPECTED = -26,
|
||||
SPA_RESULT_NO_BUFFERS = -27,
|
||||
SPA_RESULT_INVALID_BUFFER_ID = -28,
|
||||
SPA_RESULT_WRONG_STATE = -29,
|
||||
SPA_RESULT_ASYNC_BUSY = -30,
|
||||
SPA_RESULT_INVALID_OBJECT_ID = -31,
|
||||
SPA_RESULT_NO_MEMORY = -32,
|
||||
SPA_RESULT_NO_PERMISSION = -33,
|
||||
SPA_RESULT_SKIPPED = -34,
|
||||
SPA_RESULT_OUT_OF_BUFFERS = -35,
|
||||
SPA_RESULT_INCOMPATIBLE_PROPS = -36,
|
||||
SPA_RESULT_ASYNC = (1 << 30),
|
||||
SPA_RESULT_WAIT_SYNC = 2,
|
||||
SPA_RESULT_MODIFIED = 1,
|
||||
SPA_RESULT_OK = 0,
|
||||
SPA_RESULT_ERROR = -1,
|
||||
SPA_RESULT_ERRNO = -2,
|
||||
SPA_RESULT_INACTIVE = -3,
|
||||
SPA_RESULT_NO_FORMAT = -4,
|
||||
SPA_RESULT_INVALID_COMMAND = -5,
|
||||
SPA_RESULT_INVALID_PORT = -6,
|
||||
SPA_RESULT_HAVE_BUFFER = -7,
|
||||
SPA_RESULT_NEED_BUFFER = -8,
|
||||
SPA_RESULT_PORTS_CHANGED = -9,
|
||||
SPA_RESULT_FORMAT_CHANGED = -10,
|
||||
SPA_RESULT_PROPERTIES_CHANGED = -11,
|
||||
SPA_RESULT_NOT_IMPLEMENTED = -12,
|
||||
SPA_RESULT_INVALID_PROPERTY_INDEX = -13,
|
||||
SPA_RESULT_PROPERTY_UNSET = -14,
|
||||
SPA_RESULT_ENUM_END = -15,
|
||||
SPA_RESULT_WRONG_PROPERTY_TYPE = -16,
|
||||
SPA_RESULT_WRONG_PROPERTY_SIZE = -17,
|
||||
SPA_RESULT_INVALID_MEDIA_TYPE = -18,
|
||||
SPA_RESULT_INVALID_FORMAT_PROPERTIES = -19,
|
||||
SPA_RESULT_FORMAT_INCOMPLETE = -20,
|
||||
SPA_RESULT_INVALID_ARGUMENTS = -21,
|
||||
SPA_RESULT_UNKNOWN_INTERFACE = -22,
|
||||
SPA_RESULT_INVALID_DIRECTION = -23,
|
||||
SPA_RESULT_TOO_MANY_PORTS = -24,
|
||||
SPA_RESULT_INVALID_PROPERTY_ACCESS = -25,
|
||||
SPA_RESULT_UNEXPECTED = -26,
|
||||
SPA_RESULT_NO_BUFFERS = -27,
|
||||
SPA_RESULT_INVALID_BUFFER_ID = -28,
|
||||
SPA_RESULT_WRONG_STATE = -29,
|
||||
SPA_RESULT_ASYNC_BUSY = -30,
|
||||
SPA_RESULT_INVALID_OBJECT_ID = -31,
|
||||
SPA_RESULT_NO_MEMORY = -32,
|
||||
SPA_RESULT_NO_PERMISSION = -33,
|
||||
SPA_RESULT_SKIPPED = -34,
|
||||
SPA_RESULT_OUT_OF_BUFFERS = -35,
|
||||
SPA_RESULT_INCOMPATIBLE_PROPS = -36,
|
||||
};
|
||||
|
||||
#define SPA_ASYNC_MASK (3 << 30)
|
||||
|
|
@ -84,21 +84,21 @@ enum {
|
|||
#define SPA_RESULT_RETURN_ASYNC(seq) (SPA_RESULT_ASYNC | ((seq) & SPA_ASYNC_SEQ_MASK))
|
||||
|
||||
enum spa_direction {
|
||||
SPA_DIRECTION_INPUT = 0,
|
||||
SPA_DIRECTION_OUTPUT = 1,
|
||||
SPA_DIRECTION_INPUT = 0,
|
||||
SPA_DIRECTION_OUTPUT = 1,
|
||||
};
|
||||
|
||||
struct spa_rectangle {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct spa_fraction {
|
||||
uint32_t num;
|
||||
uint32_t denom;
|
||||
uint32_t num;
|
||||
uint32_t denom;
|
||||
};
|
||||
|
||||
#define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
||||
#define SPA_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#define SPA_MIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
#define SPA_MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
#define SPA_ABS(a) ((a)>0 ? (a) : -(a))
|
||||
|
|
@ -131,11 +131,11 @@ struct spa_fraction {
|
|||
#define SPA_TIMEVAL_TO_TIME(tv) ((tv)->tv_sec * SPA_NSEC_PER_SEC + (tv)->tv_usec * 1000ll)
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
|
||||
# define SPA_ALIGNED(align) __attribute__ ((aligned (align)))
|
||||
#define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
|
||||
#define SPA_ALIGNED(align) __attribute__((aligned(align)))
|
||||
#else
|
||||
# define SPA_PRINTF_FUNC(fmt, arg1)
|
||||
# define SPA_ALIGNED(align)
|
||||
#define SPA_PRINTF_FUNC(fmt, arg1)
|
||||
#define SPA_ALIGNED(align)
|
||||
#endif
|
||||
|
||||
#define SPA_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1)))
|
||||
|
|
@ -150,25 +150,25 @@ struct spa_fraction {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define spa_return_if_fail(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY (!(expr))) \
|
||||
return; \
|
||||
} while(false)
|
||||
#define spa_return_if_fail(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
return; \
|
||||
} while(false)
|
||||
|
||||
#define spa_return_val_if_fail(expr, val) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
return (val); \
|
||||
} while(false)
|
||||
#define spa_return_val_if_fail(expr, val) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
return (val); \
|
||||
} while(false)
|
||||
|
||||
/* spa_assert_se() is an assert which guarantees side effects of x,
|
||||
* i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
|
||||
#define spa_assert_se(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
abort(); \
|
||||
} while (false)
|
||||
#define spa_assert_se(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
abort(); \
|
||||
} while (false)
|
||||
|
||||
/* Does exactly nothing */
|
||||
#define spa_nop() do {} while (false)
|
||||
|
|
@ -177,8 +177,7 @@ struct spa_fraction {
|
|||
#define spa_zero(x) (spa_memzero(&(x), sizeof(x)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __SPA_DEFS_H__ */
|
||||
|
|
|
|||
|
|
@ -32,38 +32,37 @@ extern "C" {
|
|||
#include <spa/defs.h>
|
||||
|
||||
struct spa_dict_item {
|
||||
const char *key;
|
||||
const char *value;
|
||||
const char *key;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
struct spa_dict {
|
||||
uint32_t n_items;
|
||||
struct spa_dict_item *items;
|
||||
uint32_t n_items;
|
||||
struct spa_dict_item *items;
|
||||
};
|
||||
|
||||
#define SPA_DICT_INIT(n_items,items) { n_items, items }
|
||||
|
||||
#define spa_dict_for_each(item, dict) \
|
||||
for ((item) = (dict)->items; \
|
||||
(item) < &(dict)->items[(dict)->n_items]; \
|
||||
(item)++)
|
||||
#define spa_dict_for_each(item, dict) \
|
||||
for ((item) = (dict)->items; \
|
||||
(item) < &(dict)->items[(dict)->n_items]; \
|
||||
(item)++)
|
||||
|
||||
static inline struct spa_dict_item *
|
||||
spa_dict_lookup_item (const struct spa_dict *dict, const char *key)
|
||||
static inline struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict,
|
||||
const char *key)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
spa_dict_for_each (item, dict) {
|
||||
if (!strcmp (item->key, key))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
struct spa_dict_item *item;
|
||||
spa_dict_for_each(item, dict) {
|
||||
if (!strcmp(item->key, key))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
spa_dict_lookup (const struct spa_dict *dict, const char *key)
|
||||
static inline const char *spa_dict_lookup(const struct spa_dict *dict, const char *key)
|
||||
{
|
||||
struct spa_dict_item *item = spa_dict_lookup_item (dict, key);
|
||||
return item ? item->value : NULL;
|
||||
struct spa_dict_item *item = spa_dict_lookup_item(dict, key);
|
||||
return item ? item->value : NULL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -39,63 +39,63 @@ extern "C" {
|
|||
#define SPA_TYPE_EVENT_NODE__RequestClockUpdate SPA_TYPE_EVENT_NODE_BASE "RequestClockUpdate"
|
||||
|
||||
struct spa_type_event_node {
|
||||
uint32_t AsyncComplete;
|
||||
uint32_t Error;
|
||||
uint32_t Buffering;
|
||||
uint32_t RequestRefresh;
|
||||
uint32_t RequestClockUpdate;
|
||||
uint32_t AsyncComplete;
|
||||
uint32_t Error;
|
||||
uint32_t Buffering;
|
||||
uint32_t RequestRefresh;
|
||||
uint32_t RequestClockUpdate;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_event_node_map (struct spa_type_map *map, struct spa_type_event_node *type)
|
||||
spa_type_event_node_map(struct spa_type_map *map, struct spa_type_event_node *type)
|
||||
{
|
||||
if (type->AsyncComplete == 0) {
|
||||
type->AsyncComplete = spa_type_map_get_id (map, SPA_TYPE_EVENT_NODE__AsyncComplete);
|
||||
type->Error = spa_type_map_get_id (map, SPA_TYPE_EVENT_NODE__Error);
|
||||
type->Buffering = spa_type_map_get_id (map, SPA_TYPE_EVENT_NODE__Buffering);
|
||||
type->RequestRefresh = spa_type_map_get_id (map, SPA_TYPE_EVENT_NODE__RequestRefresh);
|
||||
type->RequestClockUpdate = spa_type_map_get_id (map, SPA_TYPE_EVENT_NODE__RequestClockUpdate);
|
||||
}
|
||||
if (type->AsyncComplete == 0) {
|
||||
type->AsyncComplete = spa_type_map_get_id(map, SPA_TYPE_EVENT_NODE__AsyncComplete);
|
||||
type->Error = spa_type_map_get_id(map, SPA_TYPE_EVENT_NODE__Error);
|
||||
type->Buffering = spa_type_map_get_id(map, SPA_TYPE_EVENT_NODE__Buffering);
|
||||
type->RequestRefresh = spa_type_map_get_id(map, SPA_TYPE_EVENT_NODE__RequestRefresh);
|
||||
type->RequestClockUpdate = spa_type_map_get_id(map, SPA_TYPE_EVENT_NODE__RequestClockUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
struct spa_event_node_async_complete_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_int seq SPA_ALIGNED (8);
|
||||
struct spa_pod_int res SPA_ALIGNED (8);
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_int seq SPA_ALIGNED(8);
|
||||
struct spa_pod_int res SPA_ALIGNED(8);
|
||||
};
|
||||
|
||||
struct spa_event_node_async_complete {
|
||||
struct spa_pod pod;
|
||||
struct spa_event_node_async_complete_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_event_node_async_complete_body body;
|
||||
};
|
||||
|
||||
#define SPA_EVENT_NODE_ASYNC_COMPLETE_INIT(type,seq,res) \
|
||||
SPA_EVENT_INIT_COMPLEX (struct spa_event_node_async_complete, \
|
||||
sizeof (struct spa_event_node_async_complete_body), type, \
|
||||
SPA_POD_INT_INIT (seq), \
|
||||
SPA_POD_INT_INIT (res))
|
||||
#define SPA_EVENT_NODE_ASYNC_COMPLETE_INIT(type,seq,res) \
|
||||
SPA_EVENT_INIT_COMPLEX(struct spa_event_node_async_complete, \
|
||||
sizeof(struct spa_event_node_async_complete_body), type, \
|
||||
SPA_POD_INT_INIT(seq), \
|
||||
SPA_POD_INT_INIT(res))
|
||||
|
||||
struct spa_event_node_request_clock_update_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_object_body body;
|
||||
#define SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_TIME (1 << 0)
|
||||
#define SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_SCALE (1 << 1)
|
||||
#define SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_STATE (1 << 2)
|
||||
struct spa_pod_int update_mask SPA_ALIGNED (8);
|
||||
struct spa_pod_long timestamp SPA_ALIGNED (8);
|
||||
struct spa_pod_long offset SPA_ALIGNED (8);
|
||||
struct spa_pod_int update_mask SPA_ALIGNED(8);
|
||||
struct spa_pod_long timestamp SPA_ALIGNED(8);
|
||||
struct spa_pod_long offset SPA_ALIGNED(8);
|
||||
};
|
||||
|
||||
struct spa_event_node_request_clock_update {
|
||||
struct spa_pod pod;
|
||||
struct spa_event_node_request_clock_update_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_event_node_request_clock_update_body body;
|
||||
};
|
||||
|
||||
#define SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_INIT(type,update_mask,timestamp,offset) \
|
||||
SPA_EVENT_INIT_COMPLEX (struct spa_event_node_request_clock_update, \
|
||||
sizeof (struct spa_event_node_request_clock_update_body), type, \
|
||||
SPA_POD_INT_INIT (update_mask), \
|
||||
SPA_POD_LONG_INIT (timestamp), \
|
||||
SPA_POD_LONG_INIT (offset))
|
||||
#define SPA_EVENT_NODE_REQUEST_CLOCK_UPDATE_INIT(type,update_mask,timestamp,offset) \
|
||||
SPA_EVENT_INIT_COMPLEX(struct spa_event_node_request_clock_update, \
|
||||
sizeof(struct spa_event_node_request_clock_update_body), type, \
|
||||
SPA_POD_INT_INIT(update_mask), \
|
||||
SPA_POD_LONG_INIT(timestamp), \
|
||||
SPA_POD_LONG_INIT(offset))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -31,23 +31,23 @@ extern "C" {
|
|||
#define SPA_TYPE_EVENT_BASE SPA_TYPE__Event ":"
|
||||
|
||||
struct spa_event_body {
|
||||
struct spa_pod_object_body body;
|
||||
struct spa_pod_object_body body;
|
||||
};
|
||||
|
||||
struct spa_event {
|
||||
struct spa_pod pod;
|
||||
struct spa_event_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_event_body body;
|
||||
};
|
||||
|
||||
#define SPA_EVENT_TYPE(ev) ((ev)->body.body.type)
|
||||
|
||||
#define SPA_EVENT_INIT(type) (struct spa_event) \
|
||||
{ { sizeof (struct spa_event_body), SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type } } } \
|
||||
#define SPA_EVENT_INIT(type) (struct spa_event) \
|
||||
{ { sizeof(struct spa_event_body), SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type } } } \
|
||||
|
||||
#define SPA_EVENT_INIT_COMPLEX(t,size,type,...) (t) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, __VA_ARGS__ } } \
|
||||
#define SPA_EVENT_INIT_COMPLEX(t,size,type,...) (t) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, __VA_ARGS__ } } \
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -30,30 +30,30 @@ extern "C" {
|
|||
#include <spa/pod-builder.h>
|
||||
|
||||
static inline uint32_t
|
||||
spa_pod_builder_push_format (struct spa_pod_builder *builder,
|
||||
struct spa_pod_frame *frame,
|
||||
uint32_t format_type,
|
||||
uint32_t media_type,
|
||||
uint32_t media_subtype)
|
||||
spa_pod_builder_push_format(struct spa_pod_builder *builder,
|
||||
struct spa_pod_frame *frame,
|
||||
uint32_t format_type,
|
||||
uint32_t media_type,
|
||||
uint32_t media_subtype)
|
||||
{
|
||||
const struct spa_format p = { { sizeof (struct spa_format_body), SPA_POD_TYPE_OBJECT },
|
||||
{ { 0, format_type },
|
||||
{ { sizeof (uint32_t), SPA_POD_TYPE_ID }, media_type },
|
||||
{ { sizeof (uint32_t), SPA_POD_TYPE_ID }, media_subtype } } };
|
||||
return spa_pod_builder_push (builder, frame, &p.pod,
|
||||
spa_pod_builder_raw (builder, &p, sizeof(p)));
|
||||
const struct spa_format p = {
|
||||
{sizeof(struct spa_format_body), SPA_POD_TYPE_OBJECT}, {{0, format_type},
|
||||
{{sizeof(uint32_t), SPA_POD_TYPE_ID}, media_type},
|
||||
{{sizeof(uint32_t), SPA_POD_TYPE_ID}, media_subtype} } };
|
||||
return spa_pod_builder_push(builder, frame, &p.pod,
|
||||
spa_pod_builder_raw(builder, &p, sizeof(p)));
|
||||
}
|
||||
|
||||
#define spa_pod_builder_format(b,f,format_type,media_type,media_subtype,...) \
|
||||
spa_pod_builder_object(b, f, 0, format_type, \
|
||||
SPA_POD_TYPE_ID,media_type, \
|
||||
SPA_POD_TYPE_ID,media_subtype, \
|
||||
__VA_ARGS__)
|
||||
#define spa_pod_builder_format(b,f,format_type,media_type,media_subtype,...) \
|
||||
spa_pod_builder_object(b, f, 0, format_type, \
|
||||
SPA_POD_TYPE_ID,media_type, \
|
||||
SPA_POD_TYPE_ID,media_subtype, \
|
||||
__VA_ARGS__)
|
||||
|
||||
int
|
||||
spa_format_filter (const struct spa_format *format,
|
||||
const struct spa_format *filter,
|
||||
struct spa_pod_builder *result);
|
||||
spa_format_filter(const struct spa_format *format,
|
||||
const struct spa_format *filter,
|
||||
struct spa_pod_builder *result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -31,154 +31,154 @@ extern "C" {
|
|||
#include <spa/type-map.h>
|
||||
|
||||
struct spa_type_media_type {
|
||||
uint32_t audio;
|
||||
uint32_t video;
|
||||
uint32_t image;
|
||||
uint32_t binary;
|
||||
uint32_t stream;
|
||||
uint32_t audio;
|
||||
uint32_t video;
|
||||
uint32_t image;
|
||||
uint32_t binary;
|
||||
uint32_t stream;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_media_type_map (struct spa_type_map *map, struct spa_type_media_type *type)
|
||||
spa_type_media_type_map(struct spa_type_map *map, struct spa_type_media_type *type)
|
||||
{
|
||||
if (type->audio == 0) {
|
||||
type->audio = spa_type_map_get_id (map, SPA_TYPE_MEDIA_TYPE__audio);
|
||||
type->video = spa_type_map_get_id (map, SPA_TYPE_MEDIA_TYPE__video);
|
||||
type->image = spa_type_map_get_id (map, SPA_TYPE_MEDIA_TYPE__image);
|
||||
type->binary = spa_type_map_get_id (map, SPA_TYPE_MEDIA_TYPE__binary);
|
||||
type->stream = spa_type_map_get_id (map, SPA_TYPE_MEDIA_TYPE__stream);
|
||||
}
|
||||
if (type->audio == 0) {
|
||||
type->audio = spa_type_map_get_id(map, SPA_TYPE_MEDIA_TYPE__audio);
|
||||
type->video = spa_type_map_get_id(map, SPA_TYPE_MEDIA_TYPE__video);
|
||||
type->image = spa_type_map_get_id(map, SPA_TYPE_MEDIA_TYPE__image);
|
||||
type->binary = spa_type_map_get_id(map, SPA_TYPE_MEDIA_TYPE__binary);
|
||||
type->stream = spa_type_map_get_id(map, SPA_TYPE_MEDIA_TYPE__stream);
|
||||
}
|
||||
}
|
||||
|
||||
struct spa_type_media_subtype {
|
||||
uint32_t raw;
|
||||
uint32_t raw;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_media_subtype_map (struct spa_type_map *map, struct spa_type_media_subtype *type)
|
||||
spa_type_media_subtype_map(struct spa_type_map *map, struct spa_type_media_subtype *type)
|
||||
{
|
||||
if (type->raw == 0) {
|
||||
type->raw = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__raw);
|
||||
}
|
||||
if (type->raw == 0) {
|
||||
type->raw = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__raw);
|
||||
}
|
||||
}
|
||||
|
||||
struct spa_type_media_subtype_video {
|
||||
uint32_t h264;
|
||||
uint32_t mjpg;
|
||||
uint32_t dv;
|
||||
uint32_t mpegts;
|
||||
uint32_t h263;
|
||||
uint32_t mpeg1;
|
||||
uint32_t mpeg2;
|
||||
uint32_t mpeg4;
|
||||
uint32_t xvid;
|
||||
uint32_t vc1;
|
||||
uint32_t vp8;
|
||||
uint32_t vp9;
|
||||
uint32_t jpeg;
|
||||
uint32_t bayer;
|
||||
uint32_t h264;
|
||||
uint32_t mjpg;
|
||||
uint32_t dv;
|
||||
uint32_t mpegts;
|
||||
uint32_t h263;
|
||||
uint32_t mpeg1;
|
||||
uint32_t mpeg2;
|
||||
uint32_t mpeg4;
|
||||
uint32_t xvid;
|
||||
uint32_t vc1;
|
||||
uint32_t vp8;
|
||||
uint32_t vp9;
|
||||
uint32_t jpeg;
|
||||
uint32_t bayer;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_media_subtype_video_map (struct spa_type_map *map, struct spa_type_media_subtype_video *type)
|
||||
spa_type_media_subtype_video_map(struct spa_type_map *map,
|
||||
struct spa_type_media_subtype_video *type)
|
||||
{
|
||||
if (type->h264 == 0) {
|
||||
type->h264 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__h264);
|
||||
type->mjpg = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mjpg);
|
||||
type->dv = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__dv);
|
||||
type->mpegts = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mpegts);
|
||||
type->h263 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__h263);
|
||||
type->mpeg1 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mpeg1);
|
||||
type->mpeg2 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mpeg2);
|
||||
type->mpeg4 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mpeg4);
|
||||
type->xvid = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__xvid);
|
||||
type->vc1 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__vc1);
|
||||
type->vp8 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__vp8);
|
||||
type->vp9 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__vp9);
|
||||
type->jpeg = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__jpeg);
|
||||
type->bayer = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__bayer);
|
||||
}
|
||||
if (type->h264 == 0) {
|
||||
type->h264 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__h264);
|
||||
type->mjpg = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mjpg);
|
||||
type->dv = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__dv);
|
||||
type->mpegts = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mpegts);
|
||||
type->h263 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__h263);
|
||||
type->mpeg1 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mpeg1);
|
||||
type->mpeg2 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mpeg2);
|
||||
type->mpeg4 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mpeg4);
|
||||
type->xvid = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__xvid);
|
||||
type->vc1 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__vc1);
|
||||
type->vp8 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__vp8);
|
||||
type->vp9 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__vp9);
|
||||
type->jpeg = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__jpeg);
|
||||
type->bayer = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__bayer);
|
||||
}
|
||||
}
|
||||
|
||||
struct spa_type_media_subtype_audio {
|
||||
uint32_t mp3;
|
||||
uint32_t aac;
|
||||
uint32_t vorbis;
|
||||
uint32_t wma;
|
||||
uint32_t ra;
|
||||
uint32_t sbc;
|
||||
uint32_t adpcm;
|
||||
uint32_t g723;
|
||||
uint32_t g726;
|
||||
uint32_t g729;
|
||||
uint32_t amr;
|
||||
uint32_t gsm;
|
||||
uint32_t mp3;
|
||||
uint32_t aac;
|
||||
uint32_t vorbis;
|
||||
uint32_t wma;
|
||||
uint32_t ra;
|
||||
uint32_t sbc;
|
||||
uint32_t adpcm;
|
||||
uint32_t g723;
|
||||
uint32_t g726;
|
||||
uint32_t g729;
|
||||
uint32_t amr;
|
||||
uint32_t gsm;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_type_media_subtype_audio_map (struct spa_type_map *map, struct spa_type_media_subtype_audio *type)
|
||||
spa_type_media_subtype_audio_map(struct spa_type_map *map,
|
||||
struct spa_type_media_subtype_audio *type)
|
||||
{
|
||||
if (type->mp3 == 0) {
|
||||
type->mp3 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__mp3);
|
||||
type->aac = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__aac);
|
||||
type->vorbis = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__vorbis);
|
||||
type->wma = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__wma);
|
||||
type->ra = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__ra);
|
||||
type->sbc = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__sbc);
|
||||
type->adpcm = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__adpcm);
|
||||
type->g723 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__g723);
|
||||
type->g726 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__g726);
|
||||
type->g729 = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__g729);
|
||||
type->amr = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__amr);
|
||||
type->gsm = spa_type_map_get_id (map, SPA_TYPE_MEDIA_SUBTYPE__gsm);
|
||||
}
|
||||
if (type->mp3 == 0) {
|
||||
type->mp3 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__mp3);
|
||||
type->aac = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__aac);
|
||||
type->vorbis = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__vorbis);
|
||||
type->wma = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__wma);
|
||||
type->ra = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__ra);
|
||||
type->sbc = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__sbc);
|
||||
type->adpcm = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__adpcm);
|
||||
type->g723 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__g723);
|
||||
type->g726 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__g726);
|
||||
type->g729 = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__g729);
|
||||
type->amr = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__amr);
|
||||
type->gsm = spa_type_map_get_id(map, SPA_TYPE_MEDIA_SUBTYPE__gsm);
|
||||
}
|
||||
}
|
||||
|
||||
#define SPA_FORMAT_INIT(size,type,media_type,media_subtype,...) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, \
|
||||
SPA_POD_ID_INIT (media_type), \
|
||||
SPA_POD_ID_INIT (media_subtype) } }
|
||||
#define SPA_FORMAT_INIT(size,type,media_type,media_subtype,...) \
|
||||
{ { size, SPA_POD_TYPE_OBJECT }, \
|
||||
{ { 0, type }, \
|
||||
SPA_POD_ID_INIT(media_type), \
|
||||
SPA_POD_ID_INIT(media_subtype) } }
|
||||
|
||||
#define SPA_FORMAT_BODY_FOREACH(body, size, iter) \
|
||||
for ((iter) = SPA_MEMBER ((body), sizeof (struct spa_format_body), struct spa_pod_prop); \
|
||||
(iter) < SPA_MEMBER ((body), (size), struct spa_pod_prop); \
|
||||
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), struct spa_pod_prop))
|
||||
#define SPA_FORMAT_BODY_FOREACH(body, size, iter) \
|
||||
for ((iter) = SPA_MEMBER((body), sizeof(struct spa_format_body), struct spa_pod_prop); \
|
||||
(iter) < SPA_MEMBER((body), (size), struct spa_pod_prop); \
|
||||
(iter) = SPA_MEMBER((iter), SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), struct spa_pod_prop))
|
||||
|
||||
#define SPA_FORMAT_FOREACH(format, iter) \
|
||||
SPA_FORMAT_BODY_FOREACH(&format->body, SPA_POD_BODY_SIZE(format), iter)
|
||||
SPA_FORMAT_BODY_FOREACH(&format->body, SPA_POD_BODY_SIZE(format), iter)
|
||||
|
||||
#define SPA_FORMAT_MEDIA_TYPE(f) SPA_POD_VALUE (struct spa_pod_id, &f->body.media_type)
|
||||
#define SPA_FORMAT_MEDIA_SUBTYPE(f) SPA_POD_VALUE (struct spa_pod_id, &f->body.media_subtype)
|
||||
#define SPA_FORMAT_MEDIA_TYPE(f) SPA_POD_VALUE(struct spa_pod_id, &f->body.media_type)
|
||||
#define SPA_FORMAT_MEDIA_SUBTYPE(f) SPA_POD_VALUE(struct spa_pod_id, &f->body.media_subtype)
|
||||
|
||||
static inline struct spa_pod_prop *
|
||||
spa_format_find_prop (const struct spa_format *format, uint32_t key)
|
||||
static inline struct spa_pod_prop *spa_format_find_prop(const struct spa_format *format,
|
||||
uint32_t key)
|
||||
{
|
||||
return spa_pod_contents_find_prop (&format->pod, sizeof (struct spa_format), key);
|
||||
return spa_pod_contents_find_prop(&format->pod, sizeof(struct spa_format), key);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
spa_format_query (const struct spa_format *format, uint32_t key, ...)
|
||||
static inline uint32_t spa_format_query(const struct spa_format *format, uint32_t key, ...)
|
||||
{
|
||||
uint32_t count;
|
||||
va_list args;
|
||||
uint32_t count;
|
||||
va_list args;
|
||||
|
||||
va_start (args, key);
|
||||
count = spa_pod_contents_queryv (&format->pod, sizeof (struct spa_format), key, args);
|
||||
va_end (args);
|
||||
va_start(args, key);
|
||||
count = spa_pod_contents_queryv(&format->pod, sizeof(struct spa_format), key, args);
|
||||
va_end(args);
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline int
|
||||
spa_format_fixate (struct spa_format *format)
|
||||
static inline int spa_format_fixate(struct spa_format *format)
|
||||
{
|
||||
struct spa_pod_prop *prop;
|
||||
struct spa_pod_prop *prop;
|
||||
|
||||
SPA_FORMAT_FOREACH (format, prop)
|
||||
prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
|
||||
SPA_FORMAT_FOREACH(format, prop)
|
||||
prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ struct spa_format;
|
|||
#define SPA_TYPE_MEDIA_SUBTYPE__gsm SPA_TYPE_MEDIA_SUBTYPE_BASE "gsm"
|
||||
|
||||
struct spa_format_body {
|
||||
struct spa_pod_object_body obj_body;
|
||||
struct spa_pod_id media_type SPA_ALIGNED (8);
|
||||
struct spa_pod_id media_subtype SPA_ALIGNED (8);
|
||||
/* contents follow, series of spa_pod_prop */
|
||||
struct spa_pod_object_body obj_body;
|
||||
struct spa_pod_id media_type SPA_ALIGNED(8);
|
||||
struct spa_pod_id media_subtype SPA_ALIGNED(8);
|
||||
/* contents follow, series of spa_pod_prop */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -90,8 +90,8 @@ struct spa_format_body {
|
|||
* @pod: POD object with properties
|
||||
*/
|
||||
struct spa_format {
|
||||
struct spa_pod pod;
|
||||
struct spa_format_body body;
|
||||
struct spa_pod pod;
|
||||
struct spa_format_body body;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -32,190 +32,186 @@ struct spa_graph_node;
|
|||
struct spa_graph_port;
|
||||
|
||||
struct spa_graph {
|
||||
struct spa_list nodes;
|
||||
struct spa_list ready;
|
||||
struct spa_list nodes;
|
||||
struct spa_list ready;
|
||||
};
|
||||
|
||||
typedef int (*spa_graph_node_func_t) (struct spa_graph_node *node);
|
||||
typedef int (*spa_graph_node_func_t) (struct spa_graph_node * node);
|
||||
|
||||
struct spa_graph_node {
|
||||
struct spa_list link;
|
||||
struct spa_list ready_link;
|
||||
struct spa_list ports[2];
|
||||
struct spa_list link;
|
||||
struct spa_list ready_link;
|
||||
struct spa_list ports[2];
|
||||
#define SPA_GRAPH_NODE_FLAG_ASYNC (1 << 0)
|
||||
uint32_t flags;
|
||||
int state;
|
||||
uint32_t flags;
|
||||
int state;
|
||||
#define SPA_GRAPH_ACTION_CHECK 0
|
||||
#define SPA_GRAPH_ACTION_IN 1
|
||||
#define SPA_GRAPH_ACTION_OUT 2
|
||||
uint32_t action;
|
||||
spa_graph_node_func_t schedule;
|
||||
void *user_data;
|
||||
uint32_t max_in;
|
||||
uint32_t required_in;
|
||||
uint32_t ready_in;
|
||||
uint32_t action;
|
||||
spa_graph_node_func_t schedule;
|
||||
void *user_data;
|
||||
uint32_t max_in;
|
||||
uint32_t required_in;
|
||||
uint32_t ready_in;
|
||||
};
|
||||
|
||||
struct spa_graph_port {
|
||||
struct spa_list link;
|
||||
struct spa_graph_node *node;
|
||||
enum spa_direction direction;
|
||||
uint32_t port_id;
|
||||
uint32_t flags;
|
||||
struct spa_port_io *io;
|
||||
struct spa_graph_port *peer;
|
||||
struct spa_list link;
|
||||
struct spa_graph_node *node;
|
||||
enum spa_direction direction;
|
||||
uint32_t port_id;
|
||||
uint32_t flags;
|
||||
struct spa_port_io *io;
|
||||
struct spa_graph_port *peer;
|
||||
};
|
||||
|
||||
static inline void
|
||||
spa_graph_init (struct spa_graph *graph)
|
||||
static inline void spa_graph_init(struct spa_graph *graph)
|
||||
{
|
||||
spa_list_init (&graph->nodes);
|
||||
spa_list_init (&graph->ready);
|
||||
spa_list_init(&graph->nodes);
|
||||
spa_list_init(&graph->ready);
|
||||
}
|
||||
|
||||
static inline int
|
||||
spa_graph_node_schedule_default (struct spa_graph_node *node)
|
||||
static inline int spa_graph_node_schedule_default(struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_node *n = node->user_data;
|
||||
struct spa_node *n = node->user_data;
|
||||
|
||||
if (node->action == SPA_GRAPH_ACTION_IN)
|
||||
return spa_node_process_input (n);
|
||||
else if (node->action == SPA_GRAPH_ACTION_OUT)
|
||||
return spa_node_process_output (n);
|
||||
else
|
||||
return SPA_RESULT_ERROR;
|
||||
if (node->action == SPA_GRAPH_ACTION_IN)
|
||||
return spa_node_process_input(n);
|
||||
else if (node->action == SPA_GRAPH_ACTION_OUT)
|
||||
return spa_node_process_output(n);
|
||||
else
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_node_add (struct spa_graph *graph, struct spa_graph_node *node, spa_graph_node_func_t schedule, void *user_data)
|
||||
spa_graph_node_add(struct spa_graph *graph, struct spa_graph_node *node,
|
||||
spa_graph_node_func_t schedule, void *user_data)
|
||||
{
|
||||
spa_list_init (&node->ports[SPA_DIRECTION_INPUT]);
|
||||
spa_list_init (&node->ports[SPA_DIRECTION_OUTPUT]);
|
||||
node->flags = 0;
|
||||
node->state = SPA_RESULT_OK;
|
||||
node->action = SPA_GRAPH_ACTION_OUT;
|
||||
node->schedule = schedule;
|
||||
node->user_data = user_data;
|
||||
spa_list_insert (graph->nodes.prev, &node->link);
|
||||
node->max_in = node->required_in = node->ready_in = 0;
|
||||
spa_list_init(&node->ports[SPA_DIRECTION_INPUT]);
|
||||
spa_list_init(&node->ports[SPA_DIRECTION_OUTPUT]);
|
||||
node->flags = 0;
|
||||
node->state = SPA_RESULT_OK;
|
||||
node->action = SPA_GRAPH_ACTION_OUT;
|
||||
node->schedule = schedule;
|
||||
node->user_data = user_data;
|
||||
spa_list_insert(graph->nodes.prev, &node->link);
|
||||
node->max_in = node->required_in = node->ready_in = 0;
|
||||
}
|
||||
|
||||
static inline void spa_graph_port_check(struct spa_graph *graph, struct spa_graph_port *port)
|
||||
{
|
||||
struct spa_graph_node *node = port->node;
|
||||
|
||||
if (port->io->status == SPA_RESULT_HAVE_BUFFER)
|
||||
node->ready_in++;
|
||||
|
||||
if (node->required_in > 0 && node->ready_in == node->required_in) {
|
||||
node->action = SPA_GRAPH_ACTION_IN;
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert(graph->ready.prev, &node->ready_link);
|
||||
} else if (node->ready_link.next) {
|
||||
spa_list_remove(&node->ready_link);
|
||||
node->ready_link.next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_port_check (struct spa_graph *graph,
|
||||
struct spa_graph_port *port)
|
||||
spa_graph_port_add(struct spa_graph *graph,
|
||||
struct spa_graph_node *node,
|
||||
struct spa_graph_port *port,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t flags,
|
||||
struct spa_port_io *io)
|
||||
{
|
||||
struct spa_graph_node *node = port->node;
|
||||
port->node = node;
|
||||
port->direction = direction;
|
||||
port->port_id = port_id;
|
||||
port->flags = flags;
|
||||
port->io = io;
|
||||
port->peer = NULL;
|
||||
spa_list_insert(node->ports[port->direction].prev, &port->link);
|
||||
node->max_in++;
|
||||
if (!(port->flags & SPA_PORT_INFO_FLAG_OPTIONAL) && direction == SPA_DIRECTION_INPUT)
|
||||
node->required_in++;
|
||||
spa_graph_port_check(graph, port);
|
||||
}
|
||||
|
||||
if (port->io->status == SPA_RESULT_HAVE_BUFFER)
|
||||
node->ready_in++;
|
||||
static inline void spa_graph_node_remove(struct spa_graph *graph, struct spa_graph_node *node)
|
||||
{
|
||||
spa_list_remove(&node->link);
|
||||
}
|
||||
|
||||
if (node->required_in > 0 && node->ready_in == node->required_in) {
|
||||
node->action = SPA_GRAPH_ACTION_IN;
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert (graph->ready.prev, &node->ready_link);
|
||||
} else if (node->ready_link.next) {
|
||||
spa_list_remove (&node->ready_link);
|
||||
node->ready_link.next = NULL;
|
||||
}
|
||||
static inline void spa_graph_port_remove(struct spa_graph *graph, struct spa_graph_port *port)
|
||||
{
|
||||
spa_list_remove(&port->link);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_port_add (struct spa_graph *graph,
|
||||
struct spa_graph_node *node,
|
||||
struct spa_graph_port *port,
|
||||
enum spa_direction direction,
|
||||
uint32_t port_id,
|
||||
uint32_t flags,
|
||||
struct spa_port_io *io)
|
||||
spa_graph_port_link(struct spa_graph *graph, struct spa_graph_port *out, struct spa_graph_port *in)
|
||||
{
|
||||
port->node = node;
|
||||
port->direction = direction;
|
||||
port->port_id = port_id;
|
||||
port->flags = flags;
|
||||
port->io = io;
|
||||
port->peer = NULL;
|
||||
spa_list_insert (node->ports[port->direction].prev, &port->link);
|
||||
node->max_in++;
|
||||
if (!(port->flags & SPA_PORT_INFO_FLAG_OPTIONAL) && direction == SPA_DIRECTION_INPUT)
|
||||
node->required_in++;
|
||||
spa_graph_port_check (graph, port);
|
||||
out->peer = in;
|
||||
in->peer = out;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_node_remove (struct spa_graph *graph, struct spa_graph_node *node)
|
||||
spa_graph_port_unlink(struct spa_graph *graph, struct spa_graph_port *out,
|
||||
struct spa_graph_port *in)
|
||||
{
|
||||
spa_list_remove (&node->link);
|
||||
out->peer = NULL;
|
||||
in->peer = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_port_remove (struct spa_graph *graph, struct spa_graph_port *port)
|
||||
static inline void spa_graph_node_schedule(struct spa_graph *graph, struct spa_graph_node *node)
|
||||
{
|
||||
spa_list_remove (&port->link);
|
||||
}
|
||||
struct spa_graph_port *p;
|
||||
|
||||
static inline void
|
||||
spa_graph_port_link (struct spa_graph *graph, struct spa_graph_port *out, struct spa_graph_port *in)
|
||||
{
|
||||
out->peer = in;
|
||||
in->peer = out;
|
||||
}
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert(graph->ready.prev, &node->ready_link);
|
||||
|
||||
static inline void
|
||||
spa_graph_port_unlink (struct spa_graph *graph, struct spa_graph_port *out, struct spa_graph_port *in)
|
||||
{
|
||||
out->peer = NULL;
|
||||
in->peer = NULL;
|
||||
}
|
||||
while (!spa_list_is_empty(&graph->ready)) {
|
||||
struct spa_graph_node *n =
|
||||
spa_list_first(&graph->ready, struct spa_graph_node, ready_link);
|
||||
|
||||
static inline void
|
||||
spa_graph_node_schedule (struct spa_graph *graph, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_port *p;
|
||||
spa_list_remove(&n->ready_link);
|
||||
n->ready_link.next = NULL;
|
||||
|
||||
if (node->ready_link.next == NULL)
|
||||
spa_list_insert (graph->ready.prev, &node->ready_link);
|
||||
switch (n->action) {
|
||||
case SPA_GRAPH_ACTION_IN:
|
||||
case SPA_GRAPH_ACTION_OUT:
|
||||
n->state = n->schedule(n);
|
||||
if (n->action == SPA_GRAPH_ACTION_IN && n == node)
|
||||
continue;
|
||||
n->action = SPA_GRAPH_ACTION_CHECK;
|
||||
spa_list_insert(graph->ready.prev, &n->ready_link);
|
||||
break;
|
||||
|
||||
while (!spa_list_is_empty (&graph->ready)) {
|
||||
struct spa_graph_node *n = spa_list_first (&graph->ready, struct spa_graph_node, ready_link);
|
||||
case SPA_GRAPH_ACTION_CHECK:
|
||||
if (n->state == SPA_RESULT_NEED_BUFFER) {
|
||||
n->ready_in = 0;
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
struct spa_graph_node *pn = p->peer->node;
|
||||
if (p->io->status == SPA_RESULT_NEED_BUFFER) {
|
||||
if (pn != node
|
||||
|| pn->flags & SPA_GRAPH_NODE_FLAG_ASYNC) {
|
||||
pn->action = SPA_GRAPH_ACTION_OUT;
|
||||
spa_list_insert(graph->ready.prev,
|
||||
&pn->ready_link);
|
||||
}
|
||||
} else if (p->io->status == SPA_RESULT_OK)
|
||||
n->ready_in++;
|
||||
}
|
||||
} else if (n->state == SPA_RESULT_HAVE_BUFFER) {
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link)
|
||||
spa_graph_port_check(graph, p->peer);
|
||||
}
|
||||
break;
|
||||
|
||||
spa_list_remove (&n->ready_link);
|
||||
n->ready_link.next = NULL;
|
||||
|
||||
switch (n->action) {
|
||||
case SPA_GRAPH_ACTION_IN:
|
||||
case SPA_GRAPH_ACTION_OUT:
|
||||
n->state = n->schedule (n);
|
||||
if (n->action == SPA_GRAPH_ACTION_IN && n == node)
|
||||
continue;
|
||||
n->action = SPA_GRAPH_ACTION_CHECK;
|
||||
spa_list_insert (graph->ready.prev, &n->ready_link);
|
||||
break;
|
||||
|
||||
case SPA_GRAPH_ACTION_CHECK:
|
||||
if (n->state == SPA_RESULT_NEED_BUFFER) {
|
||||
n->ready_in = 0;
|
||||
spa_list_for_each (p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
struct spa_graph_node *pn = p->peer->node;
|
||||
if (p->io->status == SPA_RESULT_NEED_BUFFER) {
|
||||
if (pn != node || pn->flags & SPA_GRAPH_NODE_FLAG_ASYNC) {
|
||||
pn->action = SPA_GRAPH_ACTION_OUT;
|
||||
spa_list_insert (graph->ready.prev, &pn->ready_link);
|
||||
}
|
||||
}
|
||||
else if (p->io->status == SPA_RESULT_OK)
|
||||
n->ready_in++;
|
||||
}
|
||||
}
|
||||
else if (n->state == SPA_RESULT_HAVE_BUFFER) {
|
||||
spa_list_for_each (p, &n->ports[SPA_DIRECTION_OUTPUT], link)
|
||||
spa_graph_port_check (graph, p->peer);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue