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