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>
38 #include <pulse/internal.h>
40 #include <pulsecore/native-common.h>
41 #include <pulsecore/packet.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/source-output.h>
44 #include <pulsecore/sink-input.h>
45 #include <pulsecore/pstream.h>
46 #include <pulsecore/tagstruct.h>
47 #include <pulsecore/pdispatch.h>
48 #include <pulsecore/pstream-util.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/creds.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/ipacl.h>
59 #include <pulsecore/thread-mq.h>
61 #include "protocol-native.h"
63 /* #define PROTOCOL_NATIVE_DEBUG */
65 /* Kick a client if it doesn't authenticate within this time */
66 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
68 /* Don't accept more connection than this */
69 #define MAX_CONNECTIONS 64
71 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
72 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
73 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
74 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
76 struct pa_native_protocol
;
78 typedef struct record_stream
{
81 pa_native_connection
*connection
;
84 pa_source_output
*source_output
;
85 pa_memblockq
*memblockq
;
87 pa_bool_t adjust_latency
:1;
88 pa_bool_t early_requests
:1;
90 /* Requested buffer attributes */
91 pa_buffer_attr buffer_attr_req
;
92 /* Fixed-up and adjusted buffer attributes */
93 pa_buffer_attr buffer_attr
;
95 pa_atomic_t on_the_fly
;
96 pa_usec_t configured_source_latency
;
99 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
100 size_t on_the_fly_snapshot
;
101 pa_usec_t current_monitor_latency
;
102 pa_usec_t current_source_latency
;
105 #define RECORD_STREAM(o) (record_stream_cast(o))
106 PA_DEFINE_PRIVATE_CLASS(record_stream
, pa_msgobject
);
108 typedef struct output_stream
{
112 #define OUTPUT_STREAM(o) (output_stream_cast(o))
113 PA_DEFINE_PRIVATE_CLASS(output_stream
, pa_msgobject
);
115 typedef struct playback_stream
{
116 output_stream parent
;
118 pa_native_connection
*connection
;
121 pa_sink_input
*sink_input
;
122 pa_memblockq
*memblockq
;
124 pa_bool_t adjust_latency
:1;
125 pa_bool_t early_requests
:1;
127 pa_bool_t is_underrun
:1;
128 pa_bool_t drain_request
:1;
132 /* Optimization to avoid too many rewinds with a lot of small blocks */
133 pa_atomic_t seek_or_post_in_queue
;
137 pa_usec_t configured_sink_latency
;
138 /* Requested buffer attributes */
139 pa_buffer_attr buffer_attr_req
;
140 /* Fixed-up and adjusted buffer attributes */
141 pa_buffer_attr buffer_attr
;
143 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
144 int64_t read_index
, write_index
;
145 size_t render_memblockq_length
;
146 pa_usec_t current_sink_latency
;
147 uint64_t playing_for
, underrun_for
;
150 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
151 PA_DEFINE_PRIVATE_CLASS(playback_stream
, output_stream
);
153 typedef struct upload_stream
{
154 output_stream parent
;
156 pa_native_connection
*connection
;
159 pa_memchunk memchunk
;
162 pa_sample_spec sample_spec
;
163 pa_channel_map channel_map
;
164 pa_proplist
*proplist
;
167 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
168 PA_DEFINE_PRIVATE_CLASS(upload_stream
, output_stream
);
170 struct pa_native_connection
{
172 pa_native_protocol
*protocol
;
173 pa_native_options
*options
;
174 pa_bool_t authorized
:1;
175 pa_bool_t is_local
:1;
179 pa_pdispatch
*pdispatch
;
180 pa_idxset
*record_streams
, *output_streams
;
181 uint32_t rrobin_index
;
182 pa_subscription
*subscription
;
183 pa_time_event
*auth_timeout_event
;
186 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
187 PA_DEFINE_PRIVATE_CLASS(pa_native_connection
, pa_msgobject
);
189 struct pa_native_protocol
{
193 pa_idxset
*connections
;
196 pa_hook hooks
[PA_NATIVE_HOOK_MAX
];
198 pa_hashmap
*extensions
;
202 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
= PA_SOURCE_OUTPUT_MESSAGE_MAX
206 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
207 SINK_INPUT_MESSAGE_DRAIN
, /* disabled prebuf, get playback started. */
208 SINK_INPUT_MESSAGE_FLUSH
,
209 SINK_INPUT_MESSAGE_TRIGGER
,
210 SINK_INPUT_MESSAGE_SEEK
,
211 SINK_INPUT_MESSAGE_PREBUF_FORCE
,
212 SINK_INPUT_MESSAGE_UPDATE_LATENCY
,
213 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
217 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, /* data requested from sink input from the main loop */
218 PLAYBACK_STREAM_MESSAGE_UNDERFLOW
,
219 PLAYBACK_STREAM_MESSAGE_OVERFLOW
,
220 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
,
221 PLAYBACK_STREAM_MESSAGE_STARTED
,
222 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
226 RECORD_STREAM_MESSAGE_POST_DATA
/* data from source output to main loop */
230 CONNECTION_MESSAGE_RELEASE
,
231 CONNECTION_MESSAGE_REVOKE
234 static bool sink_input_process_underrun_cb(pa_sink_input
*i
);
235 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
236 static void sink_input_kill_cb(pa_sink_input
*i
);
237 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
);
238 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
);
239 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
240 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
241 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
);
242 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
);
244 static void native_connection_send_memblock(pa_native_connection
*c
);
245 static void playback_stream_request_bytes(struct playback_stream
*s
);
247 static void source_output_kill_cb(pa_source_output
*o
);
248 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
249 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
);
250 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
);
251 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
252 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
);
254 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
255 static int source_output_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
257 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
258 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
259 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
260 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
261 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
262 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
263 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
264 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
265 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
266 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
267 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
268 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
269 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
270 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
271 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
272 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
273 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
274 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
275 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
276 static void command_set_volume(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
277 static void command_set_mute(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
278 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
279 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
280 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
281 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
282 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
283 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
284 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
285 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
286 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
287 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
288 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
289 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
290 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
291 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
292 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
293 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
294 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
295 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
296 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
298 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
299 [PA_COMMAND_ERROR
] = NULL
,
300 [PA_COMMAND_TIMEOUT
] = NULL
,
301 [PA_COMMAND_REPLY
] = NULL
,
302 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
303 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
304 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
305 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
306 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
307 [PA_COMMAND_AUTH
] = command_auth
,
308 [PA_COMMAND_REQUEST
] = NULL
,
309 [PA_COMMAND_EXIT
] = command_exit
,
310 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
311 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
312 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
313 [PA_COMMAND_STAT
] = command_stat
,
314 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
315 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
316 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
317 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
318 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
319 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
320 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
321 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
322 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
323 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
324 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
325 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
326 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
327 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
328 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
329 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
330 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
331 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
332 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
333 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
334 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
335 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
336 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
337 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
338 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
340 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
341 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
342 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
343 [PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
] = command_set_volume
,
345 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
346 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
347 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
348 [PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
] = command_set_mute
,
350 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
351 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
353 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
354 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
355 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
356 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
358 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
359 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
361 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
362 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
363 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
364 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
365 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
366 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
367 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
368 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
369 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
371 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
372 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
373 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
374 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
376 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
377 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
379 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
380 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
382 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
383 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
385 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
386 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
387 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
389 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
390 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
391 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
393 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
395 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
396 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
398 [PA_COMMAND_SET_PORT_LATENCY_OFFSET
] = command_set_port_latency_offset
,
400 [PA_COMMAND_EXTENSION
] = command_extension
403 /* structure management */
405 /* Called from main context */
406 static void upload_stream_unlink(upload_stream
*s
) {
412 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
413 s
->connection
= NULL
;
414 upload_stream_unref(s
);
417 /* Called from main context */
418 static void upload_stream_free(pa_object
*o
) {
419 upload_stream
*s
= UPLOAD_STREAM(o
);
422 upload_stream_unlink(s
);
427 pa_proplist_free(s
->proplist
);
429 if (s
->memchunk
.memblock
)
430 pa_memblock_unref(s
->memchunk
.memblock
);
435 /* Called from main context */
436 static upload_stream
* upload_stream_new(
437 pa_native_connection
*c
,
438 const pa_sample_spec
*ss
,
439 const pa_channel_map
*map
,
449 pa_assert(length
> 0);
452 s
= pa_msgobject_new(upload_stream
);
453 s
->parent
.parent
.parent
.free
= upload_stream_free
;
455 s
->sample_spec
= *ss
;
456 s
->channel_map
= *map
;
457 s
->name
= pa_xstrdup(name
);
458 pa_memchunk_reset(&s
->memchunk
);
460 s
->proplist
= pa_proplist_copy(p
);
461 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
463 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
468 /* Called from main context */
469 static void record_stream_unlink(record_stream
*s
) {
475 if (s
->source_output
) {
476 pa_source_output_unlink(s
->source_output
);
477 pa_source_output_unref(s
->source_output
);
478 s
->source_output
= NULL
;
481 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
482 s
->connection
= NULL
;
483 record_stream_unref(s
);
486 /* Called from main context */
487 static void record_stream_free(pa_object
*o
) {
488 record_stream
*s
= RECORD_STREAM(o
);
491 record_stream_unlink(s
);
493 pa_memblockq_free(s
->memblockq
);
497 /* Called from main context */
498 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
499 record_stream
*s
= RECORD_STREAM(o
);
500 record_stream_assert_ref(s
);
507 case RECORD_STREAM_MESSAGE_POST_DATA
:
509 /* We try to keep up to date with how many bytes are
510 * currently on the fly */
511 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
513 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
514 /* pa_log_warn("Failed to push data into output queue."); */
518 if (!pa_pstream_is_pending(s
->connection
->pstream
))
519 native_connection_send_memblock(s
->connection
);
527 /* Called from main context */
528 static void fix_record_buffer_attr_pre(record_stream
*s
) {
531 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
535 /* This function will be called from the main thread, before as
536 * well as after the source output has been activated using
537 * pa_source_output_put()! That means it may not touch any
538 * ->thread_info data! */
540 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
541 s
->buffer_attr
= s
->buffer_attr_req
;
543 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
544 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
545 if (s
->buffer_attr
.maxlength
<= 0)
546 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
548 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
549 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
550 if (s
->buffer_attr
.fragsize
<= 0)
551 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
553 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
555 if (s
->early_requests
) {
557 /* In early request mode we need to emulate the classic
558 * fragment-based playback model. We do this setting the source
559 * latency to the fragment size. */
561 source_usec
= fragsize_usec
;
563 } else if (s
->adjust_latency
) {
565 /* So, the user asked us to adjust the latency according to
566 * what the source can provide. Half the latency will be
567 * spent on the hw buffer, half of it in the async buffer
568 * queue we maintain for each client. */
570 source_usec
= fragsize_usec
/2;
574 /* Ok, the user didn't ask us to adjust the latency, hence we
577 source_usec
= (pa_usec_t
) -1;
580 if (source_usec
!= (pa_usec_t
) -1)
581 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
583 s
->configured_source_latency
= 0;
585 if (s
->early_requests
) {
587 /* Ok, we didn't necessarily get what we were asking for, so
588 * let's tell the user */
590 fragsize_usec
= s
->configured_source_latency
;
592 } else if (s
->adjust_latency
) {
594 /* Now subtract what we actually got */
596 if (fragsize_usec
>= s
->configured_source_latency
*2)
597 fragsize_usec
-= s
->configured_source_latency
;
599 fragsize_usec
= s
->configured_source_latency
;
602 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
603 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
605 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
607 if (s
->buffer_attr
.fragsize
<= 0)
608 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
611 /* Called from main context */
612 static void fix_record_buffer_attr_post(record_stream
*s
) {
617 /* This function will be called from the main thread, before as
618 * well as after the source output has been activated using
619 * pa_source_output_put()! That means it may not touch and
620 * ->thread_info data! */
622 base
= pa_frame_size(&s
->source_output
->sample_spec
);
624 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
625 if (s
->buffer_attr
.fragsize
<= 0)
626 s
->buffer_attr
.fragsize
= base
;
628 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
629 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
632 /* Called from main context */
633 static record_stream
* record_stream_new(
634 pa_native_connection
*c
,
639 pa_buffer_attr
*attr
,
643 pa_source_output_flags_t flags
,
645 pa_bool_t adjust_latency
,
646 pa_bool_t early_requests
,
647 pa_bool_t relative_volume
,
648 pa_bool_t peak_detect
,
649 pa_sink_input
*direct_on_input
,
653 pa_source_output
*source_output
= NULL
;
654 pa_source_output_new_data data
;
655 char *memblockq_name
;
662 pa_source_output_new_data_init(&data
);
664 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
665 data
.driver
= __FILE__
;
666 data
.module
= c
->options
->module
;
667 data
.client
= c
->client
;
669 pa_source_output_new_data_set_source(&data
, source
, FALSE
);
670 if (pa_sample_spec_valid(ss
))
671 pa_source_output_new_data_set_sample_spec(&data
, ss
);
672 if (pa_channel_map_valid(map
))
673 pa_source_output_new_data_set_channel_map(&data
, map
);
675 pa_source_output_new_data_set_formats(&data
, formats
);
676 data
.direct_on_input
= direct_on_input
;
678 pa_source_output_new_data_set_volume(&data
, volume
);
679 data
.volume_is_absolute
= !relative_volume
;
680 data
.save_volume
= FALSE
;
683 pa_source_output_new_data_set_muted(&data
, muted
);
684 data
.save_muted
= FALSE
;
687 data
.resample_method
= PA_RESAMPLER_PEAKS
;
690 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
692 pa_source_output_new_data_done(&data
);
697 s
= pa_msgobject_new(record_stream
);
698 s
->parent
.parent
.free
= record_stream_free
;
699 s
->parent
.process_msg
= record_stream_process_msg
;
701 s
->source_output
= source_output
;
702 s
->buffer_attr_req
= *attr
;
703 s
->adjust_latency
= adjust_latency
;
704 s
->early_requests
= early_requests
;
705 pa_atomic_store(&s
->on_the_fly
, 0);
707 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
708 s
->source_output
->push
= source_output_push_cb
;
709 s
->source_output
->kill
= source_output_kill_cb
;
710 s
->source_output
->get_latency
= source_output_get_latency_cb
;
711 s
->source_output
->moving
= source_output_moving_cb
;
712 s
->source_output
->suspend
= source_output_suspend_cb
;
713 s
->source_output
->send_event
= source_output_send_event_cb
;
714 s
->source_output
->userdata
= s
;
716 fix_record_buffer_attr_pre(s
);
718 memblockq_name
= pa_sprintf_malloc("native protocol record stream memblockq [%u]", s
->source_output
->index
);
719 s
->memblockq
= pa_memblockq_new(
722 s
->buffer_attr
.maxlength
,
724 &source_output
->sample_spec
,
729 pa_xfree(memblockq_name
);
731 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
732 fix_record_buffer_attr_post(s
);
734 *ss
= s
->source_output
->sample_spec
;
735 *map
= s
->source_output
->channel_map
;
737 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
739 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
740 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
741 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
742 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
744 pa_source_output_put(s
->source_output
);
748 /* Called from main context */
749 static void record_stream_send_killed(record_stream
*r
) {
751 record_stream_assert_ref(r
);
753 t
= pa_tagstruct_new(NULL
, 0);
754 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
755 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
756 pa_tagstruct_putu32(t
, r
->index
);
757 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
760 /* Called from main context */
761 static void playback_stream_unlink(playback_stream
*s
) {
768 pa_sink_input_unlink(s
->sink_input
);
769 pa_sink_input_unref(s
->sink_input
);
770 s
->sink_input
= NULL
;
773 if (s
->drain_request
)
774 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
776 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
777 s
->connection
= NULL
;
778 playback_stream_unref(s
);
781 /* Called from main context */
782 static void playback_stream_free(pa_object
* o
) {
783 playback_stream
*s
= PLAYBACK_STREAM(o
);
786 playback_stream_unlink(s
);
788 pa_memblockq_free(s
->memblockq
);
792 /* Called from main context */
793 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
794 playback_stream
*s
= PLAYBACK_STREAM(o
);
795 playback_stream_assert_ref(s
);
802 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
807 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
810 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
814 t
= pa_tagstruct_new(NULL
, 0);
815 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
816 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
817 pa_tagstruct_putu32(t
, s
->index
);
818 pa_tagstruct_putu32(t
, (uint32_t) l
);
819 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
821 #ifdef PROTOCOL_NATIVE_DEBUG
822 pa_log("Requesting %lu bytes", (unsigned long) l
);
827 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
830 #ifdef PROTOCOL_NATIVE_DEBUG
831 pa_log("signalling underflow");
834 /* Report that we're empty */
835 t
= pa_tagstruct_new(NULL
, 0);
836 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
837 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
838 pa_tagstruct_putu32(t
, s
->index
);
839 if (s
->connection
->version
>= 23)
840 pa_tagstruct_puts64(t
, offset
);
841 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
845 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
848 /* Notify the user we're overflowed*/
849 t
= pa_tagstruct_new(NULL
, 0);
850 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
851 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
852 pa_tagstruct_putu32(t
, s
->index
);
853 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
857 case PLAYBACK_STREAM_MESSAGE_STARTED
:
859 if (s
->connection
->version
>= 13) {
862 /* Notify the user we started playback */
863 t
= pa_tagstruct_new(NULL
, 0);
864 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
865 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
866 pa_tagstruct_putu32(t
, s
->index
);
867 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
872 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
873 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
876 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
:
878 s
->buffer_attr
.tlength
= (uint32_t) offset
;
880 if (s
->connection
->version
>= 15) {
883 t
= pa_tagstruct_new(NULL
, 0);
884 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
885 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
886 pa_tagstruct_putu32(t
, s
->index
);
887 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
888 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
889 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
890 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
891 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
892 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
901 /* Called from main context */
902 static void fix_playback_buffer_attr(playback_stream
*s
) {
903 size_t frame_size
, max_prebuf
;
904 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
908 #ifdef PROTOCOL_NATIVE_DEBUG
909 pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes",
910 (long) s
->buffer_attr_req
.maxlength
,
911 (long) s
->buffer_attr_req
.tlength
,
912 (long) s
->buffer_attr_req
.minreq
,
913 (long) s
->buffer_attr_req
.prebuf
);
915 pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
916 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
917 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
918 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
919 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
922 /* This function will be called from the main thread, before as
923 * well as after the sink input has been activated using
924 * pa_sink_input_put()! That means it may not touch any
925 * ->thread_info data, such as the memblockq! */
927 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
928 s
->buffer_attr
= s
->buffer_attr_req
;
930 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
931 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
932 if (s
->buffer_attr
.maxlength
<= 0)
933 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
935 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
936 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
937 if (s
->buffer_attr
.tlength
<= 0)
938 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
939 if (s
->buffer_attr
.tlength
> s
->buffer_attr
.maxlength
)
940 s
->buffer_attr
.tlength
= s
->buffer_attr
.maxlength
;
942 if (s
->buffer_attr
.minreq
== (uint32_t) -1) {
943 uint32_t process
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
944 /* With low-latency, tlength/4 gives a decent default in all of traditional, adjust latency and early request modes. */
945 uint32_t m
= s
->buffer_attr
.tlength
/ 4;
948 s
->buffer_attr
.minreq
= PA_MIN(process
, m
);
950 if (s
->buffer_attr
.minreq
<= 0)
951 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
953 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
954 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
956 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
957 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
959 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
960 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
961 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
963 if (s
->early_requests
) {
965 /* In early request mode we need to emulate the classic
966 * fragment-based playback model. We do this setting the sink
967 * latency to the fragment size. */
969 sink_usec
= minreq_usec
;
970 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
972 } else if (s
->adjust_latency
) {
974 /* So, the user asked us to adjust the latency of the stream
975 * buffer according to the what the sink can provide. The
976 * tlength passed in shall be the overall latency. Roughly
977 * half the latency will be spent on the hw buffer, the other
978 * half of it in the async buffer queue we maintain for each
979 * client. In between we'll have a safety space of size
980 * 2*minreq. Why the 2*minreq? When the hw buffer is completely
981 * empty and needs to be filled, then our buffer must have
982 * enough data to fulfill this request immediately and thus
983 * have at least the same tlength as the size of the hw
984 * buffer. It additionally needs space for 2 times minreq
985 * because if the buffer ran empty and a partial fillup
986 * happens immediately on the next iteration we need to be
987 * able to fulfill it and give the application also minreq
988 * time to fill it up again for the next request Makes 2 times
989 * minreq in plus.. */
991 if (tlength_usec
> minreq_usec
*2)
992 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
996 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
1000 /* Ok, the user didn't ask us to adjust the latency, but we
1001 * still need to make sure that the parameters from the user
1004 if (tlength_usec
> minreq_usec
*2)
1005 sink_usec
= (tlength_usec
- minreq_usec
*2);
1009 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
1012 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
1014 if (s
->early_requests
) {
1016 /* Ok, we didn't necessarily get what we were asking for, so
1017 * let's tell the user */
1019 minreq_usec
= s
->configured_sink_latency
;
1021 } else if (s
->adjust_latency
) {
1023 /* Ok, we didn't necessarily get what we were asking for, so
1024 * let's subtract from what we asked for for the remaining
1027 if (tlength_usec
>= s
->configured_sink_latency
)
1028 tlength_usec
-= s
->configured_sink_latency
;
1031 pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
1032 (double) sink_usec
/ PA_USEC_PER_MSEC
,
1033 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1035 /* FIXME: This is actually larger than necessary, since not all of
1036 * the sink latency is actually rewritable. */
1037 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
1038 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
1040 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
1041 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
1042 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
1044 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
1045 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
1046 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
1048 if (s
->buffer_attr
.minreq
<= 0) {
1049 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
1050 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
1053 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
1054 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
1056 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
1058 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
1059 s
->buffer_attr
.prebuf
> max_prebuf
)
1060 s
->buffer_attr
.prebuf
= max_prebuf
;
1062 #ifdef PROTOCOL_NATIVE_DEBUG
1063 pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
1064 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1065 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1066 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1067 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
1071 /* Called from main context */
1072 static playback_stream
* playback_stream_new(
1073 pa_native_connection
*c
,
1076 pa_channel_map
*map
,
1081 pa_bool_t muted_set
,
1082 pa_sink_input_flags_t flags
,
1084 pa_bool_t adjust_latency
,
1085 pa_bool_t early_requests
,
1086 pa_bool_t relative_volume
,
1091 /* Note: This function takes ownership of the 'formats' param, so we need
1092 * to take extra care to not leak it */
1094 playback_stream
*ssync
;
1095 playback_stream
*s
= NULL
;
1096 pa_sink_input
*sink_input
= NULL
;
1097 pa_memchunk silence
;
1099 int64_t start_index
;
1100 pa_sink_input_new_data data
;
1101 char *memblockq_name
;
1109 /* Find syncid group */
1110 PA_IDXSET_FOREACH(ssync
, c
->output_streams
, idx
) {
1112 if (!playback_stream_isinstance(ssync
))
1115 if (ssync
->syncid
== syncid
)
1119 /* Synced streams must connect to the same sink */
1123 sink
= ssync
->sink_input
->sink
;
1124 else if (sink
!= ssync
->sink_input
->sink
) {
1125 *ret
= PA_ERR_INVALID
;
1130 pa_sink_input_new_data_init(&data
);
1132 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1133 data
.driver
= __FILE__
;
1134 data
.module
= c
->options
->module
;
1135 data
.client
= c
->client
;
1137 pa_sink_input_new_data_set_sink(&data
, sink
, FALSE
);
1138 if (pa_sample_spec_valid(ss
))
1139 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1140 if (pa_channel_map_valid(map
))
1141 pa_sink_input_new_data_set_channel_map(&data
, map
);
1143 pa_sink_input_new_data_set_formats(&data
, formats
);
1144 /* Ownership transferred to new_data, so we don't free it ourselves */
1148 pa_sink_input_new_data_set_volume(&data
, volume
);
1149 data
.volume_is_absolute
= !relative_volume
;
1150 data
.save_volume
= FALSE
;
1153 pa_sink_input_new_data_set_muted(&data
, muted
);
1154 data
.save_muted
= FALSE
;
1156 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1159 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1161 pa_sink_input_new_data_done(&data
);
1166 s
= pa_msgobject_new(playback_stream
);
1167 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1168 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1171 s
->sink_input
= sink_input
;
1172 s
->is_underrun
= TRUE
;
1173 s
->drain_request
= FALSE
;
1174 pa_atomic_store(&s
->missing
, 0);
1175 s
->buffer_attr_req
= *a
;
1176 s
->adjust_latency
= adjust_latency
;
1177 s
->early_requests
= early_requests
;
1178 pa_atomic_store(&s
->seek_or_post_in_queue
, 0);
1179 s
->seek_windex
= -1;
1181 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1182 s
->sink_input
->pop
= sink_input_pop_cb
;
1183 s
->sink_input
->process_underrun
= sink_input_process_underrun_cb
;
1184 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1185 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1186 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1187 s
->sink_input
->kill
= sink_input_kill_cb
;
1188 s
->sink_input
->moving
= sink_input_moving_cb
;
1189 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1190 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1191 s
->sink_input
->userdata
= s
;
1193 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1195 fix_playback_buffer_attr(s
);
1197 pa_sink_input_get_silence(sink_input
, &silence
);
1198 memblockq_name
= pa_sprintf_malloc("native protocol playback stream memblockq [%u]", s
->sink_input
->index
);
1199 s
->memblockq
= pa_memblockq_new(
1202 s
->buffer_attr
.maxlength
,
1203 s
->buffer_attr
.tlength
,
1204 &sink_input
->sample_spec
,
1205 s
->buffer_attr
.prebuf
,
1206 s
->buffer_attr
.minreq
,
1209 pa_xfree(memblockq_name
);
1210 pa_memblock_unref(silence
.memblock
);
1212 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1214 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1216 #ifdef PROTOCOL_NATIVE_DEBUG
1217 pa_log("missing original: %li", (long int) *missing
);
1220 *ss
= s
->sink_input
->sample_spec
;
1221 *map
= s
->sink_input
->channel_map
;
1223 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1225 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1226 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1227 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1228 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1229 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1231 pa_sink_input_put(s
->sink_input
);
1235 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
1240 /* Called from IO context */
1241 static void playback_stream_request_bytes(playback_stream
*s
) {
1243 int previous_missing
;
1245 playback_stream_assert_ref(s
);
1247 m
= pa_memblockq_pop_missing(s
->memblockq
);
1249 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1250 /* (unsigned long) m, */
1251 /* pa_memblockq_get_tlength(s->memblockq), */
1252 /* pa_memblockq_get_minreq(s->memblockq), */
1253 /* pa_memblockq_get_length(s->memblockq), */
1254 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1259 #ifdef PROTOCOL_NATIVE_DEBUG
1260 pa_log("request_bytes(%lu)", (unsigned long) m
);
1263 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1264 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1266 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1267 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1268 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1271 /* Called from main context */
1272 static void playback_stream_send_killed(playback_stream
*p
) {
1274 playback_stream_assert_ref(p
);
1276 t
= pa_tagstruct_new(NULL
, 0);
1277 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1278 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1279 pa_tagstruct_putu32(t
, p
->index
);
1280 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1283 /* Called from main context */
1284 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1285 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1286 pa_native_connection_assert_ref(c
);
1293 case CONNECTION_MESSAGE_REVOKE
:
1294 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1297 case CONNECTION_MESSAGE_RELEASE
:
1298 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1305 /* Called from main context */
1306 static void native_connection_unlink(pa_native_connection
*c
) {
1315 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1318 pa_native_options_unref(c
->options
);
1320 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1321 record_stream_unlink(r
);
1323 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1324 if (playback_stream_isinstance(o
))
1325 playback_stream_unlink(PLAYBACK_STREAM(o
));
1327 upload_stream_unlink(UPLOAD_STREAM(o
));
1329 if (c
->subscription
)
1330 pa_subscription_free(c
->subscription
);
1333 pa_pstream_unlink(c
->pstream
);
1335 if (c
->auth_timeout_event
) {
1336 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1337 c
->auth_timeout_event
= NULL
;
1340 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1342 pa_native_connection_unref(c
);
1345 /* Called from main context */
1346 static void native_connection_free(pa_object
*o
) {
1347 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1351 native_connection_unlink(c
);
1353 pa_idxset_free(c
->record_streams
, NULL
);
1354 pa_idxset_free(c
->output_streams
, NULL
);
1356 pa_pdispatch_unref(c
->pdispatch
);
1357 pa_pstream_unref(c
->pstream
);
1358 pa_client_free(c
->client
);
1363 /* Called from main context */
1364 static void native_connection_send_memblock(pa_native_connection
*c
) {
1368 start
= PA_IDXSET_INVALID
;
1372 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1375 if (start
== PA_IDXSET_INVALID
)
1376 start
= c
->rrobin_index
;
1377 else if (start
== c
->rrobin_index
)
1380 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1381 pa_memchunk schunk
= chunk
;
1383 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1384 schunk
.length
= r
->buffer_attr
.fragsize
;
1386 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1388 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1389 pa_memblock_unref(schunk
.memblock
);
1396 /*** sink input callbacks ***/
1398 /* Called from thread context */
1399 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1400 playback_stream_assert_ref(s
);
1402 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1404 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1406 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1408 if (pa_memblockq_is_readable(s
->memblockq
)) {
1410 /* We just ended an underrun, let's ask the sink
1411 * for a complete rewind rewrite */
1413 pa_log_debug("Requesting rewind due to end of underrun.");
1414 pa_sink_input_request_rewind(s
->sink_input
,
1415 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1416 s
->sink_input
->thread_info
.underrun_for
),
1417 FALSE
, TRUE
, FALSE
);
1423 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1425 if (indexw
< indexr
) {
1426 /* OK, the sink already asked for this data, so
1427 * let's have it ask us again */
1429 pa_log_debug("Requesting rewind due to rewrite.");
1430 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1434 playback_stream_request_bytes(s
);
1437 static void flush_write_no_account(pa_memblockq
*q
) {
1438 pa_memblockq_flush_write(q
, FALSE
);
1441 /* Called from thread context */
1442 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1443 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1446 pa_sink_input_assert_ref(i
);
1447 s
= PLAYBACK_STREAM(i
->userdata
);
1448 playback_stream_assert_ref(s
);
1452 case SINK_INPUT_MESSAGE_SEEK
:
1453 case SINK_INPUT_MESSAGE_POST_DATA
: {
1454 int64_t windex
= pa_memblockq_get_write_index(s
->memblockq
);
1456 if (code
== SINK_INPUT_MESSAGE_SEEK
) {
1457 /* The client side is incapable of accounting correctly
1458 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1459 * able to deal with that. */
1461 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1462 windex
= PA_MIN(windex
, pa_memblockq_get_write_index(s
->memblockq
));
1465 if (chunk
&& pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1466 if (pa_log_ratelimit(PA_LOG_WARN
))
1467 pa_log_warn("Failed to push data into queue");
1468 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1469 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1472 /* If more data is in queue, we rewind later instead. */
1473 if (s
->seek_windex
!= -1)
1474 windex
= PA_MIN(windex
, s
->seek_windex
);
1475 if (pa_atomic_dec(&s
->seek_or_post_in_queue
) > 1)
1476 s
->seek_windex
= windex
;
1478 s
->seek_windex
= -1;
1479 handle_seek(s
, windex
);
1484 case SINK_INPUT_MESSAGE_DRAIN
:
1485 case SINK_INPUT_MESSAGE_FLUSH
:
1486 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1487 case SINK_INPUT_MESSAGE_TRIGGER
: {
1490 pa_sink_input
*isync
;
1491 void (*func
)(pa_memblockq
*bq
);
1494 case SINK_INPUT_MESSAGE_FLUSH
:
1495 func
= flush_write_no_account
;
1498 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1499 func
= pa_memblockq_prebuf_force
;
1502 case SINK_INPUT_MESSAGE_DRAIN
:
1503 case SINK_INPUT_MESSAGE_TRIGGER
:
1504 func
= pa_memblockq_prebuf_disable
;
1508 pa_assert_not_reached();
1511 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1513 handle_seek(s
, windex
);
1515 /* Do the same for all other members in the sync group */
1516 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1517 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1518 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1519 func(ssync
->memblockq
);
1520 handle_seek(ssync
, windex
);
1523 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1524 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1525 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1526 func(ssync
->memblockq
);
1527 handle_seek(ssync
, windex
);
1530 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1531 if (!pa_memblockq_is_readable(s
->memblockq
))
1532 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1534 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1535 s
->drain_request
= TRUE
;
1542 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1543 /* Atomically get a snapshot of all timing parameters... */
1544 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1545 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1546 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1547 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1548 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1549 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1553 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1556 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1558 /* We enable prebuffering so that after CORKED -> RUNNING
1559 * transitions we don't have trouble with underruns in case the
1560 * buffer has too little data. This must not be done when draining
1561 * has been requested, however, otherwise the buffered audio would
1563 if (!s
->drain_request
)
1564 pa_memblockq_prebuf_force(s
->memblockq
);
1566 handle_seek(s
, windex
);
1568 /* Fall through to the default handler */
1572 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1573 pa_usec_t
*r
= userdata
;
1575 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1577 /* Fall through, the default handler will add in the extra
1578 * latency added by the resampler */
1582 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1583 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1584 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1589 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1593 static bool handle_input_underrun(playback_stream
*s
, bool force
) {
1596 if (pa_memblockq_is_readable(s
->memblockq
))
1599 if (!s
->is_underrun
)
1600 pa_log_debug("%s %s of '%s'", force
? "Actual" : "Implicit",
1601 s
->drain_request
? "drain" : "underrun", pa_strnull(pa_proplist_gets(s
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
)));
1603 send_drain
= s
->drain_request
&& (force
|| pa_sink_input_safe_to_remove(s
->sink_input
));
1606 s
->drain_request
= false;
1607 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
);
1608 pa_log_debug("Drain acknowledged of '%s'", pa_strnull(pa_proplist_gets(s
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
)));
1609 } else if (!s
->is_underrun
) {
1610 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, pa_memblockq_get_read_index(s
->memblockq
), NULL
, NULL
);
1612 s
->is_underrun
= true;
1613 playback_stream_request_bytes(s
);
1617 /* Called from thread context */
1618 static bool sink_input_process_underrun_cb(pa_sink_input
*i
) {
1621 pa_sink_input_assert_ref(i
);
1622 s
= PLAYBACK_STREAM(i
->userdata
);
1623 playback_stream_assert_ref(s
);
1625 return handle_input_underrun(s
, true);
1629 /* Called from thread context */
1630 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1633 pa_sink_input_assert_ref(i
);
1634 s
= PLAYBACK_STREAM(i
->userdata
);
1635 playback_stream_assert_ref(s
);
1638 #ifdef PROTOCOL_NATIVE_DEBUG
1639 pa_log("%s, pop(): %lu", pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
), (unsigned long) pa_memblockq_get_length(s
->memblockq
));
1642 if (!handle_input_underrun(s
, false))
1643 s
->is_underrun
= false;
1645 /* This call will not fail with prebuf=0, hence we check for
1646 underrun explicitly in handle_input_underrun */
1647 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1650 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1652 if (i
->thread_info
.underrun_for
> 0)
1653 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1655 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1656 playback_stream_request_bytes(s
);
1661 /* Called from thread context */
1662 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1665 pa_sink_input_assert_ref(i
);
1666 s
= PLAYBACK_STREAM(i
->userdata
);
1667 playback_stream_assert_ref(s
);
1669 /* If we are in an underrun, then we don't rewind */
1670 if (i
->thread_info
.underrun_for
> 0)
1673 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1676 /* Called from thread context */
1677 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1680 pa_sink_input_assert_ref(i
);
1681 s
= PLAYBACK_STREAM(i
->userdata
);
1682 playback_stream_assert_ref(s
);
1684 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1687 /* Called from thread context */
1688 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1690 size_t new_tlength
, old_tlength
;
1692 pa_sink_input_assert_ref(i
);
1693 s
= PLAYBACK_STREAM(i
->userdata
);
1694 playback_stream_assert_ref(s
);
1696 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1697 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1699 if (old_tlength
< new_tlength
) {
1700 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1701 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1702 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1704 if (new_tlength
== old_tlength
)
1705 pa_log_debug("Failed to increase tlength");
1707 pa_log_debug("Notifying client about increased tlength");
1708 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
);
1713 /* Called from main context */
1714 static void sink_input_kill_cb(pa_sink_input
*i
) {
1717 pa_sink_input_assert_ref(i
);
1718 s
= PLAYBACK_STREAM(i
->userdata
);
1719 playback_stream_assert_ref(s
);
1721 playback_stream_send_killed(s
);
1722 playback_stream_unlink(s
);
1725 /* Called from main context */
1726 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1730 pa_sink_input_assert_ref(i
);
1731 s
= PLAYBACK_STREAM(i
->userdata
);
1732 playback_stream_assert_ref(s
);
1734 if (s
->connection
->version
< 15)
1737 t
= pa_tagstruct_new(NULL
, 0);
1738 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1739 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1740 pa_tagstruct_putu32(t
, s
->index
);
1741 pa_tagstruct_puts(t
, event
);
1742 pa_tagstruct_put_proplist(t
, pl
);
1743 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1746 /* Called from main context */
1747 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1751 pa_sink_input_assert_ref(i
);
1752 s
= PLAYBACK_STREAM(i
->userdata
);
1753 playback_stream_assert_ref(s
);
1755 if (s
->connection
->version
< 12)
1758 t
= pa_tagstruct_new(NULL
, 0);
1759 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1760 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1761 pa_tagstruct_putu32(t
, s
->index
);
1762 pa_tagstruct_put_boolean(t
, suspend
);
1763 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1766 /* Called from main context */
1767 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1771 pa_sink_input_assert_ref(i
);
1772 s
= PLAYBACK_STREAM(i
->userdata
);
1773 playback_stream_assert_ref(s
);
1778 fix_playback_buffer_attr(s
);
1779 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1780 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1782 if (s
->connection
->version
< 12)
1785 t
= pa_tagstruct_new(NULL
, 0);
1786 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1787 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1788 pa_tagstruct_putu32(t
, s
->index
);
1789 pa_tagstruct_putu32(t
, dest
->index
);
1790 pa_tagstruct_puts(t
, dest
->name
);
1791 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1793 if (s
->connection
->version
>= 13) {
1794 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1795 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1796 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1797 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1798 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1801 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1804 /*** source_output callbacks ***/
1806 /* Called from thread context */
1807 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1808 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1811 pa_source_output_assert_ref(o
);
1812 s
= RECORD_STREAM(o
->userdata
);
1813 record_stream_assert_ref(s
);
1816 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1817 /* Atomically get a snapshot of all timing parameters... */
1818 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1819 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1820 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1824 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1827 /* Called from thread context */
1828 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1831 pa_source_output_assert_ref(o
);
1832 s
= RECORD_STREAM(o
->userdata
);
1833 record_stream_assert_ref(s
);
1836 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1837 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1840 static void source_output_kill_cb(pa_source_output
*o
) {
1843 pa_source_output_assert_ref(o
);
1844 s
= RECORD_STREAM(o
->userdata
);
1845 record_stream_assert_ref(s
);
1847 record_stream_send_killed(s
);
1848 record_stream_unlink(s
);
1851 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1854 pa_source_output_assert_ref(o
);
1855 s
= RECORD_STREAM(o
->userdata
);
1856 record_stream_assert_ref(s
);
1858 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1860 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1863 /* Called from main context */
1864 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1868 pa_source_output_assert_ref(o
);
1869 s
= RECORD_STREAM(o
->userdata
);
1870 record_stream_assert_ref(s
);
1872 if (s
->connection
->version
< 15)
1875 t
= pa_tagstruct_new(NULL
, 0);
1876 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1877 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1878 pa_tagstruct_putu32(t
, s
->index
);
1879 pa_tagstruct_puts(t
, event
);
1880 pa_tagstruct_put_proplist(t
, pl
);
1881 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1884 /* Called from main context */
1885 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1889 pa_source_output_assert_ref(o
);
1890 s
= RECORD_STREAM(o
->userdata
);
1891 record_stream_assert_ref(s
);
1893 if (s
->connection
->version
< 12)
1896 t
= pa_tagstruct_new(NULL
, 0);
1897 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1898 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1899 pa_tagstruct_putu32(t
, s
->index
);
1900 pa_tagstruct_put_boolean(t
, suspend
);
1901 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1904 /* Called from main context */
1905 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1909 pa_source_output_assert_ref(o
);
1910 s
= RECORD_STREAM(o
->userdata
);
1911 record_stream_assert_ref(s
);
1916 fix_record_buffer_attr_pre(s
);
1917 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1918 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1919 fix_record_buffer_attr_post(s
);
1921 if (s
->connection
->version
< 12)
1924 t
= pa_tagstruct_new(NULL
, 0);
1925 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1926 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1927 pa_tagstruct_putu32(t
, s
->index
);
1928 pa_tagstruct_putu32(t
, dest
->index
);
1929 pa_tagstruct_puts(t
, dest
->name
);
1930 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1932 if (s
->connection
->version
>= 13) {
1933 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1934 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1935 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1938 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1941 /*** pdispatch callbacks ***/
1943 static void protocol_error(pa_native_connection
*c
) {
1944 pa_log("protocol error, kicking client");
1945 native_connection_unlink(c
);
1948 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1949 if (!(expression)) { \
1950 pa_pstream_send_error((pstream), (tag), (error)); \
1955 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1956 if (!(expression)) { \
1957 pa_pstream_send_error((pstream), (tag), (error)); \
1962 static pa_tagstruct
*reply_new(uint32_t tag
) {
1963 pa_tagstruct
*reply
;
1965 reply
= pa_tagstruct_new(NULL
, 0);
1966 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1967 pa_tagstruct_putu32(reply
, tag
);
1971 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1972 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1974 uint32_t sink_index
, syncid
, missing
= 0;
1975 pa_buffer_attr attr
;
1976 const char *name
= NULL
, *sink_name
;
1979 pa_tagstruct
*reply
;
1980 pa_sink
*sink
= NULL
;
1988 fix_channels
= FALSE
,
1990 variable_rate
= FALSE
,
1992 adjust_latency
= FALSE
,
1993 early_requests
= FALSE
,
1994 dont_inhibit_auto_suspend
= FALSE
,
1997 fail_on_suspend
= FALSE
,
1998 relative_volume
= FALSE
,
1999 passthrough
= FALSE
;
2001 pa_sink_input_flags_t flags
= 0;
2002 pa_proplist
*p
= NULL
;
2003 int ret
= PA_ERR_INVALID
;
2004 uint8_t n_formats
= 0;
2005 pa_format_info
*format
;
2006 pa_idxset
*formats
= NULL
;
2009 pa_native_connection_assert_ref(c
);
2011 memset(&attr
, 0, sizeof(attr
));
2013 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2016 PA_TAG_SAMPLE_SPEC
, &ss
,
2017 PA_TAG_CHANNEL_MAP
, &map
,
2018 PA_TAG_U32
, &sink_index
,
2019 PA_TAG_STRING
, &sink_name
,
2020 PA_TAG_U32
, &attr
.maxlength
,
2021 PA_TAG_BOOLEAN
, &corked
,
2022 PA_TAG_U32
, &attr
.tlength
,
2023 PA_TAG_U32
, &attr
.prebuf
,
2024 PA_TAG_U32
, &attr
.minreq
,
2025 PA_TAG_U32
, &syncid
,
2026 PA_TAG_CVOLUME
, &volume
,
2027 PA_TAG_INVALID
) < 0) {
2033 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2034 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
, finish
);
2035 CHECK_VALIDITY_GOTO(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
, finish
);
2036 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2037 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2039 p
= pa_proplist_new();
2042 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2044 if (c
->version
>= 12) {
2045 /* Since 0.9.8 the user can ask for a couple of additional flags */
2047 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2048 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2049 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2050 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2051 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2052 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2053 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2060 if (c
->version
>= 13) {
2062 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2063 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2064 pa_tagstruct_get_proplist(t
, p
) < 0) {
2071 if (c
->version
>= 14) {
2073 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2074 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2081 if (c
->version
>= 15) {
2083 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2084 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2085 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2092 if (c
->version
>= 17) {
2094 if (pa_tagstruct_get_boolean(t
, &relative_volume
) < 0) {
2101 if (c
->version
>= 18) {
2103 if (pa_tagstruct_get_boolean(t
, &passthrough
) < 0 ) {
2109 if (c
->version
>= 21) {
2111 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2117 formats
= pa_idxset_new(NULL
, NULL
);
2119 for (i
= 0; i
< n_formats
; i
++) {
2120 format
= pa_format_info_new();
2121 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2125 pa_idxset_put(formats
, format
, NULL
);
2129 if (n_formats
== 0) {
2130 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2131 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2132 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2134 PA_IDXSET_FOREACH(format
, formats
, i
) {
2135 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2139 if (!pa_tagstruct_eof(t
)) {
2144 if (sink_index
!= PA_INVALID_INDEX
) {
2146 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
2147 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2151 } else if (sink_name
) {
2153 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
2154 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2160 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
2161 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
2162 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
2163 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
2164 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
2165 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
2166 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
2167 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
2168 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2169 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0) |
2170 (passthrough
? PA_SINK_INPUT_PASSTHROUGH
: 0);
2172 /* Only since protocol version 15 there's a separate muted_set
2173 * flag. For older versions we synthesize it here */
2174 muted_set
= muted_set
|| muted
;
2176 s
= playback_stream_new(c
, sink
, &ss
, &map
, formats
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, flags
, p
, adjust_latency
, early_requests
, relative_volume
, syncid
, &missing
, &ret
);
2177 /* We no longer own the formats idxset */
2180 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2182 reply
= reply_new(tag
);
2183 pa_tagstruct_putu32(reply
, s
->index
);
2184 pa_assert(s
->sink_input
);
2185 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
2186 pa_tagstruct_putu32(reply
, missing
);
2188 #ifdef PROTOCOL_NATIVE_DEBUG
2189 pa_log("initial request is %u", missing
);
2192 if (c
->version
>= 9) {
2193 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2195 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2196 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
2197 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2198 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2201 if (c
->version
>= 12) {
2202 /* Since 0.9.8 we support sending the chosen sample
2203 * spec/channel map/device/suspend status back to the
2206 pa_tagstruct_put_sample_spec(reply
, &ss
);
2207 pa_tagstruct_put_channel_map(reply
, &map
);
2209 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2210 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2212 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2215 if (c
->version
>= 13)
2216 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2218 if (c
->version
>= 21) {
2219 /* Send back the format we negotiated */
2220 if (s
->sink_input
->format
)
2221 pa_tagstruct_put_format_info(reply
, s
->sink_input
->format
);
2223 pa_format_info
*f
= pa_format_info_new();
2224 pa_tagstruct_put_format_info(reply
, f
);
2225 pa_format_info_free(f
);
2229 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2233 pa_proplist_free(p
);
2235 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
2238 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2239 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2242 pa_native_connection_assert_ref(c
);
2245 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2246 !pa_tagstruct_eof(t
)) {
2251 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2255 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2257 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2258 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2262 playback_stream_unlink(s
);
2266 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2268 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2269 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2273 record_stream_unlink(s
);
2277 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2280 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2281 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2285 upload_stream_unlink(s
);
2290 pa_assert_not_reached();
2293 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2296 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2297 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2299 pa_buffer_attr attr
;
2300 uint32_t source_index
;
2301 const char *name
= NULL
, *source_name
;
2304 pa_tagstruct
*reply
;
2305 pa_source
*source
= NULL
;
2313 fix_channels
= FALSE
,
2315 variable_rate
= FALSE
,
2317 adjust_latency
= FALSE
,
2318 peak_detect
= FALSE
,
2319 early_requests
= FALSE
,
2320 dont_inhibit_auto_suspend
= FALSE
,
2323 fail_on_suspend
= FALSE
,
2324 relative_volume
= FALSE
,
2325 passthrough
= FALSE
;
2327 pa_source_output_flags_t flags
= 0;
2328 pa_proplist
*p
= NULL
;
2329 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2330 pa_sink_input
*direct_on_input
= NULL
;
2331 int ret
= PA_ERR_INVALID
;
2332 uint8_t n_formats
= 0;
2333 pa_format_info
*format
;
2334 pa_idxset
*formats
= NULL
;
2337 pa_native_connection_assert_ref(c
);
2340 memset(&attr
, 0, sizeof(attr
));
2342 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2343 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2344 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2345 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2346 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2347 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2348 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2349 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2355 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2356 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
, finish
);
2357 CHECK_VALIDITY_GOTO(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
, finish
);
2358 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2360 p
= pa_proplist_new();
2363 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2365 if (c
->version
>= 12) {
2366 /* Since 0.9.8 the user can ask for a couple of additional flags */
2368 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2369 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2370 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2371 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2372 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2373 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2374 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2381 if (c
->version
>= 13) {
2383 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2384 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2385 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2386 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2393 if (c
->version
>= 14) {
2395 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2401 if (c
->version
>= 15) {
2403 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2404 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2411 if (c
->version
>= 22) {
2412 /* For newer client versions (with per-source-output volumes), we try
2413 * to make the behaviour for playback and record streams the same. */
2416 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2422 formats
= pa_idxset_new(NULL
, NULL
);
2424 for (i
= 0; i
< n_formats
; i
++) {
2425 format
= pa_format_info_new();
2426 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2430 pa_idxset_put(formats
, format
, NULL
);
2433 if (pa_tagstruct_get_cvolume(t
, &volume
) < 0 ||
2434 pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2435 pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2436 pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2437 pa_tagstruct_get_boolean(t
, &relative_volume
) < 0 ||
2438 pa_tagstruct_get_boolean(t
, &passthrough
) < 0) {
2444 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2447 if (n_formats
== 0) {
2448 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2449 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2450 CHECK_VALIDITY_GOTO(c
->pstream
, c
->version
< 22 || (volume
.channels
== ss
.channels
), tag
, PA_ERR_INVALID
, finish
);
2451 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2453 PA_IDXSET_FOREACH(format
, formats
, i
) {
2454 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2459 if (!pa_tagstruct_eof(t
)) {
2464 if (source_index
!= PA_INVALID_INDEX
) {
2466 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2467 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2471 } else if (source_name
) {
2473 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2474 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2479 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2481 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2482 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2488 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2489 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2490 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2491 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2492 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2493 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2494 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2495 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2496 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2497 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0) |
2498 (passthrough
? PA_SOURCE_OUTPUT_PASSTHROUGH
: 0);
2500 s
= record_stream_new(c
, source
, &ss
, &map
, formats
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, flags
, p
, adjust_latency
, early_requests
, relative_volume
, peak_detect
, direct_on_input
, &ret
);
2502 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2504 reply
= reply_new(tag
);
2505 pa_tagstruct_putu32(reply
, s
->index
);
2506 pa_assert(s
->source_output
);
2507 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2509 if (c
->version
>= 9) {
2510 /* Since 0.9 we support sending the buffer metrics back to the client */
2512 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2513 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2516 if (c
->version
>= 12) {
2517 /* Since 0.9.8 we support sending the chosen sample
2518 * spec/channel map/device/suspend status back to the
2521 pa_tagstruct_put_sample_spec(reply
, &ss
);
2522 pa_tagstruct_put_channel_map(reply
, &map
);
2524 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2525 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2527 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2530 if (c
->version
>= 13)
2531 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2533 if (c
->version
>= 22) {
2534 /* Send back the format we negotiated */
2535 if (s
->source_output
->format
)
2536 pa_tagstruct_put_format_info(reply
, s
->source_output
->format
);
2538 pa_format_info
*f
= pa_format_info_new();
2539 pa_tagstruct_put_format_info(reply
, f
);
2540 pa_format_info_free(f
);
2544 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2548 pa_proplist_free(p
);
2550 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
2553 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2554 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2557 pa_native_connection_assert_ref(c
);
2560 if (!pa_tagstruct_eof(t
)) {
2565 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2566 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2567 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2569 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2571 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2574 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2575 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2577 pa_tagstruct
*reply
;
2578 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2580 pa_native_connection_assert_ref(c
);
2583 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2584 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2585 !pa_tagstruct_eof(t
)) {
2590 /* Minimum supported version */
2591 if (c
->version
< 8) {
2592 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2596 /* Starting with protocol version 13 the MSB of the version tag
2597 reflects if shm is available for this pa_native_connection or
2599 if (c
->version
>= 13) {
2600 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2601 c
->version
&= 0x7FFFFFFFU
;
2604 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2606 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2608 if (!c
->authorized
) {
2609 pa_bool_t success
= FALSE
;
2612 const pa_creds
*creds
;
2614 if ((creds
= pa_pdispatch_creds(pd
))) {
2615 if (creds
->uid
== getuid())
2617 else if (c
->options
->auth_group
) {
2621 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2622 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2623 else if (gid
== creds
->gid
)
2627 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2628 pa_log_warn("Failed to check group membership.");
2634 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2635 (unsigned long) creds
->uid
,
2636 (unsigned long) creds
->gid
,
2641 if (!success
&& c
->options
->auth_cookie
) {
2644 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2645 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2650 pa_log_warn("Denied access to client with invalid authorization data.");
2651 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2655 c
->authorized
= TRUE
;
2656 if (c
->auth_timeout_event
) {
2657 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2658 c
->auth_timeout_event
= NULL
;
2662 /* Enable shared memory support if possible */
2664 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2667 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2670 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2675 /* Only enable SHM if both sides are owned by the same
2676 * user. This is a security measure because otherwise data
2677 * private to the user might leak. */
2679 const pa_creds
*creds
;
2680 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2685 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2686 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2688 reply
= reply_new(tag
);
2689 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2693 /* SHM support is only enabled after both sides made sure they are the same user. */
2697 ucred
.uid
= getuid();
2698 ucred
.gid
= getgid();
2700 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2703 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2707 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2708 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2709 const char *name
= NULL
;
2711 pa_tagstruct
*reply
;
2713 pa_native_connection_assert_ref(c
);
2716 p
= pa_proplist_new();
2718 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2719 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2720 !pa_tagstruct_eof(t
)) {
2723 pa_proplist_free(p
);
2728 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2729 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2730 pa_proplist_free(p
);
2734 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2735 pa_proplist_free(p
);
2737 reply
= reply_new(tag
);
2739 if (c
->version
>= 13)
2740 pa_tagstruct_putu32(reply
, c
->client
->index
);
2742 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2745 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2746 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2748 uint32_t idx
= PA_IDXSET_INVALID
;
2750 pa_native_connection_assert_ref(c
);
2753 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2754 !pa_tagstruct_eof(t
)) {
2759 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2760 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
);
2762 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2764 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2768 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2769 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2770 idx
= source
->index
;
2773 if (idx
== PA_IDXSET_INVALID
)
2774 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2776 pa_tagstruct
*reply
;
2777 reply
= reply_new(tag
);
2778 pa_tagstruct_putu32(reply
, idx
);
2779 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2783 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2784 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2788 pa_native_connection_assert_ref(c
);
2791 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2792 !pa_tagstruct_eof(t
)) {
2797 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2798 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2799 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2800 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2802 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
);
2805 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2806 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2807 pa_tagstruct
*reply
;
2808 const pa_mempool_stat
*stat
;
2810 pa_native_connection_assert_ref(c
);
2813 if (!pa_tagstruct_eof(t
)) {
2818 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2820 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2822 reply
= reply_new(tag
);
2823 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2824 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2825 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2826 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2827 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2828 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2831 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2832 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2833 pa_tagstruct
*reply
;
2835 struct timeval tv
, now
;
2838 pa_native_connection_assert_ref(c
);
2841 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2842 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2843 !pa_tagstruct_eof(t
)) {
2848 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2849 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2850 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2851 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2853 /* Get an atomic snapshot of all timing parameters */
2854 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);
2856 reply
= reply_new(tag
);
2857 pa_tagstruct_put_usec(reply
,
2858 s
->current_sink_latency
+
2859 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2860 pa_tagstruct_put_usec(reply
, 0);
2861 pa_tagstruct_put_boolean(reply
,
2862 s
->playing_for
> 0 &&
2863 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2864 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2865 pa_tagstruct_put_timeval(reply
, &tv
);
2866 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2867 pa_tagstruct_puts64(reply
, s
->write_index
);
2868 pa_tagstruct_puts64(reply
, s
->read_index
);
2870 if (c
->version
>= 13) {
2871 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2872 pa_tagstruct_putu64(reply
, s
->playing_for
);
2875 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2878 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2879 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2880 pa_tagstruct
*reply
;
2882 struct timeval tv
, now
;
2885 pa_native_connection_assert_ref(c
);
2888 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2889 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2890 !pa_tagstruct_eof(t
)) {
2895 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2896 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2897 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2899 /* Get an atomic snapshot of all timing parameters */
2900 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);
2902 reply
= reply_new(tag
);
2903 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2904 pa_tagstruct_put_usec(reply
,
2905 s
->current_source_latency
+
2906 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->source
->sample_spec
));
2907 pa_tagstruct_put_boolean(reply
,
2908 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2909 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2910 pa_tagstruct_put_timeval(reply
, &tv
);
2911 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2912 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2913 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2914 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2917 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2918 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2921 const char *name
= NULL
;
2924 pa_tagstruct
*reply
;
2927 pa_native_connection_assert_ref(c
);
2930 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2931 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2932 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2933 pa_tagstruct_getu32(t
, &length
) < 0) {
2938 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2939 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2940 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2941 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2942 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2943 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2945 p
= pa_proplist_new();
2947 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2948 !pa_tagstruct_eof(t
)) {
2951 pa_proplist_free(p
);
2955 if (c
->version
< 13)
2956 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2958 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2959 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2961 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2962 pa_proplist_free(p
);
2963 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2966 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2967 pa_proplist_free(p
);
2969 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2971 reply
= reply_new(tag
);
2972 pa_tagstruct_putu32(reply
, s
->index
);
2973 pa_tagstruct_putu32(reply
, length
);
2974 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2977 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2978 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2983 pa_native_connection_assert_ref(c
);
2986 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2987 !pa_tagstruct_eof(t
)) {
2992 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2994 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2995 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2996 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2998 if (!s
->memchunk
.memblock
)
2999 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
3000 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
3001 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
3003 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3005 upload_stream_unlink(s
);
3008 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3009 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3010 uint32_t sink_index
;
3013 const char *name
, *sink_name
;
3016 pa_tagstruct
*reply
;
3018 pa_native_connection_assert_ref(c
);
3021 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3023 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
3024 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
3025 pa_tagstruct_getu32(t
, &volume
) < 0 ||
3026 pa_tagstruct_gets(t
, &name
) < 0) {
3031 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
3032 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
3033 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3034 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3036 if (sink_index
!= PA_INVALID_INDEX
)
3037 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
3039 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
3041 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3043 p
= pa_proplist_new();
3045 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
3046 !pa_tagstruct_eof(t
)) {
3048 pa_proplist_free(p
);
3052 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
3054 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
3055 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3056 pa_proplist_free(p
);
3060 pa_proplist_free(p
);
3062 reply
= reply_new(tag
);
3064 if (c
->version
>= 13)
3065 pa_tagstruct_putu32(reply
, idx
);
3067 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3070 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3071 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3074 pa_native_connection_assert_ref(c
);
3077 if (pa_tagstruct_gets(t
, &name
) < 0 ||
3078 !pa_tagstruct_eof(t
)) {
3083 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3084 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3086 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
3087 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3091 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3094 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
3097 pa_assert(original
);
3101 if (c
->version
< 12) {
3102 /* Before protocol version 12 we didn't support S32 samples,
3103 * so we need to lie about this to the client */
3105 if (fixed
->format
== PA_SAMPLE_S32LE
)
3106 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3107 if (fixed
->format
== PA_SAMPLE_S32BE
)
3108 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3111 if (c
->version
< 15) {
3112 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
3113 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3114 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
3115 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3119 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
3120 pa_sample_spec fixed_ss
;
3123 pa_sink_assert_ref(sink
);
3125 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
3129 PA_TAG_U32
, sink
->index
,
3130 PA_TAG_STRING
, sink
->name
,
3131 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3132 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3133 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
3134 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
3135 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
3136 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
3137 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
3138 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
3139 PA_TAG_USEC
, pa_sink_get_latency(sink
),
3140 PA_TAG_STRING
, sink
->driver
,
3141 PA_TAG_U32
, sink
->flags
& PA_SINK_CLIENT_FLAGS_MASK
,
3144 if (c
->version
>= 13) {
3145 pa_tagstruct_put_proplist(t
, sink
->proplist
);
3146 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
3149 if (c
->version
>= 15) {
3150 pa_tagstruct_put_volume(t
, sink
->base_volume
);
3151 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
3152 pa_log_error("Internal sink state is invalid.");
3153 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
3154 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
3155 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
3158 if (c
->version
>= 16) {
3162 pa_tagstruct_putu32(t
, pa_hashmap_size(sink
->ports
));
3164 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
3165 pa_tagstruct_puts(t
, p
->name
);
3166 pa_tagstruct_puts(t
, p
->description
);
3167 pa_tagstruct_putu32(t
, p
->priority
);
3168 if (c
->version
>= 24)
3169 pa_tagstruct_putu32(t
, p
->available
);
3172 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
3175 if (c
->version
>= 21) {
3178 pa_idxset
*formats
= pa_sink_get_formats(sink
);
3180 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3181 PA_IDXSET_FOREACH(f
, formats
, i
) {
3182 pa_tagstruct_put_format_info(t
, f
);
3185 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
3189 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
3190 pa_sample_spec fixed_ss
;
3193 pa_source_assert_ref(source
);
3195 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
3199 PA_TAG_U32
, source
->index
,
3200 PA_TAG_STRING
, source
->name
,
3201 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3202 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3203 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
3204 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
3205 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
3206 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
3207 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
3208 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
3209 PA_TAG_USEC
, pa_source_get_latency(source
),
3210 PA_TAG_STRING
, source
->driver
,
3211 PA_TAG_U32
, source
->flags
& PA_SOURCE_CLIENT_FLAGS_MASK
,
3214 if (c
->version
>= 13) {
3215 pa_tagstruct_put_proplist(t
, source
->proplist
);
3216 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
3219 if (c
->version
>= 15) {
3220 pa_tagstruct_put_volume(t
, source
->base_volume
);
3221 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
3222 pa_log_error("Internal source state is invalid.");
3223 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
3224 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
3225 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
3228 if (c
->version
>= 16) {
3232 pa_tagstruct_putu32(t
, pa_hashmap_size(source
->ports
));
3234 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
3235 pa_tagstruct_puts(t
, p
->name
);
3236 pa_tagstruct_puts(t
, p
->description
);
3237 pa_tagstruct_putu32(t
, p
->priority
);
3238 if (c
->version
>= 24)
3239 pa_tagstruct_putu32(t
, p
->available
);
3242 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
3245 if (c
->version
>= 22) {
3248 pa_idxset
*formats
= pa_source_get_formats(source
);
3250 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3251 PA_IDXSET_FOREACH(f
, formats
, i
) {
3252 pa_tagstruct_put_format_info(t
, f
);
3255 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
3259 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
3263 pa_tagstruct_putu32(t
, client
->index
);
3264 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
3265 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
3266 pa_tagstruct_puts(t
, client
->driver
);
3268 if (c
->version
>= 13)
3269 pa_tagstruct_put_proplist(t
, client
->proplist
);
3272 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
3275 pa_device_port
*port
;
3280 pa_tagstruct_putu32(t
, card
->index
);
3281 pa_tagstruct_puts(t
, card
->name
);
3282 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
3283 pa_tagstruct_puts(t
, card
->driver
);
3285 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->profiles
));
3287 PA_HASHMAP_FOREACH(p
, card
->profiles
, state
) {
3288 pa_tagstruct_puts(t
, p
->name
);
3289 pa_tagstruct_puts(t
, p
->description
);
3290 pa_tagstruct_putu32(t
, p
->n_sinks
);
3291 pa_tagstruct_putu32(t
, p
->n_sources
);
3292 pa_tagstruct_putu32(t
, p
->priority
);
3295 pa_tagstruct_puts(t
, card
->active_profile
->name
);
3296 pa_tagstruct_put_proplist(t
, card
->proplist
);
3298 if (c
->version
< 26)
3301 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->ports
));
3303 PA_HASHMAP_FOREACH(port
, card
->ports
, state
) {
3306 pa_tagstruct_puts(t
, port
->name
);
3307 pa_tagstruct_puts(t
, port
->description
);
3308 pa_tagstruct_putu32(t
, port
->priority
);
3309 pa_tagstruct_putu32(t
, port
->available
);
3310 pa_tagstruct_putu8(t
, port
->direction
);
3311 pa_tagstruct_put_proplist(t
, port
->proplist
);
3313 pa_tagstruct_putu32(t
, pa_hashmap_size(port
->profiles
));
3315 PA_HASHMAP_FOREACH(p
, port
->profiles
, state2
)
3316 pa_tagstruct_puts(t
, p
->name
);
3318 if (c
->version
>= 27)
3319 pa_tagstruct_puts64(t
, port
->latency_offset
);
3323 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
3327 pa_tagstruct_putu32(t
, module
->index
);
3328 pa_tagstruct_puts(t
, module
->name
);
3329 pa_tagstruct_puts(t
, module
->argument
);
3330 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3332 if (c
->version
< 15)
3333 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3335 if (c
->version
>= 15)
3336 pa_tagstruct_put_proplist(t
, module
->proplist
);
3339 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3340 pa_sample_spec fixed_ss
;
3341 pa_usec_t sink_latency
;
3343 pa_bool_t has_volume
= FALSE
;
3346 pa_sink_input_assert_ref(s
);
3348 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3350 has_volume
= pa_sink_input_is_volume_readable(s
);
3352 pa_sink_input_get_volume(s
, &v
, TRUE
);
3354 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3356 pa_tagstruct_putu32(t
, s
->index
);
3357 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3358 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3359 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3360 pa_tagstruct_putu32(t
, s
->sink
->index
);
3361 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3362 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3363 pa_tagstruct_put_cvolume(t
, &v
);
3364 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3365 pa_tagstruct_put_usec(t
, sink_latency
);
3366 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3367 pa_tagstruct_puts(t
, s
->driver
);
3368 if (c
->version
>= 11)
3369 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3370 if (c
->version
>= 13)
3371 pa_tagstruct_put_proplist(t
, s
->proplist
);
3372 if (c
->version
>= 19)
3373 pa_tagstruct_put_boolean(t
, (pa_sink_input_get_state(s
) == PA_SINK_INPUT_CORKED
));
3374 if (c
->version
>= 20) {
3375 pa_tagstruct_put_boolean(t
, has_volume
);
3376 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3378 if (c
->version
>= 21)
3379 pa_tagstruct_put_format_info(t
, s
->format
);
3382 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3383 pa_sample_spec fixed_ss
;
3384 pa_usec_t source_latency
;
3386 pa_bool_t has_volume
= FALSE
;
3389 pa_source_output_assert_ref(s
);
3391 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3393 has_volume
= pa_source_output_is_volume_readable(s
);
3395 pa_source_output_get_volume(s
, &v
, TRUE
);
3397 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3399 pa_tagstruct_putu32(t
, s
->index
);
3400 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3401 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3402 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3403 pa_tagstruct_putu32(t
, s
->source
->index
);
3404 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3405 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3406 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3407 pa_tagstruct_put_usec(t
, source_latency
);
3408 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3409 pa_tagstruct_puts(t
, s
->driver
);
3410 if (c
->version
>= 13)
3411 pa_tagstruct_put_proplist(t
, s
->proplist
);
3412 if (c
->version
>= 19)
3413 pa_tagstruct_put_boolean(t
, (pa_source_output_get_state(s
) == PA_SOURCE_OUTPUT_CORKED
));
3414 if (c
->version
>= 22) {
3415 pa_tagstruct_put_cvolume(t
, &v
);
3416 pa_tagstruct_put_boolean(t
, pa_source_output_get_mute(s
));
3417 pa_tagstruct_put_boolean(t
, has_volume
);
3418 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3419 pa_tagstruct_put_format_info(t
, s
->format
);
3423 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3424 pa_sample_spec fixed_ss
;
3430 if (e
->memchunk
.memblock
)
3431 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3433 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3435 pa_tagstruct_putu32(t
, e
->index
);
3436 pa_tagstruct_puts(t
, e
->name
);
3438 if (e
->volume_is_set
)
3441 pa_cvolume_init(&v
);
3443 pa_tagstruct_put_cvolume(t
, &v
);
3444 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3445 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3446 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3447 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3448 pa_tagstruct_put_boolean(t
, e
->lazy
);
3449 pa_tagstruct_puts(t
, e
->filename
);
3451 if (c
->version
>= 13)
3452 pa_tagstruct_put_proplist(t
, e
->proplist
);
3455 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3456 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3458 pa_sink
*sink
= NULL
;
3459 pa_source
*source
= NULL
;
3460 pa_client
*client
= NULL
;
3461 pa_card
*card
= NULL
;
3462 pa_module
*module
= NULL
;
3463 pa_sink_input
*si
= NULL
;
3464 pa_source_output
*so
= NULL
;
3465 pa_scache_entry
*sce
= NULL
;
3466 const char *name
= NULL
;
3467 pa_tagstruct
*reply
;
3469 pa_native_connection_assert_ref(c
);
3472 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3473 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3474 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3475 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3476 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3477 pa_tagstruct_gets(t
, &name
) < 0) ||
3478 !pa_tagstruct_eof(t
)) {
3483 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3484 CHECK_VALIDITY(c
->pstream
, !name
||
3485 (command
== PA_COMMAND_GET_SINK_INFO
&&
3486 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3487 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3488 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3489 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3490 CHECK_VALIDITY(c
->pstream
, command
== PA_COMMAND_GET_SINK_INFO
||
3491 command
== PA_COMMAND_GET_SOURCE_INFO
||
3492 (idx
!= PA_INVALID_INDEX
|| name
), tag
, PA_ERR_INVALID
);
3493 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3494 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3496 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3497 if (idx
!= PA_INVALID_INDEX
)
3498 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3500 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3501 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3502 if (idx
!= PA_INVALID_INDEX
)
3503 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3505 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3506 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3507 if (idx
!= PA_INVALID_INDEX
)
3508 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3510 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3511 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3512 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3513 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3514 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3515 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3516 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3517 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3518 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3520 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3521 if (idx
!= PA_INVALID_INDEX
)
3522 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3524 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3527 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3528 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3532 reply
= reply_new(tag
);
3534 sink_fill_tagstruct(c
, reply
, sink
);
3536 source_fill_tagstruct(c
, reply
, source
);
3538 client_fill_tagstruct(c
, reply
, client
);
3540 card_fill_tagstruct(c
, reply
, card
);
3542 module_fill_tagstruct(c
, reply
, module
);
3544 sink_input_fill_tagstruct(c
, reply
, si
);
3546 source_output_fill_tagstruct(c
, reply
, so
);
3548 scache_fill_tagstruct(c
, reply
, sce
);
3549 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3552 static void command_get_info_list(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_tagstruct
*reply
;
3559 pa_native_connection_assert_ref(c
);
3562 if (!pa_tagstruct_eof(t
)) {
3567 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3569 reply
= reply_new(tag
);
3571 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3572 i
= c
->protocol
->core
->sinks
;
3573 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3574 i
= c
->protocol
->core
->sources
;
3575 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3576 i
= c
->protocol
->core
->clients
;
3577 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3578 i
= c
->protocol
->core
->cards
;
3579 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3580 i
= c
->protocol
->core
->modules
;
3581 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3582 i
= c
->protocol
->core
->sink_inputs
;
3583 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3584 i
= c
->protocol
->core
->source_outputs
;
3586 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3587 i
= c
->protocol
->core
->scache
;
3591 PA_IDXSET_FOREACH(p
, i
, idx
) {
3592 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3593 sink_fill_tagstruct(c
, reply
, p
);
3594 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3595 source_fill_tagstruct(c
, reply
, p
);
3596 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3597 client_fill_tagstruct(c
, reply
, p
);
3598 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3599 card_fill_tagstruct(c
, reply
, p
);
3600 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3601 module_fill_tagstruct(c
, reply
, p
);
3602 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3603 sink_input_fill_tagstruct(c
, reply
, p
);
3604 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3605 source_output_fill_tagstruct(c
, reply
, p
);
3607 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3608 scache_fill_tagstruct(c
, reply
, p
);
3613 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3616 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3617 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3618 pa_tagstruct
*reply
;
3620 pa_source
*def_source
;
3621 pa_sample_spec fixed_ss
;
3624 pa_native_connection_assert_ref(c
);
3627 if (!pa_tagstruct_eof(t
)) {
3632 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3634 reply
= reply_new(tag
);
3635 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3636 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3638 u
= pa_get_user_name_malloc();
3639 pa_tagstruct_puts(reply
, u
);
3642 h
= pa_get_host_name_malloc();
3643 pa_tagstruct_puts(reply
, h
);
3646 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3647 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3649 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3650 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3651 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3652 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3654 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3656 if (c
->version
>= 15)
3657 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3659 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3662 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3664 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3666 pa_native_connection_assert_ref(c
);
3668 t
= pa_tagstruct_new(NULL
, 0);
3669 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3670 pa_tagstruct_putu32(t
, (uint32_t) -1);
3671 pa_tagstruct_putu32(t
, e
);
3672 pa_tagstruct_putu32(t
, idx
);
3673 pa_pstream_send_tagstruct(c
->pstream
, t
);
3676 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3677 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3678 pa_subscription_mask_t m
;
3680 pa_native_connection_assert_ref(c
);
3683 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3684 !pa_tagstruct_eof(t
)) {
3689 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3690 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3692 if (c
->subscription
)
3693 pa_subscription_free(c
->subscription
);
3696 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3697 pa_assert(c
->subscription
);
3699 c
->subscription
= NULL
;
3701 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3704 static void command_set_volume(
3711 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3714 pa_sink
*sink
= NULL
;
3715 pa_source
*source
= NULL
;
3716 pa_sink_input
*si
= NULL
;
3717 pa_source_output
*so
= NULL
;
3718 const char *name
= NULL
;
3719 const char *client_name
;
3721 pa_native_connection_assert_ref(c
);
3724 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3725 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3726 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3727 pa_tagstruct_get_cvolume(t
, &volume
) ||
3728 !pa_tagstruct_eof(t
)) {
3733 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3734 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
);
3735 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3736 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3737 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3738 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3742 case PA_COMMAND_SET_SINK_VOLUME
:
3743 if (idx
!= PA_INVALID_INDEX
)
3744 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3746 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3749 case PA_COMMAND_SET_SOURCE_VOLUME
:
3750 if (idx
!= PA_INVALID_INDEX
)
3751 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3753 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3756 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3757 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3760 case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
:
3761 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3765 pa_assert_not_reached();
3768 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3770 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3773 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3775 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3776 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3777 } else if (source
) {
3778 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3780 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3781 pa_source_set_volume(source
, &volume
, TRUE
, TRUE
);
3783 CHECK_VALIDITY(c
->pstream
, si
->volume_writable
, tag
, PA_ERR_BADSTATE
);
3784 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3786 pa_log_debug("Client %s changes volume of sink input %s.",
3788 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3789 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3791 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &so
->sample_spec
), tag
, PA_ERR_INVALID
);
3793 pa_log_debug("Client %s changes volume of source output %s.",
3795 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3796 pa_source_output_set_volume(so
, &volume
, TRUE
, TRUE
);
3799 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3802 static void command_set_mute(
3809 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3812 pa_sink
*sink
= NULL
;
3813 pa_source
*source
= NULL
;
3814 pa_sink_input
*si
= NULL
;
3815 pa_source_output
*so
= NULL
;
3816 const char *name
= NULL
, *client_name
;
3818 pa_native_connection_assert_ref(c
);
3821 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3822 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3823 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3824 pa_tagstruct_get_boolean(t
, &mute
) ||
3825 !pa_tagstruct_eof(t
)) {
3830 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3831 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
);
3832 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3833 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3834 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3838 case PA_COMMAND_SET_SINK_MUTE
:
3839 if (idx
!= PA_INVALID_INDEX
)
3840 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3842 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3846 case PA_COMMAND_SET_SOURCE_MUTE
:
3847 if (idx
!= PA_INVALID_INDEX
)
3848 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3850 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3854 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3855 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3858 case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
:
3859 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3863 pa_assert_not_reached();
3866 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3868 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3871 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3872 pa_sink_set_mute(sink
, mute
, TRUE
);
3873 } else if (source
) {
3874 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3875 pa_source_set_mute(source
, mute
, TRUE
);
3877 pa_log_debug("Client %s changes mute of sink input %s.",
3879 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3880 pa_sink_input_set_mute(si
, mute
, TRUE
);
3882 pa_log_debug("Client %s changes mute of source output %s.",
3884 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3885 pa_source_output_set_mute(so
, mute
, TRUE
);
3888 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3891 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3892 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3897 pa_native_connection_assert_ref(c
);
3900 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3901 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3902 !pa_tagstruct_eof(t
)) {
3907 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3908 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3909 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3910 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3911 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3913 pa_sink_input_cork(s
->sink_input
, b
);
3916 s
->is_underrun
= TRUE
;
3918 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3921 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3922 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3926 pa_native_connection_assert_ref(c
);
3929 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3930 !pa_tagstruct_eof(t
)) {
3935 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3936 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3937 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3938 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3939 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3942 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3943 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3946 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3947 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3950 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3951 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3955 pa_assert_not_reached();
3958 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3961 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3962 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3967 pa_native_connection_assert_ref(c
);
3970 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3971 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3972 !pa_tagstruct_eof(t
)) {
3977 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3978 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3979 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3981 pa_source_output_cork(s
->source_output
, b
);
3982 pa_memblockq_prebuf_force(s
->memblockq
);
3983 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3986 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3987 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3991 pa_native_connection_assert_ref(c
);
3994 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3995 !pa_tagstruct_eof(t
)) {
4000 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4001 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4002 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4004 pa_memblockq_flush_read(s
->memblockq
);
4005 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4008 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4009 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4012 pa_tagstruct
*reply
;
4014 pa_native_connection_assert_ref(c
);
4017 memset(&a
, 0, sizeof(a
));
4019 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4024 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4026 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
4028 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
4030 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4031 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4032 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4034 if (pa_tagstruct_get(
4036 PA_TAG_U32
, &a
.maxlength
,
4037 PA_TAG_U32
, &a
.tlength
,
4038 PA_TAG_U32
, &a
.prebuf
,
4039 PA_TAG_U32
, &a
.minreq
,
4040 PA_TAG_INVALID
) < 0 ||
4041 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4042 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4043 !pa_tagstruct_eof(t
)) {
4048 s
->adjust_latency
= adjust_latency
;
4049 s
->early_requests
= early_requests
;
4050 s
->buffer_attr_req
= a
;
4052 fix_playback_buffer_attr(s
);
4053 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);
4055 reply
= reply_new(tag
);
4056 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4057 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
4058 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
4059 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
4061 if (c
->version
>= 13)
4062 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
4066 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
4067 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
4069 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4070 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4072 if (pa_tagstruct_get(
4074 PA_TAG_U32
, &a
.maxlength
,
4075 PA_TAG_U32
, &a
.fragsize
,
4076 PA_TAG_INVALID
) < 0 ||
4077 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4078 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4079 !pa_tagstruct_eof(t
)) {
4084 s
->adjust_latency
= adjust_latency
;
4085 s
->early_requests
= early_requests
;
4086 s
->buffer_attr_req
= a
;
4088 fix_record_buffer_attr_pre(s
);
4089 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
4090 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
4091 fix_record_buffer_attr_post(s
);
4093 reply
= reply_new(tag
);
4094 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4095 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
4097 if (c
->version
>= 13)
4098 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
4101 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4104 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4105 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4109 pa_native_connection_assert_ref(c
);
4112 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4113 pa_tagstruct_getu32(t
, &rate
) < 0 ||
4114 !pa_tagstruct_eof(t
)) {
4119 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4120 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
4122 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
4125 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4126 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4127 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4129 pa_sink_input_set_rate(s
->sink_input
, rate
);
4133 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
4135 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4136 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4138 pa_source_output_set_rate(s
->source_output
, rate
);
4141 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4144 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4145 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4150 pa_native_connection_assert_ref(c
);
4153 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4155 p
= pa_proplist_new();
4157 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
4159 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
4160 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4161 !pa_tagstruct_eof(t
)) {
4163 pa_proplist_free(p
);
4169 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4170 pa_tagstruct_getu32(t
, &mode
) < 0 ||
4171 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4172 !pa_tagstruct_eof(t
)) {
4174 pa_proplist_free(p
);
4179 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
4180 pa_proplist_free(p
);
4181 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
4184 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
4187 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4188 if (!s
|| !playback_stream_isinstance(s
)) {
4189 pa_proplist_free(p
);
4190 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4192 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
4194 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
4197 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
4198 pa_proplist_free(p
);
4199 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4201 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
4204 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
4206 pa_client_update_proplist(c
->client
, mode
, p
);
4209 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4210 pa_proplist_free(p
);
4213 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4214 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4216 unsigned changed
= 0;
4218 pa_strlist
*l
= NULL
;
4220 pa_native_connection_assert_ref(c
);
4223 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4225 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
4227 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4233 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4236 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4237 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4238 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4240 p
= s
->sink_input
->proplist
;
4242 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4245 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4246 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4248 p
= s
->source_output
->proplist
;
4250 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4252 p
= c
->client
->proplist
;
4258 if (pa_tagstruct_gets(t
, &k
) < 0) {
4267 l
= pa_strlist_prepend(l
, k
);
4270 if (!pa_tagstruct_eof(t
)) {
4279 l
= pa_strlist_pop(l
, &z
);
4284 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
4288 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4291 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4294 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4295 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
4297 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4300 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4301 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
4304 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4305 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
4310 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4311 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4314 pa_native_connection_assert_ref(c
);
4317 if (pa_tagstruct_gets(t
, &s
) < 0 ||
4318 !pa_tagstruct_eof(t
)) {
4323 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4324 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
4326 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
4329 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
4330 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4332 pa_namereg_set_default_source(c
->protocol
->core
, source
);
4335 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
4337 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
4338 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4340 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
4343 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4346 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4347 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4351 pa_native_connection_assert_ref(c
);
4354 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4355 pa_tagstruct_gets(t
, &name
) < 0 ||
4356 !pa_tagstruct_eof(t
)) {
4361 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4362 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4364 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
4367 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4368 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4369 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4371 pa_sink_input_set_name(s
->sink_input
, name
);
4375 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
4377 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4378 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4380 pa_source_output_set_name(s
->source_output
, name
);
4383 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4386 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4387 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4390 pa_native_connection_assert_ref(c
);
4393 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4394 !pa_tagstruct_eof(t
)) {
4399 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4401 if (command
== PA_COMMAND_KILL_CLIENT
) {
4404 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4405 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4407 pa_native_connection_ref(c
);
4408 pa_client_kill(client
);
4410 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4413 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4414 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4416 pa_native_connection_ref(c
);
4417 pa_sink_input_kill(s
);
4419 pa_source_output
*s
;
4421 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4423 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4424 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4426 pa_native_connection_ref(c
);
4427 pa_source_output_kill(s
);
4430 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4431 pa_native_connection_unref(c
);
4434 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4435 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4437 const char *name
, *argument
;
4438 pa_tagstruct
*reply
;
4440 pa_native_connection_assert_ref(c
);
4443 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4444 pa_tagstruct_gets(t
, &argument
) < 0 ||
4445 !pa_tagstruct_eof(t
)) {
4450 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4451 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4452 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4454 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4455 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4459 reply
= reply_new(tag
);
4460 pa_tagstruct_putu32(reply
, m
->index
);
4461 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4464 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4465 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4469 pa_native_connection_assert_ref(c
);
4472 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4473 !pa_tagstruct_eof(t
)) {
4478 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4479 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4480 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4482 pa_module_unload_request(m
, FALSE
);
4483 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4486 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4487 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4488 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4489 const char *name_device
= NULL
;
4491 pa_native_connection_assert_ref(c
);
4494 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4495 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4496 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4497 !pa_tagstruct_eof(t
)) {
4502 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4503 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4505 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
);
4506 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4507 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4508 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4510 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4511 pa_sink_input
*si
= NULL
;
4512 pa_sink
*sink
= NULL
;
4514 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4516 if (idx_device
!= PA_INVALID_INDEX
)
4517 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4519 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4521 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4523 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4524 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4528 pa_source_output
*so
= NULL
;
4531 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4533 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4535 if (idx_device
!= PA_INVALID_INDEX
)
4536 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4538 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4540 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4542 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4543 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4548 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4551 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4552 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4553 uint32_t idx
= PA_INVALID_INDEX
;
4554 const char *name
= NULL
;
4557 pa_native_connection_assert_ref(c
);
4560 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4561 pa_tagstruct_gets(t
, &name
) < 0 ||
4562 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4563 !pa_tagstruct_eof(t
)) {
4568 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4569 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
);
4570 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4571 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4572 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4574 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4576 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4578 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4580 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4581 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4585 pa_sink
*sink
= NULL
;
4587 if (idx
!= PA_INVALID_INDEX
)
4588 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4590 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4592 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4594 pa_log_debug("%s of sink %s requested by client %" PRIu32
".",
4595 b
? "Suspending" : "Resuming", sink
->name
, c
->client
->index
);
4597 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4598 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4604 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4606 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4608 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4610 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4611 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4618 if (idx
!= PA_INVALID_INDEX
)
4619 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4621 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4623 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4625 pa_log_debug("%s of source %s requested by client %" PRIu32
".",
4626 b
? "Suspending" : "Resuming", source
->name
, c
->client
->index
);
4628 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4629 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4635 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4638 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4639 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4640 uint32_t idx
= PA_INVALID_INDEX
;
4641 const char *name
= NULL
;
4643 pa_native_protocol_ext_cb_t cb
;
4645 pa_native_connection_assert_ref(c
);
4648 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4649 pa_tagstruct_gets(t
, &name
) < 0) {
4654 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4655 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4656 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4657 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4658 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4660 if (idx
!= PA_INVALID_INDEX
)
4661 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4663 PA_IDXSET_FOREACH(m
, c
->protocol
->core
->modules
, idx
)
4664 if (pa_streq(name
, m
->name
))
4667 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4668 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4670 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4671 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4673 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4677 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4678 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4679 uint32_t idx
= PA_INVALID_INDEX
;
4680 const char *name
= NULL
, *profile
= NULL
;
4681 pa_card
*card
= NULL
;
4684 pa_native_connection_assert_ref(c
);
4687 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4688 pa_tagstruct_gets(t
, &name
) < 0 ||
4689 pa_tagstruct_gets(t
, &profile
) < 0 ||
4690 !pa_tagstruct_eof(t
)) {
4695 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4696 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4697 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4698 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4699 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4701 if (idx
!= PA_INVALID_INDEX
)
4702 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4704 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4706 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4708 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4709 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4713 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4716 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4717 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4718 uint32_t idx
= PA_INVALID_INDEX
;
4719 const char *name
= NULL
, *port
= NULL
;
4722 pa_native_connection_assert_ref(c
);
4725 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4726 pa_tagstruct_gets(t
, &name
) < 0 ||
4727 pa_tagstruct_gets(t
, &port
) < 0 ||
4728 !pa_tagstruct_eof(t
)) {
4733 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4734 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
);
4735 CHECK_VALIDITY(c
->pstream
, (idx
!= PA_INVALID_INDEX
) ^ (name
!= NULL
), tag
, PA_ERR_INVALID
);
4736 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_INVALID
);
4738 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4741 if (idx
!= PA_INVALID_INDEX
)
4742 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4744 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4746 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4748 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4749 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4755 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4757 if (idx
!= PA_INVALID_INDEX
)
4758 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4760 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4762 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4764 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4765 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4770 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4773 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4774 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4775 const char *port_name
, *card_name
;
4776 uint32_t idx
= PA_INVALID_INDEX
;
4778 pa_card
*card
= NULL
;
4779 pa_device_port
*port
= NULL
;
4781 pa_native_connection_assert_ref(c
);
4784 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4785 pa_tagstruct_gets(t
, &card_name
) < 0 ||
4786 pa_tagstruct_gets(t
, &port_name
) < 0 ||
4787 pa_tagstruct_gets64(t
, &offset
) < 0 ||
4788 !pa_tagstruct_eof(t
)) {
4792 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4793 CHECK_VALIDITY(c
->pstream
, !card_name
|| pa_namereg_is_valid_name(card_name
), tag
, PA_ERR_INVALID
);
4794 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| card_name
, tag
, PA_ERR_INVALID
);
4795 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !card_name
, tag
, PA_ERR_INVALID
);
4796 CHECK_VALIDITY(c
->pstream
, port_name
, tag
, PA_ERR_INVALID
);
4798 if (idx
!= PA_INVALID_INDEX
)
4799 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4801 card
= pa_namereg_get(c
->protocol
->core
, card_name
, PA_NAMEREG_CARD
);
4803 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4805 port
= pa_hashmap_get(card
->ports
, port_name
);
4806 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_NOENTITY
);
4808 pa_device_port_set_latency_offset(port
, offset
);
4810 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4813 /*** pstream callbacks ***/
4815 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4816 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4820 pa_native_connection_assert_ref(c
);
4822 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4823 pa_log("invalid packet.");
4824 native_connection_unlink(c
);
4828 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
) {
4829 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4830 output_stream
*stream
;
4834 pa_native_connection_assert_ref(c
);
4836 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4837 pa_log_debug("Client sent block for invalid stream.");
4842 #ifdef PROTOCOL_NATIVE_DEBUG
4843 pa_log("got %lu bytes from client", (unsigned long) chunk
->length
);
4846 if (playback_stream_isinstance(stream
)) {
4847 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4849 pa_atomic_inc(&ps
->seek_or_post_in_queue
);
4850 if (chunk
->memblock
) {
4851 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4852 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
, chunk
, NULL
);
4854 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4856 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
);
4859 upload_stream
*u
= UPLOAD_STREAM(stream
);
4862 if (!u
->memchunk
.memblock
) {
4863 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4864 u
->memchunk
= *chunk
;
4865 pa_memblock_ref(u
->memchunk
.memblock
);
4868 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4869 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4873 pa_assert(u
->memchunk
.memblock
);
4876 if (l
> chunk
->length
)
4881 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4883 if (chunk
->memblock
) {
4885 src
= pa_memblock_acquire(chunk
->memblock
);
4887 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4888 (uint8_t*) src
+ chunk
->index
, l
);
4890 pa_memblock_release(chunk
->memblock
);
4892 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4894 pa_memblock_release(u
->memchunk
.memblock
);
4896 u
->memchunk
.length
+= l
;
4902 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4903 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4906 pa_native_connection_assert_ref(c
);
4908 native_connection_unlink(c
);
4909 pa_log_info("Connection died.");
4912 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4913 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4916 pa_native_connection_assert_ref(c
);
4918 native_connection_send_memblock(c
);
4921 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4924 if (!(q
= pa_thread_mq_get()))
4925 pa_pstream_send_revoke(p
, block_id
);
4927 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4930 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4933 if (!(q
= pa_thread_mq_get()))
4934 pa_pstream_send_release(p
, block_id
);
4936 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4939 /*** client callbacks ***/
4941 static void client_kill_cb(pa_client
*c
) {
4944 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4945 pa_log_info("Connection killed.");
4948 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4950 pa_native_connection
*c
;
4953 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4954 pa_native_connection_assert_ref(c
);
4956 if (c
->version
< 15)
4959 t
= pa_tagstruct_new(NULL
, 0);
4960 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4961 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4962 pa_tagstruct_puts(t
, event
);
4963 pa_tagstruct_put_proplist(t
, pl
);
4964 pa_pstream_send_tagstruct(c
->pstream
, t
);
4967 /*** module entry points ***/
4969 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4970 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4973 pa_native_connection_assert_ref(c
);
4974 pa_assert(c
->auth_timeout_event
== e
);
4976 if (!c
->authorized
) {
4977 native_connection_unlink(c
);
4978 pa_log_info("Connection terminated due to authentication timeout.");
4982 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4983 pa_native_connection
*c
;
4986 pa_client_new_data data
;
4992 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4993 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4994 pa_iochannel_free(io
);
4998 pa_client_new_data_init(&data
);
4999 data
.module
= o
->module
;
5000 data
.driver
= __FILE__
;
5001 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
5002 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
5003 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
5004 client
= pa_client_new(p
->core
, &data
);
5005 pa_client_new_data_done(&data
);
5010 c
= pa_msgobject_new(pa_native_connection
);
5011 c
->parent
.parent
.free
= native_connection_free
;
5012 c
->parent
.process_msg
= native_connection_process_msg
;
5014 c
->options
= pa_native_options_ref(o
);
5015 c
->authorized
= FALSE
;
5017 if (o
->auth_anonymous
) {
5018 pa_log_info("Client authenticated anonymously.");
5019 c
->authorized
= TRUE
;
5022 if (!c
->authorized
&&
5024 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
5026 pa_log_info("Client authenticated by IP ACL.");
5027 c
->authorized
= TRUE
;
5031 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
5033 c
->auth_timeout_event
= NULL
;
5035 c
->is_local
= pa_iochannel_socket_is_local(io
);
5039 c
->client
->kill
= client_kill_cb
;
5040 c
->client
->send_event
= client_send_event_cb
;
5041 c
->client
->userdata
= c
;
5043 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
5044 pa_pstream_set_receive_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
5045 pa_pstream_set_receive_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
5046 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
5047 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
5048 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
5049 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
5051 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
5053 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
5054 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
5056 c
->rrobin_index
= PA_IDXSET_INVALID
;
5057 c
->subscription
= NULL
;
5059 pa_idxset_put(p
->connections
, c
, NULL
);
5062 if (pa_iochannel_creds_supported(io
))
5063 pa_iochannel_creds_enable(io
);
5066 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
5069 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
5070 pa_native_connection
*c
;
5076 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
5077 if (c
->options
->module
== m
)
5078 native_connection_unlink(c
);
5081 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
5082 pa_native_protocol
*p
;
5087 p
= pa_xnew(pa_native_protocol
, 1);
5090 p
->connections
= pa_idxset_new(NULL
, NULL
);
5094 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
5096 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5097 pa_hook_init(&p
->hooks
[h
], p
);
5099 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
5104 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
5105 pa_native_protocol
*p
;
5107 if ((p
= pa_shared_get(c
, "native-protocol")))
5108 return pa_native_protocol_ref(p
);
5110 return native_protocol_new(c
);
5113 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
5115 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5122 void pa_native_protocol_unref(pa_native_protocol
*p
) {
5123 pa_native_connection
*c
;
5127 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5129 if (PA_REFCNT_DEC(p
) > 0)
5132 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
5133 native_connection_unlink(c
);
5135 pa_idxset_free(p
->connections
, NULL
);
5137 pa_strlist_free(p
->servers
);
5139 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5140 pa_hook_done(&p
->hooks
[h
]);
5142 pa_hashmap_free(p
->extensions
, NULL
);
5144 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
5149 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
5151 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5154 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
5156 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5159 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
5161 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5164 p
->servers
= pa_strlist_remove(p
->servers
, name
);
5166 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5169 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
5171 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5176 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
5178 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5183 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
5185 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5188 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
5190 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
5194 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
5196 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5199 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
5202 pa_native_options
* pa_native_options_new(void) {
5203 pa_native_options
*o
;
5205 o
= pa_xnew0(pa_native_options
, 1);
5211 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
5213 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5220 void pa_native_options_unref(pa_native_options
*o
) {
5222 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5224 if (PA_REFCNT_DEC(o
) > 0)
5227 pa_xfree(o
->auth_group
);
5230 pa_ip_acl_free(o
->auth_ip_acl
);
5233 pa_auth_cookie_unref(o
->auth_cookie
);
5238 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
5243 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5246 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
5247 pa_log("auth-anonymous= expects a boolean argument.");
5252 if (pa_modargs_get_value_boolean(ma
, "auth-group-enable", &enabled
) < 0) {
5253 pa_log("auth-group-enable= expects a boolean argument.");
5257 pa_xfree(o
->auth_group
);
5258 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
5262 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5265 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
5268 if (!(ipa
= pa_ip_acl_new(acl
))) {
5269 pa_log("Failed to parse IP ACL '%s'", acl
);
5274 pa_ip_acl_free(o
->auth_ip_acl
);
5276 o
->auth_ip_acl
= ipa
;
5280 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
5281 pa_log("auth-cookie-enabled= expects a boolean argument.");
5286 pa_auth_cookie_unref(o
->auth_cookie
);
5291 /* The new name for this is 'auth-cookie', for compat reasons
5292 * we check the old name too */
5293 cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
);
5295 cn
= pa_modargs_get_value(ma
, "cookie", NULL
);
5298 o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5300 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5301 if (!o
->auth_cookie
) {
5302 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE_FALLBACK
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5304 if (!o
->auth_cookie
)
5305 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5309 if (!o
->auth_cookie
)
5313 o
->auth_cookie
= NULL
;
5318 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
5319 pa_native_connection_assert_ref(c
);
5324 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
5325 pa_native_connection_assert_ref(c
);