mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pw-top: add 'batch-mode' and iterations known from top
This commit is contained in:
		
							parent
							
								
									7f30621b86
								
							
						
					
					
						commit
						71653e04d2
					
				
					 1 changed files with 89 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -82,6 +82,9 @@ struct data {
 | 
			
		|||
	unsigned pending_refresh:1;
 | 
			
		||||
 | 
			
		||||
	WINDOW *win;
 | 
			
		||||
 | 
			
		||||
	unsigned int batch_mode:1;
 | 
			
		||||
	int iterations;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct point {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +92,22 @@ struct point {
 | 
			
		|||
	struct driver info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static SPA_PRINTF_FUNC(4, 5) void print_mode_dependent(struct data *d, int y, int x, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list argp;
 | 
			
		||||
	if (!d->batch_mode)
 | 
			
		||||
		mvwprintw(d->win, y, x, "%s", "");
 | 
			
		||||
 | 
			
		||||
	va_start(argp, fmt);
 | 
			
		||||
	if (d->batch_mode) {
 | 
			
		||||
		vprintf(fmt, argp);
 | 
			
		||||
		printf("\n");
 | 
			
		||||
	} else
 | 
			
		||||
		vw_printw(d->win, fmt, argp);
 | 
			
		||||
	va_end(argp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int process_info(struct data *d, const struct spa_pod *pod, struct driver *info)
 | 
			
		||||
{
 | 
			
		||||
	return spa_pod_parse_struct(pod,
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +163,7 @@ static const struct pw_proxy_events proxy_events = {
 | 
			
		|||
	.destroy = on_node_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void do_refresh(struct data *d);
 | 
			
		||||
static void do_refresh(struct data *d, bool force_refresh);
 | 
			
		||||
 | 
			
		||||
static void node_info(void *data, const struct pw_node_info *info)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +171,7 @@ static void node_info(void *data, const struct pw_node_info *info)
 | 
			
		|||
 | 
			
		||||
	if (n->state != info->state) {
 | 
			
		||||
		n->state = info->state;
 | 
			
		||||
		do_refresh(n->data);
 | 
			
		||||
		do_refresh(n->data, !n->data->batch_mode);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +278,7 @@ static void node_param(void *data, int seq,
 | 
			
		|||
		break;
 | 
			
		||||
	}
 | 
			
		||||
done:
 | 
			
		||||
	do_refresh(n->data);
 | 
			
		||||
	do_refresh(n->data, !n->data->batch_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_node_events node_events = {
 | 
			
		||||
| 
						 | 
				
			
			@ -296,6 +315,7 @@ static struct node *add_node(struct data *d, uint32_t id, const char *name)
 | 
			
		|||
	}
 | 
			
		||||
	spa_list_append(&d->node_list, &n->link);
 | 
			
		||||
	d->n_nodes++;
 | 
			
		||||
	if (!d->batch_mode)
 | 
			
		||||
		d->pending_refresh = true;
 | 
			
		||||
 | 
			
		||||
	return n;
 | 
			
		||||
| 
						 | 
				
			
			@ -307,6 +327,7 @@ static void remove_node(struct data *d, struct node *n)
 | 
			
		|||
		pw_proxy_destroy(n->proxy);
 | 
			
		||||
	spa_list_remove(&n->link);
 | 
			
		||||
	d->n_nodes--;
 | 
			
		||||
	if (!d->batch_mode)
 | 
			
		||||
		d->pending_refresh = true;
 | 
			
		||||
	free(n);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +483,7 @@ static void print_node(struct data *d, struct driver *i, struct node *n, int y)
 | 
			
		|||
	else
 | 
			
		||||
		busy = -1;
 | 
			
		||||
 | 
			
		||||
	mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u %16.16s %s%s",
 | 
			
		||||
	print_mode_dependent(d, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u %16.16s %s%s",
 | 
			
		||||
			state_as_string(n->state),
 | 
			
		||||
			n->id,
 | 
			
		||||
			frac.num, frac.denom,
 | 
			
		||||
| 
						 | 
				
			
			@ -484,23 +505,31 @@ static void clear_node(struct node *n)
 | 
			
		|||
	spa_zero(n->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_refresh(struct data *d)
 | 
			
		||||
#define HEADER	"S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR FORMAT           NAME "
 | 
			
		||||
 | 
			
		||||
static void do_refresh(struct data *d, bool force_refresh)
 | 
			
		||||
{
 | 
			
		||||
	struct node *n, *t, *f;
 | 
			
		||||
	int y = 1;
 | 
			
		||||
 | 
			
		||||
	if (!d->pending_refresh && !force_refresh)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (!d->batch_mode) {
 | 
			
		||||
		wclear(d->win);
 | 
			
		||||
		wattron(d->win, A_REVERSE);
 | 
			
		||||
	wprintw(d->win, "%-*.*s", COLS, COLS, "S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR FORMAT           NAME ");
 | 
			
		||||
		wprintw(d->win, "%-*.*s", COLS, COLS, HEADER);
 | 
			
		||||
		wattroff(d->win, A_REVERSE);
 | 
			
		||||
		wprintw(d->win, "\n");
 | 
			
		||||
	} else
 | 
			
		||||
		printf(HEADER "\n");
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each_safe(n, t, &d->node_list, link) {
 | 
			
		||||
		if (n->driver != n)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		print_node(d, &n->info, n, y++);
 | 
			
		||||
		if(y > LINES)
 | 
			
		||||
		if(!d->batch_mode && y > LINES)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		spa_list_for_each(f, &d->node_list, link) {
 | 
			
		||||
| 
						 | 
				
			
			@ -517,19 +546,28 @@ static void do_refresh(struct data *d)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!d->batch_mode) {
 | 
			
		||||
		// Clear from last line to the end of the window to hide text wrapping from the last node
 | 
			
		||||
		wmove(d->win, y, 0);
 | 
			
		||||
		wclrtobot(d->win);
 | 
			
		||||
 | 
			
		||||
		wrefresh(d->win);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d->pending_refresh = false;
 | 
			
		||||
 | 
			
		||||
	if (d->iterations > 0)
 | 
			
		||||
		d->iterations--;
 | 
			
		||||
 | 
			
		||||
	if (d->iterations == 0)
 | 
			
		||||
		pw_main_loop_quit(d->loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_timeout(void *data, uint64_t expirations)
 | 
			
		||||
{
 | 
			
		||||
	struct data *d = data;
 | 
			
		||||
	d->generation++;
 | 
			
		||||
	do_refresh(d);
 | 
			
		||||
	do_refresh(d, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void profiler_profile(void *data, const struct spa_pod *pod)
 | 
			
		||||
| 
						 | 
				
			
			@ -568,8 +606,8 @@ static void profiler_profile(void *data, const struct spa_pod *pod)
 | 
			
		|||
		if (res < 0)
 | 
			
		||||
			continue;
 | 
			
		||||
	}
 | 
			
		||||
	if (d->pending_refresh)
 | 
			
		||||
		do_refresh(d);
 | 
			
		||||
 | 
			
		||||
	do_refresh(d, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_profiler_events profiler_events = {
 | 
			
		||||
| 
						 | 
				
			
			@ -608,8 +646,8 @@ static void registry_event_global(void *data, uint32_t id,
 | 
			
		|||
		d->profiler = proxy;
 | 
			
		||||
		pw_proxy_add_object_listener(proxy, &d->profiler_listener, &profiler_events, d);
 | 
			
		||||
	}
 | 
			
		||||
	if (d->pending_refresh)
 | 
			
		||||
		do_refresh(d);
 | 
			
		||||
 | 
			
		||||
	do_refresh(d, false);
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
error_proxy:
 | 
			
		||||
| 
						 | 
				
			
			@ -623,8 +661,8 @@ static void registry_event_global_remove(void *data, uint32_t id)
 | 
			
		|||
	struct node *n;
 | 
			
		||||
	if ((n = find_node(d, id)) != NULL)
 | 
			
		||||
		remove_node(d, n);
 | 
			
		||||
	if (d->pending_refresh)
 | 
			
		||||
		do_refresh(d);
 | 
			
		||||
 | 
			
		||||
	do_refresh(d, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_registry_events registry_events = {
 | 
			
		||||
| 
						 | 
				
			
			@ -662,7 +700,7 @@ static void on_core_done(void *_data, uint32_t id, int seq)
 | 
			
		|||
			pw_log_error("no Profiler Interface found, please load one in the server");
 | 
			
		||||
			pw_main_loop_quit(d->loop);
 | 
			
		||||
		} else {
 | 
			
		||||
			do_refresh(d);
 | 
			
		||||
			do_refresh(d, true);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -683,6 +721,8 @@ static void show_help(const char *name, bool error)
 | 
			
		|||
{
 | 
			
		||||
        fprintf(error ? stderr : stdout, "Usage:\n%s [options]\n\n"
 | 
			
		||||
		"Options:\n"
 | 
			
		||||
		"  -b, --batch-mode		         run in non-interactive batch_mode mode\n"
 | 
			
		||||
		"  -n, --iterations = NUMBER             exit on maximum iterations NUMBER\n"
 | 
			
		||||
		"  -r, --remote                          Remote daemon name\n"
 | 
			
		||||
		"\n"
 | 
			
		||||
		"  -h, --help                            Show this help\n"
 | 
			
		||||
| 
						 | 
				
			
			@ -715,7 +755,7 @@ static void do_handle_io(void *data, int fd, uint32_t mask)
 | 
			
		|||
			pw_main_loop_quit(d->loop);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			do_refresh(d);
 | 
			
		||||
			do_refresh(d, !d->batch_mode);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -727,9 +767,11 @@ int main(int argc, char *argv[])
 | 
			
		|||
	struct pw_loop *l;
 | 
			
		||||
	const char *opt_remote = NULL;
 | 
			
		||||
	static const struct option long_options[] = {
 | 
			
		||||
		{ "batch-mode",	no_argument,		NULL, 'b' },
 | 
			
		||||
		{ "iterations",	required_argument,	NULL, 'n' },
 | 
			
		||||
		{ "remote",	required_argument,	NULL, 'r' },
 | 
			
		||||
		{ "help",	no_argument,		NULL, 'h' },
 | 
			
		||||
		{ "version",	no_argument,		NULL, 'V' },
 | 
			
		||||
		{ "remote",	required_argument,	NULL, 'r' },
 | 
			
		||||
		{ NULL, 0, NULL, 0}
 | 
			
		||||
	};
 | 
			
		||||
	int c;
 | 
			
		||||
| 
						 | 
				
			
			@ -739,9 +781,11 @@ int main(int argc, char *argv[])
 | 
			
		|||
	setlocale(LC_ALL, "");
 | 
			
		||||
	pw_init(&argc, &argv);
 | 
			
		||||
 | 
			
		||||
	data.iterations = -1;
 | 
			
		||||
 | 
			
		||||
	spa_list_init(&data.node_list);
 | 
			
		||||
 | 
			
		||||
	while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) {
 | 
			
		||||
	while ((c = getopt_long(argc, argv, "hVr:o:bn:", long_options, NULL)) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'h':
 | 
			
		||||
			show_help(argv[0], false);
 | 
			
		||||
| 
						 | 
				
			
			@ -757,6 +801,12 @@ int main(int argc, char *argv[])
 | 
			
		|||
		case 'r':
 | 
			
		||||
			opt_remote = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'b':
 | 
			
		||||
			data.batch_mode = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'n':
 | 
			
		||||
			spa_atoi32(optarg, &data.iterations, 10);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			show_help(argv[0], true);
 | 
			
		||||
			return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -769,6 +819,9 @@ int main(int argc, char *argv[])
 | 
			
		|||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!data.batch_mode)
 | 
			
		||||
		data.iterations = -1;
 | 
			
		||||
 | 
			
		||||
	l = pw_main_loop_get_loop(data.loop);
 | 
			
		||||
	pw_loop_add_signal(l, SIGINT, do_quit, &data);
 | 
			
		||||
	pw_loop_add_signal(l, SIGTERM, do_quit, &data);
 | 
			
		||||
| 
						 | 
				
			
			@ -802,9 +855,10 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
	data.check_profiler = pw_core_sync(data.core, 0, 0);
 | 
			
		||||
 | 
			
		||||
	if (!data.batch_mode) {
 | 
			
		||||
		terminal_start();
 | 
			
		||||
 | 
			
		||||
		data.win = newwin(LINES, COLS, 0, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data.timer = pw_loop_add_timer(l, do_timeout, &data);
 | 
			
		||||
	value.tv_sec = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -813,15 +867,16 @@ int main(int argc, char *argv[])
 | 
			
		|||
	interval.tv_nsec = 0;
 | 
			
		||||
	pw_loop_update_timer(l, data.timer, &value, &interval, false);
 | 
			
		||||
 | 
			
		||||
	if (!data.batch_mode)
 | 
			
		||||
		pw_loop_add_io(l, fileno(stdin), SPA_IO_IN, false, do_handle_io, &data);
 | 
			
		||||
 | 
			
		||||
	pw_main_loop_run(data.loop);
 | 
			
		||||
 | 
			
		||||
	if (!data.batch_mode)
 | 
			
		||||
		terminal_stop();
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(n, &data.node_list, link)
 | 
			
		||||
		remove_node(&data, n);
 | 
			
		||||
 | 
			
		||||
	if (data.profiler) {
 | 
			
		||||
		spa_hook_remove(&data.profiler_listener);
 | 
			
		||||
		pw_proxy_destroy((struct pw_proxy*)data.profiler);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue