mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-10-29 05:40:27 -04:00 
			
		
		
		
	Make scheduler more generic
Add some callbacks to trigger push and pull in a graph Remove the scheduler, make some implementations of graph push/pull functions. Add some properties to jack clients and nodes Fix the parent of the clients. Notify link format changes
This commit is contained in:
		
							parent
							
								
									eba2b82c8e
								
							
						
					
					
						commit
						bece3a013b
					
				
					 20 changed files with 248 additions and 158 deletions
				
			
		|  | @ -31,39 +31,39 @@ extern "C" { | |||
| #define SPA_GRAPH_STATE_CHECK_IN	2 | ||||
| #define SPA_GRAPH_STATE_CHECK_OUT	3 | ||||
| 
 | ||||
| struct spa_graph_scheduler { | ||||
| struct spa_graph_data { | ||||
| 	struct spa_graph *graph; | ||||
|         struct spa_list ready; | ||||
|         struct spa_graph_node *node; | ||||
| }; | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_init(struct spa_graph_scheduler *sched, | ||||
| 					    struct spa_graph *graph) | ||||
| static inline void spa_graph_data_init(struct spa_graph_data *data, | ||||
| 				       struct spa_graph *graph) | ||||
| { | ||||
| 	sched->graph = graph; | ||||
| 	spa_list_init(&sched->ready); | ||||
| 	sched->node = NULL; | ||||
| 	data->graph = graph; | ||||
| 	spa_list_init(&data->ready); | ||||
| 	data->node = NULL; | ||||
| } | ||||
| 
 | ||||
| static inline int spa_graph_scheduler_input(void *data) | ||||
| static inline int spa_graph_node_impl_input(void *data) | ||||
| { | ||||
| 	struct spa_node *n = data; | ||||
| 	return spa_node_process_input(n); | ||||
| } | ||||
| 
 | ||||
| static inline int spa_graph_scheduler_output(void *data) | ||||
| static inline int spa_graph_node_impl_output(void *data) | ||||
| { | ||||
| 	struct spa_node *n = data; | ||||
| 	return spa_node_process_output(n); | ||||
| } | ||||
| 
 | ||||
| static const struct spa_graph_node_callbacks spa_graph_scheduler_default = { | ||||
| static const struct spa_graph_node_callbacks spa_graph_node_impl_default = { | ||||
| 	SPA_VERSION_GRAPH_NODE_CALLBACKS, | ||||
| 	spa_graph_scheduler_input, | ||||
| 	spa_graph_scheduler_output, | ||||
| 	spa_graph_node_impl_input, | ||||
| 	spa_graph_node_impl_output, | ||||
| }; | ||||
| 
 | ||||
| static inline void spa_scheduler_port_check(struct spa_graph_scheduler *sched, struct spa_graph_port *port) | ||||
| static inline void spa_graph_data_port_check(struct spa_graph_data *data, struct spa_graph_port *port) | ||||
| { | ||||
| 	struct spa_graph_node *node = port->node; | ||||
| 
 | ||||
|  | @ -75,23 +75,23 @@ static inline void spa_scheduler_port_check(struct spa_graph_scheduler *sched, s | |||
| 	if (node->required_in > 0 && node->ready_in == node->required_in) { | ||||
| 		node->state = SPA_GRAPH_STATE_IN; | ||||
| 		if (node->ready_link.next == NULL) | ||||
| 			spa_list_insert(sched->ready.prev, &node->ready_link); | ||||
| 			spa_list_insert(data->ready.prev, &node->ready_link); | ||||
| 	} else if (node->ready_link.next) { | ||||
| 		spa_list_remove(&node->ready_link); | ||||
| 		node->ready_link.next = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched) | ||||
| static inline bool spa_graph_data_iterate(struct spa_graph_data *data) | ||||
| { | ||||
| 	bool res; | ||||
| 	int state; | ||||
| 	struct spa_graph_port *p; | ||||
| 	struct spa_graph_node *n; | ||||
| 
 | ||||
| 	res = !spa_list_is_empty(&sched->ready); | ||||
| 	res = !spa_list_is_empty(&data->ready); | ||||
| 	if (res) { | ||||
| 		n = spa_list_first(&sched->ready, struct spa_graph_node, ready_link); | ||||
| 		n = spa_list_first(&data->ready, struct spa_graph_node, ready_link); | ||||
| 
 | ||||
| 		spa_list_remove(&n->ready_link); | ||||
| 		n->ready_link.next = NULL; | ||||
|  | @ -106,9 +106,9 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched | |||
| 			else if (state == SPA_RESULT_HAVE_BUFFER) | ||||
| 				n->state = SPA_GRAPH_STATE_CHECK_OUT; | ||||
| 			debug("node %p processed input state %d\n", n, n->state); | ||||
| 			if (n == sched->node) | ||||
| 			if (n == data->node) | ||||
| 				break; | ||||
| 			spa_list_insert(sched->ready.prev, &n->ready_link); | ||||
| 			spa_list_append(&data->ready, &n->ready_link); | ||||
| 			break; | ||||
| 
 | ||||
| 		case SPA_GRAPH_STATE_OUT: | ||||
|  | @ -118,7 +118,7 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched | |||
| 			else if (state == SPA_RESULT_HAVE_BUFFER) | ||||
| 				n->state = SPA_GRAPH_STATE_CHECK_OUT; | ||||
| 			debug("node %p processed output state %d\n", n, n->state); | ||||
| 			spa_list_insert(sched->ready.prev, &n->ready_link); | ||||
| 			spa_list_append(&data->ready, &n->ready_link); | ||||
| 			break; | ||||
| 
 | ||||
| 		case SPA_GRAPH_STATE_CHECK_IN: | ||||
|  | @ -126,10 +126,10 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched | |||
| 			spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 				struct spa_graph_node *pn = p->peer->node; | ||||
| 				if (p->io->status == SPA_RESULT_NEED_BUFFER) { | ||||
| 					if (pn != sched->node | ||||
| 					if (pn != data->node | ||||
| 					    || pn->flags & SPA_GRAPH_NODE_FLAG_ASYNC) { | ||||
| 						pn->state = SPA_GRAPH_STATE_OUT; | ||||
| 						spa_list_insert(sched->ready.prev, | ||||
| 						spa_list_append(&data->ready, | ||||
| 								&pn->ready_link); | ||||
| 					} | ||||
| 				} else if (p->io->status == SPA_RESULT_OK) | ||||
|  | @ -137,35 +137,52 @@ static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched | |||
| 			} | ||||
| 		case SPA_GRAPH_STATE_CHECK_OUT: | ||||
| 			spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) | ||||
| 				spa_scheduler_port_check(sched, p->peer); | ||||
| 				spa_graph_data_port_check(data, p->peer); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 		res = !spa_list_is_empty(&sched->ready); | ||||
| 		res = !spa_list_is_empty(&data->ready); | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, struct spa_graph_node *node) | ||||
| static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *node) | ||||
| { | ||||
| 	struct spa_graph_data *d = data; | ||||
| 	debug("node %p start pull\n", node); | ||||
| 	node->state = SPA_GRAPH_STATE_CHECK_IN; | ||||
| 	sched->node = node; | ||||
| 	d->node = node; | ||||
| 	if (node->ready_link.next == NULL) | ||||
| 		spa_list_insert(sched->ready.prev, &node->ready_link); | ||||
| 		spa_list_append(&d->ready, &node->ready_link); | ||||
| 
 | ||||
| 	while(spa_graph_data_iterate(data)); | ||||
| 
 | ||||
| 	return SPA_RESULT_OK; | ||||
| } | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node) | ||||
| static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node *node) | ||||
| { | ||||
| 	struct spa_graph_data *d = data; | ||||
| 	debug("node %p start push\n", node); | ||||
| 	node->state = SPA_GRAPH_STATE_OUT; | ||||
| 	sched->node = node; | ||||
| 	d->node = node; | ||||
| 	if (node->ready_link.next == NULL) | ||||
| 		spa_list_insert(sched->ready.prev, &node->ready_link); | ||||
| 		spa_list_append(&d->ready, &node->ready_link); | ||||
| 
 | ||||
| 	while(spa_graph_data_iterate(data)); | ||||
| 
 | ||||
| 	return SPA_RESULT_OK; | ||||
| } | ||||
| 
 | ||||
| static const struct spa_graph_callbacks spa_graph_impl_default = { | ||||
| 	SPA_VERSION_GRAPH_CALLBACKS, | ||||
| 	.need_input = spa_graph_impl_need_input, | ||||
| 	.have_output = spa_graph_impl_have_output, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| }  /* extern "C" */ | ||||
| #endif | ||||
|  |  | |||
|  | @ -26,37 +26,26 @@ extern "C" { | |||
| 
 | ||||
| #include <spa/graph.h> | ||||
| 
 | ||||
| struct spa_graph_scheduler { | ||||
| 	struct spa_graph *graph; | ||||
| }; | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_init(struct spa_graph_scheduler *sched, | ||||
| 					    struct spa_graph *graph) | ||||
| { | ||||
| 	sched->graph = graph; | ||||
| } | ||||
| 
 | ||||
| static inline int spa_graph_node_scheduler_input(void *data) | ||||
| static inline int spa_graph_node_impl_input(void *data) | ||||
| { | ||||
| 	struct spa_node *n = data; | ||||
| 	return spa_node_process_input(n); | ||||
| } | ||||
| 
 | ||||
| static inline int spa_graph_node_scheduler_output(void *data) | ||||
| static inline int spa_graph_node_impl_output(void *data) | ||||
| { | ||||
| 	struct spa_node *n = data; | ||||
| 	return spa_node_process_output(n); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static const struct spa_graph_node_callbacks spa_graph_node_scheduler_default = { | ||||
| static const struct spa_graph_node_callbacks spa_graph_node_impl_default = { | ||||
| 	SPA_VERSION_GRAPH_NODE_CALLBACKS, | ||||
| 	spa_graph_node_scheduler_input, | ||||
| 	spa_graph_node_scheduler_output, | ||||
| 	spa_graph_node_impl_input, | ||||
| 	spa_graph_node_impl_output, | ||||
| }; | ||||
| 
 | ||||
| static inline int spa_graph_port_scheduler_reuse_buffer(void *data, | ||||
| 							uint32_t buffer_id) | ||||
| static inline int spa_graph_port_impl_reuse_buffer(void *data, | ||||
| 						   uint32_t buffer_id) | ||||
| { | ||||
| 	struct spa_graph_port *port = data; | ||||
| 	struct spa_node *node = port->node->callbacks_data; | ||||
|  | @ -64,12 +53,12 @@ static inline int spa_graph_port_scheduler_reuse_buffer(void *data, | |||
| 	return spa_node_port_reuse_buffer(node, port->port_id, buffer_id); | ||||
| } | ||||
| 
 | ||||
| static const struct spa_graph_port_callbacks spa_graph_port_scheduler_default = { | ||||
| static const struct spa_graph_port_callbacks spa_graph_port_impl_default = { | ||||
| 	SPA_VERSION_GRAPH_PORT_CALLBACKS, | ||||
| 	spa_graph_port_scheduler_reuse_buffer, | ||||
| 	spa_graph_port_impl_reuse_buffer, | ||||
| }; | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, struct spa_graph_node *node) | ||||
| static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *node) | ||||
| { | ||||
| 	struct spa_graph_port *p; | ||||
| 	struct spa_graph_node *n, *t; | ||||
|  | @ -99,7 +88,7 @@ static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, s | |||
| 		n->state = n->callbacks->process_output(n->callbacks_data); | ||||
| 		debug("peer %p processed out %d\n", n, n->state); | ||||
| 		if (n->state == SPA_RESULT_NEED_BUFFER) | ||||
| 			spa_graph_scheduler_pull(sched, n); | ||||
| 			spa_graph_need_input(n->graph, n); | ||||
| 		else { | ||||
| 			spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) { | ||||
| 				if (p->io->status == SPA_RESULT_HAVE_BUFFER) | ||||
|  | @ -123,43 +112,14 @@ static inline void spa_graph_scheduler_pull(struct spa_graph_scheduler *sched, s | |||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return SPA_RESULT_OK; | ||||
| } | ||||
| 
 | ||||
| static inline bool spa_graph_scheduler_iterate(struct spa_graph_scheduler *sched) | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node); | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_chain(struct spa_graph_scheduler *sched, | ||||
| 					     struct spa_list *ready) | ||||
| { | ||||
| 	struct spa_graph_node *n, *t; | ||||
| 	struct spa_graph_port *p; | ||||
| 
 | ||||
| 
 | ||||
| 	spa_list_for_each_safe(n, t, ready, ready_link) { | ||||
| 		n->state = n->callbacks->process_input(n->callbacks_data); | ||||
| 		debug("node %p chain processed in %d\n", n, n->state); | ||||
| 		if (n->state == SPA_RESULT_HAVE_BUFFER) | ||||
| 			spa_graph_scheduler_push(sched, n); | ||||
| 		else { | ||||
| 			n->ready_in = 0; | ||||
| 			spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 				if (p->io->status == SPA_RESULT_OK && !(n->flags & SPA_GRAPH_NODE_FLAG_ASYNC)) | ||||
| 			                n->ready_in++; | ||||
| 			} | ||||
| 		} | ||||
| 		spa_list_remove(&n->ready_link); | ||||
| 		n->ready_link.next = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, struct spa_graph_node *node) | ||||
| static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node *node) | ||||
| { | ||||
| 	struct spa_graph_port *p; | ||||
| 	struct spa_list ready; | ||||
| 	struct spa_graph_node *n, *t; | ||||
| 
 | ||||
| 	debug("node %p start push\n", node); | ||||
| 
 | ||||
|  | @ -182,7 +142,22 @@ static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, s | |||
| 				spa_list_append(&ready, &pnode->ready_link); | ||||
| 	} | ||||
| 
 | ||||
| 	spa_graph_scheduler_chain(sched, &ready); | ||||
| 	spa_list_for_each_safe(n, t, &ready, ready_link) { | ||||
| 		n->state = n->callbacks->process_input(n->callbacks_data); | ||||
| 		debug("node %p chain processed in %d\n", n, n->state); | ||||
| 		if (n->state == SPA_RESULT_HAVE_BUFFER) | ||||
| 			spa_graph_have_output(n->graph, n); | ||||
| 		else { | ||||
| 			n->ready_in = 0; | ||||
| 			spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 				if (p->io->status == SPA_RESULT_OK && | ||||
| 				    !(n->flags & SPA_GRAPH_NODE_FLAG_ASYNC)) | ||||
| 			                n->ready_in++; | ||||
| 			} | ||||
| 		} | ||||
| 		spa_list_remove(&n->ready_link); | ||||
| 		n->ready_link.next = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	node->state = node->callbacks->process_output(node->callbacks_data); | ||||
| 	debug("node %p processed out %d\n", node, node->state); | ||||
|  | @ -193,8 +168,16 @@ static inline void spa_graph_scheduler_push(struct spa_graph_scheduler *sched, s | |||
| 				node->ready_in++; | ||||
| 		} | ||||
| 	} | ||||
| 	return SPA_RESULT_OK; | ||||
| } | ||||
| 
 | ||||
| static const struct spa_graph_callbacks spa_graph_impl_default = { | ||||
| 	SPA_VERSION_GRAPH_CALLBACKS, | ||||
| 	.need_input = spa_graph_impl_need_input, | ||||
| 	.have_output = spa_graph_impl_have_output, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| }  /* extern "C" */ | ||||
| #endif | ||||
|  |  | |||
|  | @ -40,10 +40,23 @@ struct spa_graph; | |||
| struct spa_graph_node; | ||||
| struct spa_graph_port; | ||||
| 
 | ||||
| struct spa_graph_callbacks { | ||||
| #define SPA_VERSION_GRAPH_CALLBACKS	0 | ||||
| 	uint32_t version; | ||||
| 
 | ||||
| 	int (*need_input) (void *data, struct spa_graph_node *node); | ||||
| 	int (*have_output) (void *data, struct spa_graph_node *node); | ||||
| }; | ||||
| 
 | ||||
| struct spa_graph { | ||||
| 	struct spa_list nodes; | ||||
| 	const struct spa_graph_callbacks *callbacks; | ||||
| 	void *callbacks_data; | ||||
| }; | ||||
| 
 | ||||
| #define spa_graph_need_input(g,n)	((g)->callbacks->need_input((g)->callbacks_data, (n))) | ||||
| #define spa_graph_have_output(g,n)	((g)->callbacks->have_output((g)->callbacks_data, (n))) | ||||
| 
 | ||||
| struct spa_graph_node_callbacks { | ||||
| #define SPA_VERSION_GRAPH_NODE_CALLBACKS	0 | ||||
| 	uint32_t version; | ||||
|  | @ -61,6 +74,7 @@ struct spa_graph_port_callbacks { | |||
| 
 | ||||
| struct spa_graph_node { | ||||
| 	struct spa_list link;		/**< link in graph nodes list */ | ||||
| 	struct spa_graph *graph;	/**< owner graph */ | ||||
| 	struct spa_list ports[2];	/**< list of input and output ports */ | ||||
| 	struct spa_list ready_link;	/**< link for scheduler */ | ||||
| #define SPA_GRAPH_NODE_FLAG_ASYNC       (1 << 0) | ||||
|  | @ -93,6 +107,15 @@ static inline void spa_graph_init(struct spa_graph *graph) | |||
| 	spa_list_init(&graph->nodes); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| spa_graph_set_callbacks(struct spa_graph *graph, | ||||
| 			const struct spa_graph_callbacks *callbacks, | ||||
| 			void *data) | ||||
| { | ||||
| 	graph->callbacks = callbacks; | ||||
| 	graph->callbacks_data = data; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| spa_graph_node_init(struct spa_graph_node *node) | ||||
| { | ||||
|  | @ -116,6 +139,7 @@ static inline void | |||
| spa_graph_node_add(struct spa_graph *graph, | ||||
| 		   struct spa_graph_node *node) | ||||
| { | ||||
| 	node->graph = graph; | ||||
| 	node->state = SPA_RESULT_NEED_BUFFER; | ||||
| 	node->ready_link.next = NULL; | ||||
| 	spa_list_append(&graph->nodes, &node->link); | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ struct data { | |||
| 	uint32_t n_support; | ||||
| 
 | ||||
| 	struct spa_graph graph; | ||||
| 	struct spa_graph_scheduler sched; | ||||
| 	struct spa_graph_data graph_data; | ||||
| 	struct spa_graph_node source_node; | ||||
| 	struct spa_graph_port source_out; | ||||
| 	struct spa_graph_port volume_in; | ||||
|  | @ -230,10 +230,7 @@ static void on_sink_event(void *data, struct spa_event *event) | |||
| static void on_sink_need_input(void *_data) | ||||
| { | ||||
| 	struct data *data = _data; | ||||
| 
 | ||||
| 	spa_graph_scheduler_pull(&data->sched, &data->sink_node); | ||||
| 
 | ||||
| 	while (spa_graph_scheduler_iterate(&data->sched)); | ||||
| 	spa_graph_need_input(&data->graph, &data->sink_node); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
|  | @ -340,13 +337,13 @@ static int make_nodes(struct data *data, const char *device) | |||
| 	spa_node_port_set_io(data->sink, SPA_DIRECTION_INPUT, 0, &data->volume_sink_io[0]); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->source_node); | ||||
| 	spa_graph_node_set_callbacks(&data->source_node, &spa_graph_scheduler_default, data->source); | ||||
| 	spa_graph_node_set_callbacks(&data->source_node, &spa_graph_node_impl_default, data->source); | ||||
| 	spa_graph_node_add(&data->graph, &data->source_node); | ||||
| 	spa_graph_port_init(&data->source_out, SPA_DIRECTION_OUTPUT, 0, 0, &data->source_volume_io[0]); | ||||
| 	spa_graph_port_add(&data->source_node, &data->source_out); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->volume_node); | ||||
| 	spa_graph_node_set_callbacks(&data->volume_node, &spa_graph_scheduler_default, data->volume); | ||||
| 	spa_graph_node_set_callbacks(&data->volume_node, &spa_graph_node_impl_default, data->volume); | ||||
| 	spa_graph_node_add(&data->graph, &data->volume_node); | ||||
| 	spa_graph_port_init(&data->volume_in, SPA_DIRECTION_INPUT, 0, 0, &data->source_volume_io[0]); | ||||
| 	spa_graph_port_add(&data->volume_node, &data->volume_in); | ||||
|  | @ -357,7 +354,7 @@ static int make_nodes(struct data *data, const char *device) | |||
| 	spa_graph_port_add(&data->volume_node, &data->volume_out); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->sink_node); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_scheduler_default, data->sink); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_node_impl_default, data->sink); | ||||
| 	spa_graph_node_add(&data->graph, &data->sink_node); | ||||
| 	spa_graph_port_init(&data->sink_in, SPA_DIRECTION_INPUT, 0, 0, &data->volume_sink_io[0]); | ||||
| 	spa_graph_port_add(&data->sink_node, &data->sink_in); | ||||
|  | @ -532,7 +529,8 @@ int main(int argc, char *argv[]) | |||
| 
 | ||||
| 
 | ||||
| 	spa_graph_init(&data.graph); | ||||
| 	spa_graph_scheduler_init(&data.sched, &data.graph); | ||||
| 	spa_graph_data_init(&data.graph_data, &data.graph); | ||||
| 	spa_graph_set_callbacks(&data.graph, &spa_graph_impl_default, &data.graph_data); | ||||
| 
 | ||||
| 	data.map = &default_map.map; | ||||
| 	data.log = &default_log.log; | ||||
|  |  | |||
|  | @ -100,7 +100,7 @@ struct data { | |||
| 	uint32_t n_support; | ||||
| 
 | ||||
| 	struct spa_graph graph; | ||||
| 	struct spa_graph_scheduler sched; | ||||
| 	struct spa_graph_data graph_data; | ||||
| 	struct spa_graph_node source1_node; | ||||
| 	struct spa_graph_port source1_out; | ||||
| 	struct spa_graph_node source2_node; | ||||
|  | @ -242,9 +242,7 @@ static void on_sink_need_input(void *_data) | |||
| { | ||||
| 	struct data *data = _data; | ||||
| #ifdef USE_GRAPH | ||||
| 	spa_graph_scheduler_pull(&data->sched, &data->sink_node); | ||||
| 	while (spa_graph_scheduler_iterate(&data->sched)); | ||||
| 
 | ||||
| 	spa_graph_need_input(&data->graph, &data->sink_node); | ||||
| #else | ||||
| 	int res; | ||||
| 
 | ||||
|  | @ -416,19 +414,19 @@ static int make_nodes(struct data *data, const char *device) | |||
| 
 | ||||
| #ifdef USE_GRAPH | ||||
| 	spa_graph_node_init(&data->source1_node); | ||||
| 	spa_graph_node_set_callbacks(&data->source1_node, &spa_graph_scheduler_default, data->source1); | ||||
| 	spa_graph_node_set_callbacks(&data->source1_node, &spa_graph_node_impl_default, data->source1); | ||||
| 	spa_graph_port_init(&data->source1_out, SPA_DIRECTION_OUTPUT, 0, 0, &data->source1_mix_io[0]); | ||||
| 	spa_graph_port_add(&data->source1_node, &data->source1_out); | ||||
| 	spa_graph_node_add(&data->graph, &data->source1_node); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->source2_node); | ||||
| 	spa_graph_node_set_callbacks(&data->source2_node, &spa_graph_scheduler_default, data->source2); | ||||
| 	spa_graph_node_set_callbacks(&data->source2_node, &spa_graph_node_impl_default, data->source2); | ||||
| 	spa_graph_port_init(&data->source2_out, SPA_DIRECTION_OUTPUT, 0, 0, &data->source2_mix_io[0]); | ||||
| 	spa_graph_port_add(&data->source2_node, &data->source2_out); | ||||
| 	spa_graph_node_add(&data->graph, &data->source2_node); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->mix_node); | ||||
| 	spa_graph_node_set_callbacks(&data->mix_node, &spa_graph_scheduler_default, data->mix); | ||||
| 	spa_graph_node_set_callbacks(&data->mix_node, &spa_graph_node_impl_default, data->mix); | ||||
| 	spa_graph_port_init(&data->mix_in[0], SPA_DIRECTION_INPUT, | ||||
| 			    data->mix_ports[0], 0, &data->source1_mix_io[0]); | ||||
| 	spa_graph_port_add(&data->mix_node, &data->mix_in[0]); | ||||
|  | @ -444,7 +442,7 @@ static int make_nodes(struct data *data, const char *device) | |||
| 	spa_graph_port_add(&data->mix_node, &data->mix_out); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->sink_node); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_scheduler_default, data->sink); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_node_impl_default, data->sink); | ||||
| 	spa_graph_port_init(&data->sink_in, SPA_DIRECTION_INPUT, 0, 0, &data->mix_sink_io[0]); | ||||
| 	spa_graph_port_add(&data->sink_node, &data->sink_in); | ||||
| 	spa_graph_node_add(&data->graph, &data->sink_node); | ||||
|  | @ -651,7 +649,8 @@ int main(int argc, char *argv[]) | |||
| 	data.data_loop.invoke = do_invoke; | ||||
| 
 | ||||
| 	spa_graph_init(&data.graph); | ||||
| 	spa_graph_scheduler_init(&data.sched, &data.graph); | ||||
| 	spa_graph_data_init(&data.graph_data, &data.graph); | ||||
| 	spa_graph_set_callbacks(&data.graph, &spa_graph_impl_default, &data.graph_data); | ||||
| 
 | ||||
| 	if ((str = getenv("SPA_DEBUG"))) | ||||
| 		data.log->level = atoi(str); | ||||
|  |  | |||
|  | @ -103,7 +103,7 @@ struct data { | |||
| 	int iterations; | ||||
| 
 | ||||
| 	struct spa_graph graph; | ||||
| 	struct spa_graph_scheduler sched; | ||||
| 	struct spa_graph_data graph_data; | ||||
| 	struct spa_graph_node source_node; | ||||
| 	struct spa_graph_port source_out; | ||||
| 	struct spa_graph_port sink_in; | ||||
|  | @ -225,8 +225,7 @@ static void on_sink_pull(struct data *data) | |||
| 		spa_node_process_output(data->source); | ||||
| 		spa_node_process_input(data->sink); | ||||
| 	} else { | ||||
| 		spa_graph_scheduler_pull(&data->sched, &data->sink_node); | ||||
| 		while (spa_graph_scheduler_iterate(&data->sched)); | ||||
| 		spa_graph_need_input(&data->graph, &data->sink_node); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -237,8 +236,7 @@ static void on_source_push(struct data *data) | |||
| 		spa_node_process_output(data->source); | ||||
| 		spa_node_process_input(data->sink); | ||||
| 	} else { | ||||
| 		spa_graph_scheduler_push(&data->sched, &data->source_node); | ||||
| 		while (spa_graph_scheduler_iterate(&data->sched)); | ||||
| 		spa_graph_have_output(&data->graph, &data->source_node); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -364,7 +362,7 @@ static int make_nodes(struct data *data) | |||
| 	spa_node_port_set_io(data->sink, SPA_DIRECTION_INPUT, 0, &data->source_sink_io[0]); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->source_node); | ||||
| 	spa_graph_node_set_callbacks(&data->source_node, &spa_graph_scheduler_default, data->source); | ||||
| 	spa_graph_node_set_callbacks(&data->source_node, &spa_graph_node_impl_default, data->source); | ||||
| 	spa_graph_node_add(&data->graph, &data->source_node); | ||||
| 
 | ||||
| 	data->source_node.flags = (data->mode & MODE_ASYNC_PUSH) ? SPA_GRAPH_NODE_FLAG_ASYNC : 0; | ||||
|  | @ -372,7 +370,7 @@ static int make_nodes(struct data *data) | |||
| 	spa_graph_port_add(&data->source_node, &data->source_out); | ||||
| 
 | ||||
| 	spa_graph_node_init(&data->sink_node); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_scheduler_default, data->sink); | ||||
| 	spa_graph_node_set_callbacks(&data->sink_node, &spa_graph_node_impl_default, data->sink); | ||||
| 	spa_graph_node_add(&data->graph, &data->sink_node); | ||||
| 
 | ||||
| 	data->sink_node.flags = (data->mode & MODE_ASYNC_PULL) ? SPA_GRAPH_NODE_FLAG_ASYNC : 0; | ||||
|  | @ -529,7 +527,8 @@ int main(int argc, char *argv[]) | |||
| 	const char *str; | ||||
| 
 | ||||
| 	spa_graph_init(&data.graph); | ||||
| 	spa_graph_scheduler_init(&data.sched, &data.graph); | ||||
| 	spa_graph_data_init(&data.graph_data, &data.graph); | ||||
| 	spa_graph_set_callbacks(&data.graph, &spa_graph_impl_default, &data.graph_data); | ||||
| 
 | ||||
| 	data.map = &default_map.map; | ||||
| 	data.log = &default_log.log; | ||||
|  |  | |||
|  | @ -340,16 +340,17 @@ handle_activate_client(struct client *client) | |||
| 	jack_graph_manager_next_stop(mgr); | ||||
| 
 | ||||
| 	jc = server->client_table[ref_num]; | ||||
| 	if (jc) | ||||
| 	if (jc) { | ||||
| 		notify_client(jc, ref_num, NULL, jack_notify_ActivateClient, true, "", 0, 0); | ||||
| 		jc->activated = true; | ||||
| 		spa_list_append(&impl->rt.nodes, &jc->node->graph_link); | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) | ||||
| 		notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", input_ports[i], 0); | ||||
| 	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) | ||||
| 		notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", output_ports[i], 0); | ||||
| 
 | ||||
| 	jc->activated = true; | ||||
| 
 | ||||
| 	CheckWrite(&result, sizeof(int)); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -400,8 +401,10 @@ static int client_deactivate(struct impl *impl, int ref_num) | |||
| 	jack_graph_manager_next_stop(mgr); | ||||
| 
 | ||||
| 	jc = server->client_table[ref_num]; | ||||
| 	if (jc) | ||||
| 	if (jc) { | ||||
| 		jc->activated = false; | ||||
| 		spa_list_remove(&jc->node->graph_link); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -516,6 +519,7 @@ handle_client_open(struct client *client) | |||
| 	const struct ucred *ucred; | ||||
| 	struct sockaddr_un addr; | ||||
| 	struct pw_jack_node *node; | ||||
| 	struct pw_properties *properties; | ||||
| 
 | ||||
| 	CheckSize(kClientOpen_size); | ||||
| 	CheckRead(&PID, sizeof(int)); | ||||
|  | @ -524,12 +528,16 @@ handle_client_open(struct client *client) | |||
| 
 | ||||
| 	ucred = pw_client_get_ucred(client->client); | ||||
| 
 | ||||
| 	properties = pw_properties_new(NULL, NULL); | ||||
| 	pw_properties_setf(properties, "application.jack.PID", "%d", PID); | ||||
| 	pw_properties_setf(properties, "application.jack.UUID", "%d", UUID); | ||||
| 
 | ||||
| 	node = pw_jack_node_new(impl->core, | ||||
| 				pw_module_get_global(impl->module), | ||||
| 				pw_client_get_global(client->client), | ||||
| 				server, | ||||
| 				name, | ||||
| 				ucred ? ucred->pid : PID, | ||||
| 				NULL, | ||||
| 				properties, | ||||
| 				sizeof(struct jack_client)); | ||||
| 	if (node == NULL) { | ||||
| 		pw_log_error("module-jack %p: can't create node", impl); | ||||
|  | @ -563,7 +571,6 @@ handle_client_open(struct client *client) | |||
| 	pw_log_debug("module-jack %p: Added client %d \"%s\"", impl, ref_num, name); | ||||
| 
 | ||||
| 	spa_list_append(&client->jack_clients, &jc->client_link); | ||||
| 	spa_list_append(&impl->rt.nodes, &jc->node->graph_link); | ||||
| 
 | ||||
| 	if (notify_add_client(impl, jc, name, ref_num) < 0) { | ||||
| 		pw_log_error("module-jack %p: can't notify add_client", impl); | ||||
|  | @ -949,6 +956,7 @@ static struct client *client_new(struct impl *impl, int fd) | |||
| 	struct pw_client *client; | ||||
| 	socklen_t len; | ||||
| 	struct ucred ucred, *ucredp; | ||||
| 	struct pw_properties *properties; | ||||
| 
 | ||||
| 	len = sizeof(ucred); | ||||
| 	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { | ||||
|  | @ -958,8 +966,17 @@ static struct client *client_new(struct impl *impl, int fd) | |||
| 		ucredp = &ucred; | ||||
| 	} | ||||
| 
 | ||||
| 	properties = pw_properties_new("pipewire.protocol", "protocol-jack", NULL); | ||||
| 	if (properties == NULL) | ||||
| 		goto no_props; | ||||
| 
 | ||||
| 	if (ucredp) { | ||||
| 		pw_properties_setf(properties, "application.process.id", "%d", ucredp->pid); | ||||
| 		pw_properties_setf(properties, "application.process.userid", "%d", ucredp->uid); | ||||
| 	} | ||||
| 
 | ||||
|         client = pw_client_new(impl->core, pw_module_get_global(impl->module), | ||||
| 			       ucredp, NULL, sizeof(struct client)); | ||||
| 			       ucredp, properties, sizeof(struct client)); | ||||
| 	if (client == NULL) | ||||
| 		goto no_client; | ||||
| 
 | ||||
|  | @ -984,6 +1001,7 @@ static struct client *client_new(struct impl *impl, int fd) | |||
| 
 | ||||
|       no_source: | ||||
| 	free(this); | ||||
|       no_props: | ||||
|       no_client: | ||||
| 	return NULL; | ||||
| } | ||||
|  | @ -1018,6 +1036,7 @@ static void jack_node_pull(void *data) | |||
|                        do_notify, 0, sizeof(notify), ¬ify, false, impl); | ||||
| 	} | ||||
| 
 | ||||
| 	/* mix all input */ | ||||
| 	spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 		if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) | ||||
| 			continue; | ||||
|  | @ -1039,13 +1058,14 @@ static void jack_node_push(void *data) | |||
| 
 | ||||
