LADI
/
spa
1
Fork 0

pw-top: improve output

Show the node state in the S column
Use the node state to show or hide info, this will only show info for
active nodes.
Do redraw updates when something important changes
Update man page
This commit is contained in:
Wim Taymans 2022-10-25 16:22:11 +02:00
parent f5f4be5109
commit d247db8d26
2 changed files with 90 additions and 30 deletions

View File

@ -27,13 +27,15 @@ a tree-like representation.
The columns presented are as follows:
S
Measurement status.
! representing inactive - no connections
Blank representing active
Node status.
E = ERROR
C = CREATING
S = SUSPENDED
I = IDLE
R = RUNNING
ID
The ID of the pipewire node/device, as found in *pw-dump*
The ID of the pipewire node/device, as found in *pw-dump* and *pw-cli*
QUANT
The current quantum (for drivers) and the suggested quantum for follower
@ -135,6 +137,8 @@ FORMAT
For raw audio formats, the layout is <sampleformat> <channels> <samplerate>.
For IEC958 passthrough audio formats, the layout is IEC958 <codec> <samplerate>.
For DSD formats, the layout is <dsd-rate> <channels>.
For Video formats, the layout is <pixelformat> <width>x<height>.

View File

@ -62,8 +62,10 @@ struct measurement {
struct node {
struct spa_list link;
struct data *data;
uint32_t id;
char name[MAX_NAME+1];
enum pw_node_state state;
struct measurement measurement;
struct driver info;
struct node *driver;
@ -73,6 +75,7 @@ struct node {
char format[MAX_FORMAT+1];
struct pw_proxy *proxy;
struct spa_hook proxy_listener;
unsigned int inactive:1;
struct spa_hook object_listener;
};
@ -95,7 +98,7 @@ struct data {
int n_nodes;
struct spa_list node_list;
uint32_t generation;
unsigned have_data:1;
unsigned pending_refresh:1;
WINDOW *win;
};
@ -160,12 +163,29 @@ static const struct pw_proxy_events proxy_events = {
.destroy = on_node_destroy,
};
static void do_refresh(struct data *d);
static void node_info(void *data, const struct pw_node_info *info)
{
struct node *n = data;
if (n->state != info->state) {
n->state = info->state;
do_refresh(n->data);
}
}
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;
if (param == NULL) {
spa_zero(n->format);
goto done;
}
switch (id) {
case SPA_PARAM_Format:
{
@ -238,10 +258,13 @@ static void node_param(void *data, int seq,
default:
break;
}
done:
do_refresh(n->data);
}
static const struct pw_node_events node_events = {
PW_VERSION_NODE,
.info = node_info,
.param = node_param,
};
@ -256,6 +279,7 @@ static struct node *add_node(struct data *d, uint32_t id, const char *name)
strncpy(n->name, name, MAX_NAME);
else
snprintf(n->name, sizeof(n->name), "%u", id);
n->data = d;
n->id = id;
n->driver = n;
n->proxy = pw_registry_bind(d->registry, id, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
@ -272,6 +296,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++;
d->pending_refresh = true;
return n;
}
@ -282,6 +307,7 @@ static void remove_node(struct data *d, struct node *n)
pw_proxy_destroy(n->proxy);
spa_list_remove(&n->link);
d->n_nodes--;
d->pending_refresh = true;
free(n);
}
@ -346,7 +372,10 @@ static int process_follower_block(struct data *d, const struct spa_pod *pod, str
return -ENOENT;
n->measurement = m;
n->driver = point->driver;
if (n->driver != point->driver) {
n->driver = point->driver;
d->pending_refresh = true;
}
n->generation = d->generation;
if (m.status != 3) {
n->errors++;
@ -356,9 +385,9 @@ static int process_follower_block(struct data *d, const struct spa_pod *pod, str
return 0;
}
static const char *print_time(char *buf, size_t len, uint64_t val)
static const char *print_time(char *buf, bool active, size_t len, uint64_t val)
{
if (val == (uint64_t)-1)
if (val == (uint64_t)-1 || !active)
snprintf(buf, len, " --- ");
else if (val == (uint64_t)-2)
snprintf(buf, len, " +++ ");
@ -371,9 +400,9 @@ static const char *print_time(char *buf, size_t len, uint64_t val)
return buf;
}
static const char *print_perc(char *buf, size_t len, uint64_t val, float quantum)
static const char *print_perc(char *buf, bool active, size_t len, uint64_t val, float quantum)
{
if (val == (uint64_t)-1) {
if (val == (uint64_t)-1 || !active) {
snprintf(buf, len, " --- ");
} else if (val == (uint64_t)-2) {
snprintf(buf, len, " +++ ");
@ -384,6 +413,23 @@ static const char *print_perc(char *buf, size_t len, uint64_t val, float quantum
return buf;
}
static const char *state_as_string(enum pw_node_state state)
{
switch (state) {
case PW_NODE_STATE_ERROR:
return "E";
case PW_NODE_STATE_CREATING:
return "C";
case PW_NODE_STATE_SUSPENDED:
return "S";
case PW_NODE_STATE_IDLE:
return "I";
case PW_NODE_STATE_RUNNING:
return "R";
}
return "!";
}
static void print_node(struct data *d, struct driver *i, struct node *n, int y)
{
char buf1[64];
@ -393,8 +439,13 @@ static void print_node(struct data *d, struct driver *i, struct node *n, int y)
uint64_t waiting, busy;
float quantum;
struct spa_fraction frac;
bool active;
if (n->driver == n)
active = n->state == PW_NODE_STATE_RUNNING || n->state == PW_NODE_STATE_IDLE;
if (!active)
frac = SPA_FRACTION(0, 0);
else if (n->driver == n)
frac = SPA_FRACTION((uint32_t)(i->clock.duration * i->clock.rate.num), i->clock.rate.denom);
else
frac = SPA_FRACTION(n->measurement.latency.num, n->measurement.latency.denom);
@ -419,19 +470,28 @@ static void print_node(struct data *d, struct driver *i, struct node *n, int y)
busy = -1;
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 ? "!" : " ",
state_as_string(n->state),
n->id,
frac.num, frac.denom,
print_time(buf1, 64, waiting),
print_time(buf2, 64, busy),
print_perc(buf3, 64, waiting, quantum),
print_perc(buf4, 64, busy, quantum),
print_time(buf1, active, 64, waiting),
print_time(buf2, active, 64, busy),
print_perc(buf3, active, 64, waiting, quantum),
print_perc(buf4, active, 64, busy, quantum),
i->xrun_count + n->errors,
n->measurement.status != 3 ? "" : n->format,
active ? n->format : "",
n->driver == n ? "" : " + ",
n->name);
}
static void clear_node(struct node *n)
{
n->driver = n;
spa_zero(n->measurement);
spa_zero(n->info);
n->errors = 0;
n->last_error_status = 0;
}
static void do_refresh(struct data *d)
{
struct node *n, *t, *f;
@ -452,14 +512,8 @@ static void do_refresh(struct data *d)
break;
spa_list_for_each(f, &d->node_list, link) {
if (d->generation > f->generation + 2) {
f->driver = f;
spa_zero(f->measurement);
spa_zero(f->info);
spa_zero(f->format);
f->errors = 0;
f->last_error_status = 0;
}
if (d->generation > f->generation + 22)
clear_node(f);
if (f->driver != n || f == n)
continue;
@ -476,6 +530,7 @@ static void do_refresh(struct data *d)
wclrtobot(d->win);
wrefresh(d->win);
d->pending_refresh = false;
}
static void do_timeout(void *data, uint64_t expirations)
@ -521,10 +576,8 @@ static void profiler_profile(void *data, const struct spa_pod *pod)
if (res < 0)
continue;
}
if (!d->have_data) {
d->have_data = true;
if (d->pending_refresh)
do_refresh(d);
}
}
static const struct pw_profiler_events profiler_events = {
@ -563,7 +616,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);
return;
error_proxy:
@ -577,6 +631,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);
}
static const struct pw_registry_events registry_events = {