• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11 
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16 
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <pulse/context.h>
26 #include <pulse/direction.h>
27 #include <pulse/xmalloc.h>
28 #include <pulse/fork-detect.h>
29 
30 #include <pulsecore/macro.h>
31 #include <pulsecore/core-util.h>
32 #include <pulsecore/pstream-util.h>
33 
34 #include "internal.h"
35 #include "introspect.h"
36 
37 /*** Statistics ***/
38 
context_stat_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)39 static void context_stat_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
40     pa_operation *o = userdata;
41     pa_stat_info i, *p = &i;
42 
43     pa_assert(pd);
44     pa_assert(o);
45     pa_assert(PA_REFCNT_VALUE(o) >= 1);
46 
47     pa_zero(i);
48 
49     if (!o->context)
50         goto finish;
51 
52     if (command != PA_COMMAND_REPLY) {
53         if (pa_context_handle_error(o->context, command, t, false) < 0)
54             goto finish;
55 
56         p = NULL;
57     } else if (pa_tagstruct_getu32(t, &i.memblock_total) < 0 ||
58                pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 ||
59                pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 ||
60                pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 ||
61                pa_tagstruct_getu32(t, &i.scache_size) < 0 ||
62                !pa_tagstruct_eof(t)) {
63         pa_context_fail(o->context, PA_ERR_PROTOCOL);
64         goto finish;
65     }
66 
67     if (o->callback) {
68         pa_stat_info_cb_t cb = (pa_stat_info_cb_t) o->callback;
69         cb(o->context, p, o->userdata);
70     }
71 
72 finish:
73     pa_operation_done(o);
74     pa_operation_unref(o);
75 }
76 
pa_context_stat(pa_context * c,pa_stat_info_cb_t cb,void * userdata)77 pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata) {
78     return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_cb_t) cb, userdata);
79 }
80 
81 /*** Server Info ***/
82 
context_get_server_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)83 static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
84     pa_operation *o = userdata;
85     pa_server_info i, *p = &i;
86 
87     pa_assert(pd);
88     pa_assert(o);
89     pa_assert(PA_REFCNT_VALUE(o) >= 1);
90 
91     pa_zero(i);
92 
93     if (!o->context)
94         goto finish;
95 
96     if (command != PA_COMMAND_REPLY) {
97         if (pa_context_handle_error(o->context, command, t, false) < 0)
98             goto finish;
99 
100         p = NULL;
101     } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
102                pa_tagstruct_gets(t, &i.server_version) < 0 ||
103                pa_tagstruct_gets(t, &i.user_name) < 0 ||
104                pa_tagstruct_gets(t, &i.host_name) < 0 ||
105                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
106                pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
107                pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
108                pa_tagstruct_getu32(t, &i.cookie) < 0 ||
109                (o->context->version >= 15 &&
110                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0) ||
111                !pa_tagstruct_eof(t)) {
112 
113         pa_context_fail(o->context, PA_ERR_PROTOCOL);
114         goto finish;
115     }
116 
117     if (p && o->context->version < 15)
118         pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
119 
120     if (o->callback) {
121         pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback;
122         cb(o->context, p, o->userdata);
123     }
124 
125 finish:
126     pa_operation_done(o);
127     pa_operation_unref(o);
128 }
129 
pa_context_get_server_info(pa_context * c,pa_server_info_cb_t cb,void * userdata)130 pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata) {
131     return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_cb_t) cb, userdata);
132 }
133 
134 /*** Sink Info ***/
135 
context_get_sink_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)136 static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
137     pa_operation *o = userdata;
138     int eol = 1;
139     pa_sink_info i;
140     uint32_t j;
141 
142     pa_assert(pd);
143     pa_assert(o);
144     pa_assert(PA_REFCNT_VALUE(o) >= 1);
145 
146     /* For safety in case someone use fail: outside the while loop below */
147     pa_zero(i);
148 
149     if (!o->context)
150         goto finish;
151 
152     if (command != PA_COMMAND_REPLY) {
153         if (pa_context_handle_error(o->context, command, t, false) < 0)
154             goto finish;
155 
156         eol = -1;
157     } else {
158 
159         while (!pa_tagstruct_eof(t)) {
160             bool mute;
161             uint32_t flags;
162             uint32_t state;
163             const char *ap = NULL;
164 
165             pa_zero(i);
166             i.proplist = pa_proplist_new();
167             i.base_volume = PA_VOLUME_NORM;
168             i.n_volume_steps = PA_VOLUME_NORM+1;
169             mute = false;
170             state = PA_SINK_INVALID_STATE;
171             i.card = PA_INVALID_INDEX;
172 
173             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
174                 pa_tagstruct_gets(t, &i.name) < 0 ||
175                 pa_tagstruct_gets(t, &i.description) < 0 ||
176                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
177                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
178                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
179                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
180                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
181                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
182                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
183                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
184                 pa_tagstruct_gets(t, &i.driver) < 0 ||
185                 pa_tagstruct_getu32(t, &flags) < 0 ||
186                 (o->context->version >= 13 &&
187                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
188                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
189                 (o->context->version >= 15 &&
190                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
191                   pa_tagstruct_getu32(t, &state) < 0 ||
192                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
193                   pa_tagstruct_getu32(t, &i.card) < 0)) ||
194                 (o->context->version >= 16 &&
195                  (pa_tagstruct_getu32(t, &i.n_ports)))) {
196 
197                 goto fail;
198             }
199 
200             if (o->context->version >= 16) {
201                 if (i.n_ports > 0) {
202                     i.ports = pa_xnew(pa_sink_port_info*, i.n_ports+1);
203                     i.ports[0] = pa_xnew(pa_sink_port_info, i.n_ports);
204 
205                     for (j = 0; j < i.n_ports; j++) {
206                         i.ports[j] = &i.ports[0][j];
207 
208                         if (pa_tagstruct_gets(t, &i.ports[j]->name) < 0 ||
209                             pa_tagstruct_gets(t, &i.ports[j]->description) < 0 ||
210                             pa_tagstruct_getu32(t, &i.ports[j]->priority) < 0) {
211 
212                             goto fail;
213                         }
214 
215                         i.ports[j]->available = PA_PORT_AVAILABLE_UNKNOWN;
216                         if (o->context->version >= 24) {
217                             uint32_t av;
218                             if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
219                                 goto fail;
220                             i.ports[j]->available = av;
221                         }
222                         i.ports[j]->availability_group = NULL;
223                         i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
224                         if (o->context->version >= 34) {
225                             if (pa_tagstruct_gets(t, &i.ports[j]->availability_group) < 0 ||
226                                 pa_tagstruct_getu32(t, &i.ports[j]->type) < 0)
227                                 goto fail;
228                         }
229                     }
230 
231                     i.ports[j] = NULL;
232                 }
233 
234                 if (pa_tagstruct_gets(t, &ap) < 0)
235                     goto fail;
236 
237                 if (ap) {
238                     for (j = 0; j < i.n_ports; j++)
239                         if (pa_streq(i.ports[j]->name, ap)) {
240                             i.active_port = i.ports[j];
241                             break;
242                         }
243                 }
244             }
245 
246             if (o->context->version >= 21) {
247                 uint8_t n_formats;
248                 if (pa_tagstruct_getu8(t, &n_formats) < 0 || n_formats < 1)
249                     goto fail;
250 
251                 i.formats = pa_xnew0(pa_format_info*, n_formats);
252 
253                 for (j = 0; j < n_formats; j++) {
254                     i.n_formats++;
255                     i.formats[j] = pa_format_info_new();
256 
257                     if (pa_tagstruct_get_format_info(t, i.formats[j]) < 0)
258                         goto fail;
259                 }
260             }
261 
262             i.mute = (int) mute;
263             i.flags = (pa_sink_flags_t) flags;
264             i.state = (pa_sink_state_t) state;
265 
266             if (o->callback) {
267                 pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
268                 cb(o->context, &i, 0, o->userdata);
269             }
270 
271             if (i.formats) {
272                 for (j = 0; j < i.n_formats; j++)
273                     pa_format_info_free(i.formats[j]);
274                 pa_xfree(i.formats);
275             }
276             if (i.ports) {
277                 pa_xfree(i.ports[0]);
278                 pa_xfree(i.ports);
279             }
280             pa_proplist_free(i.proplist);
281         }
282     }
283 
284     if (o->callback) {
285         pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
286         cb(o->context, NULL, eol, o->userdata);
287     }
288 
289 finish:
290     pa_operation_done(o);
291     pa_operation_unref(o);
292     return;
293 
294 fail:
295     pa_assert(i.proplist);
296 
297     pa_context_fail(o->context, PA_ERR_PROTOCOL);
298 
299     if (i.formats) {
300         for (j = 0; j < i.n_formats; j++)
301             pa_format_info_free(i.formats[j]);
302         pa_xfree(i.formats);
303     }
304     if (i.ports) {
305         pa_xfree(i.ports[0]);
306         pa_xfree(i.ports);
307     }
308     pa_proplist_free(i.proplist);
309 
310     goto finish;
311 }
312 
pa_context_get_sink_info_list(pa_context * c,pa_sink_info_cb_t cb,void * userdata)313 pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata) {
314     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_cb_t) cb, userdata);
315 }
316 
pa_context_get_sink_info_by_index(pa_context * c,uint32_t idx,pa_sink_info_cb_t cb,void * userdata)317 pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata) {
318     pa_tagstruct *t;
319     pa_operation *o;
320     uint32_t tag;
321 
322     pa_assert(c);
323     pa_assert(PA_REFCNT_VALUE(c) >= 1);
324     pa_assert(cb);
325 
326     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
327     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
328 
329     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
330 
331     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
332     pa_tagstruct_putu32(t, idx);
333     pa_tagstruct_puts(t, NULL);
334     pa_pstream_send_tagstruct(c->pstream, t);
335     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
336 
337     return o;
338 }
339 
pa_context_get_sink_info_by_name(pa_context * c,const char * name,pa_sink_info_cb_t cb,void * userdata)340 pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata) {
341     pa_tagstruct *t;
342     pa_operation *o;
343     uint32_t tag;
344 
345     pa_assert(c);
346     pa_assert(PA_REFCNT_VALUE(c) >= 1);
347     pa_assert(cb);
348 
349     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
350     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
351     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
352 
353     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
354 
355     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
356     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
357     pa_tagstruct_puts(t, name);
358     pa_pstream_send_tagstruct(c->pstream, t);
359     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
360 
361     return o;
362 }
363 
pa_context_set_sink_port_by_index(pa_context * c,uint32_t idx,const char * port,pa_context_success_cb_t cb,void * userdata)364 pa_operation* pa_context_set_sink_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata) {
365     pa_operation *o;
366     pa_tagstruct *t;
367     uint32_t tag;
368 
369     pa_assert(c);
370     pa_assert(PA_REFCNT_VALUE(c) >= 1);
371 
372     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
373     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
374     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
375     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
376 
377     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
378 
379     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_PORT, &tag);
380     pa_tagstruct_putu32(t, idx);
381     pa_tagstruct_puts(t, NULL);
382     pa_tagstruct_puts(t, port);
383     pa_pstream_send_tagstruct(c->pstream, t);
384     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
385 
386     return o;
387 }
388 
pa_context_set_sink_port_by_name(pa_context * c,const char * name,const char * port,pa_context_success_cb_t cb,void * userdata)389 pa_operation* pa_context_set_sink_port_by_name(pa_context *c, const char *name, const char*port, pa_context_success_cb_t cb, void *userdata) {
390     pa_operation *o;
391     pa_tagstruct *t;
392     uint32_t tag;
393 
394     pa_assert(c);
395     pa_assert(PA_REFCNT_VALUE(c) >= 1);
396 
397     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
398     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
399     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
400     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
401 
402     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
403 
404     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_PORT, &tag);
405     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
406     pa_tagstruct_puts(t, name);
407     pa_tagstruct_puts(t, port);
408     pa_pstream_send_tagstruct(c->pstream, t);
409     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
410 
411     return o;
412 }
413 
414 /*** Source info ***/
415 
context_get_source_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)416 static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
417     pa_operation *o = userdata;
418     int eol = 1;
419     pa_source_info i;
420     uint32_t j;
421 
422     pa_assert(pd);
423     pa_assert(o);
424     pa_assert(PA_REFCNT_VALUE(o) >= 1);
425 
426     /* For safety in case someone use fail: outside the while loop below */
427     pa_zero(i);
428 
429     if (!o->context)
430         goto finish;
431 
432     if (command != PA_COMMAND_REPLY) {
433         if (pa_context_handle_error(o->context, command, t, false) < 0)
434             goto finish;
435 
436         eol = -1;
437     } else {
438 
439         while (!pa_tagstruct_eof(t)) {
440             bool mute;
441             uint32_t flags;
442             uint32_t state;
443             const char *ap;
444 
445             pa_zero(i);
446             i.proplist = pa_proplist_new();
447             i.base_volume = PA_VOLUME_NORM;
448             i.n_volume_steps = PA_VOLUME_NORM+1;
449             mute = false;
450             state = PA_SOURCE_INVALID_STATE;
451             i.card = PA_INVALID_INDEX;
452 
453             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
454                 pa_tagstruct_gets(t, &i.name) < 0 ||
455                 pa_tagstruct_gets(t, &i.description) < 0 ||
456                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
457                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
458                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
459                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
460                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
461                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
462                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
463                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
464                 pa_tagstruct_gets(t, &i.driver) < 0 ||
465                 pa_tagstruct_getu32(t, &flags) < 0 ||
466                 (o->context->version >= 13 &&
467                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
468                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
469                 (o->context->version >= 15 &&
470                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
471                   pa_tagstruct_getu32(t, &state) < 0 ||
472                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
473                   pa_tagstruct_getu32(t, &i.card) < 0)) ||
474                 (o->context->version >= 16 &&
475                  (pa_tagstruct_getu32(t, &i.n_ports)))) {
476 
477                 goto fail;
478             }
479 
480             if (o->context->version >= 16) {
481                 if (i.n_ports > 0) {
482                     i.ports = pa_xnew(pa_source_port_info*, i.n_ports+1);
483                     i.ports[0] = pa_xnew(pa_source_port_info, i.n_ports);
484 
485                     for (j = 0; j < i.n_ports; j++) {
486                         i.ports[j] = &i.ports[0][j];
487 
488                         if (pa_tagstruct_gets(t, &i.ports[j]->name) < 0 ||
489                             pa_tagstruct_gets(t, &i.ports[j]->description) < 0 ||
490                             pa_tagstruct_getu32(t, &i.ports[j]->priority) < 0) {
491 
492                             goto fail;
493                         }
494 
495                         i.ports[j]->available = PA_PORT_AVAILABLE_UNKNOWN;
496                         if (o->context->version >= 24) {
497                             uint32_t av;
498                             if (pa_tagstruct_getu32(t, &av) < 0 || av > PA_PORT_AVAILABLE_YES)
499                                 goto fail;
500                             i.ports[j]->available = av;
501                         }
502                         i.ports[j]->availability_group = NULL;
503                         i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
504                         if (o->context->version >= 34) {
505                             if (pa_tagstruct_gets(t, &i.ports[j]->availability_group) < 0 ||
506                                 pa_tagstruct_getu32(t, &i.ports[j]->type))
507                                 goto fail;
508                         }
509                     }
510 
511                     i.ports[j] = NULL;
512                 }
513                 if (pa_tagstruct_gets(t, &ap) < 0)
514                     goto fail;
515 
516                 if (ap) {
517                     for (j = 0; j < i.n_ports; j++)
518                         if (pa_streq(i.ports[j]->name, ap)) {
519                             i.active_port = i.ports[j];
520                             break;
521                         }
522                 }
523             }
524 
525             if (o->context->version >= 22) {
526                 uint8_t n_formats;
527                 if (pa_tagstruct_getu8(t, &n_formats) < 0 || n_formats < 1)
528                     goto fail;
529 
530                 i.formats = pa_xnew0(pa_format_info*, n_formats);
531 
532                 for (j = 0; j < n_formats; j++) {
533                     i.n_formats++;
534                     i.formats[j] = pa_format_info_new();
535 
536                     if (pa_tagstruct_get_format_info(t, i.formats[j]) < 0)
537                         goto fail;
538                 }
539             }
540 
541             i.mute = (int) mute;
542             i.flags = (pa_source_flags_t) flags;
543             i.state = (pa_source_state_t) state;
544 
545             if (o->callback) {
546                 pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
547                 cb(o->context, &i, 0, o->userdata);
548             }
549 
550             if (i.formats) {
551                 for (j = 0; j < i.n_formats; j++)
552                     pa_format_info_free(i.formats[j]);
553                 pa_xfree(i.formats);
554             }
555             if (i.ports) {
556                 pa_xfree(i.ports[0]);
557                 pa_xfree(i.ports);
558             }
559             pa_proplist_free(i.proplist);
560         }
561     }
562 
563     if (o->callback) {
564         pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
565         cb(o->context, NULL, eol, o->userdata);
566     }
567 
568 finish:
569     pa_operation_done(o);
570     pa_operation_unref(o);
571     return;
572 
573 fail:
574     pa_assert(i.proplist);
575 
576     pa_context_fail(o->context, PA_ERR_PROTOCOL);
577 
578     if (i.formats) {
579         for (j = 0; j < i.n_formats; j++)
580             pa_format_info_free(i.formats[j]);
581         pa_xfree(i.formats);
582     }
583     if (i.ports) {
584         pa_xfree(i.ports[0]);
585         pa_xfree(i.ports);
586     }
587     pa_proplist_free(i.proplist);
588 
589     goto finish;
590 }
591 
pa_context_get_source_info_list(pa_context * c,pa_source_info_cb_t cb,void * userdata)592 pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata) {
593     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_cb_t) cb, userdata);
594 }
595 
pa_context_get_source_info_by_index(pa_context * c,uint32_t idx,pa_source_info_cb_t cb,void * userdata)596 pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata) {
597     pa_tagstruct *t;
598     pa_operation *o;
599     uint32_t tag;
600 
601     pa_assert(c);
602     pa_assert(PA_REFCNT_VALUE(c) >= 1);
603     pa_assert(cb);
604 
605     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
606     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
607 
608     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
609 
610     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
611     pa_tagstruct_putu32(t, idx);
612     pa_tagstruct_puts(t, NULL);
613     pa_pstream_send_tagstruct(c->pstream, t);
614     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
615 
616     return o;
617 }
618 
pa_context_get_source_info_by_name(pa_context * c,const char * name,pa_source_info_cb_t cb,void * userdata)619 pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata) {
620     pa_tagstruct *t;
621     pa_operation *o;
622     uint32_t tag;
623 
624     pa_assert(c);
625     pa_assert(PA_REFCNT_VALUE(c) >= 1);
626     pa_assert(cb);
627 
628     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
629     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
630     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
631 
632     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
633 
634     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
635     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
636     pa_tagstruct_puts(t, name);
637     pa_pstream_send_tagstruct(c->pstream, t);
638     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
639 
640     return o;
641 }
642 
pa_context_set_source_port_by_index(pa_context * c,uint32_t idx,const char * port,pa_context_success_cb_t cb,void * userdata)643 pa_operation* pa_context_set_source_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata) {
644     pa_operation *o;
645     pa_tagstruct *t;
646     uint32_t tag;
647 
648     pa_assert(c);
649     pa_assert(PA_REFCNT_VALUE(c) >= 1);
650 
651     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
652     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
653     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
654     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
655 
656     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
657 
658     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_PORT, &tag);
659     pa_tagstruct_putu32(t, idx);
660     pa_tagstruct_puts(t, NULL);
661     pa_tagstruct_puts(t, port);
662     pa_pstream_send_tagstruct(c->pstream, t);
663     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
664 
665     return o;
666 }
667 
pa_context_set_source_port_by_name(pa_context * c,const char * name,const char * port,pa_context_success_cb_t cb,void * userdata)668 pa_operation* pa_context_set_source_port_by_name(pa_context *c, const char *name, const char*port, pa_context_success_cb_t cb, void *userdata) {
669     pa_operation *o;
670     pa_tagstruct *t;
671     uint32_t tag;
672 
673     pa_assert(c);
674     pa_assert(PA_REFCNT_VALUE(c) >= 1);
675 
676     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
677     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
678     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
679     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
680 
681     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
682 
683     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_PORT, &tag);
684     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
685     pa_tagstruct_puts(t, name);
686     pa_tagstruct_puts(t, port);
687     pa_pstream_send_tagstruct(c->pstream, t);
688     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
689 
690     return o;
691 }
692 
693 /*** Client info ***/
694 
context_get_client_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)695 static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
696     pa_operation *o = userdata;
697     int eol = 1;
698 
699     pa_assert(pd);
700     pa_assert(o);
701     pa_assert(PA_REFCNT_VALUE(o) >= 1);
702 
703     if (!o->context)
704         goto finish;
705 
706     if (command != PA_COMMAND_REPLY) {
707         if (pa_context_handle_error(o->context, command, t, false) < 0)
708             goto finish;
709 
710         eol = -1;
711     } else {
712 
713         while (!pa_tagstruct_eof(t)) {
714             pa_client_info i;
715 
716             pa_zero(i);
717             i.proplist = pa_proplist_new();
718 
719             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
720                 pa_tagstruct_gets(t, &i.name) < 0 ||
721                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
722                 pa_tagstruct_gets(t, &i.driver) < 0 ||
723                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
724 
725                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
726                 pa_proplist_free(i.proplist);
727                 goto finish;
728             }
729 
730             if (o->callback) {
731                 pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
732                 cb(o->context, &i, 0, o->userdata);
733             }
734 
735             pa_proplist_free(i.proplist);
736         }
737     }
738 
739     if (o->callback) {
740         pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
741         cb(o->context, NULL, eol, o->userdata);
742     }
743 
744 finish:
745     pa_operation_done(o);
746     pa_operation_unref(o);
747 }
748 
pa_context_get_client_info(pa_context * c,uint32_t idx,pa_client_info_cb_t cb,void * userdata)749 pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata) {
750     pa_tagstruct *t;
751     pa_operation *o;
752     uint32_t tag;
753 
754     pa_assert(c);
755     pa_assert(PA_REFCNT_VALUE(c) >= 1);
756     pa_assert(cb);
757 
758     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
759     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
760     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
761 
762     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
763 
764     t = pa_tagstruct_command(c, PA_COMMAND_GET_CLIENT_INFO, &tag);
765     pa_tagstruct_putu32(t, idx);
766     pa_pstream_send_tagstruct(c->pstream, t);
767     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
768 
769     return o;
770 }
771 
pa_context_get_client_info_list(pa_context * c,pa_client_info_cb_t cb,void * userdata)772 pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata) {
773     return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_cb_t) cb, userdata);
774 }
775 
776 /*** Card info ***/
777 
card_info_free(pa_card_info * i)778 static void card_info_free(pa_card_info* i) {
779     if (i->proplist)
780         pa_proplist_free(i->proplist);
781 
782     pa_xfree(i->profiles);
783 
784     if (i->n_profiles) {
785         uint32_t j;
786 
787         for (j = 0; j < i->n_profiles; j++)
788              pa_xfree(i->profiles2[j]);
789 
790         pa_xfree(i->profiles2);
791     }
792 
793     if (i->ports) {
794         uint32_t j;
795 
796         for (j = 0; j < i->n_ports; j++) {
797             if (i->ports[j]) {
798                 if (i->ports[j]->profiles)
799                     pa_xfree(i->ports[j]->profiles);
800                 if (i->ports[j]->profiles2)
801                     pa_xfree(i->ports[j]->profiles2);
802                 if (i->ports[j]->proplist)
803                     pa_proplist_free(i->ports[j]->proplist);
804             }
805         }
806 
807         pa_xfree(i->ports[0]);
808         pa_xfree(i->ports);
809     }
810 }
811 
fill_card_port_info(pa_context * context,pa_tagstruct * t,pa_card_info * i)812 static int fill_card_port_info(pa_context *context, pa_tagstruct* t, pa_card_info* i) {
813     uint32_t j, k, l;
814 
815     if (pa_tagstruct_getu32(t, &i->n_ports) < 0)
816         return -PA_ERR_PROTOCOL;
817 
818     if (i->n_ports == 0) {
819         i->ports = NULL;
820         return 0;
821     }
822 
823     i->ports = pa_xnew0(pa_card_port_info*, i->n_ports+1);
824     i->ports[0] = pa_xnew0(pa_card_port_info, i->n_ports);
825 
826     for (j = 0; j < i->n_ports; j++) {
827         uint8_t direction;
828         uint32_t available;
829         pa_card_port_info* port = i->ports[j] = &i->ports[0][j];
830 
831         port->proplist = pa_proplist_new();
832 
833         if (pa_tagstruct_gets(t, &port->name) < 0 ||
834             pa_tagstruct_gets(t, &port->description) < 0 ||
835             pa_tagstruct_getu32(t, &port->priority) < 0 ||
836             pa_tagstruct_getu32(t, &available) < 0 ||
837             pa_tagstruct_getu8(t, &direction) < 0 ||
838             !pa_direction_valid(direction) ||
839             pa_tagstruct_get_proplist(t, port->proplist) < 0 ||
840             pa_tagstruct_getu32(t, &port->n_profiles) < 0) {
841 
842             return -PA_ERR_PROTOCOL;
843         }
844 
845         if (available > PA_PORT_AVAILABLE_YES ) {
846             return -PA_ERR_PROTOCOL;
847         }
848 
849         port->direction = direction;
850         port->available = available;
851 
852         if (port->n_profiles > 0) {
853             port->profiles = pa_xnew0(pa_card_profile_info*, i->n_profiles+1);
854             port->profiles2 = pa_xnew0(pa_card_profile_info2*, i->n_profiles+1);
855 
856             for (k = 0; k < port->n_profiles; k++) {
857                 const char* profilename;
858 
859                 if (pa_tagstruct_gets(t, &profilename) < 0)
860                     return -PA_ERR_PROTOCOL;
861 
862                 for (l = 0; l < i->n_profiles; l++) {
863                     if (pa_streq(i->profiles[l].name, profilename)) {
864                         port->profiles[k] = &i->profiles[l];
865                         port->profiles2[k] = i->profiles2[l];
866                         break;
867                     }
868                 }
869 
870                 if (l >= i->n_profiles)
871                     return -PA_ERR_PROTOCOL;
872             }
873         }
874         if (context->version >= 27) {
875             if (pa_tagstruct_gets64(t, &port->latency_offset) < 0)
876                 return -PA_ERR_PROTOCOL;
877         } else
878             port->latency_offset = 0;
879 
880         port->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
881         if (context->version >= 34) {
882             if (pa_tagstruct_gets(t, &port->availability_group) < 0 ||
883                 pa_tagstruct_getu32(t, &port->type) < 0)
884                 return -PA_ERR_PROTOCOL;
885         } else
886             port->availability_group = NULL;
887     }
888 
889     return 0;
890 }
891 
fill_card_profile_info(pa_context * context,pa_tagstruct * t,pa_card_info * i)892 static int fill_card_profile_info(pa_context *context, pa_tagstruct* t, pa_card_info* i) {
893     uint32_t j;
894 
895     i->profiles = pa_xnew0(pa_card_profile_info, i->n_profiles+1);
896     i->profiles2 = pa_xnew0(pa_card_profile_info2*, i->n_profiles+1);
897 
898     for (j = 0; j < i->n_profiles; j++) {
899         if (pa_tagstruct_gets(t, &i->profiles[j].name) < 0 ||
900             pa_tagstruct_gets(t, &i->profiles[j].description) < 0 ||
901             pa_tagstruct_getu32(t, &i->profiles[j].n_sinks) < 0 ||
902             pa_tagstruct_getu32(t, &i->profiles[j].n_sources) < 0 ||
903             pa_tagstruct_getu32(t, &i->profiles[j].priority) < 0)
904                 return -PA_ERR_PROTOCOL;
905 
906         i->profiles2[j] = pa_xnew0(pa_card_profile_info2, 1);
907         i->profiles2[j]->name = i->profiles[j].name;
908         i->profiles2[j]->description = i->profiles[j].description;
909         i->profiles2[j]->n_sinks = i->profiles[j].n_sinks;
910         i->profiles2[j]->n_sources = i->profiles[j].n_sources;
911         i->profiles2[j]->priority = i->profiles[j].priority;
912         i->profiles2[j]->available = 1;
913 
914         if (context->version >= 29) {
915             uint32_t av;
916 
917             if (pa_tagstruct_getu32(t, &av) < 0)
918                 return -PA_ERR_PROTOCOL;
919 
920             i->profiles2[j]->available = av;
921         }
922     }
923 
924     return 0;
925 }
926 
context_get_card_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)927 static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
928     pa_operation *o = userdata;
929     int eol = 1;
930     pa_card_info i;
931 
932     pa_assert(pd);
933     pa_assert(o);
934     pa_assert(PA_REFCNT_VALUE(o) >= 1);
935 
936     if (!o->context)
937         goto finish;
938 
939     if (command != PA_COMMAND_REPLY) {
940         if (pa_context_handle_error(o->context, command, t, false) < 0)
941             goto finish;
942 
943         eol = -1;
944     } else {
945 
946         while (!pa_tagstruct_eof(t)) {
947             uint32_t j;
948             const char*ap;
949 
950             pa_zero(i);
951 
952             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
953                 pa_tagstruct_gets(t, &i.name) < 0 ||
954                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
955                 pa_tagstruct_gets(t, &i.driver) < 0 ||
956                 pa_tagstruct_getu32(t, &i.n_profiles) < 0)
957                     goto fail;
958 
959             if (i.n_profiles > 0) {
960                 if (fill_card_profile_info(o->context, t, &i) < 0)
961                     goto fail;
962             }
963 
964             i.proplist = pa_proplist_new();
965 
966             if (pa_tagstruct_gets(t, &ap) < 0 ||
967                 pa_tagstruct_get_proplist(t, i.proplist) < 0) {
968 
969                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
970                 card_info_free(&i);
971                 goto finish;
972             }
973 
974             if (ap) {
975                 for (j = 0; j < i.n_profiles; j++)
976                     if (pa_streq(i.profiles[j].name, ap)) {
977                         i.active_profile = &i.profiles[j];
978                         i.active_profile2 = i.profiles2[j];
979                         break;
980                     }
981             }
982 
983             if (o->context->version >= 26) {
984                 if (fill_card_port_info(o->context, t, &i) < 0)
985                     goto fail;
986             }
987 
988             if (o->callback) {
989                 pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
990                 cb(o->context, &i, 0, o->userdata);
991             }
992 
993             card_info_free(&i);
994         }
995     }
996 
997     if (o->callback) {
998         pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
999         cb(o->context, NULL, eol, o->userdata);
1000     }
1001 
1002 finish:
1003     pa_operation_done(o);
1004     pa_operation_unref(o);
1005     return;
1006 
1007 fail:
1008     pa_context_fail(o->context, PA_ERR_PROTOCOL);
1009     card_info_free(&i);
1010     goto finish;
1011 }
1012 
pa_context_get_card_info_by_index(pa_context * c,uint32_t idx,pa_card_info_cb_t cb,void * userdata)1013 pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata) {
1014     pa_tagstruct *t;
1015     pa_operation *o;
1016     uint32_t tag;
1017 
1018     pa_assert(c);
1019     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1020     pa_assert(cb);
1021 
1022     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1023     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1024     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1025     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
1026 
1027     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1028 
1029     t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
1030     pa_tagstruct_putu32(t, idx);
1031     pa_tagstruct_puts(t, NULL);
1032     pa_pstream_send_tagstruct(c->pstream, t);
1033     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1034 
1035     return o;
1036 }
1037 
pa_context_get_card_info_by_name(pa_context * c,const char * name,pa_card_info_cb_t cb,void * userdata)1038 pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char*name, pa_card_info_cb_t cb, void *userdata) {
1039     pa_tagstruct *t;
1040     pa_operation *o;
1041     uint32_t tag;
1042 
1043     pa_assert(c);
1044     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1045     pa_assert(cb);
1046 
1047     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1048     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1049     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1050     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
1051 
1052     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1053 
1054     t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
1055     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1056     pa_tagstruct_puts(t, name);
1057     pa_pstream_send_tagstruct(c->pstream, t);
1058     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1059 
1060     return o;
1061 }
1062 
pa_context_get_card_info_list(pa_context * c,pa_card_info_cb_t cb,void * userdata)1063 pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata) {
1064     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
1065 
1066     return pa_context_send_simple_command(c, PA_COMMAND_GET_CARD_INFO_LIST, context_get_card_info_callback, (pa_operation_cb_t) cb, userdata);
1067 }
1068 
pa_context_set_card_profile_by_index(pa_context * c,uint32_t idx,const char * profile,pa_context_success_cb_t cb,void * userdata)1069 pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata) {
1070     pa_operation *o;
1071     pa_tagstruct *t;
1072     uint32_t tag;
1073 
1074     pa_assert(c);
1075     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1076 
1077     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1078     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1079     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1080     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
1081 
1082     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1083 
1084     t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
1085     pa_tagstruct_putu32(t, idx);
1086     pa_tagstruct_puts(t, NULL);
1087     pa_tagstruct_puts(t, profile);
1088     pa_pstream_send_tagstruct(c->pstream, t);
1089     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1090 
1091     return o;
1092 }
1093 
pa_context_set_card_profile_by_name(pa_context * c,const char * name,const char * profile,pa_context_success_cb_t cb,void * userdata)1094 pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char *name, const char*profile, pa_context_success_cb_t cb, void *userdata) {
1095     pa_operation *o;
1096     pa_tagstruct *t;
1097     uint32_t tag;
1098 
1099     pa_assert(c);
1100     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1101 
1102     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1103     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1104     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1105     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
1106 
1107     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1108 
1109     t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
1110     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1111     pa_tagstruct_puts(t, name);
1112     pa_tagstruct_puts(t, profile);
1113     pa_pstream_send_tagstruct(c->pstream, t);
1114     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1115 
1116     return o;
1117 }
1118 
1119 /*** Module info ***/
1120 
context_get_module_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)1121 static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1122     pa_operation *o = userdata;
1123     int eol = 1;
1124 
1125     pa_assert(pd);
1126     pa_assert(o);
1127     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1128 
1129     if (!o->context)
1130         goto finish;
1131 
1132     if (command != PA_COMMAND_REPLY) {
1133         if (pa_context_handle_error(o->context, command, t, false) < 0)
1134             goto finish;
1135 
1136         eol = -1;
1137     } else {
1138 
1139         while (!pa_tagstruct_eof(t)) {
1140             pa_module_info i;
1141             bool auto_unload = false;
1142 
1143             pa_zero(i);
1144             i.proplist = pa_proplist_new();
1145 
1146             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1147                 pa_tagstruct_gets(t, &i.name) < 0 ||
1148                 pa_tagstruct_gets(t, &i.argument) < 0 ||
1149                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
1150                 (o->context->version < 15 && pa_tagstruct_get_boolean(t, &auto_unload) < 0) ||
1151                 (o->context->version >= 15 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
1152                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1153                 goto finish;
1154             }
1155 
1156             i.auto_unload = (int) auto_unload;
1157 
1158             if (o->callback) {
1159                 pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
1160                 cb(o->context, &i, 0, o->userdata);
1161             }
1162 
1163             pa_proplist_free(i.proplist);
1164         }
1165     }
1166 
1167     if (o->callback) {
1168         pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
1169         cb(o->context, NULL, eol, o->userdata);
1170     }
1171 
1172 finish:
1173     pa_operation_done(o);
1174     pa_operation_unref(o);
1175 }
1176 
pa_context_get_module_info(pa_context * c,uint32_t idx,pa_module_info_cb_t cb,void * userdata)1177 pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata) {
1178     pa_tagstruct *t;
1179     pa_operation *o;
1180     uint32_t tag;
1181 
1182     pa_assert(c);
1183     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1184     pa_assert(cb);
1185 
1186     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1187     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1188     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1189 
1190     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1191 
1192     t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag);
1193     pa_tagstruct_putu32(t, idx);
1194     pa_pstream_send_tagstruct(c->pstream, t);
1195     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1196 
1197     return o;
1198 }
1199 
pa_context_get_module_info_list(pa_context * c,pa_module_info_cb_t cb,void * userdata)1200 pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata) {
1201     return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_cb_t) cb, userdata);
1202 }
1203 
1204 /*** Sink input info ***/
1205 
context_get_sink_input_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)1206 static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1207     pa_operation *o = userdata;
1208     int eol = 1;
1209 
1210     pa_assert(pd);
1211     pa_assert(o);
1212     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1213 
1214     if (!o->context)
1215         goto finish;
1216 
1217     if (command != PA_COMMAND_REPLY) {
1218         if (pa_context_handle_error(o->context, command, t, false) < 0)
1219             goto finish;
1220 
1221         eol = -1;
1222     } else {
1223 
1224         while (!pa_tagstruct_eof(t)) {
1225             pa_sink_input_info i;
1226             bool mute = false, corked = false, has_volume = false, volume_writable = true;
1227 
1228             pa_zero(i);
1229             i.proplist = pa_proplist_new();
1230             i.format = pa_format_info_new();
1231 
1232             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1233                 pa_tagstruct_gets(t, &i.name) < 0 ||
1234                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
1235                 pa_tagstruct_getu32(t, &i.client) < 0 ||
1236                 pa_tagstruct_getu32(t, &i.sink) < 0 ||
1237                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
1238                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
1239                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
1240                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
1241                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
1242                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
1243                 pa_tagstruct_gets(t, &i.driver) < 0 ||
1244                 (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) ||
1245                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0) ||
1246                 (o->context->version >= 19 && pa_tagstruct_get_boolean(t, &corked) < 0) ||
1247                 (o->context->version >= 20 && (pa_tagstruct_get_boolean(t, &has_volume) < 0 ||
1248                                                pa_tagstruct_get_boolean(t, &volume_writable) < 0)) ||
1249                 (o->context->version >= 21 && pa_tagstruct_get_format_info(t, i.format) < 0)) {
1250 
1251                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1252                 pa_proplist_free(i.proplist);
1253                 pa_format_info_free(i.format);
1254                 goto finish;
1255             }
1256 
1257             i.mute = (int) mute;
1258             i.corked = (int) corked;
1259             i.has_volume = (int) has_volume;
1260             i.volume_writable = (int) volume_writable;
1261 
1262             if (o->callback) {
1263                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
1264                 cb(o->context, &i, 0, o->userdata);
1265             }
1266 
1267             pa_proplist_free(i.proplist);
1268             pa_format_info_free(i.format);
1269         }
1270     }
1271 
1272     if (o->callback) {
1273         pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
1274         cb(o->context, NULL, eol, o->userdata);
1275     }
1276 
1277 finish:
1278     pa_operation_done(o);
1279     pa_operation_unref(o);
1280 }
1281 
pa_context_get_sink_input_info(pa_context * c,uint32_t idx,pa_sink_input_info_cb_t cb,void * userdata)1282 pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) {
1283     pa_tagstruct *t;
1284     pa_operation *o;
1285     uint32_t tag;
1286 
1287     pa_assert(c);
1288     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1289     pa_assert(cb);
1290 
1291     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1292     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1293     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1294 
1295     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1296 
1297     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag);
1298     pa_tagstruct_putu32(t, idx);
1299     pa_pstream_send_tagstruct(c->pstream, t);
1300     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1301 
1302     return o;
1303 }
1304 
pa_context_get_sink_input_info_list(pa_context * c,void (* cb)(pa_context * c,const pa_sink_input_info * i,int is_last,void * userdata),void * userdata)1305 pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) {
1306     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_cb_t) cb, userdata);
1307 }
1308 
1309 /*** Source output info ***/
1310 
context_get_source_output_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)1311 static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1312     pa_operation *o = userdata;
1313     int eol = 1;
1314 
1315     pa_assert(pd);
1316     pa_assert(o);
1317     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1318 
1319     if (!o->context)
1320         goto finish;
1321 
1322     if (command != PA_COMMAND_REPLY) {
1323         if (pa_context_handle_error(o->context, command, t, false) < 0)
1324             goto finish;
1325 
1326         eol = -1;
1327     } else {
1328 
1329         while (!pa_tagstruct_eof(t)) {
1330             pa_source_output_info i;
1331             bool mute = false, corked = false, has_volume = false, volume_writable = true;
1332 
1333             pa_zero(i);
1334             i.proplist = pa_proplist_new();
1335             i.format = pa_format_info_new();
1336 
1337             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1338                 pa_tagstruct_gets(t, &i.name) < 0 ||
1339                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
1340                 pa_tagstruct_getu32(t, &i.client) < 0 ||
1341                 pa_tagstruct_getu32(t, &i.source) < 0 ||
1342                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
1343                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
1344                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
1345                 pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
1346                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
1347                 pa_tagstruct_gets(t, &i.driver) < 0 ||
1348                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0) ||
1349                 (o->context->version >= 19 && pa_tagstruct_get_boolean(t, &corked) < 0) ||
1350                 (o->context->version >= 22 && (pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
1351                                                pa_tagstruct_get_boolean(t, &mute) < 0 ||
1352                                                pa_tagstruct_get_boolean(t, &has_volume) < 0 ||
1353                                                pa_tagstruct_get_boolean(t, &volume_writable) < 0 ||
1354                                                pa_tagstruct_get_format_info(t, i.format) < 0))) {
1355 
1356                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1357                 pa_proplist_free(i.proplist);
1358                 pa_format_info_free(i.format);
1359                 goto finish;
1360             }
1361 
1362             i.mute = (int) mute;
1363             i.corked = (int) corked;
1364             i.has_volume = (int) has_volume;
1365             i.volume_writable = (int) volume_writable;
1366 
1367             if (o->callback) {
1368                 pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
1369                 cb(o->context, &i, 0, o->userdata);
1370             }
1371 
1372             pa_proplist_free(i.proplist);
1373             pa_format_info_free(i.format);
1374         }
1375     }
1376 
1377     if (o->callback) {
1378         pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
1379         cb(o->context, NULL, eol, o->userdata);
1380     }
1381 
1382 finish:
1383     pa_operation_done(o);
1384     pa_operation_unref(o);
1385 }
1386 
pa_context_get_source_output_info(pa_context * c,uint32_t idx,pa_source_output_info_cb_t cb,void * userdata)1387 pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata) {
1388     pa_tagstruct *t;
1389     pa_operation *o;
1390     uint32_t tag;
1391 
1392     pa_assert(c);
1393     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1394     pa_assert(cb);
1395 
1396     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1397     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1398     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1399 
1400     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1401 
1402     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag);
1403     pa_tagstruct_putu32(t, idx);
1404     pa_pstream_send_tagstruct(c->pstream, t);
1405     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1406 
1407     return o;
1408 }
1409 
pa_context_get_source_output_info_list(pa_context * c,pa_source_output_info_cb_t cb,void * userdata)1410 pa_operation* pa_context_get_source_output_info_list(pa_context *c,  pa_source_output_info_cb_t cb, void *userdata) {
1411     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_cb_t) cb, userdata);
1412 }
1413 
1414 /*** Volume manipulation ***/
1415 
pa_context_set_sink_volume_by_index(pa_context * c,uint32_t idx,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1416 pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1417     pa_operation *o;
1418     pa_tagstruct *t;
1419     uint32_t tag;
1420 
1421     pa_assert(c);
1422     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1423     pa_assert(volume);
1424 
1425     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1426     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1427     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1428 
1429     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1430 
1431     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
1432     pa_tagstruct_putu32(t, idx);
1433     pa_tagstruct_puts(t, NULL);
1434     pa_tagstruct_put_cvolume(t, volume);
1435     pa_pstream_send_tagstruct(c->pstream, t);
1436     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1437 
1438     return o;
1439 }
1440 
pa_context_set_sink_volume_by_name(pa_context * c,const char * name,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1441 pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1442     pa_operation *o;
1443     pa_tagstruct *t;
1444     uint32_t tag;
1445 
1446     pa_assert(c);
1447     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1448     pa_assert(name);
1449     pa_assert(volume);
1450 
1451     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1452     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1453     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1454     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1455 
1456     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1457 
1458     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
1459     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1460     pa_tagstruct_puts(t, name);
1461     pa_tagstruct_put_cvolume(t, volume);
1462     pa_pstream_send_tagstruct(c->pstream, t);
1463     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1464 
1465     return o;
1466 }
1467 
pa_context_set_sink_mute_by_index(pa_context * c,uint32_t idx,int mute,pa_context_success_cb_t cb,void * userdata)1468 pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1469     pa_operation *o;
1470     pa_tagstruct *t;
1471     uint32_t tag;
1472 
1473     pa_assert(c);
1474     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1475 
1476     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1477     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1478 
1479     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1480 
1481     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
1482     pa_tagstruct_putu32(t, idx);
1483     pa_tagstruct_puts(t, NULL);
1484     pa_tagstruct_put_boolean(t, mute);
1485     pa_pstream_send_tagstruct(c->pstream, t);
1486     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1487 
1488     return o;
1489 }
1490 
pa_context_set_sink_mute_by_name(pa_context * c,const char * name,int mute,pa_context_success_cb_t cb,void * userdata)1491 pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) {
1492     pa_operation *o;
1493     pa_tagstruct *t;
1494     uint32_t tag;
1495 
1496     pa_assert(c);
1497     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1498     pa_assert(name);
1499 
1500     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1501     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1502     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1503 
1504     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1505 
1506     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
1507     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1508     pa_tagstruct_puts(t, name);
1509     pa_tagstruct_put_boolean(t, mute);
1510     pa_pstream_send_tagstruct(c->pstream, t);
1511     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1512 
1513     return o;
1514 }
1515 
pa_context_set_sink_input_volume(pa_context * c,uint32_t idx,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1516 pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1517     pa_operation *o;
1518     pa_tagstruct *t;
1519     uint32_t tag;
1520 
1521     pa_assert(c);
1522     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1523     pa_assert(volume);
1524 
1525     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1526     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1527     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1528     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1529 
1530     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1531 
1532     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag);
1533     pa_tagstruct_putu32(t, idx);
1534     pa_tagstruct_put_cvolume(t, volume);
1535     pa_pstream_send_tagstruct(c->pstream, t);
1536     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1537 
1538     return o;
1539 }
1540 
pa_context_set_sink_input_mute(pa_context * c,uint32_t idx,int mute,pa_context_success_cb_t cb,void * userdata)1541 pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1542     pa_operation *o;
1543     pa_tagstruct *t;
1544     uint32_t tag;
1545 
1546     pa_assert(c);
1547     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1548 
1549     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1550     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1551     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1552     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1553 
1554     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1555 
1556     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_MUTE, &tag);
1557     pa_tagstruct_putu32(t, idx);
1558     pa_tagstruct_put_boolean(t, mute);
1559     pa_pstream_send_tagstruct(c->pstream, t);
1560     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1561 
1562     return o;
1563 }
1564 
pa_context_set_source_volume_by_index(pa_context * c,uint32_t idx,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1565 pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1566     pa_operation *o;
1567     pa_tagstruct *t;
1568     uint32_t tag;
1569 
1570     pa_assert(c);
1571     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1572     pa_assert(volume);
1573 
1574     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1575     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1576     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1577 
1578     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1579 
1580     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
1581     pa_tagstruct_putu32(t, idx);
1582     pa_tagstruct_puts(t, NULL);
1583     pa_tagstruct_put_cvolume(t, volume);
1584     pa_pstream_send_tagstruct(c->pstream, t);
1585     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1586 
1587     return o;
1588 }
1589 
pa_context_set_source_volume_by_name(pa_context * c,const char * name,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1590 pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1591     pa_operation *o;
1592     pa_tagstruct *t;
1593     uint32_t tag;
1594 
1595     pa_assert(c);
1596     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1597     pa_assert(name);
1598     pa_assert(volume);
1599 
1600     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1601     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1602     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1603     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1604 
1605     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1606 
1607     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
1608     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1609     pa_tagstruct_puts(t, name);
1610     pa_tagstruct_put_cvolume(t, volume);
1611     pa_pstream_send_tagstruct(c->pstream, t);
1612     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1613 
1614     return o;
1615 }
1616 
pa_context_set_source_mute_by_index(pa_context * c,uint32_t idx,int mute,pa_context_success_cb_t cb,void * userdata)1617 pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1618     pa_operation *o;
1619     pa_tagstruct *t;
1620     uint32_t tag;
1621 
1622     pa_assert(c);
1623     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1624 
1625     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1626     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1627 
1628     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1629 
1630     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
1631     pa_tagstruct_putu32(t, idx);
1632     pa_tagstruct_puts(t, NULL);
1633     pa_tagstruct_put_boolean(t, mute);
1634     pa_pstream_send_tagstruct(c->pstream, t);
1635     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1636 
1637     return o;
1638 }
1639 
pa_context_set_source_mute_by_name(pa_context * c,const char * name,int mute,pa_context_success_cb_t cb,void * userdata)1640 pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) {
1641     pa_operation *o;
1642     pa_tagstruct *t;
1643     uint32_t tag;
1644 
1645     pa_assert(c);
1646     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1647     pa_assert(name);
1648 
1649     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1650     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1651     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1652 
1653     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1654 
1655     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
1656     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1657     pa_tagstruct_puts(t, name);
1658     pa_tagstruct_put_boolean(t, mute);
1659     pa_pstream_send_tagstruct(c->pstream, t);
1660     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1661 
1662     return o;
1663 }
1664 
pa_context_set_source_output_volume(pa_context * c,uint32_t idx,const pa_cvolume * volume,pa_context_success_cb_t cb,void * userdata)1665 pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1666     pa_operation *o;
1667     pa_tagstruct *t;
1668     uint32_t tag;
1669 
1670     pa_assert(c);
1671     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1672     pa_assert(volume);
1673 
1674     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1675     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1676     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1677     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 22, PA_ERR_NOTSUPPORTED);
1678     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1679 
1680     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1681 
1682     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME, &tag);
1683     pa_tagstruct_putu32(t, idx);
1684     pa_tagstruct_put_cvolume(t, volume);
1685     pa_pstream_send_tagstruct(c->pstream, t);
1686     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1687 
1688     return o;
1689 }
1690 
pa_context_set_source_output_mute(pa_context * c,uint32_t idx,int mute,pa_context_success_cb_t cb,void * userdata)1691 pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1692     pa_operation *o;
1693     pa_tagstruct *t;
1694     uint32_t tag;
1695 
1696     pa_assert(c);
1697     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1698 
1699     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1700     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1701     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1702     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 22, PA_ERR_NOTSUPPORTED);
1703 
1704     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1705 
1706     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_OUTPUT_MUTE, &tag);
1707     pa_tagstruct_putu32(t, idx);
1708     pa_tagstruct_put_boolean(t, mute);
1709     pa_pstream_send_tagstruct(c->pstream, t);
1710     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1711 
1712     return o;
1713 }
1714 
1715 /** Sample Cache **/
1716 
context_get_sample_info_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)1717 static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1718     pa_operation *o = userdata;
1719     int eol = 1;
1720 
1721     pa_assert(pd);
1722     pa_assert(o);
1723     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1724 
1725     if (!o->context)
1726         goto finish;
1727 
1728     if (command != PA_COMMAND_REPLY) {
1729         if (pa_context_handle_error(o->context, command, t, false) < 0)
1730             goto finish;
1731 
1732         eol = -1;
1733     } else {
1734 
1735         while (!pa_tagstruct_eof(t)) {
1736             pa_sample_info i;
1737             bool lazy = false;
1738 
1739             pa_zero(i);
1740             i.proplist = pa_proplist_new();
1741 
1742             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1743                 pa_tagstruct_gets(t, &i.name) < 0 ||
1744                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
1745                 pa_tagstruct_get_usec(t, &i.duration) < 0 ||
1746                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
1747                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
1748                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
1749                 pa_tagstruct_get_boolean(t, &lazy) < 0 ||
1750                 pa_tagstruct_gets(t, &i.filename) < 0 ||
1751                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
1752 
1753                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1754                 goto finish;
1755             }
1756 
1757             i.lazy = (int) lazy;
1758 
1759             if (o->callback) {
1760                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1761                 cb(o->context, &i, 0, o->userdata);
1762             }
1763 
1764             pa_proplist_free(i.proplist);
1765         }
1766     }
1767 
1768     if (o->callback) {
1769         pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1770         cb(o->context, NULL, eol, o->userdata);
1771     }
1772 
1773 finish:
1774     pa_operation_done(o);
1775     pa_operation_unref(o);
1776 }
1777 
pa_context_get_sample_info_by_name(pa_context * c,const char * name,pa_sample_info_cb_t cb,void * userdata)1778 pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata) {
1779     pa_tagstruct *t;
1780     pa_operation *o;
1781     uint32_t tag;
1782 
1783     pa_assert(c);
1784     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1785     pa_assert(cb);
1786 
1787     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1788     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1789     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1790 
1791     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1792 
1793     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1794     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1795     pa_tagstruct_puts(t, name);
1796     pa_pstream_send_tagstruct(c->pstream, t);
1797     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1798 
1799     return o;
1800 }
1801 
pa_context_get_sample_info_by_index(pa_context * c,uint32_t idx,pa_sample_info_cb_t cb,void * userdata)1802 pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata) {
1803     pa_tagstruct *t;
1804     pa_operation *o;
1805     uint32_t tag;
1806 
1807     pa_assert(c);
1808     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1809     pa_assert(cb);
1810 
1811     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1812     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1813     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1814 
1815     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1816 
1817     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1818     pa_tagstruct_putu32(t, idx);
1819     pa_tagstruct_puts(t, NULL);
1820     pa_pstream_send_tagstruct(c->pstream, t);
1821     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1822 
1823     return o;
1824 }
1825 
pa_context_get_sample_info_list(pa_context * c,pa_sample_info_cb_t cb,void * userdata)1826 pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata) {
1827     return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_cb_t) cb, userdata);
1828 }
1829 
command_kill(pa_context * c,uint32_t command,uint32_t idx,pa_context_success_cb_t cb,void * userdata)1830 static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1831     pa_operation *o;
1832     pa_tagstruct *t;
1833     uint32_t tag;
1834 
1835     pa_assert(c);
1836     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1837 
1838     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1839     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1840     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1841 
1842     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1843 
1844     t = pa_tagstruct_command(c, command, &tag);
1845     pa_tagstruct_putu32(t, idx);
1846     pa_pstream_send_tagstruct(c->pstream, t);
1847     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1848 
1849     return o;
1850 }
1851 
pa_context_kill_client(pa_context * c,uint32_t idx,pa_context_success_cb_t cb,void * userdata)1852 pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1853     return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata);
1854 }
1855 
pa_context_kill_sink_input(pa_context * c,uint32_t idx,pa_context_success_cb_t cb,void * userdata)1856 pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1857     return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata);
1858 }
1859 
pa_context_kill_source_output(pa_context * c,uint32_t idx,pa_context_success_cb_t cb,void * userdata)1860 pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1861     return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata);
1862 }
1863 
context_index_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)1864 static void context_index_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1865     pa_operation *o = userdata;
1866     uint32_t idx;
1867 
1868     pa_assert(pd);
1869     pa_assert(o);
1870     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1871 
1872     if (!o->context)
1873         goto finish;
1874 
1875     if (command != PA_COMMAND_REPLY) {
1876         if (pa_context_handle_error(o->context, command, t, false) < 0)
1877             goto finish;
1878 
1879         idx = PA_INVALID_INDEX;
1880     } else if (pa_tagstruct_getu32(t, &idx) ||
1881                !pa_tagstruct_eof(t)) {
1882         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1883         goto finish;
1884     }
1885 
1886     if (o->callback) {
1887         pa_context_index_cb_t cb = (pa_context_index_cb_t) o->callback;
1888         cb(o->context, idx, o->userdata);
1889     }
1890 
1891 finish:
1892     pa_operation_done(o);
1893     pa_operation_unref(o);
1894 }
1895 
pa_context_load_module(pa_context * c,const char * name,const char * argument,pa_context_index_cb_t cb,void * userdata)1896 pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata) {
1897     pa_operation *o;
1898     pa_tagstruct *t;
1899     uint32_t tag;
1900 
1901     pa_assert(c);
1902     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1903 
1904     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1905     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1906     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1907 
1908     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1909 
1910     t = pa_tagstruct_command(c, PA_COMMAND_LOAD_MODULE, &tag);
1911     pa_tagstruct_puts(t, name);
1912     pa_tagstruct_puts(t, argument);
1913     pa_pstream_send_tagstruct(c->pstream, t);
1914     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1915 
1916     return o;
1917 }
1918 
pa_context_unload_module(pa_context * c,uint32_t idx,pa_context_success_cb_t cb,void * userdata)1919 pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1920     return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata);
1921 }
1922 
pa_context_set_port_latency_offset(pa_context * c,const char * card_name,const char * port_name,int64_t offset,pa_context_success_cb_t cb,void * userdata)1923 pa_operation* pa_context_set_port_latency_offset(pa_context *c, const char *card_name, const char *port_name, int64_t offset, pa_context_success_cb_t cb, void *userdata) {
1924     pa_operation *o;
1925     pa_tagstruct *t;
1926     uint32_t tag;
1927 
1928     pa_assert(c);
1929     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1930 
1931     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1932     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1933     PA_CHECK_VALIDITY_RETURN_NULL(c, card_name && *card_name, PA_ERR_INVALID);
1934     PA_CHECK_VALIDITY_RETURN_NULL(c, port_name && *port_name, PA_ERR_INVALID);
1935     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 27, PA_ERR_NOTSUPPORTED);
1936 
1937     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1938 
1939     t = pa_tagstruct_command(c, PA_COMMAND_SET_PORT_LATENCY_OFFSET, &tag);
1940     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1941     pa_tagstruct_puts(t, card_name);
1942     pa_tagstruct_puts(t, port_name);
1943     pa_tagstruct_puts64(t, offset);
1944     pa_pstream_send_tagstruct(c->pstream, t);
1945     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1946 
1947     return o;
1948 }
1949 
1950 /*** Autoload stuff ***/
1951 
1952 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Module auto-loading no longer supported.");
1953 
pa_context_get_autoload_info_by_name(pa_context * c,const char * name,pa_autoload_type_t type,pa_autoload_info_cb_t cb,void * userdata)1954 pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) {
1955 
1956     pa_assert(c);
1957     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1958 
1959     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1960 }
1961 
1962 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_index, "Module auto-loading no longer supported.");
1963 
pa_context_get_autoload_info_by_index(pa_context * c,uint32_t idx,pa_autoload_info_cb_t cb,void * userdata)1964 pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
1965     pa_assert(c);
1966     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1967 
1968     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1969 }
1970 
1971 PA_WARN_REFERENCE(pa_context_get_autoload_info_list, "Module auto-loading no longer supported.");
1972 
pa_context_get_autoload_info_list(pa_context * c,pa_autoload_info_cb_t cb,void * userdata)1973 pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
1974     pa_assert(c);
1975     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1976 
1977     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1978 }
1979 
1980 PA_WARN_REFERENCE(pa_context_add_autoload, "Module auto-loading no longer supported.");
1981 
pa_context_add_autoload(pa_context * c,const char * name,pa_autoload_type_t type,const char * module,const char * argument,pa_context_index_cb_t cb,void * userdata)1982 pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) {
1983     pa_assert(c);
1984     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1985 
1986     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1987 }
1988 
1989 PA_WARN_REFERENCE(pa_context_remove_autoload_by_name, "Module auto-loading no longer supported.");
1990 
pa_context_remove_autoload_by_name(pa_context * c,const char * name,pa_autoload_type_t type,pa_context_success_cb_t cb,void * userdata)1991 pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) {
1992     pa_assert(c);
1993     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1994 
1995     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1996 }
1997 
1998 PA_WARN_REFERENCE(pa_context_remove_autoload_by_index, "Module auto-loading no longer supported.");
1999 
pa_context_remove_autoload_by_index(pa_context * c,uint32_t idx,pa_context_success_cb_t cb,void * userdata)2000 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
2001     pa_assert(c);
2002     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2003 
2004     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
2005 }
2006 
pa_context_move_sink_input_by_name(pa_context * c,uint32_t idx,const char * sink_name,pa_context_success_cb_t cb,void * userdata)2007 pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, const char *sink_name, pa_context_success_cb_t cb, void* userdata) {
2008     pa_operation *o;
2009     pa_tagstruct *t;
2010     uint32_t tag;
2011 
2012     pa_assert(c);
2013     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2014 
2015     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2016     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2017     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
2018     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2019     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_name && *sink_name, PA_ERR_INVALID);
2020 
2021     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2022 
2023     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag);
2024     pa_tagstruct_putu32(t, idx);
2025     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
2026     pa_tagstruct_puts(t, sink_name);
2027     pa_pstream_send_tagstruct(c->pstream, t);
2028     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2029 
2030     return o;
2031 }
2032 
pa_context_move_sink_input_by_index(pa_context * c,uint32_t idx,uint32_t sink_idx,pa_context_success_cb_t cb,void * userdata)2033 pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata) {
2034     pa_operation *o;
2035     pa_tagstruct *t;
2036     uint32_t tag;
2037 
2038     pa_assert(c);
2039     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2040 
2041     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2042     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2043     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
2044     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2045     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2046 
2047     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2048 
2049     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag);
2050     pa_tagstruct_putu32(t, idx);
2051     pa_tagstruct_putu32(t, sink_idx);
2052     pa_tagstruct_puts(t, NULL);
2053     pa_pstream_send_tagstruct(c->pstream, t);
2054     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2055 
2056     return o;
2057 }
2058 
pa_context_move_source_output_by_name(pa_context * c,uint32_t idx,const char * source_name,pa_context_success_cb_t cb,void * userdata)2059 pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, const char *source_name, pa_context_success_cb_t cb, void* userdata) {
2060     pa_operation *o;
2061     pa_tagstruct *t;
2062     uint32_t tag;
2063 
2064     pa_assert(c);
2065     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2066 
2067     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2068     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2069     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
2070     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2071     PA_CHECK_VALIDITY_RETURN_NULL(c, source_name && *source_name, PA_ERR_INVALID);
2072 
2073     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2074 
2075     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
2076     pa_tagstruct_putu32(t, idx);
2077     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
2078     pa_tagstruct_puts(t, source_name);
2079     pa_pstream_send_tagstruct(c->pstream, t);
2080     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2081 
2082     return o;
2083 }
2084 
pa_context_move_source_output_by_index(pa_context * c,uint32_t idx,uint32_t source_idx,pa_context_success_cb_t cb,void * userdata)2085 pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata) {
2086     pa_operation *o;
2087     pa_tagstruct *t;
2088     uint32_t tag;
2089 
2090     pa_assert(c);
2091     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2092 
2093     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2094     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2095     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
2096     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2097     PA_CHECK_VALIDITY_RETURN_NULL(c, source_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
2098 
2099     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2100 
2101     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
2102     pa_tagstruct_putu32(t, idx);
2103     pa_tagstruct_putu32(t, source_idx);
2104     pa_tagstruct_puts(t, NULL);
2105     pa_pstream_send_tagstruct(c->pstream, t);
2106     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2107 
2108     return o;
2109 }
2110 
pa_context_suspend_sink_by_name(pa_context * c,const char * sink_name,int suspend,pa_context_success_cb_t cb,void * userdata)2111 pa_operation* pa_context_suspend_sink_by_name(pa_context *c, const char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
2112     pa_operation *o;
2113     pa_tagstruct *t;
2114     uint32_t tag;
2115 
2116     pa_assert(c);
2117     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2118 
2119     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2120     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2121     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
2122     PA_CHECK_VALIDITY_RETURN_NULL(c, !sink_name || *sink_name, PA_ERR_INVALID);
2123 
2124     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2125 
2126     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
2127     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
2128     pa_tagstruct_puts(t, sink_name);
2129     pa_tagstruct_put_boolean(t, suspend);
2130     pa_pstream_send_tagstruct(c->pstream, t);
2131     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2132 
2133     return o;
2134 }
2135 
pa_context_suspend_sink_by_index(pa_context * c,uint32_t idx,int suspend,pa_context_success_cb_t cb,void * userdata)2136 pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
2137     pa_operation *o;
2138     pa_tagstruct *t;
2139     uint32_t tag;
2140 
2141     pa_assert(c);
2142     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2143 
2144     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2145     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2146     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
2147 
2148     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2149 
2150     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
2151     pa_tagstruct_putu32(t, idx);
2152     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
2153     pa_tagstruct_put_boolean(t, suspend);
2154     pa_pstream_send_tagstruct(c->pstream, t);
2155     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2156 
2157     return o;
2158 }
2159 
pa_context_suspend_source_by_name(pa_context * c,const char * source_name,int suspend,pa_context_success_cb_t cb,void * userdata)2160 pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
2161     pa_operation *o;
2162     pa_tagstruct *t;
2163     uint32_t tag;
2164 
2165     pa_assert(c);
2166     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2167 
2168     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2169     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2170     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
2171     PA_CHECK_VALIDITY_RETURN_NULL(c, !source_name || *source_name, PA_ERR_INVALID);
2172 
2173     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2174 
2175     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
2176     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
2177     pa_tagstruct_puts(t, source_name);
2178     pa_tagstruct_put_boolean(t, suspend);
2179     pa_pstream_send_tagstruct(c->pstream, t);
2180     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2181 
2182     return o;
2183 }
2184 
pa_context_suspend_source_by_index(pa_context * c,uint32_t idx,int suspend,pa_context_success_cb_t cb,void * userdata)2185 pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
2186     pa_operation *o;
2187     pa_tagstruct *t;
2188     uint32_t tag;
2189 
2190     pa_assert(c);
2191     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2192 
2193     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2194     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2195     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
2196 
2197     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2198 
2199     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
2200     pa_tagstruct_putu32(t, idx);
2201     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
2202     pa_tagstruct_put_boolean(t, suspend);
2203     pa_pstream_send_tagstruct(c->pstream, t);
2204     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2205 
2206     return o;
2207 }
2208 
2209 /** Object response string processing **/
2210 
context_string_callback(pa_pdispatch * pd,uint32_t command,uint32_t tag,pa_tagstruct * t,void * userdata)2211 static void context_string_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2212     pa_operation *o = userdata;
2213     const char *response;
2214     int success = 1;
2215 
2216     pa_assert(pd);
2217     pa_assert(o);
2218     pa_assert(PA_REFCNT_VALUE(o) >= 1);
2219 
2220     if (!o->context)
2221         goto finish;
2222 
2223     if (command != PA_COMMAND_REPLY) {
2224         if (pa_context_handle_error(o->context, command, t, false) < 0)
2225             goto finish;
2226 
2227         success = 0;
2228         response = "";
2229     } else if (pa_tagstruct_gets(t, &response)  < 0 ||
2230                !pa_tagstruct_eof(t)) {
2231         pa_context_fail(o->context, PA_ERR_PROTOCOL);
2232         goto finish;
2233     }
2234 
2235     if (!response)
2236         response = "";
2237 
2238     if (o->callback) {
2239         char *response_copy;
2240         pa_context_string_cb_t cb;
2241 
2242         response_copy = pa_xstrdup(response);
2243 
2244         cb = (pa_context_string_cb_t) o->callback;
2245         cb(o->context, success, response_copy, o->userdata);
2246 
2247         pa_xfree(response_copy);
2248     }
2249 
2250 finish:
2251     pa_operation_done(o);
2252     pa_operation_unref(o);
2253 }
2254 
pa_context_send_message_to_object(pa_context * c,const char * object_path,const char * message,const char * message_parameters,pa_context_string_cb_t cb,void * userdata)2255 pa_operation* pa_context_send_message_to_object(pa_context *c, const char *object_path, const char *message, const char *message_parameters, pa_context_string_cb_t cb, void *userdata) {
2256     pa_operation *o;
2257     pa_tagstruct *t;
2258     uint32_t tag;
2259 
2260     pa_assert(c);
2261     pa_assert(PA_REFCNT_VALUE(c) >= 1);
2262 
2263     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
2264     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
2265     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 35, PA_ERR_NOTSUPPORTED);
2266 
2267     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
2268 
2269     t = pa_tagstruct_command(c, PA_COMMAND_SEND_OBJECT_MESSAGE, &tag);
2270 
2271     pa_tagstruct_puts(t, object_path);
2272     pa_tagstruct_puts(t, message);
2273     pa_tagstruct_puts(t, message_parameters);
2274 
2275     pa_pstream_send_tagstruct(c->pstream, t);
2276     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_string_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
2277 
2278     return o;
2279 }
2280