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
:
831 s
->buffer_attr
.tlength
= (uint32_t) offset
;
833 if (s
->connection
->version
>= 15) {
836 t
= pa_tagstruct_new(NULL
, 0);
837 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
838 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
839 pa_tagstruct_putu32(t
, s
->index
);
840 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
841 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
842 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
843 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
844 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
845 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
854 /* Called from main context */
855 static void fix_playback_buffer_attr(playback_stream
*s
) {
856 size_t frame_size
, max_prebuf
;
857 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
861 /* This function will be called from the main thread, before as
862 * well as after the sink input has been activated using
863 * pa_sink_input_put()! That means it may not touch any
864 * ->thread_info data, such as the memblockq! */
866 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
868 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
869 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
870 if (s
->buffer_attr
.maxlength
<= 0)
871 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
873 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
874 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
875 if (s
->buffer_attr
.tlength
<= 0)
876 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
878 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
879 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
880 if (s
->buffer_attr
.minreq
<= 0)
881 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
883 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
884 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
886 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
887 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
889 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
890 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
891 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
893 if (s
->early_requests
) {
895 /* In early request mode we need to emulate the classic
896 * fragment-based playback model. We do this setting the sink
897 * latency to the fragment size. */
899 sink_usec
= minreq_usec
;
900 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
902 } else if (s
->adjust_latency
) {
904 /* So, the user asked us to adjust the latency of the stream
905 * buffer according to the what the sink can provide. The
906 * tlength passed in shall be the overall latency. Roughly
907 * half the latency will be spent on the hw buffer, the other
908 * half of it in the async buffer queue we maintain for each
909 * client. In between we'll have a safety space of size
910 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
911 * empty and needs to be filled, then our buffer must have
912 * enough data to fulfill this request immediatly and thus
913 * have at least the same tlength as the size of the hw
914 * buffer. It additionally needs space for 2 times minreq
915 * because if the buffer ran empty and a partial fillup
916 * happens immediately on the next iteration we need to be
917 * able to fulfill it and give the application also minreq
918 * time to fill it up again for the next request Makes 2 times
919 * minreq in plus.. */
921 if (tlength_usec
> minreq_usec
*2)
922 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
926 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
930 /* Ok, the user didn't ask us to adjust the latency, but we
931 * still need to make sure that the parameters from the user
934 if (tlength_usec
> minreq_usec
*2)
935 sink_usec
= (tlength_usec
- minreq_usec
*2);
939 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
942 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
944 if (s
->early_requests
) {
946 /* Ok, we didn't necessarily get what we were asking for, so
947 * let's tell the user */
949 minreq_usec
= s
->configured_sink_latency
;
951 } else if (s
->adjust_latency
) {
953 /* Ok, we didn't necessarily get what we were asking for, so
954 * let's subtract from what we asked for for the remaining
957 if (tlength_usec
>= s
->configured_sink_latency
)
958 tlength_usec
-= s
->configured_sink_latency
;
961 /* FIXME: This is actually larger than necessary, since not all of
962 * the sink latency is actually rewritable. */
963 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
964 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
966 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
967 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
968 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
970 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
971 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
972 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
974 if (s
->buffer_attr
.minreq
<= 0) {
975 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
976 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
979 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
980 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
982 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
984 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
985 s
->buffer_attr
.prebuf
> max_prebuf
)
986 s
->buffer_attr
.prebuf
= max_prebuf
;
989 /* Called from main context */
990 static playback_stream
* playback_stream_new(
991 pa_native_connection
*c
,
1001 pa_sink_input_flags_t flags
,
1003 pa_bool_t adjust_latency
,
1004 pa_bool_t early_requests
,
1005 pa_bool_t relative_volume
,
1008 playback_stream
*s
, *ssync
;
1009 pa_sink_input
*sink_input
= NULL
;
1010 pa_memchunk silence
;
1012 int64_t start_index
;
1013 pa_sink_input_new_data data
;
1021 /* Find syncid group */
1022 for (ssync
= pa_idxset_first(c
->output_streams
, &idx
); ssync
; ssync
= pa_idxset_next(c
->output_streams
, &idx
)) {
1024 if (!playback_stream_isinstance(ssync
))
1027 if (ssync
->syncid
== syncid
)
1031 /* Synced streams must connect to the same sink */
1035 sink
= ssync
->sink_input
->sink
;
1036 else if (sink
!= ssync
->sink_input
->sink
) {
1037 *ret
= PA_ERR_INVALID
;
1042 pa_sink_input_new_data_init(&data
);
1044 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1045 data
.driver
= __FILE__
;
1046 data
.module
= c
->options
->module
;
1047 data
.client
= c
->client
;
1050 data
.save_sink
= TRUE
;
1052 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1053 pa_sink_input_new_data_set_channel_map(&data
, map
);
1055 pa_sink_input_new_data_set_volume(&data
, volume
);
1056 data
.volume_is_absolute
= !relative_volume
;
1057 data
.save_volume
= TRUE
;
1060 pa_sink_input_new_data_set_muted(&data
, muted
);
1061 data
.save_muted
= TRUE
;
1063 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1066 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1068 pa_sink_input_new_data_done(&data
);
1073 s
= pa_msgobject_new(playback_stream
);
1074 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1075 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1078 s
->sink_input
= sink_input
;
1079 s
->is_underrun
= TRUE
;
1080 s
->drain_request
= FALSE
;
1081 pa_atomic_store(&s
->missing
, 0);
1082 s
->buffer_attr
= *a
;
1083 s
->adjust_latency
= adjust_latency
;
1084 s
->early_requests
= early_requests
;
1086 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1087 s
->sink_input
->pop
= sink_input_pop_cb
;
1088 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1089 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1090 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1091 s
->sink_input
->kill
= sink_input_kill_cb
;
1092 s
->sink_input
->moving
= sink_input_moving_cb
;
1093 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1094 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1095 s
->sink_input
->userdata
= s
;
1097 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1099 fix_playback_buffer_attr(s
);
1101 pa_sink_input_get_silence(sink_input
, &silence
);
1102 s
->memblockq
= pa_memblockq_new(
1104 s
->buffer_attr
.maxlength
,
1105 s
->buffer_attr
.tlength
,
1106 pa_frame_size(&sink_input
->sample_spec
),
1107 s
->buffer_attr
.prebuf
,
1108 s
->buffer_attr
.minreq
,
1111 pa_memblock_unref(silence
.memblock
);
1113 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1115 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1117 /* pa_log("missing original: %li", (long int) *missing); */
1119 *ss
= s
->sink_input
->sample_spec
;
1120 *map
= s
->sink_input
->channel_map
;
1122 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1124 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1125 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1126 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1127 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1128 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1130 pa_sink_input_put(s
->sink_input
);
1134 /* Called from IO context */
1135 static void playback_stream_request_bytes(playback_stream
*s
) {
1137 int previous_missing
;
1139 playback_stream_assert_ref(s
);
1141 m
= pa_memblockq_pop_missing(s
->memblockq
);
1143 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1144 /* (unsigned long) m, */
1145 /* pa_memblockq_get_tlength(s->memblockq), */
1146 /* pa_memblockq_get_minreq(s->memblockq), */
1147 /* pa_memblockq_get_length(s->memblockq), */
1148 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1153 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1155 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1156 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1158 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1159 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1160 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1163 /* Called from main context */
1164 static void playback_stream_send_killed(playback_stream
*p
) {
1166 playback_stream_assert_ref(p
);
1168 t
= pa_tagstruct_new(NULL
, 0);
1169 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1170 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1171 pa_tagstruct_putu32(t
, p
->index
);
1172 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1175 /* Called from main context */
1176 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1177 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1178 pa_native_connection_assert_ref(c
);
1185 case CONNECTION_MESSAGE_REVOKE
:
1186 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1189 case CONNECTION_MESSAGE_RELEASE
:
1190 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1197 /* Called from main context */
1198 static void native_connection_unlink(pa_native_connection
*c
) {
1207 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1210 pa_native_options_unref(c
->options
);
1212 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1213 record_stream_unlink(r
);
1215 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1216 if (playback_stream_isinstance(o
))
1217 playback_stream_unlink(PLAYBACK_STREAM(o
));
1219 upload_stream_unlink(UPLOAD_STREAM(o
));
1221 if (c
->subscription
)
1222 pa_subscription_free(c
->subscription
);
1225 pa_pstream_unlink(c
->pstream
);
1227 if (c
->auth_timeout_event
) {
1228 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1229 c
->auth_timeout_event
= NULL
;
1232 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1234 pa_native_connection_unref(c
);
1237 /* Called from main context */
1238 static void native_connection_free(pa_object
*o
) {
1239 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1243 native_connection_unlink(c
);
1245 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1246 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1248 pa_pdispatch_unref(c
->pdispatch
);
1249 pa_pstream_unref(c
->pstream
);
1250 pa_client_free(c
->client
);
1255 /* Called from main context */
1256 static void native_connection_send_memblock(pa_native_connection
*c
) {
1260 start
= PA_IDXSET_INVALID
;
1264 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1267 if (start
== PA_IDXSET_INVALID
)
1268 start
= c
->rrobin_index
;
1269 else if (start
== c
->rrobin_index
)
1272 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1273 pa_memchunk schunk
= chunk
;
1275 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1276 schunk
.length
= r
->buffer_attr
.fragsize
;
1278 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1280 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1281 pa_memblock_unref(schunk
.memblock
);
1288 /*** sink input callbacks ***/
1290 /* Called from thread context */
1291 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1292 playback_stream_assert_ref(s
);
1294 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1296 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1298 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1300 if (pa_memblockq_is_readable(s
->memblockq
)) {
1302 /* We just ended an underrun, let's ask the sink
1303 * for a complete rewind rewrite */
1305 pa_log_debug("Requesting rewind due to end of underrun.");
1306 pa_sink_input_request_rewind(s
->sink_input
,
1307 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1308 s
->sink_input
->thread_info
.underrun_for
),
1309 FALSE
, TRUE
, FALSE
);
1315 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1317 if (indexw
< indexr
) {
1318 /* OK, the sink already asked for this data, so
1319 * let's have it usk us again */
1321 pa_log_debug("Requesting rewind due to rewrite.");
1322 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1326 playback_stream_request_bytes(s
);
1329 static void flush_write_no_account(pa_memblockq
*q
) {
1330 pa_memblockq_flush_write(q
, FALSE
);
1333 /* Called from thread context */
1334 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1335 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1338 pa_sink_input_assert_ref(i
);
1339 s
= PLAYBACK_STREAM(i
->userdata
);
1340 playback_stream_assert_ref(s
);
1344 case SINK_INPUT_MESSAGE_SEEK
: {
1347 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1349 /* The client side is incapable of accounting correctly
1350 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1351 * able to deal with that. */
1353 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1355 handle_seek(s
, windex
);
1359 case SINK_INPUT_MESSAGE_POST_DATA
: {
1364 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1366 /* pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1368 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1370 if (pa_log_ratelimit())
1371 pa_log_warn("Failed to push data into queue");
1372 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1373 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1376 handle_seek(s
, windex
);
1378 /* pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1383 case SINK_INPUT_MESSAGE_DRAIN
:
1384 case SINK_INPUT_MESSAGE_FLUSH
:
1385 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1386 case SINK_INPUT_MESSAGE_TRIGGER
: {
1389 pa_sink_input
*isync
;
1390 void (*func
)(pa_memblockq
*bq
);
1393 case SINK_INPUT_MESSAGE_FLUSH
:
1394 func
= flush_write_no_account
;
1397 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1398 func
= pa_memblockq_prebuf_force
;
1401 case SINK_INPUT_MESSAGE_DRAIN
:
1402 case SINK_INPUT_MESSAGE_TRIGGER
:
1403 func
= pa_memblockq_prebuf_disable
;
1407 pa_assert_not_reached();
1410 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1412 handle_seek(s
, windex
);
1414 /* Do the same for all other members in the sync group */
1415 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1416 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1417 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1418 func(ssync
->memblockq
);
1419 handle_seek(ssync
, windex
);
1422 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1423 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1424 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1425 func(ssync
->memblockq
);
1426 handle_seek(ssync
, windex
);
1429 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1430 if (!pa_memblockq_is_readable(s
->memblockq
))
1431 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1433 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1434 s
->drain_request
= TRUE
;
1441 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1442 /* Atomically get a snapshot of all timing parameters... */
1443 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1444 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1445 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1446 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1447 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1448 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1452 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1455 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1457 pa_memblockq_prebuf_force(s
->memblockq
);
1459 handle_seek(s
, windex
);
1461 /* Fall through to the default handler */
1465 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1466 pa_usec_t
*r
= userdata
;
1468 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1470 /* Fall through, the default handler will add in the extra
1471 * latency added by the resampler */
1475 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1476 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1477 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1482 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1485 /* Called from thread context */
1486 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1489 pa_sink_input_assert_ref(i
);
1490 s
= PLAYBACK_STREAM(i
->userdata
);
1491 playback_stream_assert_ref(s
);
1494 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1496 if (pa_memblockq_is_readable(s
->memblockq
))
1497 s
->is_underrun
= FALSE
;
1499 if (!s
->is_underrun
)
1500 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
));
1502 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1503 s
->drain_request
= FALSE
;
1504 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
);
1505 } else if (!s
->is_underrun
)
1506 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, 0, NULL
, NULL
);
1508 s
->is_underrun
= TRUE
;
1510 playback_stream_request_bytes(s
);
1513 /* This call will not fail with prebuf=0, hence we check for
1514 underrun explicitly above */
1515 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1518 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1520 if (i
->thread_info
.underrun_for
> 0)
1521 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1523 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1524 playback_stream_request_bytes(s
);
1529 /* Called from thread context */
1530 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1533 pa_sink_input_assert_ref(i
);
1534 s
= PLAYBACK_STREAM(i
->userdata
);
1535 playback_stream_assert_ref(s
);
1537 /* If we are in an underrun, then we don't rewind */
1538 if (i
->thread_info
.underrun_for
> 0)
1541 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1544 /* Called from thread context */
1545 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1548 pa_sink_input_assert_ref(i
);
1549 s
= PLAYBACK_STREAM(i
->userdata
);
1550 playback_stream_assert_ref(s
);
1552 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1555 /* Called from thread context */
1556 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1558 size_t new_tlength
, old_tlength
;
1560 pa_sink_input_assert_ref(i
);
1561 s
= PLAYBACK_STREAM(i
->userdata
);
1562 playback_stream_assert_ref(s
);
1564 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1565 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1567 if (old_tlength
< new_tlength
) {
1568 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1569 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1570 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1572 if (new_tlength
== old_tlength
)
1573 pa_log_debug("Failed to increase tlength");
1575 pa_log_debug("Notifying client about increased tlength");
1576 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
);
1581 /* Called from main context */
1582 static void sink_input_kill_cb(pa_sink_input
*i
) {
1585 pa_sink_input_assert_ref(i
);
1586 s
= PLAYBACK_STREAM(i
->userdata
);
1587 playback_stream_assert_ref(s
);
1589 playback_stream_send_killed(s
);
1590 playback_stream_unlink(s
);
1593 /* Called from main context */
1594 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1598 pa_sink_input_assert_ref(i
);
1599 s
= PLAYBACK_STREAM(i
->userdata
);
1600 playback_stream_assert_ref(s
);
1602 if (s
->connection
->version
< 15)
1605 t
= pa_tagstruct_new(NULL
, 0);
1606 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1607 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1608 pa_tagstruct_putu32(t
, s
->index
);
1609 pa_tagstruct_puts(t
, event
);
1610 pa_tagstruct_put_proplist(t
, pl
);
1611 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1614 /* Called from main context */
1615 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1619 pa_sink_input_assert_ref(i
);
1620 s
= PLAYBACK_STREAM(i
->userdata
);
1621 playback_stream_assert_ref(s
);
1623 if (s
->connection
->version
< 12)
1626 t
= pa_tagstruct_new(NULL
, 0);
1627 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1628 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1629 pa_tagstruct_putu32(t
, s
->index
);
1630 pa_tagstruct_put_boolean(t
, suspend
);
1631 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1634 /* Called from main context */
1635 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1639 pa_sink_input_assert_ref(i
);
1640 s
= PLAYBACK_STREAM(i
->userdata
);
1641 playback_stream_assert_ref(s
);
1646 fix_playback_buffer_attr(s
);
1647 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1648 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1650 if (s
->connection
->version
< 12)
1653 t
= pa_tagstruct_new(NULL
, 0);
1654 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1655 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1656 pa_tagstruct_putu32(t
, s
->index
);
1657 pa_tagstruct_putu32(t
, dest
->index
);
1658 pa_tagstruct_puts(t
, dest
->name
);
1659 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1661 if (s
->connection
->version
>= 13) {
1662 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1663 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1664 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1665 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1666 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1669 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1672 /*** source_output callbacks ***/
1674 /* Called from thread context */
1675 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1676 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1679 pa_source_output_assert_ref(o
);
1680 s
= RECORD_STREAM(o
->userdata
);
1681 record_stream_assert_ref(s
);
1684 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1685 /* Atomically get a snapshot of all timing parameters... */
1686 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1687 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1688 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1692 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1695 /* Called from thread context */
1696 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1699 pa_source_output_assert_ref(o
);
1700 s
= RECORD_STREAM(o
->userdata
);
1701 record_stream_assert_ref(s
);
1704 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1705 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1708 static void source_output_kill_cb(pa_source_output
*o
) {
1711 pa_source_output_assert_ref(o
);
1712 s
= RECORD_STREAM(o
->userdata
);
1713 record_stream_assert_ref(s
);
1715 record_stream_send_killed(s
);
1716 record_stream_unlink(s
);
1719 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1722 pa_source_output_assert_ref(o
);
1723 s
= RECORD_STREAM(o
->userdata
);
1724 record_stream_assert_ref(s
);
1726 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1728 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1731 /* Called from main context */
1732 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1736 pa_source_output_assert_ref(o
);
1737 s
= RECORD_STREAM(o
->userdata
);
1738 record_stream_assert_ref(s
);
1740 if (s
->connection
->version
< 15)
1743 t
= pa_tagstruct_new(NULL
, 0);
1744 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1745 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1746 pa_tagstruct_putu32(t
, s
->index
);
1747 pa_tagstruct_puts(t
, event
);
1748 pa_tagstruct_put_proplist(t
, pl
);
1749 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1752 /* Called from main context */
1753 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1757 pa_source_output_assert_ref(o
);
1758 s
= RECORD_STREAM(o
->userdata
);
1759 record_stream_assert_ref(s
);
1761 if (s
->connection
->version
< 12)
1764 t
= pa_tagstruct_new(NULL
, 0);
1765 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1766 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1767 pa_tagstruct_putu32(t
, s
->index
);
1768 pa_tagstruct_put_boolean(t
, suspend
);
1769 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1772 /* Called from main context */
1773 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1777 pa_source_output_assert_ref(o
);
1778 s
= RECORD_STREAM(o
->userdata
);
1779 record_stream_assert_ref(s
);
1784 fix_record_buffer_attr_pre(s
);
1785 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1786 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1787 fix_record_buffer_attr_post(s
);
1789 if (s
->connection
->version
< 12)
1792 t
= pa_tagstruct_new(NULL
, 0);
1793 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1794 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1795 pa_tagstruct_putu32(t
, s
->index
);
1796 pa_tagstruct_putu32(t
, dest
->index
);
1797 pa_tagstruct_puts(t
, dest
->name
);
1798 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1800 if (s
->connection
->version
>= 13) {
1801 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1802 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1803 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1806 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1809 /*** pdispatch callbacks ***/
1811 static void protocol_error(pa_native_connection
*c
) {
1812 pa_log("protocol error, kicking client");
1813 native_connection_unlink(c
);
1816 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1817 if (!(expression)) { \
1818 pa_pstream_send_error((pstream), (tag), (error)); \
1823 static pa_tagstruct
*reply_new(uint32_t tag
) {
1824 pa_tagstruct
*reply
;
1826 reply
= pa_tagstruct_new(NULL
, 0);
1827 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1828 pa_tagstruct_putu32(reply
, tag
);
1832 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1833 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1835 uint32_t sink_index
, syncid
, missing
;
1836 pa_buffer_attr attr
;
1837 const char *name
= NULL
, *sink_name
;
1840 pa_tagstruct
*reply
;
1841 pa_sink
*sink
= NULL
;
1849 fix_channels
= FALSE
,
1851 variable_rate
= FALSE
,
1853 adjust_latency
= FALSE
,
1854 early_requests
= FALSE
,
1855 dont_inhibit_auto_suspend
= FALSE
,
1857 fail_on_suspend
= FALSE
,
1858 relative_volume
= FALSE
;
1859 pa_sink_input_flags_t flags
= 0;
1861 pa_bool_t volume_set
= TRUE
;
1862 int ret
= PA_ERR_INVALID
;
1864 pa_native_connection_assert_ref(c
);
1866 memset(&attr
, 0, sizeof(attr
));
1868 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1871 PA_TAG_SAMPLE_SPEC
, &ss
,
1872 PA_TAG_CHANNEL_MAP
, &map
,
1873 PA_TAG_U32
, &sink_index
,
1874 PA_TAG_STRING
, &sink_name
,
1875 PA_TAG_U32
, &attr
.maxlength
,
1876 PA_TAG_BOOLEAN
, &corked
,
1877 PA_TAG_U32
, &attr
.tlength
,
1878 PA_TAG_U32
, &attr
.prebuf
,
1879 PA_TAG_U32
, &attr
.minreq
,
1880 PA_TAG_U32
, &syncid
,
1881 PA_TAG_CVOLUME
, &volume
,
1882 PA_TAG_INVALID
) < 0) {
1888 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
1889 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
1890 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
1891 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
1892 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
1893 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
1894 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
1895 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
1897 p
= pa_proplist_new();
1900 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1902 if (c
->version
>= 12) {
1903 /* Since 0.9.8 the user can ask for a couple of additional flags */
1905 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
1906 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
1907 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
1908 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
1909 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
1910 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
1911 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
1914 pa_proplist_free(p
);
1919 if (c
->version
>= 13) {
1921 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
1922 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
1923 pa_tagstruct_get_proplist(t
, p
) < 0) {
1925 pa_proplist_free(p
);
1930 if (c
->version
>= 14) {
1932 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
1933 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
1935 pa_proplist_free(p
);
1940 if (c
->version
>= 15) {
1942 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
1943 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
1944 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
1946 pa_proplist_free(p
);
1951 if (c
->version
>= 17) {
1953 if (pa_tagstruct_get_boolean(t
, &relative_volume
) < 0) {
1955 pa_proplist_free(p
);
1960 if (!pa_tagstruct_eof(t
)) {
1962 pa_proplist_free(p
);
1966 if (sink_index
!= PA_INVALID_INDEX
) {
1968 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
1969 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1970 pa_proplist_free(p
);
1974 } else if (sink_name
) {
1976 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
1977 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1978 pa_proplist_free(p
);
1984 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
1985 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
1986 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
1987 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
1988 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
1989 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
1990 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
1991 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
1992 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
1993 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0);
1995 /* Only since protocol version 15 there's a seperate muted_set
1996 * flag. For older versions we synthesize it here */
1997 muted_set
= muted_set
|| muted
;
1999 s
= playback_stream_new(c
, sink
, &ss
, &map
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, syncid
, &missing
, flags
, p
, adjust_latency
, early_requests
, relative_volume
, &ret
);
2000 pa_proplist_free(p
);
2002 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
2004 reply
= reply_new(tag
);
2005 pa_tagstruct_putu32(reply
, s
->index
);
2006 pa_assert(s
->sink_input
);
2007 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
2008 pa_tagstruct_putu32(reply
, missing
);
2010 /* pa_log("initial request is %u", missing); */
2012 if (c
->version
>= 9) {
2013 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2015 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2016 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
2017 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2018 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2021 if (c
->version
>= 12) {
2022 /* Since 0.9.8 we support sending the chosen sample
2023 * spec/channel map/device/suspend status back to the
2026 pa_tagstruct_put_sample_spec(reply
, &ss
);
2027 pa_tagstruct_put_channel_map(reply
, &map
);
2029 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2030 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2032 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2035 if (c
->version
>= 13)
2036 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2038 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2041 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2042 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2045 pa_native_connection_assert_ref(c
);
2048 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2049 !pa_tagstruct_eof(t
)) {
2054 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2058 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2060 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2061 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2065 playback_stream_unlink(s
);
2069 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2071 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2072 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2076 record_stream_unlink(s
);
2080 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2083 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2084 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2088 upload_stream_unlink(s
);
2093 pa_assert_not_reached();
2096 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2099 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2100 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2102 pa_buffer_attr attr
;
2103 uint32_t source_index
;
2104 const char *name
= NULL
, *source_name
;
2107 pa_tagstruct
*reply
;
2108 pa_source
*source
= NULL
;
2115 fix_channels
= FALSE
,
2117 variable_rate
= FALSE
,
2118 adjust_latency
= FALSE
,
2119 peak_detect
= FALSE
,
2120 early_requests
= FALSE
,
2121 dont_inhibit_auto_suspend
= FALSE
,
2122 fail_on_suspend
= FALSE
;
2123 pa_source_output_flags_t flags
= 0;
2125 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2126 pa_sink_input
*direct_on_input
= NULL
;
2127 int ret
= PA_ERR_INVALID
;
2129 pa_native_connection_assert_ref(c
);
2132 memset(&attr
, 0, sizeof(attr
));
2134 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2135 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2136 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2137 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2138 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2139 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2140 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2141 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2146 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2147 CHECK_VALIDITY(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
2148 CHECK_VALIDITY(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
);
2149 CHECK_VALIDITY(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2150 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2151 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2152 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2154 p
= pa_proplist_new();
2157 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2159 if (c
->version
>= 12) {
2160 /* Since 0.9.8 the user can ask for a couple of additional flags */
2162 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2163 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2164 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2165 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2166 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2167 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2168 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2171 pa_proplist_free(p
);
2176 if (c
->version
>= 13) {
2178 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2179 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2180 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2181 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2183 pa_proplist_free(p
);
2188 if (c
->version
>= 14) {
2190 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2192 pa_proplist_free(p
);
2197 if (c
->version
>= 15) {
2199 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2200 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2202 pa_proplist_free(p
);
2207 if (!pa_tagstruct_eof(t
)) {
2209 pa_proplist_free(p
);
2213 if (source_index
!= PA_INVALID_INDEX
) {
2215 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2216 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2217 pa_proplist_free(p
);
2221 } else if (source_name
) {
2223 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2224 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2225 pa_proplist_free(p
);
2230 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2232 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2233 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2234 pa_proplist_free(p
);
2240 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2241 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2242 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2243 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2244 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2245 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2246 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2247 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2248 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2249 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0);
2251 s
= record_stream_new(c
, source
, &ss
, &map
, peak_detect
, &attr
, flags
, p
, adjust_latency
, direct_on_input
, early_requests
, &ret
);
2252 pa_proplist_free(p
);
2254 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
2256 reply
= reply_new(tag
);
2257 pa_tagstruct_putu32(reply
, s
->index
);
2258 pa_assert(s
->source_output
);
2259 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2261 if (c
->version
>= 9) {
2262 /* Since 0.9 we support sending the buffer metrics back to the client */
2264 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2265 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2268 if (c
->version
>= 12) {
2269 /* Since 0.9.8 we support sending the chosen sample
2270 * spec/channel map/device/suspend status back to the
2273 pa_tagstruct_put_sample_spec(reply
, &ss
);
2274 pa_tagstruct_put_channel_map(reply
, &map
);
2276 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2277 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2279 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2282 if (c
->version
>= 13)
2283 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2285 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2288 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2289 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2292 pa_native_connection_assert_ref(c
);
2295 if (!pa_tagstruct_eof(t
)) {
2300 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2301 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2302 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2304 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2306 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2309 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2310 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2312 pa_tagstruct
*reply
;
2313 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2315 pa_native_connection_assert_ref(c
);
2318 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2319 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2320 !pa_tagstruct_eof(t
)) {
2325 /* Minimum supported version */
2326 if (c
->version
< 8) {
2327 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2331 /* Starting with protocol version 13 the MSB of the version tag
2332 reflects if shm is available for this pa_native_connection or
2334 if (c
->version
>= 13) {
2335 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2336 c
->version
&= 0x7FFFFFFFU
;
2339 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2341 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2343 if (!c
->authorized
) {
2344 pa_bool_t success
= FALSE
;
2347 const pa_creds
*creds
;
2349 if ((creds
= pa_pdispatch_creds(pd
))) {
2350 if (creds
->uid
== getuid())
2352 else if (c
->options
->auth_group
) {
2356 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2357 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2358 else if (gid
== creds
->gid
)
2362 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2363 pa_log_warn("Failed to check group membership.");
2369 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2370 (unsigned long) creds
->uid
,
2371 (unsigned long) creds
->gid
,
2376 if (!success
&& c
->options
->auth_cookie
) {
2379 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2380 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2385 pa_log_warn("Denied access to client with invalid authorization data.");
2386 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2390 c
->authorized
= TRUE
;
2391 if (c
->auth_timeout_event
) {
2392 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2393 c
->auth_timeout_event
= NULL
;
2397 /* Enable shared memory support if possible */
2399 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2402 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2405 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2410 /* Only enable SHM if both sides are owned by the same
2411 * user. This is a security measure because otherwise data
2412 * private to the user might leak. */
2414 const pa_creds
*creds
;
2415 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2420 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2421 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2423 reply
= reply_new(tag
);
2424 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2428 /* SHM support is only enabled after both sides made sure they are the same user. */
2432 ucred
.uid
= getuid();
2433 ucred
.gid
= getgid();
2435 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2438 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2442 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2443 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2444 const char *name
= NULL
;
2446 pa_tagstruct
*reply
;
2448 pa_native_connection_assert_ref(c
);
2451 p
= pa_proplist_new();
2453 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2454 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2455 !pa_tagstruct_eof(t
)) {
2458 pa_proplist_free(p
);
2463 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2464 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2465 pa_proplist_free(p
);
2469 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2470 pa_proplist_free(p
);
2472 reply
= reply_new(tag
);
2474 if (c
->version
>= 13)
2475 pa_tagstruct_putu32(reply
, c
->client
->index
);
2477 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2480 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2481 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2483 uint32_t idx
= PA_IDXSET_INVALID
;
2485 pa_native_connection_assert_ref(c
);
2488 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2489 !pa_tagstruct_eof(t
)) {
2494 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2495 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
);
2497 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2499 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2503 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2504 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2505 idx
= source
->index
;
2508 if (idx
== PA_IDXSET_INVALID
)
2509 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2511 pa_tagstruct
*reply
;
2512 reply
= reply_new(tag
);
2513 pa_tagstruct_putu32(reply
, idx
);
2514 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2518 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2519 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2523 pa_native_connection_assert_ref(c
);
2526 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2527 !pa_tagstruct_eof(t
)) {
2532 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2533 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2534 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2535 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2537 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
);
2540 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2541 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2542 pa_tagstruct
*reply
;
2543 const pa_mempool_stat
*stat
;
2545 pa_native_connection_assert_ref(c
);
2548 if (!pa_tagstruct_eof(t
)) {
2553 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2555 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2557 reply
= reply_new(tag
);
2558 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2559 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2560 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2561 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2562 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2563 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2566 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2567 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2568 pa_tagstruct
*reply
;
2570 struct timeval tv
, now
;
2573 pa_native_connection_assert_ref(c
);
2576 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2577 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2578 !pa_tagstruct_eof(t
)) {
2583 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2584 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2585 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2586 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2588 /* Get an atomic snapshot of all timing parameters */
2589 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);
2591 reply
= reply_new(tag
);
2592 pa_tagstruct_put_usec(reply
,
2593 s
->current_sink_latency
+
2594 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2595 pa_tagstruct_put_usec(reply
, 0);
2596 pa_tagstruct_put_boolean(reply
,
2597 s
->playing_for
> 0 &&
2598 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2599 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2600 pa_tagstruct_put_timeval(reply
, &tv
);
2601 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2602 pa_tagstruct_puts64(reply
, s
->write_index
);
2603 pa_tagstruct_puts64(reply
, s
->read_index
);
2605 if (c
->version
>= 13) {
2606 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2607 pa_tagstruct_putu64(reply
, s
->playing_for
);
2610 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2613 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2614 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2615 pa_tagstruct
*reply
;
2617 struct timeval tv
, now
;
2620 pa_native_connection_assert_ref(c
);
2623 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2624 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2625 !pa_tagstruct_eof(t
)) {
2630 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2631 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2632 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2634 /* Get an atomic snapshot of all timing parameters */
2635 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);
2637 reply
= reply_new(tag
);
2638 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2639 pa_tagstruct_put_usec(reply
,
2640 s
->current_source_latency
+
2641 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->source
->sample_spec
));
2642 pa_tagstruct_put_boolean(reply
,
2643 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2644 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2645 pa_tagstruct_put_timeval(reply
, &tv
);
2646 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2647 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2648 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2649 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2652 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2653 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2656 const char *name
= NULL
;
2659 pa_tagstruct
*reply
;
2662 pa_native_connection_assert_ref(c
);
2665 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2666 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2667 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2668 pa_tagstruct_getu32(t
, &length
) < 0) {
2673 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2674 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2675 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2676 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2677 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2678 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2680 p
= pa_proplist_new();
2682 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2683 !pa_tagstruct_eof(t
)) {
2686 pa_proplist_free(p
);
2690 if (c
->version
< 13)
2691 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2693 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2694 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2696 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2697 pa_proplist_free(p
);
2698 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2701 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2702 pa_proplist_free(p
);
2704 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2706 reply
= reply_new(tag
);
2707 pa_tagstruct_putu32(reply
, s
->index
);
2708 pa_tagstruct_putu32(reply
, length
);
2709 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2712 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2713 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2718 pa_native_connection_assert_ref(c
);
2721 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2722 !pa_tagstruct_eof(t
)) {
2727 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2729 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2730 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2731 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2733 if (!s
->memchunk
.memblock
)
2734 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2735 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2736 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2738 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2740 upload_stream_unlink(s
);
2743 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2744 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2745 uint32_t sink_index
;
2748 const char *name
, *sink_name
;
2751 pa_tagstruct
*reply
;
2753 pa_native_connection_assert_ref(c
);
2756 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2758 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2759 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2760 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2761 pa_tagstruct_gets(t
, &name
) < 0) {
2766 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
2767 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2768 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2769 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2771 if (sink_index
!= PA_INVALID_INDEX
)
2772 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
2774 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
2776 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
2778 p
= pa_proplist_new();
2780 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2781 !pa_tagstruct_eof(t
)) {
2783 pa_proplist_free(p
);
2787 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
2789 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
2790 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2791 pa_proplist_free(p
);
2795 pa_proplist_free(p
);
2797 reply
= reply_new(tag
);
2799 if (c
->version
>= 13)
2800 pa_tagstruct_putu32(reply
, idx
);
2802 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2805 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2806 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2809 pa_native_connection_assert_ref(c
);
2812 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2813 !pa_tagstruct_eof(t
)) {
2818 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2819 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2821 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
2822 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2826 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2829 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
2832 pa_assert(original
);
2836 if (c
->version
< 12) {
2837 /* Before protocol version 12 we didn't support S32 samples,
2838 * so we need to lie about this to the client */
2840 if (fixed
->format
== PA_SAMPLE_S32LE
)
2841 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2842 if (fixed
->format
== PA_SAMPLE_S32BE
)
2843 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2846 if (c
->version
< 15) {
2847 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
2848 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2849 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
2850 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2854 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
2855 pa_sample_spec fixed_ss
;
2858 pa_sink_assert_ref(sink
);
2860 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
2864 PA_TAG_U32
, sink
->index
,
2865 PA_TAG_STRING
, sink
->name
,
2866 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2867 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2868 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
2869 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
2870 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
2871 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
2872 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
2873 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
2874 PA_TAG_USEC
, pa_sink_get_latency(sink
),
2875 PA_TAG_STRING
, sink
->driver
,
2876 PA_TAG_U32
, sink
->flags
,
2879 if (c
->version
>= 13) {
2880 pa_tagstruct_put_proplist(t
, sink
->proplist
);
2881 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
2884 if (c
->version
>= 15) {
2885 pa_tagstruct_put_volume(t
, sink
->base_volume
);
2886 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
2887 pa_log_error("Internal sink state is invalid.");
2888 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
2889 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
2890 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
2893 if (c
->version
>= 16) {
2894 pa_tagstruct_putu32(t
, sink
->ports
? pa_hashmap_size(sink
->ports
) : 0);
2900 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
2901 pa_tagstruct_puts(t
, p
->name
);
2902 pa_tagstruct_puts(t
, p
->description
);
2903 pa_tagstruct_putu32(t
, p
->priority
);
2907 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
2911 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
2912 pa_sample_spec fixed_ss
;
2915 pa_source_assert_ref(source
);
2917 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
2921 PA_TAG_U32
, source
->index
,
2922 PA_TAG_STRING
, source
->name
,
2923 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2924 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2925 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
2926 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
2927 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
2928 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
2929 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
2930 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
2931 PA_TAG_USEC
, pa_source_get_latency(source
),
2932 PA_TAG_STRING
, source
->driver
,
2933 PA_TAG_U32
, source
->flags
,
2936 if (c
->version
>= 13) {
2937 pa_tagstruct_put_proplist(t
, source
->proplist
);
2938 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
2941 if (c
->version
>= 15) {
2942 pa_tagstruct_put_volume(t
, source
->base_volume
);
2943 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
2944 pa_log_error("Internal source state is invalid.");
2945 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
2946 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
2947 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
2950 if (c
->version
>= 16) {
2952 pa_tagstruct_putu32(t
, source
->ports
? pa_hashmap_size(source
->ports
) : 0);
2954 if (source
->ports
) {
2958 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
2959 pa_tagstruct_puts(t
, p
->name
);
2960 pa_tagstruct_puts(t
, p
->description
);
2961 pa_tagstruct_putu32(t
, p
->priority
);
2965 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
2969 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
2973 pa_tagstruct_putu32(t
, client
->index
);
2974 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
2975 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
2976 pa_tagstruct_puts(t
, client
->driver
);
2978 if (c
->version
>= 13)
2979 pa_tagstruct_put_proplist(t
, client
->proplist
);
2982 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
2989 pa_tagstruct_putu32(t
, card
->index
);
2990 pa_tagstruct_puts(t
, card
->name
);
2991 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
2992 pa_tagstruct_puts(t
, card
->driver
);
2994 pa_tagstruct_putu32(t
, card
->profiles
? pa_hashmap_size(card
->profiles
) : 0);
2996 if (card
->profiles
) {
2997 while ((p
= pa_hashmap_iterate(card
->profiles
, &state
, NULL
))) {
2998 pa_tagstruct_puts(t
, p
->name
);
2999 pa_tagstruct_puts(t
, p
->description
);
3000 pa_tagstruct_putu32(t
, p
->n_sinks
);
3001 pa_tagstruct_putu32(t
, p
->n_sources
);
3002 pa_tagstruct_putu32(t
, p
->priority
);
3006 pa_tagstruct_puts(t
, card
->active_profile
? card
->active_profile
->name
: NULL
);
3007 pa_tagstruct_put_proplist(t
, card
->proplist
);
3010 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
3014 pa_tagstruct_putu32(t
, module
->index
);
3015 pa_tagstruct_puts(t
, module
->name
);
3016 pa_tagstruct_puts(t
, module
->argument
);
3017 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3019 if (c
->version
< 15)
3020 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3022 if (c
->version
>= 15)
3023 pa_tagstruct_put_proplist(t
, module
->proplist
);
3026 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3027 pa_sample_spec fixed_ss
;
3028 pa_usec_t sink_latency
;
3032 pa_sink_input_assert_ref(s
);
3034 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3036 pa_tagstruct_putu32(t
, s
->index
);
3037 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3038 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3039 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3040 pa_tagstruct_putu32(t
, s
->sink
->index
);
3041 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3042 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3043 pa_tagstruct_put_cvolume(t
, pa_sink_input_get_volume(s
, &v
, TRUE
));
3044 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3045 pa_tagstruct_put_usec(t
, sink_latency
);
3046 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3047 pa_tagstruct_puts(t
, s
->driver
);
3048 if (c
->version
>= 11)
3049 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3050 if (c
->version
>= 13)
3051 pa_tagstruct_put_proplist(t
, s
->proplist
);
3054 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3055 pa_sample_spec fixed_ss
;
3056 pa_usec_t source_latency
;
3059 pa_source_output_assert_ref(s
);
3061 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3063 pa_tagstruct_putu32(t
, s
->index
);
3064 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3065 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3066 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3067 pa_tagstruct_putu32(t
, s
->source
->index
);
3068 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3069 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3070 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3071 pa_tagstruct_put_usec(t
, source_latency
);
3072 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3073 pa_tagstruct_puts(t
, s
->driver
);
3075 if (c
->version
>= 13)
3076 pa_tagstruct_put_proplist(t
, s
->proplist
);
3079 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3080 pa_sample_spec fixed_ss
;
3086 if (e
->memchunk
.memblock
)
3087 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3089 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3091 pa_tagstruct_putu32(t
, e
->index
);
3092 pa_tagstruct_puts(t
, e
->name
);
3094 if (e
->volume_is_set
)
3097 pa_cvolume_init(&v
);
3099 pa_tagstruct_put_cvolume(t
, &v
);
3100 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3101 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3102 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3103 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3104 pa_tagstruct_put_boolean(t
, e
->lazy
);
3105 pa_tagstruct_puts(t
, e
->filename
);
3107 if (c
->version
>= 13)
3108 pa_tagstruct_put_proplist(t
, e
->proplist
);
3111 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3112 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3114 pa_sink
*sink
= NULL
;
3115 pa_source
*source
= NULL
;
3116 pa_client
*client
= NULL
;
3117 pa_card
*card
= NULL
;
3118 pa_module
*module
= NULL
;
3119 pa_sink_input
*si
= NULL
;
3120 pa_source_output
*so
= NULL
;
3121 pa_scache_entry
*sce
= NULL
;
3122 const char *name
= NULL
;
3123 pa_tagstruct
*reply
;
3125 pa_native_connection_assert_ref(c
);
3128 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3129 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3130 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3131 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3132 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3133 pa_tagstruct_gets(t
, &name
) < 0) ||
3134 !pa_tagstruct_eof(t
)) {
3139 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3140 CHECK_VALIDITY(c
->pstream
, !name
||
3141 (command
== PA_COMMAND_GET_SINK_INFO
&&
3142 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3143 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3144 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3145 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3146 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3147 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3148 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3150 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3151 if (idx
!= PA_INVALID_INDEX
)
3152 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3154 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3155 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3156 if (idx
!= PA_INVALID_INDEX
)
3157 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3159 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3160 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3161 if (idx
!= PA_INVALID_INDEX
)
3162 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3164 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3165 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3166 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3167 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3168 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3169 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3170 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3171 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3172 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3174 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3175 if (idx
!= PA_INVALID_INDEX
)
3176 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3178 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3181 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3182 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3186 reply
= reply_new(tag
);
3188 sink_fill_tagstruct(c
, reply
, sink
);
3190 source_fill_tagstruct(c
, reply
, source
);
3192 client_fill_tagstruct(c
, reply
, client
);
3194 card_fill_tagstruct(c
, reply
, card
);
3196 module_fill_tagstruct(c
, reply
, module
);
3198 sink_input_fill_tagstruct(c
, reply
, si
);
3200 source_output_fill_tagstruct(c
, reply
, so
);
3202 scache_fill_tagstruct(c
, reply
, sce
);
3203 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3206 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3207 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3211 pa_tagstruct
*reply
;
3213 pa_native_connection_assert_ref(c
);
3216 if (!pa_tagstruct_eof(t
)) {
3221 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3223 reply
= reply_new(tag
);
3225 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3226 i
= c
->protocol
->core
->sinks
;
3227 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3228 i
= c
->protocol
->core
->sources
;
3229 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3230 i
= c
->protocol
->core
->clients
;
3231 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3232 i
= c
->protocol
->core
->cards
;
3233 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3234 i
= c
->protocol
->core
->modules
;
3235 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3236 i
= c
->protocol
->core
->sink_inputs
;
3237 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3238 i
= c
->protocol
->core
->source_outputs
;
3240 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3241 i
= c
->protocol
->core
->scache
;
3245 for (p
= pa_idxset_first(i
, &idx
); p
; p
= pa_idxset_next(i
, &idx
)) {
3246 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3247 sink_fill_tagstruct(c
, reply
, p
);
3248 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3249 source_fill_tagstruct(c
, reply
, p
);
3250 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3251 client_fill_tagstruct(c
, reply
, p
);
3252 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3253 card_fill_tagstruct(c
, reply
, p
);
3254 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3255 module_fill_tagstruct(c
, reply
, p
);
3256 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3257 sink_input_fill_tagstruct(c
, reply
, p
);
3258 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3259 source_output_fill_tagstruct(c
, reply
, p
);
3261 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3262 scache_fill_tagstruct(c
, reply
, p
);
3267 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3270 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3271 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3272 pa_tagstruct
*reply
;
3274 pa_source
*def_source
;
3275 pa_sample_spec fixed_ss
;
3278 pa_native_connection_assert_ref(c
);
3281 if (!pa_tagstruct_eof(t
)) {
3286 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3288 reply
= reply_new(tag
);
3289 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3290 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3292 u
= pa_get_user_name_malloc();
3293 pa_tagstruct_puts(reply
, u
);
3296 h
= pa_get_host_name_malloc();
3297 pa_tagstruct_puts(reply
, h
);
3300 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3301 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3303 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3304 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3305 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3306 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3308 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3310 if (c
->version
>= 15)
3311 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3313 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3316 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3318 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3320 pa_native_connection_assert_ref(c
);
3322 t
= pa_tagstruct_new(NULL
, 0);
3323 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3324 pa_tagstruct_putu32(t
, (uint32_t) -1);
3325 pa_tagstruct_putu32(t
, e
);
3326 pa_tagstruct_putu32(t
, idx
);
3327 pa_pstream_send_tagstruct(c
->pstream
, t
);
3330 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3331 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3332 pa_subscription_mask_t m
;
3334 pa_native_connection_assert_ref(c
);
3337 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3338 !pa_tagstruct_eof(t
)) {
3343 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3344 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3346 if (c
->subscription
)
3347 pa_subscription_free(c
->subscription
);
3350 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3351 pa_assert(c
->subscription
);
3353 c
->subscription
= NULL
;
3355 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3358 static void command_set_volume(
3365 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3368 pa_sink
*sink
= NULL
;
3369 pa_source
*source
= NULL
;
3370 pa_sink_input
*si
= NULL
;
3371 const char *name
= NULL
;
3372 const char *client_name
;
3374 pa_native_connection_assert_ref(c
);
3377 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3378 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3379 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3380 pa_tagstruct_get_cvolume(t
, &volume
) ||
3381 !pa_tagstruct_eof(t
)) {
3386 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3387 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
);
3388 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3389 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3390 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3391 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3395 case PA_COMMAND_SET_SINK_VOLUME
:
3396 if (idx
!= PA_INVALID_INDEX
)
3397 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3399 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3402 case PA_COMMAND_SET_SOURCE_VOLUME
:
3403 if (idx
!= PA_INVALID_INDEX
)
3404 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3406 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3409 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3410 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3414 pa_assert_not_reached();
3417 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3419 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3422 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3424 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3425 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3426 } else if (source
) {
3427 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3429 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3430 pa_source_set_volume(source
, &volume
, TRUE
);
3432 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3434 pa_log_debug("Client %s changes volume of sink input %s.",
3436 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3437 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3440 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3443 static void command_set_mute(
3450 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3453 pa_sink
*sink
= NULL
;
3454 pa_source
*source
= NULL
;
3455 pa_sink_input
*si
= NULL
;
3456 const char *name
= NULL
, *client_name
;
3458 pa_native_connection_assert_ref(c
);
3461 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3462 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3463 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3464 pa_tagstruct_get_boolean(t
, &mute
) ||
3465 !pa_tagstruct_eof(t
)) {
3470 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3471 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
);
3472 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3473 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3474 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3478 case PA_COMMAND_SET_SINK_MUTE
:
3479 if (idx
!= PA_INVALID_INDEX
)
3480 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3482 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3486 case PA_COMMAND_SET_SOURCE_MUTE
:
3487 if (idx
!= PA_INVALID_INDEX
)
3488 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3490 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3494 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3495 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3499 pa_assert_not_reached();
3502 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3504 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3507 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3508 pa_sink_set_mute(sink
, mute
, TRUE
);
3509 } else if (source
) {
3510 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3511 pa_source_set_mute(source
, mute
, TRUE
);
3513 pa_log_debug("Client %s changes mute of sink input %s.",
3515 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3516 pa_sink_input_set_mute(si
, mute
, TRUE
);
3519 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3522 static void command_cork_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
);
3528 pa_native_connection_assert_ref(c
);
3531 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3532 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3533 !pa_tagstruct_eof(t
)) {
3538 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3539 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3540 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3541 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3542 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3544 pa_sink_input_cork(s
->sink_input
, b
);
3547 s
->is_underrun
= TRUE
;
3549 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3552 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3553 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3557 pa_native_connection_assert_ref(c
);
3560 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3561 !pa_tagstruct_eof(t
)) {
3566 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3567 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3568 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3569 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3570 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3573 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3574 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3577 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3578 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3581 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3582 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3586 pa_assert_not_reached();
3589 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3592 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3593 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3598 pa_native_connection_assert_ref(c
);
3601 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3602 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3603 !pa_tagstruct_eof(t
)) {
3608 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3609 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3610 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3612 pa_source_output_cork(s
->source_output
, b
);
3613 pa_memblockq_prebuf_force(s
->memblockq
);
3614 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3617 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3618 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3622 pa_native_connection_assert_ref(c
);
3625 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3626 !pa_tagstruct_eof(t
)) {
3631 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3632 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3633 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3635 pa_memblockq_flush_read(s
->memblockq
);
3636 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3639 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3640 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3643 pa_tagstruct
*reply
;
3645 pa_native_connection_assert_ref(c
);
3648 memset(&a
, 0, sizeof(a
));
3650 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3655 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3657 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3659 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3661 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3662 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3663 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3665 if (pa_tagstruct_get(
3667 PA_TAG_U32
, &a
.maxlength
,
3668 PA_TAG_U32
, &a
.tlength
,
3669 PA_TAG_U32
, &a
.prebuf
,
3670 PA_TAG_U32
, &a
.minreq
,
3671 PA_TAG_INVALID
) < 0 ||
3672 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3673 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3674 !pa_tagstruct_eof(t
)) {
3679 s
->adjust_latency
= adjust_latency
;
3680 s
->early_requests
= early_requests
;
3683 fix_playback_buffer_attr(s
);
3684 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);
3686 reply
= reply_new(tag
);
3687 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3688 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
3689 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
3690 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
3692 if (c
->version
>= 13)
3693 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
3697 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3698 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
3700 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3701 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3703 if (pa_tagstruct_get(
3705 PA_TAG_U32
, &a
.maxlength
,
3706 PA_TAG_U32
, &a
.fragsize
,
3707 PA_TAG_INVALID
) < 0 ||
3708 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3709 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3710 !pa_tagstruct_eof(t
)) {
3715 s
->adjust_latency
= adjust_latency
;
3716 s
->early_requests
= early_requests
;
3719 fix_record_buffer_attr_pre(s
);
3720 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
3721 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
3722 fix_record_buffer_attr_post(s
);
3724 reply
= reply_new(tag
);
3725 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3726 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
3728 if (c
->version
>= 13)
3729 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
3732 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3735 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3736 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3740 pa_native_connection_assert_ref(c
);
3743 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3744 pa_tagstruct_getu32(t
, &rate
) < 0 ||
3745 !pa_tagstruct_eof(t
)) {
3750 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3751 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
3753 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
3756 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3757 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3758 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3760 pa_sink_input_set_rate(s
->sink_input
, rate
);
3764 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
3766 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3767 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3769 pa_source_output_set_rate(s
->source_output
, rate
);
3772 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3775 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3776 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3781 pa_native_connection_assert_ref(c
);
3784 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3786 p
= pa_proplist_new();
3788 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
3790 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
3791 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3792 !pa_tagstruct_eof(t
)) {
3794 pa_proplist_free(p
);
3800 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3801 pa_tagstruct_getu32(t
, &mode
) < 0 ||
3802 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3803 !pa_tagstruct_eof(t
)) {
3805 pa_proplist_free(p
);
3810 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
3811 pa_proplist_free(p
);
3812 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
3815 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
3818 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3819 if (!s
|| !playback_stream_isinstance(s
)) {
3820 pa_proplist_free(p
);
3821 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3823 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
3825 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
3828 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
3829 pa_proplist_free(p
);
3830 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3832 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
3835 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
3837 pa_client_update_proplist(c
->client
, mode
, p
);
3840 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3841 pa_proplist_free(p
);
3844 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3845 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3847 unsigned changed
= 0;
3849 pa_strlist
*l
= NULL
;
3851 pa_native_connection_assert_ref(c
);
3854 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3856 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
3858 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3864 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3867 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3868 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3869 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3871 p
= s
->sink_input
->proplist
;
3873 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3876 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3877 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3879 p
= s
->source_output
->proplist
;
3881 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3883 p
= c
->client
->proplist
;
3889 if (pa_tagstruct_gets(t
, &k
) < 0) {
3898 l
= pa_strlist_prepend(l
, k
);
3901 if (!pa_tagstruct_eof(t
)) {
3910 l
= pa_strlist_pop(l
, &z
);
3915 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
3919 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3922 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3925 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3926 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
3928 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3931 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3932 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
3935 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3936 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
3941 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3942 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3945 pa_native_connection_assert_ref(c
);
3948 if (pa_tagstruct_gets(t
, &s
) < 0 ||
3949 !pa_tagstruct_eof(t
)) {
3954 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3955 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
3957 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
3960 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
3961 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
3963 pa_namereg_set_default_source(c
->protocol
->core
, source
);
3966 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
3968 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
3969 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3971 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
3974 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3977 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3978 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3982 pa_native_connection_assert_ref(c
);
3985 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3986 pa_tagstruct_gets(t
, &name
) < 0 ||
3987 !pa_tagstruct_eof(t
)) {
3992 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3993 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
3995 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
3998 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3999 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4000 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4002 pa_sink_input_set_name(s
->sink_input
, name
);
4006 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
4008 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4009 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4011 pa_source_output_set_name(s
->source_output
, name
);
4014 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4017 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4018 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4021 pa_native_connection_assert_ref(c
);
4024 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4025 !pa_tagstruct_eof(t
)) {
4030 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4032 if (command
== PA_COMMAND_KILL_CLIENT
) {
4035 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4036 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4038 pa_native_connection_ref(c
);
4039 pa_client_kill(client
);
4041 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4044 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4045 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4047 pa_native_connection_ref(c
);
4048 pa_sink_input_kill(s
);
4050 pa_source_output
*s
;
4052 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4054 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4055 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4057 pa_native_connection_ref(c
);
4058 pa_source_output_kill(s
);
4061 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4062 pa_native_connection_unref(c
);
4065 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4066 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4068 const char *name
, *argument
;
4069 pa_tagstruct
*reply
;
4071 pa_native_connection_assert_ref(c
);
4074 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4075 pa_tagstruct_gets(t
, &argument
) < 0 ||
4076 !pa_tagstruct_eof(t
)) {
4081 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4082 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4083 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4085 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4086 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4090 reply
= reply_new(tag
);
4091 pa_tagstruct_putu32(reply
, m
->index
);
4092 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4095 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4096 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4100 pa_native_connection_assert_ref(c
);
4103 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4104 !pa_tagstruct_eof(t
)) {
4109 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4110 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4111 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4113 pa_module_unload_request(m
, FALSE
);
4114 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4117 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4118 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4119 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4120 const char *name_device
= NULL
;
4122 pa_native_connection_assert_ref(c
);
4125 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4126 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4127 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4128 !pa_tagstruct_eof(t
)) {
4133 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4134 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4136 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
);
4137 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4138 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4139 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4141 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4142 pa_sink_input
*si
= NULL
;
4143 pa_sink
*sink
= NULL
;
4145 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4147 if (idx_device
!= PA_INVALID_INDEX
)
4148 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4150 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4152 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4154 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4155 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4159 pa_source_output
*so
= NULL
;
4162 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4164 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4166 if (idx_device
!= PA_INVALID_INDEX
)
4167 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4169 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4171 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4173 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4174 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4179 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4182 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4183 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4184 uint32_t idx
= PA_INVALID_INDEX
;
4185 const char *name
= NULL
;
4188 pa_native_connection_assert_ref(c
);
4191 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4192 pa_tagstruct_gets(t
, &name
) < 0 ||
4193 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4194 !pa_tagstruct_eof(t
)) {
4199 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4200 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
);
4201 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4202 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4203 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4205 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4207 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4209 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4211 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4212 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4216 pa_sink
*sink
= NULL
;
4218 if (idx
!= PA_INVALID_INDEX
)
4219 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4221 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4223 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4225 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4226 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4232 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4234 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4236 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4238 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4239 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4246 if (idx
!= PA_INVALID_INDEX
)
4247 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4249 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4251 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4253 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4254 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4260 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4263 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4264 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4265 uint32_t idx
= PA_INVALID_INDEX
;
4266 const char *name
= NULL
;
4268 pa_native_protocol_ext_cb_t cb
;
4270 pa_native_connection_assert_ref(c
);
4273 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4274 pa_tagstruct_gets(t
, &name
) < 0) {
4279 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4280 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4281 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4282 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4283 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4285 if (idx
!= PA_INVALID_INDEX
)
4286 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4288 for (m
= pa_idxset_first(c
->protocol
->core
->modules
, &idx
); m
; m
= pa_idxset_next(c
->protocol
->core
->modules
, &idx
))
4289 if (strcmp(name
, m
->name
) == 0)
4293 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4294 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4296 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4297 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4299 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4303 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4304 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4305 uint32_t idx
= PA_INVALID_INDEX
;
4306 const char *name
= NULL
, *profile
= NULL
;
4307 pa_card
*card
= NULL
;
4310 pa_native_connection_assert_ref(c
);
4313 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4314 pa_tagstruct_gets(t
, &name
) < 0 ||
4315 pa_tagstruct_gets(t
, &profile
) < 0 ||
4316 !pa_tagstruct_eof(t
)) {
4321 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4322 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4323 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4324 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4325 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4327 if (idx
!= PA_INVALID_INDEX
)
4328 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4330 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4332 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4334 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4335 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4339 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4342 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4343 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4344 uint32_t idx
= PA_INVALID_INDEX
;
4345 const char *name
= NULL
, *port
= NULL
;
4348 pa_native_connection_assert_ref(c
);
4351 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4352 pa_tagstruct_gets(t
, &name
) < 0 ||
4353 pa_tagstruct_gets(t
, &port
) < 0 ||
4354 !pa_tagstruct_eof(t
)) {
4359 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4360 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
);
4361 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4362 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4363 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4365 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4368 if (idx
!= PA_INVALID_INDEX
)
4369 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4371 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4373 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4375 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4376 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4382 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4384 if (idx
!= PA_INVALID_INDEX
)
4385 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4387 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4389 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4391 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4392 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4397 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4400 /*** pstream callbacks ***/
4402 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4403 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4407 pa_native_connection_assert_ref(c
);
4409 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4410 pa_log("invalid packet.");
4411 native_connection_unlink(c
);
4415 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
) {
4416 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4417 output_stream
*stream
;
4421 pa_native_connection_assert_ref(c
);
4423 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4424 pa_log_debug("Client sent block for invalid stream.");
4429 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4431 if (playback_stream_isinstance(stream
)) {
4432 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4434 if (chunk
->memblock
) {
4435 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4436 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
);
4438 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4440 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
);
4443 upload_stream
*u
= UPLOAD_STREAM(stream
);
4446 if (!u
->memchunk
.memblock
) {
4447 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4448 u
->memchunk
= *chunk
;
4449 pa_memblock_ref(u
->memchunk
.memblock
);
4452 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4453 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4457 pa_assert(u
->memchunk
.memblock
);
4460 if (l
> chunk
->length
)
4465 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4467 if (chunk
->memblock
) {
4469 src
= pa_memblock_acquire(chunk
->memblock
);
4471 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4472 (uint8_t*) src
+ chunk
->index
, l
);
4474 pa_memblock_release(chunk
->memblock
);
4476 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4478 pa_memblock_release(u
->memchunk
.memblock
);
4480 u
->memchunk
.length
+= l
;
4486 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4487 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4490 pa_native_connection_assert_ref(c
);
4492 native_connection_unlink(c
);
4493 pa_log_info("Connection died.");
4496 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4497 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4500 pa_native_connection_assert_ref(c
);
4502 native_connection_send_memblock(c
);
4505 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4508 if (!(q
= pa_thread_mq_get()))
4509 pa_pstream_send_revoke(p
, block_id
);
4511 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4514 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4517 if (!(q
= pa_thread_mq_get()))
4518 pa_pstream_send_release(p
, block_id
);
4520 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4523 /*** client callbacks ***/
4525 static void client_kill_cb(pa_client
*c
) {
4528 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4529 pa_log_info("Connection killed.");
4532 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4534 pa_native_connection
*c
;
4537 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4538 pa_native_connection_assert_ref(c
);
4540 if (c
->version
< 15)
4543 t
= pa_tagstruct_new(NULL
, 0);
4544 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4545 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4546 pa_tagstruct_puts(t
, event
);
4547 pa_tagstruct_put_proplist(t
, pl
);
4548 pa_pstream_send_tagstruct(c
->pstream
, t
);
4551 /*** module entry points ***/
4553 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4554 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4557 pa_native_connection_assert_ref(c
);
4558 pa_assert(c
->auth_timeout_event
== e
);
4560 if (!c
->authorized
) {
4561 native_connection_unlink(c
);
4562 pa_log_info("Connection terminated due to authentication timeout.");
4566 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4567 pa_native_connection
*c
;
4570 pa_client_new_data data
;
4576 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4577 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4578 pa_iochannel_free(io
);
4582 pa_client_new_data_init(&data
);
4583 data
.module
= o
->module
;
4584 data
.driver
= __FILE__
;
4585 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4586 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4587 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4588 client
= pa_client_new(p
->core
, &data
);
4589 pa_client_new_data_done(&data
);
4594 c
= pa_msgobject_new(pa_native_connection
);
4595 c
->parent
.parent
.free
= native_connection_free
;
4596 c
->parent
.process_msg
= native_connection_process_msg
;
4598 c
->options
= pa_native_options_ref(o
);
4599 c
->authorized
= FALSE
;
4601 if (o
->auth_anonymous
) {
4602 pa_log_info("Client authenticated anonymously.");
4603 c
->authorized
= TRUE
;
4606 if (!c
->authorized
&&
4608 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4610 pa_log_info("Client authenticated by IP ACL.");
4611 c
->authorized
= TRUE
;
4615 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4617 c
->auth_timeout_event
= NULL
;
4619 c
->is_local
= pa_iochannel_socket_is_local(io
);
4623 c
->client
->kill
= client_kill_cb
;
4624 c
->client
->send_event
= client_send_event_cb
;
4625 c
->client
->userdata
= c
;
4627 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4628 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
4629 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
4630 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
4631 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
4632 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
4633 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
4635 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
4637 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
4638 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
4640 c
->rrobin_index
= PA_IDXSET_INVALID
;
4641 c
->subscription
= NULL
;
4643 pa_idxset_put(p
->connections
, c
, NULL
);
4646 if (pa_iochannel_creds_supported(io
))
4647 pa_iochannel_creds_enable(io
);
4650 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
4653 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
4654 pa_native_connection
*c
;
4660 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
4661 if (c
->options
->module
== m
)
4662 native_connection_unlink(c
);
4665 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
4666 pa_native_protocol
*p
;
4671 p
= pa_xnew(pa_native_protocol
, 1);
4674 p
->connections
= pa_idxset_new(NULL
, NULL
);
4678 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
4680 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4681 pa_hook_init(&p
->hooks
[h
], p
);
4683 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
4688 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
4689 pa_native_protocol
*p
;
4691 if ((p
= pa_shared_get(c
, "native-protocol")))
4692 return pa_native_protocol_ref(p
);
4694 return native_protocol_new(c
);
4697 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
4699 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4706 void pa_native_protocol_unref(pa_native_protocol
*p
) {
4707 pa_native_connection
*c
;
4711 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4713 if (PA_REFCNT_DEC(p
) > 0)
4716 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
4717 native_connection_unlink(c
);
4719 pa_idxset_free(p
->connections
, NULL
, NULL
);
4721 pa_strlist_free(p
->servers
);
4723 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4724 pa_hook_done(&p
->hooks
[h
]);
4726 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
4728 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
4733 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
4735 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4738 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
4740 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4743 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
4745 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4748 p
->servers
= pa_strlist_remove(p
->servers
, name
);
4750 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4753 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
4755 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4760 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
4762 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4767 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
4769 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4772 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
4774 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
4778 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
4780 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4783 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
4786 pa_native_options
* pa_native_options_new(void) {
4787 pa_native_options
*o
;
4789 o
= pa_xnew0(pa_native_options
, 1);
4795 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
4797 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4804 void pa_native_options_unref(pa_native_options
*o
) {
4806 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4808 if (PA_REFCNT_DEC(o
) > 0)
4811 pa_xfree(o
->auth_group
);
4814 pa_ip_acl_free(o
->auth_ip_acl
);
4817 pa_auth_cookie_unref(o
->auth_cookie
);
4822 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
4827 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4830 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
4831 pa_log("auth-anonymous= expects a boolean argument.");
4836 if (pa_modargs_get_value_boolean(ma
, "auth-group-enabled", &enabled
) < 0) {
4837 pa_log("auth-group-enabled= expects a boolean argument.");
4841 pa_xfree(o
->auth_group
);
4842 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
4846 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4849 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
4852 if (!(ipa
= pa_ip_acl_new(acl
))) {
4853 pa_log("Failed to parse IP ACL '%s'", acl
);
4858 pa_ip_acl_free(o
->auth_ip_acl
);
4860 o
->auth_ip_acl
= ipa
;
4864 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
4865 pa_log("auth-cookie-enabled= expects a boolean argument.");
4870 pa_auth_cookie_unref(o
->auth_cookie
);
4875 /* The new name for this is 'auth-cookie', for compat reasons
4876 * we check the old name too */
4877 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
4878 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
4879 cn
= PA_NATIVE_COOKIE_FILE
;
4881 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, PA_NATIVE_COOKIE_LENGTH
)))
4885 o
->auth_cookie
= NULL
;
4890 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
4891 pa_native_connection_assert_ref(c
);
4896 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
4897 pa_native_connection_assert_ref(c
);