mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-15 08:56:38 -05:00
pw-mon: add support for colored output
Same CLI as pw-dump, i.e. -N, --no-colors, --color=always etc are
supported.
This uses a for-loop macro hack to automatically print prefixes and
suffixes, the with_prefix() macro resolves into the correct printf
statements to insert either just the marker "*" or the ansi sequences
for color/reset. Use of the macro is simply:
```
with_prefix(true, stderr) {
fprintf(stderr, "this will be prefixed\n");
}
```
This commit is contained in:
parent
cafe94efc2
commit
671410b3bf
2 changed files with 98 additions and 29 deletions
|
|
@ -33,6 +33,10 @@ OPTIONS
|
||||||
--version
|
--version
|
||||||
Show version information.
|
Show version information.
|
||||||
|
|
||||||
|
-N | --color=WHEN
|
||||||
|
Whether to use color, one of 'never', 'always', or 'auto'. The
|
||||||
|
default is 'auto'. **-N** is equivalent to **--color=never**.
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <spa/utils/result.h>
|
#include <spa/utils/result.h>
|
||||||
#include <spa/utils/string.h>
|
#include <spa/utils/string.h>
|
||||||
|
#include <spa/utils/ansi.h>
|
||||||
#include <spa/debug/pod.h>
|
#include <spa/debug/pod.h>
|
||||||
#include <spa/debug/format.h>
|
#include <spa/debug/format.h>
|
||||||
#include <spa/debug/types.h>
|
#include <spa/debug/types.h>
|
||||||
|
|
@ -38,6 +40,20 @@ struct proxy_data;
|
||||||
|
|
||||||
typedef void (*print_func_t) (struct proxy_data *data);
|
typedef void (*print_func_t) (struct proxy_data *data);
|
||||||
|
|
||||||
|
static struct pprefix {
|
||||||
|
const char *prefix;
|
||||||
|
const char *suffix;
|
||||||
|
} pprefix[2] = {
|
||||||
|
{ .prefix = " ", .suffix = "" },
|
||||||
|
{ .prefix = "*", .suffix = "" },
|
||||||
|
};
|
||||||
|
|
||||||
|
#define with_prefix(use_prefix_, stream_) \
|
||||||
|
for (bool once_ = !!fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).prefix); \
|
||||||
|
once_; \
|
||||||
|
once_ = false, fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).suffix))
|
||||||
|
|
||||||
|
|
||||||
struct param {
|
struct param {
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
@ -155,41 +171,51 @@ static void event_param(void *object, int seq, uint32_t id,
|
||||||
spa_list_append(&data->param_list, &p->link);
|
spa_list_append(&data->param_list, &p->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_params(struct proxy_data *data, const char *mark)
|
static void print_params(struct proxy_data *data, bool use_prefix)
|
||||||
{
|
{
|
||||||
struct param *p;
|
struct param *p;
|
||||||
|
|
||||||
fprintf(stderr, "%s\tparams:\n", mark);
|
with_prefix(use_prefix, stderr) {
|
||||||
|
fprintf(stderr, "\tparams:\n");
|
||||||
|
}
|
||||||
|
|
||||||
spa_list_for_each(p, &data->param_list, link) {
|
spa_list_for_each(p, &data->param_list, link) {
|
||||||
fprintf(stderr, "%s\t id:%u (%s)\n", p->changed ? mark : " ", p->id,
|
with_prefix(p->changed, stderr) {
|
||||||
spa_debug_type_find_name(spa_type_param, p->id));
|
fprintf(stderr, "\t id:%u (%s)\n",
|
||||||
if (spa_pod_is_object_type(p->param, SPA_TYPE_OBJECT_Format))
|
p->id,
|
||||||
spa_debug_format(10, NULL, p->param);
|
spa_debug_type_find_name(spa_type_param, p->id));
|
||||||
else
|
if (spa_pod_is_object_type(p->param, SPA_TYPE_OBJECT_Format))
|
||||||
spa_debug_pod(10, NULL, p->param);
|
spa_debug_format(10, NULL, p->param);
|
||||||
|
else
|
||||||
|
spa_debug_pod(10, NULL, p->param);
|
||||||
|
}
|
||||||
p->changed = false;
|
p->changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_properties(const struct spa_dict *props, const char *mark)
|
static void print_properties(const struct spa_dict *props, bool use_prefix)
|
||||||
{
|
{
|
||||||
const struct spa_dict_item *item;
|
const struct spa_dict_item *item;
|
||||||
|
|
||||||
fprintf(stderr, "%s\tproperties:\n", mark);
|
with_prefix(use_prefix, stderr) {
|
||||||
if (props == NULL || props->n_items == 0) {
|
fprintf(stderr, "\tproperties:\n");
|
||||||
fprintf(stderr, "\t\tnone\n");
|
if (props == NULL || props->n_items == 0) {
|
||||||
return;
|
fprintf(stderr, "\t\tnone\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_dict_for_each(item, props) {
|
spa_dict_for_each(item, props) {
|
||||||
if (item->value)
|
with_prefix(use_prefix, stderr) {
|
||||||
fprintf(stderr, "%s\t\t%s = \"%s\"\n", mark, item->key, item->value);
|
if (item->value)
|
||||||
else
|
fprintf(stderr, "\t\t%s = \"%s\"\n", item->key, item->value);
|
||||||
fprintf(stderr, "%s\t\t%s = (null)\n", mark, item->key);
|
else
|
||||||
|
fprintf(stderr, "\t\t%s = (null)\n", item->key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MARK_CHANGE(f) ((print_mark && ((info)->change_mask & (f))) ? "*" : " ")
|
#define MARK_CHANGE(f) (!!(print_mark && ((info)->change_mask & (f))))
|
||||||
|
|
||||||
static void on_core_info(void *data, const struct pw_core_info *info)
|
static void on_core_info(void *data, const struct pw_core_info *info)
|
||||||
{
|
{
|
||||||
|
|
@ -262,12 +288,18 @@ static void print_node(struct proxy_data *data)
|
||||||
fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version);
|
fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version);
|
||||||
if (print_all) {
|
if (print_all) {
|
||||||
print_params(data, MARK_CHANGE(PW_NODE_CHANGE_MASK_PARAMS));
|
print_params(data, MARK_CHANGE(PW_NODE_CHANGE_MASK_PARAMS));
|
||||||
fprintf(stderr, "%s\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS),
|
with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), stderr) {
|
||||||
|
fprintf(stderr, "\tinput ports: %u/%u\n",
|
||||||
info->n_input_ports, info->max_input_ports);
|
info->n_input_ports, info->max_input_ports);
|
||||||
fprintf(stderr, "%s\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS),
|
}
|
||||||
|
with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), stderr) {
|
||||||
|
fprintf(stderr, "\toutput ports: %u/%u\n",
|
||||||
info->n_output_ports, info->max_output_ports);
|
info->n_output_ports, info->max_output_ports);
|
||||||
fprintf(stderr, "%s\tstate: \"%s\"", MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE),
|
}
|
||||||
|
with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE), stderr) {
|
||||||
|
fprintf(stderr, "\tstate: \"%s\"",
|
||||||
pw_node_state_as_string(info->state));
|
pw_node_state_as_string(info->state));
|
||||||
|
}
|
||||||
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
||||||
fprintf(stderr, " \"%s\"\n", info->error);
|
fprintf(stderr, " \"%s\"\n", info->error);
|
||||||
else
|
else
|
||||||
|
|
@ -459,17 +491,21 @@ static void link_event_info(void *object, const struct pw_link_info *info)
|
||||||
fprintf(stderr, "\tinput-node-id: %u\n", info->input_node_id);
|
fprintf(stderr, "\tinput-node-id: %u\n", info->input_node_id);
|
||||||
fprintf(stderr, "\tinput-port-id: %u\n", info->input_port_id);
|
fprintf(stderr, "\tinput-port-id: %u\n", info->input_port_id);
|
||||||
if (print_all) {
|
if (print_all) {
|
||||||
fprintf(stderr, "%s\tstate: \"%s\"", MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE),
|
with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE), stderr) {
|
||||||
|
fprintf(stderr, "\tstate: \"%s\"",
|
||||||
pw_link_state_as_string(info->state));
|
pw_link_state_as_string(info->state));
|
||||||
|
}
|
||||||
if (info->state == PW_LINK_STATE_ERROR && info->error)
|
if (info->state == PW_LINK_STATE_ERROR && info->error)
|
||||||
fprintf(stderr, " \"%s\"\n", info->error);
|
fprintf(stderr, " \"%s\"\n", info->error);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "%s\tformat:\n", MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT));
|
with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT), stderr) {
|
||||||
if (info->format)
|
fprintf(stderr, "\tformat:\n");
|
||||||
spa_debug_format(2, NULL, info->format);
|
if (info->format)
|
||||||
else
|
spa_debug_format(2, NULL, info->format);
|
||||||
fprintf(stderr, "\t\tnone\n");
|
else
|
||||||
|
fprintf(stderr, "\t\tnone\n");
|
||||||
|
}
|
||||||
print_properties(info->props, MARK_CHANGE(PW_LINK_CHANGE_MASK_PROPS));
|
print_properties(info->props, MARK_CHANGE(PW_LINK_CHANGE_MASK_PROPS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -617,7 +653,7 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
|
fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
|
||||||
PW_PERMISSION_ARGS(permissions));
|
PW_PERMISSION_ARGS(permissions));
|
||||||
fprintf(stderr, "\ttype: %s (version %d)\n", type, version);
|
fprintf(stderr, "\ttype: %s (version %d)\n", type, version);
|
||||||
print_properties(props, " ");
|
print_properties(props, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -710,7 +746,9 @@ static void show_help(const char *name)
|
||||||
fprintf(stdout, "%s [options]\n"
|
fprintf(stdout, "%s [options]\n"
|
||||||
" -h, --help Show this help\n"
|
" -h, --help Show this help\n"
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -r, --remote Remote daemon name\n",
|
" -r, --remote Remote daemon name\n"
|
||||||
|
" -N, --no-colors disable color output\n"
|
||||||
|
" -C, --color[=WHEN] whether to enable color support. WHEN is `never`, `always`, or `auto`\n",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -723,12 +761,18 @@ int main(int argc, char *argv[])
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
{ "remote", required_argument, NULL, 'r' },
|
{ "remote", required_argument, NULL, 'r' },
|
||||||
|
{ "no-colors", no_argument, NULL, 'N' },
|
||||||
|
{ "color", optional_argument, NULL, 'C' },
|
||||||
{ NULL, 0, NULL, 0}
|
{ NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
bool colors = false;
|
||||||
|
|
||||||
pw_init(&argc, &argv);
|
pw_init(&argc, &argv);
|
||||||
|
|
||||||
|
if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL)
|
||||||
|
colors = true;
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
|
|
@ -745,12 +789,33 @@ int main(int argc, char *argv[])
|
||||||
case 'r':
|
case 'r':
|
||||||
opt_remote = optarg;
|
opt_remote = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'N' :
|
||||||
|
colors = false;
|
||||||
|
break;
|
||||||
|
case 'C' :
|
||||||
|
if (optarg == NULL || !strcmp(optarg, "auto"))
|
||||||
|
break; /* nothing to do, tty detection was done
|
||||||
|
before parsing options */
|
||||||
|
else if (!strcmp(optarg, "never"))
|
||||||
|
colors = false;
|
||||||
|
else if (!strcmp(optarg, "always"))
|
||||||
|
colors = true;
|
||||||
|
else {
|
||||||
|
show_help(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
show_help(argv[0]);
|
show_help(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (colors) {
|
||||||
|
pprefix[1].prefix = SPA_ANSI_RED "*";
|
||||||
|
pprefix[1].suffix = SPA_ANSI_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
data.loop = pw_main_loop_new(NULL);
|
data.loop = pw_main_loop_new(NULL);
|
||||||
if (data.loop == NULL) {
|
if (data.loop == NULL) {
|
||||||
fprintf(stderr, "can't create main loop: %m\n");
|
fprintf(stderr, "can't create main loop: %m\n");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue