mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
Add audiotestsrc
Work on idle poll Move node state to the node interface so that we can actually get it in the sync case. Add enabled field to the poll event Work on audiotestsrc
This commit is contained in:
parent
52e45cf2a1
commit
7aa79a2a0d
24 changed files with 721 additions and 100 deletions
|
|
@ -245,6 +245,7 @@ if BUILD_MODULE_SPA
|
||||||
module_LTLIBRARIES += module-spa.la
|
module_LTLIBRARIES += module-spa.la
|
||||||
|
|
||||||
module_spa_la_SOURCES = \
|
module_spa_la_SOURCES = \
|
||||||
|
modules/spa/spa-audiotestsrc.c \
|
||||||
modules/spa/spa-alsa-sink.c \
|
modules/spa/spa-alsa-sink.c \
|
||||||
modules/spa/spa-v4l2-source.c \
|
modules/spa/spa-v4l2-source.c \
|
||||||
modules/spa/module.c
|
modules/spa/module.c
|
||||||
|
|
|
||||||
|
|
@ -833,7 +833,7 @@ parse_control (PinosStream *stream,
|
||||||
bid.buf = p.buffers[i];
|
bid.buf = p.buffers[i];
|
||||||
bid.cleanup = false;
|
bid.cleanup = false;
|
||||||
bid.id = bid.buf->id;
|
bid.id = bid.buf->id;
|
||||||
g_debug ("add buffer %d, %d", bid.id, bid.buf->mem.mem.id);
|
g_debug ("add buffer %d, %d, %zd, %zd", bid.id, bid.buf->mem.mem.id, bid.buf->mem.offset, bid.buf->mem.size);
|
||||||
|
|
||||||
if (bid.id != priv->buffer_ids->len) {
|
if (bid.id != priv->buffer_ids->len) {
|
||||||
g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len);
|
g_warning ("unexpected id %u found, expected %u", bid.id, priv->buffer_ids->len);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "spa-alsa-sink.h"
|
#include "spa-alsa-sink.h"
|
||||||
#include "spa-v4l2-source.h"
|
#include "spa-v4l2-source.h"
|
||||||
|
#include "spa-audiotestsrc.h"
|
||||||
|
|
||||||
gboolean pinos__module_init (PinosModule *module, const gchar * args);
|
gboolean pinos__module_init (PinosModule *module, const gchar * args);
|
||||||
|
|
||||||
|
|
@ -31,6 +32,7 @@ pinos__module_init (PinosModule * module, G_GNUC_UNUSED const gchar * args)
|
||||||
{
|
{
|
||||||
pinos_spa_alsa_sink_new (module->daemon, "alsa-sink", NULL);
|
pinos_spa_alsa_sink_new (module->daemon, "alsa-sink", NULL);
|
||||||
pinos_spa_v4l2_source_new (module->daemon, "v4l2-source", NULL);
|
pinos_spa_v4l2_source_new (module->daemon, "v4l2-source", NULL);
|
||||||
|
pinos_spa_audiotestsrc_new (module->daemon, "audiotestsrc", NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
198
pinos/modules/spa/spa-audiotestsrc.c
Normal file
198
pinos/modules/spa/spa-audiotestsrc.c
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
/* Pinos
|
||||||
|
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <spa/include/spa/node.h>
|
||||||
|
|
||||||
|
#include "spa-audiotestsrc.h"
|
||||||
|
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcPrivate))
|
||||||
|
|
||||||
|
struct _PinosSpaAudioTestSrcPrivate
|
||||||
|
{
|
||||||
|
PinosRingbuffer *ringbuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (PinosSpaAudioTestSrc, pinos_spa_audiotestsrc, PINOS_TYPE_NODE);
|
||||||
|
|
||||||
|
static SpaResult
|
||||||
|
make_node (SpaNode **node, const char *lib, const char *name)
|
||||||
|
{
|
||||||
|
SpaHandle *handle;
|
||||||
|
SpaResult res;
|
||||||
|
void *hnd, *state = NULL;
|
||||||
|
SpaEnumHandleFactoryFunc enum_func;
|
||||||
|
|
||||||
|
if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) {
|
||||||
|
g_error ("can't load %s: %s", lib, dlerror());
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) {
|
||||||
|
g_error ("can't find enum function");
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const SpaHandleFactory *factory;
|
||||||
|
void *iface;
|
||||||
|
|
||||||
|
if ((res = enum_func (&factory, &state)) < 0) {
|
||||||
|
if (res != SPA_RESULT_ENUM_END)
|
||||||
|
g_error ("can't enumerate factories: %d", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp (factory->name, name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
handle = calloc (1, factory->size);
|
||||||
|
if ((res = factory->init (factory, handle)) < 0) {
|
||||||
|
g_error ("can't make factory instance: %d", res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if ((res = handle->get_interface (handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) {
|
||||||
|
g_error ("can't get interface %d", res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*node = iface;
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_node (PinosSpaAudioTestSrc *this)
|
||||||
|
{
|
||||||
|
PinosNode *node = PINOS_NODE (this);
|
||||||
|
SpaResult res;
|
||||||
|
SpaProps *props;
|
||||||
|
SpaPropValue value;
|
||||||
|
|
||||||
|
if ((res = spa_node_get_props (node->node, &props)) < 0)
|
||||||
|
g_debug ("got get_props error %d", res);
|
||||||
|
|
||||||
|
value.type = SPA_PROP_TYPE_STRING;
|
||||||
|
value.value = "hw:1";
|
||||||
|
value.size = strlen (value.value)+1;
|
||||||
|
spa_props_set_prop (props, spa_props_index_for_name (props, "device"), &value);
|
||||||
|
|
||||||
|
if ((res = spa_node_set_props (node->node, props)) < 0)
|
||||||
|
g_debug ("got set_props error %d", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
src_constructed (GObject * object)
|
||||||
|
{
|
||||||
|
PinosSpaAudioTestSrc *src = PINOS_SPA_AUDIOTESTSRC (object);
|
||||||
|
|
||||||
|
setup_node (src);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (pinos_spa_audiotestsrc_parent_class)->constructed (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
src_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
PinosNode *node = PINOS_NODE (object);
|
||||||
|
PinosSpaAudioTestSrc *src = PINOS_SPA_AUDIOTESTSRC (object);
|
||||||
|
|
||||||
|
g_debug ("audiotestsrc %p: dispose", src);
|
||||||
|
spa_handle_clear (node->node->handle);
|
||||||
|
g_free (node->node->handle);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (pinos_spa_audiotestsrc_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pinos_spa_audiotestsrc_class_init (PinosSpaAudioTestSrcClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (PinosSpaAudioTestSrcPrivate));
|
||||||
|
|
||||||
|
gobject_class->constructed = src_constructed;
|
||||||
|
gobject_class->finalize = src_finalize;
|
||||||
|
gobject_class->get_property = get_property;
|
||||||
|
gobject_class->set_property = set_property;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pinos_spa_audiotestsrc_init (PinosSpaAudioTestSrc * this)
|
||||||
|
{
|
||||||
|
this->priv = PINOS_SPA_AUDIOTESTSRC_GET_PRIVATE (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PinosNode *
|
||||||
|
pinos_spa_audiotestsrc_new (PinosDaemon *daemon,
|
||||||
|
const gchar *name,
|
||||||
|
PinosProperties *properties)
|
||||||
|
{
|
||||||
|
PinosNode *node;
|
||||||
|
SpaNode *n;
|
||||||
|
SpaResult res;
|
||||||
|
|
||||||
|
if ((res = make_node (&n,
|
||||||
|
"spa/build/plugins/audiotestsrc/libspa-audiotestsrc.so",
|
||||||
|
"audiotestsrc")) < 0) {
|
||||||
|
g_error ("can't create audiotestsrc: %d", res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = g_object_new (PINOS_TYPE_SPA_AUDIOTESTSRC,
|
||||||
|
"daemon", daemon,
|
||||||
|
"name", name,
|
||||||
|
"properties", properties,
|
||||||
|
"node", n,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
61
pinos/modules/spa/spa-audiotestsrc.h
Normal file
61
pinos/modules/spa/spa-audiotestsrc.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* Pinos
|
||||||
|
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PINOS_SPA_AUDIOTESTSRC_H__
|
||||||
|
#define __PINOS_SPA_AUDIOTESTSRC_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include <client/pinos.h>
|
||||||
|
#include <server/node.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define PINOS_TYPE_SPA_AUDIOTESTSRC (pinos_spa_audiotestsrc_get_type ())
|
||||||
|
#define PINOS_IS_SPA_AUDIOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC))
|
||||||
|
#define PINOS_IS_SPA_AUDIOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SPA_AUDIOTESTSRC))
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcClass))
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrc))
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcClass))
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC_CAST(obj) ((PinosSpaAudioTestSrc*)(obj))
|
||||||
|
#define PINOS_SPA_AUDIOTESTSRC_CLASS_CAST(klass) ((PinosSpaAudioTestSrcClass*)(klass))
|
||||||
|
|
||||||
|
typedef struct _PinosSpaAudioTestSrc PinosSpaAudioTestSrc;
|
||||||
|
typedef struct _PinosSpaAudioTestSrcClass PinosSpaAudioTestSrcClass;
|
||||||
|
typedef struct _PinosSpaAudioTestSrcPrivate PinosSpaAudioTestSrcPrivate;
|
||||||
|
|
||||||
|
struct _PinosSpaAudioTestSrc {
|
||||||
|
PinosNode object;
|
||||||
|
|
||||||
|
PinosSpaAudioTestSrcPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PinosSpaAudioTestSrcClass {
|
||||||
|
PinosNodeClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType pinos_spa_audiotestsrc_get_type (void);
|
||||||
|
|
||||||
|
PinosNode * pinos_spa_audiotestsrc_new (PinosDaemon *daemon,
|
||||||
|
const gchar *name,
|
||||||
|
PinosProperties *properties);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __PINOS_SPA_AUDIOTESTSRC_H__ */
|
||||||
|
|
@ -410,8 +410,8 @@ check_states (PinosLink *this)
|
||||||
SpaResult res;
|
SpaResult res;
|
||||||
SpaNodeState in_state, out_state;
|
SpaNodeState in_state, out_state;
|
||||||
|
|
||||||
in_state = this->input_node->node_state;
|
in_state = this->input_node->node->state;
|
||||||
out_state = this->output_node->node_state;
|
out_state = this->output_node->node->state;
|
||||||
|
|
||||||
g_debug ("link %p: input %d, output %d", this, in_state, out_state);
|
g_debug ("link %p: input %d, output %d", this, in_state, out_state);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,12 @@ struct _PinosNodePrivate
|
||||||
|
|
||||||
PinosProperties *properties;
|
PinosProperties *properties;
|
||||||
|
|
||||||
|
unsigned int n_poll;
|
||||||
|
SpaPollItem poll[16];
|
||||||
|
|
||||||
|
bool rebuild_fds;
|
||||||
SpaPollFd fds[16];
|
SpaPollFd fds[16];
|
||||||
unsigned int n_fds;
|
unsigned int n_fds;
|
||||||
SpaPollItem poll;
|
|
||||||
|
|
||||||
gboolean running;
|
gboolean running;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|
@ -119,6 +122,8 @@ update_port_ids (PinosNode *node, gboolean create)
|
||||||
&priv->n_output_ports,
|
&priv->n_output_ports,
|
||||||
&priv->max_output_ports);
|
&priv->max_output_ports);
|
||||||
|
|
||||||
|
g_debug ("node %p: update_port ids %u, %u", node, priv->max_input_ports, priv->max_output_ports);
|
||||||
|
|
||||||
priv->input_port_ids = g_realloc_n (priv->input_port_ids, priv->max_input_ports, sizeof (uint32_t));
|
priv->input_port_ids = g_realloc_n (priv->input_port_ids, priv->max_input_ports, sizeof (uint32_t));
|
||||||
priv->output_port_ids = g_realloc_n (priv->output_port_ids, priv->max_output_ports, sizeof (uint32_t));
|
priv->output_port_ids = g_realloc_n (priv->output_port_ids, priv->max_output_ports, sizeof (uint32_t));
|
||||||
|
|
||||||
|
|
@ -134,11 +139,58 @@ loop (void *user_data)
|
||||||
{
|
{
|
||||||
PinosNode *this = user_data;
|
PinosNode *this = user_data;
|
||||||
PinosNodePrivate *priv = this->priv;
|
PinosNodePrivate *priv = this->priv;
|
||||||
int r;
|
unsigned int i, j;
|
||||||
|
|
||||||
g_debug ("node %p: enter thread", this);
|
g_debug ("node %p: enter thread", this);
|
||||||
while (priv->running) {
|
while (priv->running) {
|
||||||
SpaPollNotifyData ndata;
|
SpaPollNotifyData ndata;
|
||||||
|
unsigned int n_idle = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* prepare */
|
||||||
|
for (i = 0; i < priv->n_poll; i++) {
|
||||||
|
SpaPollItem *p = &priv->poll[i];
|
||||||
|
|
||||||
|
if (p->enabled && p->idle_cb) {
|
||||||
|
ndata.fds = NULL;
|
||||||
|
ndata.n_fds = 0;
|
||||||
|
ndata.user_data = p->user_data;
|
||||||
|
p->idle_cb (&ndata);
|
||||||
|
n_idle++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n_idle > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* rebuild */
|
||||||
|
if (priv->rebuild_fds) {
|
||||||
|
g_debug ("node %p: rebuild fds", this);
|
||||||
|
priv->n_fds = 1;
|
||||||
|
for (i = 0; i < priv->n_poll; i++) {
|
||||||
|
SpaPollItem *p = &priv->poll[i];
|
||||||
|
|
||||||
|
if (!p->enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (j = 0; j < p->n_fds; j++)
|
||||||
|
priv->fds[priv->n_fds + j] = p->fds[j];
|
||||||
|
p->fds = &priv->fds[priv->n_fds];
|
||||||
|
priv->n_fds += p->n_fds;
|
||||||
|
}
|
||||||
|
priv->rebuild_fds = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* before */
|
||||||
|
for (i = 0; i < priv->n_poll; i++) {
|
||||||
|
SpaPollItem *p = &priv->poll[i];
|
||||||
|
|
||||||
|
if (p->enabled && p->before_cb) {
|
||||||
|
ndata.fds = p->fds;
|
||||||
|
ndata.n_fds = p->n_fds;
|
||||||
|
ndata.user_data = p->user_data;
|
||||||
|
p->before_cb (&ndata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = poll ((struct pollfd *) priv->fds, priv->n_fds, -1);
|
r = poll ((struct pollfd *) priv->fds, priv->n_fds, -1);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|
@ -150,19 +202,25 @@ loop (void *user_data)
|
||||||
g_debug ("node %p: select timeout", this);
|
g_debug ("node %p: select timeout", this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check wakeup */
|
||||||
if (priv->fds[0].revents & POLLIN) {
|
if (priv->fds[0].revents & POLLIN) {
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
if (read (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t))
|
if (read (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||||
g_warning ("node %p: failed to read fd", strerror (errno));
|
g_warning ("node %p: failed to read fd", strerror (errno));
|
||||||
g_debug ("node %p: event signaled", this);
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->poll.after_cb) {
|
/* after */
|
||||||
ndata.fds = priv->poll.fds;
|
for (i = 0; i < priv->n_poll; i++) {
|
||||||
ndata.n_fds = priv->poll.n_fds;
|
SpaPollItem *p = &priv->poll[i];
|
||||||
ndata.user_data = priv->poll.user_data;
|
|
||||||
priv->poll.after_cb (&ndata);
|
if (p->enabled && p->after_cb) {
|
||||||
|
ndata.fds = p->fds;
|
||||||
|
ndata.n_fds = p->n_fds;
|
||||||
|
ndata.user_data = p->user_data;
|
||||||
|
p->after_cb (&ndata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_debug ("node %p: leave thread", this);
|
g_debug ("node %p: leave thread", this);
|
||||||
|
|
@ -170,6 +228,15 @@ loop (void *user_data)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wakeup_thread (PinosNode *this)
|
||||||
|
{
|
||||||
|
PinosNodePrivate *priv = this->priv;
|
||||||
|
uint64_t u = 1;
|
||||||
|
|
||||||
|
if (write (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||||
|
g_warning ("node %p: failed to write fd", strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_thread (PinosNode *this)
|
start_thread (PinosNode *this)
|
||||||
|
|
@ -192,12 +259,8 @@ stop_thread (PinosNode *this)
|
||||||
PinosNodePrivate *priv = this->priv;
|
PinosNodePrivate *priv = this->priv;
|
||||||
|
|
||||||
if (priv->running) {
|
if (priv->running) {
|
||||||
uint64_t u = 1;
|
|
||||||
|
|
||||||
if (write (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t))
|
|
||||||
g_warning ("node %p: failed to write fd", strerror (errno));
|
|
||||||
|
|
||||||
priv->running = false;
|
priv->running = false;
|
||||||
|
wakeup_thread (this);
|
||||||
pthread_join (priv->thread, NULL);
|
pthread_join (priv->thread, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -286,15 +349,12 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
||||||
{
|
{
|
||||||
SpaEventStateChange *sc = event->data;
|
SpaEventStateChange *sc = event->data;
|
||||||
|
|
||||||
if (this->node_state != sc->state) {
|
|
||||||
g_debug ("node %p: update SPA state to %d", this, sc->state);
|
g_debug ("node %p: update SPA state to %d", this, sc->state);
|
||||||
this->node_state = sc->state;
|
|
||||||
g_object_notify (G_OBJECT (this), "node-state");
|
g_object_notify (G_OBJECT (this), "node-state");
|
||||||
|
|
||||||
if (sc->state == SPA_NODE_STATE_CONFIGURE) {
|
if (sc->state == SPA_NODE_STATE_CONFIGURE) {
|
||||||
update_port_ids (this, FALSE);
|
update_port_ids (this, FALSE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
switch (sc->state) {
|
switch (sc->state) {
|
||||||
case SPA_NODE_STATE_CONFIGURE:
|
case SPA_NODE_STATE_CONFIGURE:
|
||||||
{
|
{
|
||||||
|
|
@ -315,23 +375,38 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
||||||
case SPA_EVENT_TYPE_ADD_POLL:
|
case SPA_EVENT_TYPE_ADD_POLL:
|
||||||
{
|
{
|
||||||
SpaPollItem *poll = event->data;
|
SpaPollItem *poll = event->data;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
g_debug ("node %p: add poll %d", this, poll->n_fds);
|
g_debug ("node %p: add poll %d", this, poll->n_fds);
|
||||||
priv->poll = *poll;
|
priv->poll[priv->n_poll] = *poll;
|
||||||
priv->poll.fds = &priv->fds[priv->n_fds];
|
priv->n_poll++;
|
||||||
for (i = 0; i < poll->n_fds; i++)
|
if (poll->n_fds)
|
||||||
priv->fds[priv->n_fds++] = poll->fds[i];
|
priv->rebuild_fds = true;
|
||||||
|
wakeup_thread (this);
|
||||||
|
|
||||||
start_thread (this);
|
start_thread (this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPA_EVENT_TYPE_UPDATE_POLL:
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
SpaPollItem *poll = event->data;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->n_poll; i++) {
|
||||||
|
if (priv->poll[i].id == poll->id)
|
||||||
|
priv->poll[i] = *poll;
|
||||||
|
}
|
||||||
|
if (poll->n_fds)
|
||||||
|
priv->rebuild_fds = true;
|
||||||
|
wakeup_thread (this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPA_EVENT_TYPE_REMOVE_POLL:
|
case SPA_EVENT_TYPE_REMOVE_POLL:
|
||||||
{
|
{
|
||||||
SpaPollItem *poll = event->data;
|
SpaPollItem *poll = event->data;
|
||||||
|
|
||||||
g_debug ("node %p: remove poll %d", this, poll->n_fds);
|
g_debug ("node %p: remove poll %d", this, poll->n_fds);
|
||||||
priv->n_fds -= poll->n_fds;
|
priv->rebuild_fds = true;
|
||||||
|
wakeup_thread (this);
|
||||||
|
|
||||||
stop_thread (this);
|
stop_thread (this);
|
||||||
break;
|
break;
|
||||||
|
|
@ -433,7 +508,7 @@ pinos_node_get_property (GObject *_object,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_NODE_STATE:
|
case PROP_NODE_STATE:
|
||||||
g_value_set_uint (value, node->node_state);
|
g_value_set_uint (value, node->node->state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ struct _PinosNode {
|
||||||
GObject object;
|
GObject object;
|
||||||
|
|
||||||
SpaNode *node;
|
SpaNode *node;
|
||||||
SpaNodeState node_state;
|
|
||||||
|
|
||||||
PinosNodePrivate *priv;
|
PinosNodePrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ typedef struct _SpaEvent SpaEvent;
|
||||||
* @SPA_EVENT_TYPE_NEED_INPUT: emited when more data can be pushed to an async node
|
* @SPA_EVENT_TYPE_NEED_INPUT: emited when more data can be pushed to an async node
|
||||||
* @SPA_EVENT_TYPE_REUSE_BUFFER: emited when a buffer can be reused
|
* @SPA_EVENT_TYPE_REUSE_BUFFER: emited when a buffer can be reused
|
||||||
* @SPA_EVENT_TYPE_ADD_POLL: emited when a pollfd should be added. data points to #SpaPollItem
|
* @SPA_EVENT_TYPE_ADD_POLL: emited when a pollfd should be added. data points to #SpaPollItem
|
||||||
|
* @SPA_EVENT_TYPE_UPDATE_POLL: update the pollfd item
|
||||||
* @SPA_EVENT_TYPE_REMOVE_POLL: emited when a pollfd should be removed. data points to #SpaPollItem
|
* @SPA_EVENT_TYPE_REMOVE_POLL: emited when a pollfd should be removed. data points to #SpaPollItem
|
||||||
* @SPA_EVENT_TYPE_DRAINED: emited when DRAIN command completed
|
* @SPA_EVENT_TYPE_DRAINED: emited when DRAIN command completed
|
||||||
* @SPA_EVENT_TYPE_MARKER: emited when MARK command completed
|
* @SPA_EVENT_TYPE_MARKER: emited when MARK command completed
|
||||||
|
|
@ -56,6 +57,7 @@ typedef enum {
|
||||||
SPA_EVENT_TYPE_NEED_INPUT,
|
SPA_EVENT_TYPE_NEED_INPUT,
|
||||||
SPA_EVENT_TYPE_REUSE_BUFFER,
|
SPA_EVENT_TYPE_REUSE_BUFFER,
|
||||||
SPA_EVENT_TYPE_ADD_POLL,
|
SPA_EVENT_TYPE_ADD_POLL,
|
||||||
|
SPA_EVENT_TYPE_UPDATE_POLL,
|
||||||
SPA_EVENT_TYPE_REMOVE_POLL,
|
SPA_EVENT_TYPE_REMOVE_POLL,
|
||||||
SPA_EVENT_TYPE_DRAINED,
|
SPA_EVENT_TYPE_DRAINED,
|
||||||
SPA_EVENT_TYPE_MARKER,
|
SPA_EVENT_TYPE_MARKER,
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,12 @@ struct _SpaNode {
|
||||||
/* the total size of this node. This can be used to expand this
|
/* the total size of this node. This can be used to expand this
|
||||||
* structure in the future */
|
* structure in the future */
|
||||||
size_t size;
|
size_t size;
|
||||||
|
/**
|
||||||
|
* SpaNode::state:
|
||||||
|
*
|
||||||
|
* The current state of the node
|
||||||
|
*/
|
||||||
|
SpaNodeState state;
|
||||||
/**
|
/**
|
||||||
* SpaNode::get_props:
|
* SpaNode::get_props:
|
||||||
* @node: a #SpaNode
|
* @node: a #SpaNode
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct _SpaEvent SpaEvent;
|
|
||||||
|
|
||||||
#include <spa/defs.h>
|
#include <spa/defs.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,6 +61,7 @@ typedef int (*SpaPollNotify) (SpaPollNotifyData *data);
|
||||||
/**
|
/**
|
||||||
* SpaPollItem:
|
* SpaPollItem:
|
||||||
* @id: id of the poll item
|
* @id: id of the poll item
|
||||||
|
* @enabled: if the item is enabled
|
||||||
* @fds: array of file descriptors to watch
|
* @fds: array of file descriptors to watch
|
||||||
* @n_fds: number of elements in @fds
|
* @n_fds: number of elements in @fds
|
||||||
* @idle_cb: callback called when there is no other work
|
* @idle_cb: callback called when there is no other work
|
||||||
|
|
@ -72,6 +71,7 @@ typedef int (*SpaPollNotify) (SpaPollNotifyData *data);
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
bool enabled;
|
||||||
SpaPollFd *fds;
|
SpaPollFd *fds;
|
||||||
unsigned int n_fds;
|
unsigned int n_fds;
|
||||||
SpaPollNotify idle_cb;
|
SpaPollNotify idle_cb;
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ spa_alsa_sink_node_get_port_ids (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_input_ports > 0)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -634,6 +634,7 @@ spa_alsa_sink_node_port_pull_output (SpaNode *node,
|
||||||
static const SpaNode alsasink_node = {
|
static const SpaNode alsasink_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_alsa_sink_node_get_props,
|
spa_alsa_sink_node_get_props,
|
||||||
spa_alsa_sink_node_set_props,
|
spa_alsa_sink_node_set_props,
|
||||||
spa_alsa_sink_node_send_command,
|
spa_alsa_sink_node_send_command,
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,8 @@ spa_alsa_start (SpaALSASink *this)
|
||||||
event.data = &state->poll;
|
event.data = &state->poll;
|
||||||
event.size = sizeof (state->poll);
|
event.size = sizeof (state->poll);
|
||||||
|
|
||||||
|
state->poll.id = 0;
|
||||||
|
state->poll.enabled = true;
|
||||||
state->poll.fds = state->fds;
|
state->poll.fds = state->fds;
|
||||||
state->poll.idle_cb = NULL;
|
state->poll.idle_cb = NULL;
|
||||||
state->poll.before_cb = NULL;
|
state->poll.before_cb = NULL;
|
||||||
|
|
|
||||||
|
|
@ -725,6 +725,7 @@ spa_audiomixer_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode audiomixer_node = {
|
static const SpaNode audiomixer_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_audiomixer_node_get_props,
|
spa_audiomixer_node_get_props,
|
||||||
spa_audiomixer_node_set_props,
|
spa_audiomixer_node_set_props,
|
||||||
spa_audiomixer_node_send_command,
|
spa_audiomixer_node_send_command,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <spa/node.h>
|
#include <spa/node.h>
|
||||||
#include <spa/audio/format.h>
|
#include <spa/audio/format.h>
|
||||||
|
|
@ -32,6 +33,20 @@ typedef struct {
|
||||||
double volume;
|
double volume;
|
||||||
} SpaAudioTestSrcProps;
|
} SpaAudioTestSrcProps;
|
||||||
|
|
||||||
|
typedef struct _ATSBuffer ATSBuffer;
|
||||||
|
|
||||||
|
struct _ATSBuffer {
|
||||||
|
SpaBuffer buffer;
|
||||||
|
SpaMeta metas[1];
|
||||||
|
SpaMetaHeader header;
|
||||||
|
SpaData datas[1];
|
||||||
|
SpaBuffer *outbuf;
|
||||||
|
bool outstanding;
|
||||||
|
ATSBuffer *next;
|
||||||
|
void *ptr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
struct _SpaAudioTestSrc {
|
struct _SpaAudioTestSrc {
|
||||||
SpaHandle handle;
|
SpaHandle handle;
|
||||||
SpaNode node;
|
SpaNode node;
|
||||||
|
|
@ -41,12 +56,27 @@ struct _SpaAudioTestSrc {
|
||||||
SpaEventCallback event_cb;
|
SpaEventCallback event_cb;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
|
SpaPollItem idle;
|
||||||
|
|
||||||
SpaPortInfo info;
|
SpaPortInfo info;
|
||||||
|
SpaAllocParam *params[1];
|
||||||
|
SpaAllocParamBuffers param_buffers;
|
||||||
SpaPortStatus status;
|
SpaPortStatus status;
|
||||||
|
|
||||||
bool have_format;
|
bool have_format;
|
||||||
SpaFormatAudio query_format;
|
SpaFormatAudio query_format;
|
||||||
SpaFormatAudio current_format;
|
SpaFormatAudio current_format;
|
||||||
|
|
||||||
|
SpaMemory *alloc_mem;
|
||||||
|
ATSBuffer *alloc_buffers;
|
||||||
|
|
||||||
|
bool have_buffers;
|
||||||
|
SpaBuffer **buffers;
|
||||||
|
unsigned int n_buffers;
|
||||||
|
|
||||||
|
ATSBuffer *empty;
|
||||||
|
ATSBuffer *ready;
|
||||||
|
unsigned int ready_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t default_wave = 1.0;
|
static const uint32_t default_wave = 1.0;
|
||||||
|
|
@ -152,6 +182,58 @@ spa_audiotestsrc_node_set_props (SpaNode *node,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SpaResult
|
||||||
|
send_have_output (SpaAudioTestSrc *this)
|
||||||
|
{
|
||||||
|
SpaEvent event;
|
||||||
|
SpaEventHaveOutput ho;
|
||||||
|
|
||||||
|
if (this->event_cb) {
|
||||||
|
event.type = SPA_EVENT_TYPE_HAVE_OUTPUT;
|
||||||
|
event.size = sizeof (ho);
|
||||||
|
event.data = &ho;
|
||||||
|
ho.port_id = 0;
|
||||||
|
this->event_cb (&this->node, &event, this->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_state (SpaAudioTestSrc *this, SpaNodeState state)
|
||||||
|
{
|
||||||
|
SpaEvent event;
|
||||||
|
SpaEventStateChange sc;
|
||||||
|
|
||||||
|
if (this->node.state == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->node.state = state;
|
||||||
|
|
||||||
|
if (this->event_cb) {
|
||||||
|
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
||||||
|
event.data = ≻
|
||||||
|
event.size = sizeof (sc);
|
||||||
|
sc.state = state;
|
||||||
|
this->event_cb (&this->node, &event, this->user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SpaResult
|
||||||
|
update_idle_enabled (SpaAudioTestSrc *this, bool enabled)
|
||||||
|
{
|
||||||
|
SpaEvent event;
|
||||||
|
|
||||||
|
if (this->event_cb) {
|
||||||
|
this->idle.enabled = enabled;
|
||||||
|
event.type = SPA_EVENT_TYPE_UPDATE_POLL;
|
||||||
|
event.data = &this->idle;
|
||||||
|
event.size = sizeof (this->idle);
|
||||||
|
this->event_cb (&this->node, &event, this->user_data);
|
||||||
|
}
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_audiotestsrc_node_send_command (SpaNode *node,
|
spa_audiotestsrc_node_send_command (SpaNode *node,
|
||||||
SpaCommand *command)
|
SpaCommand *command)
|
||||||
|
|
@ -168,33 +250,31 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
|
||||||
return SPA_RESULT_INVALID_COMMAND;
|
return SPA_RESULT_INVALID_COMMAND;
|
||||||
|
|
||||||
case SPA_COMMAND_START:
|
case SPA_COMMAND_START:
|
||||||
if (this->event_cb) {
|
{
|
||||||
SpaEvent event;
|
if (!this->have_format)
|
||||||
SpaEventStateChange sc;
|
return SPA_RESULT_NO_FORMAT;
|
||||||
|
|
||||||
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
if (!this->have_buffers)
|
||||||
event.data = ≻
|
return SPA_RESULT_NO_BUFFERS;
|
||||||
event.size = sizeof (sc);
|
|
||||||
sc.state = SPA_NODE_STATE_STREAMING;
|
|
||||||
|
|
||||||
this->event_cb (node, &event, this->user_data);
|
update_idle_enabled (this, true);
|
||||||
}
|
|
||||||
|
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPA_COMMAND_PAUSE:
|
case SPA_COMMAND_PAUSE:
|
||||||
if (this->event_cb) {
|
{
|
||||||
SpaEvent event;
|
if (!this->have_format)
|
||||||
SpaEventStateChange sc;
|
return SPA_RESULT_NO_FORMAT;
|
||||||
|
|
||||||
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
if (!this->have_buffers)
|
||||||
event.data = ≻
|
return SPA_RESULT_NO_BUFFERS;
|
||||||
event.size = sizeof (sc);
|
|
||||||
sc.state = SPA_NODE_STATE_PAUSED;
|
|
||||||
|
|
||||||
this->event_cb (node, &event, this->user_data);
|
update_idle_enabled (this, false);
|
||||||
}
|
|
||||||
|
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPA_COMMAND_FLUSH:
|
case SPA_COMMAND_FLUSH:
|
||||||
case SPA_COMMAND_DRAIN:
|
case SPA_COMMAND_DRAIN:
|
||||||
case SPA_COMMAND_MARKER:
|
case SPA_COMMAND_MARKER:
|
||||||
|
|
@ -205,19 +285,33 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_audiotestsrc_node_set_event_callback (SpaNode *node,
|
spa_audiotestsrc_node_set_event_callback (SpaNode *node,
|
||||||
SpaEventCallback event,
|
SpaEventCallback event_cb,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
SpaAudioTestSrc *this;
|
SpaAudioTestSrc *this;
|
||||||
|
SpaEvent event;
|
||||||
|
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = (SpaAudioTestSrc *) node->handle;
|
this = (SpaAudioTestSrc *) node->handle;
|
||||||
|
|
||||||
this->event_cb = event;
|
if (event_cb == NULL && this->event_cb) {
|
||||||
|
event.type = SPA_EVENT_TYPE_REMOVE_POLL;
|
||||||
|
event.data = &this->idle;
|
||||||
|
event.size = sizeof (this->idle);
|
||||||
|
this->event_cb (&this->node, &event, this->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->event_cb = event_cb;
|
||||||
this->user_data = user_data;
|
this->user_data = user_data;
|
||||||
|
|
||||||
|
if (this->event_cb) {
|
||||||
|
event.type = SPA_EVENT_TYPE_ADD_POLL;
|
||||||
|
event.data = &this->idle;
|
||||||
|
event.size = sizeof (this->idle);
|
||||||
|
this->event_cb (&this->node, &event, this->user_data);
|
||||||
|
}
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,10 +344,10 @@ spa_audiotestsrc_node_get_port_ids (SpaNode *node,
|
||||||
unsigned int n_output_ports,
|
unsigned int n_output_ports,
|
||||||
uint32_t *output_ids)
|
uint32_t *output_ids)
|
||||||
{
|
{
|
||||||
if (node == NULL || node->handle == NULL || input_ids == NULL || output_ids == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 0;
|
output_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -295,6 +389,9 @@ spa_audiotestsrc_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (filter)
|
||||||
|
spa_format_audio_parse (filter, &this->query_format);
|
||||||
|
else
|
||||||
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO,
|
||||||
SPA_MEDIA_SUBTYPE_RAW,
|
SPA_MEDIA_SUBTYPE_RAW,
|
||||||
&this->query_format);
|
&this->query_format);
|
||||||
|
|
@ -327,13 +424,34 @@ spa_audiotestsrc_node_port_set_format (SpaNode *node,
|
||||||
|
|
||||||
if (format == NULL) {
|
if (format == NULL) {
|
||||||
this->have_format = false;
|
this->have_format = false;
|
||||||
return SPA_RESULT_OK;
|
this->have_buffers = false;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if ((res = spa_format_audio_parse (format, &this->current_format)) < 0)
|
if ((res = spa_format_audio_parse (format, &this->current_format)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
this->have_format = true;
|
this->have_format = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->have_format) {
|
||||||
|
this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
|
||||||
|
this->info.maxbuffering = -1;
|
||||||
|
this->info.latency = -1;
|
||||||
|
|
||||||
|
this->info.n_params = 1;
|
||||||
|
this->info.params = this->params;
|
||||||
|
this->params[0] = &this->param_buffers.param;
|
||||||
|
this->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS;
|
||||||
|
this->param_buffers.param.size = sizeof (this->param_buffers);
|
||||||
|
this->param_buffers.minsize = 1024;
|
||||||
|
this->param_buffers.stride = 1024;
|
||||||
|
this->param_buffers.min_buffers = 2;
|
||||||
|
this->param_buffers.max_buffers = 32;
|
||||||
|
this->param_buffers.align = 16;
|
||||||
|
this->info.features = NULL;
|
||||||
|
update_state (this, SPA_NODE_STATE_READY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -403,7 +521,74 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
|
||||||
SpaBuffer **buffers,
|
SpaBuffer **buffers,
|
||||||
uint32_t n_buffers)
|
uint32_t n_buffers)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
SpaAudioTestSrc *this;
|
||||||
|
|
||||||
|
if (node == NULL || node->handle == NULL)
|
||||||
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
this = (SpaAudioTestSrc *) node->handle;
|
||||||
|
|
||||||
|
if (port_id != 0)
|
||||||
|
return SPA_RESULT_INVALID_PORT;
|
||||||
|
|
||||||
|
if (!this->have_format)
|
||||||
|
return SPA_RESULT_NO_FORMAT;
|
||||||
|
|
||||||
|
if (this->have_buffers) {
|
||||||
|
if (this->alloc_mem)
|
||||||
|
spa_memory_unref (&this->alloc_mem->mem);
|
||||||
|
this->alloc_mem = NULL;
|
||||||
|
this->buffers = NULL;
|
||||||
|
this->n_buffers = 0;
|
||||||
|
this->have_buffers = false;
|
||||||
|
}
|
||||||
|
if (buffers != NULL && n_buffers != 0) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
this->alloc_mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL,
|
||||||
|
NULL,
|
||||||
|
sizeof (ATSBuffer) * n_buffers);
|
||||||
|
this->alloc_buffers = spa_memory_ensure_ptr (this->alloc_mem);
|
||||||
|
|
||||||
|
for (i = 0; i < n_buffers; i++) {
|
||||||
|
ATSBuffer *b;
|
||||||
|
SpaMemoryRef *mem_ref;
|
||||||
|
SpaMemory *mem;
|
||||||
|
SpaData *d = SPA_BUFFER_DATAS (buffers[i]);
|
||||||
|
|
||||||
|
b = &this->alloc_buffers[i];
|
||||||
|
if (i + 1 == n_buffers)
|
||||||
|
b->next = NULL;
|
||||||
|
else
|
||||||
|
b->next = &this->alloc_buffers[i + 1];
|
||||||
|
|
||||||
|
b->buffer.mem.mem = this->alloc_mem->mem;
|
||||||
|
b->buffer.mem.offset = sizeof (ATSBuffer) * i;
|
||||||
|
b->buffer.mem.size = sizeof (ATSBuffer);
|
||||||
|
b->buffer.id = SPA_ID_INVALID;
|
||||||
|
b->outbuf = buffers[i];
|
||||||
|
b->outstanding = true;
|
||||||
|
|
||||||
|
mem_ref = &d[0].mem.mem;
|
||||||
|
if (!(mem = spa_memory_find (mem_ref))) {
|
||||||
|
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
b->ptr = SPA_MEMBER (spa_memory_ensure_ptr (mem), d[0].mem.offset, void);
|
||||||
|
b->size = d[0].mem.size;
|
||||||
|
}
|
||||||
|
this->buffers = buffers;
|
||||||
|
this->n_buffers = n_buffers;
|
||||||
|
this->have_buffers = true;
|
||||||
|
this->empty = this->alloc_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->have_buffers)
|
||||||
|
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||||
|
else
|
||||||
|
update_state (this, SPA_NODE_STATE_READY);
|
||||||
|
|
||||||
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -422,7 +607,35 @@ spa_audiotestsrc_node_port_reuse_buffer (SpaNode *node,
|
||||||
uint32_t port_id,
|
uint32_t port_id,
|
||||||
uint32_t buffer_id)
|
uint32_t buffer_id)
|
||||||
{
|
{
|
||||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
SpaAudioTestSrc *this;
|
||||||
|
ATSBuffer *b;
|
||||||
|
|
||||||
|
if (node == NULL || node->handle == NULL)
|
||||||
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
this = (SpaAudioTestSrc *) node->handle;
|
||||||
|
|
||||||
|
if (port_id != 0)
|
||||||
|
return SPA_RESULT_INVALID_PORT;
|
||||||
|
|
||||||
|
if (!this->have_buffers)
|
||||||
|
return SPA_RESULT_NO_BUFFERS;
|
||||||
|
|
||||||
|
if (buffer_id >= this->n_buffers)
|
||||||
|
return SPA_RESULT_INVALID_BUFFER_ID;
|
||||||
|
|
||||||
|
b = &this->alloc_buffers[buffer_id];
|
||||||
|
if (!b->outstanding)
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
|
||||||
|
b->outstanding = false;
|
||||||
|
b->next = this->empty;
|
||||||
|
this->empty = b;
|
||||||
|
|
||||||
|
if (b->next == NULL)
|
||||||
|
update_idle_enabled (this, true);
|
||||||
|
|
||||||
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
@ -457,14 +670,48 @@ spa_audiotestsrc_node_port_push_input (SpaNode *node,
|
||||||
return SPA_RESULT_INVALID_PORT;
|
return SPA_RESULT_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SpaResult
|
||||||
|
fill_buffer (SpaAudioTestSrc *this, ATSBuffer *b)
|
||||||
|
{
|
||||||
|
uint8_t *p = b->ptr;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < b->size; i++) {
|
||||||
|
p[i] = rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
audiotestsrc_idle (SpaPollNotifyData *data)
|
||||||
|
{
|
||||||
|
SpaAudioTestSrc *this = data->user_data;
|
||||||
|
ATSBuffer *empty;
|
||||||
|
|
||||||
|
empty = this->empty;
|
||||||
|
if (!empty) {
|
||||||
|
update_idle_enabled (this, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_buffer (this, empty);
|
||||||
|
|
||||||
|
this->empty = empty->next;
|
||||||
|
empty->next = this->ready;
|
||||||
|
this->ready = empty;
|
||||||
|
this->ready_count++;
|
||||||
|
send_have_output (this);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
||||||
unsigned int n_info,
|
unsigned int n_info,
|
||||||
SpaOutputInfo *info)
|
SpaOutputInfo *info)
|
||||||
{
|
{
|
||||||
SpaAudioTestSrc *this;
|
SpaAudioTestSrc *this;
|
||||||
size_t j, size;
|
|
||||||
uint8_t *ptr = NULL;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool have_error = false;
|
bool have_error = false;
|
||||||
|
|
||||||
|
|
@ -474,6 +721,8 @@ spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
||||||
this = (SpaAudioTestSrc *) node->handle;
|
this = (SpaAudioTestSrc *) node->handle;
|
||||||
|
|
||||||
for (i = 0; i < n_info; i++) {
|
for (i = 0; i < n_info; i++) {
|
||||||
|
ATSBuffer *b;
|
||||||
|
|
||||||
if (info[i].port_id != 0) {
|
if (info[i].port_id != 0) {
|
||||||
info[i].status = SPA_RESULT_INVALID_PORT;
|
info[i].status = SPA_RESULT_INVALID_PORT;
|
||||||
have_error = true;
|
have_error = true;
|
||||||
|
|
@ -485,12 +734,18 @@ spa_audiotestsrc_node_port_pull_output (SpaNode *node,
|
||||||
have_error = true;
|
have_error = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (this->ready_count == 0) {
|
||||||
|
info[i].status = SPA_RESULT_UNEXPECTED;
|
||||||
|
have_error = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
size = 0;
|
b = this->ready;
|
||||||
|
this->ready = b->next;
|
||||||
for (j = 0; j < size; j++)
|
this->ready_count--;
|
||||||
ptr[j] = rand();
|
b->outstanding = true;
|
||||||
|
|
||||||
|
info[i].buffer_id = b->outbuf->id;
|
||||||
info[i].status = SPA_RESULT_OK;
|
info[i].status = SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
if (have_error)
|
if (have_error)
|
||||||
|
|
@ -510,6 +765,7 @@ spa_audiotestsrc_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode audiotestsrc_node = {
|
static const SpaNode audiotestsrc_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_audiotestsrc_node_get_props,
|
spa_audiotestsrc_node_get_props,
|
||||||
spa_audiotestsrc_node_set_props,
|
spa_audiotestsrc_node_set_props,
|
||||||
spa_audiotestsrc_node_send_command,
|
spa_audiotestsrc_node_send_command,
|
||||||
|
|
@ -580,9 +836,20 @@ audiotestsrc_init (const SpaHandleFactory *factory,
|
||||||
this->props[1].props.prop_info = prop_info;
|
this->props[1].props.prop_info = prop_info;
|
||||||
reset_audiotestsrc_props (&this->props[1]);
|
reset_audiotestsrc_props (&this->props[1]);
|
||||||
|
|
||||||
|
this->idle.id = 0;
|
||||||
|
this->idle.enabled = false;
|
||||||
|
this->idle.fds = NULL;
|
||||||
|
this->idle.n_fds = 0;
|
||||||
|
this->idle.idle_cb = audiotestsrc_idle;
|
||||||
|
this->idle.before_cb = NULL;
|
||||||
|
this->idle.after_cb = NULL;
|
||||||
|
this->idle.user_data = this;
|
||||||
|
|
||||||
this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
|
this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
|
||||||
SPA_PORT_INFO_FLAG_NO_REF;
|
SPA_PORT_INFO_FLAG_NO_REF;
|
||||||
this->status.flags = SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
|
this->status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
||||||
|
|
||||||
|
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,9 +227,9 @@ spa_ffmpeg_dec_node_get_port_ids (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_input_ports > 0)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 1;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -502,6 +502,7 @@ spa_ffmpeg_dec_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode ffmpeg_dec_node = {
|
static const SpaNode ffmpeg_dec_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_ffmpeg_dec_node_get_props,
|
spa_ffmpeg_dec_node_get_props,
|
||||||
spa_ffmpeg_dec_node_set_props,
|
spa_ffmpeg_dec_node_set_props,
|
||||||
spa_ffmpeg_dec_node_send_command,
|
spa_ffmpeg_dec_node_send_command,
|
||||||
|
|
|
||||||
|
|
@ -227,9 +227,9 @@ spa_ffmpeg_enc_node_get_port_ids (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_input_ports > 0)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 1;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -505,6 +505,7 @@ spa_ffmpeg_enc_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode ffmpeg_enc_node = {
|
static const SpaNode ffmpeg_enc_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_ffmpeg_enc_node_get_props,
|
spa_ffmpeg_enc_node_get_props,
|
||||||
spa_ffmpeg_enc_node_set_props,
|
spa_ffmpeg_enc_node_set_props,
|
||||||
spa_ffmpeg_enc_node_send_command,
|
spa_ffmpeg_enc_node_send_command,
|
||||||
|
|
@ -570,5 +571,7 @@ spa_ffmpeg_enc_init (SpaHandle *handle)
|
||||||
this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
this->state[OUTPUT_PORT_ID].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
this->state[OUTPUT_PORT_ID].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
||||||
|
|
||||||
|
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -219,9 +219,9 @@ spa_libva_dec_node_get_port_ids (SpaHandle *handle,
|
||||||
if (handle == NULL)
|
if (handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_input_ports > 0)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 1;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
|
|
@ -219,9 +219,9 @@ spa_libva_enc_node_get_port_ids (SpaHandle *handle,
|
||||||
if (handle == NULL)
|
if (handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_input_ports > 0)
|
if (n_input_ports > 0 && input_ids != NULL)
|
||||||
input_ids[0] = 0;
|
input_ids[0] = 0;
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 1;
|
output_ids[0] = 1;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ typedef struct {
|
||||||
struct _SpaProxy {
|
struct _SpaProxy {
|
||||||
SpaHandle handle;
|
SpaHandle handle;
|
||||||
SpaNode node;
|
SpaNode node;
|
||||||
SpaNodeState state;
|
|
||||||
|
|
||||||
SpaProxyProps props[2];
|
SpaProxyProps props[2];
|
||||||
|
|
||||||
|
|
@ -130,11 +129,11 @@ update_poll (SpaProxy *this, int socketfd)
|
||||||
static SpaResult
|
static SpaResult
|
||||||
update_state (SpaProxy *this, SpaNodeState state)
|
update_state (SpaProxy *this, SpaNodeState state)
|
||||||
{
|
{
|
||||||
if (this->state != state) {
|
if (this->node.state != state) {
|
||||||
SpaEvent event;
|
SpaEvent event;
|
||||||
SpaEventStateChange sc;
|
SpaEventStateChange sc;
|
||||||
|
|
||||||
this->state = state;
|
this->node.state = state;
|
||||||
|
|
||||||
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
||||||
event.data = ≻
|
event.data = ≻
|
||||||
|
|
@ -1077,6 +1076,7 @@ proxy_on_fd_events (SpaPollNotifyData *data)
|
||||||
static const SpaNode proxy_node = {
|
static const SpaNode proxy_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_proxy_node_get_props,
|
spa_proxy_node_get_props,
|
||||||
spa_proxy_node_set_props,
|
spa_proxy_node_set_props,
|
||||||
spa_proxy_node_send_command,
|
spa_proxy_node_send_command,
|
||||||
|
|
@ -1151,6 +1151,7 @@ proxy_init (const SpaHandleFactory *factory,
|
||||||
this->fds[0].events = POLLIN | POLLPRI | POLLERR;
|
this->fds[0].events = POLLIN | POLLPRI | POLLERR;
|
||||||
this->fds[0].revents = 0;
|
this->fds[0].revents = 0;
|
||||||
this->poll.id = 0;
|
this->poll.id = 0;
|
||||||
|
this->poll.enabled = true;
|
||||||
this->poll.fds = this->fds;
|
this->poll.fds = this->fds;
|
||||||
this->poll.n_fds = 1;
|
this->poll.n_fds = 1;
|
||||||
this->poll.idle_cb = NULL;
|
this->poll.idle_cb = NULL;
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,6 @@ typedef struct {
|
||||||
struct _SpaV4l2Source {
|
struct _SpaV4l2Source {
|
||||||
SpaHandle handle;
|
SpaHandle handle;
|
||||||
SpaNode node;
|
SpaNode node;
|
||||||
SpaNodeState node_state;
|
|
||||||
|
|
||||||
SpaV4l2SourceProps props[2];
|
SpaV4l2SourceProps props[2];
|
||||||
|
|
||||||
|
|
@ -208,10 +207,10 @@ update_state (SpaV4l2Source *this, SpaNodeState state)
|
||||||
SpaEvent event;
|
SpaEvent event;
|
||||||
SpaEventStateChange sc;
|
SpaEventStateChange sc;
|
||||||
|
|
||||||
if (this->node_state == state)
|
if (this->node.state == state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this->node_state = state;
|
this->node.state = state;
|
||||||
|
|
||||||
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
|
||||||
event.data = ≻
|
event.data = ≻
|
||||||
|
|
@ -329,7 +328,7 @@ spa_v4l2_source_node_get_port_ids (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 0;
|
output_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -718,6 +717,7 @@ spa_v4l2_source_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode v4l2source_node = {
|
static const SpaNode v4l2source_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_v4l2_source_node_get_props,
|
spa_v4l2_source_node_get_props,
|
||||||
spa_v4l2_source_node_set_props,
|
spa_v4l2_source_node_set_props,
|
||||||
spa_v4l2_source_node_send_command,
|
spa_v4l2_source_node_send_command,
|
||||||
|
|
@ -793,8 +793,6 @@ v4l2_source_init (const SpaHandleFactory *factory,
|
||||||
|
|
||||||
this->state[0].export_buf = true;
|
this->state[0].export_buf = true;
|
||||||
|
|
||||||
this->node_state = SPA_NODE_STATE_INIT;
|
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -625,7 +625,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
|
||||||
|
|
||||||
if (state->alloc_mem)
|
if (state->alloc_mem)
|
||||||
spa_memory_unref (&state->alloc_mem->mem);
|
spa_memory_unref (&state->alloc_mem->mem);
|
||||||
state->alloc_mem = spa_memory_alloc_with_fd (SPA_MEMORY_POOL_SHARED,
|
state->alloc_mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL,
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (V4l2Buffer) * reqbuf.count);
|
sizeof (V4l2Buffer) * reqbuf.count);
|
||||||
state->alloc_buffers = spa_memory_ensure_ptr (state->alloc_mem);
|
state->alloc_buffers = spa_memory_ensure_ptr (state->alloc_mem);
|
||||||
|
|
@ -646,7 +646,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
|
||||||
|
|
||||||
fprintf (stderr, "import buffer %p\n", buffers[i]);
|
fprintf (stderr, "import buffer %p\n", buffers[i]);
|
||||||
|
|
||||||
mem_ref = &SPA_BUFFER_DATAS (buffers[i])[0].mem.mem;
|
mem_ref = &d[0].mem.mem;
|
||||||
if (!(mem = spa_memory_find (mem_ref))) {
|
if (!(mem = spa_memory_find (mem_ref))) {
|
||||||
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
|
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -656,7 +656,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
|
||||||
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
b->v4l2_buffer.memory = state->memtype;
|
b->v4l2_buffer.memory = state->memtype;
|
||||||
b->v4l2_buffer.index = i;
|
b->v4l2_buffer.index = i;
|
||||||
b->v4l2_buffer.m.userptr = (unsigned long) ((uint8_t*)mem->ptr + d[0].mem.offset);
|
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (mem->ptr, d[0].mem.offset, void *);
|
||||||
b->v4l2_buffer.length = d[0].mem.size;
|
b->v4l2_buffer.length = d[0].mem.size;
|
||||||
|
|
||||||
spa_v4l2_buffer_recycle (this, buffers[i]->id);
|
spa_v4l2_buffer_recycle (this, buffers[i]->id);
|
||||||
|
|
@ -869,6 +869,7 @@ spa_v4l2_start (SpaV4l2Source *this)
|
||||||
state->fds[0].revents = 0;
|
state->fds[0].revents = 0;
|
||||||
|
|
||||||
state->poll.id = 0;
|
state->poll.id = 0;
|
||||||
|
state->poll.enabled = true;
|
||||||
state->poll.fds = state->fds;
|
state->poll.fds = state->fds;
|
||||||
state->poll.n_fds = 1;
|
state->poll.n_fds = 1;
|
||||||
state->poll.idle_cb = NULL;
|
state->poll.idle_cb = NULL;
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,7 @@ spa_volume_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode volume_node = {
|
static const SpaNode volume_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_volume_node_get_props,
|
spa_volume_node_get_props,
|
||||||
spa_volume_node_set_props,
|
spa_volume_node_set_props,
|
||||||
spa_volume_node_send_command,
|
spa_volume_node_send_command,
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ spa_xv_sink_node_get_port_ids (SpaNode *node,
|
||||||
if (node == NULL || node->handle == NULL)
|
if (node == NULL || node->handle == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
if (n_output_ports > 0)
|
if (n_output_ports > 0 && output_ids != NULL)
|
||||||
output_ids[0] = 0;
|
output_ids[0] = 0;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
@ -500,6 +500,7 @@ spa_xv_sink_node_port_push_event (SpaNode *node,
|
||||||
static const SpaNode xvsink_node = {
|
static const SpaNode xvsink_node = {
|
||||||
NULL,
|
NULL,
|
||||||
sizeof (SpaNode),
|
sizeof (SpaNode),
|
||||||
|
SPA_NODE_STATE_INIT,
|
||||||
spa_xv_sink_node_get_props,
|
spa_xv_sink_node_get_props,
|
||||||
spa_xv_sink_node_set_props,
|
spa_xv_sink_node_set_props,
|
||||||
spa_xv_sink_node_send_command,
|
spa_xv_sink_node_send_command,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue