2
This file is part of PulseAudio.
4
Copyright 2008 Lennart Poettering
5
Copyright 2011 Colin Guthrie
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.
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.
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/>.
25
#include <pulse/context.h>
26
#include <pulse/gccmacro.h>
27
#include <pulse/xmalloc.h>
28
#include <pulse/fork-detect.h>
29
#include <pulse/operation.h>
30
#include <pulse/format.h>
32
#include <pulsecore/macro.h>
33
#include <pulsecore/pstream-util.h>
36
#include "ext-device-restore.h"
38
/* Protocol extension commands */
43
SUBCOMMAND_READ_FORMATS_ALL,
44
SUBCOMMAND_READ_FORMATS,
45
SUBCOMMAND_SAVE_FORMATS
48
static void ext_device_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
49
pa_operation *o = userdata;
50
uint32_t version = PA_INVALID_INDEX;
54
pa_assert(PA_REFCNT_VALUE(o) >= 1);
59
if (command != PA_COMMAND_REPLY) {
60
if (pa_context_handle_error(o->context, command, t, false) < 0)
63
} else if (pa_tagstruct_getu32(t, &version) < 0 ||
64
!pa_tagstruct_eof(t)) {
66
pa_context_fail(o->context, PA_ERR_PROTOCOL);
71
pa_ext_device_restore_test_cb_t cb = (pa_ext_device_restore_test_cb_t) o->callback;
72
cb(o->context, version, o->userdata);
77
pa_operation_unref(o);
80
pa_operation *pa_ext_device_restore_test(
82
pa_ext_device_restore_test_cb_t cb,
90
pa_assert(PA_REFCNT_VALUE(c) >= 1);
92
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
93
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
94
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
96
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
98
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
99
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
100
pa_tagstruct_puts(t, "module-device-restore");
101
pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
102
pa_pstream_send_tagstruct(c->pstream, t);
103
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
108
pa_operation *pa_ext_device_restore_subscribe(
111
pa_context_success_cb_t cb,
119
pa_assert(PA_REFCNT_VALUE(c) >= 1);
121
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
122
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
123
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
125
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
127
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
128
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
129
pa_tagstruct_puts(t, "module-device-restore");
130
pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
131
pa_tagstruct_put_boolean(t, enable);
132
pa_pstream_send_tagstruct(c->pstream, t);
133
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);
138
void pa_ext_device_restore_set_subscribe_cb(
140
pa_ext_device_restore_subscribe_cb_t cb,
144
pa_assert(PA_REFCNT_VALUE(c) >= 1);
146
if (pa_detect_fork())
149
c->ext_device_restore.callback = cb;
150
c->ext_device_restore.userdata = userdata;
153
static void ext_device_restore_read_device_formats_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
154
pa_operation *o = userdata;
159
pa_assert(PA_REFCNT_VALUE(o) >= 1);
164
if (command != PA_COMMAND_REPLY) {
165
if (pa_context_handle_error(o->context, command, t, false) < 0)
172
while (!pa_tagstruct_eof(t)) {
173
pa_ext_device_restore_info i;
176
if (pa_tagstruct_getu32(t, &i.type) < 0 ||
177
pa_tagstruct_getu32(t, &i.index) < 0 ||
178
pa_tagstruct_getu8(t, &i.n_formats) < 0) {
180
pa_context_fail(o->context, PA_ERR_PROTOCOL);
184
if (PA_DEVICE_TYPE_SINK != i.type && PA_DEVICE_TYPE_SOURCE != i.type) {
185
pa_context_fail(o->context, PA_ERR_PROTOCOL);
189
if (i.index == PA_INVALID_INDEX) {
190
pa_context_fail(o->context, PA_ERR_PROTOCOL);
194
if (i.n_formats > 0) {
195
i.formats = pa_xnew0(pa_format_info*, i.n_formats);
197
for (j = 0; j < i.n_formats; j++) {
199
pa_format_info *f = i.formats[j] = pa_format_info_new();
200
if (pa_tagstruct_get_format_info(t, f) < 0) {
203
pa_context_fail(o->context, PA_ERR_PROTOCOL);
204
for (k = 0; k < j+1; k++)
205
pa_format_info_free(i.formats[k]);
213
pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
214
cb(o->context, &i, 0, o->userdata);
217
for (j = 0; j < i.n_formats; j++)
218
pa_format_info_free(i.formats[j]);
224
pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
225
cb(o->context, NULL, eol, o->userdata);
229
pa_operation_done(o);
230
pa_operation_unref(o);
233
pa_operation *pa_ext_device_restore_read_formats_all(
235
pa_ext_device_restore_read_device_formats_cb_t cb,
243
pa_assert(PA_REFCNT_VALUE(c) >= 1);
245
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
246
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
247
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
249
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
251
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
252
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
253
pa_tagstruct_puts(t, "module-device-restore");
254
pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS_ALL);
255
pa_pstream_send_tagstruct(c->pstream, t);
256
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_read_device_formats_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
261
pa_operation *pa_ext_device_restore_read_formats(
263
pa_device_type_t type,
265
pa_ext_device_restore_read_device_formats_cb_t cb,
273
pa_assert(PA_REFCNT_VALUE(c) >= 1);
274
pa_assert(idx != PA_INVALID_INDEX);
276
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
277
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
278
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
280
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
282
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
283
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
284
pa_tagstruct_puts(t, "module-device-restore");
285
pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS);
286
pa_tagstruct_putu32(t, type);
287
pa_tagstruct_putu32(t, idx);
288
pa_pstream_send_tagstruct(c->pstream, t);
289
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_read_device_formats_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
294
pa_operation *pa_ext_device_restore_save_formats(
296
pa_device_type_t type,
299
pa_format_info **formats,
300
pa_context_success_cb_t cb,
309
pa_assert(PA_REFCNT_VALUE(c) >= 1);
310
pa_assert(idx != PA_INVALID_INDEX);
311
pa_assert(n_formats > 0);
312
pa_assert(formats && *formats);
314
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
315
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
316
PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
318
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
320
t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
321
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
322
pa_tagstruct_puts(t, "module-device-restore");
323
pa_tagstruct_putu32(t, SUBCOMMAND_SAVE_FORMATS);
325
pa_tagstruct_putu32(t, type);
326
pa_tagstruct_putu32(t, idx);
327
pa_tagstruct_putu8(t, n_formats);
328
for (j = 0; j < n_formats; j++)
329
pa_tagstruct_put_format_info(t, formats[j]);
331
pa_pstream_send_tagstruct(c->pstream, t);
332
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);
337
/* Command function defined in internal.h */
338
void pa_ext_device_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
340
pa_device_type_t type;
344
pa_assert(PA_REFCNT_VALUE(c) >= 1);
347
if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
348
pa_tagstruct_getu32(t, &type) < 0 ||
349
pa_tagstruct_getu32(t, &idx) < 0 ||
350
!pa_tagstruct_eof(t)) {
352
pa_context_fail(c, PA_ERR_PROTOCOL);
356
if (subcommand != SUBCOMMAND_EVENT) {
357
pa_context_fail(c, PA_ERR_PROTOCOL);
361
if (PA_DEVICE_TYPE_SINK != type && PA_DEVICE_TYPE_SOURCE != type) {
362
pa_context_fail(c, PA_ERR_PROTOCOL);
366
if (idx == PA_INVALID_INDEX) {
367
pa_context_fail(c, PA_ERR_PROTOCOL);
371
if (c->ext_device_restore.callback)
372
c->ext_device_restore.callback(c, type, idx, c->ext_device_restore.userdata);