mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pw-top: show negotiated formats
Add a column with negotiated formats. It requires an adapter that will enumerate the port formats so it does not work for video streams yet. Fixes #2566
This commit is contained in:
		
							parent
							
								
									305f2104ee
								
							
						
					
					
						commit
						76631e6251
					
				
					 1 changed files with 113 additions and 4 deletions
				
			
		| 
						 | 
					@ -32,10 +32,14 @@
 | 
				
			||||||
#include <spa/utils/string.h>
 | 
					#include <spa/utils/string.h>
 | 
				
			||||||
#include <spa/pod/parser.h>
 | 
					#include <spa/pod/parser.h>
 | 
				
			||||||
#include <spa/debug/pod.h>
 | 
					#include <spa/debug/pod.h>
 | 
				
			||||||
 | 
					#include <spa/param/format-utils.h>
 | 
				
			||||||
 | 
					#include <spa/param/audio/format-utils.h>
 | 
				
			||||||
 | 
					#include <spa/param/video/format-utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pipewire/impl.h>
 | 
					#include <pipewire/impl.h>
 | 
				
			||||||
#include <pipewire/extensions/profiler.h>
 | 
					#include <pipewire/extensions/profiler.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_FORMAT		16
 | 
				
			||||||
#define MAX_NAME		128
 | 
					#define MAX_NAME		128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct driver {
 | 
					struct driver {
 | 
				
			||||||
| 
						 | 
					@ -59,13 +63,17 @@ struct measurement {
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
	uint32_t id;
 | 
						uint32_t id;
 | 
				
			||||||
	char name[MAX_NAME];
 | 
						char name[MAX_NAME+1];
 | 
				
			||||||
	struct measurement measurement;
 | 
						struct measurement measurement;
 | 
				
			||||||
	struct driver info;
 | 
						struct driver info;
 | 
				
			||||||
	struct node *driver;
 | 
						struct node *driver;
 | 
				
			||||||
	uint32_t errors;
 | 
						uint32_t errors;
 | 
				
			||||||
	int32_t last_error_status;
 | 
						int32_t last_error_status;
 | 
				
			||||||
	uint32_t generation;
 | 
						uint32_t generation;
 | 
				
			||||||
 | 
						char format[MAX_FORMAT+1];
 | 
				
			||||||
 | 
						struct pw_proxy *proxy;
 | 
				
			||||||
 | 
						struct spa_hook proxy_listener;
 | 
				
			||||||
 | 
						struct spa_hook object_listener;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct data {
 | 
					struct data {
 | 
				
			||||||
| 
						 | 
					@ -131,6 +139,91 @@ static struct node *find_node(struct data *d, uint32_t id)
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void on_node_removed(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct node *n = data;
 | 
				
			||||||
 | 
						pw_proxy_destroy(n->proxy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void on_node_destroy(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct node *n = data;
 | 
				
			||||||
 | 
						n->proxy = NULL;
 | 
				
			||||||
 | 
						spa_hook_remove(&n->proxy_listener);
 | 
				
			||||||
 | 
						spa_hook_remove(&n->object_listener);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct pw_proxy_events proxy_events = {
 | 
				
			||||||
 | 
						PW_VERSION_PROXY_EVENTS,
 | 
				
			||||||
 | 
						.removed = on_node_removed,
 | 
				
			||||||
 | 
						.destroy = on_node_destroy,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void node_param(void *data, int seq,
 | 
				
			||||||
 | 
								uint32_t id, uint32_t index, uint32_t next,
 | 
				
			||||||
 | 
								const struct spa_pod *param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct node *n = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case SPA_PARAM_Format:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint32_t media_type, media_subtype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spa_format_parse(param, &media_type, &media_subtype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch(media_type) {
 | 
				
			||||||
 | 
							case SPA_MEDIA_TYPE_audio:
 | 
				
			||||||
 | 
								switch(media_subtype) {
 | 
				
			||||||
 | 
								case SPA_MEDIA_SUBTYPE_raw:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									struct spa_audio_info_raw info;
 | 
				
			||||||
 | 
									if (spa_format_audio_raw_parse(param, &info) >= 0) {
 | 
				
			||||||
 | 
										snprintf(n->format, sizeof(n->format), "%6.6s/%d %-6d",
 | 
				
			||||||
 | 
											spa_debug_type_find_short_name(spa_type_audio_format, info.format),
 | 
				
			||||||
 | 
											info.channels, info.rate);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								case SPA_MEDIA_SUBTYPE_dsd:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									struct spa_audio_info_dsd info;
 | 
				
			||||||
 | 
									if (spa_format_audio_dsd_parse(param, &info) >= 0) {
 | 
				
			||||||
 | 
										snprintf(n->format, sizeof(n->format), "DSD%d/%2d ",
 | 
				
			||||||
 | 
											8 * info.rate / 44100, info.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case SPA_MEDIA_TYPE_video:
 | 
				
			||||||
 | 
								switch(media_subtype) {
 | 
				
			||||||
 | 
								case SPA_MEDIA_SUBTYPE_raw:
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									struct spa_video_info_raw info;
 | 
				
			||||||
 | 
									if (spa_format_video_raw_parse(param, &info) >= 0) {
 | 
				
			||||||
 | 
										snprintf(n->format, sizeof(n->format), "%6.6s %dx%d",
 | 
				
			||||||
 | 
											spa_debug_type_find_short_name(spa_type_video_format, info.format),
 | 
				
			||||||
 | 
											info.size.width, info.size.height);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct pw_node_events node_events = {
 | 
				
			||||||
 | 
						PW_VERSION_NODE,
 | 
				
			||||||
 | 
						.param = node_param,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct node *add_node(struct data *d, uint32_t id, const char *name)
 | 
					static struct node *add_node(struct data *d, uint32_t id, const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct node *n;
 | 
						struct node *n;
 | 
				
			||||||
| 
						 | 
					@ -139,11 +232,23 @@ static struct node *add_node(struct data *d, uint32_t id, const char *name)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (name)
 | 
						if (name)
 | 
				
			||||||
		strncpy(n->name, name, MAX_NAME-1);
 | 
							strncpy(n->name, name, MAX_NAME);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		snprintf(n->name, sizeof(n->name), "%u", id);
 | 
							snprintf(n->name, sizeof(n->name), "%u", id);
 | 
				
			||||||
	n->id = id;
 | 
						n->id = id;
 | 
				
			||||||
	n->driver = n;
 | 
						n->driver = n;
 | 
				
			||||||
 | 
						n->proxy = pw_registry_bind(d->registry, id, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
 | 
				
			||||||
 | 
						if (n->proxy) {
 | 
				
			||||||
 | 
							uint32_t ids[1] = { SPA_PARAM_Format };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pw_proxy_add_listener(n->proxy,
 | 
				
			||||||
 | 
									&n->proxy_listener, &proxy_events, n);
 | 
				
			||||||
 | 
							pw_proxy_add_object_listener(n->proxy,
 | 
				
			||||||
 | 
									&n->object_listener, &node_events, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pw_node_subscribe_params((struct pw_node*)n->proxy,
 | 
				
			||||||
 | 
											ids, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	spa_list_append(&d->node_list, &n->link);
 | 
						spa_list_append(&d->node_list, &n->link);
 | 
				
			||||||
	d->n_nodes++;
 | 
						d->n_nodes++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,6 +257,8 @@ static struct node *add_node(struct data *d, uint32_t id, const char *name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void remove_node(struct data *d, struct node *n)
 | 
					static void remove_node(struct data *d, struct node *n)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (n->proxy)
 | 
				
			||||||
 | 
							pw_proxy_destroy(n->proxy);
 | 
				
			||||||
	spa_list_remove(&n->link);
 | 
						spa_list_remove(&n->link);
 | 
				
			||||||
	d->n_nodes--;
 | 
						d->n_nodes--;
 | 
				
			||||||
	free(n);
 | 
						free(n);
 | 
				
			||||||
| 
						 | 
					@ -290,7 +397,7 @@ static void print_node(struct data *d, struct driver *i, struct node *n, int y)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		busy = -1;
 | 
							busy = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u  %s%s",
 | 
						mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u %16.16s %s%s",
 | 
				
			||||||
			n->measurement.status != 3 ? "!" : " ",
 | 
								n->measurement.status != 3 ? "!" : " ",
 | 
				
			||||||
			n->id,
 | 
								n->id,
 | 
				
			||||||
			frac.num, frac.denom,
 | 
								frac.num, frac.denom,
 | 
				
			||||||
| 
						 | 
					@ -299,6 +406,7 @@ static void print_node(struct data *d, struct driver *i, struct node *n, int y)
 | 
				
			||||||
			print_perc(buf3, 64, waiting, quantum),
 | 
								print_perc(buf3, 64, waiting, quantum),
 | 
				
			||||||
			print_perc(buf4, 64, busy, quantum),
 | 
								print_perc(buf4, 64, busy, quantum),
 | 
				
			||||||
			i->xrun_count + n->errors,
 | 
								i->xrun_count + n->errors,
 | 
				
			||||||
 | 
								n->measurement.status != 3 ? "" : n->format,
 | 
				
			||||||
			n->driver == n ? "" : " + ",
 | 
								n->driver == n ? "" : " + ",
 | 
				
			||||||
			n->name);
 | 
								n->name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -310,7 +418,7 @@ static void do_refresh(struct data *d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wclear(d->win);
 | 
						wclear(d->win);
 | 
				
			||||||
	wattron(d->win, A_REVERSE);
 | 
						wattron(d->win, A_REVERSE);
 | 
				
			||||||
	wprintw(d->win, "%-*.*s", COLS, COLS, "S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR  NAME ");
 | 
						wprintw(d->win, "%-*.*s", COLS, COLS, "S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR FORMAT           NAME ");
 | 
				
			||||||
	wattroff(d->win, A_REVERSE);
 | 
						wattroff(d->win, A_REVERSE);
 | 
				
			||||||
	wprintw(d->win, "\n");
 | 
						wprintw(d->win, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,6 +435,7 @@ static void do_refresh(struct data *d)
 | 
				
			||||||
				f->driver = f;
 | 
									f->driver = f;
 | 
				
			||||||
				spa_zero(f->measurement);
 | 
									spa_zero(f->measurement);
 | 
				
			||||||
				spa_zero(f->info);
 | 
									spa_zero(f->info);
 | 
				
			||||||
 | 
									spa_zero(f->format);
 | 
				
			||||||
				f->errors = 0;
 | 
									f->errors = 0;
 | 
				
			||||||
				f->last_error_status = 0;
 | 
									f->last_error_status = 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue