mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-09-20 00:11:31 +00:00
Add more generic export-spa example
Replace the v4l2 example with a more generic version that can add any spa node to a remote graph Make the dictionary items const Add some info to nodes and factories. Add the node info to the node properties. We can then set the media.class directly on the node, instead of letting the monitor set it. Debug node info in spa-inspect. Do async operation on the audiotestsrc and videotestsrc differently.
This commit is contained in:
parent
21cd5a2918
commit
dc85a79786
|
@ -38,7 +38,7 @@ struct spa_dict_item {
|
|||
|
||||
struct spa_dict {
|
||||
uint32_t n_items;
|
||||
struct spa_dict_item *items;
|
||||
const struct spa_dict_item *items;
|
||||
};
|
||||
|
||||
#define SPA_DICT_INIT(n_items,items) { n_items, items }
|
||||
|
@ -48,10 +48,10 @@ struct spa_dict {
|
|||
(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 const struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict,
|
||||
const char *key)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
const struct spa_dict_item *item;
|
||||
spa_dict_for_each(item, dict) {
|
||||
if (!strcmp(item->key, key))
|
||||
return item;
|
||||
|
@ -61,7 +61,7 @@ static inline struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *
|
|||
|
||||
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);
|
||||
const struct spa_dict_item *item = spa_dict_lookup_item(dict, key);
|
||||
return item ? item->value : NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0)
|
||||
|
||||
static const char default_device[] = "hw:0";
|
||||
static const uint32_t default_min_latency = 64;
|
||||
static const uint32_t default_min_latency = 128;
|
||||
|
||||
static void reset_props(struct props *props)
|
||||
{
|
||||
|
@ -446,7 +446,7 @@ impl_node_port_use_buffers(struct spa_node *node,
|
|||
|
||||
for (i = 0; i < n_buffers; i++) {
|
||||
struct buffer *b = &this->buffers[i];
|
||||
uint32_t type = buffers[i]->datas[0].type;
|
||||
uint32_t type;
|
||||
|
||||
b->outbuf = buffers[i];
|
||||
b->outstanding = true;
|
||||
|
@ -454,6 +454,7 @@ impl_node_port_use_buffers(struct spa_node *node,
|
|||
b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header);
|
||||
b->rb = spa_buffer_find_meta(b->outbuf, this->type.meta.Ringbuffer);
|
||||
|
||||
type = buffers[i]->datas[0].type;
|
||||
if ((type == this->type.data.MemFd ||
|
||||
type == this->type.data.DmaBuf ||
|
||||
type == this->type.data.MemPtr) && buffers[i]->datas[0].data == NULL) {
|
||||
|
@ -569,10 +570,18 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item node_info_items[] = {
|
||||
{ "media.class", "Audio/Sink" },
|
||||
};
|
||||
|
||||
static const struct spa_dict node_info = {
|
||||
SPA_N_ELEMENTS(node_info_items),
|
||||
node_info_items
|
||||
};
|
||||
|
||||
static const struct spa_node impl_node = {
|
||||
SPA_VERSION_NODE,
|
||||
NULL,
|
||||
&node_info,
|
||||
impl_node_get_props,
|
||||
impl_node_set_props,
|
||||
impl_node_send_command,
|
||||
|
@ -693,10 +702,20 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item info_items[] = {
|
||||
{ "factory.author", "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ "factory.description", "Play audio with the alsa API" },
|
||||
};
|
||||
|
||||
static const struct spa_dict info = {
|
||||
SPA_N_ELEMENTS(info_items),
|
||||
info_items
|
||||
};
|
||||
|
||||
const struct spa_handle_factory spa_alsa_sink_factory = {
|
||||
SPA_VERSION_HANDLE_FACTORY,
|
||||
NAME,
|
||||
NULL,
|
||||
&info,
|
||||
sizeof(struct state),
|
||||
impl_init,
|
||||
impl_enum_interface_info,
|
||||
|
|
|
@ -580,9 +580,18 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item node_info_items[] = {
|
||||
{ "media.class", "Audio/Sink" },
|
||||
};
|
||||
|
||||
static const struct spa_dict node_info = {
|
||||
SPA_N_ELEMENTS(node_info_items),
|
||||
node_info_items
|
||||
};
|
||||
|
||||
static const struct spa_node impl_node = {
|
||||
SPA_VERSION_NODE,
|
||||
NULL,
|
||||
&node_info,
|
||||
impl_node_get_props,
|
||||
impl_node_set_props,
|
||||
impl_node_send_command,
|
||||
|
@ -749,10 +758,20 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item info_items[] = {
|
||||
{ "factory.author", "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ "factory.description", "Record audio with the alsa API" },
|
||||
};
|
||||
|
||||
static const struct spa_dict info = {
|
||||
SPA_N_ELEMENTS(info_items),
|
||||
info_items
|
||||
};
|
||||
|
||||
const struct spa_handle_factory spa_alsa_source_factory = {
|
||||
SPA_VERSION_HANDLE_FACTORY,
|
||||
NAME,
|
||||
NULL,
|
||||
&info,
|
||||
sizeof(struct state),
|
||||
impl_init,
|
||||
impl_enum_interface_info,
|
||||
|
|
|
@ -373,9 +373,7 @@ pull_frames(struct state *state,
|
|||
b->outstanding = true;
|
||||
state->io->buffer_id = b->outbuf->id;
|
||||
spa_log_trace(state->log, "alsa-util %p: reuse buffer %u", state, b->outbuf->id);
|
||||
state->callbacks->reuse_buffer(state->callbacks_data,
|
||||
0,
|
||||
b->outbuf->id);
|
||||
state->callbacks->reuse_buffer(state->callbacks_data, 0, b->outbuf->id);
|
||||
state->ready_offset = 0;
|
||||
}
|
||||
total_frames += n_frames;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <spa/list.h>
|
||||
#include <spa/audio/format-utils.h>
|
||||
#include <spa/format-builder.h>
|
||||
|
||||
#include <lib/format.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
|
@ -126,6 +127,7 @@ struct impl {
|
|||
const struct spa_node_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
|
||||
bool async;
|
||||
struct spa_source timer_source;
|
||||
struct itimerspec timerspec;
|
||||
|
||||
|
@ -154,7 +156,7 @@ struct impl {
|
|||
#define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_PORT_NUM(this,d,p) && this->io)
|
||||
|
||||
#define DEFAULT_LIVE true
|
||||
#define DEFAULT_LIVE false
|
||||
#define DEFAULT_WAVE wave_sine
|
||||
#define DEFAULT_FREQ 440.0
|
||||
#define DEFAULT_VOLUME 1.0
|
||||
|
@ -242,7 +244,7 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
|
|||
|
||||
static void set_timer(struct impl *this, bool enabled)
|
||||
{
|
||||
if ((this->callbacks && this->callbacks->have_output) || this->props.live) {
|
||||
if (this->async || this->props.live) {
|
||||
if (enabled) {
|
||||
if (this->props.live) {
|
||||
uint64_t next_time = this->start_time + this->elapsed_time;
|
||||
|
@ -264,7 +266,7 @@ static void read_timer(struct impl *this)
|
|||
{
|
||||
uint64_t expirations;
|
||||
|
||||
if ((this->callbacks && this->callbacks->have_output) || this->props.live) {
|
||||
if (this->async || this->props.live) {
|
||||
if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
perror("read timerfd");
|
||||
}
|
||||
|
@ -415,10 +417,6 @@ impl_node_set_callbacks(struct spa_node *node,
|
|||
|
||||
this = SPA_CONTAINER_OF(node, struct impl, node);
|
||||
|
||||
if (this->data_loop == NULL && (callbacks && callbacks->have_output != NULL)) {
|
||||
spa_log_error(this->log, "a data_loop is needed for async operation");
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
this->callbacks = callbacks;
|
||||
this->callbacks_data = data;
|
||||
|
||||
|
@ -680,15 +678,13 @@ impl_node_port_enum_params(struct spa_node *node,
|
|||
switch (index) {
|
||||
case 0:
|
||||
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
|
||||
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
1024 * this->bpf),
|
||||
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
|
||||
this->bpf),
|
||||
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
|
||||
32,
|
||||
2, 32),
|
||||
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
|
||||
16));
|
||||
PROP_U_MM(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
|
||||
1024 * this->bpf,
|
||||
16 * this->bpf,
|
||||
INT32_MAX / this->bpf),
|
||||
PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0),
|
||||
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 2, 1, 32),
|
||||
PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -753,6 +749,7 @@ impl_node_port_use_buffers(struct spa_node *node,
|
|||
d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) {
|
||||
spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this,
|
||||
buffers[i]);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
spa_list_append(&this->empty, &b->link);
|
||||
}
|
||||
|
@ -867,16 +864,24 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
this->io->buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
|
||||
if ((this->callbacks == NULL || this->callbacks->have_output == NULL) &&
|
||||
(io->status == SPA_RESULT_NEED_BUFFER))
|
||||
if (!this->async && (io->status == SPA_RESULT_NEED_BUFFER))
|
||||
return make_buffer(this);
|
||||
else
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item node_info_items[] = {
|
||||
{ "media.class", "Audio/Source" },
|
||||
};
|
||||
|
||||
static const struct spa_dict node_info = {
|
||||
SPA_N_ELEMENTS(node_info_items),
|
||||
node_info_items
|
||||
};
|
||||
|
||||
static const struct spa_node impl_node = {
|
||||
SPA_VERSION_NODE,
|
||||
NULL,
|
||||
&node_info,
|
||||
impl_node_get_props,
|
||||
impl_node_set_props,
|
||||
impl_node_send_command,
|
||||
|
@ -1061,10 +1066,20 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item info_items[] = {
|
||||
{ "factory.author", "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ "factory.description", "Generate an audio test pattern" },
|
||||
};
|
||||
|
||||
static const struct spa_dict info = {
|
||||
SPA_N_ELEMENTS(info_items),
|
||||
info_items
|
||||
};
|
||||
|
||||
const struct spa_handle_factory spa_audiotestsrc_factory = {
|
||||
SPA_VERSION_HANDLE_FACTORY,
|
||||
NAME,
|
||||
NULL,
|
||||
&info,
|
||||
sizeof(struct impl),
|
||||
impl_init,
|
||||
impl_enum_interface_info,
|
||||
|
|
|
@ -823,9 +823,18 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
return res;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item info_items[] = {
|
||||
{ "media.class", "Video/Source" },
|
||||
};
|
||||
|
||||
static const struct spa_dict info = {
|
||||
SPA_N_ELEMENTS(info_items),
|
||||
info_items
|
||||
};
|
||||
|
||||
static const struct spa_node impl_node = {
|
||||
SPA_VERSION_NODE,
|
||||
NULL,
|
||||
&info,
|
||||
impl_node_get_props,
|
||||
impl_node_set_props,
|
||||
impl_node_send_command,
|
||||
|
|
|
@ -116,6 +116,7 @@ struct impl {
|
|||
const struct spa_node_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
|
||||
bool async;
|
||||
struct spa_source timer_source;
|
||||
struct itimerspec timerspec;
|
||||
|
||||
|
@ -143,7 +144,7 @@ struct impl {
|
|||
#define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_PORT_NUM(this,d,p) && this->io)
|
||||
|
||||
#define DEFAULT_LIVE true
|
||||
#define DEFAULT_LIVE false
|
||||
#define DEFAULT_PATTERN pattern_smpte_snow
|
||||
|
||||
static void reset_props(struct impl *this, struct props *props)
|
||||
|
@ -224,7 +225,7 @@ static int fill_buffer(struct impl *this, struct buffer *b)
|
|||
|
||||
static void set_timer(struct impl *this, bool enabled)
|
||||
{
|
||||
if ((this->callbacks && this->callbacks->have_output) || this->props.live) {
|
||||
if (this->async || this->props.live) {
|
||||
if (enabled) {
|
||||
if (this->props.live) {
|
||||
uint64_t next_time = this->start_time + this->elapsed_time;
|
||||
|
@ -246,7 +247,7 @@ static void read_timer(struct impl *this)
|
|||
{
|
||||
uint64_t expirations;
|
||||
|
||||
if ((this->callbacks && this->callbacks->have_output) || this->props.live) {
|
||||
if (this->async || this->props.live) {
|
||||
if (read(this->timer_source.fd, &expirations, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
perror("read timerfd");
|
||||
}
|
||||
|
@ -366,10 +367,6 @@ impl_node_set_callbacks(struct spa_node *node,
|
|||
|
||||
this = SPA_CONTAINER_OF(node, struct impl, node);
|
||||
|
||||
if (this->data_loop == NULL && callbacks != NULL && callbacks->have_output != NULL) {
|
||||
spa_log_error(this->log, "a data_loop is needed for async operation");
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
this->callbacks = callbacks;
|
||||
this->callbacks_data = data;
|
||||
|
||||
|
@ -631,7 +628,7 @@ impl_node_port_enum_params(struct spa_node *node,
|
|||
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
|
||||
this->stride),
|
||||
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
|
||||
32, 2, 32),
|
||||
2, 1, 32),
|
||||
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
|
||||
16));
|
||||
break;
|
||||
|
@ -697,8 +694,9 @@ impl_node_port_use_buffers(struct spa_node *node,
|
|||
d[0].type == this->type.data.DmaBuf) && d[0].data == NULL) {
|
||||
spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this,
|
||||
buffers[i]);
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
spa_list_insert(this->empty.prev, &b->link);
|
||||
spa_list_append(&this->empty, &b->link);
|
||||
}
|
||||
this->n_buffers = n_buffers;
|
||||
|
||||
|
@ -712,7 +710,7 @@ impl_node_port_alloc_buffers(struct spa_node *node,
|
|||
struct spa_param **params,
|
||||
uint32_t n_params,
|
||||
struct spa_buffer **buffers,
|
||||
uint32_t * n_buffers)
|
||||
uint32_t *n_buffers)
|
||||
{
|
||||
struct impl *this;
|
||||
|
||||
|
@ -755,7 +753,7 @@ static inline void reuse_buffer(struct impl *this, uint32_t id)
|
|||
spa_log_trace(this->log, NAME " %p: reuse buffer %d", this, id);
|
||||
|
||||
b->outstanding = false;
|
||||
spa_list_insert(this->empty.prev, &b->link);
|
||||
spa_list_append(&this->empty, &b->link);
|
||||
|
||||
if (!this->props.live)
|
||||
set_timer(this, true);
|
||||
|
@ -811,16 +809,24 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
this->io->buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
|
||||
if ((this->callbacks == NULL || this->callbacks->have_output == NULL) &&
|
||||
(io->status == SPA_RESULT_NEED_BUFFER))
|
||||
if (!this->async && (io->status == SPA_RESULT_NEED_BUFFER))
|
||||
return make_buffer(this);
|
||||
else
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item node_info_items[] = {
|
||||
{ "media.class", "Video/Source" },
|
||||
};
|
||||
|
||||
static const struct spa_dict node_info = {
|
||||
SPA_N_ELEMENTS(node_info_items),
|
||||
node_info_items
|
||||
};
|
||||
|
||||
static const struct spa_node impl_node = {
|
||||
SPA_VERSION_NODE,
|
||||
NULL,
|
||||
&node_info,
|
||||
impl_node_get_props,
|
||||
impl_node_set_props,
|
||||
impl_node_send_command,
|
||||
|
@ -1005,10 +1011,20 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static const struct spa_dict_item info_items[] = {
|
||||
{ "factory.author", "Wim Taymans <wim.taymans@gmail.com>" },
|
||||
{ "factory.description", "Generate a video test pattern" },
|
||||
};
|
||||
|
||||
static const struct spa_dict info = {
|
||||
SPA_N_ELEMENTS(info_items),
|
||||
info_items
|
||||
};
|
||||
|
||||
const struct spa_handle_factory spa_videotestsrc_factory = {
|
||||
SPA_VERSION_HANDLE_FACTORY,
|
||||
NAME,
|
||||
NULL,
|
||||
&info,
|
||||
sizeof(struct impl),
|
||||
impl_init,
|
||||
impl_enum_interface_info,
|
||||
|
|
|
@ -89,6 +89,12 @@ static void inspect_node(struct data *data, struct spa_node *node)
|
|||
uint32_t *in_ports, *out_ports;
|
||||
struct spa_props *props;
|
||||
|
||||
printf("node info:\n");
|
||||
if (node->info)
|
||||
spa_debug_dict(node->info);
|
||||
else
|
||||
printf(" none\n");
|
||||
|
||||
if ((res = spa_node_get_props(node, &props)) < 0)
|
||||
printf("can't get properties: %d\n", res);
|
||||
else
|
||||
|
|
|
@ -3,9 +3,9 @@ load-module libpipewire-module-protocol-native
|
|||
load-module libpipewire-module-suspend-on-idle
|
||||
load-module libpipewire-module-spa-monitor alsa/libspa-alsa alsa-monitor alsa
|
||||
load-module libpipewire-module-spa-monitor v4l2/libspa-v4l2 v4l2-monitor v4l2
|
||||
#load-module libpipewire-module-spa-node videotestsrc/libspa-videotestsrc videotestsrc videotestsrc media.class=Video/Source Spa:POD:Object:Props:patternType=Spa:POD:Object:Props:patternType:snow
|
||||
#load-module libpipewire-module-spa-node videotestsrc/libspa-videotestsrc videotestsrc videotestsrc Spa:POD:Object:Props:patternType=Spa:POD:Object:Props:patternType:snow
|
||||
load-module libpipewire-module-autolink
|
||||
#load-module libpipewire-module-mixer
|
||||
load-module libpipewire-module-client-node
|
||||
load-module libpipewire-module-flatpak
|
||||
load-module libpipewire-module-jack
|
||||
#load-module libpipewire-module-jack
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include <spa/lib/debug.h>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/module.h>
|
||||
#include <pipewire/node-factory.h>
|
||||
|
||||
#define M_PI_M2 ( M_PI + M_PI )
|
||||
|
||||
|
@ -312,9 +310,6 @@ static int impl_node_process_output(struct spa_node *node)
|
|||
int16_t *dst;
|
||||
struct spa_port_io *io = d->io;
|
||||
|
||||
if (io->status == SPA_RESULT_HAVE_BUFFER)
|
||||
return SPA_RESULT_HAVE_BUFFER;
|
||||
|
||||
if (io->buffer_id < d->n_buffers) {
|
||||
reuse_buffer(d, io->buffer_id);
|
||||
io->buffer_id = SPA_ID_INVALID;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <spa/lib/debug.h>
|
||||
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/module.h>
|
||||
#include <pipewire/node-factory.h>
|
||||
|
||||
struct data {
|
||||
|
@ -42,19 +41,33 @@ struct data {
|
|||
struct spa_hook remote_listener;
|
||||
|
||||
struct pw_node *node;
|
||||
const char *library;
|
||||
const char *factory;
|
||||
const char *path;
|
||||
};
|
||||
|
||||
static void make_node(struct data *data)
|
||||
static int make_node(struct data *data)
|
||||
{
|
||||
struct pw_node_factory *factory;
|
||||
struct pw_properties *props;
|
||||
|
||||
factory = pw_core_find_node_factory(data->core, "spa-node-factory");
|
||||
props = pw_properties_new("spa.library.name", "v4l2/libspa-v4l2",
|
||||
"spa.factory.name", "v4l2-source", NULL);
|
||||
data->node = pw_node_factory_create_node(factory, NULL, "v4l2-source", props);
|
||||
if (factory == NULL)
|
||||
return -1;
|
||||
|
||||
props = pw_properties_new("spa.library.name", data->library,
|
||||
"spa.factory.name", data->factory, NULL);
|
||||
|
||||
if (data->path) {
|
||||
pw_properties_set(props, "pipewire.autoconnect", "1");
|
||||
pw_properties_set(props, "pipewire.target.node", data->path);
|
||||
}
|
||||
|
||||
data->node = pw_node_factory_create_node(factory, NULL, data->factory, props);
|
||||
|
||||
pw_remote_export(data->remote, data->node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
|
||||
|
@ -69,7 +82,10 @@ static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remo
|
|||
|
||||
case PW_REMOTE_STATE_CONNECTED:
|
||||
printf("remote state: \"%s\"\n", pw_remote_state_as_string(state));
|
||||
make_node(data);
|
||||
if (make_node(data) < 0) {
|
||||
pw_log_error("can't make node");
|
||||
pw_main_loop_quit(data->loop);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -96,6 +112,13 @@ int main(int argc, char *argv[])
|
|||
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "usage: %s <library> <factory> [path]\n\n"
|
||||
"\texample: %s v4l2/libspa-v4l2 v4l2-source\n\n",
|
||||
argv[0], argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data.loop = pw_main_loop_new(NULL);
|
||||
l = pw_main_loop_get_loop(data.loop);
|
||||
pw_loop_add_signal(l, SIGINT, do_quit, &data);
|
||||
|
@ -103,6 +126,10 @@ int main(int argc, char *argv[])
|
|||
data.core = pw_core_new(l, NULL);
|
||||
data.t = pw_core_get_type(data.core);
|
||||
data.remote = pw_remote_new(data.core, NULL);
|
||||
data.library = argv[1];
|
||||
data.factory = argv[2];
|
||||
if (argc > 3)
|
||||
data.path = argv[3];
|
||||
|
||||
pw_module_load(data.core, "libpipewire-module-spa-node-factory", NULL);
|
||||
|
||||
|
@ -114,7 +141,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
pw_main_loop_run(data.loop);
|
||||
|
||||
pw_remote_destroy(data.remote);
|
||||
if (data.node)
|
||||
pw_node_destroy(data.node);
|
||||
pw_core_destroy(data.core);
|
|
@ -3,17 +3,18 @@ executable('video-src',
|
|||
install: false,
|
||||
dependencies : [pipewire_dep],
|
||||
)
|
||||
executable('export-v4l2',
|
||||
'export-v4l2.c',
|
||||
install: false,
|
||||
dependencies : [pipewire_dep],
|
||||
)
|
||||
executable('export-source',
|
||||
'export-source.c',
|
||||
install: false,
|
||||
dependencies : [pipewire_dep, libm],
|
||||
)
|
||||
|
||||
executable('export-spa',
|
||||
'export-spa.c',
|
||||
install: false,
|
||||
dependencies : [pipewire_dep, libm],
|
||||
)
|
||||
|
||||
if sdl_dep.found()
|
||||
executable('video-play',
|
||||
'video-play.c',
|
||||
|
|
|
@ -198,7 +198,7 @@ new_node (GstPipeWireDeviceProvider *self, const struct pw_node_info *info, uint
|
|||
GstCaps *caps = NULL;
|
||||
GstStructure *props;
|
||||
const gchar *klass = NULL;
|
||||
struct spa_dict_item *item;
|
||||
const struct spa_dict_item *item;
|
||||
GstPipeWireDeviceType type;
|
||||
int i;
|
||||
struct pw_type *t = self->type;
|
||||
|
|
|
@ -96,7 +96,6 @@ static void add_item(struct pw_spa_monitor *this, struct spa_monitor_item *item)
|
|||
pw_properties_set(props, key, val);
|
||||
}
|
||||
}
|
||||
pw_properties_set(props, "media.class", klass);
|
||||
|
||||
support = pw_core_get_support(impl->core, &n_support);
|
||||
|
||||
|
|
|
@ -103,20 +103,6 @@ pw_spa_node_new(struct pw_core *core,
|
|||
struct pw_node *this;
|
||||
struct impl *impl;
|
||||
|
||||
if (node->info) {
|
||||
uint32_t i;
|
||||
|
||||
if (properties == NULL)
|
||||
properties = pw_properties_new(NULL, NULL);
|
||||
if (properties == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < node->info->n_items; i++)
|
||||
pw_properties_set(properties,
|
||||
node->info->items[i].key,
|
||||
node->info->items[i].value);
|
||||
}
|
||||
|
||||
this = pw_node_new(core, owner, parent, name, properties, sizeof(struct impl) + user_data_size);
|
||||
if (this == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -76,19 +76,20 @@ const char *pw_link_state_as_string(enum pw_link_state state)
|
|||
|
||||
static void pw_spa_dict_destroy(struct spa_dict *dict)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
const struct spa_dict_item *item;
|
||||
|
||||
spa_dict_for_each(item, dict) {
|
||||
free((void *) item->key);
|
||||
free((void *) item->value);
|
||||
}
|
||||
free(dict->items);
|
||||
free((void*)dict->items);
|
||||
free(dict);
|
||||
}
|
||||
|
||||
static struct spa_dict *pw_spa_dict_copy(struct spa_dict *dict)
|
||||
{
|
||||
struct spa_dict *copy;
|
||||
struct spa_dict_item *items;
|
||||
uint32_t i;
|
||||
|
||||
if (dict == NULL)
|
||||
|
@ -97,14 +98,14 @@ static struct spa_dict *pw_spa_dict_copy(struct spa_dict *dict)
|
|||
copy = calloc(1, sizeof(struct spa_dict));
|
||||
if (copy == NULL)
|
||||
goto no_mem;
|
||||
copy->items = calloc(dict->n_items, sizeof(struct spa_dict_item));
|
||||
copy->items = 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);
|
||||
items[i].key = strdup(dict->items[i].key);
|
||||
items[i].value = strdup(dict->items[i].value);
|
||||
}
|
||||
return copy;
|
||||
|
||||
|
|
|
@ -610,7 +610,7 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s
|
|||
data_sizes, data_strides,
|
||||
&this->buffer_mem);
|
||||
|
||||
pw_log_debug("link %p: allocating %d input buffers %p %zd %zd", this,
|
||||
pw_log_debug("link %p: allocating %d buffers %p %zd %zd", this,
|
||||
this->n_buffers, this->buffers, minsize, stride);
|
||||
}
|
||||
|
||||
|
|
|
@ -500,6 +500,14 @@ void pw_node_set_implementation(struct pw_node *node,
|
|||
node->node = spa_node;
|
||||
spa_node_set_callbacks(node->node, &node_callbacks, node);
|
||||
spa_graph_node_set_implementation(&node->rt.node, spa_node);
|
||||
|
||||
if (spa_node->info) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < spa_node->info->n_items; i++)
|
||||
pw_properties_set(node->properties,
|
||||
spa_node->info->items[i].key,
|
||||
spa_node->info->items[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
struct spa_node *pw_node_get_implementation(struct pw_node *node)
|
||||
|
|
|
@ -54,7 +54,7 @@ struct proxy_data {
|
|||
|
||||
static void print_properties(struct spa_dict *props, char mark)
|
||||
{
|
||||
struct spa_dict_item *item;
|
||||
const struct spa_dict_item *item;
|
||||
|
||||
printf("%c\tproperties:\n", mark);
|
||||
if (props == NULL || props->n_items == 0) {
|
||||
|
|
Loading…
Reference in a new issue