2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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
32 #include <pulse/rtclock.h>
33 #include <pulse/timeval.h>
34 #include <pulse/version.h>
35 #include <pulse/utf8.h>
36 #include <pulse/util.h>
37 #include <pulse/xmalloc.h>
39 #include <pulsecore/native-common.h>
40 #include <pulsecore/packet.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/pstream.h>
45 #include <pulsecore/tagstruct.h>
46 #include <pulsecore/pdispatch.h>
47 #include <pulsecore/pstream-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/llist.h>
57 #include <pulsecore/creds.h>
58 #include <pulsecore/core-util.h>
59 #include <pulsecore/ipacl.h>
60 #include <pulsecore/thread-mq.h>
62 #include "protocol-native.h"
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
71 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
72 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
73 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
75 struct pa_native_protocol
;
77 typedef struct record_stream
{
80 pa_native_connection
*connection
;
83 pa_source_output
*source_output
;
84 pa_memblockq
*memblockq
;
86 pa_bool_t adjust_latency
:1;
87 pa_bool_t early_requests
:1;
89 pa_buffer_attr buffer_attr
;
91 pa_atomic_t on_the_fly
;
92 pa_usec_t configured_source_latency
;
95 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
96 size_t on_the_fly_snapshot
;
97 pa_usec_t current_monitor_latency
;
98 pa_usec_t current_source_latency
;
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 PA_DEFINE_PRIVATE_CLASS(record_stream
, pa_msgobject
);
104 typedef struct output_stream
{
108 #define OUTPUT_STREAM(o) (output_stream_cast(o))
109 PA_DEFINE_PRIVATE_CLASS(output_stream
, pa_msgobject
);
111 typedef struct playback_stream
{
112 output_stream parent
;
114 pa_native_connection
*connection
;
117 pa_sink_input
*sink_input
;
118 pa_memblockq
*memblockq
;
120 pa_bool_t adjust_latency
:1;
121 pa_bool_t early_requests
:1;
123 pa_bool_t is_underrun
:1;
124 pa_bool_t drain_request
:1;
129 pa_usec_t configured_sink_latency
;
130 pa_buffer_attr buffer_attr
;
132 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
133 int64_t read_index
, write_index
;
134 size_t render_memblockq_length
;
135 pa_usec_t current_sink_latency
;
136 uint64_t playing_for
, underrun_for
;
139 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
140 PA_DEFINE_PRIVATE_CLASS(playback_stream
, output_stream
);
142 typedef struct upload_stream
{
143 output_stream parent
;
145 pa_native_connection
*connection
;
148 pa_memchunk memchunk
;
151 pa_sample_spec sample_spec
;
152 pa_channel_map channel_map
;
153 pa_proplist
*proplist
;
156 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
157 PA_DEFINE_PRIVATE_CLASS(upload_stream
, output_stream
);
159 struct pa_native_connection
{
161 pa_native_protocol
*protocol
;
162 pa_native_options
*options
;
163 pa_bool_t authorized
:1;
164 pa_bool_t is_local
:1;
168 pa_pdispatch
*pdispatch
;
169 pa_idxset
*record_streams
, *output_streams
;
170 uint32_t rrobin_index
;
171 pa_subscription
*subscription
;
172 pa_time_event
*auth_timeout_event
;
175 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
176 PA_DEFINE_PRIVATE_CLASS(pa_native_connection
, pa_msgobject
);
178 struct pa_native_protocol
{
182 pa_idxset
*connections
;
185 pa_hook hooks
[PA_NATIVE_HOOK_MAX
];
187 pa_hashmap
*extensions
;
191 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
= PA_SOURCE_OUTPUT_MESSAGE_MAX
195 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
196 SINK_INPUT_MESSAGE_DRAIN
, /* disabled prebuf, get playback started. */
197 SINK_INPUT_MESSAGE_FLUSH
,
198 SINK_INPUT_MESSAGE_TRIGGER
,
199 SINK_INPUT_MESSAGE_SEEK
,
200 SINK_INPUT_MESSAGE_PREBUF_FORCE
,
201 SINK_INPUT_MESSAGE_UPDATE_LATENCY
,
202 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
206 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, /* data requested from sink input from the main loop */
207 PLAYBACK_STREAM_MESSAGE_UNDERFLOW
,
208 PLAYBACK_STREAM_MESSAGE_OVERFLOW
,
209 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
,
210 PLAYBACK_STREAM_MESSAGE_STARTED
,
211 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
215 RECORD_STREAM_MESSAGE_POST_DATA
/* data from source output to main loop */
219 CONNECTION_MESSAGE_RELEASE
,
220 CONNECTION_MESSAGE_REVOKE
223 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
224 static void sink_input_kill_cb(pa_sink_input
*i
);
225 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
);
226 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
);
227 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
228 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
229 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
);
230 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
);
232 static void native_connection_send_memblock(pa_native_connection
*c
);
233 static void playback_stream_request_bytes(struct playback_stream
*s
);
235 static void source_output_kill_cb(pa_source_output
*o
);
236 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
237 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
);
238 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
);
239 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
240 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
);
242 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
243 static int source_output_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
245 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
246 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
247 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
248 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
249 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
250 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
251 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
252 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
253 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
254 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
255 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
256 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
257 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
258 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
259 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
260 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
261 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
262 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
263 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
264 static void command_set_volume(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
265 static void command_set_mute(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
266 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
267 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
268 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
269 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
270 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
271 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
272 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
273 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
274 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
275 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
276 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
277 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
278 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
279 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
280 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
281 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
282 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
283 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
285 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
286 [PA_COMMAND_ERROR
] = NULL
,
287 [PA_COMMAND_TIMEOUT
] = NULL
,
288 [PA_COMMAND_REPLY
] = NULL
,
289 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
290 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
291 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
292 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
293 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
294 [PA_COMMAND_AUTH
] = command_auth
,
295 [PA_COMMAND_REQUEST
] = NULL
,
296 [PA_COMMAND_EXIT
] = command_exit
,
297 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
298 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
299 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
300 [PA_COMMAND_STAT
] = command_stat
,
301 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
302 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
303 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
304 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
305 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
306 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
307 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
308 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
309 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
310 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
311 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
312 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
313 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
314 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
315 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
316 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
317 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
318 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
319 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
320 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
321 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
322 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
323 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
324 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
325 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
327 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
328 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
329 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
331 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
332 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
333 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
335 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
336 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
338 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
339 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
340 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
341 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
343 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
344 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
346 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
347 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
348 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
349 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
350 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
351 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
352 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
353 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
354 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
356 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
357 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
358 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
359 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
361 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
362 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
364 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
365 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
367 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
368 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
370 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
371 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
372 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
374 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
375 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
376 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
378 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
380 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
381 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
383 [PA_COMMAND_EXTENSION
] = command_extension
386 /* structure management */
388 /* Called from main context */
389 static void upload_stream_unlink(upload_stream
*s
) {
395 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
396 s
->connection
= NULL
;
397 upload_stream_unref(s
);
400 /* Called from main context */
401 static void upload_stream_free(pa_object
*o
) {
402 upload_stream
*s
= UPLOAD_STREAM(o
);
405 upload_stream_unlink(s
);
410 pa_proplist_free(s
->proplist
);
412 if (s
->memchunk
.memblock
)
413 pa_memblock_unref(s
->memchunk
.memblock
);
418 /* Called from main context */
419 static upload_stream
* upload_stream_new(
420 pa_native_connection
*c
,
421 const pa_sample_spec
*ss
,
422 const pa_channel_map
*map
,
432 pa_assert(length
> 0);
435 s
= pa_msgobject_new(upload_stream
);
436 s
->parent
.parent
.parent
.free
= upload_stream_free
;
438 s
->sample_spec
= *ss
;
439 s
->channel_map
= *map
;
440 s
->name
= pa_xstrdup(name
);
441 pa_memchunk_reset(&s
->memchunk
);
443 s
->proplist
= pa_proplist_copy(p
);
444 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
446 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
451 /* Called from main context */
452 static void record_stream_unlink(record_stream
*s
) {
458 if (s
->source_output
) {
459 pa_source_output_unlink(s
->source_output
);
460 pa_source_output_unref(s
->source_output
);
461 s
->source_output
= NULL
;
464 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
465 s
->connection
= NULL
;
466 record_stream_unref(s
);
469 /* Called from main context */
470 static void record_stream_free(pa_object
*o
) {
471 record_stream
*s
= RECORD_STREAM(o
);
474 record_stream_unlink(s
);
476 pa_memblockq_free(s
->memblockq
);
480 /* Called from main context */
481 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
482 record_stream
*s
= RECORD_STREAM(o
);
483 record_stream_assert_ref(s
);
490 case RECORD_STREAM_MESSAGE_POST_DATA
:
492 /* We try to keep up to date with how many bytes are
493 * currently on the fly */
494 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
496 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
497 /* pa_log_warn("Failed to push data into output queue."); */
501 if (!pa_pstream_is_pending(s
->connection
->pstream
))
502 native_connection_send_memblock(s
->connection
);
510 /* Called from main context */
511 static void fix_record_buffer_attr_pre(record_stream
*s
) {
514 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
518 /* This function will be called from the main thread, before as
519 * well as after the source output has been activated using
520 * pa_source_output_put()! That means it may not touch any
521 * ->thread_info data! */
523 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
525 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
526 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
527 if (s
->buffer_attr
.maxlength
<= 0)
528 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
530 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
531 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
532 if (s
->buffer_attr
.fragsize
<= 0)
533 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
535 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
537 if (s
->early_requests
) {
539 /* In early request mode we need to emulate the classic
540 * fragment-based playback model. We do this setting the source
541 * latency to the fragment size. */
543 source_usec
= fragsize_usec
;
545 } else if (s
->adjust_latency
) {
547 /* So, the user asked us to adjust the latency according to
548 * what the source can provide. Half the latency will be
549 * spent on the hw buffer, half of it in the async buffer
550 * queue we maintain for each client. */
552 source_usec
= fragsize_usec
/2;
556 /* Ok, the user didn't ask us to adjust the latency, hence we
559 source_usec
= (pa_usec_t
) -1;
562 if (source_usec
!= (pa_usec_t
) -1)
563 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
565 s
->configured_source_latency
= 0;
567 if (s
->early_requests
) {
569 /* Ok, we didn't necessarily get what we were asking for, so
570 * let's tell the user */
572 fragsize_usec
= s
->configured_source_latency
;
574 } else if (s
->adjust_latency
) {
576 /* Now subtract what we actually got */
578 if (fragsize_usec
>= s
->configured_source_latency
*2)
579 fragsize_usec
-= s
->configured_source_latency
;
581 fragsize_usec
= s
->configured_source_latency
;
584 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
585 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
587 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
589 if (s
->buffer_attr
.fragsize
<= 0)
590 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
593 /* Called from main context */
594 static void fix_record_buffer_attr_post(record_stream
*s
) {
599 /* This function will be called from the main thread, before as
600 * well as after the source output has been activated using
601 * pa_source_output_put()! That means it may not touch and
602 * ->thread_info data! */
604 base
= pa_frame_size(&s
->source_output
->sample_spec
);
606 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
607 if (s
->buffer_attr
.fragsize
<= 0)
608 s
->buffer_attr
.fragsize
= base
;
610 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
611 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
614 /* Called from main context */
615 static record_stream
* record_stream_new(
616 pa_native_connection
*c
,
620 pa_bool_t peak_detect
,
621 pa_buffer_attr
*attr
,
622 pa_source_output_flags_t flags
,
624 pa_bool_t adjust_latency
,
625 pa_sink_input
*direct_on_input
,
626 pa_bool_t early_requests
,
630 pa_source_output
*source_output
= NULL
;
632 pa_source_output_new_data data
;
639 pa_source_output_new_data_init(&data
);
641 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
642 data
.driver
= __FILE__
;
643 data
.module
= c
->options
->module
;
644 data
.client
= c
->client
;
645 data
.source
= source
;
646 data
.direct_on_input
= direct_on_input
;
647 pa_source_output_new_data_set_sample_spec(&data
, ss
);
648 pa_source_output_new_data_set_channel_map(&data
, map
);
650 data
.resample_method
= PA_RESAMPLER_PEAKS
;
653 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
655 pa_source_output_new_data_done(&data
);
660 s
= pa_msgobject_new(record_stream
);
661 s
->parent
.parent
.free
= record_stream_free
;
662 s
->parent
.process_msg
= record_stream_process_msg
;
664 s
->source_output
= source_output
;
665 s
->buffer_attr
= *attr
;
666 s
->adjust_latency
= adjust_latency
;
667 s
->early_requests
= early_requests
;
668 pa_atomic_store(&s
->on_the_fly
, 0);
670 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
671 s
->source_output
->push
= source_output_push_cb
;
672 s
->source_output
->kill
= source_output_kill_cb
;
673 s
->source_output
->get_latency
= source_output_get_latency_cb
;
674 s
->source_output
->moving
= source_output_moving_cb
;
675 s
->source_output
->suspend
= source_output_suspend_cb
;
676 s
->source_output
->send_event
= source_output_send_event_cb
;
677 s
->source_output
->userdata
= s
;
679 fix_record_buffer_attr_pre(s
);
681 s
->memblockq
= pa_memblockq_new(
683 s
->buffer_attr
.maxlength
,
685 base
= pa_frame_size(&source_output
->sample_spec
),
691 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
692 fix_record_buffer_attr_post(s
);
694 *ss
= s
->source_output
->sample_spec
;
695 *map
= s
->source_output
->channel_map
;
697 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
699 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
700 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
701 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
702 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
704 pa_source_output_put(s
->source_output
);
708 /* Called from main context */
709 static void record_stream_send_killed(record_stream
*r
) {
711 record_stream_assert_ref(r
);
713 t
= pa_tagstruct_new(NULL
, 0);
714 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
715 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
716 pa_tagstruct_putu32(t
, r
->index
);
717 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
720 /* Called from main context */
721 static void playback_stream_unlink(playback_stream
*s
) {
728 pa_sink_input_unlink(s
->sink_input
);
729 pa_sink_input_unref(s
->sink_input
);
730 s
->sink_input
= NULL
;
733 if (s
->drain_request
)
734 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
736 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
737 s
->connection
= NULL
;
738 playback_stream_unref(s
);
741 /* Called from main context */
742 static void playback_stream_free(pa_object
* o
) {
743 playback_stream
*s
= PLAYBACK_STREAM(o
);
746 playback_stream_unlink(s
);
748 pa_memblockq_free(s
->memblockq
);
752 /* Called from main context */
753 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
754 playback_stream
*s
= PLAYBACK_STREAM(o
);
755 playback_stream_assert_ref(s
);
762 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
767 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
770 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
774 t
= pa_tagstruct_new(NULL
, 0);
775 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
776 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
777 pa_tagstruct_putu32(t
, s
->index
);
778 pa_tagstruct_putu32(t
, (uint32_t) l
);
779 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
781 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
785 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
788 /* pa_log("signalling underflow"); */
790 /* Report that we're empty */
791 t
= pa_tagstruct_new(NULL
, 0);
792 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
793 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
794 pa_tagstruct_putu32(t
, s
->index
);
795 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
799 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
802 /* Notify the user we're overflowed*/
803 t
= pa_tagstruct_new(NULL
, 0);
804 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
805 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
806 pa_tagstruct_putu32(t
, s
->index
);
807 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
811 case PLAYBACK_STREAM_MESSAGE_STARTED
:
813 if (s
->connection
->version
>= 13) {
816 /* Notify the user we started playback */
817 t
= pa_tagstruct_new(NULL
, 0);
818 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
819 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
820 pa_tagstruct_putu32(t
, s
->index
);
821 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
826 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
827 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
830 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
: {
833 s
->buffer_attr
.tlength
= (uint32_t) offset
;
835 t
= pa_tagstruct_new(NULL
, 0);
836 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
837 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
838 pa_tagstruct_putu32(t
, s
->index
);
839 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
840 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
841 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
842 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
843 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
844 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
853 /* Called from main context */
854 static void fix_playback_buffer_attr(playback_stream
*s
) {
855 size_t frame_size
, max_prebuf
;
856 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
860 /* This function will be called from the main thread, before as
861 * well as after the sink input has been activated using
862 * pa_sink_input_put()! That means it may not touch any
863 * ->thread_info data, such as the memblockq! */
865 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
867 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
868 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
869 if (s
->buffer_attr
.maxlength
<= 0)
870 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
872 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
873 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
874 if (s
->buffer_attr
.tlength
<= 0)
875 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
877 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
878 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
879 if (s
->buffer_attr
.minreq
<= 0)
880 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
882 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
883 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
885 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
886 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
888 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
889 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
890 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
892 if (s
->early_requests
) {
894 /* In early request mode we need to emulate the classic
895 * fragment-based playback model. We do this setting the sink
896 * latency to the fragment size. */
898 sink_usec
= minreq_usec
;
899 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
901 } else if (s
->adjust_latency
) {
903 /* So, the user asked us to adjust the latency of the stream
904 * buffer according to the what the sink can provide. The
905 * tlength passed in shall be the overall latency. Roughly
906 * half the latency will be spent on the hw buffer, the other
907 * half of it in the async buffer queue we maintain for each
908 * client. In between we'll have a safety space of size
909 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
910 * empty and needs to be filled, then our buffer must have
911 * enough data to fulfill this request immediatly and thus
912 * have at least the same tlength as the size of the hw
913 * buffer. It additionally needs space for 2 times minreq
914 * because if the buffer ran empty and a partial fillup
915 * happens immediately on the next iteration we need to be
916 * able to fulfill it and give the application also minreq
917 * time to fill it up again for the next request Makes 2 times
918 * minreq in plus.. */
920 if (tlength_usec
> minreq_usec
*2)
921 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
925 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
929 /* Ok, the user didn't ask us to adjust the latency, but we
930 * still need to make sure that the parameters from the user
933 if (tlength_usec
> minreq_usec
*2)
934 sink_usec
= (tlength_usec
- minreq_usec
*2);
938 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
941 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
943 if (s
->early_requests
) {
945 /* Ok, we didn't necessarily get what we were asking for, so
946 * let's tell the user */
948 minreq_usec
= s
->configured_sink_latency
;
950 } else if (s
->adjust_latency
) {
952 /* Ok, we didn't necessarily get what we were asking for, so
953 * let's subtract from what we asked for for the remaining
956 if (tlength_usec
>= s
->configured_sink_latency
)
957 tlength_usec
-= s
->configured_sink_latency
;
960 /* FIXME: This is actually larger than necessary, since not all of
961 * the sink latency is actually rewritable. */
962 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
963 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
965 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
966 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
967 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
969 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
970 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
971 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
973 if (s
->buffer_attr
.minreq
<= 0) {
974 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
975 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
978 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
979 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
981 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
983 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
984 s
->buffer_attr
.prebuf
> max_prebuf
)
985 s
->buffer_attr
.prebuf
= max_prebuf
;
988 /* Called from main context */
989 static playback_stream
* playback_stream_new(
990 pa_native_connection
*c
,
1000 pa_sink_input_flags_t flags
,
1002 pa_bool_t adjust_latency
,
1003 pa_bool_t early_requests
,
1006 playback_stream
*s
, *ssync
;
1007 pa_sink_input
*sink_input
= NULL
;
1008 pa_memchunk silence
;
1010 int64_t start_index
;
1011 pa_sink_input_new_data data
;
1019 /* Find syncid group */
1020 for (ssync
= pa_idxset_first(c
->output_streams
, &idx
); ssync
; ssync
= pa_idxset_next(c
->output_streams
, &idx
)) {
1022 if (!playback_stream_isinstance(ssync
))
1025 if (ssync
->syncid
== syncid
)
1029 /* Synced streams must connect to the same sink */
1033 sink
= ssync
->sink_input
->sink
;
1034 else if (sink
!= ssync
->sink_input
->sink
) {
1035 *ret
= PA_ERR_INVALID
;
1040 pa_sink_input_new_data_init(&data
);
1042 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1043 data
.driver
= __FILE__
;
1044 data
.module
= c
->options
->module
;
1045 data
.client
= c
->client
;
1047 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1048 pa_sink_input_new_data_set_channel_map(&data
, map
);
1050 pa_sink_input_new_data_set_volume(&data
, volume
);
1052 pa_sink_input_new_data_set_muted(&data
, muted
);
1053 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1056 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1058 pa_sink_input_new_data_done(&data
);
1063 s
= pa_msgobject_new(playback_stream
);
1064 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1065 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1068 s
->sink_input
= sink_input
;
1069 s
->is_underrun
= TRUE
;
1070 s
->drain_request
= FALSE
;
1071 pa_atomic_store(&s
->missing
, 0);
1072 s
->buffer_attr
= *a
;
1073 s
->adjust_latency
= adjust_latency
;
1074 s
->early_requests
= early_requests
;
1076 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1077 s
->sink_input
->pop
= sink_input_pop_cb
;
1078 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1079 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1080 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1081 s
->sink_input
->kill
= sink_input_kill_cb
;
1082 s
->sink_input
->moving
= sink_input_moving_cb
;
1083 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1084 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1085 s
->sink_input
->userdata
= s
;
1087 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1089 fix_playback_buffer_attr(s
);
1091 pa_sink_input_get_silence(sink_input
, &silence
);
1092 s
->memblockq
= pa_memblockq_new(
1094 s
->buffer_attr
.maxlength
,
1095 s
->buffer_attr
.tlength
,
1096 pa_frame_size(&sink_input
->sample_spec
),
1097 s
->buffer_attr
.prebuf
,
1098 s
->buffer_attr
.minreq
,
1101 pa_memblock_unref(silence
.memblock
);
1103 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1105 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1107 *ss
= s
->sink_input
->sample_spec
;
1108 *map
= s
->sink_input
->channel_map
;
1110 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1112 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1113 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1114 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1115 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1116 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1118 pa_sink_input_put(s
->sink_input
);
1122 /* Called from IO context */
1123 static void playback_stream_request_bytes(playback_stream
*s
) {
1125 int previous_missing
;
1127 playback_stream_assert_ref(s
);
1129 m
= pa_memblockq_pop_missing(s
->memblockq
);
1131 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
1132 /* (unsigned long) m, */
1133 /* pa_memblockq_get_tlength(s->memblockq), */
1134 /* pa_memblockq_get_minreq(s->memblockq), */
1135 /* pa_memblockq_get_length(s->memblockq)); */
1140 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1142 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1143 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1145 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1146 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1147 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1150 /* Called from main context */
1151 static void playback_stream_send_killed(playback_stream
*p
) {
1153 playback_stream_assert_ref(p
);
1155 t
= pa_tagstruct_new(NULL
, 0);
1156 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1157 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1158 pa_tagstruct_putu32(t
, p
->index
);
1159 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1162 /* Called from main context */
1163 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1164 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1165 pa_native_connection_assert_ref(c
);
1172 case CONNECTION_MESSAGE_REVOKE
:
1173 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1176 case CONNECTION_MESSAGE_RELEASE
:
1177 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1184 /* Called from main context */
1185 static void native_connection_unlink(pa_native_connection
*c
) {
1194 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1197 pa_native_options_unref(c
->options
);
1199 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1200 record_stream_unlink(r
);
1202 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1203 if (playback_stream_isinstance(o
))
1204 playback_stream_unlink(PLAYBACK_STREAM(o
));
1206 upload_stream_unlink(UPLOAD_STREAM(o
));
1208 if (c
->subscription
)
1209 pa_subscription_free(c
->subscription
);
1212 pa_pstream_unlink(c
->pstream
);
1214 if (c
->auth_timeout_event
) {
1215 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1216 c
->auth_timeout_event
= NULL
;
1219 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1221 pa_native_connection_unref(c
);
1224 /* Called from main context */
1225 static void native_connection_free(pa_object
*o
) {
1226 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1230 native_connection_unlink(c
);
1232 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1233 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1235 pa_pdispatch_unref(c
->pdispatch
);
1236 pa_pstream_unref(c
->pstream
);
1237 pa_client_free(c
->client
);
1242 /* Called from main context */
1243 static void native_connection_send_memblock(pa_native_connection
*c
) {
1247 start
= PA_IDXSET_INVALID
;
1251 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1254 if (start
== PA_IDXSET_INVALID
)
1255 start
= c
->rrobin_index
;
1256 else if (start
== c
->rrobin_index
)
1259 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1260 pa_memchunk schunk
= chunk
;
1262 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1263 schunk
.length
= r
->buffer_attr
.fragsize
;
1265 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1267 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1268 pa_memblock_unref(schunk
.memblock
);
1275 /*** sink input callbacks ***/
1277 /* Called from thread context */
1278 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1279 playback_stream_assert_ref(s
);
1281 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1283 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1285 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1287 if (pa_memblockq_is_readable(s
->memblockq
)) {
1289 /* We just ended an underrun, let's ask the sink
1290 * for a complete rewind rewrite */
1292 pa_log_debug("Requesting rewind due to end of underrun.");
1293 pa_sink_input_request_rewind(s
->sink_input
,
1294 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1295 s
->sink_input
->thread_info
.underrun_for
),
1296 FALSE
, TRUE
, FALSE
);
1302 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1304 if (indexw
< indexr
) {
1305 /* OK, the sink already asked for this data, so
1306 * let's have it usk us again */
1308 pa_log_debug("Requesting rewind due to rewrite.");
1309 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1313 playback_stream_request_bytes(s
);
1316 /* Called from thread context */
1317 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1318 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1321 pa_sink_input_assert_ref(i
);
1322 s
= PLAYBACK_STREAM(i
->userdata
);
1323 playback_stream_assert_ref(s
);
1327 case SINK_INPUT_MESSAGE_SEEK
: {
1330 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1332 /* The client side is incapable of accounting correctly
1333 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1334 * able to deal with that. */
1336 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1338 handle_seek(s
, windex
);
1342 case SINK_INPUT_MESSAGE_POST_DATA
: {
1347 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1349 /* pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1351 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1353 if (pa_log_ratelimit())
1354 pa_log_warn("Failed to push data into queue");
1355 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1356 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1359 handle_seek(s
, windex
);
1361 /* pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1366 case SINK_INPUT_MESSAGE_DRAIN
:
1367 case SINK_INPUT_MESSAGE_FLUSH
:
1368 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1369 case SINK_INPUT_MESSAGE_TRIGGER
: {
1372 pa_sink_input
*isync
;
1373 void (*func
)(pa_memblockq
*bq
);
1376 case SINK_INPUT_MESSAGE_FLUSH
:
1377 func
= pa_memblockq_flush_write
;
1380 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1381 func
= pa_memblockq_prebuf_force
;
1384 case SINK_INPUT_MESSAGE_DRAIN
:
1385 case SINK_INPUT_MESSAGE_TRIGGER
:
1386 func
= pa_memblockq_prebuf_disable
;
1390 pa_assert_not_reached();
1393 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1395 handle_seek(s
, windex
);
1397 /* Do the same for all other members in the sync group */
1398 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1399 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1400 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1401 func(ssync
->memblockq
);
1402 handle_seek(ssync
, windex
);
1405 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1406 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1407 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1408 func(ssync
->memblockq
);
1409 handle_seek(ssync
, windex
);
1412 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1413 if (!pa_memblockq_is_readable(s
->memblockq
))
1414 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1416 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1417 s
->drain_request
= TRUE
;
1424 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1425 /* Atomically get a snapshot of all timing parameters... */
1426 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1427 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1428 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1429 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1430 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1431 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1435 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1438 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1440 pa_memblockq_prebuf_force(s
->memblockq
);
1442 handle_seek(s
, windex
);
1444 /* Fall through to the default handler */
1448 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1449 pa_usec_t
*r
= userdata
;
1451 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1453 /* Fall through, the default handler will add in the extra
1454 * latency added by the resampler */
1458 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1459 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1460 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1465 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1468 /* Called from thread context */
1469 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1472 pa_sink_input_assert_ref(i
);
1473 s
= PLAYBACK_STREAM(i
->userdata
);
1474 playback_stream_assert_ref(s
);
1477 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1479 if (pa_memblockq_is_readable(s
->memblockq
))
1480 s
->is_underrun
= FALSE
;
1482 if (!s
->is_underrun
)
1483 pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)), (unsigned long) pa_memblockq_get_length(s
->memblockq
));
1485 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1486 s
->drain_request
= FALSE
;
1487 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, PA_UINT_TO_PTR(s
->drain_tag
), 0, NULL
, NULL
);
1488 } else if (!s
->is_underrun
)
1489 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, 0, NULL
, NULL
);
1491 s
->is_underrun
= TRUE
;
1493 playback_stream_request_bytes(s
);
1496 /* This call will not fail with prebuf=0, hence we check for
1497 underrun explicitly above */
1498 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1501 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1503 if (i
->thread_info
.underrun_for
> 0)
1504 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1506 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1507 playback_stream_request_bytes(s
);
1512 /* Called from thread context */
1513 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1516 pa_sink_input_assert_ref(i
);
1517 s
= PLAYBACK_STREAM(i
->userdata
);
1518 playback_stream_assert_ref(s
);
1520 /* If we are in an underrun, then we don't rewind */
1521 if (i
->thread_info
.underrun_for
> 0)
1524 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1527 /* Called from thread context */
1528 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1531 pa_sink_input_assert_ref(i
);
1532 s
= PLAYBACK_STREAM(i
->userdata
);
1533 playback_stream_assert_ref(s
);
1535 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1538 /* Called from thread context */
1539 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1541 size_t new_tlength
, old_tlength
;
1543 pa_sink_input_assert_ref(i
);
1544 s
= PLAYBACK_STREAM(i
->userdata
);
1545 playback_stream_assert_ref(s
);
1547 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1548 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1550 if (old_tlength
< new_tlength
) {
1551 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1552 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1553 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1555 if (new_tlength
== old_tlength
)
1556 pa_log_debug("Failed to increase tlength");
1558 pa_log_debug("Notifying client about increased tlength");
1559 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
, NULL
, pa_memblockq_get_tlength(s
->memblockq
), NULL
, NULL
);
1564 /* Called from main context */
1565 static void sink_input_kill_cb(pa_sink_input
*i
) {
1568 pa_sink_input_assert_ref(i
);
1569 s
= PLAYBACK_STREAM(i
->userdata
);
1570 playback_stream_assert_ref(s
);
1572 playback_stream_send_killed(s
);
1573 playback_stream_unlink(s
);
1576 /* Called from main context */
1577 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1581 pa_sink_input_assert_ref(i
);
1582 s
= PLAYBACK_STREAM(i
->userdata
);
1583 playback_stream_assert_ref(s
);
1585 if (s
->connection
->version
< 15)
1588 t
= pa_tagstruct_new(NULL
, 0);
1589 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1590 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1591 pa_tagstruct_putu32(t
, s
->index
);
1592 pa_tagstruct_puts(t
, event
);
1593 pa_tagstruct_put_proplist(t
, pl
);
1594 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1597 /* Called from main context */
1598 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1602 pa_sink_input_assert_ref(i
);
1603 s
= PLAYBACK_STREAM(i
->userdata
);
1604 playback_stream_assert_ref(s
);
1606 if (s
->connection
->version
< 12)
1609 t
= pa_tagstruct_new(NULL
, 0);
1610 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1611 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1612 pa_tagstruct_putu32(t
, s
->index
);
1613 pa_tagstruct_put_boolean(t
, suspend
);
1614 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1617 /* Called from main context */
1618 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1622 pa_sink_input_assert_ref(i
);
1623 s
= PLAYBACK_STREAM(i
->userdata
);
1624 playback_stream_assert_ref(s
);
1629 fix_playback_buffer_attr(s
);
1630 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1631 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1633 if (s
->connection
->version
< 12)
1636 t
= pa_tagstruct_new(NULL
, 0);
1637 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1638 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1639 pa_tagstruct_putu32(t
, s
->index
);
1640 pa_tagstruct_putu32(t
, dest
->index
);
1641 pa_tagstruct_puts(t
, dest
->name
);
1642 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1644 if (s
->connection
->version
>= 13) {
1645 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1646 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1647 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1648 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1649 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1652 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1655 /*** source_output callbacks ***/
1657 /* Called from thread context */
1658 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1659 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1662 pa_source_output_assert_ref(o
);
1663 s
= RECORD_STREAM(o
->userdata
);
1664 record_stream_assert_ref(s
);
1667 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1668 /* Atomically get a snapshot of all timing parameters... */
1669 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1670 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1671 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1675 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1678 /* Called from thread context */
1679 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1682 pa_source_output_assert_ref(o
);
1683 s
= RECORD_STREAM(o
->userdata
);
1684 record_stream_assert_ref(s
);
1687 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1688 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1691 static void source_output_kill_cb(pa_source_output
*o
) {
1694 pa_source_output_assert_ref(o
);
1695 s
= RECORD_STREAM(o
->userdata
);
1696 record_stream_assert_ref(s
);
1698 record_stream_send_killed(s
);
1699 record_stream_unlink(s
);
1702 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1705 pa_source_output_assert_ref(o
);
1706 s
= RECORD_STREAM(o
->userdata
);
1707 record_stream_assert_ref(s
);
1709 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1711 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1714 /* Called from main context */
1715 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1719 pa_source_output_assert_ref(o
);
1720 s
= RECORD_STREAM(o
->userdata
);
1721 record_stream_assert_ref(s
);
1723 if (s
->connection
->version
< 15)
1726 t
= pa_tagstruct_new(NULL
, 0);
1727 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1728 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1729 pa_tagstruct_putu32(t
, s
->index
);
1730 pa_tagstruct_puts(t
, event
);
1731 pa_tagstruct_put_proplist(t
, pl
);
1732 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1735 /* Called from main context */
1736 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1740 pa_source_output_assert_ref(o
);
1741 s
= RECORD_STREAM(o
->userdata
);
1742 record_stream_assert_ref(s
);
1744 if (s
->connection
->version
< 12)
1747 t
= pa_tagstruct_new(NULL
, 0);
1748 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1749 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1750 pa_tagstruct_putu32(t
, s
->index
);
1751 pa_tagstruct_put_boolean(t
, suspend
);
1752 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1755 /* Called from main context */
1756 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1760 pa_source_output_assert_ref(o
);
1761 s
= RECORD_STREAM(o
->userdata
);
1762 record_stream_assert_ref(s
);
1767 fix_record_buffer_attr_pre(s
);
1768 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1769 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1770 fix_record_buffer_attr_post(s
);
1772 if (s
->connection
->version
< 12)
1775 t
= pa_tagstruct_new(NULL
, 0);
1776 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1777 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1778 pa_tagstruct_putu32(t
, s
->index
);
1779 pa_tagstruct_putu32(t
, dest
->index
);
1780 pa_tagstruct_puts(t
, dest
->name
);
1781 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1783 if (s
->connection
->version
>= 13) {
1784 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1785 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1786 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1789 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1792 /*** pdispatch callbacks ***/
1794 static void protocol_error(pa_native_connection
*c
) {
1795 pa_log("protocol error, kicking client");
1796 native_connection_unlink(c
);
1799 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1800 if (!(expression)) { \
1801 pa_pstream_send_error((pstream), (tag), (error)); \
1806 static pa_tagstruct
*reply_new(uint32_t tag
) {
1807 pa_tagstruct
*reply
;
1809 reply
= pa_tagstruct_new(NULL
, 0);
1810 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1811 pa_tagstruct_putu32(reply
, tag
);
1815 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1816 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1818 uint32_t sink_index
, syncid
, missing
;
1819 pa_buffer_attr attr
;
1820 const char *name
= NULL
, *sink_name
;
1823 pa_tagstruct
*reply
;
1824 pa_sink
*sink
= NULL
;
1832 fix_channels
= FALSE
,
1834 variable_rate
= FALSE
,
1836 adjust_latency
= FALSE
,
1837 early_requests
= FALSE
,
1838 dont_inhibit_auto_suspend
= FALSE
,
1840 fail_on_suspend
= FALSE
;
1841 pa_sink_input_flags_t flags
= 0;
1843 pa_bool_t volume_set
= TRUE
;
1844 int ret
= PA_ERR_INVALID
;
1846 pa_native_connection_assert_ref(c
);
1848 memset(&attr
, 0, sizeof(attr
));
1850 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1853 PA_TAG_SAMPLE_SPEC
, &ss
,
1854 PA_TAG_CHANNEL_MAP
, &map
,
1855 PA_TAG_U32
, &sink_index
,
1856 PA_TAG_STRING
, &sink_name
,
1857 PA_TAG_U32
, &attr
.maxlength
,
1858 PA_TAG_BOOLEAN
, &corked
,
1859 PA_TAG_U32
, &attr
.tlength
,
1860 PA_TAG_U32
, &attr
.prebuf
,
1861 PA_TAG_U32
, &attr
.minreq
,
1862 PA_TAG_U32
, &syncid
,
1863 PA_TAG_CVOLUME
, &volume
,
1864 PA_TAG_INVALID
) < 0) {
1870 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
1871 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name(sink_name
), tag
, PA_ERR_INVALID
);
1872 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
1873 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
1874 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
1875 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
1876 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
1877 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
1879 p
= pa_proplist_new();
1882 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1884 if (c
->version
>= 12) {
1885 /* Since 0.9.8 the user can ask for a couple of additional flags */
1887 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
1888 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
1889 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
1890 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
1891 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
1892 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
1893 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
1896 pa_proplist_free(p
);
1901 if (c
->version
>= 13) {
1903 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
1904 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
1905 pa_tagstruct_get_proplist(t
, p
) < 0) {
1907 pa_proplist_free(p
);
1912 if (c
->version
>= 14) {
1914 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
1915 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
1917 pa_proplist_free(p
);
1922 if (c
->version
>= 15) {
1924 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
1925 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
1926 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
1928 pa_proplist_free(p
);
1933 if (!pa_tagstruct_eof(t
)) {
1935 pa_proplist_free(p
);
1939 if (sink_index
!= PA_INVALID_INDEX
) {
1941 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
1942 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1943 pa_proplist_free(p
);
1947 } else if (sink_name
) {
1949 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
1950 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1951 pa_proplist_free(p
);
1957 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
1958 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
1959 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
1960 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
1961 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
1962 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
1963 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
1964 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
1965 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
1966 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0);
1968 /* Only since protocol version 15 there's a seperate muted_set
1969 * flag. For older versions we synthesize it here */
1970 muted_set
= muted_set
|| muted
;
1972 s
= playback_stream_new(c
, sink
, &ss
, &map
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, syncid
, &missing
, flags
, p
, adjust_latency
, early_requests
, &ret
);
1973 pa_proplist_free(p
);
1975 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
1977 reply
= reply_new(tag
);
1978 pa_tagstruct_putu32(reply
, s
->index
);
1979 pa_assert(s
->sink_input
);
1980 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
1981 pa_tagstruct_putu32(reply
, missing
);
1983 /* pa_log("initial request is %u", missing); */
1985 if (c
->version
>= 9) {
1986 /* Since 0.9.0 we support sending the buffer metrics back to the client */
1988 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
1989 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
1990 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
1991 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
1994 if (c
->version
>= 12) {
1995 /* Since 0.9.8 we support sending the chosen sample
1996 * spec/channel map/device/suspend status back to the
1999 pa_tagstruct_put_sample_spec(reply
, &ss
);
2000 pa_tagstruct_put_channel_map(reply
, &map
);
2002 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2003 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2005 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2008 if (c
->version
>= 13)
2009 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2011 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2014 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2015 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2018 pa_native_connection_assert_ref(c
);
2021 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2022 !pa_tagstruct_eof(t
)) {
2027 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2031 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2033 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2034 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2038 playback_stream_unlink(s
);
2042 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2044 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2045 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2049 record_stream_unlink(s
);
2053 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2056 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2057 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2061 upload_stream_unlink(s
);
2066 pa_assert_not_reached();
2069 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2072 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2073 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2075 pa_buffer_attr attr
;
2076 uint32_t source_index
;
2077 const char *name
= NULL
, *source_name
;
2080 pa_tagstruct
*reply
;
2081 pa_source
*source
= NULL
;
2088 fix_channels
= FALSE
,
2090 variable_rate
= FALSE
,
2091 adjust_latency
= FALSE
,
2092 peak_detect
= FALSE
,
2093 early_requests
= FALSE
,
2094 dont_inhibit_auto_suspend
= FALSE
,
2095 fail_on_suspend
= FALSE
;
2096 pa_source_output_flags_t flags
= 0;
2098 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2099 pa_sink_input
*direct_on_input
= NULL
;
2100 int ret
= PA_ERR_INVALID
;
2102 pa_native_connection_assert_ref(c
);
2105 memset(&attr
, 0, sizeof(attr
));
2107 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2108 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2109 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2110 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2111 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2112 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2113 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2114 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2119 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2120 CHECK_VALIDITY(c
->pstream
, !source_name
|| pa_namereg_is_valid_name(source_name
), tag
, PA_ERR_INVALID
);
2121 CHECK_VALIDITY(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
);
2122 CHECK_VALIDITY(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2123 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2124 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2125 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2127 p
= pa_proplist_new();
2130 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2132 if (c
->version
>= 12) {
2133 /* Since 0.9.8 the user can ask for a couple of additional flags */
2135 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2136 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2137 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2138 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2139 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2140 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2141 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2144 pa_proplist_free(p
);
2149 if (c
->version
>= 13) {
2151 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2152 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2153 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2154 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2156 pa_proplist_free(p
);
2161 if (c
->version
>= 14) {
2163 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2165 pa_proplist_free(p
);
2170 if (c
->version
>= 15) {
2172 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2173 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2175 pa_proplist_free(p
);
2180 if (!pa_tagstruct_eof(t
)) {
2182 pa_proplist_free(p
);
2186 if (source_index
!= PA_INVALID_INDEX
) {
2188 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2189 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2190 pa_proplist_free(p
);
2194 } else if (source_name
) {
2196 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2197 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2198 pa_proplist_free(p
);
2203 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2205 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2206 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2207 pa_proplist_free(p
);
2213 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2214 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2215 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2216 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2217 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2218 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2219 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2220 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2221 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2222 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0);
2224 s
= record_stream_new(c
, source
, &ss
, &map
, peak_detect
, &attr
, flags
, p
, adjust_latency
, direct_on_input
, early_requests
, &ret
);
2225 pa_proplist_free(p
);
2227 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
2229 reply
= reply_new(tag
);
2230 pa_tagstruct_putu32(reply
, s
->index
);
2231 pa_assert(s
->source_output
);
2232 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2234 if (c
->version
>= 9) {
2235 /* Since 0.9 we support sending the buffer metrics back to the client */
2237 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2238 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2241 if (c
->version
>= 12) {
2242 /* Since 0.9.8 we support sending the chosen sample
2243 * spec/channel map/device/suspend status back to the
2246 pa_tagstruct_put_sample_spec(reply
, &ss
);
2247 pa_tagstruct_put_channel_map(reply
, &map
);
2249 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2250 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2252 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2255 if (c
->version
>= 13)
2256 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2258 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2261 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2262 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2265 pa_native_connection_assert_ref(c
);
2268 if (!pa_tagstruct_eof(t
)) {
2273 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2274 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2275 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2277 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2280 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2281 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2283 pa_tagstruct
*reply
;
2284 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2286 pa_native_connection_assert_ref(c
);
2289 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2290 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2291 !pa_tagstruct_eof(t
)) {
2296 /* Minimum supported version */
2297 if (c
->version
< 8) {
2298 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2302 /* Starting with protocol version 13 the MSB of the version tag
2303 reflects if shm is available for this pa_native_connection or
2305 if (c
->version
>= 13) {
2306 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2307 c
->version
&= 0x7FFFFFFFU
;
2310 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2312 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2314 if (!c
->authorized
) {
2315 pa_bool_t success
= FALSE
;
2318 const pa_creds
*creds
;
2320 if ((creds
= pa_pdispatch_creds(pd
))) {
2321 if (creds
->uid
== getuid())
2323 else if (c
->options
->auth_group
) {
2327 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2328 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2329 else if (gid
== creds
->gid
)
2333 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2334 pa_log_warn("Failed to check group membership.");
2340 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2341 (unsigned long) creds
->uid
,
2342 (unsigned long) creds
->gid
,
2347 if (!success
&& c
->options
->auth_cookie
) {
2350 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2351 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2356 pa_log_warn("Denied access to client with invalid authorization data.");
2357 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2361 c
->authorized
= TRUE
;
2362 if (c
->auth_timeout_event
) {
2363 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2364 c
->auth_timeout_event
= NULL
;
2368 /* Enable shared memory support if possible */
2370 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2373 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2376 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2381 /* Only enable SHM if both sides are owned by the same
2382 * user. This is a security measure because otherwise data
2383 * private to the user might leak. */
2385 const pa_creds
*creds
;
2386 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2391 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2392 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2394 reply
= reply_new(tag
);
2395 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2399 /* SHM support is only enabled after both sides made sure they are the same user. */
2403 ucred
.uid
= getuid();
2404 ucred
.gid
= getgid();
2406 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2409 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2413 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2414 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2415 const char *name
= NULL
;
2417 pa_tagstruct
*reply
;
2419 pa_native_connection_assert_ref(c
);
2422 p
= pa_proplist_new();
2424 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2425 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2426 !pa_tagstruct_eof(t
)) {
2429 pa_proplist_free(p
);
2434 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2435 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2436 pa_proplist_free(p
);
2440 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2441 pa_proplist_free(p
);
2443 reply
= reply_new(tag
);
2445 if (c
->version
>= 13)
2446 pa_tagstruct_putu32(reply
, c
->client
->index
);
2448 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2451 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2452 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2454 uint32_t idx
= PA_IDXSET_INVALID
;
2456 pa_native_connection_assert_ref(c
);
2459 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2460 !pa_tagstruct_eof(t
)) {
2465 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2466 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2468 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2470 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2474 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2475 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2476 idx
= source
->index
;
2479 if (idx
== PA_IDXSET_INVALID
)
2480 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2482 pa_tagstruct
*reply
;
2483 reply
= reply_new(tag
);
2484 pa_tagstruct_putu32(reply
, idx
);
2485 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2489 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2490 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2494 pa_native_connection_assert_ref(c
);
2497 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2498 !pa_tagstruct_eof(t
)) {
2503 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2504 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2505 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2506 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2508 pa_asyncmsgq_post(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_DRAIN
, PA_UINT_TO_PTR(tag
), 0, NULL
, NULL
);
2511 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2512 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2513 pa_tagstruct
*reply
;
2514 const pa_mempool_stat
*stat
;
2516 pa_native_connection_assert_ref(c
);
2519 if (!pa_tagstruct_eof(t
)) {
2524 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2526 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2528 reply
= reply_new(tag
);
2529 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2530 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2531 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2532 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2533 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2534 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2537 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2538 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2539 pa_tagstruct
*reply
;
2541 struct timeval tv
, now
;
2544 pa_native_connection_assert_ref(c
);
2547 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2548 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2549 !pa_tagstruct_eof(t
)) {
2554 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2555 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2556 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2557 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2559 /* Get an atomic snapshot of all timing parameters */
2560 pa_assert_se(pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_UPDATE_LATENCY
, s
, 0, NULL
) == 0);
2562 reply
= reply_new(tag
);
2563 pa_tagstruct_put_usec(reply
,
2564 s
->current_sink_latency
+
2565 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2566 pa_tagstruct_put_usec(reply
, 0);
2567 pa_tagstruct_put_boolean(reply
,
2568 s
->playing_for
> 0 &&
2569 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2570 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2571 pa_tagstruct_put_timeval(reply
, &tv
);
2572 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2573 pa_tagstruct_puts64(reply
, s
->write_index
);
2574 pa_tagstruct_puts64(reply
, s
->read_index
);
2576 if (c
->version
>= 13) {
2577 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2578 pa_tagstruct_putu64(reply
, s
->playing_for
);
2581 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2584 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2585 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2586 pa_tagstruct
*reply
;
2588 struct timeval tv
, now
;
2591 pa_native_connection_assert_ref(c
);
2594 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2595 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2596 !pa_tagstruct_eof(t
)) {
2601 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2602 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2603 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2605 /* Get an atomic snapshot of all timing parameters */
2606 pa_assert_se(pa_asyncmsgq_send(s
->source_output
->source
->asyncmsgq
, PA_MSGOBJECT(s
->source_output
), SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
, s
, 0, NULL
) == 0);
2608 reply
= reply_new(tag
);
2609 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2610 pa_tagstruct_put_usec(reply
,
2611 s
->current_source_latency
+
2612 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->sample_spec
));
2613 pa_tagstruct_put_boolean(reply
,
2614 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2615 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2616 pa_tagstruct_put_timeval(reply
, &tv
);
2617 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2618 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2619 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2620 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2623 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2624 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2627 const char *name
= NULL
;
2630 pa_tagstruct
*reply
;
2633 pa_native_connection_assert_ref(c
);
2636 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2637 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2638 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2639 pa_tagstruct_getu32(t
, &length
) < 0) {
2644 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2645 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2646 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2647 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2648 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2649 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2651 p
= pa_proplist_new();
2653 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2654 !pa_tagstruct_eof(t
)) {
2657 pa_proplist_free(p
);
2661 if (c
->version
< 13)
2662 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2664 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2665 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2667 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2668 pa_proplist_free(p
);
2669 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2672 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2673 pa_proplist_free(p
);
2675 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2677 reply
= reply_new(tag
);
2678 pa_tagstruct_putu32(reply
, s
->index
);
2679 pa_tagstruct_putu32(reply
, length
);
2680 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2683 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2684 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2689 pa_native_connection_assert_ref(c
);
2692 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2693 !pa_tagstruct_eof(t
)) {
2698 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2700 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2701 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2702 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2704 if (!s
->memchunk
.memblock
)
2705 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2706 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2707 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2709 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2711 upload_stream_unlink(s
);
2714 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2715 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2716 uint32_t sink_index
;
2719 const char *name
, *sink_name
;
2722 pa_tagstruct
*reply
;
2724 pa_native_connection_assert_ref(c
);
2727 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2729 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2730 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2731 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2732 pa_tagstruct_gets(t
, &name
) < 0) {
2737 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name(sink_name
), tag
, PA_ERR_INVALID
);
2738 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2739 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2740 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2742 if (sink_index
!= PA_INVALID_INDEX
)
2743 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
2745 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
2747 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
2749 p
= pa_proplist_new();
2751 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2752 !pa_tagstruct_eof(t
)) {
2754 pa_proplist_free(p
);
2758 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
2760 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
2761 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2762 pa_proplist_free(p
);
2766 pa_proplist_free(p
);
2768 reply
= reply_new(tag
);
2770 if (c
->version
>= 13)
2771 pa_tagstruct_putu32(reply
, idx
);
2773 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2776 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2777 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2780 pa_native_connection_assert_ref(c
);
2783 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2784 !pa_tagstruct_eof(t
)) {
2789 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2790 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2792 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
2793 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2797 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2800 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
2803 pa_assert(original
);
2807 if (c
->version
< 12) {
2808 /* Before protocol version 12 we didn't support S32 samples,
2809 * so we need to lie about this to the client */
2811 if (fixed
->format
== PA_SAMPLE_S32LE
)
2812 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2813 if (fixed
->format
== PA_SAMPLE_S32BE
)
2814 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2817 if (c
->version
< 15) {
2818 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
2819 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2820 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
2821 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2825 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
2826 pa_sample_spec fixed_ss
;
2829 pa_sink_assert_ref(sink
);
2831 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
2835 PA_TAG_U32
, sink
->index
,
2836 PA_TAG_STRING
, sink
->name
,
2837 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2838 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2839 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
2840 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
2841 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
2842 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
2843 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
2844 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
2845 PA_TAG_USEC
, pa_sink_get_latency(sink
),
2846 PA_TAG_STRING
, sink
->driver
,
2847 PA_TAG_U32
, sink
->flags
,
2850 if (c
->version
>= 13) {
2851 pa_tagstruct_put_proplist(t
, sink
->proplist
);
2852 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
2855 if (c
->version
>= 15) {
2856 pa_tagstruct_put_volume(t
, sink
->base_volume
);
2857 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
2858 pa_log_error("Internal sink state is invalid.");
2859 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
2860 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
2861 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
2864 if (c
->version
>= 16) {
2865 pa_tagstruct_putu32(t
, sink
->ports
? pa_hashmap_size(sink
->ports
) : 0);
2871 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
2872 pa_tagstruct_puts(t
, p
->name
);
2873 pa_tagstruct_puts(t
, p
->description
);
2874 pa_tagstruct_putu32(t
, p
->priority
);
2878 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
2882 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
2883 pa_sample_spec fixed_ss
;
2886 pa_source_assert_ref(source
);
2888 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
2892 PA_TAG_U32
, source
->index
,
2893 PA_TAG_STRING
, source
->name
,
2894 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2895 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2896 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
2897 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
2898 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
2899 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
2900 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
2901 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
2902 PA_TAG_USEC
, pa_source_get_latency(source
),
2903 PA_TAG_STRING
, source
->driver
,
2904 PA_TAG_U32
, source
->flags
,
2907 if (c
->version
>= 13) {
2908 pa_tagstruct_put_proplist(t
, source
->proplist
);
2909 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
2912 if (c
->version
>= 15) {
2913 pa_tagstruct_put_volume(t
, source
->base_volume
);
2914 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
2915 pa_log_error("Internal source state is invalid.");
2916 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
2917 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
2918 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
2921 if (c
->version
>= 16) {
2923 pa_tagstruct_putu32(t
, source
->ports
? pa_hashmap_size(source
->ports
) : 0);
2925 if (source
->ports
) {
2929 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
2930 pa_tagstruct_puts(t
, p
->name
);
2931 pa_tagstruct_puts(t
, p
->description
);
2932 pa_tagstruct_putu32(t
, p
->priority
);
2936 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
2940 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
2944 pa_tagstruct_putu32(t
, client
->index
);
2945 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
2946 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
2947 pa_tagstruct_puts(t
, client
->driver
);
2949 if (c
->version
>= 13)
2950 pa_tagstruct_put_proplist(t
, client
->proplist
);
2953 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
2960 pa_tagstruct_putu32(t
, card
->index
);
2961 pa_tagstruct_puts(t
, card
->name
);
2962 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
2963 pa_tagstruct_puts(t
, card
->driver
);
2965 pa_tagstruct_putu32(t
, card
->profiles
? pa_hashmap_size(card
->profiles
) : 0);
2967 if (card
->profiles
) {
2968 while ((p
= pa_hashmap_iterate(card
->profiles
, &state
, NULL
))) {
2969 pa_tagstruct_puts(t
, p
->name
);
2970 pa_tagstruct_puts(t
, p
->description
);
2971 pa_tagstruct_putu32(t
, p
->n_sinks
);
2972 pa_tagstruct_putu32(t
, p
->n_sources
);
2973 pa_tagstruct_putu32(t
, p
->priority
);
2977 pa_tagstruct_puts(t
, card
->active_profile
? card
->active_profile
->name
: NULL
);
2978 pa_tagstruct_put_proplist(t
, card
->proplist
);
2981 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
2985 pa_tagstruct_putu32(t
, module
->index
);
2986 pa_tagstruct_puts(t
, module
->name
);
2987 pa_tagstruct_puts(t
, module
->argument
);
2988 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
2990 if (c
->version
< 15)
2991 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
2993 if (c
->version
>= 15)
2994 pa_tagstruct_put_proplist(t
, module
->proplist
);
2997 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
2998 pa_sample_spec fixed_ss
;
2999 pa_usec_t sink_latency
;
3003 pa_sink_input_assert_ref(s
);
3005 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3007 pa_tagstruct_putu32(t
, s
->index
);
3008 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3009 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3010 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3011 pa_tagstruct_putu32(t
, s
->sink
->index
);
3012 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3013 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3014 pa_tagstruct_put_cvolume(t
, pa_sink_input_get_volume(s
, &v
, TRUE
));
3015 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3016 pa_tagstruct_put_usec(t
, sink_latency
);
3017 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3018 pa_tagstruct_puts(t
, s
->driver
);
3019 if (c
->version
>= 11)
3020 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3021 if (c
->version
>= 13)
3022 pa_tagstruct_put_proplist(t
, s
->proplist
);
3025 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3026 pa_sample_spec fixed_ss
;
3027 pa_usec_t source_latency
;
3030 pa_source_output_assert_ref(s
);
3032 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3034 pa_tagstruct_putu32(t
, s
->index
);
3035 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3036 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3037 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3038 pa_tagstruct_putu32(t
, s
->source
->index
);
3039 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3040 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3041 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3042 pa_tagstruct_put_usec(t
, source_latency
);
3043 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3044 pa_tagstruct_puts(t
, s
->driver
);
3046 if (c
->version
>= 13)
3047 pa_tagstruct_put_proplist(t
, s
->proplist
);
3050 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3051 pa_sample_spec fixed_ss
;
3057 if (e
->memchunk
.memblock
)
3058 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3060 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3062 pa_tagstruct_putu32(t
, e
->index
);
3063 pa_tagstruct_puts(t
, e
->name
);
3065 if (e
->volume_is_set
)
3068 pa_cvolume_init(&v
);
3070 pa_tagstruct_put_cvolume(t
, &v
);
3071 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3072 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3073 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3074 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3075 pa_tagstruct_put_boolean(t
, e
->lazy
);
3076 pa_tagstruct_puts(t
, e
->filename
);
3078 if (c
->version
>= 13)
3079 pa_tagstruct_put_proplist(t
, e
->proplist
);
3082 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3083 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3085 pa_sink
*sink
= NULL
;
3086 pa_source
*source
= NULL
;
3087 pa_client
*client
= NULL
;
3088 pa_card
*card
= NULL
;
3089 pa_module
*module
= NULL
;
3090 pa_sink_input
*si
= NULL
;
3091 pa_source_output
*so
= NULL
;
3092 pa_scache_entry
*sce
= NULL
;
3093 const char *name
= NULL
;
3094 pa_tagstruct
*reply
;
3096 pa_native_connection_assert_ref(c
);
3099 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3100 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3101 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3102 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3103 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3104 pa_tagstruct_gets(t
, &name
) < 0) ||
3105 !pa_tagstruct_eof(t
)) {
3110 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3111 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3112 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3113 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3114 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3116 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3117 if (idx
!= PA_INVALID_INDEX
)
3118 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3120 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3121 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3122 if (idx
!= PA_INVALID_INDEX
)
3123 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3125 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3126 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3127 if (idx
!= PA_INVALID_INDEX
)
3128 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3130 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3131 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3132 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3133 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3134 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3135 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3136 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3137 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3138 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3140 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3141 if (idx
!= PA_INVALID_INDEX
)
3142 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3144 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3147 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3148 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3152 reply
= reply_new(tag
);
3154 sink_fill_tagstruct(c
, reply
, sink
);
3156 source_fill_tagstruct(c
, reply
, source
);
3158 client_fill_tagstruct(c
, reply
, client
);
3160 card_fill_tagstruct(c
, reply
, card
);
3162 module_fill_tagstruct(c
, reply
, module
);
3164 sink_input_fill_tagstruct(c
, reply
, si
);
3166 source_output_fill_tagstruct(c
, reply
, so
);
3168 scache_fill_tagstruct(c
, reply
, sce
);
3169 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3172 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3173 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3177 pa_tagstruct
*reply
;
3179 pa_native_connection_assert_ref(c
);
3182 if (!pa_tagstruct_eof(t
)) {
3187 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3189 reply
= reply_new(tag
);
3191 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3192 i
= c
->protocol
->core
->sinks
;
3193 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3194 i
= c
->protocol
->core
->sources
;
3195 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3196 i
= c
->protocol
->core
->clients
;
3197 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3198 i
= c
->protocol
->core
->cards
;
3199 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3200 i
= c
->protocol
->core
->modules
;
3201 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3202 i
= c
->protocol
->core
->sink_inputs
;
3203 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3204 i
= c
->protocol
->core
->source_outputs
;
3206 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3207 i
= c
->protocol
->core
->scache
;
3211 for (p
= pa_idxset_first(i
, &idx
); p
; p
= pa_idxset_next(i
, &idx
)) {
3212 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3213 sink_fill_tagstruct(c
, reply
, p
);
3214 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3215 source_fill_tagstruct(c
, reply
, p
);
3216 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3217 client_fill_tagstruct(c
, reply
, p
);
3218 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3219 card_fill_tagstruct(c
, reply
, p
);
3220 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3221 module_fill_tagstruct(c
, reply
, p
);
3222 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3223 sink_input_fill_tagstruct(c
, reply
, p
);
3224 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3225 source_output_fill_tagstruct(c
, reply
, p
);
3227 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3228 scache_fill_tagstruct(c
, reply
, p
);
3233 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3236 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3237 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3238 pa_tagstruct
*reply
;
3240 pa_source
*def_source
;
3241 pa_sample_spec fixed_ss
;
3244 pa_native_connection_assert_ref(c
);
3247 if (!pa_tagstruct_eof(t
)) {
3252 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3254 reply
= reply_new(tag
);
3255 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3256 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3258 u
= pa_get_user_name_malloc();
3259 pa_tagstruct_puts(reply
, u
);
3262 h
= pa_get_host_name_malloc();
3263 pa_tagstruct_puts(reply
, h
);
3266 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3267 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3269 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3270 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3271 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3272 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3274 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3276 if (c
->version
>= 15)
3277 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3279 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3282 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3284 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3286 pa_native_connection_assert_ref(c
);
3288 t
= pa_tagstruct_new(NULL
, 0);
3289 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3290 pa_tagstruct_putu32(t
, (uint32_t) -1);
3291 pa_tagstruct_putu32(t
, e
);
3292 pa_tagstruct_putu32(t
, idx
);
3293 pa_pstream_send_tagstruct(c
->pstream
, t
);
3296 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3297 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3298 pa_subscription_mask_t m
;
3300 pa_native_connection_assert_ref(c
);
3303 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3304 !pa_tagstruct_eof(t
)) {
3309 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3310 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3312 if (c
->subscription
)
3313 pa_subscription_free(c
->subscription
);
3316 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3317 pa_assert(c
->subscription
);
3319 c
->subscription
= NULL
;
3321 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3324 static void command_set_volume(
3331 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3334 pa_sink
*sink
= NULL
;
3335 pa_source
*source
= NULL
;
3336 pa_sink_input
*si
= NULL
;
3337 const char *name
= NULL
;
3338 const char *client_name
;
3340 pa_native_connection_assert_ref(c
);
3343 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3344 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3345 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3346 pa_tagstruct_get_cvolume(t
, &volume
) ||
3347 !pa_tagstruct_eof(t
)) {
3352 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3353 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3354 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3355 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3356 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3357 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3361 case PA_COMMAND_SET_SINK_VOLUME
:
3362 if (idx
!= PA_INVALID_INDEX
)
3363 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3365 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3368 case PA_COMMAND_SET_SOURCE_VOLUME
:
3369 if (idx
!= PA_INVALID_INDEX
)
3370 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3372 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3375 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3376 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3380 pa_assert_not_reached();
3383 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3385 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3388 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3389 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3390 } else if (source
) {
3391 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3392 pa_source_set_volume(source
, &volume
, TRUE
);
3394 pa_log_debug("Client %s changes volume of sink input %s.",
3396 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3397 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3400 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3403 static void command_set_mute(
3410 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3413 pa_sink
*sink
= NULL
;
3414 pa_source
*source
= NULL
;
3415 pa_sink_input
*si
= NULL
;
3416 const char *name
= NULL
, *client_name
;
3418 pa_native_connection_assert_ref(c
);
3421 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3422 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3423 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3424 pa_tagstruct_get_boolean(t
, &mute
) ||
3425 !pa_tagstruct_eof(t
)) {
3430 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3431 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3432 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3433 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3434 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3438 case PA_COMMAND_SET_SINK_MUTE
:
3440 if (idx
!= PA_INVALID_INDEX
)
3441 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3443 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3447 case PA_COMMAND_SET_SOURCE_MUTE
:
3448 if (idx
!= PA_INVALID_INDEX
)
3449 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3451 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3455 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3456 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3460 pa_assert_not_reached();
3463 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3465 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3468 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3469 pa_sink_set_mute(sink
, mute
, TRUE
);
3470 } else if (source
) {
3471 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3472 pa_source_set_mute(source
, mute
, TRUE
);
3474 pa_log_debug("Client %s changes mute of sink input %s.",
3476 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3477 pa_sink_input_set_mute(si
, mute
, TRUE
);
3480 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3483 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3484 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3489 pa_native_connection_assert_ref(c
);
3492 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3493 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3494 !pa_tagstruct_eof(t
)) {
3499 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3500 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3501 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3502 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3503 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3505 pa_sink_input_cork(s
->sink_input
, b
);
3508 s
->is_underrun
= TRUE
;
3510 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3513 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3514 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3518 pa_native_connection_assert_ref(c
);
3521 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3522 !pa_tagstruct_eof(t
)) {
3527 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3528 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3529 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3530 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3531 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3534 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3535 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3538 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3539 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3542 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3543 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3547 pa_assert_not_reached();
3550 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3553 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3554 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3559 pa_native_connection_assert_ref(c
);
3562 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3563 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3564 !pa_tagstruct_eof(t
)) {
3569 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3570 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3571 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3573 pa_source_output_cork(s
->source_output
, b
);
3574 pa_memblockq_prebuf_force(s
->memblockq
);
3575 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3578 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3579 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3583 pa_native_connection_assert_ref(c
);
3586 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3587 !pa_tagstruct_eof(t
)) {
3592 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3593 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3594 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3596 pa_memblockq_flush_read(s
->memblockq
);
3597 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3600 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3601 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3604 pa_tagstruct
*reply
;
3606 pa_native_connection_assert_ref(c
);
3609 memset(&a
, 0, sizeof(a
));
3611 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3616 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3618 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3620 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3622 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3623 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3624 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3626 if (pa_tagstruct_get(
3628 PA_TAG_U32
, &a
.maxlength
,
3629 PA_TAG_U32
, &a
.tlength
,
3630 PA_TAG_U32
, &a
.prebuf
,
3631 PA_TAG_U32
, &a
.minreq
,
3632 PA_TAG_INVALID
) < 0 ||
3633 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3634 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3635 !pa_tagstruct_eof(t
)) {
3640 s
->adjust_latency
= adjust_latency
;
3641 s
->early_requests
= early_requests
;
3644 fix_playback_buffer_attr(s
);
3645 pa_assert_se(pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
, NULL
, 0, NULL
) == 0);
3647 reply
= reply_new(tag
);
3648 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3649 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
3650 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
3651 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
3653 if (c
->version
>= 13)
3654 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
3658 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3659 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
3661 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3662 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3664 if (pa_tagstruct_get(
3666 PA_TAG_U32
, &a
.maxlength
,
3667 PA_TAG_U32
, &a
.fragsize
,
3668 PA_TAG_INVALID
) < 0 ||
3669 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3670 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3671 !pa_tagstruct_eof(t
)) {
3676 s
->adjust_latency
= adjust_latency
;
3677 s
->early_requests
= early_requests
;
3680 fix_record_buffer_attr_pre(s
);
3681 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
3682 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
3683 fix_record_buffer_attr_post(s
);
3685 reply
= reply_new(tag
);
3686 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3687 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
3689 if (c
->version
>= 13)
3690 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
3693 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3696 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3697 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3701 pa_native_connection_assert_ref(c
);
3704 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3705 pa_tagstruct_getu32(t
, &rate
) < 0 ||
3706 !pa_tagstruct_eof(t
)) {
3711 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3712 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
3714 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
3717 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3718 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3719 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3721 pa_sink_input_set_rate(s
->sink_input
, rate
);
3725 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
3727 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3728 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3730 pa_source_output_set_rate(s
->source_output
, rate
);
3733 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3736 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3737 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3742 pa_native_connection_assert_ref(c
);
3745 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3747 p
= pa_proplist_new();
3749 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
3751 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
3752 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3753 !pa_tagstruct_eof(t
)) {
3755 pa_proplist_free(p
);
3761 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3762 pa_tagstruct_getu32(t
, &mode
) < 0 ||
3763 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3764 !pa_tagstruct_eof(t
)) {
3766 pa_proplist_free(p
);
3771 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
3772 pa_proplist_free(p
);
3773 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
3776 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
3779 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3780 if (!s
|| !playback_stream_isinstance(s
)) {
3781 pa_proplist_free(p
);
3782 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3784 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
3786 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
3789 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
3790 pa_proplist_free(p
);
3791 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3793 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
3796 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
3798 pa_client_update_proplist(c
->client
, mode
, p
);
3801 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3802 pa_proplist_free(p
);
3805 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3806 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3808 unsigned changed
= 0;
3810 pa_strlist
*l
= NULL
;
3812 pa_native_connection_assert_ref(c
);
3815 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3817 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
3819 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3825 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3828 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3829 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3830 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3832 p
= s
->sink_input
->proplist
;
3834 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3837 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3838 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3840 p
= s
->source_output
->proplist
;
3842 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3844 p
= c
->client
->proplist
;
3850 if (pa_tagstruct_gets(t
, &k
) < 0) {
3859 l
= pa_strlist_prepend(l
, k
);
3862 if (!pa_tagstruct_eof(t
)) {
3871 l
= pa_strlist_pop(l
, &z
);
3876 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
3880 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3883 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3886 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3887 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
3889 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3892 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3893 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
3896 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3897 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
3902 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3903 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3906 pa_native_connection_assert_ref(c
);
3909 if (pa_tagstruct_gets(t
, &s
) < 0 ||
3910 !pa_tagstruct_eof(t
)) {
3915 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3916 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
3918 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
3921 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
3922 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
3924 pa_namereg_set_default_source(c
->protocol
->core
, source
);
3927 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
3929 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
3930 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3932 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
3935 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3938 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3939 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3943 pa_native_connection_assert_ref(c
);
3946 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3947 pa_tagstruct_gets(t
, &name
) < 0 ||
3948 !pa_tagstruct_eof(t
)) {
3953 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3954 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
3956 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
3959 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3960 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3961 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3963 pa_sink_input_set_name(s
->sink_input
, name
);
3967 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
3969 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3970 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3972 pa_source_output_set_name(s
->source_output
, name
);
3975 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3978 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3979 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3982 pa_native_connection_assert_ref(c
);
3985 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3986 !pa_tagstruct_eof(t
)) {
3991 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3993 if (command
== PA_COMMAND_KILL_CLIENT
) {
3996 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3997 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
3999 pa_native_connection_ref(c
);
4000 pa_client_kill(client
);
4002 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4005 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4006 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4008 pa_native_connection_ref(c
);
4009 pa_sink_input_kill(s
);
4011 pa_source_output
*s
;
4013 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4015 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4016 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4018 pa_native_connection_ref(c
);
4019 pa_source_output_kill(s
);
4022 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4023 pa_native_connection_unref(c
);
4026 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4027 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4029 const char *name
, *argument
;
4030 pa_tagstruct
*reply
;
4032 pa_native_connection_assert_ref(c
);
4035 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4036 pa_tagstruct_gets(t
, &argument
) < 0 ||
4037 !pa_tagstruct_eof(t
)) {
4042 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4043 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4044 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4046 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4047 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4051 reply
= reply_new(tag
);
4052 pa_tagstruct_putu32(reply
, m
->index
);
4053 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4056 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4057 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4061 pa_native_connection_assert_ref(c
);
4064 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4065 !pa_tagstruct_eof(t
)) {
4070 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4071 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4072 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4074 pa_module_unload_request(m
, FALSE
);
4075 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4078 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4079 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4080 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4081 const char *name_device
= NULL
;
4083 pa_native_connection_assert_ref(c
);
4086 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4087 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4088 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4089 !pa_tagstruct_eof(t
)) {
4094 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4095 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4097 CHECK_VALIDITY(c
->pstream
, !name_device
|| pa_namereg_is_valid_name(name_device
), tag
, PA_ERR_INVALID
);
4098 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4099 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4100 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4102 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4103 pa_sink_input
*si
= NULL
;
4104 pa_sink
*sink
= NULL
;
4106 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4108 if (idx_device
!= PA_INVALID_INDEX
)
4109 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4111 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4113 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4115 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4116 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4120 pa_source_output
*so
= NULL
;
4123 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4125 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4127 if (idx_device
!= PA_INVALID_INDEX
)
4128 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4130 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4132 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4134 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4135 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4140 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4143 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4144 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4145 uint32_t idx
= PA_INVALID_INDEX
;
4146 const char *name
= NULL
;
4149 pa_native_connection_assert_ref(c
);
4152 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4153 pa_tagstruct_gets(t
, &name
) < 0 ||
4154 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4155 !pa_tagstruct_eof(t
)) {
4160 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4161 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
) || *name
== 0, tag
, PA_ERR_INVALID
);
4162 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4163 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4164 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4166 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4168 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4170 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4172 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4173 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4177 pa_sink
*sink
= NULL
;
4179 if (idx
!= PA_INVALID_INDEX
)
4180 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4182 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4184 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4186 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4187 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4193 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4195 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4197 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4199 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4200 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4207 if (idx
!= PA_INVALID_INDEX
)
4208 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4210 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4212 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4214 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4215 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4221 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4224 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4225 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4226 uint32_t idx
= PA_INVALID_INDEX
;
4227 const char *name
= NULL
;
4229 pa_native_protocol_ext_cb_t cb
;
4231 pa_native_connection_assert_ref(c
);
4234 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4235 pa_tagstruct_gets(t
, &name
) < 0) {
4240 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4241 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4242 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4243 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4244 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4246 if (idx
!= PA_INVALID_INDEX
)
4247 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4249 for (m
= pa_idxset_first(c
->protocol
->core
->modules
, &idx
); m
; m
= pa_idxset_next(c
->protocol
->core
->modules
, &idx
))
4250 if (strcmp(name
, m
->name
) == 0)
4254 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4255 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4257 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4258 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4260 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4264 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4265 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4266 uint32_t idx
= PA_INVALID_INDEX
;
4267 const char *name
= NULL
, *profile
= NULL
;
4268 pa_card
*card
= NULL
;
4271 pa_native_connection_assert_ref(c
);
4274 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4275 pa_tagstruct_gets(t
, &name
) < 0 ||
4276 pa_tagstruct_gets(t
, &profile
) < 0 ||
4277 !pa_tagstruct_eof(t
)) {
4282 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4283 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4284 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4285 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4286 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4288 if (idx
!= PA_INVALID_INDEX
)
4289 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4291 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4293 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4295 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4296 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4300 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4303 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4304 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4305 uint32_t idx
= PA_INVALID_INDEX
;
4306 const char *name
= NULL
, *port
= NULL
;
4309 pa_native_connection_assert_ref(c
);
4312 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4313 pa_tagstruct_gets(t
, &name
) < 0 ||
4314 pa_tagstruct_gets(t
, &port
) < 0 ||
4315 !pa_tagstruct_eof(t
)) {
4320 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4321 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4322 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4323 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4324 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4326 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4329 if (idx
!= PA_INVALID_INDEX
)
4330 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4332 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4334 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4336 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4337 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4343 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4345 if (idx
!= PA_INVALID_INDEX
)
4346 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4348 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4350 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4352 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4353 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4358 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4361 /*** pstream callbacks ***/
4363 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4364 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4368 pa_native_connection_assert_ref(c
);
4370 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4371 pa_log("invalid packet.");
4372 native_connection_unlink(c
);
4376 static void pstream_memblock_callback(pa_pstream
*p
, uint32_t channel
, int64_t offset
, pa_seek_mode_t seek
, const pa_memchunk
*chunk
, void *userdata
) {
4377 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4378 output_stream
*stream
;
4382 pa_native_connection_assert_ref(c
);
4384 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4385 pa_log_debug("Client sent block for invalid stream.");
4390 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4392 if (playback_stream_isinstance(stream
)) {
4393 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4395 if (chunk
->memblock
) {
4396 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4397 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
, NULL
, NULL
);
4399 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4401 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
+chunk
->length
, NULL
, NULL
);
4404 upload_stream
*u
= UPLOAD_STREAM(stream
);
4407 if (!u
->memchunk
.memblock
) {
4408 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4409 u
->memchunk
= *chunk
;
4410 pa_memblock_ref(u
->memchunk
.memblock
);
4413 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4414 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4418 pa_assert(u
->memchunk
.memblock
);
4421 if (l
> chunk
->length
)
4426 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4428 if (chunk
->memblock
) {
4430 src
= pa_memblock_acquire(chunk
->memblock
);
4432 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4433 (uint8_t*) src
+ chunk
->index
, l
);
4435 pa_memblock_release(chunk
->memblock
);
4437 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4439 pa_memblock_release(u
->memchunk
.memblock
);
4441 u
->memchunk
.length
+= l
;
4447 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4448 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4451 pa_native_connection_assert_ref(c
);
4453 native_connection_unlink(c
);
4454 pa_log_info("Connection died.");
4457 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4458 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4461 pa_native_connection_assert_ref(c
);
4463 native_connection_send_memblock(c
);
4466 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4469 if (!(q
= pa_thread_mq_get()))
4470 pa_pstream_send_revoke(p
, block_id
);
4472 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4475 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4478 if (!(q
= pa_thread_mq_get()))
4479 pa_pstream_send_release(p
, block_id
);
4481 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4484 /*** client callbacks ***/
4486 static void client_kill_cb(pa_client
*c
) {
4489 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4490 pa_log_info("Connection killed.");
4493 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4495 pa_native_connection
*c
;
4498 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4499 pa_native_connection_assert_ref(c
);
4501 if (c
->version
< 15)
4504 t
= pa_tagstruct_new(NULL
, 0);
4505 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4506 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4507 pa_tagstruct_puts(t
, event
);
4508 pa_tagstruct_put_proplist(t
, pl
);
4509 pa_pstream_send_tagstruct(c
->pstream
, t
);
4512 /*** module entry points ***/
4514 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4515 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4518 pa_native_connection_assert_ref(c
);
4519 pa_assert(c
->auth_timeout_event
== e
);
4521 if (!c
->authorized
) {
4522 native_connection_unlink(c
);
4523 pa_log_info("Connection terminated due to authentication timeout.");
4527 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4528 pa_native_connection
*c
;
4531 pa_client_new_data data
;
4537 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4538 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4539 pa_iochannel_free(io
);
4543 pa_client_new_data_init(&data
);
4544 data
.module
= o
->module
;
4545 data
.driver
= __FILE__
;
4546 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4547 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4548 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4549 client
= pa_client_new(p
->core
, &data
);
4550 pa_client_new_data_done(&data
);
4555 c
= pa_msgobject_new(pa_native_connection
);
4556 c
->parent
.parent
.free
= native_connection_free
;
4557 c
->parent
.process_msg
= native_connection_process_msg
;
4559 c
->options
= pa_native_options_ref(o
);
4560 c
->authorized
= FALSE
;
4562 if (o
->auth_anonymous
) {
4563 pa_log_info("Client authenticated anonymously.");
4564 c
->authorized
= TRUE
;
4567 if (!c
->authorized
&&
4569 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4571 pa_log_info("Client authenticated by IP ACL.");
4572 c
->authorized
= TRUE
;
4576 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4578 c
->auth_timeout_event
= NULL
;
4580 c
->is_local
= pa_iochannel_socket_is_local(io
);
4584 c
->client
->kill
= client_kill_cb
;
4585 c
->client
->send_event
= client_send_event_cb
;
4586 c
->client
->userdata
= c
;
4588 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4589 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
4590 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
4591 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
4592 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
4593 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
4594 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
4596 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
4598 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
4599 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
4601 c
->rrobin_index
= PA_IDXSET_INVALID
;
4602 c
->subscription
= NULL
;
4604 pa_idxset_put(p
->connections
, c
, NULL
);
4607 if (pa_iochannel_creds_supported(io
))
4608 pa_iochannel_creds_enable(io
);
4611 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
4614 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
4615 pa_native_connection
*c
;
4621 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
4622 if (c
->options
->module
== m
)
4623 native_connection_unlink(c
);
4626 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
4627 pa_native_protocol
*p
;
4632 p
= pa_xnew(pa_native_protocol
, 1);
4635 p
->connections
= pa_idxset_new(NULL
, NULL
);
4639 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
4641 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4642 pa_hook_init(&p
->hooks
[h
], p
);
4644 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
4649 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
4650 pa_native_protocol
*p
;
4652 if ((p
= pa_shared_get(c
, "native-protocol")))
4653 return pa_native_protocol_ref(p
);
4655 return native_protocol_new(c
);
4658 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
4660 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4667 void pa_native_protocol_unref(pa_native_protocol
*p
) {
4668 pa_native_connection
*c
;
4672 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4674 if (PA_REFCNT_DEC(p
) > 0)
4677 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
4678 native_connection_unlink(c
);
4680 pa_idxset_free(p
->connections
, NULL
, NULL
);
4682 pa_strlist_free(p
->servers
);
4684 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4685 pa_hook_done(&p
->hooks
[h
]);
4687 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
4689 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
4694 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
4696 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4699 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
4701 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4704 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
4706 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4709 p
->servers
= pa_strlist_remove(p
->servers
, name
);
4711 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4714 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
4716 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4721 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
4723 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4728 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
4730 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4733 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
4735 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
4739 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
4741 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4744 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
4747 pa_native_options
* pa_native_options_new(void) {
4748 pa_native_options
*o
;
4750 o
= pa_xnew0(pa_native_options
, 1);
4756 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
4758 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4765 void pa_native_options_unref(pa_native_options
*o
) {
4767 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4769 if (PA_REFCNT_DEC(o
) > 0)
4772 pa_xfree(o
->auth_group
);
4775 pa_ip_acl_free(o
->auth_ip_acl
);
4778 pa_auth_cookie_unref(o
->auth_cookie
);
4783 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
4788 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4791 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
4792 pa_log("auth-anonymous= expects a boolean argument.");
4797 if (pa_modargs_get_value_boolean(ma
, "auth-group-enabled", &enabled
) < 0) {
4798 pa_log("auth-group-enabled= expects a boolean argument.");
4802 pa_xfree(o
->auth_group
);
4803 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
4807 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4810 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
4813 if (!(ipa
= pa_ip_acl_new(acl
))) {
4814 pa_log("Failed to parse IP ACL '%s'", acl
);
4819 pa_ip_acl_free(o
->auth_ip_acl
);
4821 o
->auth_ip_acl
= ipa
;
4825 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
4826 pa_log("auth-cookie-enabled= expects a boolean argument.");
4831 pa_auth_cookie_unref(o
->auth_cookie
);
4836 /* The new name for this is 'auth-cookie', for compat reasons
4837 * we check the old name too */
4838 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
4839 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
4840 cn
= PA_NATIVE_COOKIE_FILE
;
4842 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, PA_NATIVE_COOKIE_LENGTH
)))
4846 o
->auth_cookie
= NULL
;
4851 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
4852 pa_native_connection_assert_ref(c
);
4857 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
4858 pa_native_connection_assert_ref(c
);