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
;
631 pa_source_output_new_data data
;
638 pa_source_output_new_data_init(&data
);
640 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
641 data
.driver
= __FILE__
;
642 data
.module
= c
->options
->module
;
643 data
.client
= c
->client
;
644 data
.source
= source
;
645 data
.direct_on_input
= direct_on_input
;
646 pa_source_output_new_data_set_sample_spec(&data
, ss
);
647 pa_source_output_new_data_set_channel_map(&data
, map
);
649 data
.resample_method
= PA_RESAMPLER_PEAKS
;
652 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
654 pa_source_output_new_data_done(&data
);
659 s
= pa_msgobject_new(record_stream
);
660 s
->parent
.parent
.free
= record_stream_free
;
661 s
->parent
.process_msg
= record_stream_process_msg
;
663 s
->source_output
= source_output
;
664 s
->buffer_attr
= *attr
;
665 s
->adjust_latency
= adjust_latency
;
666 s
->early_requests
= early_requests
;
667 pa_atomic_store(&s
->on_the_fly
, 0);
669 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
670 s
->source_output
->push
= source_output_push_cb
;
671 s
->source_output
->kill
= source_output_kill_cb
;
672 s
->source_output
->get_latency
= source_output_get_latency_cb
;
673 s
->source_output
->moving
= source_output_moving_cb
;
674 s
->source_output
->suspend
= source_output_suspend_cb
;
675 s
->source_output
->send_event
= source_output_send_event_cb
;
676 s
->source_output
->userdata
= s
;
678 fix_record_buffer_attr_pre(s
);
680 s
->memblockq
= pa_memblockq_new(
682 s
->buffer_attr
.maxlength
,
684 pa_frame_size(&source_output
->sample_spec
),
690 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
691 fix_record_buffer_attr_post(s
);
693 *ss
= s
->source_output
->sample_spec
;
694 *map
= s
->source_output
->channel_map
;
696 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
698 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
699 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
700 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
701 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
703 pa_source_output_put(s
->source_output
);
707 /* Called from main context */
708 static void record_stream_send_killed(record_stream
*r
) {
710 record_stream_assert_ref(r
);
712 t
= pa_tagstruct_new(NULL
, 0);
713 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
714 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
715 pa_tagstruct_putu32(t
, r
->index
);
716 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
719 /* Called from main context */
720 static void playback_stream_unlink(playback_stream
*s
) {
727 pa_sink_input_unlink(s
->sink_input
);
728 pa_sink_input_unref(s
->sink_input
);
729 s
->sink_input
= NULL
;
732 if (s
->drain_request
)
733 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
735 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
736 s
->connection
= NULL
;
737 playback_stream_unref(s
);
740 /* Called from main context */
741 static void playback_stream_free(pa_object
* o
) {
742 playback_stream
*s
= PLAYBACK_STREAM(o
);
745 playback_stream_unlink(s
);
747 pa_memblockq_free(s
->memblockq
);
751 /* Called from main context */
752 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
753 playback_stream
*s
= PLAYBACK_STREAM(o
);
754 playback_stream_assert_ref(s
);
761 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
766 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
769 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
773 t
= pa_tagstruct_new(NULL
, 0);
774 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
775 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
776 pa_tagstruct_putu32(t
, s
->index
);
777 pa_tagstruct_putu32(t
, (uint32_t) l
);
778 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
780 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
784 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
787 /* pa_log("signalling underflow"); */
789 /* Report that we're empty */
790 t
= pa_tagstruct_new(NULL
, 0);
791 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
792 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
793 pa_tagstruct_putu32(t
, s
->index
);
794 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
798 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
801 /* Notify the user we're overflowed*/
802 t
= pa_tagstruct_new(NULL
, 0);
803 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
804 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
805 pa_tagstruct_putu32(t
, s
->index
);
806 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
810 case PLAYBACK_STREAM_MESSAGE_STARTED
:
812 if (s
->connection
->version
>= 13) {
815 /* Notify the user we started playback */
816 t
= pa_tagstruct_new(NULL
, 0);
817 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
818 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
819 pa_tagstruct_putu32(t
, s
->index
);
820 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
825 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
826 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
829 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
: {
832 s
->buffer_attr
.tlength
= (uint32_t) offset
;
834 t
= pa_tagstruct_new(NULL
, 0);
835 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
836 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
837 pa_tagstruct_putu32(t
, s
->index
);
838 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
839 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
840 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
841 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
842 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
843 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
852 /* Called from main context */
853 static void fix_playback_buffer_attr(playback_stream
*s
) {
854 size_t frame_size
, max_prebuf
;
855 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
859 /* This function will be called from the main thread, before as
860 * well as after the sink input has been activated using
861 * pa_sink_input_put()! That means it may not touch any
862 * ->thread_info data, such as the memblockq! */
864 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
866 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
867 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
868 if (s
->buffer_attr
.maxlength
<= 0)
869 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
871 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
872 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
873 if (s
->buffer_attr
.tlength
<= 0)
874 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
876 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
877 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
878 if (s
->buffer_attr
.minreq
<= 0)
879 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
881 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
882 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
884 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
885 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
887 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
888 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
889 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
891 if (s
->early_requests
) {
893 /* In early request mode we need to emulate the classic
894 * fragment-based playback model. We do this setting the sink
895 * latency to the fragment size. */
897 sink_usec
= minreq_usec
;
898 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
900 } else if (s
->adjust_latency
) {
902 /* So, the user asked us to adjust the latency of the stream
903 * buffer according to the what the sink can provide. The
904 * tlength passed in shall be the overall latency. Roughly
905 * half the latency will be spent on the hw buffer, the other
906 * half of it in the async buffer queue we maintain for each
907 * client. In between we'll have a safety space of size
908 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
909 * empty and needs to be filled, then our buffer must have
910 * enough data to fulfill this request immediatly and thus
911 * have at least the same tlength as the size of the hw
912 * buffer. It additionally needs space for 2 times minreq
913 * because if the buffer ran empty and a partial fillup
914 * happens immediately on the next iteration we need to be
915 * able to fulfill it and give the application also minreq
916 * time to fill it up again for the next request Makes 2 times
917 * minreq in plus.. */
919 if (tlength_usec
> minreq_usec
*2)
920 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
924 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
928 /* Ok, the user didn't ask us to adjust the latency, but we
929 * still need to make sure that the parameters from the user
932 if (tlength_usec
> minreq_usec
*2)
933 sink_usec
= (tlength_usec
- minreq_usec
*2);
937 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
940 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
942 if (s
->early_requests
) {
944 /* Ok, we didn't necessarily get what we were asking for, so
945 * let's tell the user */
947 minreq_usec
= s
->configured_sink_latency
;
949 } else if (s
->adjust_latency
) {
951 /* Ok, we didn't necessarily get what we were asking for, so
952 * let's subtract from what we asked for for the remaining
955 if (tlength_usec
>= s
->configured_sink_latency
)
956 tlength_usec
-= s
->configured_sink_latency
;
959 /* FIXME: This is actually larger than necessary, since not all of
960 * the sink latency is actually rewritable. */
961 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
962 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
964 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
965 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
966 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
968 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
969 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
970 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
972 if (s
->buffer_attr
.minreq
<= 0) {
973 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
974 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
977 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
978 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
980 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
982 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
983 s
->buffer_attr
.prebuf
> max_prebuf
)
984 s
->buffer_attr
.prebuf
= max_prebuf
;
987 /* Called from main context */
988 static playback_stream
* playback_stream_new(
989 pa_native_connection
*c
,
999 pa_sink_input_flags_t flags
,
1001 pa_bool_t adjust_latency
,
1002 pa_bool_t early_requests
,
1005 playback_stream
*s
, *ssync
;
1006 pa_sink_input
*sink_input
= NULL
;
1007 pa_memchunk silence
;
1009 int64_t start_index
;
1010 pa_sink_input_new_data data
;
1018 /* Find syncid group */
1019 for (ssync
= pa_idxset_first(c
->output_streams
, &idx
); ssync
; ssync
= pa_idxset_next(c
->output_streams
, &idx
)) {
1021 if (!playback_stream_isinstance(ssync
))
1024 if (ssync
->syncid
== syncid
)
1028 /* Synced streams must connect to the same sink */
1032 sink
= ssync
->sink_input
->sink
;
1033 else if (sink
!= ssync
->sink_input
->sink
) {
1034 *ret
= PA_ERR_INVALID
;
1039 pa_sink_input_new_data_init(&data
);
1041 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1042 data
.driver
= __FILE__
;
1043 data
.module
= c
->options
->module
;
1044 data
.client
= c
->client
;
1046 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1047 pa_sink_input_new_data_set_channel_map(&data
, map
);
1049 pa_sink_input_new_data_set_volume(&data
, volume
);
1051 pa_sink_input_new_data_set_muted(&data
, muted
);
1052 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1055 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1057 pa_sink_input_new_data_done(&data
);
1062 s
= pa_msgobject_new(playback_stream
);
1063 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1064 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1067 s
->sink_input
= sink_input
;
1068 s
->is_underrun
= TRUE
;
1069 s
->drain_request
= FALSE
;
1070 pa_atomic_store(&s
->missing
, 0);
1071 s
->buffer_attr
= *a
;
1072 s
->adjust_latency
= adjust_latency
;
1073 s
->early_requests
= early_requests
;
1075 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1076 s
->sink_input
->pop
= sink_input_pop_cb
;
1077 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1078 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1079 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1080 s
->sink_input
->kill
= sink_input_kill_cb
;
1081 s
->sink_input
->moving
= sink_input_moving_cb
;
1082 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1083 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1084 s
->sink_input
->userdata
= s
;
1086 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1088 fix_playback_buffer_attr(s
);
1090 pa_sink_input_get_silence(sink_input
, &silence
);
1091 s
->memblockq
= pa_memblockq_new(
1093 s
->buffer_attr
.maxlength
,
1094 s
->buffer_attr
.tlength
,
1095 pa_frame_size(&sink_input
->sample_spec
),
1096 s
->buffer_attr
.prebuf
,
1097 s
->buffer_attr
.minreq
,
1100 pa_memblock_unref(silence
.memblock
);
1102 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1104 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1106 *ss
= s
->sink_input
->sample_spec
;
1107 *map
= s
->sink_input
->channel_map
;
1109 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1111 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1112 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1113 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1114 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1115 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1117 pa_sink_input_put(s
->sink_input
);
1121 /* Called from IO context */
1122 static void playback_stream_request_bytes(playback_stream
*s
) {
1124 int previous_missing
;
1126 playback_stream_assert_ref(s
);
1128 m
= pa_memblockq_pop_missing(s
->memblockq
);
1130 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
1131 /* (unsigned long) m, */
1132 /* pa_memblockq_get_tlength(s->memblockq), */
1133 /* pa_memblockq_get_minreq(s->memblockq), */
1134 /* pa_memblockq_get_length(s->memblockq)); */
1139 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1141 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1142 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1144 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1145 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1146 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1149 /* Called from main context */
1150 static void playback_stream_send_killed(playback_stream
*p
) {
1152 playback_stream_assert_ref(p
);
1154 t
= pa_tagstruct_new(NULL
, 0);
1155 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1156 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1157 pa_tagstruct_putu32(t
, p
->index
);
1158 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1161 /* Called from main context */
1162 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1163 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1164 pa_native_connection_assert_ref(c
);
1171 case CONNECTION_MESSAGE_REVOKE
:
1172 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1175 case CONNECTION_MESSAGE_RELEASE
:
1176 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1183 /* Called from main context */
1184 static void native_connection_unlink(pa_native_connection
*c
) {
1193 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1196 pa_native_options_unref(c
->options
);
1198 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1199 record_stream_unlink(r
);
1201 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1202 if (playback_stream_isinstance(o
))
1203 playback_stream_unlink(PLAYBACK_STREAM(o
));
1205 upload_stream_unlink(UPLOAD_STREAM(o
));
1207 if (c
->subscription
)
1208 pa_subscription_free(c
->subscription
);
1211 pa_pstream_unlink(c
->pstream
);
1213 if (c
->auth_timeout_event
) {
1214 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1215 c
->auth_timeout_event
= NULL
;
1218 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1220 pa_native_connection_unref(c
);
1223 /* Called from main context */
1224 static void native_connection_free(pa_object
*o
) {
1225 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1229 native_connection_unlink(c
);
1231 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1232 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1234 pa_pdispatch_unref(c
->pdispatch
);
1235 pa_pstream_unref(c
->pstream
);
1236 pa_client_free(c
->client
);
1241 /* Called from main context */
1242 static void native_connection_send_memblock(pa_native_connection
*c
) {
1246 start
= PA_IDXSET_INVALID
;
1250 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1253 if (start
== PA_IDXSET_INVALID
)
1254 start
= c
->rrobin_index
;
1255 else if (start
== c
->rrobin_index
)
1258 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1259 pa_memchunk schunk
= chunk
;
1261 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1262 schunk
.length
= r
->buffer_attr
.fragsize
;
1264 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1266 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1267 pa_memblock_unref(schunk
.memblock
);
1274 /*** sink input callbacks ***/
1276 /* Called from thread context */
1277 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1278 playback_stream_assert_ref(s
);
1280 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1282 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1284 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1286 if (pa_memblockq_is_readable(s
->memblockq
)) {
1288 /* We just ended an underrun, let's ask the sink
1289 * for a complete rewind rewrite */
1291 pa_log_debug("Requesting rewind due to end of underrun.");
1292 pa_sink_input_request_rewind(s
->sink_input
,
1293 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1294 s
->sink_input
->thread_info
.underrun_for
),
1295 FALSE
, TRUE
, FALSE
);
1301 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1303 if (indexw
< indexr
) {
1304 /* OK, the sink already asked for this data, so
1305 * let's have it usk us again */
1307 pa_log_debug("Requesting rewind due to rewrite.");
1308 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1312 playback_stream_request_bytes(s
);
1315 /* Called from thread context */
1316 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1317 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1320 pa_sink_input_assert_ref(i
);
1321 s
= PLAYBACK_STREAM(i
->userdata
);
1322 playback_stream_assert_ref(s
);
1326 case SINK_INPUT_MESSAGE_SEEK
: {
1329 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1331 /* The client side is incapable of accounting correctly
1332 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1333 * able to deal with that. */
1335 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1337 handle_seek(s
, windex
);
1341 case SINK_INPUT_MESSAGE_POST_DATA
: {
1346 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1348 /* pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1350 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1352 if (pa_log_ratelimit())
1353 pa_log_warn("Failed to push data into queue");
1354 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1355 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1358 handle_seek(s
, windex
);
1360 /* pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1365 case SINK_INPUT_MESSAGE_DRAIN
:
1366 case SINK_INPUT_MESSAGE_FLUSH
:
1367 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1368 case SINK_INPUT_MESSAGE_TRIGGER
: {
1371 pa_sink_input
*isync
;
1372 void (*func
)(pa_memblockq
*bq
);
1375 case SINK_INPUT_MESSAGE_FLUSH
:
1376 func
= pa_memblockq_flush_write
;
1379 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1380 func
= pa_memblockq_prebuf_force
;
1383 case SINK_INPUT_MESSAGE_DRAIN
:
1384 case SINK_INPUT_MESSAGE_TRIGGER
:
1385 func
= pa_memblockq_prebuf_disable
;
1389 pa_assert_not_reached();
1392 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1394 handle_seek(s
, windex
);
1396 /* Do the same for all other members in the sync group */
1397 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1398 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1399 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1400 func(ssync
->memblockq
);
1401 handle_seek(ssync
, windex
);
1404 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1405 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1406 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1407 func(ssync
->memblockq
);
1408 handle_seek(ssync
, windex
);
1411 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1412 if (!pa_memblockq_is_readable(s
->memblockq
))
1413 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1415 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1416 s
->drain_request
= TRUE
;
1423 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1424 /* Atomically get a snapshot of all timing parameters... */
1425 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1426 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1427 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1428 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1429 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1430 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1434 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1437 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1439 pa_memblockq_prebuf_force(s
->memblockq
);
1441 handle_seek(s
, windex
);
1443 /* Fall through to the default handler */
1447 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1448 pa_usec_t
*r
= userdata
;
1450 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1452 /* Fall through, the default handler will add in the extra
1453 * latency added by the resampler */
1457 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1458 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1459 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1464 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1467 /* Called from thread context */
1468 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1471 pa_sink_input_assert_ref(i
);
1472 s
= PLAYBACK_STREAM(i
->userdata
);
1473 playback_stream_assert_ref(s
);
1476 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1478 if (pa_memblockq_is_readable(s
->memblockq
))
1479 s
->is_underrun
= FALSE
;
1481 if (!s
->is_underrun
)
1482 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
));
1484 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1485 s
->drain_request
= FALSE
;
1486 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
);
1487 } else if (!s
->is_underrun
)
1488 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, 0, NULL
, NULL
);
1490 s
->is_underrun
= TRUE
;
1492 playback_stream_request_bytes(s
);
1495 /* This call will not fail with prebuf=0, hence we check for
1496 underrun explicitly above */
1497 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1500 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1502 if (i
->thread_info
.underrun_for
> 0)
1503 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1505 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1506 playback_stream_request_bytes(s
);
1511 /* Called from thread context */
1512 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1515 pa_sink_input_assert_ref(i
);
1516 s
= PLAYBACK_STREAM(i
->userdata
);
1517 playback_stream_assert_ref(s
);
1519 /* If we are in an underrun, then we don't rewind */
1520 if (i
->thread_info
.underrun_for
> 0)
1523 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1526 /* Called from thread context */
1527 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1530 pa_sink_input_assert_ref(i
);
1531 s
= PLAYBACK_STREAM(i
->userdata
);
1532 playback_stream_assert_ref(s
);
1534 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1537 /* Called from thread context */
1538 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1540 size_t new_tlength
, old_tlength
;
1542 pa_sink_input_assert_ref(i
);
1543 s
= PLAYBACK_STREAM(i
->userdata
);
1544 playback_stream_assert_ref(s
);
1546 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1547 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1549 if (old_tlength
< new_tlength
) {
1550 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1551 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1552 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1554 if (new_tlength
== old_tlength
)
1555 pa_log_debug("Failed to increase tlength");
1557 pa_log_debug("Notifying client about increased tlength");
1558 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
);
1563 /* Called from main context */
1564 static void sink_input_kill_cb(pa_sink_input
*i
) {
1567 pa_sink_input_assert_ref(i
);
1568 s
= PLAYBACK_STREAM(i
->userdata
);
1569 playback_stream_assert_ref(s
);
1571 playback_stream_send_killed(s
);
1572 playback_stream_unlink(s
);
1575 /* Called from main context */
1576 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1580 pa_sink_input_assert_ref(i
);
1581 s
= PLAYBACK_STREAM(i
->userdata
);
1582 playback_stream_assert_ref(s
);
1584 if (s
->connection
->version
< 15)
1587 t
= pa_tagstruct_new(NULL
, 0);
1588 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1589 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1590 pa_tagstruct_putu32(t
, s
->index
);
1591 pa_tagstruct_puts(t
, event
);
1592 pa_tagstruct_put_proplist(t
, pl
);
1593 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1596 /* Called from main context */
1597 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1601 pa_sink_input_assert_ref(i
);
1602 s
= PLAYBACK_STREAM(i
->userdata
);
1603 playback_stream_assert_ref(s
);
1605 if (s
->connection
->version
< 12)
1608 t
= pa_tagstruct_new(NULL
, 0);
1609 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1610 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1611 pa_tagstruct_putu32(t
, s
->index
);
1612 pa_tagstruct_put_boolean(t
, suspend
);
1613 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1616 /* Called from main context */
1617 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1621 pa_sink_input_assert_ref(i
);
1622 s
= PLAYBACK_STREAM(i
->userdata
);
1623 playback_stream_assert_ref(s
);
1628 fix_playback_buffer_attr(s
);
1629 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1630 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1632 if (s
->connection
->version
< 12)
1635 t
= pa_tagstruct_new(NULL
, 0);
1636 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1637 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1638 pa_tagstruct_putu32(t
, s
->index
);
1639 pa_tagstruct_putu32(t
, dest
->index
);
1640 pa_tagstruct_puts(t
, dest
->name
);
1641 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1643 if (s
->connection
->version
>= 13) {
1644 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1645 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1646 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1647 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1648 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1651 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1654 /*** source_output callbacks ***/
1656 /* Called from thread context */
1657 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1658 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1661 pa_source_output_assert_ref(o
);
1662 s
= RECORD_STREAM(o
->userdata
);
1663 record_stream_assert_ref(s
);
1666 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1667 /* Atomically get a snapshot of all timing parameters... */
1668 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1669 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1670 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1674 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1677 /* Called from thread context */
1678 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1681 pa_source_output_assert_ref(o
);
1682 s
= RECORD_STREAM(o
->userdata
);
1683 record_stream_assert_ref(s
);
1686 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1687 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1690 static void source_output_kill_cb(pa_source_output
*o
) {
1693 pa_source_output_assert_ref(o
);
1694 s
= RECORD_STREAM(o
->userdata
);
1695 record_stream_assert_ref(s
);
1697 record_stream_send_killed(s
);
1698 record_stream_unlink(s
);
1701 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1704 pa_source_output_assert_ref(o
);
1705 s
= RECORD_STREAM(o
->userdata
);
1706 record_stream_assert_ref(s
);
1708 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1710 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1713 /* Called from main context */
1714 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1718 pa_source_output_assert_ref(o
);
1719 s
= RECORD_STREAM(o
->userdata
);
1720 record_stream_assert_ref(s
);
1722 if (s
->connection
->version
< 15)
1725 t
= pa_tagstruct_new(NULL
, 0);
1726 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1727 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1728 pa_tagstruct_putu32(t
, s
->index
);
1729 pa_tagstruct_puts(t
, event
);
1730 pa_tagstruct_put_proplist(t
, pl
);
1731 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1734 /* Called from main context */
1735 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1739 pa_source_output_assert_ref(o
);
1740 s
= RECORD_STREAM(o
->userdata
);
1741 record_stream_assert_ref(s
);
1743 if (s
->connection
->version
< 12)
1746 t
= pa_tagstruct_new(NULL
, 0);
1747 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1748 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1749 pa_tagstruct_putu32(t
, s
->index
);
1750 pa_tagstruct_put_boolean(t
, suspend
);
1751 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1754 /* Called from main context */
1755 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1759 pa_source_output_assert_ref(o
);
1760 s
= RECORD_STREAM(o
->userdata
);
1761 record_stream_assert_ref(s
);
1766 fix_record_buffer_attr_pre(s
);
1767 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1768 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1769 fix_record_buffer_attr_post(s
);
1771 if (s
->connection
->version
< 12)
1774 t
= pa_tagstruct_new(NULL
, 0);
1775 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1776 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1777 pa_tagstruct_putu32(t
, s
->index
);
1778 pa_tagstruct_putu32(t
, dest
->index
);
1779 pa_tagstruct_puts(t
, dest
->name
);
1780 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1782 if (s
->connection
->version
>= 13) {
1783 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1784 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1785 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1788 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1791 /*** pdispatch callbacks ***/
1793 static void protocol_error(pa_native_connection
*c
) {
1794 pa_log("protocol error, kicking client");
1795 native_connection_unlink(c
);
1798 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1799 if (!(expression)) { \
1800 pa_pstream_send_error((pstream), (tag), (error)); \
1805 static pa_tagstruct
*reply_new(uint32_t tag
) {
1806 pa_tagstruct
*reply
;
1808 reply
= pa_tagstruct_new(NULL
, 0);
1809 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1810 pa_tagstruct_putu32(reply
, tag
);
1814 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1815 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1817 uint32_t sink_index
, syncid
, missing
;
1818 pa_buffer_attr attr
;
1819 const char *name
= NULL
, *sink_name
;
1822 pa_tagstruct
*reply
;
1823 pa_sink
*sink
= NULL
;
1831 fix_channels
= FALSE
,
1833 variable_rate
= FALSE
,
1835 adjust_latency
= FALSE
,
1836 early_requests
= FALSE
,
1837 dont_inhibit_auto_suspend
= FALSE
,
1839 fail_on_suspend
= FALSE
;
1840 pa_sink_input_flags_t flags
= 0;
1842 pa_bool_t volume_set
= TRUE
;
1843 int ret
= PA_ERR_INVALID
;
1845 pa_native_connection_assert_ref(c
);
1847 memset(&attr
, 0, sizeof(attr
));
1849 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1852 PA_TAG_SAMPLE_SPEC
, &ss
,
1853 PA_TAG_CHANNEL_MAP
, &map
,
1854 PA_TAG_U32
, &sink_index
,
1855 PA_TAG_STRING
, &sink_name
,
1856 PA_TAG_U32
, &attr
.maxlength
,
1857 PA_TAG_BOOLEAN
, &corked
,
1858 PA_TAG_U32
, &attr
.tlength
,
1859 PA_TAG_U32
, &attr
.prebuf
,
1860 PA_TAG_U32
, &attr
.minreq
,
1861 PA_TAG_U32
, &syncid
,
1862 PA_TAG_CVOLUME
, &volume
,
1863 PA_TAG_INVALID
) < 0) {
1869 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
1870 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
1871 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
1872 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
1873 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
1874 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
1875 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
1876 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
1878 p
= pa_proplist_new();
1881 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1883 if (c
->version
>= 12) {
1884 /* Since 0.9.8 the user can ask for a couple of additional flags */
1886 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
1887 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
1888 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
1889 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
1890 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
1891 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
1892 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
1895 pa_proplist_free(p
);
1900 if (c
->version
>= 13) {
1902 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
1903 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
1904 pa_tagstruct_get_proplist(t
, p
) < 0) {
1906 pa_proplist_free(p
);
1911 if (c
->version
>= 14) {
1913 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
1914 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
1916 pa_proplist_free(p
);
1921 if (c
->version
>= 15) {
1923 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
1924 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
1925 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
1927 pa_proplist_free(p
);
1932 if (!pa_tagstruct_eof(t
)) {
1934 pa_proplist_free(p
);
1938 if (sink_index
!= PA_INVALID_INDEX
) {
1940 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
1941 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1942 pa_proplist_free(p
);
1946 } else if (sink_name
) {
1948 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
1949 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1950 pa_proplist_free(p
);
1956 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
1957 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
1958 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
1959 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
1960 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
1961 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
1962 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
1963 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
1964 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
1965 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0);
1967 /* Only since protocol version 15 there's a seperate muted_set
1968 * flag. For older versions we synthesize it here */
1969 muted_set
= muted_set
|| muted
;
1971 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
);
1972 pa_proplist_free(p
);
1974 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
1976 reply
= reply_new(tag
);
1977 pa_tagstruct_putu32(reply
, s
->index
);
1978 pa_assert(s
->sink_input
);
1979 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
1980 pa_tagstruct_putu32(reply
, missing
);
1982 /* pa_log("initial request is %u", missing); */
1984 if (c
->version
>= 9) {
1985 /* Since 0.9.0 we support sending the buffer metrics back to the client */
1987 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
1988 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
1989 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
1990 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
1993 if (c
->version
>= 12) {
1994 /* Since 0.9.8 we support sending the chosen sample
1995 * spec/channel map/device/suspend status back to the
1998 pa_tagstruct_put_sample_spec(reply
, &ss
);
1999 pa_tagstruct_put_channel_map(reply
, &map
);
2001 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2002 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2004 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2007 if (c
->version
>= 13)
2008 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2010 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2013 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2014 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2017 pa_native_connection_assert_ref(c
);
2020 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2021 !pa_tagstruct_eof(t
)) {
2026 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2030 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2032 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2033 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2037 playback_stream_unlink(s
);
2041 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2043 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2044 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2048 record_stream_unlink(s
);
2052 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2055 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2056 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2060 upload_stream_unlink(s
);
2065 pa_assert_not_reached();
2068 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2071 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2072 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2074 pa_buffer_attr attr
;
2075 uint32_t source_index
;
2076 const char *name
= NULL
, *source_name
;
2079 pa_tagstruct
*reply
;
2080 pa_source
*source
= NULL
;
2087 fix_channels
= FALSE
,
2089 variable_rate
= FALSE
,
2090 adjust_latency
= FALSE
,
2091 peak_detect
= FALSE
,
2092 early_requests
= FALSE
,
2093 dont_inhibit_auto_suspend
= FALSE
,
2094 fail_on_suspend
= FALSE
;
2095 pa_source_output_flags_t flags
= 0;
2097 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2098 pa_sink_input
*direct_on_input
= NULL
;
2099 int ret
= PA_ERR_INVALID
;
2101 pa_native_connection_assert_ref(c
);
2104 memset(&attr
, 0, sizeof(attr
));
2106 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2107 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2108 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2109 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2110 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2111 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2112 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2113 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2118 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2119 CHECK_VALIDITY(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
2120 CHECK_VALIDITY(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
);
2121 CHECK_VALIDITY(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2122 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2123 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2124 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2126 p
= pa_proplist_new();
2129 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2131 if (c
->version
>= 12) {
2132 /* Since 0.9.8 the user can ask for a couple of additional flags */
2134 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2135 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2136 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2137 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2138 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2139 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2140 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2143 pa_proplist_free(p
);
2148 if (c
->version
>= 13) {
2150 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2151 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2152 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2153 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2155 pa_proplist_free(p
);
2160 if (c
->version
>= 14) {
2162 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2164 pa_proplist_free(p
);
2169 if (c
->version
>= 15) {
2171 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2172 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2174 pa_proplist_free(p
);
2179 if (!pa_tagstruct_eof(t
)) {
2181 pa_proplist_free(p
);
2185 if (source_index
!= PA_INVALID_INDEX
) {
2187 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2188 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2189 pa_proplist_free(p
);
2193 } else if (source_name
) {
2195 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2196 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2197 pa_proplist_free(p
);
2202 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2204 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2205 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2206 pa_proplist_free(p
);
2212 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2213 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2214 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2215 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2216 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2217 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2218 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2219 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2220 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2221 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0);
2223 s
= record_stream_new(c
, source
, &ss
, &map
, peak_detect
, &attr
, flags
, p
, adjust_latency
, direct_on_input
, early_requests
, &ret
);
2224 pa_proplist_free(p
);
2226 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
2228 reply
= reply_new(tag
);
2229 pa_tagstruct_putu32(reply
, s
->index
);
2230 pa_assert(s
->source_output
);
2231 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2233 if (c
->version
>= 9) {
2234 /* Since 0.9 we support sending the buffer metrics back to the client */
2236 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2237 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2240 if (c
->version
>= 12) {
2241 /* Since 0.9.8 we support sending the chosen sample
2242 * spec/channel map/device/suspend status back to the
2245 pa_tagstruct_put_sample_spec(reply
, &ss
);
2246 pa_tagstruct_put_channel_map(reply
, &map
);
2248 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2249 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2251 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2254 if (c
->version
>= 13)
2255 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2257 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2260 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2261 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2264 pa_native_connection_assert_ref(c
);
2267 if (!pa_tagstruct_eof(t
)) {
2272 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2273 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2274 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2276 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2279 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2280 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2282 pa_tagstruct
*reply
;
2283 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2285 pa_native_connection_assert_ref(c
);
2288 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2289 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2290 !pa_tagstruct_eof(t
)) {
2295 /* Minimum supported version */
2296 if (c
->version
< 8) {
2297 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2301 /* Starting with protocol version 13 the MSB of the version tag
2302 reflects if shm is available for this pa_native_connection or
2304 if (c
->version
>= 13) {
2305 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2306 c
->version
&= 0x7FFFFFFFU
;
2309 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2311 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2313 if (!c
->authorized
) {
2314 pa_bool_t success
= FALSE
;
2317 const pa_creds
*creds
;
2319 if ((creds
= pa_pdispatch_creds(pd
))) {
2320 if (creds
->uid
== getuid())
2322 else if (c
->options
->auth_group
) {
2326 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2327 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2328 else if (gid
== creds
->gid
)
2332 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2333 pa_log_warn("Failed to check group membership.");
2339 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2340 (unsigned long) creds
->uid
,
2341 (unsigned long) creds
->gid
,
2346 if (!success
&& c
->options
->auth_cookie
) {
2349 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2350 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2355 pa_log_warn("Denied access to client with invalid authorization data.");
2356 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2360 c
->authorized
= TRUE
;
2361 if (c
->auth_timeout_event
) {
2362 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2363 c
->auth_timeout_event
= NULL
;
2367 /* Enable shared memory support if possible */
2369 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2372 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2375 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2380 /* Only enable SHM if both sides are owned by the same
2381 * user. This is a security measure because otherwise data
2382 * private to the user might leak. */
2384 const pa_creds
*creds
;
2385 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2390 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2391 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2393 reply
= reply_new(tag
);
2394 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2398 /* SHM support is only enabled after both sides made sure they are the same user. */
2402 ucred
.uid
= getuid();
2403 ucred
.gid
= getgid();
2405 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2408 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2412 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2413 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2414 const char *name
= NULL
;
2416 pa_tagstruct
*reply
;
2418 pa_native_connection_assert_ref(c
);
2421 p
= pa_proplist_new();
2423 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2424 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2425 !pa_tagstruct_eof(t
)) {
2428 pa_proplist_free(p
);
2433 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2434 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2435 pa_proplist_free(p
);
2439 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2440 pa_proplist_free(p
);
2442 reply
= reply_new(tag
);
2444 if (c
->version
>= 13)
2445 pa_tagstruct_putu32(reply
, c
->client
->index
);
2447 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2450 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2451 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2453 uint32_t idx
= PA_IDXSET_INVALID
;
2455 pa_native_connection_assert_ref(c
);
2458 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2459 !pa_tagstruct_eof(t
)) {
2464 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2465 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_LOOKUP_SINK
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
2467 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2469 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2473 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2474 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2475 idx
= source
->index
;
2478 if (idx
== PA_IDXSET_INVALID
)
2479 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2481 pa_tagstruct
*reply
;
2482 reply
= reply_new(tag
);
2483 pa_tagstruct_putu32(reply
, idx
);
2484 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2488 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2489 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2493 pa_native_connection_assert_ref(c
);
2496 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2497 !pa_tagstruct_eof(t
)) {
2502 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2503 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2504 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2505 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2507 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
);
2510 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2511 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2512 pa_tagstruct
*reply
;
2513 const pa_mempool_stat
*stat
;
2515 pa_native_connection_assert_ref(c
);
2518 if (!pa_tagstruct_eof(t
)) {
2523 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2525 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2527 reply
= reply_new(tag
);
2528 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2529 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2530 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2531 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2532 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2533 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2536 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2537 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2538 pa_tagstruct
*reply
;
2540 struct timeval tv
, now
;
2543 pa_native_connection_assert_ref(c
);
2546 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2547 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2548 !pa_tagstruct_eof(t
)) {
2553 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2554 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2555 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2556 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2558 /* Get an atomic snapshot of all timing parameters */
2559 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);
2561 reply
= reply_new(tag
);
2562 pa_tagstruct_put_usec(reply
,
2563 s
->current_sink_latency
+
2564 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2565 pa_tagstruct_put_usec(reply
, 0);
2566 pa_tagstruct_put_boolean(reply
,
2567 s
->playing_for
> 0 &&
2568 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2569 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2570 pa_tagstruct_put_timeval(reply
, &tv
);
2571 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2572 pa_tagstruct_puts64(reply
, s
->write_index
);
2573 pa_tagstruct_puts64(reply
, s
->read_index
);
2575 if (c
->version
>= 13) {
2576 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2577 pa_tagstruct_putu64(reply
, s
->playing_for
);
2580 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2583 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2584 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2585 pa_tagstruct
*reply
;
2587 struct timeval tv
, now
;
2590 pa_native_connection_assert_ref(c
);
2593 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2594 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2595 !pa_tagstruct_eof(t
)) {
2600 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2601 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2602 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2604 /* Get an atomic snapshot of all timing parameters */
2605 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);
2607 reply
= reply_new(tag
);
2608 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2609 pa_tagstruct_put_usec(reply
,
2610 s
->current_source_latency
+
2611 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->sample_spec
));
2612 pa_tagstruct_put_boolean(reply
,
2613 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2614 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2615 pa_tagstruct_put_timeval(reply
, &tv
);
2616 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2617 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2618 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2619 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2622 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2623 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2626 const char *name
= NULL
;
2629 pa_tagstruct
*reply
;
2632 pa_native_connection_assert_ref(c
);
2635 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2636 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2637 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2638 pa_tagstruct_getu32(t
, &length
) < 0) {
2643 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2644 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2645 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2646 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2647 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2648 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2650 p
= pa_proplist_new();
2652 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2653 !pa_tagstruct_eof(t
)) {
2656 pa_proplist_free(p
);
2660 if (c
->version
< 13)
2661 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2663 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2664 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2666 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2667 pa_proplist_free(p
);
2668 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2671 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2672 pa_proplist_free(p
);
2674 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2676 reply
= reply_new(tag
);
2677 pa_tagstruct_putu32(reply
, s
->index
);
2678 pa_tagstruct_putu32(reply
, length
);
2679 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2682 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2683 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2688 pa_native_connection_assert_ref(c
);
2691 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2692 !pa_tagstruct_eof(t
)) {
2697 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2699 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2700 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2701 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2703 if (!s
->memchunk
.memblock
)
2704 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2705 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2706 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2708 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2710 upload_stream_unlink(s
);
2713 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2714 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2715 uint32_t sink_index
;
2718 const char *name
, *sink_name
;
2721 pa_tagstruct
*reply
;
2723 pa_native_connection_assert_ref(c
);
2726 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2728 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2729 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2730 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2731 pa_tagstruct_gets(t
, &name
) < 0) {
2736 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
2737 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2738 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2739 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2741 if (sink_index
!= PA_INVALID_INDEX
)
2742 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
2744 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
2746 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
2748 p
= pa_proplist_new();
2750 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2751 !pa_tagstruct_eof(t
)) {
2753 pa_proplist_free(p
);
2757 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
2759 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
2760 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2761 pa_proplist_free(p
);
2765 pa_proplist_free(p
);
2767 reply
= reply_new(tag
);
2769 if (c
->version
>= 13)
2770 pa_tagstruct_putu32(reply
, idx
);
2772 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2775 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2776 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2779 pa_native_connection_assert_ref(c
);
2782 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2783 !pa_tagstruct_eof(t
)) {
2788 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2789 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2791 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
2792 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2796 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2799 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
2802 pa_assert(original
);
2806 if (c
->version
< 12) {
2807 /* Before protocol version 12 we didn't support S32 samples,
2808 * so we need to lie about this to the client */
2810 if (fixed
->format
== PA_SAMPLE_S32LE
)
2811 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2812 if (fixed
->format
== PA_SAMPLE_S32BE
)
2813 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2816 if (c
->version
< 15) {
2817 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
2818 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2819 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
2820 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2824 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
2825 pa_sample_spec fixed_ss
;
2828 pa_sink_assert_ref(sink
);
2830 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
2834 PA_TAG_U32
, sink
->index
,
2835 PA_TAG_STRING
, sink
->name
,
2836 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2837 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2838 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
2839 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
2840 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
2841 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
2842 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
2843 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
2844 PA_TAG_USEC
, pa_sink_get_latency(sink
),
2845 PA_TAG_STRING
, sink
->driver
,
2846 PA_TAG_U32
, sink
->flags
,
2849 if (c
->version
>= 13) {
2850 pa_tagstruct_put_proplist(t
, sink
->proplist
);
2851 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
2854 if (c
->version
>= 15) {
2855 pa_tagstruct_put_volume(t
, sink
->base_volume
);
2856 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
2857 pa_log_error("Internal sink state is invalid.");
2858 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
2859 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
2860 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
2863 if (c
->version
>= 16) {
2864 pa_tagstruct_putu32(t
, sink
->ports
? pa_hashmap_size(sink
->ports
) : 0);
2870 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
2871 pa_tagstruct_puts(t
, p
->name
);
2872 pa_tagstruct_puts(t
, p
->description
);
2873 pa_tagstruct_putu32(t
, p
->priority
);
2877 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
2881 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
2882 pa_sample_spec fixed_ss
;
2885 pa_source_assert_ref(source
);
2887 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
2891 PA_TAG_U32
, source
->index
,
2892 PA_TAG_STRING
, source
->name
,
2893 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2894 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2895 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
2896 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
2897 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
2898 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
2899 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
2900 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
2901 PA_TAG_USEC
, pa_source_get_latency(source
),
2902 PA_TAG_STRING
, source
->driver
,
2903 PA_TAG_U32
, source
->flags
,
2906 if (c
->version
>= 13) {
2907 pa_tagstruct_put_proplist(t
, source
->proplist
);
2908 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
2911 if (c
->version
>= 15) {
2912 pa_tagstruct_put_volume(t
, source
->base_volume
);
2913 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
2914 pa_log_error("Internal source state is invalid.");
2915 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
2916 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
2917 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
2920 if (c
->version
>= 16) {
2922 pa_tagstruct_putu32(t
, source
->ports
? pa_hashmap_size(source
->ports
) : 0);
2924 if (source
->ports
) {
2928 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
2929 pa_tagstruct_puts(t
, p
->name
);
2930 pa_tagstruct_puts(t
, p
->description
);
2931 pa_tagstruct_putu32(t
, p
->priority
);
2935 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
2939 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
2943 pa_tagstruct_putu32(t
, client
->index
);
2944 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
2945 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
2946 pa_tagstruct_puts(t
, client
->driver
);
2948 if (c
->version
>= 13)
2949 pa_tagstruct_put_proplist(t
, client
->proplist
);
2952 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
2959 pa_tagstruct_putu32(t
, card
->index
);
2960 pa_tagstruct_puts(t
, card
->name
);
2961 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
2962 pa_tagstruct_puts(t
, card
->driver
);
2964 pa_tagstruct_putu32(t
, card
->profiles
? pa_hashmap_size(card
->profiles
) : 0);
2966 if (card
->profiles
) {
2967 while ((p
= pa_hashmap_iterate(card
->profiles
, &state
, NULL
))) {
2968 pa_tagstruct_puts(t
, p
->name
);
2969 pa_tagstruct_puts(t
, p
->description
);
2970 pa_tagstruct_putu32(t
, p
->n_sinks
);
2971 pa_tagstruct_putu32(t
, p
->n_sources
);
2972 pa_tagstruct_putu32(t
, p
->priority
);
2976 pa_tagstruct_puts(t
, card
->active_profile
? card
->active_profile
->name
: NULL
);
2977 pa_tagstruct_put_proplist(t
, card
->proplist
);
2980 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
2984 pa_tagstruct_putu32(t
, module
->index
);
2985 pa_tagstruct_puts(t
, module
->name
);
2986 pa_tagstruct_puts(t
, module
->argument
);
2987 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
2989 if (c
->version
< 15)
2990 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
2992 if (c
->version
>= 15)
2993 pa_tagstruct_put_proplist(t
, module
->proplist
);
2996 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
2997 pa_sample_spec fixed_ss
;
2998 pa_usec_t sink_latency
;
3002 pa_sink_input_assert_ref(s
);
3004 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3006 pa_tagstruct_putu32(t
, s
->index
);
3007 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3008 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3009 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3010 pa_tagstruct_putu32(t
, s
->sink
->index
);
3011 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3012 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3013 pa_tagstruct_put_cvolume(t
, pa_sink_input_get_volume(s
, &v
, TRUE
));
3014 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3015 pa_tagstruct_put_usec(t
, sink_latency
);
3016 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3017 pa_tagstruct_puts(t
, s
->driver
);
3018 if (c
->version
>= 11)
3019 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3020 if (c
->version
>= 13)
3021 pa_tagstruct_put_proplist(t
, s
->proplist
);
3024 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3025 pa_sample_spec fixed_ss
;
3026 pa_usec_t source_latency
;
3029 pa_source_output_assert_ref(s
);
3031 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3033 pa_tagstruct_putu32(t
, s
->index
);
3034 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3035 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3036 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3037 pa_tagstruct_putu32(t
, s
->source
->index
);
3038 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3039 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3040 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3041 pa_tagstruct_put_usec(t
, source_latency
);
3042 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3043 pa_tagstruct_puts(t
, s
->driver
);
3045 if (c
->version
>= 13)
3046 pa_tagstruct_put_proplist(t
, s
->proplist
);
3049 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3050 pa_sample_spec fixed_ss
;
3056 if (e
->memchunk
.memblock
)
3057 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3059 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3061 pa_tagstruct_putu32(t
, e
->index
);
3062 pa_tagstruct_puts(t
, e
->name
);
3064 if (e
->volume_is_set
)
3067 pa_cvolume_init(&v
);
3069 pa_tagstruct_put_cvolume(t
, &v
);
3070 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3071 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3072 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3073 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3074 pa_tagstruct_put_boolean(t
, e
->lazy
);
3075 pa_tagstruct_puts(t
, e
->filename
);
3077 if (c
->version
>= 13)
3078 pa_tagstruct_put_proplist(t
, e
->proplist
);
3081 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3082 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3084 pa_sink
*sink
= NULL
;
3085 pa_source
*source
= NULL
;
3086 pa_client
*client
= NULL
;
3087 pa_card
*card
= NULL
;
3088 pa_module
*module
= NULL
;
3089 pa_sink_input
*si
= NULL
;
3090 pa_source_output
*so
= NULL
;
3091 pa_scache_entry
*sce
= NULL
;
3092 const char *name
= NULL
;
3093 pa_tagstruct
*reply
;
3095 pa_native_connection_assert_ref(c
);
3098 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3099 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3100 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3101 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3102 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3103 pa_tagstruct_gets(t
, &name
) < 0) ||
3104 !pa_tagstruct_eof(t
)) {
3109 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3110 CHECK_VALIDITY(c
->pstream
, !name
||
3111 (command
== PA_COMMAND_GET_SINK_INFO
&&
3112 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3113 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3114 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3115 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3116 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3117 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3118 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3120 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3121 if (idx
!= PA_INVALID_INDEX
)
3122 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3124 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3125 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3126 if (idx
!= PA_INVALID_INDEX
)
3127 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3129 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3130 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3131 if (idx
!= PA_INVALID_INDEX
)
3132 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3134 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3135 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3136 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3137 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3138 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3139 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3140 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3141 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3142 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3144 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3145 if (idx
!= PA_INVALID_INDEX
)
3146 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3148 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3151 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3152 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3156 reply
= reply_new(tag
);
3158 sink_fill_tagstruct(c
, reply
, sink
);
3160 source_fill_tagstruct(c
, reply
, source
);
3162 client_fill_tagstruct(c
, reply
, client
);
3164 card_fill_tagstruct(c
, reply
, card
);
3166 module_fill_tagstruct(c
, reply
, module
);
3168 sink_input_fill_tagstruct(c
, reply
, si
);
3170 source_output_fill_tagstruct(c
, reply
, so
);
3172 scache_fill_tagstruct(c
, reply
, sce
);
3173 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3176 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3177 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3181 pa_tagstruct
*reply
;
3183 pa_native_connection_assert_ref(c
);
3186 if (!pa_tagstruct_eof(t
)) {
3191 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3193 reply
= reply_new(tag
);
3195 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3196 i
= c
->protocol
->core
->sinks
;
3197 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3198 i
= c
->protocol
->core
->sources
;
3199 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3200 i
= c
->protocol
->core
->clients
;
3201 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3202 i
= c
->protocol
->core
->cards
;
3203 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3204 i
= c
->protocol
->core
->modules
;
3205 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3206 i
= c
->protocol
->core
->sink_inputs
;
3207 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3208 i
= c
->protocol
->core
->source_outputs
;
3210 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3211 i
= c
->protocol
->core
->scache
;
3215 for (p
= pa_idxset_first(i
, &idx
); p
; p
= pa_idxset_next(i
, &idx
)) {
3216 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3217 sink_fill_tagstruct(c
, reply
, p
);
3218 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3219 source_fill_tagstruct(c
, reply
, p
);
3220 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3221 client_fill_tagstruct(c
, reply
, p
);
3222 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3223 card_fill_tagstruct(c
, reply
, p
);
3224 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3225 module_fill_tagstruct(c
, reply
, p
);
3226 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3227 sink_input_fill_tagstruct(c
, reply
, p
);
3228 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3229 source_output_fill_tagstruct(c
, reply
, p
);
3231 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3232 scache_fill_tagstruct(c
, reply
, p
);
3237 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3240 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3241 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3242 pa_tagstruct
*reply
;
3244 pa_source
*def_source
;
3245 pa_sample_spec fixed_ss
;
3248 pa_native_connection_assert_ref(c
);
3251 if (!pa_tagstruct_eof(t
)) {
3256 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3258 reply
= reply_new(tag
);
3259 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3260 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3262 u
= pa_get_user_name_malloc();
3263 pa_tagstruct_puts(reply
, u
);
3266 h
= pa_get_host_name_malloc();
3267 pa_tagstruct_puts(reply
, h
);
3270 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3271 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3273 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3274 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3275 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3276 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3278 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3280 if (c
->version
>= 15)
3281 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3283 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3286 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3288 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3290 pa_native_connection_assert_ref(c
);
3292 t
= pa_tagstruct_new(NULL
, 0);
3293 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3294 pa_tagstruct_putu32(t
, (uint32_t) -1);
3295 pa_tagstruct_putu32(t
, e
);
3296 pa_tagstruct_putu32(t
, idx
);
3297 pa_pstream_send_tagstruct(c
->pstream
, t
);
3300 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3301 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3302 pa_subscription_mask_t m
;
3304 pa_native_connection_assert_ref(c
);
3307 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3308 !pa_tagstruct_eof(t
)) {
3313 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3314 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3316 if (c
->subscription
)
3317 pa_subscription_free(c
->subscription
);
3320 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3321 pa_assert(c
->subscription
);
3323 c
->subscription
= NULL
;
3325 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3328 static void command_set_volume(
3335 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3338 pa_sink
*sink
= NULL
;
3339 pa_source
*source
= NULL
;
3340 pa_sink_input
*si
= NULL
;
3341 const char *name
= NULL
;
3342 const char *client_name
;
3344 pa_native_connection_assert_ref(c
);
3347 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3348 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3349 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3350 pa_tagstruct_get_cvolume(t
, &volume
) ||
3351 !pa_tagstruct_eof(t
)) {
3356 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3357 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_VOLUME
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
3358 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3359 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3360 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3361 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3365 case PA_COMMAND_SET_SINK_VOLUME
:
3366 if (idx
!= PA_INVALID_INDEX
)
3367 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3369 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3372 case PA_COMMAND_SET_SOURCE_VOLUME
:
3373 if (idx
!= PA_INVALID_INDEX
)
3374 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3376 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3379 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3380 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3384 pa_assert_not_reached();
3387 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3389 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3392 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3394 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3395 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3396 } else if (source
) {
3397 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3399 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3400 pa_source_set_volume(source
, &volume
, TRUE
);
3402 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3404 pa_log_debug("Client %s changes volume of sink input %s.",
3406 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3407 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3410 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3413 static void command_set_mute(
3420 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3423 pa_sink
*sink
= NULL
;
3424 pa_source
*source
= NULL
;
3425 pa_sink_input
*si
= NULL
;
3426 const char *name
= NULL
, *client_name
;
3428 pa_native_connection_assert_ref(c
);
3431 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3432 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3433 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3434 pa_tagstruct_get_boolean(t
, &mute
) ||
3435 !pa_tagstruct_eof(t
)) {
3440 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3441 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_MUTE
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
3442 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3443 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3444 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3448 case PA_COMMAND_SET_SINK_MUTE
:
3449 if (idx
!= PA_INVALID_INDEX
)
3450 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3452 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3456 case PA_COMMAND_SET_SOURCE_MUTE
:
3457 if (idx
!= PA_INVALID_INDEX
)
3458 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3460 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3464 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3465 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3469 pa_assert_not_reached();
3472 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3474 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3477 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3478 pa_sink_set_mute(sink
, mute
, TRUE
);
3479 } else if (source
) {
3480 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3481 pa_source_set_mute(source
, mute
, TRUE
);
3483 pa_log_debug("Client %s changes mute of sink input %s.",
3485 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3486 pa_sink_input_set_mute(si
, mute
, TRUE
);
3489 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3492 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3493 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3498 pa_native_connection_assert_ref(c
);
3501 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3502 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3503 !pa_tagstruct_eof(t
)) {
3508 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3509 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3510 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3511 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3512 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3514 pa_sink_input_cork(s
->sink_input
, b
);
3517 s
->is_underrun
= TRUE
;
3519 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3522 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3523 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3527 pa_native_connection_assert_ref(c
);
3530 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3531 !pa_tagstruct_eof(t
)) {
3536 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3537 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3538 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3539 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3540 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3543 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3544 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3547 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3548 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3551 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3552 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3556 pa_assert_not_reached();
3559 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3562 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3563 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3568 pa_native_connection_assert_ref(c
);
3571 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3572 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3573 !pa_tagstruct_eof(t
)) {
3578 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3579 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3580 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3582 pa_source_output_cork(s
->source_output
, b
);
3583 pa_memblockq_prebuf_force(s
->memblockq
);
3584 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3587 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3588 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3592 pa_native_connection_assert_ref(c
);
3595 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3596 !pa_tagstruct_eof(t
)) {
3601 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3602 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3603 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3605 pa_memblockq_flush_read(s
->memblockq
);
3606 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3609 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3610 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3613 pa_tagstruct
*reply
;
3615 pa_native_connection_assert_ref(c
);
3618 memset(&a
, 0, sizeof(a
));
3620 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3625 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3627 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3629 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3631 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3632 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3633 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3635 if (pa_tagstruct_get(
3637 PA_TAG_U32
, &a
.maxlength
,
3638 PA_TAG_U32
, &a
.tlength
,
3639 PA_TAG_U32
, &a
.prebuf
,
3640 PA_TAG_U32
, &a
.minreq
,
3641 PA_TAG_INVALID
) < 0 ||
3642 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3643 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3644 !pa_tagstruct_eof(t
)) {
3649 s
->adjust_latency
= adjust_latency
;
3650 s
->early_requests
= early_requests
;
3653 fix_playback_buffer_attr(s
);
3654 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);
3656 reply
= reply_new(tag
);
3657 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3658 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
3659 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
3660 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
3662 if (c
->version
>= 13)
3663 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
3667 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3668 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
3670 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3671 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3673 if (pa_tagstruct_get(
3675 PA_TAG_U32
, &a
.maxlength
,
3676 PA_TAG_U32
, &a
.fragsize
,
3677 PA_TAG_INVALID
) < 0 ||
3678 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3679 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3680 !pa_tagstruct_eof(t
)) {
3685 s
->adjust_latency
= adjust_latency
;
3686 s
->early_requests
= early_requests
;
3689 fix_record_buffer_attr_pre(s
);
3690 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
3691 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
3692 fix_record_buffer_attr_post(s
);
3694 reply
= reply_new(tag
);
3695 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3696 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
3698 if (c
->version
>= 13)
3699 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
3702 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3705 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3706 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3710 pa_native_connection_assert_ref(c
);
3713 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3714 pa_tagstruct_getu32(t
, &rate
) < 0 ||
3715 !pa_tagstruct_eof(t
)) {
3720 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3721 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
3723 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
3726 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3727 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3728 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3730 pa_sink_input_set_rate(s
->sink_input
, rate
);
3734 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
3736 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3737 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3739 pa_source_output_set_rate(s
->source_output
, rate
);
3742 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3745 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3746 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3751 pa_native_connection_assert_ref(c
);
3754 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3756 p
= pa_proplist_new();
3758 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
3760 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
3761 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3762 !pa_tagstruct_eof(t
)) {
3764 pa_proplist_free(p
);
3770 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3771 pa_tagstruct_getu32(t
, &mode
) < 0 ||
3772 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3773 !pa_tagstruct_eof(t
)) {
3775 pa_proplist_free(p
);
3780 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
3781 pa_proplist_free(p
);
3782 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
3785 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
3788 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3789 if (!s
|| !playback_stream_isinstance(s
)) {
3790 pa_proplist_free(p
);
3791 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3793 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
3795 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
3798 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
3799 pa_proplist_free(p
);
3800 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3802 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
3805 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
3807 pa_client_update_proplist(c
->client
, mode
, p
);
3810 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3811 pa_proplist_free(p
);
3814 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3815 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3817 unsigned changed
= 0;
3819 pa_strlist
*l
= NULL
;
3821 pa_native_connection_assert_ref(c
);
3824 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3826 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
3828 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3834 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3837 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3838 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3839 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3841 p
= s
->sink_input
->proplist
;
3843 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3846 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3847 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3849 p
= s
->source_output
->proplist
;
3851 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3853 p
= c
->client
->proplist
;
3859 if (pa_tagstruct_gets(t
, &k
) < 0) {
3868 l
= pa_strlist_prepend(l
, k
);
3871 if (!pa_tagstruct_eof(t
)) {
3880 l
= pa_strlist_pop(l
, &z
);
3885 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
3889 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3892 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3895 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3896 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
3898 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3901 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3902 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
3905 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3906 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
3911 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3912 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3915 pa_native_connection_assert_ref(c
);
3918 if (pa_tagstruct_gets(t
, &s
) < 0 ||
3919 !pa_tagstruct_eof(t
)) {
3924 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3925 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
3927 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
3930 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
3931 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
3933 pa_namereg_set_default_source(c
->protocol
->core
, source
);
3936 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
3938 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
3939 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3941 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
3944 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3947 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3948 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3952 pa_native_connection_assert_ref(c
);
3955 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3956 pa_tagstruct_gets(t
, &name
) < 0 ||
3957 !pa_tagstruct_eof(t
)) {
3962 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3963 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
3965 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
3968 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3969 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3970 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3972 pa_sink_input_set_name(s
->sink_input
, name
);
3976 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
3978 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3979 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3981 pa_source_output_set_name(s
->source_output
, name
);
3984 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3987 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3988 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3991 pa_native_connection_assert_ref(c
);
3994 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3995 !pa_tagstruct_eof(t
)) {
4000 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4002 if (command
== PA_COMMAND_KILL_CLIENT
) {
4005 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4006 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4008 pa_native_connection_ref(c
);
4009 pa_client_kill(client
);
4011 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4014 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4015 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4017 pa_native_connection_ref(c
);
4018 pa_sink_input_kill(s
);
4020 pa_source_output
*s
;
4022 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4024 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4025 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4027 pa_native_connection_ref(c
);
4028 pa_source_output_kill(s
);
4031 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4032 pa_native_connection_unref(c
);
4035 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4036 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4038 const char *name
, *argument
;
4039 pa_tagstruct
*reply
;
4041 pa_native_connection_assert_ref(c
);
4044 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4045 pa_tagstruct_gets(t
, &argument
) < 0 ||
4046 !pa_tagstruct_eof(t
)) {
4051 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4052 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4053 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4055 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4056 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4060 reply
= reply_new(tag
);
4061 pa_tagstruct_putu32(reply
, m
->index
);
4062 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4065 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4066 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4070 pa_native_connection_assert_ref(c
);
4073 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4074 !pa_tagstruct_eof(t
)) {
4079 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4080 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4081 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4083 pa_module_unload_request(m
, FALSE
);
4084 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4087 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4088 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4089 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4090 const char *name_device
= NULL
;
4092 pa_native_connection_assert_ref(c
);
4095 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4096 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4097 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4098 !pa_tagstruct_eof(t
)) {
4103 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4104 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4106 CHECK_VALIDITY(c
->pstream
, !name_device
|| pa_namereg_is_valid_name_or_wildcard(name_device
, command
== PA_COMMAND_MOVE_SINK_INPUT
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
4107 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4108 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4109 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4111 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4112 pa_sink_input
*si
= NULL
;
4113 pa_sink
*sink
= NULL
;
4115 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4117 if (idx_device
!= PA_INVALID_INDEX
)
4118 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4120 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4122 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4124 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4125 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4129 pa_source_output
*so
= NULL
;
4132 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4134 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4136 if (idx_device
!= PA_INVALID_INDEX
)
4137 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4139 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4141 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4143 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4144 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4149 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4152 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4153 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4154 uint32_t idx
= PA_INVALID_INDEX
;
4155 const char *name
= NULL
;
4158 pa_native_connection_assert_ref(c
);
4161 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4162 pa_tagstruct_gets(t
, &name
) < 0 ||
4163 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4164 !pa_tagstruct_eof(t
)) {
4169 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4170 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SUSPEND_SINK
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
) || *name
== 0, tag
, PA_ERR_INVALID
);
4171 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4172 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4173 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4175 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4177 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4179 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4181 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4182 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4186 pa_sink
*sink
= NULL
;
4188 if (idx
!= PA_INVALID_INDEX
)
4189 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4191 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4193 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4195 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4196 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4202 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4204 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4206 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4208 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4209 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4216 if (idx
!= PA_INVALID_INDEX
)
4217 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4219 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4221 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4223 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4224 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4230 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4233 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4234 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4235 uint32_t idx
= PA_INVALID_INDEX
;
4236 const char *name
= NULL
;
4238 pa_native_protocol_ext_cb_t cb
;
4240 pa_native_connection_assert_ref(c
);
4243 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4244 pa_tagstruct_gets(t
, &name
) < 0) {
4249 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4250 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4251 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4252 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4253 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4255 if (idx
!= PA_INVALID_INDEX
)
4256 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4258 for (m
= pa_idxset_first(c
->protocol
->core
->modules
, &idx
); m
; m
= pa_idxset_next(c
->protocol
->core
->modules
, &idx
))
4259 if (strcmp(name
, m
->name
) == 0)
4263 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4264 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4266 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4267 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4269 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4273 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4274 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4275 uint32_t idx
= PA_INVALID_INDEX
;
4276 const char *name
= NULL
, *profile
= NULL
;
4277 pa_card
*card
= NULL
;
4280 pa_native_connection_assert_ref(c
);
4283 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4284 pa_tagstruct_gets(t
, &name
) < 0 ||
4285 pa_tagstruct_gets(t
, &profile
) < 0 ||
4286 !pa_tagstruct_eof(t
)) {
4291 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4292 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4293 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4294 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4295 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4297 if (idx
!= PA_INVALID_INDEX
)
4298 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4300 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4302 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4304 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4305 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4309 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4312 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4313 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4314 uint32_t idx
= PA_INVALID_INDEX
;
4315 const char *name
= NULL
, *port
= NULL
;
4318 pa_native_connection_assert_ref(c
);
4321 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4322 pa_tagstruct_gets(t
, &name
) < 0 ||
4323 pa_tagstruct_gets(t
, &port
) < 0 ||
4324 !pa_tagstruct_eof(t
)) {
4329 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4330 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_PORT
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
4331 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4332 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4333 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4335 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4338 if (idx
!= PA_INVALID_INDEX
)
4339 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4341 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4343 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4345 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4346 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4352 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4354 if (idx
!= PA_INVALID_INDEX
)
4355 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4357 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4359 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4361 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4362 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4367 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4370 /*** pstream callbacks ***/
4372 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4373 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4377 pa_native_connection_assert_ref(c
);
4379 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4380 pa_log("invalid packet.");
4381 native_connection_unlink(c
);
4385 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
) {
4386 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4387 output_stream
*stream
;
4391 pa_native_connection_assert_ref(c
);
4393 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4394 pa_log_debug("Client sent block for invalid stream.");
4399 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4401 if (playback_stream_isinstance(stream
)) {
4402 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4404 if (chunk
->memblock
) {
4405 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4406 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
);
4408 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4410 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
);
4413 upload_stream
*u
= UPLOAD_STREAM(stream
);
4416 if (!u
->memchunk
.memblock
) {
4417 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4418 u
->memchunk
= *chunk
;
4419 pa_memblock_ref(u
->memchunk
.memblock
);
4422 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4423 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4427 pa_assert(u
->memchunk
.memblock
);
4430 if (l
> chunk
->length
)
4435 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4437 if (chunk
->memblock
) {
4439 src
= pa_memblock_acquire(chunk
->memblock
);
4441 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4442 (uint8_t*) src
+ chunk
->index
, l
);
4444 pa_memblock_release(chunk
->memblock
);
4446 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4448 pa_memblock_release(u
->memchunk
.memblock
);
4450 u
->memchunk
.length
+= l
;
4456 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4457 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4460 pa_native_connection_assert_ref(c
);
4462 native_connection_unlink(c
);
4463 pa_log_info("Connection died.");
4466 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4467 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4470 pa_native_connection_assert_ref(c
);
4472 native_connection_send_memblock(c
);
4475 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4478 if (!(q
= pa_thread_mq_get()))
4479 pa_pstream_send_revoke(p
, block_id
);
4481 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4484 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4487 if (!(q
= pa_thread_mq_get()))
4488 pa_pstream_send_release(p
, block_id
);
4490 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4493 /*** client callbacks ***/
4495 static void client_kill_cb(pa_client
*c
) {
4498 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4499 pa_log_info("Connection killed.");
4502 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4504 pa_native_connection
*c
;
4507 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4508 pa_native_connection_assert_ref(c
);
4510 if (c
->version
< 15)
4513 t
= pa_tagstruct_new(NULL
, 0);
4514 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4515 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4516 pa_tagstruct_puts(t
, event
);
4517 pa_tagstruct_put_proplist(t
, pl
);
4518 pa_pstream_send_tagstruct(c
->pstream
, t
);
4521 /*** module entry points ***/
4523 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4524 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4527 pa_native_connection_assert_ref(c
);
4528 pa_assert(c
->auth_timeout_event
== e
);
4530 if (!c
->authorized
) {
4531 native_connection_unlink(c
);
4532 pa_log_info("Connection terminated due to authentication timeout.");
4536 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4537 pa_native_connection
*c
;
4540 pa_client_new_data data
;
4546 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4547 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4548 pa_iochannel_free(io
);
4552 pa_client_new_data_init(&data
);
4553 data
.module
= o
->module
;
4554 data
.driver
= __FILE__
;
4555 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4556 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4557 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4558 client
= pa_client_new(p
->core
, &data
);
4559 pa_client_new_data_done(&data
);
4564 c
= pa_msgobject_new(pa_native_connection
);
4565 c
->parent
.parent
.free
= native_connection_free
;
4566 c
->parent
.process_msg
= native_connection_process_msg
;
4568 c
->options
= pa_native_options_ref(o
);
4569 c
->authorized
= FALSE
;
4571 if (o
->auth_anonymous
) {
4572 pa_log_info("Client authenticated anonymously.");
4573 c
->authorized
= TRUE
;
4576 if (!c
->authorized
&&
4578 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4580 pa_log_info("Client authenticated by IP ACL.");
4581 c
->authorized
= TRUE
;
4585 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4587 c
->auth_timeout_event
= NULL
;
4589 c
->is_local
= pa_iochannel_socket_is_local(io
);
4593 c
->client
->kill
= client_kill_cb
;
4594 c
->client
->send_event
= client_send_event_cb
;
4595 c
->client
->userdata
= c
;
4597 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4598 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
4599 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
4600 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
4601 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
4602 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
4603 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
4605 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
4607 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
4608 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
4610 c
->rrobin_index
= PA_IDXSET_INVALID
;
4611 c
->subscription
= NULL
;
4613 pa_idxset_put(p
->connections
, c
, NULL
);
4616 if (pa_iochannel_creds_supported(io
))
4617 pa_iochannel_creds_enable(io
);
4620 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
4623 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
4624 pa_native_connection
*c
;
4630 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
4631 if (c
->options
->module
== m
)
4632 native_connection_unlink(c
);
4635 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
4636 pa_native_protocol
*p
;
4641 p
= pa_xnew(pa_native_protocol
, 1);
4644 p
->connections
= pa_idxset_new(NULL
, NULL
);
4648 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
4650 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4651 pa_hook_init(&p
->hooks
[h
], p
);
4653 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
4658 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
4659 pa_native_protocol
*p
;
4661 if ((p
= pa_shared_get(c
, "native-protocol")))
4662 return pa_native_protocol_ref(p
);
4664 return native_protocol_new(c
);
4667 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
4669 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4676 void pa_native_protocol_unref(pa_native_protocol
*p
) {
4677 pa_native_connection
*c
;
4681 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4683 if (PA_REFCNT_DEC(p
) > 0)
4686 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
4687 native_connection_unlink(c
);
4689 pa_idxset_free(p
->connections
, NULL
, NULL
);
4691 pa_strlist_free(p
->servers
);
4693 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4694 pa_hook_done(&p
->hooks
[h
]);
4696 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
4698 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
4703 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
4705 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4708 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
4710 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4713 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
4715 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4718 p
->servers
= pa_strlist_remove(p
->servers
, name
);
4720 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4723 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
4725 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4730 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
4732 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4737 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
4739 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4742 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
4744 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
4748 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
4750 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4753 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
4756 pa_native_options
* pa_native_options_new(void) {
4757 pa_native_options
*o
;
4759 o
= pa_xnew0(pa_native_options
, 1);
4765 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
4767 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4774 void pa_native_options_unref(pa_native_options
*o
) {
4776 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4778 if (PA_REFCNT_DEC(o
) > 0)
4781 pa_xfree(o
->auth_group
);
4784 pa_ip_acl_free(o
->auth_ip_acl
);
4787 pa_auth_cookie_unref(o
->auth_cookie
);
4792 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
4797 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4800 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
4801 pa_log("auth-anonymous= expects a boolean argument.");
4806 if (pa_modargs_get_value_boolean(ma
, "auth-group-enabled", &enabled
) < 0) {
4807 pa_log("auth-group-enabled= expects a boolean argument.");
4811 pa_xfree(o
->auth_group
);
4812 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
4816 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4819 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
4822 if (!(ipa
= pa_ip_acl_new(acl
))) {
4823 pa_log("Failed to parse IP ACL '%s'", acl
);
4828 pa_ip_acl_free(o
->auth_ip_acl
);
4830 o
->auth_ip_acl
= ipa
;
4834 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
4835 pa_log("auth-cookie-enabled= expects a boolean argument.");
4840 pa_auth_cookie_unref(o
->auth_cookie
);
4845 /* The new name for this is 'auth-cookie', for compat reasons
4846 * we check the old name too */
4847 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
4848 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
4849 cn
= PA_NATIVE_COOKIE_FILE
;
4851 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, PA_NATIVE_COOKIE_LENGTH
)))
4855 o
->auth_cookie
= NULL
;
4860 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
4861 pa_native_connection_assert_ref(c
);
4866 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
4867 pa_native_connection_assert_ref(c
);