| 	conn = jack_graph_manager_get_current(mgr); | ||||
| 
 | ||||
| 	activation = jack_connection_manager_get_activation(conn, server->freewheel_ref_num); | ||||
| 	if (activation != 0) | ||||
| 		pw_log_warn("resume %d, some client did not complete", activation); | ||||
| 
 | ||||
| 	jack_connection_manager_reset(conn, mgr->client_timing); | ||||
| 
 | ||||
| 	activation = jack_connection_manager_get_activation(conn, server->freewheel_ref_num); | ||||
| 	if (activation == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	pw_log_trace("resume %d", activation); | ||||
|         jack_activation_count_signal(&conn->input_counter[server->freewheel_ref_num], | ||||
|                                     &server->synchro_table[server->freewheel_ref_num]); | ||||
| 
 | ||||
| 	spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 		if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) | ||||
|  | @ -1055,16 +1075,25 @@ static void jack_node_push(void *data) | |||
| 
 | ||||
| 	spa_list_for_each(node, &impl->rt.nodes, graph_link) { | ||||
| 		n = &node->node->rt.node; | ||||
| 
 | ||||
| 		spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) { | ||||
| 			if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) | ||||
| 				continue; | ||||
| 			pn->state = pn->callbacks->process_output(pn->callbacks_data); | ||||
| 		} | ||||
| 		n->state = n->callbacks->process_output(n->callbacks_data); | ||||
| 
 | ||||
