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