mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	jack: emit latency notify when buffer_frames changes
When the buffer frames change, make sure we emit a latency recalculation even if we don't have a buffer_size callback. Remove the unused GRAPH notify. Protect ringbuffer writes to the notify queue with a lock because we can't know what thread they execute in. Make a new TOTAL_LATENCY notify type to trigger a complete latency recalculation.
This commit is contained in:
		
							parent
							
								
									d08d05629b
								
							
						
					
					
						commit
						88e4a69765
					
				
					 1 changed files with 36 additions and 32 deletions
				
			
		| 
						 | 
					@ -86,12 +86,12 @@ struct notify {
 | 
				
			||||||
#define NOTIFY_TYPE_REGISTRATION	((1<<4))
 | 
					#define NOTIFY_TYPE_REGISTRATION	((1<<4))
 | 
				
			||||||
#define NOTIFY_TYPE_PORTREGISTRATION	((2<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_PORTREGISTRATION	((2<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_CONNECT		((3<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_CONNECT		((3<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_GRAPH		((4<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_BUFFER_FRAMES	((4<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_BUFFER_FRAMES	((5<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_SAMPLE_RATE		((5<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_SAMPLE_RATE		((6<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_FREEWHEEL		((6<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_FREEWHEEL		((7<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_SHUTDOWN		((7<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_SHUTDOWN		((8<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_LATENCY		((8<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
#define NOTIFY_TYPE_LATENCY		((9<<4)|NOTIFY_ACTIVE_FLAG)
 | 
					#define NOTIFY_TYPE_TOTAL_LATENCY	((9<<4)|NOTIFY_ACTIVE_FLAG)
 | 
				
			||||||
	int type;
 | 
						int type;
 | 
				
			||||||
	struct object *object;
 | 
						struct object *object;
 | 
				
			||||||
	int arg1;
 | 
						int arg1;
 | 
				
			||||||
| 
						 | 
					@ -901,12 +901,6 @@ jack_get_version_string(void)
 | 
				
			||||||
	return name;
 | 
						return name;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void recompute_latencies(struct client *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg);
 | 
					 | 
				
			||||||
	do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define freeze_callbacks(c)		\
 | 
					#define freeze_callbacks(c)		\
 | 
				
			||||||
({					\
 | 
					({					\
 | 
				
			||||||
	(c)->frozen_callbacks++;	\
 | 
						(c)->frozen_callbacks++;	\
 | 
				
			||||||
| 
						 | 
					@ -929,7 +923,7 @@ static void emit_callbacks(struct client *c)
 | 
				
			||||||
	int32_t avail;
 | 
						int32_t avail;
 | 
				
			||||||
	uint32_t index;
 | 
						uint32_t index;
 | 
				
			||||||
	struct notify *notify;
 | 
						struct notify *notify;
 | 
				
			||||||
	bool do_graph = false;
 | 
						bool do_graph = false, do_recompute_capture = false, do_recompute_playback = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->frozen_callbacks != 0 || !c->pending_callbacks)
 | 
						if (c->frozen_callbacks != 0 || !c->pending_callbacks)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -982,10 +976,7 @@ static void emit_callbacks(struct client *c)
 | 
				
			||||||
					c->connect_arg);
 | 
										c->connect_arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			do_graph = true;
 | 
								do_graph = true;
 | 
				
			||||||
			break;
 | 
								do_recompute_capture = do_recompute_playback = true;
 | 
				
			||||||
		case NOTIFY_TYPE_GRAPH:
 | 
					 | 
				
			||||||
			pw_log_debug("%p: graph", c);
 | 
					 | 
				
			||||||
			do_graph = true;
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
							case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
				
			||||||
			pw_log_debug("%p: buffer frames %d", c, notify->arg1);
 | 
								pw_log_debug("%p: buffer frames %d", c, notify->arg1);
 | 
				
			||||||
| 
						 | 
					@ -993,7 +984,7 @@ static void emit_callbacks(struct client *c)
 | 
				
			||||||
				do_callback_expr(c, c->buffer_frames = notify->arg1,
 | 
									do_callback_expr(c, c->buffer_frames = notify->arg1,
 | 
				
			||||||
						bufsize_callback, c->active,
 | 
											bufsize_callback, c->active,
 | 
				
			||||||
						notify->arg1, c->bufsize_arg);
 | 
											notify->arg1, c->bufsize_arg);
 | 
				
			||||||
				recompute_latencies(c);
 | 
									do_recompute_capture = do_recompute_playback = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NOTIFY_TYPE_SAMPLE_RATE:
 | 
							case NOTIFY_TYPE_SAMPLE_RATE:
 | 
				
			||||||
| 
						 | 
					@ -1020,7 +1011,14 @@ static void emit_callbacks(struct client *c)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NOTIFY_TYPE_LATENCY:
 | 
							case NOTIFY_TYPE_LATENCY:
 | 
				
			||||||
			pw_log_debug("%p: latency %d", c, notify->arg1);
 | 
								pw_log_debug("%p: latency %d", c, notify->arg1);
 | 
				
			||||||
			do_callback(c, latency_callback, c->active, notify->arg1, c->latency_arg);
 | 
								if (notify->arg1 == JackCaptureLatency)
 | 
				
			||||||
 | 
									do_recompute_capture = true;
 | 
				
			||||||
 | 
								else if (notify->arg1 == JackPlaybackLatency)
 | 
				
			||||||
 | 
									do_recompute_playback = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case NOTIFY_TYPE_TOTAL_LATENCY:
 | 
				
			||||||
 | 
								pw_log_debug("%p: total latency", c);
 | 
				
			||||||
 | 
								do_recompute_capture = do_recompute_playback = true;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -1036,10 +1034,13 @@ static void emit_callbacks(struct client *c)
 | 
				
			||||||
		index += sizeof(struct notify);
 | 
							index += sizeof(struct notify);
 | 
				
			||||||
		spa_ringbuffer_read_update(&c->notify_ring, index);
 | 
							spa_ringbuffer_read_update(&c->notify_ring, index);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (do_graph) {
 | 
						if (do_recompute_capture)
 | 
				
			||||||
		recompute_latencies(c);
 | 
							do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg);
 | 
				
			||||||
 | 
						if (do_recompute_playback)
 | 
				
			||||||
 | 
							do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg);
 | 
				
			||||||
 | 
						if (do_graph)
 | 
				
			||||||
		do_callback(c, graph_callback, c->active, c->graph_arg);
 | 
							do_callback(c, graph_callback, c->active, c->graph_arg);
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	thaw_callbacks(c);
 | 
						thaw_callbacks(c);
 | 
				
			||||||
	pw_log_debug("%p: leave", c);
 | 
						pw_log_debug("%p: leave", c);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1050,6 +1051,7 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
	uint32_t index;
 | 
						uint32_t index;
 | 
				
			||||||
	struct notify *notify;
 | 
						struct notify *notify;
 | 
				
			||||||
	bool emit = false;
 | 
						bool emit = false;
 | 
				
			||||||
 | 
						int res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (type) {
 | 
						switch (type) {
 | 
				
			||||||
	case NOTIFY_TYPE_REGISTRATION:
 | 
						case NOTIFY_TYPE_REGISTRATION:
 | 
				
			||||||
| 
						 | 
					@ -1062,9 +1064,6 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
	case NOTIFY_TYPE_CONNECT:
 | 
						case NOTIFY_TYPE_CONNECT:
 | 
				
			||||||
		emit = c->connect_callback != NULL && o != NULL;
 | 
							emit = c->connect_callback != NULL && o != NULL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NOTIFY_TYPE_GRAPH:
 | 
					 | 
				
			||||||
		emit = c->graph_callback != NULL || c->latency_callback != NULL;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
						case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
				
			||||||
		emit = c->bufsize_callback != NULL;
 | 
							emit = c->bufsize_callback != NULL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -1078,6 +1077,7 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
		emit = c->info_shutdown_callback != NULL || c->shutdown_callback != NULL;
 | 
							emit = c->info_shutdown_callback != NULL || c->shutdown_callback != NULL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NOTIFY_TYPE_LATENCY:
 | 
						case NOTIFY_TYPE_LATENCY:
 | 
				
			||||||
 | 
						case NOTIFY_TYPE_TOTAL_LATENCY:
 | 
				
			||||||
		emit = c->latency_callback != NULL;
 | 
							emit = c->latency_callback != NULL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
| 
						 | 
					@ -1086,8 +1086,10 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
	if (!emit || ((type & NOTIFY_ACTIVE_FLAG) && !c->active)) {
 | 
						if (!emit || ((type & NOTIFY_ACTIVE_FLAG) && !c->active)) {
 | 
				
			||||||
		switch (type) {
 | 
							switch (type) {
 | 
				
			||||||
		case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
							case NOTIFY_TYPE_BUFFER_FRAMES:
 | 
				
			||||||
			if (!emit)
 | 
								if (!emit) {
 | 
				
			||||||
				c->buffer_frames = arg1;
 | 
									c->buffer_frames = arg1;
 | 
				
			||||||
 | 
									queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case NOTIFY_TYPE_SAMPLE_RATE:
 | 
							case NOTIFY_TYPE_SAMPLE_RATE:
 | 
				
			||||||
			if (!emit)
 | 
								if (!emit)
 | 
				
			||||||
| 
						 | 
					@ -1100,13 +1102,15 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
			o->removing = false;
 | 
								o->removing = false;
 | 
				
			||||||
			free_object(c, o);
 | 
								free_object(c, o);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0;
 | 
							return res;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pthread_mutex_lock(&c->context.lock);
 | 
				
			||||||
	filled = spa_ringbuffer_get_write_index(&c->notify_ring, &index);
 | 
						filled = spa_ringbuffer_get_write_index(&c->notify_ring, &index);
 | 
				
			||||||
	if (filled < 0 || filled + sizeof(struct notify) > NOTIFY_BUFFER_SIZE) {
 | 
						if (filled < 0 || filled + sizeof(struct notify) > NOTIFY_BUFFER_SIZE) {
 | 
				
			||||||
		pw_log_warn("%p: notify queue full %d", c, type);
 | 
							pw_log_warn("%p: notify queue full %d", c, type);
 | 
				
			||||||
		return -ENOSPC;
 | 
							res = -ENOSPC;
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	notify = SPA_PTROFF(c->notify_buffer, index & NOTIFY_BUFFER_MASK, struct notify);
 | 
						notify = SPA_PTROFF(c->notify_buffer, index & NOTIFY_BUFFER_MASK, struct notify);
 | 
				
			||||||
| 
						 | 
					@ -1120,7 +1124,9 @@ static int queue_notify(struct client *c, int type, struct object *o, int arg1,
 | 
				
			||||||
	spa_ringbuffer_write_update(&c->notify_ring, index);
 | 
						spa_ringbuffer_write_update(&c->notify_ring, index);
 | 
				
			||||||
	c->pending_callbacks = true;
 | 
						c->pending_callbacks = true;
 | 
				
			||||||
	check_callbacks(c);
 | 
						check_callbacks(c);
 | 
				
			||||||
	return 0;
 | 
					done:
 | 
				
			||||||
 | 
						pthread_mutex_unlock(&c->context.lock);
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_notify_event(void *data, uint64_t count)
 | 
					static void on_notify_event(void *data, uint64_t count)
 | 
				
			||||||
| 
						 | 
					@ -5860,9 +5866,7 @@ SPA_EXPORT
 | 
				
			||||||
int jack_recompute_total_latencies (jack_client_t *client)
 | 
					int jack_recompute_total_latencies (jack_client_t *client)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *c = (struct client *) client;
 | 
						struct client *c = (struct client *) client;
 | 
				
			||||||
	queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackCaptureLatency, NULL);
 | 
						return queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL);
 | 
				
			||||||
	queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackPlaybackLatency, NULL);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static jack_nframes_t port_get_latency (jack_port_t *port)
 | 
					static jack_nframes_t port_get_latency (jack_port_t *port)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue