mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
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:
parent
a8e9e17159
commit
3049964031
2 changed files with 115 additions and 7 deletions
|
|
@ -668,6 +668,8 @@ struct pw_stream {
|
||||||
|
|
||||||
struct pw_node_proxy *node;
|
struct pw_node_proxy *node;
|
||||||
struct spa_hook node_listener;
|
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__)
|
#define pw_factory_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct pw_factory_events, m, v, ##__VA_ARGS__)
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,14 @@ struct param {
|
||||||
struct spa_pod *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
|
#define DEFAULT_VOLUME 1.0
|
||||||
|
|
||||||
struct props {
|
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,
|
static void node_event_param(void *object, int seq,
|
||||||
uint32_t id, uint32_t index, uint32_t next,
|
uint32_t id, uint32_t index, uint32_t next,
|
||||||
const struct spa_pod *param)
|
const struct spa_pod *param)
|
||||||
|
|
@ -887,19 +905,92 @@ static void node_event_param(void *object, int seq,
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case SPA_PARAM_PropInfo:
|
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;
|
break;
|
||||||
|
}
|
||||||
case SPA_PARAM_Props:
|
case SPA_PARAM_Props:
|
||||||
{
|
{
|
||||||
struct spa_pod_prop *prop;
|
struct spa_pod_prop *prop;
|
||||||
struct spa_pod_object *obj = (struct spa_pod_object *) param;
|
struct spa_pod_object *obj = (struct spa_pod_object *) param;
|
||||||
float value;
|
union {
|
||||||
|
float f;
|
||||||
|
bool b;
|
||||||
|
} value;
|
||||||
|
|
||||||
SPA_POD_OBJECT_FOREACH(obj, prop) {
|
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;
|
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;
|
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_list_init(&impl->param_list);
|
||||||
|
|
||||||
spa_hook_list_init(&this->listener_list);
|
spa_hook_list_init(&this->listener_list);
|
||||||
|
spa_list_init(&this->controls);
|
||||||
|
|
||||||
this->state = PW_STREAM_STATE_UNCONNECTED;
|
this->state = PW_STREAM_STATE_UNCONNECTED;
|
||||||
|
|
||||||
|
|
@ -1124,6 +1216,7 @@ SPA_EXPORT
|
||||||
void pw_stream_destroy(struct pw_stream *stream)
|
void pw_stream_destroy(struct pw_stream *stream)
|
||||||
{
|
{
|
||||||
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
|
struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
|
||||||
|
struct control *c;
|
||||||
|
|
||||||
pw_log_debug("stream %p: destroy", stream);
|
pw_log_debug("stream %p: destroy", stream);
|
||||||
|
|
||||||
|
|
@ -1142,6 +1235,11 @@ void pw_stream_destroy(struct pw_stream *stream)
|
||||||
|
|
||||||
free(stream->name);
|
free(stream->name);
|
||||||
|
|
||||||
|
spa_list_consume(c, &stream->controls, link) {
|
||||||
|
spa_list_remove(&c->link);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
|
|
||||||
if (impl->free_data)
|
if (impl->free_data)
|
||||||
pw_core_destroy(impl->data.core);
|
pw_core_destroy(impl->data.core);
|
||||||
|
|
||||||
|
|
@ -1200,7 +1298,7 @@ struct pw_remote *pw_stream_get_remote(struct pw_stream *stream)
|
||||||
return stream->remote;
|
return stream->remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_controls(struct pw_stream *stream)
|
static void add_params(struct pw_stream *stream)
|
||||||
{
|
{
|
||||||
uint8_t buffer[4096];
|
uint8_t buffer[4096];
|
||||||
struct spa_pod_builder b;
|
struct spa_pod_builder b;
|
||||||
|
|
@ -1253,7 +1351,7 @@ pw_stream_connect(struct pw_stream *stream,
|
||||||
for (i = 0; i < n_params; i++)
|
for (i = 0; i < n_params; i++)
|
||||||
add_param(stream, PARAM_TYPE_INIT, 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);
|
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
|
SPA_EXPORT
|
||||||
const struct pw_stream_control *pw_stream_get_control(struct pw_stream *stream, uint32_t id)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue