monitor: return factory_name in the object_info

Pass a factory_name in the object_info of monitor and device.
Restructure the factory name to mean something functionaly. With
the factory to library mapping this then means that the implementation
of certain factories can be configured in the config file.
This commit is contained in:
Wim Taymans 2019-05-31 15:06:44 +02:00
parent 89a86db0c4
commit 1d1f035e78
26 changed files with 218 additions and 168 deletions

View file

@ -283,7 +283,7 @@ static int make_nodes(struct data *data, const char *device)
//uint32_t idx;
if ((res = make_node(data, &data->sink,
"build/spa/plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) {
"build/spa/plugins/alsa/libspa-alsa.so", "api.alsa.pcm.sink")) < 0) {
printf("can't create alsa-sink: %d\n", res);
return res;
}

View file

@ -255,7 +255,7 @@ static int make_nodes(struct data *data, const char *device)
uint32_t index;
if ((res =
make_node(data, &data->source, PATH "v4l2/libspa-v4l2.so", "v4l2-source")) < 0) {
make_node(data, &data->source, PATH "v4l2/libspa-v4l2.so", "api.v4l2.source")) < 0) {
printf("can't create v4l2-source: %d\n", res);
return res;
}

View file

@ -64,7 +64,7 @@ struct spa_device_object_info {
uint32_t version;
uint32_t type;
const struct spa_handle_factory *factory;
const char *factory_name;
#define SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS (1u<<0)
#define SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS (1u<<1)

View file

@ -55,7 +55,7 @@ struct spa_monitor_object_info {
uint32_t version;
uint32_t type;
const struct spa_handle_factory *factory;
const char *factory_name;
#define SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS (1u<<0)
#define SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS (1u<<1)

View file

@ -46,9 +46,6 @@
#define MAX_DEVICES 64
extern const struct spa_handle_factory spa_alsa_sink_factory;
extern const struct spa_handle_factory spa_alsa_source_factory;
static const char default_device[] = "hw:0";
struct props {
@ -112,9 +109,9 @@ static int emit_node(struct impl *this, snd_pcm_info_t *pcminfo, uint32_t id)
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
if (snd_pcm_info_get_stream(pcminfo) == SND_PCM_STREAM_PLAYBACK)
info.factory = &spa_alsa_sink_factory;
info.factory_name = "api.alsa.pcm.sink";
else
info.factory = &spa_alsa_source_factory;
info.factory_name = "api.alsa.pcm.source";
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
snprintf(device_name, 128, "%s,%d", this->props.device, snd_pcm_info_get_device(pcminfo));
@ -494,7 +491,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_alsa_device_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.alsa.device",
NULL,
impl_get_size,
impl_init,

View file

@ -47,8 +47,6 @@
#define ACTION_CHANGE 1
#define ACTION_REMOVE 2
extern const struct spa_handle_factory spa_alsa_device_factory;
struct impl {
struct spa_handle handle;
struct spa_monitor monitor;
@ -111,7 +109,7 @@ static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_alsa_device_factory;
info.factory_name = "api.alsa.device";
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
@ -481,7 +479,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_alsa_monitor_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.alsa.monitor",
NULL,
impl_get_size,
impl_init,

View file

@ -542,7 +542,7 @@ impl_node_port_use_buffers(void *object,
spa_log_error(this->log, NAME " %p: need mapped memory", this);
return -EINVAL;
}
spa_log_debug(this->log, "alsa-sink %p: %d %p data:%p", this, i, b->buf, d[0].data);
spa_log_debug(this->log, NAME " %p: %d %p data:%p", this, i, b->buf, d[0].data);
}
this->n_buffers = n_buffers;
@ -801,7 +801,7 @@ static const struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items);
const struct spa_handle_factory spa_alsa_sink_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.alsa.pcm.sink",
&info,
impl_get_size,
impl_init,

View file

@ -813,7 +813,7 @@ static const struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items);
const struct spa_handle_factory spa_alsa_source_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.alsa.pcm.source",
&info,
impl_get_size,
impl_init,

View file

@ -290,7 +290,7 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size)
slaved = is_slaved(this);
if (this->started && slaved != this->slaved) {
spa_log_debug(this->log, "a2dp-sink %p: reslave %d->%d", this, this->slaved, slaved);
spa_log_debug(this->log, NAME " %p: reslave %d->%d", this, this->slaved, slaved);
this->slaved = slaved;
spa_loop_invoke(this->data_loop, do_reslave, 0, NULL, 0, true, this);
}
@ -367,12 +367,12 @@ static int send_buffer(struct impl *this)
ioctl(this->transport->fd, TIOCOUTQ, &val);
spa_log_trace(this->log, "a2dp-sink %p: send %d %u %u %u %lu %d",
spa_log_trace(this->log, NAME " %p: send %d %u %u %u %lu %d",
this, this->frame_count, this->seqnum, this->timestamp, this->buffer_used,
this->sample_time, val);
written = write(this->transport->fd, this->buffer, this->buffer_used);
spa_log_trace(this->log, "a2dp-sink %p: send %d", this, written);
spa_log_trace(this->log, NAME " %p: send %d", this, written);
if (written < 0)
return -errno;
@ -389,7 +389,7 @@ static int encode_buffer(struct impl *this, const void *data, int size)
ssize_t out_encoded;
struct port *port = &this->port;
spa_log_trace(this->log, "a2dp-sink %p: encode %d used %d, %d %d %d/%d",
spa_log_trace(this->log, NAME " %p: encode %d used %d, %d %d %d/%d",
this, size, this->buffer_used, port->frame_size, this->write_size,
this->frame_count, MAX_FRAME_COUNT);
@ -408,7 +408,7 @@ static int encode_buffer(struct impl *this, const void *data, int size)
this->frame_count += processed / this->codesize;
this->buffer_used += out_encoded;
spa_log_trace(this->log, "a2dp-sink %p: processed %d %ld used %d",
spa_log_trace(this->log, NAME " %p: processed %d %ld used %d",
this, processed, out_encoded, this->buffer_used);
return processed;
@ -422,8 +422,8 @@ static bool need_flush(struct impl *this)
static int flush_buffer(struct impl *this, bool force)
{
spa_log_trace(this->log, "%d %d %d", this->buffer_used, this->frame_length,
this->write_size);
spa_log_trace(this->log, NAME" %p: %d %d %d", this,
this->buffer_used, this->frame_length, this->write_size);
if (force || need_flush(this))
return send_buffer(this);
@ -492,7 +492,7 @@ static int set_bitpool(struct impl *this, int bitpool)
this->sbc.bitpool = bitpool;
spa_log_debug(this->log, "set bitpool %d", this->sbc.bitpool);
spa_log_debug(this->log, NAME" %p: set bitpool %d", this, this->sbc.bitpool);
this->codesize = sbc_get_codesize(&this->sbc);
this->frame_length = sbc_get_frame_length(&this->sbc);
@ -563,19 +563,19 @@ static int flush_data(struct impl *this, uint64_t now_time)
if (port->ready_offset >= d[0].chunk->size) {
spa_list_remove(&b->link);
b->outstanding = true;
spa_log_trace(this->log, "a2dp-sink %p: reuse buffer %u", this, b->id);
spa_log_trace(this->log, NAME " %p: reuse buffer %u", this, b->id);
spa_node_call_reuse_buffer(&this->callbacks, 0, b->id);
port->ready_offset = 0;
}
total_frames += n_frames;
spa_log_trace(this->log, "a2dp-sink %p: written %u frames", this, total_frames);
spa_log_trace(this->log, NAME " %p: written %u frames", this, total_frames);
}
written = flush_buffer(this, false);
if (written == -EAGAIN) {
spa_log_trace(this->log, "delay flush %ld", this->sample_time);
spa_log_trace(this->log, NAME" %p: delay flush %ld", this, this->sample_time);
if ((this->flush_source.mask & SPA_IO_OUT) == 0) {
this->flush_source.mask = SPA_IO_OUT;
spa_loop_update_source(this->data_loop, &this->flush_source);
@ -585,7 +585,8 @@ static int flush_data(struct impl *this, uint64_t now_time)
}
}
else if (written < 0) {
spa_log_trace(this->log, "error flushing %s", spa_strerror(written));
spa_log_trace(this->log, NAME" %p: error flushing %s", this,
spa_strerror(written));
return written;
}
else if (written > 0) {
@ -607,7 +608,7 @@ static int flush_data(struct impl *this, uint64_t now_time)
queued = this->sample_time - elapsed;
spa_log_trace(this->log, "%ld %ld %ld %ld %d",
spa_log_trace(this->log, NAME" %p: %ld %ld %ld %ld %d", this,
now_time, queued, this->sample_time, elapsed, this->write_samples);
if (!this->slaved) {
@ -644,10 +645,10 @@ static void a2dp_on_flush(struct spa_source *source)
struct impl *this = source->data;
uint64_t now_time;
spa_log_trace(this->log, "flushing");
spa_log_trace(this->log, NAME" %p: flushing", this);
if ((source->rmask & SPA_IO_OUT) == 0) {
spa_log_warn(this->log, "error %d", source->rmask);
spa_log_warn(this->log, NAME" %p: error %d", this, source->rmask);
if (this->flush_source.loop)
spa_loop_remove_source(this->data_loop, &this->flush_source);
this->source.mask = 0;
@ -675,7 +676,8 @@ static void a2dp_on_timeout(struct spa_source *source)
clock_gettime(CLOCK_MONOTONIC, &this->now);
now_time = SPA_TIMESPEC_TO_NSEC(&this->now);
spa_log_trace(this->log, "timeout %ld %ld", now_time, now_time - this->last_time);
spa_log_trace(this->log, NAME" %p: timeout %ld %ld", this,
now_time, now_time - this->last_time);
this->last_time = now_time;
if (this->start_time == 0) {
@ -685,7 +687,7 @@ static void a2dp_on_timeout(struct spa_source *source)
}
if (spa_list_is_empty(&port->ready)) {
spa_log_trace(this->log, "a2dp-sink %p: %d", this, io->status);
spa_log_trace(this->log, NAME " %p: %d", this, io->status);
io->status = SPA_STATUS_NEED_BUFFER;
@ -765,7 +767,7 @@ static int init_sbc(struct impl *this)
this->seqnum = 0;
spa_log_debug(this->log, "a2dp-sink %p: codesize %d frame_length %d size %d:%d %d",
spa_log_debug(this->log, NAME " %p: codesize %d frame_length %d size %d:%d %d",
this, this->codesize, this->frame_length, this->read_size, this->write_size,
this->sbc.bitpool);
@ -782,7 +784,7 @@ static int do_start(struct impl *this)
this->slaved = is_slaved(this);
spa_log_debug(this->log, "a2dp-sink %p: start slaved:%d", this, this->slaved);
spa_log_debug(this->log, NAME " %p: start slaved:%d", this, this->slaved);
if ((res = spa_bt_transport_acquire(this->transport, false)) < 0)
return res;
@ -791,19 +793,19 @@ static int do_start(struct impl *this)
val = FILL_FRAMES * this->transport->write_mtu;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "a2dp-sink %p: SO_SNDBUF %m", this);
spa_log_warn(this->log, NAME " %p: SO_SNDBUF %m", this);
len = sizeof(val);
if (getsockopt(this->transport->fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) {
spa_log_warn(this->log, "a2dp-sink %p: SO_SNDBUF %m", this);
spa_log_warn(this->log, NAME " %p: SO_SNDBUF %m", this);
}
else {
spa_log_debug(this->log, "a2dp-sink %p: SO_SNDBUF: %d", this, val);
spa_log_debug(this->log, NAME " %p: SO_SNDBUF: %d", this, val);
}
val = FILL_FRAMES * this->transport->read_mtu;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "a2dp-sink %p: SO_RCVBUF %m", this);
spa_log_warn(this->log, NAME " %p: SO_RCVBUF %m", this);
val = 6;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
@ -861,7 +863,7 @@ static int do_stop(struct impl *this)
if (!this->started)
return 0;
spa_log_trace(this->log, "a2dp-sink %p: stop", this);
spa_log_trace(this->log, NAME " %p: stop", this);
spa_loop_invoke(this->data_loop, do_remove_source, 0, NULL, 0, true, this);
@ -1515,7 +1517,7 @@ static const struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items);
struct spa_handle_factory spa_a2dp_sink_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.bluez5.a2dp.sink",
&info,
impl_get_size,
impl_init,

View file

@ -244,7 +244,7 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size)
slaved = is_slaved(this);
if (this->started && slaved != this->slaved) {
spa_log_debug(this->log, "a2dp-source %p: reslave %d->%d", this, this->slaved, slaved);
spa_log_debug(this->log, NAME" %p: reslave %d->%d", this, this->slaved, slaved);
this->slaved = slaved;
spa_loop_invoke(this->data_loop, do_reslave, 0, NULL, 0, true, this);
}
@ -443,11 +443,11 @@ static int transport_start(struct impl *this)
val = FILL_FRAMES * this->transport->write_mtu;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "a2dp-source %p: SO_SNDBUF %m", this);
spa_log_warn(this->log, NAME" %p: SO_SNDBUF %m", this);
val = FILL_FRAMES * this->transport->read_mtu;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) < 0)
spa_log_warn(this->log, "a2dp-source %p: SO_RCVBUF %m", this);
spa_log_warn(this->log, NAME" %p: SO_RCVBUF %m", this);
val = 6;
if (setsockopt(this->transport->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
@ -477,7 +477,7 @@ static int do_start(struct impl *this)
if (this->transport == NULL)
return -EIO;
spa_log_debug(this->log, "a2dp-source %p: start", this);
spa_log_debug(this->log, NAME" %p: start", this);
if (this->transport->state >= SPA_BT_TRANSPORT_STATE_PENDING)
res = transport_start(this);
@ -509,7 +509,7 @@ static int do_stop(struct impl *this)
if (!this->started)
return 0;
spa_log_debug(this->log, "a2dp-source %p: stop", this);
spa_log_debug(this->log, NAME" %p: stop", this);
spa_loop_invoke(this->data_loop, do_remove_source, 0, NULL, 0, true, this);
@ -1217,7 +1217,7 @@ static const struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items);
struct spa_handle_factory spa_a2dp_source_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.bluez5.a2dp.source",
&info,
impl_get_size,
impl_init,

View file

@ -43,9 +43,6 @@
#define MAX_DEVICES 64
extern const struct spa_handle_factory spa_a2dp_source_factory;
extern const struct spa_handle_factory spa_a2dp_sink_factory;
static const char default_device[] = "";
struct props {
@ -110,7 +107,7 @@ static int emit_source_node(struct impl *this)
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
info.factory = &spa_a2dp_source_factory;
info.factory_name = "api.bluez5.a2dp.source";
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
@ -157,7 +154,7 @@ static int emit_sink_node(struct impl *this)
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
info.factory = &spa_a2dp_sink_factory;
info.factory_name = "api.bluez5.a2dp.sink";
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
@ -346,7 +343,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_bluez5_device_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.bluez5.device",
NULL,
impl_get_size,
impl_init,

View file

@ -75,8 +75,6 @@ struct transport_data {
struct spa_source sco;
};
struct spa_handle_factory spa_bluez5_device_factory;
static inline void add_dict(struct spa_pod_builder *builder, const char *key, const char *val)
{
spa_pod_builder_string(builder, key);
@ -500,7 +498,7 @@ static int device_add(struct spa_bt_monitor *monitor, struct spa_bt_device *devi
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_bluez5_device_factory;
info.factory_name = "api.bluez5.device";
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
@ -2289,7 +2287,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_bluez5_monitor_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.bluez5.monitor",
NULL,
impl_get_size,
impl_init,

View file

@ -42,8 +42,6 @@
static const char default_device[] = "/dev/video0";
extern const struct spa_handle_factory spa_v4l2_source_factory;
struct props {
char device[64];
char device_name[128];
@ -103,7 +101,7 @@ static int emit_info(struct impl *this, bool full)
oinfo = SPA_DEVICE_OBJECT_INFO_INIT();
oinfo.type = SPA_TYPE_INTERFACE_Node;
oinfo.factory = &spa_v4l2_source_factory;
oinfo.factory_name = "api.v4l2.source";
oinfo.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
oinfo.props = &SPA_DICT_INIT(items, 6);
@ -266,7 +264,7 @@ static int impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_v4l2_device_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.v4l2.device",
NULL,
impl_get_size,
impl_init,

View file

@ -40,8 +40,6 @@
#define NAME "v4l2-monitor"
extern const struct spa_handle_factory spa_v4l2_device_factory;
struct impl {
struct spa_handle handle;
struct spa_monitor monitor;
@ -100,7 +98,7 @@ static int emit_object_info(struct impl *this, uint32_t id, struct udev_device *
info = SPA_MONITOR_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Device;
info.factory = &spa_v4l2_device_factory;
info.factory_name = "api.v4l2.device";
info.change_mask = SPA_MONITOR_OBJECT_CHANGE_MASK_FLAGS |
SPA_MONITOR_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0;
@ -394,7 +392,7 @@ impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_v4l2_monitor_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.v4l2.monitor",
NULL,
impl_get_size,
impl_init,

View file

@ -1045,7 +1045,7 @@ static int impl_enum_interface_info(const struct spa_handle_factory *factory,
const struct spa_handle_factory spa_v4l2_source_factory = {
SPA_VERSION_HANDLE_FACTORY,
NAME,
"api.v4l2.source",
NULL,
impl_get_size,
impl_init,

View file

@ -1,9 +1,15 @@
#daemon config file for PipeWire version @VERSION@
add-spa-lib api.alsa.* alsa/libspa-alsa
add-spa-lib api.v4l2.* v4l2/libspa-v4l2
add-spa-lib api.bluez5.* bluez5/libspa-bluez5
load-module libpipewire-module-rtkit
load-module libpipewire-module-protocol-native
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-monitor bluez5/libspa-bluez5 bluez5-monitor bluez5
load-module libpipewire-module-spa-monitor api.alsa.monitor alsa
load-module libpipewire-module-spa-monitor api.v4l2.monitor v4l2
load-module libpipewire-module-spa-monitor api.bluez5.monitor bluez5
#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-client-node
load-module libpipewire-module-client-device

View file

@ -107,7 +107,9 @@ static struct node *create_node(struct object *obj, uint32_t id,
{
struct node *node;
struct impl *impl = obj->impl;
struct pw_core *core = impl->core;
const struct spa_support *support;
const char *lib;
uint32_t n_support;
struct spa_handle *handle;
int res;
@ -118,26 +120,31 @@ static struct node *create_node(struct object *obj, uint32_t id,
if (info->type != SPA_TYPE_INTERFACE_Node)
return NULL;
support = pw_core_get_support(impl->core, &n_support);
support = pw_core_get_support(core, &n_support);
handle = calloc(1, spa_handle_factory_get_size(info->factory, NULL));
if ((res = spa_handle_factory_init(info->factory,
handle,
lib = pw_core_find_spa_lib(core, info->factory_name);
if (lib == NULL) {
pw_log_error("can't find spa lib for factory %s", info->factory_name);
goto exit;
}
handle = pw_load_spa_handle(lib,
info->factory_name,
info->props,
support,
n_support)) < 0) {
pw_log_error("can't make factory instance: %d", res);
goto free_handle;
n_support, support);
if (handle == NULL) {
pw_log_error("can't make factory instance: %m");
goto exit;
}
if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) {
pw_log_error("can't get %d interface: %d", info->type, res);
goto clean_handle;
goto unload_handle;
}
node = calloc(1, sizeof(*node));
if (node == NULL)
goto clean_handle;
goto unload_handle;
node->impl = impl;
node->object = obj;
@ -157,10 +164,9 @@ static struct node *create_node(struct object *obj, uint32_t id,
clean_node:
free(node);
clean_handle:
spa_handle_clear(handle);
free_handle:
free(handle);
unload_handle:
pw_unload_spa_handle(handle);
exit:
return NULL;
}
@ -221,10 +227,12 @@ static void update_object(struct impl *impl, struct object *obj,
static struct object *create_object(struct impl *impl, uint32_t id,
const struct spa_monitor_object_info *info)
{
struct pw_core *core = impl->core;
struct object *obj;
const struct spa_support *support;
uint32_t n_support;
struct spa_handle *handle;
const char *lib;
int res;
void *iface;
@ -233,26 +241,31 @@ static struct object *create_object(struct impl *impl, uint32_t id,
if (info->type != SPA_TYPE_INTERFACE_Device)
return NULL;
support = pw_core_get_support(impl->core, &n_support);
support = pw_core_get_support(core, &n_support);
handle = calloc(1, spa_handle_factory_get_size(info->factory, NULL));
if ((res = spa_handle_factory_init(info->factory,
handle,
lib = pw_core_find_spa_lib(core, info->factory_name);
if (lib == NULL) {
pw_log_error("can't find spa lib for factory %s", info->factory_name);
goto exit;
}
handle = pw_load_spa_handle(lib,
info->factory_name,
info->props,
support,
n_support)) < 0) {
pw_log_error("can't make factory instance: %d", res);
goto free_handle;
n_support, support);
if (handle == NULL) {
pw_log_error("can't make factory instance: %m");
goto exit;
}
if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) {
pw_log_error("can't get %d interface: %d", info->type, res);
goto clean_handle;
goto unload_handle;
}
obj = calloc(1, sizeof(*obj));
if (obj == NULL)
goto clean_handle;
goto unload_handle;
obj->impl = impl;
obj->id = id;
@ -276,10 +289,9 @@ static struct object *create_object(struct impl *impl, uint32_t id,
clean_object:
free(obj);
clean_handle:
spa_handle_clear(handle);
free_handle:
free(handle);
unload_handle:
pw_unload_spa_handle(handle);
exit:
return NULL;
}

View file

@ -113,7 +113,7 @@ int main(int argc, char *argv[])
if (argc < 3) {
fprintf(stderr, "usage: %s <library> <factory>\n\n"
"\texample: %s v4l2/libspa-v4l2 v4l2-device\n\n",
"\texample: %s v4l2/libspa-v4l2 api.v4l2.device\n\n",
argv[0], argv[0]);
return -1;
}

View file

@ -119,7 +119,7 @@ int main(int argc, char *argv[])
if (argc < 3) {
fprintf(stderr, "usage: %s <library> <factory> [path]\n\n"
"\texample: %s v4l2/libspa-v4l2 v4l2-source\n\n",
"\texample: %s v4l2/libspa-v4l2 api.v4l2.source\n\n",
argv[0], argv[0]);
return -1;
}

View file

@ -332,7 +332,7 @@ static const struct spa_node_methods impl_node = {
.process = impl_node_process,
};
static void make_nodes(struct data *data)
static int make_nodes(struct data *data)
{
struct pw_factory *factory;
struct pw_properties *props;
@ -348,13 +348,16 @@ static void make_nodes(struct data *data)
factory = pw_core_find_factory(data->core, "spa-node-factory");
props = pw_properties_new("spa.library.name", "v4l2/libspa-v4l2",
"spa.factory.name", "v4l2-source", NULL);
"spa.factory.name", "api.v4l2.source", NULL);
data->v4l2 = pw_factory_create_object(factory,
NULL,
PW_TYPE_INTERFACE_Node,
PW_VERSION_NODE_PROXY,
props,
SPA_ID_INVALID);
if (data->v4l2 == NULL)
return -ENOMEM;
data->link = pw_link_new(data->core,
pw_node_find_port(data->v4l2, PW_DIRECTION_OUTPUT, 0),
pw_node_find_port(data->node, PW_DIRECTION_INPUT, 0),
@ -365,6 +368,8 @@ static void make_nodes(struct data *data)
pw_node_set_active(data->node, true);
pw_node_set_active(data->v4l2, true);
return 0;
}
int main(int argc, char *argv[])

View file

@ -76,6 +76,7 @@ static void *create_object(void *_data,
uint32_t new_id)
{
struct factory_data *data = _data;
struct pw_core *core = data->core;
struct pw_device *device;
const char *lib, *factory_name, *name;
struct device_data *nd;
@ -87,13 +88,15 @@ static void *create_object(void *_data,
factory_name = pw_properties_get(properties, "spa.factory.name");
name = pw_properties_get(properties, "name");
if (lib == NULL && factory_name != NULL)
lib = pw_core_find_spa_lib(core, factory_name);
if (lib == NULL || factory_name == NULL)
goto no_properties;
if (name == NULL)
name = "spa-device";
device = pw_spa_device_load(data->core,
device = pw_spa_device_load(core,
NULL,
pw_factory_get_global(data->this),
lib,
@ -120,11 +123,11 @@ static void *create_object(void *_data,
return device;
no_properties:
pw_log_error("needed properties: spa.library.name=<library-name> spa.factory.name=<factory-name>");
pw_log_error("needed properties: [spa.library.name=<library-name>] spa.factory.name=<factory-name>");
if (resource) {
pw_resource_error(resource, -EINVAL,
"needed properties: "
"spa.library.name=<library-name> "
"[spa.library.name=<library-name>] "
"spa.factory.name=<factory-name>");
}
return NULL;

View file

@ -67,7 +67,8 @@ const struct pw_module_events module_events = {
SPA_EXPORT
int pipewire__module_init(struct pw_module *module, const char *args)
{
const char *dir;
struct pw_core *core = pw_module_get_core(module);
const char *dir, *lib;
char **argv;
int n_tokens;
struct pw_spa_monitor *monitor;
@ -77,15 +78,21 @@ int pipewire__module_init(struct pw_module *module, const char *args)
goto wrong_arguments;
argv = pw_split_strv(args, " \t", INT_MAX, &n_tokens);
if (n_tokens < 3)
if (n_tokens < 2)
goto not_enough_arguments;
if ((dir = getenv("SPA_PLUGIN_DIR")) == NULL)
dir = PLUGINDIR;
monitor = pw_spa_monitor_load(pw_module_get_core(module),
if (n_tokens < 3)
lib = pw_core_find_spa_lib(core, argv[0]);
else
lib = argv[2];
monitor = pw_spa_monitor_load(core,
pw_module_get_global(module),
dir, argv[0], argv[1], argv[2],
dir, lib, argv[0], argv[1],
NULL,
sizeof(struct data));
if (monitor == NULL)
return -ENOMEM;
@ -104,6 +111,6 @@ int pipewire__module_init(struct pw_module *module, const char *args)
not_enough_arguments:
pw_free_strv(argv);
wrong_arguments:
pw_log_error("usage: module-spa-monitor <plugin> <factory> <name>");
pw_log_error("usage: module-spa-monitor <factory> <name> [<plugin>]");
return -EINVAL;
}

View file

@ -76,6 +76,7 @@ static void *create_object(void *_data,
uint32_t new_id)
{
struct factory_data *data = _data;
struct pw_core *core = data->core;
struct pw_node *node;
const char *lib, *factory_name, *name;
struct node_data *nd;
@ -87,13 +88,15 @@ static void *create_object(void *_data,
factory_name = pw_properties_get(properties, "spa.factory.name");
name = pw_properties_get(properties, "name");
if (lib == NULL && factory_name != NULL)
lib = pw_core_find_spa_lib(core, factory_name);
if (lib == NULL || factory_name == NULL)
goto no_properties;
if (name == NULL)
name = "spa-node";
node = pw_spa_node_load(data->core,
node = pw_spa_node_load(core,
NULL,
pw_factory_get_global(data->this),
lib,
@ -120,11 +123,11 @@ static void *create_object(void *_data,
return node;
no_properties:
pw_log_error("needed properties: spa.library.name=<library-name> spa.factory.name=<factory-name>");
pw_log_error("needed properties: [spa.library.name=<library-name>] spa.factory.name=<factory-name>");
if (resource) {
pw_resource_error(resource, -EINVAL,
"needed properties: "
"spa.library.name=<library-name> "
"[spa.library.name=<library-name>] "
"spa.factory.name=<factory-name>");
}
return NULL;

View file

@ -72,8 +72,7 @@ static void device_free(void *data)
struct monitor_object *obj = data;
spa_hook_remove(&obj->object_listener);
spa_list_remove(&obj->link);
spa_handle_clear(obj->handle);
free(obj->handle);
pw_unload_spa_handle(obj->handle);
free(obj);
}
@ -86,10 +85,11 @@ static struct monitor_object *add_object(struct pw_spa_monitor *this, uint32_t i
const struct spa_monitor_object_info *info, uint64_t now)
{
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
struct pw_core *core = impl->core;
int res;
struct spa_handle *handle;
struct monitor_object *obj;
const char *name, *str;
const char *name, *str, *lib;
void *iface;
struct pw_properties *props = NULL;
const struct spa_support *support;
@ -111,23 +111,25 @@ static struct monitor_object *add_object(struct pw_spa_monitor *this, uint32_t i
if (now != 0 && pw_properties_get(props, PW_KEY_DEVICE_PLUGGED) == NULL)
pw_properties_setf(props, PW_KEY_DEVICE_PLUGGED, "%"PRIu64, now);
support = pw_core_get_support(impl->core, &n_support);
lib = pw_core_find_spa_lib(core, info->factory_name);
if (lib == NULL) {
pw_log_warn("monitor %p: unknown library for %s",
this, info->factory_name);
goto error_free_props;
}
handle = calloc(1, spa_handle_factory_get_size(info->factory, NULL));
if ((res = spa_handle_factory_init(info->factory,
handle,
&props->dict,
support,
n_support)) < 0) {
pw_properties_free(props);
pw_log_error("can't make factory instance: %d", res);
return NULL;
support = pw_core_get_support(core, &n_support);
handle = pw_load_spa_handle(lib, info->factory_name,
&props->dict, n_support, support);
if (handle == NULL) {
pw_log_error("can't make factory instance: %m");
goto error_free_props;
}
if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) {
pw_log_error("can't get %d interface: %d", info->type, res);
pw_properties_free(props);
return NULL;
goto error_free_handle;
}
obj = calloc(1, sizeof(struct monitor_object));
@ -140,7 +142,7 @@ static struct monitor_object *add_object(struct pw_spa_monitor *this, uint32_t i
case SPA_TYPE_INTERFACE_Device:
{
struct pw_device *device;
device = pw_spa_device_new(impl->core, NULL, impl->parent, name,
device = pw_spa_device_new(core, NULL, impl->parent, name,
0, iface, handle, props, 0);
pw_device_add_listener(device, &obj->object_listener,
&device_events, obj);
@ -149,14 +151,21 @@ static struct monitor_object *add_object(struct pw_spa_monitor *this, uint32_t i
}
default:
pw_log_error("interface %d not implemented", obj->type);
free(obj->name);
free(obj);
return NULL;
goto error_free_object;
}
spa_list_append(&impl->item_list, &obj->link);
return obj;
error_free_object:
free(obj->name);
free(obj);
error_free_handle:
pw_unload_spa_handle(handle);
error_free_props:
pw_properties_free(props);
return NULL;
}
static struct monitor_object *find_object(struct pw_spa_monitor *this, uint32_t id)
@ -259,6 +268,7 @@ 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_properties *properties,
size_t user_data_size)
{
struct impl *impl;
@ -276,7 +286,7 @@ struct pw_spa_monitor *pw_spa_monitor_load(struct pw_core *core,
handle = pw_load_spa_handle(lib,
factory_name,
NULL,
properties ? &properties->dict : NULL,
n_support, support);
if (handle == NULL)
goto no_mem;
@ -296,6 +306,7 @@ struct pw_spa_monitor *pw_spa_monitor_load(struct pw_core *core,
this->factory_name = strdup(factory_name);
this->system_name = strdup(system_name);
this->handle = handle;
this->properties = properties;
if (user_data_size > 0)
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
@ -330,6 +341,7 @@ void pw_spa_monitor_destroy(struct pw_spa_monitor *monitor)
free(monitor->lib);
free(monitor->factory_name);
free(monitor->system_name);
if (monitor->properties)
pw_properties_free(monitor->properties);
free(impl);
}

View file

@ -40,6 +40,7 @@ struct pw_spa_monitor {
char *factory_name;
char *system_name;
struct spa_handle *handle;
struct pw_properties *properties;
void *user_data;
};
@ -51,6 +52,7 @@ pw_spa_monitor_load(struct pw_core *core,
const char *lib,
const char *factory_name,
const char *system_name,
struct pw_properties *properties,
size_t user_data_size);
void
pw_spa_monitor_destroy(struct pw_spa_monitor *monitor);

View file

@ -27,6 +27,7 @@
#include <spa/debug/types.h>
#include <spa/monitor/utils.h>
#include "pipewire/pipewire.h"
#include "pipewire/device.h"
#include "pipewire/private.h"
#include "pipewire/interfaces.h"
@ -377,12 +378,18 @@ static void node_destroy(void *data)
{
struct node_data *nd = data;
spa_list_remove(&nd->link);
spa_handle_clear(nd->handle);
}
static void node_free(void *data)
{
struct node_data *nd = data;
pw_unload_spa_handle(nd->handle);
}
static const struct pw_node_events node_events = {
PW_VERSION_NODE_EVENTS,
.destroy = node_destroy,
.free = node_free,
};
static void emit_info_changed(struct pw_device *device)
@ -432,11 +439,14 @@ static void device_info(void *data, const struct spa_device_info *info)
static void device_add(struct pw_device *device, uint32_t id,
const struct spa_device_object_info *info)
{
struct pw_core *core = device->core;
const struct spa_support *support;
uint32_t n_support;
struct spa_handle *handle;
struct pw_node *node;
struct node_data *nd;
struct pw_properties *props;
const char *lib;
int res;
void *iface;
@ -444,45 +454,51 @@ static void device_add(struct pw_device *device, uint32_t id,
pw_log_warn("device %p: unknown type %d", device, info->type);
return;
}
if (info->factory == NULL) {
pw_log_warn("device %p: missing factory", device);
if (info->factory_name == NULL) {
pw_log_warn("device %p: missing factory name", device);
return;
}
lib = pw_core_find_spa_lib(core, info->factory_name);
if (lib == NULL) {
pw_log_warn("device %p: unknown library for %s",
device, info->factory_name);
return;
}
pw_log_debug("device %p: add node %d", device, id);
support = pw_core_get_support(device->core, &n_support);
support = pw_core_get_support(core, &n_support);
handle = pw_load_spa_handle(lib, info->factory_name,
info->props, n_support, support);
if (handle == NULL) {
pw_log_warn("device %p: can't load handle %s:%s",
device, lib, info->factory_name);
return;
}
if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) {
pw_log_error("can't get NODE interface: %d", res);
return;
}
props = pw_properties_copy(device->properties);
if (info->props)
pw_properties_update(props, info->props);
node = pw_node_new(device->core,
node = pw_node_new(core,
device->info.name,
props,
sizeof(struct node_data) +
spa_handle_factory_get_size(info->factory, info->props));
sizeof(struct node_data));
nd = pw_node_get_user_data(node);
nd->id = id;
nd->node = node;
nd->handle = SPA_MEMBER(nd, sizeof(struct node_data), void);
nd->handle = handle;
pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
spa_list_append(&device->node_list, &nd->link);
if ((res = spa_handle_factory_init(info->factory,
nd->handle,
info->props,
support,
n_support)) < 0) {
pw_log_error("can't make factory instance: %d", res);
goto error;;
}
if ((res = spa_handle_get_interface(nd->handle, info->type, &iface)) < 0) {
pw_log_error("can't get NODE interface: %d", res);
goto error;;
}
pw_node_set_implementation(node, iface);
if (device->global) {
@ -490,10 +506,6 @@ static void device_add(struct pw_device *device, uint32_t id,
pw_node_set_active(node, true);
}
return;
error:
pw_node_destroy(node);
return;
}
static struct node_data *find_node(struct pw_device *device, uint32_t id)