stream: parse PropInfo and make controls

Parse the PropInfo params and make pw_stream_control elements.
Only emit control changes when something changed.
This commit is contained in:
Wim Taymans 2019-03-18 11:19:08 +01:00
parent a8e9e17159
commit 3049964031
2 changed files with 115 additions and 7 deletions

View file

@ -668,6 +668,8 @@ struct pw_stream {
struct pw_node_proxy *node;
struct spa_hook node_listener;
struct spa_list controls;
};
#define pw_factory_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct pw_factory_events, m, v, ##__VA_ARGS__)

View file

@ -78,6 +78,14 @@ struct param {
struct spa_pod *param;
};
struct control {
uint32_t id;
struct spa_list link;
struct pw_stream_control control;
struct spa_pod *info;
int emitted:1;
};
#define DEFAULT_VOLUME 1.0
struct props {
@ -879,6 +887,16 @@ static void node_event_info(void *object, const struct pw_node_info *info)
}
}
static struct control *find_control(struct pw_stream *stream, uint32_t id)
{
struct control *c;
spa_list_for_each(c, &stream->controls, link) {
if (c->id == id)
return c;
}
return NULL;
}
static void node_event_param(void *object, int seq,
uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
@ -887,19 +905,92 @@ static void node_event_param(void *object, int seq,
switch (id) {
case SPA_PARAM_PropInfo:
pw_log_debug("info");
{
struct control *c;
const struct spa_pod *type, *pod;
uint32_t iid, choice, n_vals;
float *vals, bool_range[3] = { 1.0, 0.0, 1.0 };
c = calloc(1, sizeof(*c) + SPA_POD_SIZE(param));
c->info = SPA_MEMBER(c, sizeof(*c), struct spa_pod);
memcpy(c->info, param, SPA_POD_SIZE(param));
spa_list_append(&stream->controls, &c->link);
if (spa_pod_parse_object(c->info,
SPA_TYPE_OBJECT_PropInfo, NULL,
SPA_PROP_INFO_id, SPA_POD_Id(&iid),
SPA_PROP_INFO_name, SPA_POD_String(&c->control.name),
SPA_PROP_INFO_type, SPA_POD_PodChoice(&type)) < 0)
return;
pod = spa_pod_get_values(type, &n_vals, &choice);
if (spa_pod_is_float(pod))
vals = SPA_POD_BODY(pod);
else if (spa_pod_is_bool(pod) && n_vals > 0) {
choice = SPA_CHOICE_Range;
vals = bool_range;
vals[0] = SPA_POD_VALUE(struct spa_pod_bool, pod);
n_vals = 3;
}
else
return;
switch (choice) {
case SPA_CHOICE_None:
if (n_vals < 1)
return;
c->control.value = c->control.def = c->control.min = c->control.max = vals[0];
break;
case SPA_CHOICE_Range:
if (n_vals < 3)
return;
c->control.value = vals[0];
c->control.def = vals[0];
c->control.min = vals[1];
c->control.max = vals[2];
break;
default:
return;
}
c->id = iid;
pw_log_debug("stream %p: add control %d (%s) (def:%f min:%f max:%f)",
stream, c->id, c->control.name,
c->control.def, c->control.min, c->control.max);
break;
}
case SPA_PARAM_Props:
{
struct spa_pod_prop *prop;
struct spa_pod_object *obj = (struct spa_pod_object *) param;
float value;
union {
float f;
bool b;
} value;
SPA_POD_OBJECT_FOREACH(obj, prop) {
if (spa_pod_get_float(&prop->value, &value) < 0)
struct control *c;
c = find_control(stream, prop->key);
if (c == NULL)
continue;
pw_log_debug("stream %p: control %d changed %f", stream, prop->key, value);
pw_stream_emit_control_changed(stream, prop->key, value);
if (spa_pod_get_float(&prop->value, &value.f) == 0)
;
else if (spa_pod_get_bool(&prop->value, &value.b) == 0)
value.f = value.b ? 1.0 : 0.0;
else
continue;
if (c->control.value == value.f && c->emitted)
continue;
c->control.value = value.f;
c->emitted = true;
pw_log_debug("stream %p: control %d (%s) changed %f", stream,
prop->key, c->control.name, value.f);
pw_stream_emit_control_changed(stream, prop->key, value.f);
}
break;
}
@ -1046,6 +1137,7 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
spa_list_init(&impl->param_list);
spa_hook_list_init(&this->listener_list);
spa_list_init(&this->controls);
this->state = PW_STREAM_STATE_UNCONNECTED;
@ -1124,6 +1216,7 @@ SPA_EXPORT
void pw_stream_destroy(struct pw_stream *stream)
{
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
struct control *c;
pw_log_debug("stream %p: destroy", stream);
@ -1142,6 +1235,11 @@ void pw_stream_destroy(struct pw_stream *stream)
free(stream->name);
spa_list_consume(c, &stream->controls, link) {
spa_list_remove(&c->link);
free(c);
}
if (impl->free_data)
pw_core_destroy(impl->data.core);
@ -1200,7 +1298,7 @@ struct pw_remote *pw_stream_get_remote(struct pw_stream *stream)
return stream->remote;
}
static void add_controls(struct pw_stream *stream)
static void add_params(struct pw_stream *stream)
{
uint8_t buffer[4096];
struct spa_pod_builder b;
@ -1253,7 +1351,7 @@ pw_stream_connect(struct pw_stream *stream,
for (i = 0; i < n_params; i++)
add_param(stream, PARAM_TYPE_INIT, params[i]);
add_controls(stream);
add_params(stream);
stream_set_state(stream, PW_STREAM_STATE_CONNECTING, NULL);
@ -1352,6 +1450,14 @@ int pw_stream_set_control(struct pw_stream *stream, uint32_t id, float value)
SPA_EXPORT
const struct pw_stream_control *pw_stream_get_control(struct pw_stream *stream, uint32_t id)
{
struct control *c;
if (id == 0)
return NULL;
if ((c = find_control(stream, id)))
return &c->control;
return NULL;
}