• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5 
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10 
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15 
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <pulse/volume.h>
25 #include <pulse/xmalloc.h>
26 #include <pulse/timeval.h>
27 
28 #include <pulsecore/module.h>
29 #include <pulsecore/client.h>
30 #include <pulsecore/card.h>
31 #include <pulsecore/sink.h>
32 #include <pulsecore/source.h>
33 #include <pulsecore/sink-input.h>
34 #include <pulsecore/source-output.h>
35 #include <pulsecore/strbuf.h>
36 #include <pulsecore/core-scache.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/core-util.h>
39 #include <pulsecore/namereg.h>
40 
41 #include "cli-text.h"
42 
pa_module_list_to_string(pa_core * c)43 char *pa_module_list_to_string(pa_core *c) {
44     pa_strbuf *s;
45     pa_module *m;
46     uint32_t idx = PA_IDXSET_INVALID;
47     pa_assert(c);
48 
49     s = pa_strbuf_new();
50 
51     pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules));
52 
53     PA_IDXSET_FOREACH(m, c->modules, idx) {
54         char *t;
55 
56         pa_strbuf_printf(s, "    index: %u\n"
57                          "\tname: <%s>\n"
58                          "\targument: <%s>\n"
59                          "\tused: %i\n"
60                          "\tload once: %s\n",
61                          m->index,
62                          m->name,
63                          pa_strempty(m->argument),
64                          pa_module_get_n_used(m),
65                          pa_yes_no(m->load_once));
66 
67         t = pa_proplist_to_string_sep(m->proplist, "\n\t\t");
68         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
69         pa_xfree(t);
70     }
71 
72     return pa_strbuf_to_string_free(s);
73 }
74 
pa_client_list_to_string(pa_core * c)75 char *pa_client_list_to_string(pa_core *c) {
76     pa_strbuf *s;
77     pa_client *client;
78     uint32_t idx = PA_IDXSET_INVALID;
79     pa_assert(c);
80 
81     s = pa_strbuf_new();
82 
83     pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients));
84 
85     PA_IDXSET_FOREACH(client, c->clients, idx) {
86         char *t;
87         pa_strbuf_printf(
88                 s,
89                 "    index: %u\n"
90                 "\tdriver: <%s>\n",
91                 client->index,
92                 client->driver);
93 
94         if (client->module)
95             pa_strbuf_printf(s, "\towner module: %u\n", client->module->index);
96 
97         t = pa_proplist_to_string_sep(client->proplist, "\n\t\t");
98         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
99         pa_xfree(t);
100     }
101 
102     return pa_strbuf_to_string_free(s);
103 }
104 
append_port_list(pa_strbuf * s,pa_hashmap * ports)105 static void append_port_list(pa_strbuf *s, pa_hashmap *ports) {
106     pa_device_port *p;
107     void *state;
108 
109     pa_assert(ports);
110 
111     if (pa_hashmap_isempty(ports))
112         return;
113 
114     pa_strbuf_puts(s, "\tports:\n");
115     PA_HASHMAP_FOREACH(p, ports, state) {
116         char *t = pa_proplist_to_string_sep(p->proplist, "\n\t\t\t\t");
117         pa_strbuf_printf(s, "\t\t%s: %s (priority %u, latency offset %" PRId64 " usec, available: %s)\n",
118             p->name, p->description, p->priority, p->latency_offset,
119             pa_available_to_string(p->available));
120         pa_strbuf_printf(s, "\t\t\tproperties:\n\t\t\t\t%s\n", t);
121         pa_xfree(t);
122     }
123 }
124 
pa_card_list_to_string(pa_core * c)125 char *pa_card_list_to_string(pa_core *c) {
126     pa_strbuf *s;
127     pa_card *card;
128     uint32_t idx = PA_IDXSET_INVALID;
129     pa_assert(c);
130 
131     s = pa_strbuf_new();
132 
133     pa_strbuf_printf(s, "%u card(s) available.\n", pa_idxset_size(c->cards));
134 
135     PA_IDXSET_FOREACH(card, c->cards, idx) {
136         char *t;
137         pa_sink *sink;
138         pa_source *source;
139         uint32_t sidx;
140         pa_card_profile *profile;
141         void *state;
142 
143         pa_strbuf_printf(
144                 s,
145                 "    index: %u\n"
146                 "\tname: <%s>\n"
147                 "\tdriver: <%s>\n",
148                 card->index,
149                 card->name,
150                 card->driver);
151 
152         if (card->module)
153             pa_strbuf_printf(s, "\towner module: %u\n", card->module->index);
154 
155         t = pa_proplist_to_string_sep(card->proplist, "\n\t\t");
156         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
157         pa_xfree(t);
158 
159         pa_strbuf_puts(s, "\tprofiles:\n");
160         PA_HASHMAP_FOREACH(profile, card->profiles, state)
161             pa_strbuf_printf(s, "\t\t%s: %s (priority %u, available: %s)\n", profile->name, profile->description,
162                              profile->priority, pa_available_to_string(profile->available));
163 
164         pa_strbuf_printf(
165                 s,
166                 "\tactive profile: <%s>\n",
167                 card->active_profile->name);
168 
169         if (!pa_idxset_isempty(card->sinks)) {
170             pa_strbuf_puts(s, "\tsinks:\n");
171             PA_IDXSET_FOREACH(sink, card->sinks, sidx)
172                 pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", sink->name, sink->index, pa_strna(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
173         }
174 
175         if (!pa_idxset_isempty(card->sources)) {
176             pa_strbuf_puts(s, "\tsources:\n");
177             PA_IDXSET_FOREACH(source, card->sources, sidx)
178                 pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", source->name, source->index, pa_strna(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)));
179         }
180 
181         append_port_list(s, card->ports);
182     }
183 
184     return pa_strbuf_to_string_free(s);
185 }
186 
pa_sink_list_to_string(pa_core * c)187 char *pa_sink_list_to_string(pa_core *c) {
188     pa_strbuf *s;
189     pa_sink *sink;
190     uint32_t idx = PA_IDXSET_INVALID;
191     pa_assert(c);
192 
193     s = pa_strbuf_new();
194 
195     pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
196 
197     PA_IDXSET_FOREACH(sink, c->sinks, idx) {
198         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
199             cv[PA_CVOLUME_SNPRINT_VERBOSE_MAX],
200             v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
201             cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
202         const char *cmn;
203         char suspend_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
204 
205         cmn = pa_channel_map_to_pretty_name(&sink->channel_map);
206 
207         pa_strbuf_printf(
208             s,
209             "  %c index: %u\n"
210             "\tname: <%s>\n"
211             "\tdriver: <%s>\n"
212             "\tflags: %s%s%s%s%s%s%s%s\n"
213             "\tstate: %s\n"
214             "\tsuspend cause: %s\n"
215             "\tpriority: %u\n"
216             "\tvolume: %s\n"
217             "\t        balance %0.2f\n"
218             "\tbase volume: %s\n"
219             "\tvolume steps: %u\n"
220             "\tmuted: %s\n"
221             "\tcurrent latency: %0.2f ms\n"
222             "\tmax request: %lu KiB\n"
223             "\tmax rewind: %lu KiB\n"
224             "\tmonitor source: %u\n"
225             "\tsample spec: %s\n"
226             "\tchannel map: %s%s%s\n"
227             "\tused by: %u\n"
228             "\tlinked by: %u\n",
229             sink == c->default_sink ? '*' : ' ',
230             sink->index,
231             sink->name,
232             sink->driver,
233             sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
234             sink->flags & PA_SINK_NETWORK ? "NETWORK " : "",
235             sink->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
236             sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
237             sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
238             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
239             sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "",
240             sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
241             pa_sink_state_to_string(sink->state),
242             pa_suspend_cause_to_string(sink->suspend_cause, suspend_cause_buf),
243             sink->priority,
244             pa_cvolume_snprint_verbose(cv,
245                                        sizeof(cv),
246                                        pa_sink_get_volume(sink, false),
247                                        &sink->channel_map,
248                                        sink->flags & PA_SINK_DECIBEL_VOLUME),
249             pa_cvolume_get_balance(pa_sink_get_volume(sink, false), &sink->channel_map),
250             pa_volume_snprint_verbose(v, sizeof(v), sink->base_volume, sink->flags & PA_SINK_DECIBEL_VOLUME),
251             sink->n_volume_steps,
252             pa_yes_no(pa_sink_get_mute(sink, false)),
253             (double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC,
254             (unsigned long) pa_sink_get_max_request(sink) / 1024,
255             (unsigned long) pa_sink_get_max_rewind(sink) / 1024,
256             sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
257             pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec),
258             pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map),
259             cmn ? "\n\t             " : "",
260             cmn ? cmn : "",
261             pa_sink_used_by(sink),
262             pa_sink_linked_by(sink));
263 
264         if (sink->flags & PA_SINK_DYNAMIC_LATENCY) {
265             pa_usec_t min_latency, max_latency;
266             pa_sink_get_latency_range(sink, &min_latency, &max_latency);
267 
268             pa_strbuf_printf(
269                     s,
270                     "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n",
271                     (double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
272                     (double) min_latency / PA_USEC_PER_MSEC,
273                     (double) max_latency / PA_USEC_PER_MSEC);
274         } else
275             pa_strbuf_printf(
276                     s,
277                     "\tfixed latency: %0.2f ms\n",
278                     (double) pa_sink_get_fixed_latency(sink) / PA_USEC_PER_MSEC);
279 
280         if (sink->card)
281             pa_strbuf_printf(s, "\tcard: %u <%s>\n", sink->card->index, sink->card->name);
282         if (sink->module)
283             pa_strbuf_printf(s, "\tmodule: %u\n", sink->module->index);
284 
285         t = pa_proplist_to_string_sep(sink->proplist, "\n\t\t");
286         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
287         pa_xfree(t);
288 
289         append_port_list(s, sink->ports);
290 
291         if (sink->active_port)
292             pa_strbuf_printf(
293                     s,
294                     "\tactive port: <%s>\n",
295                     sink->active_port->name);
296     }
297 
298     return pa_strbuf_to_string_free(s);
299 }
300 
pa_source_list_to_string(pa_core * c)301 char *pa_source_list_to_string(pa_core *c) {
302     pa_strbuf *s;
303     pa_source *source;
304     uint32_t idx = PA_IDXSET_INVALID;
305     pa_assert(c);
306 
307     s = pa_strbuf_new();
308 
309     pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
310 
311     PA_IDXSET_FOREACH(source, c->sources, idx) {
312         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX],
313             cv[PA_CVOLUME_SNPRINT_VERBOSE_MAX],
314             v[PA_VOLUME_SNPRINT_VERBOSE_MAX],
315             cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
316         const char *cmn;
317         char suspend_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
318 
319         cmn = pa_channel_map_to_pretty_name(&source->channel_map);
320 
321         pa_strbuf_printf(
322             s,
323             "  %c index: %u\n"
324             "\tname: <%s>\n"
325             "\tdriver: <%s>\n"
326             "\tflags: %s%s%s%s%s%s%s\n"
327             "\tstate: %s\n"
328             "\tsuspend cause: %s\n"
329             "\tpriority: %u\n"
330             "\tvolume: %s\n"
331             "\t        balance %0.2f\n"
332             "\tbase volume: %s\n"
333             "\tvolume steps: %u\n"
334             "\tmuted: %s\n"
335             "\tcurrent latency: %0.2f ms\n"
336             "\tmax rewind: %lu KiB\n"
337             "\tsample spec: %s\n"
338             "\tchannel map: %s%s%s\n"
339             "\tused by: %u\n"
340             "\tlinked by: %u\n",
341             source == c->default_source ? '*' : ' ',
342             source->index,
343             source->name,
344             source->driver,
345             source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
346             source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
347             source->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
348             source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
349             source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
350             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
351             source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
352             pa_source_state_to_string(source->state),
353             pa_suspend_cause_to_string(source->suspend_cause, suspend_cause_buf),
354             source->priority,
355             pa_cvolume_snprint_verbose(cv,
356                                        sizeof(cv),
357                                        pa_source_get_volume(source, false),
358                                        &source->channel_map,
359                                        source->flags & PA_SOURCE_DECIBEL_VOLUME),
360             pa_cvolume_get_balance(pa_source_get_volume(source, false), &source->channel_map),
361             pa_volume_snprint_verbose(v, sizeof(v), source->base_volume, source->flags & PA_SOURCE_DECIBEL_VOLUME),
362             source->n_volume_steps,
363             pa_yes_no(pa_source_get_mute(source, false)),
364             (double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
365             (unsigned long) pa_source_get_max_rewind(source) / 1024,
366             pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
367             pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
368             cmn ? "\n\t             " : "",
369             cmn ? cmn : "",
370             pa_source_used_by(source),
371             pa_source_linked_by(source));
372 
373         if (source->flags & PA_SOURCE_DYNAMIC_LATENCY) {
374             pa_usec_t min_latency, max_latency;
375             pa_source_get_latency_range(source, &min_latency, &max_latency);
376 
377             pa_strbuf_printf(
378                     s,
379                     "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n",
380                     (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
381                     (double) min_latency / PA_USEC_PER_MSEC,
382                     (double) max_latency / PA_USEC_PER_MSEC);
383         } else
384             pa_strbuf_printf(
385                     s,
386                     "\tfixed latency: %0.2f ms\n",
387                     (double) pa_source_get_fixed_latency(source) / PA_USEC_PER_MSEC);
388 
389         if (source->monitor_of)
390             pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index);
391         if (source->card)
392             pa_strbuf_printf(s, "\tcard: %u <%s>\n", source->card->index, source->card->name);
393         if (source->module)
394             pa_strbuf_printf(s, "\tmodule: %u\n", source->module->index);
395 
396         t = pa_proplist_to_string_sep(source->proplist, "\n\t\t");
397         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
398         pa_xfree(t);
399 
400         append_port_list(s, source->ports);
401 
402         if (source->active_port)
403             pa_strbuf_printf(
404                     s,
405                     "\tactive port: <%s>\n",
406                     source->active_port->name);
407     }
408 
409     return pa_strbuf_to_string_free(s);
410 }
411 
pa_source_output_list_to_string(pa_core * c)412 char *pa_source_output_list_to_string(pa_core *c) {
413     pa_strbuf *s;
414     pa_source_output *o;
415     uint32_t idx = PA_IDXSET_INVALID;
416     static const char* const state_table[] = {
417         [PA_SOURCE_OUTPUT_INIT] = "INIT",
418         [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING",
419         [PA_SOURCE_OUTPUT_CORKED] = "CORKED",
420         [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED"
421     };
422     pa_assert(c);
423 
424     s = pa_strbuf_new();
425 
426     pa_strbuf_printf(s, "%u source output(s) available.\n", pa_idxset_size(c->source_outputs));
427 
428     PA_IDXSET_FOREACH(o, c->source_outputs, idx) {
429         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_VERBOSE_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28];
430         pa_usec_t cl;
431         const char *cmn;
432         pa_cvolume v;
433         char *volume_str = NULL;
434 
435         cmn = pa_channel_map_to_pretty_name(&o->channel_map);
436 
437         if ((cl = pa_source_output_get_requested_latency(o)) == (pa_usec_t) -1)
438             pa_snprintf(clt, sizeof(clt), "n/a");
439         else
440             pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC);
441 
442         pa_assert(o->source);
443 
444         if (pa_source_output_is_volume_readable(o)) {
445             pa_source_output_get_volume(o, &v, true);
446             volume_str = pa_sprintf_malloc("%s\n\t        balance %0.2f",
447                                            pa_cvolume_snprint_verbose(cv, sizeof(cv), &v, &o->channel_map, true),
448                                            pa_cvolume_get_balance(&v, &o->channel_map));
449         } else
450             volume_str = pa_xstrdup("n/a");
451 
452         pa_strbuf_printf(
453             s,
454             "    index: %u\n"
455             "\tdriver: <%s>\n"
456             "\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n"
457             "\tstate: %s\n"
458             "\tsource: %u <%s>\n"
459             "\tvolume: %s\n"
460             "\tmuted: %s\n"
461             "\tcurrent latency: %0.2f ms\n"
462             "\trequested latency: %s\n"
463             "\tsample spec: %s\n"
464             "\tchannel map: %s%s%s\n"
465             "\tresample method: %s\n",
466             o->index,
467             o->driver,
468             o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
469             o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "",
470             o->flags & PA_SOURCE_OUTPUT_START_CORKED ? "START_CORKED " : "",
471             o->flags & PA_SOURCE_OUTPUT_NO_REMAP ? "NO_REMAP " : "",
472             o->flags & PA_SOURCE_OUTPUT_NO_REMIX ? "NO_REMIX " : "",
473             o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
474             o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "",
475             o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
476             o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
477             o->flags & PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND ? "NO_CREATE_ON_SUSPEND " : "",
478             o->flags & PA_SOURCE_OUTPUT_KILL_ON_SUSPEND ? "KILL_ON_SUSPEND " : "",
479             o->flags & PA_SOURCE_OUTPUT_PASSTHROUGH ? "PASSTHROUGH " : "",
480             state_table[o->state],
481             o->source->index, o->source->name,
482             volume_str,
483             pa_yes_no(o->muted),
484             (double) pa_source_output_get_latency(o, NULL) / PA_USEC_PER_MSEC,
485             clt,
486             pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec),
487             pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
488             cmn ? "\n\t             " : "",
489             cmn ? cmn : "",
490             pa_resample_method_to_string(pa_source_output_get_resample_method(o)));
491 
492         pa_xfree(volume_str);
493 
494         if (o->module)
495             pa_strbuf_printf(s, "\towner module: %u\n", o->module->index);
496         if (o->client)
497             pa_strbuf_printf(s, "\tclient: %u <%s>\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME)));
498         if (o->direct_on_input)
499             pa_strbuf_printf(s, "\tdirect on input: %u\n", o->direct_on_input->index);
500 
501         t = pa_proplist_to_string_sep(o->proplist, "\n\t\t");
502         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
503         pa_xfree(t);
504     }
505 
506     return pa_strbuf_to_string_free(s);
507 }
508 
pa_sink_input_list_to_string(pa_core * c)509 char *pa_sink_input_list_to_string(pa_core *c) {
510     pa_strbuf *s;
511     pa_sink_input *i;
512     uint32_t idx = PA_IDXSET_INVALID;
513     static const char* const state_table[] = {
514         [PA_SINK_INPUT_INIT] = "INIT",
515         [PA_SINK_INPUT_RUNNING] = "RUNNING",
516         [PA_SINK_INPUT_CORKED] = "CORKED",
517         [PA_SINK_INPUT_UNLINKED] = "UNLINKED"
518     };
519 
520     pa_assert(c);
521     s = pa_strbuf_new();
522 
523     pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));
524 
525     PA_IDXSET_FOREACH(i, c->sink_inputs, idx) {
526         char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28];
527         pa_usec_t cl;
528         const char *cmn;
529         pa_cvolume v;
530         char *volume_str = NULL;
531 
532         cmn = pa_channel_map_to_pretty_name(&i->channel_map);
533 
534         if ((cl = pa_sink_input_get_requested_latency(i)) == (pa_usec_t) -1)
535             pa_snprintf(clt, sizeof(clt), "n/a");
536         else
537             pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC);
538 
539         pa_assert(i->sink);
540 
541         if (pa_sink_input_is_volume_readable(i)) {
542             pa_sink_input_get_volume(i, &v, true);
543             volume_str = pa_sprintf_malloc("%s\n\t        balance %0.2f",
544                                            pa_cvolume_snprint_verbose(cv, sizeof(cv), &v, &i->channel_map, true),
545                                            pa_cvolume_get_balance(&v, &i->channel_map));
546         } else
547             volume_str = pa_xstrdup("n/a");
548 
549         pa_strbuf_printf(
550             s,
551             "    index: %u\n"
552             "\tdriver: <%s>\n"
553             "\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n"
554             "\tstate: %s\n"
555             "\tsink: %u <%s>\n"
556             "\tvolume: %s\n"
557             "\tmuted: %s\n"
558             "\tcurrent latency: %0.2f ms\n"
559             "\trequested latency: %s\n"
560             "\tsample spec: %s\n"
561             "\tchannel map: %s%s%s\n"
562             "\tresample method: %s\n",
563             i->index,
564             i->driver,
565             i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
566             i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "",
567             i->flags & PA_SINK_INPUT_START_CORKED ? "START_CORKED " : "",
568             i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "",
569             i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "",
570             i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
571             i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "",
572             i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
573             i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
574             i->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND ? "NO_CREATE_SUSPEND " : "",
575             i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND ? "KILL_ON_SUSPEND " : "",
576             i->flags & PA_SINK_INPUT_PASSTHROUGH ? "PASSTHROUGH " : "",
577             state_table[i->state],
578             i->sink->index, i->sink->name,
579             volume_str,
580             pa_yes_no(i->muted),
581             (double) pa_sink_input_get_latency(i, NULL) / PA_USEC_PER_MSEC,
582             clt,
583             pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
584             pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
585             cmn ? "\n\t             " : "",
586             cmn ? cmn : "",
587             pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));
588 
589         pa_xfree(volume_str);
590 
591         if (i->module)
592             pa_strbuf_printf(s, "\tmodule: %u\n", i->module->index);
593         if (i->client)
594             pa_strbuf_printf(s, "\tclient: %u <%s>\n", i->client->index, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME)));
595 
596         t = pa_proplist_to_string_sep(i->proplist, "\n\t\t");
597         pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
598         pa_xfree(t);
599     }
600 
601     return pa_strbuf_to_string_free(s);
602 }
603 
pa_scache_list_to_string(pa_core * c)604 char *pa_scache_list_to_string(pa_core *c) {
605     pa_strbuf *s;
606     pa_assert(c);
607 
608     s = pa_strbuf_new();
609 
610     pa_strbuf_printf(s, "%u cache entrie(s) available.\n", c->scache ? pa_idxset_size(c->scache) : 0);
611 
612     if (c->scache) {
613         pa_scache_entry *e;
614         uint32_t idx = PA_IDXSET_INVALID;
615 
616         PA_IDXSET_FOREACH(e, c->scache, idx) {
617             double l = 0;
618             char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a", *t;
619             const char *cmn;
620 
621             cmn = pa_channel_map_to_pretty_name(&e->channel_map);
622 
623             if (e->memchunk.memblock) {
624                 pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
625                 pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map);
626                 l = (double) e->memchunk.length / (double) pa_bytes_per_second(&e->sample_spec);
627             }
628 
629             pa_strbuf_printf(
630                 s,
631                 "    name: <%s>\n"
632                 "\tindex: %u\n"
633                 "\tsample spec: %s\n"
634                 "\tchannel map: %s%s%s\n"
635                 "\tlength: %lu\n"
636                 "\tduration: %0.1f s\n"
637                 "\tvolume: %s\n"
638                 "\t        balance %0.2f\n"
639                 "\tlazy: %s\n"
640                 "\tfilename: <%s>\n",
641                 e->name,
642                 e->index,
643                 ss,
644                 cm,
645                 cmn ? "\n\t             " : "",
646                 cmn ? cmn : "",
647                 (long unsigned)(e->memchunk.memblock ? e->memchunk.length : 0),
648                 l,
649                 e->volume_is_set ? pa_cvolume_snprint_verbose(cv, sizeof(cv), &e->volume, &e->channel_map, true) : "n/a",
650                 (e->memchunk.memblock && e->volume_is_set) ? pa_cvolume_get_balance(&e->volume, &e->channel_map) : 0.0f,
651                 pa_yes_no(e->lazy),
652                 e->filename ? e->filename : "n/a");
653 
654             t = pa_proplist_to_string_sep(e->proplist, "\n\t\t");
655             pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t);
656             pa_xfree(t);
657         }
658     }
659 
660     return pa_strbuf_to_string_free(s);
661 }
662 
pa_full_status_string(pa_core * c)663 char *pa_full_status_string(pa_core *c) {
664     pa_strbuf *s;
665     int i;
666 
667     s = pa_strbuf_new();
668 
669     for (i = 0; i < 8; i++) {
670         char *t = NULL;
671 
672         switch (i) {
673             case 0:
674                 t = pa_sink_list_to_string(c);
675                 break;
676             case 1:
677                 t = pa_source_list_to_string(c);
678                 break;
679             case 2:
680                 t = pa_sink_input_list_to_string(c);
681                 break;
682             case 3:
683                 t = pa_source_output_list_to_string(c);
684                 break;
685             case 4:
686                 t = pa_client_list_to_string(c);
687                 break;
688             case 5:
689                 t = pa_card_list_to_string(c);
690                 break;
691             case 6:
692                 t = pa_module_list_to_string(c);
693                 break;
694             case 7:
695                 t = pa_scache_list_to_string(c);
696                 break;
697         }
698 
699         pa_strbuf_puts(s, t);
700         pa_xfree(t);
701     }
702 
703     return pa_strbuf_to_string_free(s);
704 }
705