mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-12-22 08:56:52 -05:00
sink, source: improve suspend cause logging
Previously the suspend cause was logged as a hexadecimal number, now it's logged as a human-friendly string. Also, the command line interface handled only a subset of causes when printing them, now all suspend causes are printed.
This commit is contained in:
parent
eeee5664fa
commit
f176443181
5 changed files with 80 additions and 15 deletions
|
|
@ -212,6 +212,7 @@ char *pa_sink_list_to_string(pa_core *c) {
|
||||||
v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
|
v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
|
||||||
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
|
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
|
||||||
const char *cmn;
|
const char *cmn;
|
||||||
|
char suspend_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
|
||||||
cmn = pa_channel_map_to_pretty_name(&sink->channel_map);
|
cmn = pa_channel_map_to_pretty_name(&sink->channel_map);
|
||||||
|
|
||||||
|
|
@ -222,7 +223,7 @@ char *pa_sink_list_to_string(pa_core *c) {
|
||||||
"\tdriver: <%s>\n"
|
"\tdriver: <%s>\n"
|
||||||
"\tflags: %s%s%s%s%s%s%s%s\n"
|
"\tflags: %s%s%s%s%s%s%s%s\n"
|
||||||
"\tstate: %s\n"
|
"\tstate: %s\n"
|
||||||
"\tsuspend cause: %s%s%s%s\n"
|
"\tsuspend cause: %s\n"
|
||||||
"\tpriority: %u\n"
|
"\tpriority: %u\n"
|
||||||
"\tvolume: %s\n"
|
"\tvolume: %s\n"
|
||||||
"\t balance %0.2f\n"
|
"\t balance %0.2f\n"
|
||||||
|
|
@ -250,10 +251,7 @@ char *pa_sink_list_to_string(pa_core *c) {
|
||||||
sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "",
|
sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "",
|
||||||
sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
|
sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
|
||||||
pa_sink_state_to_string(pa_sink_get_state(sink)),
|
pa_sink_state_to_string(pa_sink_get_state(sink)),
|
||||||
sink->suspend_cause & PA_SUSPEND_USER ? "USER " : "",
|
pa_suspend_cause_to_string(sink->suspend_cause, suspend_cause_buf),
|
||||||
sink->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "",
|
|
||||||
sink->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "",
|
|
||||||
sink->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "",
|
|
||||||
sink->priority,
|
sink->priority,
|
||||||
pa_cvolume_snprint_verbose(cv,
|
pa_cvolume_snprint_verbose(cv,
|
||||||
sizeof(cv),
|
sizeof(cv),
|
||||||
|
|
@ -328,6 +326,7 @@ char *pa_source_list_to_string(pa_core *c) {
|
||||||
v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
|
v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
|
||||||
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
|
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
|
||||||
const char *cmn;
|
const char *cmn;
|
||||||
|
char suspend_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
|
||||||
cmn = pa_channel_map_to_pretty_name(&source->channel_map);
|
cmn = pa_channel_map_to_pretty_name(&source->channel_map);
|
||||||
|
|
||||||
|
|
@ -338,7 +337,7 @@ char *pa_source_list_to_string(pa_core *c) {
|
||||||
"\tdriver: <%s>\n"
|
"\tdriver: <%s>\n"
|
||||||
"\tflags: %s%s%s%s%s%s%s\n"
|
"\tflags: %s%s%s%s%s%s%s\n"
|
||||||
"\tstate: %s\n"
|
"\tstate: %s\n"
|
||||||
"\tsuspend cause: %s%s%s%s\n"
|
"\tsuspend cause: %s\n"
|
||||||
"\tpriority: %u\n"
|
"\tpriority: %u\n"
|
||||||
"\tvolume: %s\n"
|
"\tvolume: %s\n"
|
||||||
"\t balance %0.2f\n"
|
"\t balance %0.2f\n"
|
||||||
|
|
@ -363,10 +362,7 @@ char *pa_source_list_to_string(pa_core *c) {
|
||||||
source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
|
source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
|
||||||
source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
|
source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
|
||||||
pa_source_state_to_string(pa_source_get_state(source)),
|
pa_source_state_to_string(pa_source_get_state(source)),
|
||||||
source->suspend_cause & PA_SUSPEND_USER ? "USER " : "",
|
pa_suspend_cause_to_string(source->suspend_cause, suspend_cause_buf),
|
||||||
source->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "",
|
|
||||||
source->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "",
|
|
||||||
source->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "",
|
|
||||||
source->priority,
|
source->priority,
|
||||||
pa_cvolume_snprint_verbose(cv,
|
pa_cvolume_snprint_verbose(cv,
|
||||||
sizeof(cv),
|
sizeof(cv),
|
||||||
|
|
|
||||||
|
|
@ -502,3 +502,44 @@ void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
|
||||||
|
|
||||||
c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
|
c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper macro to reduce repetition in pa_suspend_cause_to_string().
|
||||||
|
* Parameters:
|
||||||
|
* char *p: the current position in the write buffer
|
||||||
|
* bool first: is cause_to_check the first cause to be written?
|
||||||
|
* pa_suspend_cause_t cause_bitfield: the causes given to pa_suspend_cause_to_string()
|
||||||
|
* pa_suspend_cause_t cause_to_check: the cause whose presence in cause_bitfield is to be checked
|
||||||
|
*/
|
||||||
|
#define CHECK_CAUSE(p, first, cause_bitfield, cause_to_check) \
|
||||||
|
if (cause_bitfield & PA_SUSPEND_##cause_to_check) { \
|
||||||
|
size_t len = sizeof(#cause_to_check) - 1; \
|
||||||
|
if (!first) { \
|
||||||
|
*p = '|'; \
|
||||||
|
p++; \
|
||||||
|
} \
|
||||||
|
first = false; \
|
||||||
|
memcpy(p, #cause_to_check, len); \
|
||||||
|
p += len; \
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause_bitfield, char buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]) {
|
||||||
|
char *p = buf;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, USER);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, APPLICATION);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, IDLE);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, SESSION);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, PASSTHROUGH);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, INTERNAL);
|
||||||
|
CHECK_CAUSE(p, first, cause_bitfield, UNAVAILABLE);
|
||||||
|
|
||||||
|
if (p == buf) {
|
||||||
|
memcpy(p, "(none)", 6);
|
||||||
|
p += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@
|
||||||
#include <pulsecore/cpu.h>
|
#include <pulsecore/cpu.h>
|
||||||
|
|
||||||
/* This is a bitmask that encodes the cause why a sink/source is
|
/* This is a bitmask that encodes the cause why a sink/source is
|
||||||
* suspended. */
|
* suspended.
|
||||||
|
*
|
||||||
|
* When adding new causes, remember to update pa_suspend_cause_to_string() and
|
||||||
|
* PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE! */
|
||||||
typedef enum pa_suspend_cause {
|
typedef enum pa_suspend_cause {
|
||||||
PA_SUSPEND_USER = 1, /* Exposed to the user via some protocol */
|
PA_SUSPEND_USER = 1, /* Exposed to the user via some protocol */
|
||||||
PA_SUSPEND_APPLICATION = 2, /* Used by the device reservation logic */
|
PA_SUSPEND_APPLICATION = 2, /* Used by the device reservation logic */
|
||||||
|
|
@ -266,4 +269,11 @@ void pa_core_maybe_vacuum(pa_core *c);
|
||||||
pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata);
|
pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata);
|
||||||
void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec);
|
void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec);
|
||||||
|
|
||||||
|
static const size_t PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE =
|
||||||
|
sizeof("USER|APPLICATION|IDLE|SESSION|PASSTHROUGH|INTERNAL|UNAVAILABLE");
|
||||||
|
|
||||||
|
/* Converts the given suspend cause to a string. The string is written to the
|
||||||
|
* provided buffer. The same buffer is the return value of this function. */
|
||||||
|
const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -840,11 +840,17 @@ void pa_sink_set_mixer_dirty(pa_sink *s, bool is_dirty) {
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
|
int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
|
pa_suspend_cause_t old_cause;
|
||||||
|
char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
char new_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
|
||||||
pa_sink_assert_ref(s);
|
pa_sink_assert_ref(s);
|
||||||
pa_assert_ctl_context();
|
pa_assert_ctl_context();
|
||||||
pa_assert(PA_SINK_IS_LINKED(s->state));
|
pa_assert(PA_SINK_IS_LINKED(s->state));
|
||||||
pa_assert(cause != 0);
|
pa_assert(cause != 0);
|
||||||
|
|
||||||
|
old_cause = s->suspend_cause;
|
||||||
|
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
s->suspend_cause |= cause;
|
s->suspend_cause |= cause;
|
||||||
s->monitor_source->suspend_cause |= cause;
|
s->monitor_source->suspend_cause |= cause;
|
||||||
|
|
@ -853,6 +859,11 @@ int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
s->monitor_source->suspend_cause &= ~cause;
|
s->monitor_source->suspend_cause &= ~cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->suspend_cause != old_cause) {
|
||||||
|
pa_log_debug("%s: suspend_cause: %s -> %s", s->name, pa_suspend_cause_to_string(old_cause, old_cause_buf),
|
||||||
|
pa_suspend_cause_to_string(s->suspend_cause, new_cause_buf));
|
||||||
|
}
|
||||||
|
|
||||||
if (!(s->suspend_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
|
if (!(s->suspend_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
|
||||||
/* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
|
/* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
|
||||||
it'll be handled just fine. */
|
it'll be handled just fine. */
|
||||||
|
|
@ -877,8 +888,6 @@ int pa_sink_suspend(pa_sink *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause)
|
if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pa_log_debug("Suspend cause of sink %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
|
|
||||||
|
|
||||||
if (s->suspend_cause)
|
if (s->suspend_cause)
|
||||||
return sink_set_state(s, PA_SINK_SUSPENDED);
|
return sink_set_state(s, PA_SINK_SUSPENDED);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -761,6 +761,10 @@ void pa_source_set_mixer_dirty(pa_source *s, bool is_dirty) {
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
int pa_source_suspend(pa_source *s, bool suspend, pa_suspend_cause_t cause) {
|
int pa_source_suspend(pa_source *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
|
pa_suspend_cause_t old_cause;
|
||||||
|
char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
char new_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
|
||||||
|
|
||||||
pa_source_assert_ref(s);
|
pa_source_assert_ref(s);
|
||||||
pa_assert_ctl_context();
|
pa_assert_ctl_context();
|
||||||
pa_assert(PA_SOURCE_IS_LINKED(s->state));
|
pa_assert(PA_SOURCE_IS_LINKED(s->state));
|
||||||
|
|
@ -769,11 +773,18 @@ int pa_source_suspend(pa_source *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
if (s->monitor_of && cause != PA_SUSPEND_PASSTHROUGH)
|
if (s->monitor_of && cause != PA_SUSPEND_PASSTHROUGH)
|
||||||
return -PA_ERR_NOTSUPPORTED;
|
return -PA_ERR_NOTSUPPORTED;
|
||||||
|
|
||||||
|
old_cause = s->suspend_cause;
|
||||||
|
|
||||||
if (suspend)
|
if (suspend)
|
||||||
s->suspend_cause |= cause;
|
s->suspend_cause |= cause;
|
||||||
else
|
else
|
||||||
s->suspend_cause &= ~cause;
|
s->suspend_cause &= ~cause;
|
||||||
|
|
||||||
|
if (s->suspend_cause != old_cause) {
|
||||||
|
pa_log_debug("%s: suspend_cause: %s -> %s", s->name, pa_suspend_cause_to_string(old_cause, old_cause_buf),
|
||||||
|
pa_suspend_cause_to_string(s->suspend_cause, new_cause_buf));
|
||||||
|
}
|
||||||
|
|
||||||
if (!(s->suspend_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
|
if (!(s->suspend_cause & PA_SUSPEND_SESSION) && (pa_atomic_load(&s->mixer_dirty) != 0)) {
|
||||||
/* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
|
/* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
|
||||||
it'll be handled just fine. */
|
it'll be handled just fine. */
|
||||||
|
|
@ -798,8 +809,6 @@ int pa_source_suspend(pa_source *s, bool suspend, pa_suspend_cause_t cause) {
|
||||||
if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
|
if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
|
|
||||||
|
|
||||||
if (s->suspend_cause)
|
if (s->suspend_cause)
|
||||||
return source_set_state(s, PA_SOURCE_SUSPENDED);
|
return source_set_state(s, PA_SOURCE_SUSPENDED);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue