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