| 		/* mix inputs */ | ||||
| 		spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 			if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) | ||||
| 				continue; | ||||
| 			pn->state = pn->callbacks->process_output(pn->callbacks_data); | ||||
| 			pn->state = pn->callbacks->process_input(pn->callbacks_data); | ||||
| 		} | ||||
| 
 | ||||
| 		n->state = n->callbacks->process_input(n->callbacks_data); | ||||
| 
 | ||||
| 		/* tee outputs */ | ||||
| 		spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) { | ||||
| 			if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) | ||||
| 				continue; | ||||
|  | @ -1340,7 +1369,7 @@ static int init_server(struct impl *impl, const char *name, bool promiscuous) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static struct impl *module_init(struct pw_module *module, struct pw_properties *properties) | ||||
| static bool module_init(struct pw_module *module, struct pw_properties *properties) | ||||
| { | ||||
| 	struct pw_core *core = pw_module_get_core(module); | ||||
| 	struct impl *impl; | ||||
|  | @ -1379,11 +1408,11 @@ static struct impl *module_init(struct pw_module *module, struct pw_properties * | |||
| 	if (init_server(impl, name, promiscuous) < 0) | ||||
| 		goto error; | ||||
| 
 | ||||
| 	return impl; | ||||
| 	return true; | ||||
| 
 | ||||
|       error: | ||||
| 	free(impl); | ||||
| 	return NULL; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
|  | @ -1399,6 +1428,5 @@ static void module_destroy(struct impl *impl) | |||
| 
 | ||||
| bool pipewire__module_init(struct pw_module *module, const char *args) | ||||
| { | ||||
| 	module_init(module, NULL); | ||||
| 	return true; | ||||
| 	return module_init(module, NULL); | ||||
| } | ||||
|  |  | |||
|  | @ -676,6 +676,10 @@ struct pw_jack_node *pw_jack_node_new(struct pw_core *core, | |||
| 	struct jack_graph_manager *mgr = server->graph_manager; | ||||
|         struct jack_connection_manager *conn; | ||||
| 
 | ||||
| 	if (properties == NULL) | ||||
| 		properties = pw_properties_new("jack.server.name", server->engine_control->server_name, | ||||
| 					       "jack.name", name, NULL); | ||||
| 
 | ||||
| 	ref_num = jack_server_allocate_ref_num(server); | ||||
| 	if (ref_num == -1) { | ||||
|                 pw_log_error(NAME " %p: can't allocated ref_num", core); | ||||
|  | @ -690,6 +694,7 @@ struct pw_jack_node *pw_jack_node_new(struct pw_core *core, | |||
|                 pw_log_error(NAME " %p: can't init synchro", core); | ||||
|                 return NULL; | ||||
|         } | ||||
| 	pw_properties_setf(properties, "jack.ref-num", "%d", ref_num); | ||||
| 
 | ||||
| 	node = pw_node_new(core, NULL, parent, name, properties, sizeof(struct node_data) + user_data_size); | ||||
| 	if (node == NULL) | ||||
|  | @ -744,6 +749,10 @@ pw_jack_driver_new(struct pw_core *core, | |||
|         struct jack_connection_manager *conn; | ||||
|         char n[REAL_JACK_PORT_NAME_SIZE]; | ||||
| 
 | ||||
| 	if (properties == NULL) | ||||
| 		properties = pw_properties_new("jack.server.name", server->engine_control->server_name, | ||||
| 					       "jack.name", name, NULL); | ||||
| 
 | ||||
| 	ref_num = jack_server_allocate_ref_num(server); | ||||
| 	if (ref_num == -1) { | ||||
|                 pw_log_error(NAME " %p: can't allocated ref_num", core); | ||||
|  | @ -758,6 +767,7 @@ pw_jack_driver_new(struct pw_core *core, | |||
|                 pw_log_error(NAME " %p: can't init synchro", core); | ||||
|                 return NULL; | ||||
|         } | ||||
| 	pw_properties_setf(properties, "jack.ref-num", "%d", ref_num); | ||||
| 
 | ||||
| 	node = pw_node_new(core, NULL, parent, name, properties, sizeof(struct node_data) + user_data_size); | ||||
| 	if (node == NULL) | ||||
|  |  | |||
|  | @ -274,8 +274,10 @@ static inline bool jack_activation_count_signal(struct jack_activation_count *cn | |||
| { | ||||
| 	bool res = true; | ||||
| 
 | ||||
| 	if (cnt->value == 0) | ||||
| 	if (cnt->value == 0) { | ||||
| 		pw_log_error("activation == 0"); | ||||
| 		res = jack_synchro_signal(synchro); | ||||
| 	} | ||||
| 	else if (__atomic_sub_fetch(&cnt->value, 1, __ATOMIC_SEQ_CST) == 0) | ||||
| 		res = jack_synchro_signal(synchro); | ||||
| 
 | ||||
|  | @ -1012,7 +1014,7 @@ jack_engine_control_alloc(const char* name) | |||
|         ctrl = (struct jack_engine_control *)jack_shm_addr(&info); | ||||
|         ctrl->info = info; | ||||
| 
 | ||||
| 	ctrl->buffer_size = 64; | ||||
| 	ctrl->buffer_size = 128; | ||||
|         ctrl->sample_rate = 48000; | ||||
| 	ctrl->sync_mode = false; | ||||
| 	ctrl->temporary = false; | ||||
|  |  | |||
|  | @ -21,8 +21,6 @@ | |||
| #include "config.h" | ||||
| #endif | ||||
| 
 | ||||
| #include <spa/graph-scheduler3.h> | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <dlfcn.h> | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ struct pw_client *pw_client_new(struct pw_core *core, | |||
| 	if (impl == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	pw_log_debug("client %p: new", impl); | ||||
| 	pw_log_debug("client %p: new parent %d", impl, parent ? parent->id : 0); | ||||
| 
 | ||||
| 	this = &impl->this; | ||||
| 	this->core = core; | ||||
|  | @ -123,7 +123,7 @@ struct pw_client *pw_client_new(struct pw_core *core, | |||
| 
 | ||||
| 	this->info.props = this->properties ? &this->properties->dict : NULL; | ||||
| 
 | ||||
| 	this->global = pw_core_add_global(core, this, parent, core->type.client, PW_VERSION_CLIENT, | ||||
| 	this->global = pw_core_add_global(core, NULL, parent, core->type.client, PW_VERSION_CLIENT, | ||||
| 			   client_bind_func, this); | ||||
| 
 | ||||
| 	return this; | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| 
 | ||||
| #include <spa/lib/debug.h> | ||||
| #include <spa/format-utils.h> | ||||
| #include <spa/graph-scheduler3.h> | ||||
| 
 | ||||
| #include <pipewire/pipewire.h> | ||||
| #include <pipewire/private.h> | ||||
|  | @ -338,7 +339,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro | |||
| 	pw_map_init(&this->globals, 128, 32); | ||||
| 
 | ||||
| 	spa_graph_init(&this->rt.graph); | ||||
| 	spa_graph_scheduler_init(&this->rt.sched, &this->rt.graph); | ||||
| 	spa_graph_set_callbacks(&this->rt.graph, &spa_graph_impl_default, NULL); | ||||
| 
 | ||||
| 	spa_debug_set_type_map(this->type.map); | ||||
| 
 | ||||
|  |  | |||
|  | @ -117,6 +117,7 @@ void pw_module_info_free(struct pw_module_info *info); | |||
| 
 | ||||
| /** The client information. Extra information can be added in later versions \memberof pw_introspect */ | ||||
| struct pw_client_info { | ||||
| #define PW_CLIENT_CHANGE_MASK_PROPS		(1 << 0) | ||||
| 	uint64_t change_mask;	/**< bitfield of changed fields since last call */ | ||||
| 	struct spa_dict *props;	/**< extra properties */ | ||||
| }; | ||||
|  | @ -164,6 +165,10 @@ pw_node_info_free(struct pw_node_info *info); | |||
| 
 | ||||
| /** The link information. Extra information can be added in later versions \memberof pw_introspect */ | ||||
| struct pw_link_info { | ||||
| #define PW_LINK_CHANGE_MASK_OUTPUT		(1 << 0) | ||||
| #define PW_LINK_CHANGE_MASK_INPUT		(1 << 1) | ||||
| #define PW_LINK_CHANGE_MASK_FORMAT		(1 << 2) | ||||
| #define PW_LINK_CHANGE_MASK_PROPS		(1 << 3) | ||||
| 	uint64_t change_mask;		/**< bitfield of changed fields since last call */ | ||||
| 	uint32_t output_node_id;	/**< server side output node id */ | ||||
| 	uint32_t output_port_id;	/**< output port id */ | ||||
|  |  | |||
|  | @ -116,6 +116,8 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st | |||
| 	int res = SPA_RESULT_ERROR, res2; | ||||
| 	struct spa_format *format, *current; | ||||
| 	char *error = NULL; | ||||
| 	struct pw_resource *resource; | ||||
| 	bool changed = true; | ||||
| 
 | ||||
| 	if (in_state != PW_PORT_STATE_CONFIGURE && out_state != PW_PORT_STATE_CONFIGURE) | ||||
| 		return SPA_RESULT_OK; | ||||
|  | @ -139,8 +141,10 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st | |||
| 			pw_node_set_state(this->output->node, PW_NODE_STATE_SUSPENDED); | ||||
| 			out_state = PW_PORT_STATE_CONFIGURE; | ||||
| 		} | ||||
| 		else | ||||
| 		else { | ||||
| 			pw_node_update_state(this->output->node, PW_NODE_STATE_RUNNING, NULL); | ||||
| 			changed = false; | ||||
| 		} | ||||
| 	} | ||||
| 	if (in_state > PW_PORT_STATE_CONFIGURE && this->input->node->info.state == PW_NODE_STATE_IDLE) { | ||||
| 		if ((res = pw_port_get_format(this->input, | ||||
|  | @ -153,8 +157,10 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st | |||
| 			pw_node_set_state(this->input->node, PW_NODE_STATE_SUSPENDED); | ||||
| 			in_state = PW_PORT_STATE_CONFIGURE; | ||||
| 		} | ||||
| 		else | ||||
| 		else { | ||||
| 			pw_node_update_state(this->input->node, PW_NODE_STATE_RUNNING, NULL); | ||||
| 			changed = false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	pw_log_debug("link %p: doing set format", this); | ||||
|  | @ -181,10 +187,20 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st | |||
| 			pw_work_queue_add(impl->work, this->input->node, res2, complete_ready, this->input); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	if (this->info.format) | ||||
| 		free(this->info.format); | ||||
| 	this->info.format = format; | ||||
| 
 | ||||
| 	if (changed) { | ||||
| 		this->info.change_mask |= PW_LINK_CHANGE_MASK_FORMAT; | ||||
| 
 | ||||
| 		spa_list_for_each(resource, &this->resource_list, link) | ||||
| 			pw_link_resource_info(resource, &this->info); | ||||
| 
 | ||||
| 		this->info.change_mask = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return SPA_RESULT_OK; | ||||
| 
 | ||||
|       error: | ||||
|  |  | |||
|  | @ -217,7 +217,7 @@ struct pw_module *pw_module_load(struct pw_core *core, const char *name, const c | |||
| 	this->info.args = args ? strdup(args) : NULL; | ||||
| 	this->info.props = NULL; | ||||
| 
 | ||||
| 	spa_list_insert(core->module_list.prev, &this->link); | ||||
| 	spa_list_append(&core->module_list, &this->link); | ||||
| 	this->global = pw_core_add_global(core, NULL, core->global, | ||||
| 					  core->type.module, PW_VERSION_MODULE, | ||||
| 					  module_bind_func, this); | ||||
|  |  | |||
|  | @ -169,7 +169,7 @@ static void node_need_input(void *data) | |||
|         struct impl *impl = data; | ||||
| 	struct pw_node *this = &impl->this; | ||||
| 
 | ||||
| 	spa_graph_scheduler_pull(this->rt.sched, &this->rt.node); | ||||
| 	spa_graph_need_input(this->rt.graph, &this->rt.node); | ||||
| } | ||||
| 
 | ||||
| static void node_have_output(void *data) | ||||
|  | @ -177,7 +177,7 @@ static void node_have_output(void *data) | |||
|         struct impl *impl = data; | ||||
| 	struct pw_node *this = &impl->this; | ||||
| 
 | ||||
| 	spa_graph_scheduler_push(this->rt.sched, &this->rt.node); | ||||
| 	spa_graph_have_output(this->rt.graph, &this->rt.node); | ||||
| } | ||||
| 
 | ||||
| static void node_unbind_func(void *data) | ||||
|  | @ -291,7 +291,7 @@ do_node_add(struct spa_loop *loop, | |||
| { | ||||
| 	struct pw_node *this = user_data; | ||||
| 
 | ||||
| 	spa_graph_node_add(this->rt.sched->graph, &this->rt.node); | ||||
| 	spa_graph_node_add(this->rt.graph, &this->rt.node); | ||||
| 
 | ||||
| 	return SPA_RESULT_OK; | ||||
| } | ||||
|  | @ -393,7 +393,7 @@ struct pw_node *pw_node_new(struct pw_core *core, | |||
| 
 | ||||
| 	this->data_loop = core->data_loop; | ||||
| 
 | ||||
| 	this->rt.sched = &core->rt.sched; | ||||
| 	this->rt.graph = &core->rt.graph; | ||||
| 
 | ||||
| 	spa_list_init(&this->resource_list); | ||||
| 
 | ||||
|  |  | |||
|  | @ -289,7 +289,7 @@ void pw_port_add(struct pw_port *port, struct pw_node *node) | |||
| 	if (port->implementation->set_io) | ||||
| 		port->implementation->set_io(port->implementation_data, &port->io); | ||||
| 
 | ||||
| 	port->rt.graph = node->rt.sched->graph; | ||||
| 	port->rt.graph = node->rt.graph; | ||||
| 	pw_loop_invoke(node->data_loop, do_add_port, SPA_ID_INVALID, 0, NULL, false, port); | ||||
| 
 | ||||
| 	port_update_state(port, PW_PORT_STATE_CONFIGURE); | ||||
|  |  | |||
|  | @ -24,8 +24,9 @@ | |||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #include <spa/graph.h> | ||||
| 
 | ||||
| #include <sys/socket.h> | ||||
| #include <spa/graph-scheduler3.h> | ||||
| 
 | ||||
| #include "pipewire/mem.h" | ||||
| #include "pipewire/pipewire.h" | ||||
|  | @ -116,7 +117,6 @@ struct pw_core { | |||
| 	uint32_t n_support;		/**< number of support items */ | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct spa_graph_scheduler sched; | ||||
| 		struct spa_graph graph; | ||||
| 	} rt; | ||||
| }; | ||||
|  | @ -218,7 +218,7 @@ struct pw_node { | |||
| 	struct pw_loop *data_loop;		/**< the data loop for this node */ | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct spa_graph_scheduler *sched; | ||||
| 		struct spa_graph *graph; | ||||
| 		struct spa_graph_node node; | ||||
| 	} rt; | ||||
| 
 | ||||
|  |  | |||
|  | @ -424,15 +424,24 @@ static void handle_rtnode_message(struct pw_proxy *proxy, struct pw_client_node_ | |||
| 	struct spa_graph_node *n = &data->node->rt.node; | ||||
| 
 | ||||
|         if (PW_CLIENT_NODE_MESSAGE_TYPE(message) == PW_CLIENT_NODE_MESSAGE_PROCESS_INPUT) { | ||||
| 		struct spa_list ready; | ||||
| 		struct spa_graph_port *port; | ||||
| 		struct spa_graph_port *port, *pp; | ||||
| 		struct spa_graph_node *pn; | ||||
| 
 | ||||
| 		spa_list_init(&ready); | ||||
| 
 | ||||
| 		spa_list_for_each(port, &n->ports[SPA_DIRECTION_INPUT], link) | ||||
| 			spa_list_insert(ready.prev, &port->peer->node->ready_link); | ||||
| 
 | ||||
| 	        spa_graph_scheduler_chain(data->node->rt.sched, &ready); | ||||
| 		/* process all input in the mixers */ | ||||
| 		spa_list_for_each(port, &n->ports[SPA_DIRECTION_INPUT], link) { | ||||
| 			pn = port->peer->node; | ||||
| 	                pn->state = pn->callbacks->process_input(pn->callbacks_data); | ||||
| 	                if (pn->state == SPA_RESULT_HAVE_BUFFER) | ||||
| 	                        spa_graph_have_output(data->node->rt.graph, pn); | ||||
| 			else { | ||||
| 	                        pn->ready_in = 0; | ||||
| 	                        spa_list_for_each(pp, &pn->ports[SPA_DIRECTION_INPUT], link) { | ||||
|                                 if (pp->io->status == SPA_RESULT_OK && | ||||
| 				    !(pn->flags & SPA_GRAPH_NODE_FLAG_ASYNC)) | ||||
|                                         pn->ready_in++; | ||||
| 				} | ||||
| 	                } | ||||
| 		} | ||||
|         } | ||||
| 	else if (PW_CLIENT_NODE_MESSAGE_TYPE(message) == PW_CLIENT_NODE_MESSAGE_PROCESS_OUTPUT) { | ||||
| 		n->callbacks->process_output(n->callbacks_data); | ||||
|  |  | |||
|  | @ -231,14 +231,15 @@ static void link_event_info(void *object, struct pw_link_info *info) | |||
| 	printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Link, data->version); | ||||
| 	if (print_all) { | ||||
| 		printf("%c\toutput-node-id: %u\n", MARK_CHANGE(0), info->output_node_id); | ||||
| 		printf("%c\toutput-port-id: %u\n", MARK_CHANGE(1), info->output_port_id); | ||||
| 		printf("%c\tinput-node-id: %u\n", MARK_CHANGE(2), info->input_node_id); | ||||
| 		printf("%c\tinput-port-id: %u\n", MARK_CHANGE(3), info->input_port_id); | ||||
| 		printf("%c\tformat:\n", MARK_CHANGE(4)); | ||||
| 		printf("%c\toutput-port-id: %u\n", MARK_CHANGE(0), info->output_port_id); | ||||
| 		printf("%c\tinput-node-id: %u\n", MARK_CHANGE(1), info->input_node_id); | ||||
| 		printf("%c\tinput-port-id: %u\n", MARK_CHANGE(1), info->input_port_id); | ||||
| 		printf("%c\tformat:\n", MARK_CHANGE(2)); | ||||
| 		if (info->format) | ||||
| 			spa_debug_format(info->format); | ||||
| 		else | ||||
| 			printf("\t  none\n"); | ||||
| 		print_properties(info->props, MARK_CHANGE(3)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Wim Taymans
						Wim Taymans