This commit is contained in:
Wim Taymans 2017-05-26 08:05:01 +02:00
parent d1a06ae247
commit 5b037661d9
154 changed files with 21017 additions and 23044 deletions

View file

@ -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" */

View file

@ -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;
}

View file

@ -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

View file

@ -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
}

View file

@ -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__)

View file

@ -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);
}

View file

@ -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
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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__)

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -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];
}

View file

@ -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

View file

@ -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
}

View file

@ -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());
}

View file

@ -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

View file

@ -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
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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" */

View file

@ -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__ */

View file

@ -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

View file

@ -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" */

View file

@ -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" */

View file

@ -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" */

View file

@ -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

View file

@ -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

View file

@ -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