diff --git a/spa/include/spa/debug/pod.h b/spa/include/spa/debug/pod.h index 045f4420f..2c5b14b93 100644 --- a/spa/include/spa/debug/pod.h +++ b/spa/include/spa/debug/pod.h @@ -112,8 +112,7 @@ spa_debug_pod_value(int indent, const struct spa_type_info *info, { struct spa_pod_object_body *b = body; struct spa_pod *p; - const struct spa_type_info *ti; - const struct spa_type_info *ii; + const struct spa_type_info *ti, *ii; ti = spa_debug_type_find(info, b->type); ii = ti ? spa_debug_type_find(ti->values, 0) : NULL; @@ -129,6 +128,30 @@ spa_debug_pod_value(int indent, const struct spa_type_info *info, p->type, SPA_POD_BODY(p), p->size); break; } + case SPA_TYPE_Sequence: + { + struct spa_pod_sequence_body *b = body; + const struct spa_type_info *ti, *ii; + struct spa_pod_control *c; + + ti = spa_debug_type_find(info, b->unit); + + spa_debug("%*s" "Sequence: size %d, unit %s", indent, "", size, + ti ? ti->name : "unknown"); + + SPA_POD_SEQUENCE_BODY_FOREACH(b, size, c) { + ii = spa_debug_type_find(info, c->type); + + spa_debug("%*s" "Event: offset %d, type %s", indent+2, "", + c->offset, ii ? ii->name : "unknown"); + + spa_debug_pod_value(indent + 2, info, + c->value.type, + SPA_POD_CONTENTS(struct spa_pod_control, c), + c->value.size); + } + break; + } case SPA_TYPE_Prop: { struct spa_pod_prop_body *b = body; diff --git a/spa/include/spa/node/io.h b/spa/include/spa/node/io.h index a13261176..c4c4161b7 100644 --- a/spa/include/spa/node/io.h +++ b/spa/include/spa/node/io.h @@ -36,10 +36,11 @@ extern "C" { /** Different IO area types */ enum spa_io_type { SPA_IO_Buffers, - SPA_IO_ControlRange, + SPA_IO_Range, SPA_IO_Clock, SPA_IO_Latency, - SPA_IO_Events, + SPA_IO_Control, + SPA_IO_Notify, }; struct spa_io_buffers { @@ -56,7 +57,7 @@ struct spa_io_buffers { #define SPA_IO_BUFFERS_INIT (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, } /** A range, suitable for input ports that can suggest a range to output ports */ -struct spa_io_control_range { +struct spa_io_range { uint64_t offset; /**< offset in range */ uint32_t min_size; /**< minimum size of data */ uint32_t max_size; /**< maximum size of data */ @@ -79,11 +80,12 @@ struct spa_io_latency { uint64_t max; /**< max latency */ }; -/** event stream */ -struct spa_io_events { +/** control stream */ +struct spa_io_sequence { struct spa_pod_sequence sequence; /**< sequence of timed events */ }; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/param/param.h b/spa/include/spa/param/param.h index 7b8aeda6b..8e604b258 100644 --- a/spa/include/spa/param/param.h +++ b/spa/include/spa/param/param.h @@ -28,14 +28,15 @@ extern "C" { /** different parameter types that can be queried */ enum spa_param_type { - SPA_PARAM_List, /**< available params */ - SPA_PARAM_PropInfo, /**< property information */ - SPA_PARAM_Props, /**< properties */ - SPA_PARAM_EnumFormat, /**< available formats */ - SPA_PARAM_Format, /**< configured format */ - SPA_PARAM_Buffers, /**< buffer configurations */ - SPA_PARAM_Meta, /**< allowed metadata for buffers */ - SPA_PARAM_IO, /**< configurable IO areas */ + SPA_PARAM_START, /**< no value */ + SPA_PARAM_List, /**< available params */ + SPA_PARAM_PropInfo, /**< property information */ + SPA_PARAM_Props, /**< properties */ + SPA_PARAM_EnumFormat, /**< available formats */ + SPA_PARAM_Format, /**< configured format */ + SPA_PARAM_Buffers, /**< buffer configurations */ + SPA_PARAM_Meta, /**< allowed metadata for buffers */ + SPA_PARAM_IO, /**< configurable IO areas */ }; /** Properties for SPA_TYPE_OBJECT_ParamList */ diff --git a/spa/include/spa/param/type-info.h b/spa/include/spa/param/type-info.h index 6f1b8bf85..ab771f66b 100644 --- a/spa/include/spa/param/type-info.h +++ b/spa/include/spa/param/type-info.h @@ -34,6 +34,7 @@ extern "C" { #define SPA_TYPE_PARAM_ID_BASE SPA_TYPE__ParamId ":" static const struct spa_type_info spa_type_param[] = { + { SPA_PARAM_START, "undefined", SPA_TYPE_Int, }, { SPA_PARAM_List, SPA_TYPE_PARAM_ID_BASE "List", SPA_TYPE_Int, }, { SPA_PARAM_PropInfo, SPA_TYPE_PARAM_ID_BASE "PropInfo", SPA_TYPE_Int, }, { SPA_PARAM_Props, SPA_TYPE_PARAM_ID_BASE "Props", SPA_TYPE_Int, }, diff --git a/spa/include/spa/pod/builder.h b/spa/include/spa/pod/builder.h index 674dfbefd..56c8805e0 100644 --- a/spa/include/spa/pod/builder.h +++ b/spa/include/spa/pod/builder.h @@ -371,6 +371,25 @@ spa_pod_builder_push_prop(struct spa_pod_builder *builder, uint32_t key, uint32_ sizeof(p) - sizeof(struct spa_pod))); } +#define SPA_POD_SEQUENCE_INIT(size,unit,...) \ + (struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 }, ##__VA_ARGS__ } + +static inline uint32_t +spa_pod_builder_push_sequence(struct spa_pod_builder *builder, uint32_t unit) +{ + const struct spa_pod_sequence p = + SPA_POD_SEQUENCE_INIT(sizeof(struct spa_pod_sequence_body), unit); + return spa_pod_builder_push(builder, &p.pod, + spa_pod_builder_raw(builder, &p, sizeof(p))); +} + +static inline uint32_t +spa_pod_builder_control_header(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) +{ + const struct { uint32_t offset; uint32_t type; } p = { offset, type }; + return spa_pod_builder_raw(builder, &p, sizeof(p)); +} + static inline uint32_t spa_pod_range_from_id(char id) { switch (id) { @@ -400,6 +419,8 @@ static inline uint32_t spa_pod_flag_from_id(char id) return SPA_POD_PROP_FLAG_DEPRECATED; case 'i': return SPA_POD_PROP_FLAG_INFO; + case 'c': + return SPA_POD_PROP_FLAG_CONTROLLABLE; default: return 0; } @@ -518,6 +539,19 @@ spa_pod_builder_addv(struct spa_pod_builder *builder, case '(': spa_pod_builder_push_array(builder); break; + case '{': + { + uint32_t unit = va_arg(args, uint32_t); + spa_pod_builder_push_sequence(builder, unit); + break; + } + case '.': + { + uint32_t offset = va_arg(args, uint32_t); + uint32_t type = va_arg(args, uint32_t); + spa_pod_builder_control_header(builder, offset, type); + break; + } case ':': { int n_values; @@ -553,7 +587,7 @@ spa_pod_builder_addv(struct spa_pod_builder *builder, /* don't advance format */ continue; } - case ']': case ')': case '>': + case ']': case ')': case '>': case '}': spa_pod_builder_pop(builder); if (builder->state.depth > 0 && builder->frame[builder->state.depth-1].pod.type == SPA_TYPE_Prop) @@ -595,6 +629,12 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, const c #define SPA_POD_PROP(key,spec,type,value,...) \ ":", key, spec, value, ##__VA_ARGS__ +#define SPA_POD_SEQUENCE(unit,...) \ + "{", unit, ##__VA_ARGS__, "}" + +#define SPA_POD_CONTROL(offset,type,...) \ + ".", offset, type, ##__VA_ARGS__ + #define SPA_POD_PROP_MIN_MAX(min,max) 2,(min),(max) #define SPA_POD_PROP_STEP(min,max,step) 3,(min),(max),(step) #define SPA_POD_PROP_ENUM(n_vals,...) (n_vals),__VA_ARGS__ @@ -605,6 +645,9 @@ static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, const c #define spa_pod_builder_struct(b,...) \ spa_pod_builder_add(b, SPA_POD_STRUCT(__VA_ARGS__), NULL) +#define spa_pod_builder_sequence(b,unit,...) \ + spa_pod_builder_add(b, SPA_POD_SEQUENCE(unit,__VA_ARGS__), NULL) + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/pod/iter.h b/spa/include/spa/pod/iter.h index e5ecb3e0a..23548e014 100644 --- a/spa/include/spa/pod/iter.h +++ b/spa/include/spa/pod/iter.h @@ -64,11 +64,21 @@ static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const struc return iter < SPA_MEMBER(pod, size, struct spa_pod); } +static inline bool spa_pod_control_is_inside(const void *pod, uint32_t size, const struct spa_pod_control *iter) +{ + return iter < SPA_MEMBER(pod, size, struct spa_pod_control); +} + static inline struct spa_pod *spa_pod_next(const struct spa_pod *iter) { return SPA_MEMBER(iter, SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), struct spa_pod); } +static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) +{ + return SPA_MEMBER(iter, SPA_ROUND_UP_N (SPA_POD_CONTROL_SIZE (iter), 8), struct spa_pod_control); +} + #define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \ for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_array_body), __typeof__(*(iter))); \ (iter) < SPA_MEMBER((body), (_size), __typeof__(*(iter))); \ @@ -90,6 +100,14 @@ static inline struct spa_pod *spa_pod_next(const struct spa_pod *iter) #define SPA_POD_OBJECT_FOREACH(obj, iter) \ SPA_POD_OBJECT_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) +#define SPA_POD_SEQUENCE_BODY_FOREACH(body, size, iter) \ + for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_sequence_body), struct spa_pod_control); \ + spa_pod_control_is_inside(body, size, iter); \ + (iter) = spa_pod_control_next(iter)) + +#define SPA_POD_SEQUENCE_FOREACH(seq, iter) \ + SPA_POD_SEQUENCE_BODY_FOREACH(&(seq)->body, SPA_POD_BODY_SIZE(seq), iter) + #define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \ for ((iter) = SPA_MEMBER((body), (body)->value.size + \ sizeof(struct spa_pod_prop_body), __typeof__(*iter)); \ diff --git a/spa/include/spa/pod/pod.h b/spa/include/spa/pod/pod.h index f1238ca3b..7f0ccfeb5 100644 --- a/spa/include/spa/pod/pod.h +++ b/spa/include/spa/pod/pod.h @@ -179,6 +179,7 @@ struct spa_pod_prop_body { #define SPA_POD_PROP_FLAG_DEPRECATED (1 << 7) /**< property is deprecated */ #define SPA_POD_PROP_FLAG_INFO (1 << 8) /**< property is informational and is not * used when filtering */ +#define SPA_POD_PROP_FLAG_CONTROLLABLE (1 << 9) /**< property can be controlled */ uint32_t flags; struct spa_pod value; /* array with elements of value.size follows, @@ -190,20 +191,23 @@ struct spa_pod_prop { struct spa_pod_prop_body body; }; -/* events can be inside an event array and mark timed values */ -struct spa_pod_event { - uint64_t offset; - struct spa_pod value; +#define SPA_POD_CONTROL_SIZE(ev) (sizeof(struct spa_pod_control) + (ev)->value.size) + +/* controls can be inside a sequence and mark timed values */ +struct spa_pod_control { + uint32_t offset; /**< media offset */ + uint32_t type; /**< type of control, enum spa_control_type */ + struct spa_pod value; /**< control value, depends on type */ /* value contents follow */ }; struct spa_pod_sequence_body { uint32_t unit; uint32_t pad; - /* array of struct spa_pod_event follows */ + /* series of struct spa_pod_control follows */ }; -/** a sequence of timed events */ +/** a sequence of timed controls */ struct spa_pod_sequence { struct spa_pod pod; struct spa_pod_sequence_body body; diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 542ae2f45..3fbaf7644 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -398,8 +398,8 @@ impl_node_port_enum_params(struct spa_node *node, case 1: param = spa_pod_builder_object(&b, SPA_TYPE_OBJECT_ParamIO, id, - ":", SPA_PARAM_IO_id, "I", SPA_IO_ControlRange, - ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_control_range)); + ":", SPA_PARAM_IO_id, "I", SPA_IO_Range, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range)); break; case 2: param = spa_pod_builder_object(&b, @@ -586,7 +586,7 @@ impl_node_port_set_io(struct spa_node *node, case SPA_IO_Buffers: this->io = data; break; - case SPA_IO_ControlRange: + case SPA_IO_Range: this->range = data; break; case SPA_IO_Clock: diff --git a/spa/plugins/alsa/alsa-utils.h b/spa/plugins/alsa/alsa-utils.h index 7347e84cb..96c593d91 100644 --- a/spa/plugins/alsa/alsa-utils.h +++ b/spa/plugins/alsa/alsa-utils.h @@ -91,7 +91,7 @@ struct state { struct spa_port_info info; struct spa_io_buffers *io; - struct spa_io_control_range *range; + struct spa_io_range *range; struct spa_io_clock *clock; struct buffer buffers[MAX_BUFFERS]; diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 1cc9a0124..4fa3d6904 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -69,10 +69,6 @@ struct link { struct spa_buffer **buffers; }; -struct control { - struct spa_pod_float *volume; -}; - struct impl { struct spa_handle handle; struct spa_node node; @@ -80,7 +76,6 @@ struct impl { struct spa_log *log; struct props props; - struct control control; const struct spa_node_callbacks *callbacks; void *user_data; @@ -653,13 +648,14 @@ impl_node_port_set_io(struct spa_node *node, spa_log_debug(this->log, "set io %d %d %d", id, direction, port_id); - if (id == SPA_IO_ControlRange) + switch (id) { + case SPA_IO_Range: res = spa_node_port_set_io(this->resample, direction, 0, id, data, size); -// else if (id == t->io_prop_volume) -// res = spa_node_port_set_io(this->channelmix, direction, 0, id, data, size); - else + break; + default: res = spa_node_port_set_io(this->fmt[direction], direction, port_id, id, data, size); - + break; + } return res; } diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 920f88022..0d84a997d 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -74,7 +74,7 @@ struct port { bool valid; struct spa_io_buffers *io; - struct spa_io_control_range *ctrl; + struct spa_io_range *ctrl; struct spa_port_info info; struct spa_dict info_props; @@ -837,7 +837,7 @@ impl_node_port_set_io(struct spa_node *node, case SPA_IO_Buffers: port->io = data; break; - case SPA_IO_ControlRange: + case SPA_IO_Range: port->ctrl = data; break; default: diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c index 5c29a6411..7bf356893 100644 --- a/spa/plugins/audioconvert/merger.c +++ b/spa/plugins/audioconvert/merger.c @@ -51,7 +51,7 @@ struct port { uint32_t id; struct spa_io_buffers *io; - struct spa_io_control_range *ctrl; + struct spa_io_range *ctrl; struct spa_port_info info; @@ -787,7 +787,7 @@ impl_node_port_set_io(struct spa_node *node, case SPA_IO_Buffers: port->io = data; break; - case SPA_IO_ControlRange: + case SPA_IO_Range: port->ctrl = data; break; default: diff --git a/spa/plugins/audioconvert/resample.c b/spa/plugins/audioconvert/resample.c index 9674141d0..9e8f9177f 100644 --- a/spa/plugins/audioconvert/resample.c +++ b/spa/plugins/audioconvert/resample.c @@ -60,7 +60,7 @@ struct port { uint32_t id; struct spa_io_buffers *io; - struct spa_io_control_range *ctrl; + struct spa_io_range *ctrl; struct spa_port_info info; bool have_format; @@ -623,13 +623,16 @@ impl_node_port_set_io(struct spa_node *node, port = GET_PORT(this, direction, port_id); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: port->io = data; - else if (id == SPA_IO_ControlRange) + break; + case SPA_IO_Range: port->ctrl = data; - else + break; + default: return -ENOENT; - + } return 0; } diff --git a/spa/plugins/audioconvert/splitter.c b/spa/plugins/audioconvert/splitter.c index 5187427c4..61e3f389b 100644 --- a/spa/plugins/audioconvert/splitter.c +++ b/spa/plugins/audioconvert/splitter.c @@ -51,7 +51,7 @@ struct port { uint32_t id; struct spa_io_buffers *io; - struct spa_io_control_range *ctrl; + struct spa_io_range *ctrl; struct spa_port_info info; @@ -785,13 +785,16 @@ impl_node_port_set_io(struct spa_node *node, port = GET_PORT(this, direction, port_id); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: port->io = data; - else if (id == SPA_IO_ControlRange) + break; + case SPA_IO_Range: port->ctrl = data; - else + break; + default: return -ENOENT; - + } return 0; } diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index cba784f6a..5a749e032 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -66,7 +66,7 @@ struct port { struct port_props props; struct spa_io_buffers *io; - struct spa_io_control_range *io_range; + struct spa_io_range *io_range; double *io_volume; int32_t *io_mute; @@ -472,42 +472,19 @@ impl_node_port_enum_params(struct spa_node *node, case 1: param = spa_pod_builder_object(&b, SPA_TYPE_OBJECT_ParamIO, id, - ":", SPA_PARAM_IO_id, "I", SPA_IO_ControlRange, - ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_control_range)); + ":", SPA_PARAM_IO_id, "I", SPA_IO_Range, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range)); + break; + case 2: + param = spa_pod_builder_object(&b, + SPA_TYPE_OBJECT_ParamIO, id, + ":", SPA_PARAM_IO_id, "I", SPA_IO_Control, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence)); break; default: return 0; } -#if 0 - else if (id == t->param_io.idPropsIn) { - struct port_props *p = &port->props; - - if (direction == SPA_DIRECTION_OUTPUT) - return 0; - - switch (*index) { - case 0: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_volume, - ":", t->param_io.size, "i", sizeof(struct spa_pod_double), - ":", t->param.propId, "I", t->prop_volume, - ":", t->param.propType, "dru", p->volume, - SPA_POD_PROP_MIN_MAX(0.0, 10.0)); - break; - case 1: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_mute, - ":", t->param_io.size, "i", sizeof(struct spa_pod_bool), - ":", t->param.propId, "I", t->prop_mute, - ":", t->param.propType, "b", p->mute); - break; - default: - return 0; - } - } -#endif + break; default: return -ENOENT; } @@ -701,25 +678,16 @@ impl_node_port_set_io(struct spa_node *node, port = GET_PORT(this, direction, port_id); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: port->io = data; - else if (id == SPA_IO_ControlRange) + break; + case SPA_IO_Range: port->io_range = data; -#if 0 - else if (id == t->io_prop_volume && direction == SPA_DIRECTION_INPUT) - if (data && size >= sizeof(struct spa_pod_double)) - port->io_volume = &SPA_POD_VALUE(struct spa_pod_double, data); - else - port->io_volume = &port->props.volume; - else if (id == t->io_prop_mute && direction == SPA_DIRECTION_INPUT) - if (data && size >= sizeof(struct spa_pod_bool)) - port->io_mute = &SPA_POD_VALUE(struct spa_pod_bool, data); - else - port->io_mute = &port->props.mute; -#endif - else + break; + default: return -ENOENT; - + } return 0; } diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 4b84e5bcd..ca19dc164 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -32,6 +32,7 @@ #include #include #include +#include #define NAME "audiotestsrc" @@ -96,7 +97,8 @@ struct impl { struct spa_port_info info; struct spa_io_buffers *io; - struct spa_io_control_range *io_range; + struct spa_io_range *io_range; + struct spa_io_sequence *io_control; uint32_t *io_wave; double *io_freq; @@ -297,7 +299,7 @@ static int make_buffer(struct impl *this) { struct buffer *b; struct spa_io_buffers *io = this->io; - struct spa_io_control_range *range = this->io_range; + struct spa_io_range *range = this->io_range; int n_bytes, n_samples; uint32_t maxsize; void *data; @@ -659,52 +661,19 @@ impl_node_port_enum_params(struct spa_node *node, case 1: param = spa_pod_builder_object(&b, SPA_TYPE_OBJECT_ParamIO, id, - ":", SPA_PARAM_IO_id, "I", SPA_IO_ControlRange, - ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_control_range)); + ":", SPA_PARAM_IO_id, "I", SPA_IO_Range, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range)); + break; + case 2: + param = spa_pod_builder_object(&b, + SPA_TYPE_OBJECT_ParamIO, id, + ":", SPA_PARAM_IO_id, "I", SPA_IO_Control, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence)); break; default: return 0; } break; -#if 0 - else if (id == t->param_io.idPropsIn) { - struct props *p = &this->props; - - switch (*index) { - case 0: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_wave, - ":", t->param_io.size, "i", sizeof(struct spa_pod_id), - ":", SPA_PROP_INFO_id, "I", SPA_PROP_wave, - ":", SPA_PROP_INFO_type, "i", p->wave, - ":", SPA_PROP_INFO_labels, "[-i", - "i", WAVE_SINE, "s", "Sine wave", - "i", WAVE_SQUARE, "s", "Square wave", "]"); - break; - case 1: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_freq, - ":", t->param_io.size, "i", sizeof(struct spa_pod_double), - ":", SPA_PROP_INFO_id, "I", SPA_PROP_freq, - ":", SPA_PROP_INFO_type, "dr", p->freq, - SPA_POD_PROP_MIN_MAX(0.0, 50000000.0)); - break; - case 2: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_volume, - ":", t->param_io.size, "i", sizeof(struct spa_pod_double), - ":", SPA_PROP_INFO_id, "I", SPA_PROP_volume, - ":", SPA_PROP_INFO_type, "dr", p->volume, - SPA_POD_PROP_MIN_MAX(0.0, 10.0)); - break; - default: - return 0; - } - } -#endif default: return -ENOENT; } @@ -880,31 +849,19 @@ impl_node_port_set_io(struct spa_node *node, spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: this->io = data; - else if (id == SPA_IO_ControlRange) + break; + case SPA_IO_Range: this->io_range = data; -#if 0 - else if (id == t->io_prop_wave) { - if (data && size >= sizeof(struct spa_pod_id)) - this->io_wave = &SPA_POD_VALUE(struct spa_pod_id, data); - else - this->io_wave = &this->props.wave; - } - else if (id == t->io_prop_freq) - if (data && size >= sizeof(struct spa_pod_double)) - this->io_freq = &SPA_POD_VALUE(struct spa_pod_double, data); - else - this->io_freq = &this->props.freq; - else if (id == t->io_prop_volume) - if (data && size >= sizeof(struct spa_pod_double)) - this->io_volume = &SPA_POD_VALUE(struct spa_pod_double, data); - else - this->io_volume = &this->props.volume; -#endif - else + break; + case SPA_IO_Control: + this->io_control = data; + break; + default: return -ENOENT; - + } return 0; } @@ -947,6 +904,28 @@ impl_node_port_send_command(struct spa_node *node, return -ENOTSUP; } +static int impl_node_process_control(struct impl *this, struct spa_io_sequence *control) +{ + struct spa_pod_control *c; + + SPA_POD_SEQUENCE_FOREACH(&control->sequence, c) { + switch (c->type) { + case SPA_CONTROL_properties: + { + struct props *p = &this->props; + spa_pod_object_parse(&c->value, + ":",SPA_PROP_frequency, "?d", &p->freq, + ":",SPA_PROP_volume, "?d", &p->volume, + NULL); + break; + } + default: + break; + } + } + return 0; +} + static int impl_node_process(struct spa_node *node) { struct impl *this; @@ -958,6 +937,9 @@ static int impl_node_process(struct spa_node *node) io = this->io; spa_return_val_if_fail(io != NULL, -EIO); + if (this->io_control) + impl_node_process_control(this, this->io_control); + if (io->status == SPA_STATUS_HAVE_BUFFER) return SPA_STATUS_HAVE_BUFFER; diff --git a/spa/plugins/bluez5/a2dp-sink.c b/spa/plugins/bluez5/a2dp-sink.c index 1f6bf01e0..02f1315eb 100644 --- a/spa/plugins/bluez5/a2dp-sink.c +++ b/spa/plugins/bluez5/a2dp-sink.c @@ -82,7 +82,7 @@ struct impl { struct spa_port_info info; struct spa_io_buffers *io; - struct spa_io_control_range *range; + struct spa_io_range *range; struct buffer buffers[MAX_BUFFERS]; unsigned int n_buffers; @@ -1196,7 +1196,7 @@ impl_node_port_set_io(struct spa_node *node, case SPA_IO_Buffers: this->io = data; break; - case SPA_IO_ControlRange: + case SPA_IO_Range: this->range = data; break; default: diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 08f883ea4..5058031ad 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -64,7 +64,7 @@ struct port { struct buffer buffers[MAX_BUFFERS]; uint32_t n_buffers; struct spa_io_buffers *io; - struct spa_io_control_range *range; + struct spa_io_range *range; struct spa_list empty; }; @@ -463,8 +463,8 @@ impl_node_port_enum_params(struct spa_node *node, case 1: param = spa_pod_builder_object(&b, SPA_TYPE_OBJECT_ParamIO, id, - ":", SPA_PARAM_IO_id, "I", SPA_IO_ControlRange, - ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_control_range)); + ":", SPA_PARAM_IO_id, "I", SPA_IO_Range, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range)); break; default: return 0; @@ -625,13 +625,16 @@ impl_node_port_set_io(struct spa_node *node, port = GET_PORT(this, direction, port_id); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: port->io = data; - else if (id == SPA_IO_ControlRange) + break; + case SPA_IO_Range: port->range = data; - else + break; + default: return -ENOENT; - + } return 0; } diff --git a/spa/tests/test-control.c b/spa/tests/test-control.c index cd6e5a732..9b84a342a 100644 --- a/spa/tests/test-control.c +++ b/spa/tests/test-control.c @@ -35,6 +35,7 @@ #include #include #include +#include #define M_PI_M2 ( M_PI + M_PI ) @@ -79,9 +80,8 @@ struct data { struct spa_buffer *source_buffers[1]; struct buffer source_buffer[1]; - struct spa_pod_double ctrl_source_freq; + uint8_t ctrl[1024]; double freq_accum; - struct spa_pod_double ctrl_source_volume; double volume_accum; bool running; @@ -95,7 +95,7 @@ struct data { unsigned int n_fds; }; -#define MIN_LATENCY 64 +#define MIN_LATENCY 1024 #define BUFFER_SIZE MIN_LATENCY @@ -194,12 +194,47 @@ static void on_sink_event(void *data, struct spa_event *event) static void update_props(struct data *data) { - data->ctrl_source_freq.value = ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0; + struct spa_pod_builder b; + struct spa_pod *pod; + + spa_pod_builder_init(&b, data->ctrl, sizeof(data->ctrl)); + +#if 1 + pod = spa_pod_builder_sequence(&b, 0, + ".", 0, SPA_CONTROL_properties, + SPA_POD_OBJECT(SPA_TYPE_OBJECT_Props, 0, + ":", SPA_PROP_frequency, "d", ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0, + ":", SPA_PROP_volume, "d", (sin(data->volume_accum) / 2.0) + 0.5)); +#endif +#if 0 + spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_event_header(&b, 0, SPA_CONTROL_properties); + spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0); + spa_pod_builder_push_prop(&b, SPA_PROP_frequency, 0); + spa_pod_builder_double(&b, ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0); + spa_pod_builder_pop(&b); + spa_pod_builder_push_prop(&b, SPA_PROP_volume, 0); + spa_pod_builder_double(&b, (sin(data->volume_accum) / 2.0) + 0.5); + spa_pod_builder_pop(&b); + spa_pod_builder_pop(&b); + pod = spa_pod_builder_pop(&b); +#endif +#if 0 + spa_pod_builder_push_sequence(&b, 0); + spa_pod_builder_event_header(&b, 0, SPA_CONTROL_properties); + spa_pod_builder_object(&b, + SPA_TYPE_OBJECT_Props, 0, + ":", SPA_PROP_frequency, "d", ((sin(data->freq_accum) + 1.0) * 200.0) + 440.0, + ":", SPA_PROP_volume, "d", (sin(data->volume_accum) / 2.0) + 0.5); + pod = spa_pod_builder_pop(&b); +#endif + + spa_debug_pod(0, spa_types, pod); + data->freq_accum += M_PI_M2 / 880.0; if (data->freq_accum >= M_PI_M2) data->freq_accum -= M_PI_M2; - data->ctrl_source_volume.value = (sin(data->volume_accum) / 2.0) + 0.5; data->volume_accum += M_PI_M2 / 2000.0; if (data->volume_accum >= M_PI_M2) data->volume_accum -= M_PI_M2; @@ -211,6 +246,7 @@ static void on_sink_process(void *_data, int status) update_props(data); + spa_graph_node_process(&data->source_node); spa_graph_node_process(&data->sink_node); } @@ -297,48 +333,15 @@ static int make_nodes(struct data *data, const char *device) ":", SPA_PROP_volume, "d", 0.5, ":", SPA_PROP_live, "b", false); - data->ctrl_source_freq = SPA_POD_DOUBLE_INIT(600.0); - data->ctrl_source_volume = SPA_POD_DOUBLE_INIT(0.5); - if ((res = spa_node_set_param(data->source, SPA_PARAM_Props, 0, props)) < 0) printf("got set_props error %d\n", res); -#if 0 - for (idx = 0;;) { - struct spa_pod *param; - uint32_t id = 0, propId = 0; - - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if ((res = spa_node_port_enum_params(data->source, SPA_DIRECTION_OUTPUT, 0, - data->type.param_io.idPropsIn, &idx, NULL, ¶m, &b)) < 1) { - if (res < 0) - error(0, -res, "port_enum_params"); - break; - } - - spa_pod_object_parse(param, - ":", data->type.param_io.id, "I", &id, - ":", data->type.param.propId, "?I", &propId, - NULL); - - if (propId == data->type.props_freq) { - if ((res = spa_node_port_set_io(data->source, + if ((res = spa_node_port_set_io(data->source, SPA_DIRECTION_OUTPUT, 0, - id, - &data->ctrl_source_freq, sizeof(data->ctrl_source_freq))) < 0) + SPA_IO_Control, + &data->ctrl, sizeof(data->ctrl))) < 0) error(0, -res, "set_io freq"); - } - else if (propId == data->type.props_volume) { - if ((res = spa_node_port_set_io(data->source, - SPA_DIRECTION_OUTPUT, 0, - id, - &data->ctrl_source_volume, sizeof(data->ctrl_source_volume))) < 0) - error(0, -res, "set_io volume"); - } - } -#endif - data->source_sink_io[0] = SPA_IO_BUFFERS_INIT; spa_node_port_set_io(data->source, diff --git a/src/modules/module-client-node/client-stream.c b/src/modules/module-client-node/client-stream.c index 75a11f720..fa63b19b3 100644 --- a/src/modules/module-client-node/client-stream.c +++ b/src/modules/module-client-node/client-stream.c @@ -84,7 +84,7 @@ struct impl { struct pw_port_mix client_port_mix; struct spa_io_buffers *io; - struct spa_io_control_range ctrl; + struct spa_io_range range; struct spa_buffer **buffers; uint32_t n_buffers; @@ -253,9 +253,9 @@ impl_node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t if ((res = spa_node_port_set_io(impl->adapter_mix, direction, port_id, - SPA_IO_ControlRange, - &impl->ctrl, - sizeof(&impl->ctrl))) < 0) + SPA_IO_Range, + &impl->range, + sizeof(&impl->range))) < 0) return res; return res; @@ -745,9 +745,9 @@ static int impl_node_process(struct spa_node *node) struct pw_driver_quantum *q = impl->this.node->driver_node->rt.quantum; int status, trigger; - impl->ctrl.min_size = impl->ctrl.max_size = q->size * sizeof(float); + impl->range.min_size = impl->range.max_size = q->size * sizeof(float); - spa_log_trace(this->log, "%p: process %d", this, impl->ctrl.max_size); + spa_log_trace(this->log, "%p: process %d", this, impl->range.max_size); if (impl->use_converter) { status = spa_node_process(impl->adapter); diff --git a/src/modules/module-media-session/floatmix.c b/src/modules/module-media-session/floatmix.c index 5a70b7295..9de291446 100644 --- a/src/modules/module-media-session/floatmix.c +++ b/src/modules/module-media-session/floatmix.c @@ -70,7 +70,7 @@ struct port { struct port_props props; struct spa_io_buffers *io; - struct spa_io_control_range *ctrl; + struct spa_io_range *range; double *io_volume; int32_t *io_mute; @@ -473,43 +473,19 @@ impl_node_port_enum_params(struct spa_node *node, case 1: param = spa_pod_builder_object(&b, SPA_TYPE_OBJECT_ParamIO, id, - ":", SPA_PARAM_IO_id, "I", SPA_IO_ControlRange, - ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_control_range)); + ":", SPA_PARAM_IO_id, "I", SPA_IO_Range, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range)); + break; + case 2: + param = spa_pod_builder_object(&b, + SPA_TYPE_OBJECT_ParamIO, id, + ":", SPA_PARAM_IO_id, "I", SPA_IO_Control, + ":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence)); break; default: return 0; } break; -#if 0 - else if (id == t->param_io.idPropsIn) { - struct port_props *p = &port->props; - - if (direction == SPA_DIRECTION_OUTPUT) - return 0; - - switch (*index) { - case 0: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_volume, - ":", t->param_io.size, "i", sizeof(struct spa_pod_double), - ":", t->param.propId, "I", t->prop_volume, - ":", t->param.propType, "dru", p->volume, - SPA_POD_PROP_MIN_MAX(0.0, 10.0)); - break; - case 1: - param = spa_pod_builder_object(&b, - id, t->param_io.Prop, - ":", t->param_io.id, "I", t->io_prop_mute, - ":", t->param_io.size, "i", sizeof(struct spa_pod_bool), - ":", t->param.propId, "I", t->prop_mute, - ":", t->param.propType, "b", p->mute); - break; - default: - return 0; - } - } -#endif default: return -ENOENT; } @@ -712,25 +688,16 @@ impl_node_port_set_io(struct spa_node *node, port = GET_PORT(this, direction, port_id); - if (id == SPA_IO_Buffers) + switch (id) { + case SPA_IO_Buffers: port->io = data; - else if (id == SPA_IO_ControlRange) - port->ctrl = data; -#if 0 - else if (id == t->io_prop_volume && direction == SPA_DIRECTION_INPUT) - if (data && size >= sizeof(struct spa_pod_double)) - port->io_volume = &SPA_POD_VALUE(struct spa_pod_double, data); - else - port->io_volume = &port->props.volume; - else if (id == t->io_prop_mute && direction == SPA_DIRECTION_INPUT) - if (data && size >= sizeof(struct spa_pod_bool)) - port->io_mute = &SPA_POD_VALUE(struct spa_pod_bool, data); - else - port->io_mute = &port->props.mute; -#endif - else + break; + case SPA_IO_Range: + port->range = data; + break; + default: return -ENOENT; - + } return 0; } @@ -827,8 +794,8 @@ static int impl_node_process(struct spa_node *node) n_buffers = 0; maxsize = MAX_SAMPLES * sizeof(float); - if (outport->ctrl) - maxsize = SPA_MIN(outport->ctrl->max_size, maxsize); + if (outport->range) + maxsize = SPA_MIN(outport->range->max_size, maxsize); for (i = 0; i < this->last_port; i++) { struct port *inport = GET_IN_PORT(this, i);