summaryrefslogtreecommitdiff
path: root/spa/plugins/alsa/alsa-sink.c
diff options
context:
space:
mode:
Diffstat (limited to 'spa/plugins/alsa/alsa-sink.c')
-rw-r--r--spa/plugins/alsa/alsa-sink.c303
1 files changed, 157 insertions, 146 deletions
diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c
index b65fe423..5471a8d0 100644
--- a/spa/plugins/alsa/alsa-sink.c
+++ b/spa/plugins/alsa/alsa-sink.c
@@ -42,20 +42,22 @@ static void reset_props(struct props *props)
props->max_latency = default_max_latency;
}
-static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
+static int impl_node_enum_params(struct spa_node *node,
+ uint32_t id, uint32_t *index,
+ const struct spa_pod_object *filter,
+ struct spa_pod_builder *builder)
{
struct state *this;
- struct spa_pod_builder b = { NULL, };
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
- spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
+ spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
+ spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
- spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
-
- *props = spa_pod_builder_props(&b,
- this->type.props,
+ if (id == this->type.param.idProps) {
+ spa_pod_builder_object(builder,
+ id, this->type.props,
":", this->type.prop_device, "S", this->props.device, sizeof(this->props.device),
":", this->type.prop_device_name, "S", this->props.device_name, sizeof(this->props.device_name),
":", this->type.prop_card_name, "S", this->props.card_name, sizeof(this->props.card_name),
@@ -63,11 +65,15 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
2, 1, INT32_MAX,
":", this->type.prop_max_latency, "ir", this->props.max_latency,
2, 1, INT32_MAX);
+ }
+ else
+ return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
-static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
+static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
+ const struct spa_pod_object *param)
{
struct state *this;
@@ -75,14 +81,18 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct state, node);
- if (props == NULL) {
- reset_props(&this->props);
- return SPA_RESULT_OK;
- } else {
- spa_props_parse(props,
+ if (id == this->type.param.idProps) {
+ if (param == NULL) {
+ reset_props(&this->props);
+ return SPA_RESULT_OK;
+ }
+ spa_pod_object_parse(param,
":", this->type.prop_device, "?S", this->props.device, sizeof(this->props.device),
":", this->type.prop_min_latency, "?i", &this->props.min_latency, NULL);
}
+ else
+ return SPA_RESULT_UNKNOWN_PARAM;
+
return SPA_RESULT_OK;
}
@@ -213,50 +223,149 @@ static int impl_node_remove_port(struct spa_node *node, enum spa_direction direc
}
static int
-impl_node_port_enum_formats(struct spa_node *node,
- enum spa_direction direction,
- uint32_t port_id,
- struct spa_format **format,
- const struct spa_format *filter,
- uint32_t index)
+impl_node_port_get_info(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
{
struct state *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
- spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
+ spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
- return spa_alsa_enum_format(this, format, filter, index);
+ *info = &this->info;
+
+ return SPA_RESULT_OK;
}
-static int clear_buffers(struct state *this)
+static int port_enum_formats(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id,
+ uint32_t *index,
+ const struct spa_pod_object *filter,
+ struct spa_pod_builder *builder)
{
- if (this->n_buffers > 0) {
- spa_list_init(&this->ready);
- this->n_buffers = 0;
- }
+ struct state *this = SPA_CONTAINER_OF(node, struct state, node);
+ return spa_alsa_enum_format(this, index, filter, builder);
+}
+
+static int port_get_format(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id,
+ uint32_t *index,
+ const struct spa_pod_object *filter,
+ struct spa_pod_builder *builder)
+{
+ struct state *this = SPA_CONTAINER_OF(node, struct state, node);
+ struct type *t = &this->type;
+
+ if (!this->have_format)
+ return SPA_RESULT_NO_FORMAT;
+
+ if(*index > 0)
+ return SPA_RESULT_ENUM_END;
+
+ spa_pod_builder_object(builder,
+ t->param.idFormat, t->format,
+ "I", t->media_type.audio,
+ "I", t->media_subtype.raw,
+ ":", t->format_audio.format, "I", this->current_format.info.raw.format,
+ ":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
+ ":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
+
return SPA_RESULT_OK;
}
static int
-impl_node_port_set_format(struct spa_node *node,
- enum spa_direction direction,
- uint32_t port_id,
- uint32_t flags,
- const struct spa_format *format)
+impl_node_port_enum_params(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id,
+ uint32_t id, uint32_t *index,
+ const struct spa_pod_object *filter,
+ struct spa_pod_builder *builder)
{
+
struct state *this;
- int err;
+ struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
+ spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
+ spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
+ t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
+ if (id == t->param.idEnumFormat) {
+ return port_enum_formats(node, direction, port_id, index, filter, builder);
+ }
+ else if (id == t->param.idFormat) {
+ return port_get_format(node, direction, port_id, index, filter, builder);
+ }
+ else if (id == t->param.idBuffers) {
+ if (*index > 0)
+ return SPA_RESULT_ENUM_END;
+
+ spa_pod_builder_object(builder,
+ id, t->param_alloc_buffers.Buffers,
+ ":", t->param_alloc_buffers.size, "iru", this->props.min_latency * this->frame_size,
+ 2, this->props.min_latency * this->frame_size,
+ INT32_MAX,
+ ":", t->param_alloc_buffers.stride, "i", 0,
+ ":", t->param_alloc_buffers.buffers, "ir", 2,
+ 2, 2, MAX_BUFFERS,
+ ":", t->param_alloc_buffers.align, "i", 16);
+ }
+ else if (id == t->param.idMeta) {
+ switch (*index) {
+ case 0:
+ spa_pod_builder_object(builder,
+ id, t->param_alloc_meta_enable.MetaEnable,
+ ":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
+ ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
+ break;
+ case 1:
+ spa_pod_builder_object(builder,
+ id, t->param_alloc_meta_enable.MetaEnable,
+ ":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer,
+ ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer),
+ ":", t->param_alloc_meta_enable.ringbufferSize, "iru",
+ this->props.max_latency * this->frame_size,
+ 2, this->props.min_latency * this->frame_size,
+ this->period_frames * this->frame_size,
+ ":", t->param_alloc_meta_enable.ringbufferStride, "i", 0,
+ ":", t->param_alloc_meta_enable.ringbufferBlocks, "i", 1,
+ ":", t->param_alloc_meta_enable.ringbufferAlign, "i", 16);
+ break;
+ default:
+ return SPA_RESULT_ENUM_END;
+ }
+ }
+ else
+ return SPA_RESULT_UNKNOWN_PARAM;
+
+ (*index)++;
+
+ return SPA_RESULT_OK;
+}
+
+static int clear_buffers(struct state *this)
+{
+ if (this->n_buffers > 0) {
+ spa_list_init(&this->ready);
+ this->n_buffers = 0;
+ }
+ return SPA_RESULT_OK;
+}
+
+static int port_set_format(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id,
+ uint32_t flags,
+ const struct spa_pod_object *format)
+{
+ struct state *this = SPA_CONTAINER_OF(node, struct state, node);
+ int err;
+
if (format == NULL) {
spa_log_info(this->log, "clear format");
spa_alsa_pause(this, false);
@@ -264,9 +373,11 @@ impl_node_port_set_format(struct spa_node *node,
spa_alsa_close(this);
this->have_format = false;
} else {
- struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
- SPA_FORMAT_MEDIA_SUBTYPE(format),
- };
+ struct spa_audio_info info = { 0 };
+
+ spa_pod_object_parse(format,
+ "I", &info.media_type,
+ "I", &info.media_subtype);
if (info.media_type != this->type.media_type.audio ||
info.media_subtype != this->type.media_subtype.raw)
@@ -291,123 +402,26 @@ impl_node_port_set_format(struct spa_node *node,
}
static int
-impl_node_port_get_format(struct spa_node *node,
- enum spa_direction direction,
- uint32_t port_id,
- const struct spa_format **format)
-{
- struct state *this;
- struct spa_pod_builder b = { NULL, };
- struct type *t;
-
- spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
- spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
-
- this = SPA_CONTAINER_OF(node, struct state, node);
- t = &this->type;
-
- spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
-
- if (!this->have_format)
- return SPA_RESULT_NO_FORMAT;
-
- spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
- *format = spa_pod_builder_format(&b,
- t->format,
- t->media_type.audio, t->media_subtype.raw,
- ":", t->format_audio.format, "I", this->current_format.info.raw.format,
- ":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
- ":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
-
- return SPA_RESULT_OK;
-}
-
-static int
-impl_node_port_get_info(struct spa_node *node,
- enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
-{
- struct state *this;
-
- spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
- spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
-
- this = SPA_CONTAINER_OF(node, struct state, node);
-
- spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
-
- *info = &this->info;
-
- return SPA_RESULT_OK;
-}
-
-static int
-impl_node_port_enum_params(struct spa_node *node,
- enum spa_direction direction,
- uint32_t port_id,
- uint32_t index,
- struct spa_param **param)
+impl_node_port_set_param(struct spa_node *node,
+ enum spa_direction direction, uint32_t port_id,
+ uint32_t id, uint32_t flags,
+ const struct spa_pod_object *param)
{
-
struct state *this;
- struct spa_pod_builder b = { NULL };
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
- spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
- spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
-
- switch (index) {
- case 0:
- *param = spa_pod_builder_param(&b,
- t->param_alloc_buffers.Buffers,
- ":", t->param_alloc_buffers.size, "iru", this->props.min_latency * this->frame_size,
- 2, this->props.min_latency * this->frame_size,
- INT32_MAX,
- ":", t->param_alloc_buffers.stride, "i", 0,
- ":", t->param_alloc_buffers.buffers, "ir", 2,
- 2, 2, MAX_BUFFERS,
- ":", t->param_alloc_buffers.align, "i", 16);
- break;
-
- case 1:
- *param = spa_pod_builder_param(&b,
- t->param_alloc_meta_enable.MetaEnable,
- ":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
- ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
- break;
-
- case 2:
- *param = spa_pod_builder_param(&b,
- t->param_alloc_meta_enable.MetaEnable,
- ":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer,
- ":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer),
- ":", t->param_alloc_meta_enable.ringbufferSize, "iru",
- this->props.max_latency * this->frame_size,
- 2, this->props.min_latency * this->frame_size,
- this->period_frames * this->frame_size,
- ":", t->param_alloc_meta_enable.ringbufferStride, "i", 0,
- ":", t->param_alloc_meta_enable.ringbufferBlocks, "i", 1,
- ":", t->param_alloc_meta_enable.ringbufferAlign, "i", 16);
- break;
-
- default:
- return SPA_RESULT_ENUM_END;
+ if (id == t->param.idFormat) {
+ return port_set_format(node, direction, port_id, flags, param);
}
-
- return SPA_RESULT_OK;
-}
-
-static int
-impl_node_port_set_param(struct spa_node *node,
- enum spa_direction direction, uint32_t port_id, const struct spa_param *param)
-{
- return SPA_RESULT_NOT_IMPLEMENTED;
+ else
+ return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@@ -462,7 +476,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
- struct spa_param **params,
+ struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@@ -573,17 +587,14 @@ static const struct spa_dict node_info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&node_info,
- impl_node_get_props,
- impl_node_set_props,
+ impl_node_enum_params,
+ impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
- impl_node_port_enum_formats,
- impl_node_port_set_format,
- impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,