]> code.delx.au - pulseaudio/blob - src/pulse/ext-device-restore.c
i18n: Update Russian translation
[pulseaudio] / src / pulse / ext-device-restore.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Lennart Poettering
5 Copyright 2011 Colin Guthrie
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <pulse/context.h>
28 #include <pulse/gccmacro.h>
29 #include <pulse/xmalloc.h>
30 #include <pulse/fork-detect.h>
31 #include <pulse/operation.h>
32 #include <pulse/format.h>
33
34 #include <pulsecore/macro.h>
35 #include <pulsecore/pstream-util.h>
36
37 #include "internal.h"
38 #include "ext-device-restore.h"
39
40 /* Protocol extension commands */
41 enum {
42 SUBCOMMAND_TEST,
43 SUBCOMMAND_SUBSCRIBE,
44 SUBCOMMAND_EVENT,
45 SUBCOMMAND_READ_FORMATS_ALL,
46 SUBCOMMAND_READ_FORMATS,
47 SUBCOMMAND_SAVE_FORMATS
48 };
49
50 static void ext_device_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
51 pa_operation *o = userdata;
52 uint32_t version = PA_INVALID_INDEX;
53
54 pa_assert(pd);
55 pa_assert(o);
56 pa_assert(PA_REFCNT_VALUE(o) >= 1);
57
58 if (!o->context)
59 goto finish;
60
61 if (command != PA_COMMAND_REPLY) {
62 if (pa_context_handle_error(o->context, command, t, false) < 0)
63 goto finish;
64
65 } else if (pa_tagstruct_getu32(t, &version) < 0 ||
66 !pa_tagstruct_eof(t)) {
67
68 pa_context_fail(o->context, PA_ERR_PROTOCOL);
69 goto finish;
70 }
71
72 if (o->callback) {
73 pa_ext_device_restore_test_cb_t cb = (pa_ext_device_restore_test_cb_t) o->callback;
74 cb(o->context, version, o->userdata);
75 }
76
77 finish:
78 pa_operation_done(o);
79 pa_operation_unref(o);
80 }
81
82 pa_operation *pa_ext_device_restore_test(
83 pa_context *c,
84 pa_ext_device_restore_test_cb_t cb,
85 void *userdata) {
86
87 uint32_t tag;
88 pa_operation *o;
89 pa_tagstruct *t;
90
91 pa_assert(c);
92 pa_assert(PA_REFCNT_VALUE(c) >= 1);
93
94 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
95 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
96 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
97
98 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
99
100 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
101 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
102 pa_tagstruct_puts(t, "module-device-restore");
103 pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
104 pa_pstream_send_tagstruct(c->pstream, t);
105 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);
106
107 return o;
108 }
109
110 pa_operation *pa_ext_device_restore_subscribe(
111 pa_context *c,
112 int enable,
113 pa_context_success_cb_t cb,
114 void *userdata) {
115
116 uint32_t tag;
117 pa_operation *o;
118 pa_tagstruct *t;
119
120 pa_assert(c);
121 pa_assert(PA_REFCNT_VALUE(c) >= 1);
122
123 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
124 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
125 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
126
127 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
128
129 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
130 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
131 pa_tagstruct_puts(t, "module-device-restore");
132 pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
133 pa_tagstruct_put_boolean(t, enable);
134 pa_pstream_send_tagstruct(c->pstream, t);
135 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);
136
137 return o;
138 }
139
140 void pa_ext_device_restore_set_subscribe_cb(
141 pa_context *c,
142 pa_ext_device_restore_subscribe_cb_t cb,
143 void *userdata) {
144
145 pa_assert(c);
146 pa_assert(PA_REFCNT_VALUE(c) >= 1);
147
148 if (pa_detect_fork())
149 return;
150
151 c->ext_device_restore.callback = cb;
152 c->ext_device_restore.userdata = userdata;
153 }
154
155 static void ext_device_restore_read_device_formats_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
156 pa_operation *o = userdata;
157 int eol = 1;
158
159 pa_assert(pd);
160 pa_assert(o);
161 pa_assert(PA_REFCNT_VALUE(o) >= 1);
162
163 if (!o->context)
164 goto finish;
165
166 if (command != PA_COMMAND_REPLY) {
167 if (pa_context_handle_error(o->context, command, t, false) < 0)
168 goto finish;
169
170 eol = -1;
171 } else {
172 uint8_t j;
173
174 while (!pa_tagstruct_eof(t)) {
175 pa_ext_device_restore_info i;
176 pa_zero(i);
177
178 if (pa_tagstruct_getu32(t, &i.type) < 0 ||
179 pa_tagstruct_getu32(t, &i.index) < 0 ||
180 pa_tagstruct_getu8(t, &i.n_formats) < 0) {
181
182 pa_context_fail(o->context, PA_ERR_PROTOCOL);
183 goto finish;
184 }
185
186 if (PA_DEVICE_TYPE_SINK != i.type && PA_DEVICE_TYPE_SOURCE != i.type) {
187 pa_context_fail(o->context, PA_ERR_PROTOCOL);
188 goto finish;
189 }
190
191 if (i.index == PA_INVALID_INDEX) {
192 pa_context_fail(o->context, PA_ERR_PROTOCOL);
193 goto finish;
194 }
195
196 if (i.n_formats > 0) {
197 i.formats = pa_xnew0(pa_format_info*, i.n_formats);
198
199 for (j = 0; j < i.n_formats; j++) {
200
201 pa_format_info *f = i.formats[j] = pa_format_info_new();
202 if (pa_tagstruct_get_format_info(t, f) < 0) {
203 uint8_t k;
204
205 pa_context_fail(o->context, PA_ERR_PROTOCOL);
206 for (k = 0; k < j+1; k++)
207 pa_format_info_free(i.formats[k]);
208 pa_xfree(i.formats);
209 goto finish;
210 }
211 }
212 }
213
214 if (o->callback) {
215 pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
216 cb(o->context, &i, 0, o->userdata);
217 }
218
219 for (j = 0; j < i.n_formats; j++)
220 pa_format_info_free(i.formats[j]);
221 pa_xfree(i.formats);
222 }
223 }
224
225 if (o->callback) {
226 pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
227 cb(o->context, NULL, eol, o->userdata);
228 }
229
230 finish:
231 pa_operation_done(o);
232 pa_operation_unref(o);
233 }
234
235 pa_operation *pa_ext_device_restore_read_formats_all(
236 pa_context *c,
237 pa_ext_device_restore_read_device_formats_cb_t cb,
238 void *userdata) {
239
240 uint32_t tag;
241 pa_operation *o;
242 pa_tagstruct *t;
243
244 pa_assert(c);
245 pa_assert(PA_REFCNT_VALUE(c) >= 1);
246
247 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
248 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
249 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
250
251 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
252
253 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
254 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
255 pa_tagstruct_puts(t, "module-device-restore");
256 pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS_ALL);
257 pa_pstream_send_tagstruct(c->pstream, t);
258 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);
259
260 return o;
261 }
262
263 pa_operation *pa_ext_device_restore_read_formats(
264 pa_context *c,
265 pa_device_type_t type,
266 uint32_t idx,
267 pa_ext_device_restore_read_device_formats_cb_t cb,
268 void *userdata) {
269
270 uint32_t tag;
271 pa_operation *o;
272 pa_tagstruct *t;
273
274 pa_assert(c);
275 pa_assert(PA_REFCNT_VALUE(c) >= 1);
276 pa_assert(idx != PA_INVALID_INDEX);
277
278 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
279 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
280 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
281
282 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
283
284 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
285 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
286 pa_tagstruct_puts(t, "module-device-restore");
287 pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS);
288 pa_tagstruct_putu32(t, type);
289 pa_tagstruct_putu32(t, idx);
290 pa_pstream_send_tagstruct(c->pstream, t);
291 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);
292
293 return o;
294 }
295
296 pa_operation *pa_ext_device_restore_save_formats(
297 pa_context *c,
298 pa_device_type_t type,
299 uint32_t idx,
300 uint8_t n_formats,
301 pa_format_info **formats,
302 pa_context_success_cb_t cb,
303 void *userdata) {
304
305 uint32_t tag;
306 pa_operation *o;
307 pa_tagstruct *t;
308 uint8_t j;
309
310 pa_assert(c);
311 pa_assert(PA_REFCNT_VALUE(c) >= 1);
312 pa_assert(idx != PA_INVALID_INDEX);
313 pa_assert(n_formats > 0);
314 pa_assert(formats && *formats);
315
316 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
317 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
318 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
319
320 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
321
322 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
323 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
324 pa_tagstruct_puts(t, "module-device-restore");
325 pa_tagstruct_putu32(t, SUBCOMMAND_SAVE_FORMATS);
326
327 pa_tagstruct_putu32(t, type);
328 pa_tagstruct_putu32(t, idx);
329 pa_tagstruct_putu8(t, n_formats);
330 for (j = 0; j < n_formats; j++)
331 pa_tagstruct_put_format_info(t, formats[j]);
332
333 pa_pstream_send_tagstruct(c->pstream, t);
334 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);
335
336 return o;
337 }
338
339 /* Command function defined in internal.h */
340 void pa_ext_device_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
341 uint32_t subcommand;
342 pa_device_type_t type;
343 uint32_t idx;
344
345 pa_assert(c);
346 pa_assert(PA_REFCNT_VALUE(c) >= 1);
347 pa_assert(t);
348
349 if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
350 pa_tagstruct_getu32(t, &type) < 0 ||
351 pa_tagstruct_getu32(t, &idx) < 0 ||
352 !pa_tagstruct_eof(t)) {
353
354 pa_context_fail(c, PA_ERR_PROTOCOL);
355 return;
356 }
357
358 if (subcommand != SUBCOMMAND_EVENT) {
359 pa_context_fail(c, PA_ERR_PROTOCOL);
360 return;
361 }
362
363 if (PA_DEVICE_TYPE_SINK != type && PA_DEVICE_TYPE_SOURCE != type) {
364 pa_context_fail(c, PA_ERR_PROTOCOL);
365 return;
366 }
367
368 if (idx == PA_INVALID_INDEX) {
369 pa_context_fail(c, PA_ERR_PROTOCOL);
370 return;
371 }
372
373 if (c->ext_device_restore.callback)
374 c->ext_device_restore.callback(c, type, idx, c->ext_device_restore.userdata);
375 }