don't use PA_GCC_UNUSED anymore
[profile/ivi/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 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/gccmacro.h>
29
30 #include <pulsecore/macro.h>
31 #include <pulsecore/pstream-util.h>
32
33 #include "internal.h"
34
35 #include "introspect.h"
36
37 /*** Statistics ***/
38
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     memset(&i, 0, sizeof(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_context_fail(o->context, PA_ERR_PROTOCOL);
63         goto finish;
64     }
65
66     if (o->callback) {
67         pa_stat_info_cb_t cb = (pa_stat_info_cb_t) o->callback;
68         cb(o->context, p, o->userdata);
69     }
70
71 finish:
72     pa_operation_done(o);
73     pa_operation_unref(o);
74 }
75
76 pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata) {
77     return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_cb_t) cb, userdata);
78 }
79
80 /*** Server Info ***/
81
82 static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
83     pa_operation *o = userdata;
84     pa_server_info i, *p = &i;
85
86     pa_assert(pd);
87     pa_assert(o);
88     pa_assert(PA_REFCNT_VALUE(o) >= 1);
89
90     memset(&i, 0, sizeof(i));
91
92     if (!o->context)
93         goto finish;
94
95     if (command != PA_COMMAND_REPLY) {
96         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
97             goto finish;
98
99         p = NULL;
100     } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
101                pa_tagstruct_gets(t, &i.server_version) < 0 ||
102                pa_tagstruct_gets(t, &i.user_name) < 0 ||
103                pa_tagstruct_gets(t, &i.host_name) < 0 ||
104                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
105                pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
106                pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
107                pa_tagstruct_getu32(t, &i.cookie) < 0 ||
108                !pa_tagstruct_eof(t)) {
109
110         pa_context_fail(o->context, PA_ERR_PROTOCOL);
111         goto finish;
112     }
113
114     if (o->callback) {
115         pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback;
116         cb(o->context, p, o->userdata);
117     }
118
119 finish:
120     pa_operation_done(o);
121     pa_operation_unref(o);
122 }
123
124 pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata) {
125     return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_cb_t) cb, userdata);
126 }
127
128 /*** Sink Info ***/
129
130 static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
131     pa_operation *o = userdata;
132     int eol = 1;
133
134     pa_assert(pd);
135     pa_assert(o);
136     pa_assert(PA_REFCNT_VALUE(o) >= 1);
137
138     if (!o->context)
139         goto finish;
140
141     if (command != PA_COMMAND_REPLY) {
142         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
143             goto finish;
144
145         eol = -1;
146     } else {
147         uint32_t flags;
148
149         while (!pa_tagstruct_eof(t)) {
150             pa_sink_info i;
151             pa_bool_t mute = FALSE;
152
153             memset(&i, 0, sizeof(i));
154             i.proplist = pa_proplist_new();
155
156             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
157                 pa_tagstruct_gets(t, &i.name) < 0 ||
158                 pa_tagstruct_gets(t, &i.description) < 0 ||
159                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
160                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
161                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
162                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
163                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
164                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
165                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
166                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
167                 pa_tagstruct_gets(t, &i.driver) < 0 ||
168                 pa_tagstruct_getu32(t, &flags) < 0 ||
169                 (o->context->version >= 13 &&
170                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
171                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
172
173                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
174                 pa_proplist_free(i.proplist);
175                 goto finish;
176             }
177
178             i.mute = (int) mute;
179             i.flags = (pa_sink_flags_t) flags;
180
181             if (o->callback) {
182                 pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
183                 cb(o->context, &i, 0, o->userdata);
184             }
185
186             pa_proplist_free(i.proplist);
187         }
188     }
189
190     if (o->callback) {
191         pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
192         cb(o->context, NULL, eol, o->userdata);
193     }
194
195 finish:
196     pa_operation_done(o);
197     pa_operation_unref(o);
198 }
199
200 pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata) {
201     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_cb_t) cb, userdata);
202 }
203
204 pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata) {
205     pa_tagstruct *t;
206     pa_operation *o;
207     uint32_t tag;
208
209     pa_assert(c);
210     pa_assert(PA_REFCNT_VALUE(c) >= 1);
211     pa_assert(cb);
212
213     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
214
215     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
216
217     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
218     pa_tagstruct_putu32(t, idx);
219     pa_tagstruct_puts(t, NULL);
220     pa_pstream_send_tagstruct(c->pstream, t);
221     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);
222
223     return o;
224 }
225
226 pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata) {
227     pa_tagstruct *t;
228     pa_operation *o;
229     uint32_t tag;
230
231     pa_assert(c);
232     pa_assert(PA_REFCNT_VALUE(c) >= 1);
233     pa_assert(cb);
234
235     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
236     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
237
238     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
239
240     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
241     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
242     pa_tagstruct_puts(t, name);
243     pa_pstream_send_tagstruct(c->pstream, t);
244     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);
245
246     return o;
247 }
248
249 /*** Source info ***/
250
251 static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
252     pa_operation *o = userdata;
253     int eol = 1;
254
255     pa_assert(pd);
256     pa_assert(o);
257     pa_assert(PA_REFCNT_VALUE(o) >= 1);
258
259     if (!o->context)
260         goto finish;
261
262     if (command != PA_COMMAND_REPLY) {
263         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
264             goto finish;
265
266         eol = -1;
267     } else {
268
269         while (!pa_tagstruct_eof(t)) {
270             pa_source_info i;
271             uint32_t flags;
272             pa_bool_t mute = FALSE;
273
274             memset(&i, 0, sizeof(i));
275             i.proplist = pa_proplist_new();
276
277             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
278                 pa_tagstruct_gets(t, &i.name) < 0 ||
279                 pa_tagstruct_gets(t, &i.description) < 0 ||
280                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
281                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
282                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
283                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
284                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
285                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
286                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
287                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
288                 pa_tagstruct_gets(t, &i.driver) < 0 ||
289                 pa_tagstruct_getu32(t, &flags) < 0 ||
290                 (o->context->version >= 13 &&
291                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
292                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
293
294                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
295                 pa_proplist_free(i.proplist);
296                 goto finish;
297             }
298
299             i.mute = (int) mute;
300             i.flags = (pa_source_flags_t) flags;
301
302             if (o->callback) {
303                 pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
304                 cb(o->context, &i, 0, o->userdata);
305             }
306
307             pa_proplist_free(i.proplist);
308         }
309     }
310
311     if (o->callback) {
312         pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
313         cb(o->context, NULL, eol, o->userdata);
314     }
315
316 finish:
317     pa_operation_done(o);
318     pa_operation_unref(o);
319 }
320
321 pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata) {
322     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_cb_t) cb, userdata);
323 }
324
325 pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata) {
326     pa_tagstruct *t;
327     pa_operation *o;
328     uint32_t tag;
329
330     pa_assert(c);
331     pa_assert(PA_REFCNT_VALUE(c) >= 1);
332     pa_assert(cb);
333
334     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
335
336     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
337
338     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
339     pa_tagstruct_putu32(t, idx);
340     pa_tagstruct_puts(t, NULL);
341     pa_pstream_send_tagstruct(c->pstream, t);
342     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);
343
344     return o;
345 }
346
347 pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata) {
348     pa_tagstruct *t;
349     pa_operation *o;
350     uint32_t tag;
351
352     pa_assert(c);
353     pa_assert(PA_REFCNT_VALUE(c) >= 1);
354     pa_assert(cb);
355
356     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
357     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
358
359     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
360
361     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
362     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
363     pa_tagstruct_puts(t, name);
364     pa_pstream_send_tagstruct(c->pstream, t);
365     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);
366
367     return o;
368 }
369
370 /*** Client info ***/
371
372 static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
373     pa_operation *o = userdata;
374     int eol = 1;
375
376     pa_assert(pd);
377     pa_assert(o);
378     pa_assert(PA_REFCNT_VALUE(o) >= 1);
379
380     if (!o->context)
381         goto finish;
382
383     if (command != PA_COMMAND_REPLY) {
384         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
385             goto finish;
386
387         eol = -1;
388     } else {
389
390         while (!pa_tagstruct_eof(t)) {
391             pa_client_info i;
392
393             memset(&i, 0, sizeof(i));
394             i.proplist = pa_proplist_new();
395
396             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
397                 pa_tagstruct_gets(t, &i.name) < 0 ||
398                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
399                 pa_tagstruct_gets(t, &i.driver) < 0 ||
400                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
401
402                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
403                 pa_proplist_free(i.proplist);
404                 goto finish;
405             }
406
407             if (o->callback) {
408                 pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
409                 cb(o->context, &i, 0, o->userdata);
410             }
411
412             pa_proplist_free(i.proplist);
413         }
414     }
415
416     if (o->callback) {
417         pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
418         cb(o->context, NULL, eol, o->userdata);
419     }
420
421 finish:
422     pa_operation_done(o);
423     pa_operation_unref(o);
424 }
425
426 pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata) {
427     pa_tagstruct *t;
428     pa_operation *o;
429     uint32_t tag;
430
431     pa_assert(c);
432     pa_assert(PA_REFCNT_VALUE(c) >= 1);
433     pa_assert(cb);
434
435     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
436     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
437
438     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
439
440     t = pa_tagstruct_command(c, PA_COMMAND_GET_CLIENT_INFO, &tag);
441     pa_tagstruct_putu32(t, idx);
442     pa_pstream_send_tagstruct(c->pstream, t);
443     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);
444
445     return o;
446 }
447
448 pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata) {
449     return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_cb_t) cb, userdata);
450 }
451
452 /*** Module info ***/
453
454 static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
455     pa_operation *o = userdata;
456     int eol = 1;
457
458     pa_assert(pd);
459     pa_assert(o);
460     pa_assert(PA_REFCNT_VALUE(o) >= 1);
461
462     if (!o->context)
463         goto finish;
464
465     if (command != PA_COMMAND_REPLY) {
466         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
467             goto finish;
468
469         eol = -1;
470     } else {
471
472         while (!pa_tagstruct_eof(t)) {
473             pa_module_info i;
474             pa_bool_t auto_unload = FALSE;
475             memset(&i, 0, sizeof(i));
476
477             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
478                 pa_tagstruct_gets(t, &i.name) < 0 ||
479                 pa_tagstruct_gets(t, &i.argument) < 0 ||
480                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
481                 pa_tagstruct_get_boolean(t, &auto_unload) < 0) {
482                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
483                 goto finish;
484             }
485
486             i.auto_unload = (int) auto_unload;
487
488             if (o->callback) {
489                 pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
490                 cb(o->context, &i, 0, o->userdata);
491             }
492         }
493     }
494
495     if (o->callback) {
496         pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
497         cb(o->context, NULL, eol, o->userdata);
498     }
499
500 finish:
501     pa_operation_done(o);
502     pa_operation_unref(o);
503 }
504
505 pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata) {
506     pa_tagstruct *t;
507     pa_operation *o;
508     uint32_t tag;
509
510     pa_assert(c);
511     pa_assert(PA_REFCNT_VALUE(c) >= 1);
512     pa_assert(cb);
513
514     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
515     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
516
517     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
518
519     t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag);
520     pa_tagstruct_putu32(t, idx);
521     pa_pstream_send_tagstruct(c->pstream, t);
522     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);
523
524     return o;
525 }
526
527 pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata) {
528     return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_cb_t) cb, userdata);
529 }
530
531 /*** Sink input info ***/
532
533 static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
534     pa_operation *o = userdata;
535     int eol = 1;
536
537     pa_assert(pd);
538     pa_assert(o);
539     pa_assert(PA_REFCNT_VALUE(o) >= 1);
540
541     if (!o->context)
542         goto finish;
543
544     if (command != PA_COMMAND_REPLY) {
545         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
546             goto finish;
547
548         eol = -1;
549     } else {
550
551         while (!pa_tagstruct_eof(t)) {
552             pa_sink_input_info i;
553             pa_bool_t mute = FALSE;
554
555             memset(&i, 0, sizeof(i));
556             i.proplist = pa_proplist_new();
557
558             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
559                 pa_tagstruct_gets(t, &i.name) < 0 ||
560                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
561                 pa_tagstruct_getu32(t, &i.client) < 0 ||
562                 pa_tagstruct_getu32(t, &i.sink) < 0 ||
563                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
564                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
565                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
566                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
567                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
568                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
569                 pa_tagstruct_gets(t, &i.driver) < 0 ||
570                 (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) ||
571                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
572
573                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
574                 pa_proplist_free(i.proplist);
575                 goto finish;
576             }
577
578             i.mute = (int) mute;
579
580             if (o->callback) {
581                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
582                 cb(o->context, &i, 0, o->userdata);
583             }
584
585             pa_proplist_free(i.proplist);
586         }
587     }
588
589     if (o->callback) {
590         pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
591         cb(o->context, NULL, eol, o->userdata);
592     }
593
594 finish:
595     pa_operation_done(o);
596     pa_operation_unref(o);
597 }
598
599 pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) {
600     pa_tagstruct *t;
601     pa_operation *o;
602     uint32_t tag;
603
604     pa_assert(c);
605     pa_assert(PA_REFCNT_VALUE(c) >= 1);
606     pa_assert(cb);
607
608     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
609     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
610
611     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
612
613     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag);
614     pa_tagstruct_putu32(t, idx);
615     pa_pstream_send_tagstruct(c->pstream, t);
616     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);
617
618     return o;
619 }
620
621 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) {
622     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);
623 }
624
625 /*** Source output info ***/
626
627 static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
628     pa_operation *o = userdata;
629     int eol = 1;
630
631     pa_assert(pd);
632     pa_assert(o);
633     pa_assert(PA_REFCNT_VALUE(o) >= 1);
634
635     if (!o->context)
636         goto finish;
637
638     if (command != PA_COMMAND_REPLY) {
639         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
640             goto finish;
641
642         eol = -1;
643     } else {
644
645         while (!pa_tagstruct_eof(t)) {
646             pa_source_output_info i;
647
648             memset(&i, 0, sizeof(i));
649             i.proplist = pa_proplist_new();
650
651             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
652                 pa_tagstruct_gets(t, &i.name) < 0 ||
653                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
654                 pa_tagstruct_getu32(t, &i.client) < 0 ||
655                 pa_tagstruct_getu32(t, &i.source) < 0 ||
656                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
657                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
658                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
659                 pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
660                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
661                 pa_tagstruct_gets(t, &i.driver) < 0 ||
662                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
663
664                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
665                 pa_proplist_free(i.proplist);
666                 goto finish;
667             }
668
669             if (o->callback) {
670                 pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
671                 cb(o->context, &i, 0, o->userdata);
672             }
673
674             pa_proplist_free(i.proplist);
675         }
676     }
677
678     if (o->callback) {
679         pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
680         cb(o->context, NULL, eol, o->userdata);
681     }
682
683 finish:
684     pa_operation_done(o);
685     pa_operation_unref(o);
686 }
687
688 pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata) {
689     pa_tagstruct *t;
690     pa_operation *o;
691     uint32_t tag;
692
693     pa_assert(c);
694     pa_assert(PA_REFCNT_VALUE(c) >= 1);
695     pa_assert(cb);
696
697     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
698     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
699
700     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
701
702     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag);
703     pa_tagstruct_putu32(t, idx);
704     pa_pstream_send_tagstruct(c->pstream, t);
705     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);
706
707     return o;
708 }
709
710 pa_operation* pa_context_get_source_output_info_list(pa_context *c,  pa_source_output_info_cb_t cb, void *userdata) {
711     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);
712 }
713
714 /*** Volume manipulation ***/
715
716 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) {
717     pa_operation *o;
718     pa_tagstruct *t;
719     uint32_t tag;
720
721     pa_assert(c);
722     pa_assert(PA_REFCNT_VALUE(c) >= 1);
723     pa_assert(volume);
724
725     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
726     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
727
728     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
729
730     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
731     pa_tagstruct_putu32(t, idx);
732     pa_tagstruct_puts(t, NULL);
733     pa_tagstruct_put_cvolume(t, volume);
734     pa_pstream_send_tagstruct(c->pstream, t);
735     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);
736
737     return o;
738 }
739
740 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) {
741     pa_operation *o;
742     pa_tagstruct *t;
743     uint32_t tag;
744
745     pa_assert(c);
746     pa_assert(PA_REFCNT_VALUE(c) >= 1);
747     pa_assert(name);
748     pa_assert(volume);
749
750     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
751     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
752     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
753
754     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
755
756     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
757     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
758     pa_tagstruct_puts(t, name);
759     pa_tagstruct_put_cvolume(t, volume);
760     pa_pstream_send_tagstruct(c->pstream, t);
761     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);
762
763     return o;
764 }
765
766 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) {
767     pa_operation *o;
768     pa_tagstruct *t;
769     uint32_t tag;
770
771     pa_assert(c);
772     pa_assert(PA_REFCNT_VALUE(c) >= 1);
773
774     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
775
776     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
777
778     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
779     pa_tagstruct_putu32(t, idx);
780     pa_tagstruct_puts(t, NULL);
781     pa_tagstruct_put_boolean(t, mute);
782     pa_pstream_send_tagstruct(c->pstream, t);
783     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);
784
785     return o;
786 }
787
788 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) {
789     pa_operation *o;
790     pa_tagstruct *t;
791     uint32_t tag;
792
793     pa_assert(c);
794     pa_assert(PA_REFCNT_VALUE(c) >= 1);
795     pa_assert(name);
796
797     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
798     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
799
800     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
801
802     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
803     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
804     pa_tagstruct_puts(t, name);
805     pa_tagstruct_put_boolean(t, mute);
806     pa_pstream_send_tagstruct(c->pstream, t);
807     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);
808
809     return o;
810 }
811
812 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) {
813     pa_operation *o;
814     pa_tagstruct *t;
815     uint32_t tag;
816
817     pa_assert(c);
818     pa_assert(PA_REFCNT_VALUE(c) >= 1);
819     pa_assert(volume);
820
821     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
822     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
823     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
824
825     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
826
827     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag);
828     pa_tagstruct_putu32(t, idx);
829     pa_tagstruct_put_cvolume(t, volume);
830     pa_pstream_send_tagstruct(c->pstream, t);
831     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);
832
833     return o;
834 }
835
836 pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
837     pa_operation *o;
838     pa_tagstruct *t;
839     uint32_t tag;
840
841     pa_assert(c);
842     pa_assert(PA_REFCNT_VALUE(c) >= 1);
843
844     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
845     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
846     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
847
848     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
849
850     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_MUTE, &tag);
851     pa_tagstruct_putu32(t, idx);
852     pa_tagstruct_put_boolean(t, mute);
853     pa_pstream_send_tagstruct(c->pstream, t);
854     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);
855
856     return o;
857 }
858
859 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) {
860     pa_operation *o;
861     pa_tagstruct *t;
862     uint32_t tag;
863
864     pa_assert(c);
865     pa_assert(PA_REFCNT_VALUE(c) >= 1);
866     pa_assert(volume);
867
868     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
869     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
870
871     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
872
873     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
874     pa_tagstruct_putu32(t, idx);
875     pa_tagstruct_puts(t, NULL);
876     pa_tagstruct_put_cvolume(t, volume);
877     pa_pstream_send_tagstruct(c->pstream, t);
878     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);
879
880     return o;
881 }
882
883 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) {
884     pa_operation *o;
885     pa_tagstruct *t;
886     uint32_t tag;
887
888     pa_assert(c);
889     pa_assert(PA_REFCNT_VALUE(c) >= 1);
890     pa_assert(name);
891     pa_assert(volume);
892
893     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
894     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
895     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
896
897     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
898
899     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
900     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
901     pa_tagstruct_puts(t, name);
902     pa_tagstruct_put_cvolume(t, volume);
903     pa_pstream_send_tagstruct(c->pstream, t);
904     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);
905
906     return o;
907 }
908
909 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) {
910     pa_operation *o;
911     pa_tagstruct *t;
912     uint32_t tag;
913
914     pa_assert(c);
915     pa_assert(PA_REFCNT_VALUE(c) >= 1);
916
917     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
918
919     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
920
921     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
922     pa_tagstruct_putu32(t, idx);
923     pa_tagstruct_puts(t, NULL);
924     pa_tagstruct_put_boolean(t, mute);
925     pa_pstream_send_tagstruct(c->pstream, t);
926     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);
927
928     return o;
929 }
930
931 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) {
932     pa_operation *o;
933     pa_tagstruct *t;
934     uint32_t tag;
935
936     pa_assert(c);
937     pa_assert(PA_REFCNT_VALUE(c) >= 1);
938     pa_assert(name);
939
940     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
941     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
942
943     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
944
945     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
946     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
947     pa_tagstruct_puts(t, name);
948     pa_tagstruct_put_boolean(t, mute);
949     pa_pstream_send_tagstruct(c->pstream, t);
950     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);
951
952     return o;
953 }
954
955 /** Sample Cache **/
956
957 static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
958     pa_operation *o = userdata;
959     int eol = 1;
960
961     pa_assert(pd);
962     pa_assert(o);
963     pa_assert(PA_REFCNT_VALUE(o) >= 1);
964
965     if (!o->context)
966         goto finish;
967
968     if (command != PA_COMMAND_REPLY) {
969         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
970             goto finish;
971
972         eol = -1;
973     } else {
974
975         while (!pa_tagstruct_eof(t)) {
976             pa_sample_info i;
977             pa_bool_t lazy = FALSE;
978
979             memset(&i, 0, sizeof(i));
980             i.proplist = pa_proplist_new();
981
982             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
983                 pa_tagstruct_gets(t, &i.name) < 0 ||
984                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
985                 pa_tagstruct_get_usec(t, &i.duration) < 0 ||
986                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
987                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
988                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
989                 pa_tagstruct_get_boolean(t, &lazy) < 0 ||
990                 pa_tagstruct_gets(t, &i.filename) < 0 ||
991                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
992
993                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
994                 goto finish;
995             }
996
997             i.lazy = (int) lazy;
998
999             if (o->callback) {
1000                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1001                 cb(o->context, &i, 0, o->userdata);
1002             }
1003
1004             pa_proplist_free(i.proplist);
1005         }
1006     }
1007
1008     if (o->callback) {
1009         pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1010         cb(o->context, NULL, eol, o->userdata);
1011     }
1012
1013 finish:
1014     pa_operation_done(o);
1015     pa_operation_unref(o);
1016 }
1017
1018 pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata) {
1019     pa_tagstruct *t;
1020     pa_operation *o;
1021     uint32_t tag;
1022
1023     pa_assert(c);
1024     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1025     pa_assert(cb);
1026
1027     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1028     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1029
1030     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1031
1032     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1033     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1034     pa_tagstruct_puts(t, name);
1035     pa_pstream_send_tagstruct(c->pstream, t);
1036     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);
1037
1038     return o;
1039 }
1040
1041 pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata) {
1042     pa_tagstruct *t;
1043     pa_operation *o;
1044     uint32_t tag;
1045
1046     pa_assert(c);
1047     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1048     pa_assert(cb);
1049
1050     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1051     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1052
1053     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1054
1055     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1056     pa_tagstruct_putu32(t, idx);
1057     pa_tagstruct_puts(t, NULL);
1058     pa_pstream_send_tagstruct(c->pstream, t);
1059     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);
1060
1061     return o;
1062 }
1063
1064 pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata) {
1065     return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_cb_t) cb, userdata);
1066 }
1067
1068 static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1069     pa_operation *o;
1070     pa_tagstruct *t;
1071     uint32_t tag;
1072
1073     pa_assert(c);
1074     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1075
1076     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1077     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1078
1079     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1080
1081     t = pa_tagstruct_command(c, command, &tag);
1082     pa_tagstruct_putu32(t, idx);
1083     pa_pstream_send_tagstruct(c->pstream, t);
1084     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);
1085
1086     return o;
1087 }
1088
1089 pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1090     return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata);
1091 }
1092
1093 pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1094     return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata);
1095 }
1096
1097 pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1098     return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata);
1099 }
1100
1101 static void context_index_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1102     pa_operation *o = userdata;
1103     uint32_t idx;
1104
1105     pa_assert(pd);
1106     pa_assert(o);
1107     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1108
1109     if (!o->context)
1110         goto finish;
1111
1112     if (command != PA_COMMAND_REPLY) {
1113         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1114             goto finish;
1115
1116         idx = PA_INVALID_INDEX;
1117     } else if (pa_tagstruct_getu32(t, &idx) ||
1118                !pa_tagstruct_eof(t)) {
1119         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1120         goto finish;
1121     }
1122
1123     if (o->callback) {
1124         pa_context_index_cb_t cb = (pa_context_index_cb_t) o->callback;
1125         cb(o->context, idx, o->userdata);
1126     }
1127
1128
1129 finish:
1130     pa_operation_done(o);
1131     pa_operation_unref(o);
1132 }
1133
1134 pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata) {
1135     pa_operation *o;
1136     pa_tagstruct *t;
1137     uint32_t tag;
1138
1139     pa_assert(c);
1140     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1141
1142     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1143     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1144
1145     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1146
1147     t = pa_tagstruct_command(c, PA_COMMAND_LOAD_MODULE, &tag);
1148     pa_tagstruct_puts(t, name);
1149     pa_tagstruct_puts(t, argument);
1150     pa_pstream_send_tagstruct(c->pstream, t);
1151     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1152
1153     return o;
1154 }
1155
1156 pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1157     return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata);
1158 }
1159
1160 /*** Autoload stuff ***/
1161
1162 static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1163     pa_operation *o = userdata;
1164     int eol = 1;
1165
1166     pa_assert(pd);
1167     pa_assert(o);
1168     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1169
1170     if (!o->context)
1171         goto finish;
1172
1173     if (command != PA_COMMAND_REPLY) {
1174         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1175             goto finish;
1176
1177         eol = -1;
1178     } else {
1179
1180         while (!pa_tagstruct_eof(t)) {
1181             pa_autoload_info i;
1182
1183             memset(&i, 0, sizeof(i));
1184
1185             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1186                 pa_tagstruct_gets(t, &i.name) < 0 ||
1187                 pa_tagstruct_getu32(t, &i.type) < 0 ||
1188                 pa_tagstruct_gets(t, &i.module) < 0 ||
1189                 pa_tagstruct_gets(t, &i.argument) < 0) {
1190                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1191                 goto finish;
1192             }
1193
1194             if (o->callback) {
1195                 pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback;
1196                 cb(o->context, &i, 0, o->userdata);
1197             }
1198         }
1199     }
1200
1201     if (o->callback) {
1202         pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback;
1203         cb(o->context, NULL, eol, o->userdata);
1204     }
1205
1206 finish:
1207     pa_operation_done(o);
1208     pa_operation_unref(o);
1209 }
1210
1211 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1212
1213 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) {
1214     pa_tagstruct *t;
1215     pa_operation *o;
1216     uint32_t tag;
1217
1218     pa_assert(c);
1219     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1220     pa_assert(cb);
1221
1222     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1223     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1224     PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID);
1225
1226     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1227
1228     t = pa_tagstruct_command(c, PA_COMMAND_GET_AUTOLOAD_INFO, &tag);
1229     pa_tagstruct_puts(t, name);
1230     pa_tagstruct_putu32(t, type);
1231     pa_pstream_send_tagstruct(c->pstream, t);
1232     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1233
1234     return o;
1235 }
1236
1237 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1238
1239 pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
1240     pa_tagstruct *t;
1241     pa_operation *o;
1242     uint32_t tag;
1243
1244     pa_assert(c);
1245     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1246     pa_assert(cb);
1247
1248     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1249     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1250
1251     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1252
1253     t = pa_tagstruct_command(c, PA_COMMAND_GET_AUTOLOAD_INFO, &tag);
1254     pa_tagstruct_putu32(t, idx);
1255     pa_pstream_send_tagstruct(c->pstream, t);
1256     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1257
1258     return o;
1259 }
1260
1261
1262 PA_WARN_REFERENCE(pa_context_get_autoload_info_list, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1263
1264 pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
1265     return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_cb_t) cb, userdata);
1266 }
1267
1268 PA_WARN_REFERENCE(pa_context_add_autoload, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1269
1270 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) {
1271     pa_operation *o;
1272     pa_tagstruct *t;
1273     uint32_t tag;
1274
1275     pa_assert(c);
1276     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1277
1278     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1279     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1280     PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID);
1281     PA_CHECK_VALIDITY_RETURN_NULL(c, module && *module, PA_ERR_INVALID);
1282
1283     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1284
1285     t = pa_tagstruct_command(c, PA_COMMAND_ADD_AUTOLOAD, &tag);
1286     pa_tagstruct_puts(t, name);
1287     pa_tagstruct_putu32(t, type);
1288     pa_tagstruct_puts(t, module);
1289     pa_tagstruct_puts(t, argument);
1290     pa_pstream_send_tagstruct(c->pstream, t);
1291     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1292
1293     return o;
1294 }
1295
1296 PA_WARN_REFERENCE(pa_context_remove_autoload_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1297
1298 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) {
1299     pa_operation *o;
1300     pa_tagstruct *t;
1301     uint32_t tag;
1302
1303     pa_assert(c);
1304     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1305
1306     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1307     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1308     PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID);
1309
1310     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1311
1312     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_AUTOLOAD, &tag);
1313     pa_tagstruct_puts(t, name);
1314     pa_tagstruct_putu32(t, type);
1315     pa_pstream_send_tagstruct(c->pstream, t);
1316     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);
1317
1318     return o;
1319 }
1320
1321 PA_WARN_REFERENCE(pa_context_remove_autoload_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
1322
1323 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
1324     pa_operation *o;
1325     pa_tagstruct *t;
1326     uint32_t tag;
1327
1328     pa_assert(c);
1329     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1330
1331     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1332     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1333
1334     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1335
1336     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_AUTOLOAD, &tag);
1337     pa_tagstruct_putu32(t, idx);
1338     pa_pstream_send_tagstruct(c->pstream, t);
1339     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);
1340
1341     return o;
1342 }
1343
1344 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) {
1345     pa_operation *o;
1346     pa_tagstruct *t;
1347     uint32_t tag;
1348
1349     pa_assert(c);
1350     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1351
1352     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1353     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1354     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1355     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_name && *sink_name, PA_ERR_INVALID);
1356
1357     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1358
1359     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag);
1360     pa_tagstruct_putu32(t, idx);
1361     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1362     pa_tagstruct_puts(t, sink_name);
1363     pa_pstream_send_tagstruct(c->pstream, t);
1364     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);
1365
1366     return o;
1367 }
1368
1369 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) {
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
1377     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1378     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1379     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1380     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_idx != PA_INVALID_INDEX, 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_MOVE_SINK_INPUT, &tag);
1385     pa_tagstruct_putu32(t, idx);
1386     pa_tagstruct_putu32(t, sink_idx);
1387     pa_tagstruct_puts(t, NULL);
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_move_source_output_by_name(pa_context *c, uint32_t idx, const char *source_name, 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
1402     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1403     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1404     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1405     PA_CHECK_VALIDITY_RETURN_NULL(c, source_name && *source_name, PA_ERR_INVALID);
1406
1407     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1408
1409     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
1410     pa_tagstruct_putu32(t, idx);
1411     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1412     pa_tagstruct_puts(t, source_name);
1413     pa_pstream_send_tagstruct(c->pstream, t);
1414     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);
1415
1416     return o;
1417 }
1418
1419 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) {
1420     pa_operation *o;
1421     pa_tagstruct *t;
1422     uint32_t tag;
1423
1424     pa_assert(c);
1425     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1426
1427     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1428     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1429     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1430     PA_CHECK_VALIDITY_RETURN_NULL(c, source_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1431
1432     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1433
1434     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
1435     pa_tagstruct_putu32(t, idx);
1436     pa_tagstruct_putu32(t, source_idx);
1437     pa_tagstruct_puts(t, NULL);
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_suspend_sink_by_name(pa_context *c, const char *sink_name, int suspend, 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
1452     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1453     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1454     PA_CHECK_VALIDITY_RETURN_NULL(c, !sink_name || *sink_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_SUSPEND_SINK, &tag);
1459     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1460     pa_tagstruct_puts(t, sink_name);
1461     pa_tagstruct_put_boolean(t, suspend);
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
1468 pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, 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, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1477     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1478
1479     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1480
1481     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
1482     pa_tagstruct_putu32(t, idx);
1483     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
1484     pa_tagstruct_put_boolean(t, suspend);
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
1491 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) {
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
1499     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1500     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1501     PA_CHECK_VALIDITY_RETURN_NULL(c, !source_name || *source_name, PA_ERR_INVALID);
1502
1503     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1504
1505     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
1506     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1507     pa_tagstruct_puts(t, source_name);
1508     pa_tagstruct_put_boolean(t, suspend);
1509     pa_pstream_send_tagstruct(c->pstream, t);
1510     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);
1511
1512     return o;
1513 }
1514
1515 pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
1516     pa_operation *o;
1517     pa_tagstruct *t;
1518     uint32_t tag;
1519
1520     pa_assert(c);
1521     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1522
1523     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1524     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1525
1526     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1527
1528     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
1529     pa_tagstruct_putu32(t, idx);
1530     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
1531     pa_tagstruct_put_boolean(t, suspend);
1532     pa_pstream_send_tagstruct(c->pstream, t);
1533     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);
1534
1535     return o;
1536 }