mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -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;
 | 
								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:
 | 
						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