2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 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, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <pulse/context.h>
28 #include <pulse/gccmacro.h>
30 #include <pulsecore/macro.h>
31 #include <pulsecore/pstream-util.h>
34 #include "operation.h"
35 #include "fork-detect.h"
37 #include "ext-device-manager.h"
44 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
,
45 SUBCOMMAND_PREFER_DEVICE
,
46 SUBCOMMAND_DEFER_DEVICE
,
51 static void ext_device_manager_test_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
52 pa_operation
*o
= userdata
;
53 uint32_t version
= PA_INVALID_INDEX
;
57 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
62 if (command
!= PA_COMMAND_REPLY
) {
63 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
66 } else if (pa_tagstruct_getu32(t
, &version
) < 0 ||
67 !pa_tagstruct_eof(t
)) {
69 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
74 pa_ext_device_manager_test_cb_t cb
= (pa_ext_device_manager_test_cb_t
) o
->callback
;
75 cb(o
->context
, version
, o
->userdata
);
80 pa_operation_unref(o
);
83 pa_operation
*pa_ext_device_manager_test(
85 pa_ext_device_manager_test_cb_t cb
,
93 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
95 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
96 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
97 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
99 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
101 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
102 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
103 pa_tagstruct_puts(t
, "module-device-manager");
104 pa_tagstruct_putu32(t
, SUBCOMMAND_TEST
);
105 pa_pstream_send_tagstruct(c
->pstream
, t
);
106 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, ext_device_manager_test_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
111 static void ext_device_manager_read_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
112 pa_operation
*o
= userdata
;
117 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
122 if (command
!= PA_COMMAND_REPLY
) {
123 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
129 while (!pa_tagstruct_eof(t
)) {
130 pa_ext_device_manager_info i
;
132 memset(&i
, 0, sizeof(i
));
134 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
135 pa_tagstruct_gets(t
, &i
.description
) < 0) {
137 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
142 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
143 cb(o
->context
, &i
, 0, o
->userdata
);
149 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
150 cb(o
->context
, NULL
, eol
, o
->userdata
);
154 pa_operation_done(o
);
155 pa_operation_unref(o
);
158 pa_operation
*pa_ext_device_manager_read(
160 pa_ext_device_manager_read_cb_t cb
,
168 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
170 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
171 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
172 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
174 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
176 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
177 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
178 pa_tagstruct_puts(t
, "module-device-manager");
179 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
180 pa_pstream_send_tagstruct(c
->pstream
, t
);
181 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, ext_device_manager_read_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
186 pa_operation
*pa_ext_device_manager_write(
188 pa_update_mode_t mode
,
189 const pa_ext_device_manager_info data
[],
191 int apply_immediately
,
192 pa_context_success_cb_t cb
,
196 pa_operation
*o
= NULL
;
197 pa_tagstruct
*t
= NULL
;
200 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
201 pa_assert(mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
|| mode
== PA_UPDATE_SET
);
204 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
205 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
206 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
208 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
210 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
211 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
212 pa_tagstruct_puts(t
, "module-device-manager");
213 pa_tagstruct_putu32(t
, SUBCOMMAND_WRITE
);
215 pa_tagstruct_putu32(t
, mode
);
216 pa_tagstruct_put_boolean(t
, apply_immediately
);
218 for (; n
> 0; n
--, data
++) {
219 if (!data
->name
|| !*data
->name
)
222 pa_tagstruct_puts(t
, data
->name
);
223 pa_tagstruct_puts(t
, data
->description
);
226 pa_pstream_send_tagstruct(c
->pstream
, t
);
227 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
);
233 pa_operation_cancel(o
);
234 pa_operation_unref(o
);
238 pa_tagstruct_free(t
);
240 pa_context_set_error(c
, PA_ERR_INVALID
);
244 pa_operation
*pa_ext_device_manager_delete(
246 const char *const s
[],
247 pa_context_success_cb_t cb
,
251 pa_operation
*o
= NULL
;
252 pa_tagstruct
*t
= NULL
;
253 const char *const *k
;
256 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
259 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
260 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
261 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
263 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
265 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
266 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
267 pa_tagstruct_puts(t
, "module-device-manager");
268 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
270 for (k
= s
; *k
; k
++) {
274 pa_tagstruct_puts(t
, *k
);
277 pa_pstream_send_tagstruct(c
->pstream
, t
);
278 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
);
284 pa_operation_cancel(o
);
285 pa_operation_unref(o
);
289 pa_tagstruct_free(t
);
291 pa_context_set_error(c
, PA_ERR_INVALID
);
295 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
298 pa_context_success_cb_t cb
,
302 pa_operation
*o
= NULL
;
303 pa_tagstruct
*t
= NULL
;
306 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
308 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
309 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
310 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
312 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
314 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
315 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
316 pa_tagstruct_puts(t
, "module-device-manager");
317 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
318 pa_tagstruct_put_boolean(t
, !!enable
);
320 pa_pstream_send_tagstruct(c
->pstream
, t
);
321 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
);
326 pa_operation
*pa_ext_device_manager_prefer_device(
330 pa_context_success_cb_t cb
,
334 pa_operation
*o
= NULL
;
335 pa_tagstruct
*t
= NULL
;
338 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
340 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
341 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
342 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
347 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
349 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
350 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
351 pa_tagstruct_puts(t
, "module-device-manager");
352 pa_tagstruct_putu32(t
, SUBCOMMAND_PREFER_DEVICE
);
353 pa_tagstruct_puts(t
, role
);
354 pa_tagstruct_puts(t
, device
);
356 pa_pstream_send_tagstruct(c
->pstream
, t
);
357 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
);
362 pa_operation
*pa_ext_device_manager_defer_device(
366 pa_context_success_cb_t cb
,
370 pa_operation
*o
= NULL
;
371 pa_tagstruct
*t
= NULL
;
374 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
376 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
377 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
378 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
383 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
385 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
386 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
387 pa_tagstruct_puts(t
, "module-device-manager");
388 pa_tagstruct_putu32(t
, SUBCOMMAND_DEFER_DEVICE
);
389 pa_tagstruct_puts(t
, role
);
390 pa_tagstruct_puts(t
, device
);
392 pa_pstream_send_tagstruct(c
->pstream
, t
);
393 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
);
398 pa_operation
*pa_ext_device_manager_subscribe(
401 pa_context_success_cb_t cb
,
409 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
411 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
412 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
413 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
415 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
417 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
418 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
419 pa_tagstruct_puts(t
, "module-device-manager");
420 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
421 pa_tagstruct_put_boolean(t
, enable
);
422 pa_pstream_send_tagstruct(c
->pstream
, t
);
423 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
);
428 void pa_ext_device_manager_set_subscribe_cb(
430 pa_ext_device_manager_subscribe_cb_t cb
,
434 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
436 if (pa_detect_fork())
439 c
->ext_device_manager
.callback
= cb
;
440 c
->ext_device_manager
.userdata
= userdata
;
443 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
447 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
450 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
451 !pa_tagstruct_eof(t
)) {
453 pa_context_fail(c
, PA_ERR_PROTOCOL
);
457 if (subcommand
!= SUBCOMMAND_EVENT
) {
458 pa_context_fail(c
, PA_ERR_PROTOCOL
);
462 if (c
->ext_device_manager
.callback
)
463 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);