protocol-native: log explicitly when someone asks us to quit
[profile/ivi/pulseaudio.git] / src / pulsecore / protocol-native.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31
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
39 #include <pulsecore/native-common.h>
40 #include <pulsecore/packet.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/pstream.h>
45 #include <pulsecore/tagstruct.h>
46 #include <pulsecore/pdispatch.h>
47 #include <pulsecore/pstream-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/llist.h>
57 #include <pulsecore/creds.h>
58 #include <pulsecore/core-util.h>
59 #include <pulsecore/ipacl.h>
60 #include <pulsecore/thread-mq.h>
61
62 #include "protocol-native.h"
63
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
66
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
69
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
71 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
72 #define DEFAULT_PROCESS_MSEC 20   /* 20ms */
73 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
74
75 struct pa_native_protocol;
76
77 typedef struct record_stream {
78     pa_msgobject parent;
79
80     pa_native_connection *connection;
81     uint32_t index;
82
83     pa_source_output *source_output;
84     pa_memblockq *memblockq;
85
86     pa_bool_t adjust_latency:1;
87     pa_bool_t early_requests:1;
88
89     pa_buffer_attr buffer_attr;
90
91     pa_atomic_t on_the_fly;
92     pa_usec_t configured_source_latency;
93     size_t drop_initial;
94
95     /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
96     size_t on_the_fly_snapshot;
97     pa_usec_t current_monitor_latency;
98     pa_usec_t current_source_latency;
99 } record_stream;
100
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
103
104 typedef struct output_stream {
105     pa_msgobject parent;
106 } output_stream;
107
108 #define OUTPUT_STREAM(o) (output_stream_cast(o))
109 PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
110
111 typedef struct playback_stream {
112     output_stream parent;
113
114     pa_native_connection *connection;
115     uint32_t index;
116
117     pa_sink_input *sink_input;
118     pa_memblockq *memblockq;
119
120     pa_bool_t adjust_latency:1;
121     pa_bool_t early_requests:1;
122
123     pa_bool_t is_underrun:1;
124     pa_bool_t drain_request:1;
125     uint32_t drain_tag;
126     uint32_t syncid;
127
128     pa_atomic_t missing;
129     pa_usec_t configured_sink_latency;
130     pa_buffer_attr buffer_attr;
131
132     /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
133     int64_t read_index, write_index;
134     size_t render_memblockq_length;
135     pa_usec_t current_sink_latency;
136     uint64_t playing_for, underrun_for;
137 } playback_stream;
138
139 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
140 PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
141
142 typedef struct upload_stream {
143     output_stream parent;
144
145     pa_native_connection *connection;
146     uint32_t index;
147
148     pa_memchunk memchunk;
149     size_t length;
150     char *name;
151     pa_sample_spec sample_spec;
152     pa_channel_map channel_map;
153     pa_proplist *proplist;
154 } upload_stream;
155
156 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
157 PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
158
159 struct pa_native_connection {
160     pa_msgobject parent;
161     pa_native_protocol *protocol;
162     pa_native_options *options;
163     pa_bool_t authorized:1;
164     pa_bool_t is_local:1;
165     uint32_t version;
166     pa_client *client;
167     pa_pstream *pstream;
168     pa_pdispatch *pdispatch;
169     pa_idxset *record_streams, *output_streams;
170     uint32_t rrobin_index;
171     pa_subscription *subscription;
172     pa_time_event *auth_timeout_event;
173 };
174
175 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
176 PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject);
177
178 struct pa_native_protocol {
179     PA_REFCNT_DECLARE;
180
181     pa_core *core;
182     pa_idxset *connections;
183
184     pa_strlist *servers;
185     pa_hook hooks[PA_NATIVE_HOOK_MAX];
186
187     pa_hashmap *extensions;
188 };
189
190 enum {
191     SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX
192 };
193
194 enum {
195     SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
196     SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
197     SINK_INPUT_MESSAGE_FLUSH,
198     SINK_INPUT_MESSAGE_TRIGGER,
199     SINK_INPUT_MESSAGE_SEEK,
200     SINK_INPUT_MESSAGE_PREBUF_FORCE,
201     SINK_INPUT_MESSAGE_UPDATE_LATENCY,
202     SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
203 };
204
205 enum {
206     PLAYBACK_STREAM_MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
207     PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
208     PLAYBACK_STREAM_MESSAGE_OVERFLOW,
209     PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
210     PLAYBACK_STREAM_MESSAGE_STARTED,
211     PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
212 };
213
214 enum {
215     RECORD_STREAM_MESSAGE_POST_DATA         /* data from source output to main loop */
216 };
217
218 enum {
219     CONNECTION_MESSAGE_RELEASE,
220     CONNECTION_MESSAGE_REVOKE
221 };
222
223 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
224 static void sink_input_kill_cb(pa_sink_input *i);
225 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
226 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest);
227 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
228 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
229 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
230 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl);
231
232 static void native_connection_send_memblock(pa_native_connection *c);
233 static void playback_stream_request_bytes(struct playback_stream*s);
234
235 static void source_output_kill_cb(pa_source_output *o);
236 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
237 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend);
238 static void source_output_moving_cb(pa_source_output *o, pa_source *dest);
239 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
240 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
241
242 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
243 static int source_output_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
244
245 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
246 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
247 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
248 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
249 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
250 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
251 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
252 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
253 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
254 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
255 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
256 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
257 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
258 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
259 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
260 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
261 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
262 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
263 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
264 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
265 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
266 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
267 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
268 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
269 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
270 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
271 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
272 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
273 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
274 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
275 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
276 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
277 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
278 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
279 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
280 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
281 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
282 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
283 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
284
285 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
286     [PA_COMMAND_ERROR] = NULL,
287     [PA_COMMAND_TIMEOUT] = NULL,
288     [PA_COMMAND_REPLY] = NULL,
289     [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
290     [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
291     [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
292     [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
293     [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
294     [PA_COMMAND_AUTH] = command_auth,
295     [PA_COMMAND_REQUEST] = NULL,
296     [PA_COMMAND_EXIT] = command_exit,
297     [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
298     [PA_COMMAND_LOOKUP_SINK] = command_lookup,
299     [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
300     [PA_COMMAND_STAT] = command_stat,
301     [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
302     [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
303     [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
304     [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
305     [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
306     [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
307     [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
308     [PA_COMMAND_GET_SINK_INFO] = command_get_info,
309     [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
310     [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
311     [PA_COMMAND_GET_CARD_INFO] = command_get_info,
312     [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
313     [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
314     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
315     [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
316     [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
317     [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
318     [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
319     [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
320     [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
321     [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
322     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
323     [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
324     [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
325     [PA_COMMAND_SUBSCRIBE] = command_subscribe,
326
327     [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
328     [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
329     [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
330
331     [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
332     [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
333     [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
334
335     [PA_COMMAND_SUSPEND_SINK] = command_suspend,
336     [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
337
338     [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
339     [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
340     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
341     [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
342
343     [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
344     [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
345
346     [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
347     [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
348     [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
349     [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
350     [PA_COMMAND_KILL_CLIENT] = command_kill,
351     [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
352     [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
353     [PA_COMMAND_LOAD_MODULE] = command_load_module,
354     [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
355
356     [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
357     [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
358     [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
359     [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
360
361     [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
362     [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
363
364     [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
365     [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
366
367     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
368     [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
369
370     [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
371     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
372     [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
373
374     [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
375     [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
376     [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
377
378     [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
379
380     [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
381     [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
382
383     [PA_COMMAND_EXTENSION] = command_extension
384 };
385
386 /* structure management */
387
388 /* Called from main context */
389 static void upload_stream_unlink(upload_stream *s) {
390     pa_assert(s);
391
392     if (!s->connection)
393         return;
394
395     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
396     s->connection = NULL;
397     upload_stream_unref(s);
398 }
399
400 /* Called from main context */
401 static void upload_stream_free(pa_object *o) {
402     upload_stream *s = UPLOAD_STREAM(o);
403     pa_assert(s);
404
405     upload_stream_unlink(s);
406
407     pa_xfree(s->name);
408
409     if (s->proplist)
410         pa_proplist_free(s->proplist);
411
412     if (s->memchunk.memblock)
413         pa_memblock_unref(s->memchunk.memblock);
414
415     pa_xfree(s);
416 }
417
418 /* Called from main context */
419 static upload_stream* upload_stream_new(
420         pa_native_connection *c,
421         const pa_sample_spec *ss,
422         const pa_channel_map *map,
423         const char *name,
424         size_t length,
425         pa_proplist *p) {
426
427     upload_stream *s;
428
429     pa_assert(c);
430     pa_assert(ss);
431     pa_assert(name);
432     pa_assert(length > 0);
433     pa_assert(p);
434
435     s = pa_msgobject_new(upload_stream);
436     s->parent.parent.parent.free = upload_stream_free;
437     s->connection = c;
438     s->sample_spec = *ss;
439     s->channel_map = *map;
440     s->name = pa_xstrdup(name);
441     pa_memchunk_reset(&s->memchunk);
442     s->length = length;
443     s->proplist = pa_proplist_copy(p);
444     pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
445
446     pa_idxset_put(c->output_streams, s, &s->index);
447
448     return s;
449 }
450
451 /* Called from main context */
452 static void record_stream_unlink(record_stream *s) {
453     pa_assert(s);
454
455     if (!s->connection)
456         return;
457
458     if (s->source_output) {
459         pa_source_output_unlink(s->source_output);
460         pa_source_output_unref(s->source_output);
461         s->source_output = NULL;
462     }
463
464     pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
465     s->connection = NULL;
466     record_stream_unref(s);
467 }
468
469 /* Called from main context */
470 static void record_stream_free(pa_object *o) {
471     record_stream *s = RECORD_STREAM(o);
472     pa_assert(s);
473
474     record_stream_unlink(s);
475
476     pa_memblockq_free(s->memblockq);
477     pa_xfree(s);
478 }
479
480 /* Called from main context */
481 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
482     record_stream *s = RECORD_STREAM(o);
483     record_stream_assert_ref(s);
484
485     if (!s->connection)
486         return -1;
487
488     switch (code) {
489
490         case RECORD_STREAM_MESSAGE_POST_DATA:
491
492             /* We try to keep up to date with how many bytes are
493              * currently on the fly */
494             pa_atomic_sub(&s->on_the_fly, chunk->length);
495
496             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
497 /*                 pa_log_warn("Failed to push data into output queue."); */
498                 return -1;
499             }
500
501             if (!pa_pstream_is_pending(s->connection->pstream))
502                 native_connection_send_memblock(s->connection);
503
504             break;
505     }
506
507     return 0;
508 }
509
510 /* Called from main context */
511 static void fix_record_buffer_attr_pre(record_stream *s) {
512
513     size_t frame_size;
514     pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
515
516     pa_assert(s);
517
518     /* This function will be called from the main thread, before as
519      * well as after the source output has been activated using
520      * pa_source_output_put()! That means it may not touch any
521      * ->thread_info data! */
522
523     frame_size = pa_frame_size(&s->source_output->sample_spec);
524
525     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
526         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
527     if (s->buffer_attr.maxlength <= 0)
528         s->buffer_attr.maxlength = (uint32_t) frame_size;
529
530     if (s->buffer_attr.fragsize == (uint32_t) -1)
531         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
532     if (s->buffer_attr.fragsize <= 0)
533         s->buffer_attr.fragsize = (uint32_t) frame_size;
534
535     orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
536
537     if (s->early_requests) {
538
539         /* In early request mode we need to emulate the classic
540          * fragment-based playback model. We do this setting the source
541          * latency to the fragment size. */
542
543         source_usec = fragsize_usec;
544
545     } else if (s->adjust_latency) {
546
547         /* So, the user asked us to adjust the latency according to
548          * what the source can provide. Half the latency will be
549          * spent on the hw buffer, half of it in the async buffer
550          * queue we maintain for each client. */
551
552         source_usec = fragsize_usec/2;
553
554     } else {
555
556         /* Ok, the user didn't ask us to adjust the latency, hence we
557          * don't */
558
559         source_usec = (pa_usec_t) -1;
560     }
561
562     if (source_usec != (pa_usec_t) -1)
563         s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
564     else
565         s->configured_source_latency = 0;
566
567     if (s->early_requests) {
568
569         /* Ok, we didn't necessarily get what we were asking for, so
570          * let's tell the user */
571
572         fragsize_usec = s->configured_source_latency;
573
574     } else if (s->adjust_latency) {
575
576         /* Now subtract what we actually got */
577
578         if (fragsize_usec >= s->configured_source_latency*2)
579             fragsize_usec -= s->configured_source_latency;
580         else
581             fragsize_usec = s->configured_source_latency;
582     }
583
584     if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
585         pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
586
587         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
588
589     if (s->buffer_attr.fragsize <= 0)
590         s->buffer_attr.fragsize = (uint32_t) frame_size;
591 }
592
593 /* Called from main context */
594 static void fix_record_buffer_attr_post(record_stream *s) {
595     size_t base;
596
597     pa_assert(s);
598
599     /* This function will be called from the main thread, before as
600      * well as after the source output has been activated using
601      * pa_source_output_put()! That means it may not touch and
602      * ->thread_info data! */
603
604     base = pa_frame_size(&s->source_output->sample_spec);
605
606     s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
607     if (s->buffer_attr.fragsize <= 0)
608         s->buffer_attr.fragsize = base;
609
610     if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
611         s->buffer_attr.fragsize = s->buffer_attr.maxlength;
612 }
613
614 /* Called from main context */
615 static record_stream* record_stream_new(
616         pa_native_connection *c,
617         pa_source *source,
618         pa_sample_spec *ss,
619         pa_channel_map *map,
620         pa_bool_t peak_detect,
621         pa_buffer_attr *attr,
622         pa_source_output_flags_t flags,
623         pa_proplist *p,
624         pa_bool_t adjust_latency,
625         pa_sink_input *direct_on_input,
626         pa_bool_t early_requests,
627         int *ret) {
628
629     record_stream *s;
630     pa_source_output *source_output = NULL;
631     pa_source_output_new_data data;
632
633     pa_assert(c);
634     pa_assert(ss);
635     pa_assert(p);
636     pa_assert(ret);
637
638     pa_source_output_new_data_init(&data);
639
640     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
641     data.driver = __FILE__;
642     data.module = c->options->module;
643     data.client = c->client;
644     data.source = source;
645     data.direct_on_input = direct_on_input;
646     pa_source_output_new_data_set_sample_spec(&data, ss);
647     pa_source_output_new_data_set_channel_map(&data, map);
648     if (peak_detect)
649         data.resample_method = PA_RESAMPLER_PEAKS;
650     data.flags = flags;
651
652     *ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
653
654     pa_source_output_new_data_done(&data);
655
656     if (!source_output)
657         return NULL;
658
659     s = pa_msgobject_new(record_stream);
660     s->parent.parent.free = record_stream_free;
661     s->parent.process_msg = record_stream_process_msg;
662     s->connection = c;
663     s->source_output = source_output;
664     s->buffer_attr = *attr;
665     s->adjust_latency = adjust_latency;
666     s->early_requests = early_requests;
667     pa_atomic_store(&s->on_the_fly, 0);
668
669     s->source_output->parent.process_msg = source_output_process_msg;
670     s->source_output->push = source_output_push_cb;
671     s->source_output->kill = source_output_kill_cb;
672     s->source_output->get_latency = source_output_get_latency_cb;
673     s->source_output->moving = source_output_moving_cb;
674     s->source_output->suspend = source_output_suspend_cb;
675     s->source_output->send_event = source_output_send_event_cb;
676     s->source_output->userdata = s;
677
678     fix_record_buffer_attr_pre(s);
679
680     s->memblockq = pa_memblockq_new(
681             0,
682             s->buffer_attr.maxlength,
683             0,
684             pa_frame_size(&source_output->sample_spec),
685             1,
686             0,
687             0,
688             NULL);
689
690     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
691     fix_record_buffer_attr_post(s);
692
693     *ss = s->source_output->sample_spec;
694     *map = s->source_output->channel_map;
695
696     pa_idxset_put(c->record_streams, s, &s->index);
697
698     pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
699                 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
700                 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
701                 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
702
703     pa_source_output_put(s->source_output);
704     return s;
705 }
706
707 /* Called from main context */
708 static void record_stream_send_killed(record_stream *r) {
709     pa_tagstruct *t;
710     record_stream_assert_ref(r);
711
712     t = pa_tagstruct_new(NULL, 0);
713     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
714     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
715     pa_tagstruct_putu32(t, r->index);
716     pa_pstream_send_tagstruct(r->connection->pstream, t);
717 }
718
719 /* Called from main context */
720 static void playback_stream_unlink(playback_stream *s) {
721     pa_assert(s);
722
723     if (!s->connection)
724         return;
725
726     if (s->sink_input) {
727         pa_sink_input_unlink(s->sink_input);
728         pa_sink_input_unref(s->sink_input);
729         s->sink_input = NULL;
730     }
731
732     if (s->drain_request)
733         pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
734
735     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
736     s->connection = NULL;
737     playback_stream_unref(s);
738 }
739
740 /* Called from main context */
741 static void playback_stream_free(pa_object* o) {
742     playback_stream *s = PLAYBACK_STREAM(o);
743     pa_assert(s);
744
745     playback_stream_unlink(s);
746
747     pa_memblockq_free(s->memblockq);
748     pa_xfree(s);
749 }
750
751 /* Called from main context */
752 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
753     playback_stream *s = PLAYBACK_STREAM(o);
754     playback_stream_assert_ref(s);
755
756     if (!s->connection)
757         return -1;
758
759     switch (code) {
760
761         case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
762             pa_tagstruct *t;
763             int l = 0;
764
765             for (;;) {
766                 if ((l = pa_atomic_load(&s->missing)) <= 0)
767                     return 0;
768
769                 if (pa_atomic_cmpxchg(&s->missing, l, 0))
770                     break;
771             }
772
773             t = pa_tagstruct_new(NULL, 0);
774             pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
775             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
776             pa_tagstruct_putu32(t, s->index);
777             pa_tagstruct_putu32(t, (uint32_t) l);
778             pa_pstream_send_tagstruct(s->connection->pstream, t);
779
780 /*             pa_log("Requesting %lu bytes", (unsigned long) l); */
781             break;
782         }
783
784         case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
785             pa_tagstruct *t;
786
787 /*             pa_log("signalling underflow"); */
788
789             /* Report that we're empty */
790             t = pa_tagstruct_new(NULL, 0);
791             pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
792             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
793             pa_tagstruct_putu32(t, s->index);
794             pa_pstream_send_tagstruct(s->connection->pstream, t);
795             break;
796         }
797
798         case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
799             pa_tagstruct *t;
800
801             /* Notify the user we're overflowed*/
802             t = pa_tagstruct_new(NULL, 0);
803             pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
804             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
805             pa_tagstruct_putu32(t, s->index);
806             pa_pstream_send_tagstruct(s->connection->pstream, t);
807             break;
808         }
809
810         case PLAYBACK_STREAM_MESSAGE_STARTED:
811
812             if (s->connection->version >= 13) {
813                 pa_tagstruct *t;
814
815                 /* Notify the user we started playback */
816                 t = pa_tagstruct_new(NULL, 0);
817                 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
818                 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
819                 pa_tagstruct_putu32(t, s->index);
820                 pa_pstream_send_tagstruct(s->connection->pstream, t);
821             }
822
823             break;
824
825         case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
826             pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
827             break;
828
829         case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
830             pa_tagstruct *t;
831
832             s->buffer_attr.tlength = (uint32_t) offset;
833
834             t = pa_tagstruct_new(NULL, 0);
835             pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
836             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
837             pa_tagstruct_putu32(t, s->index);
838             pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
839             pa_tagstruct_putu32(t, s->buffer_attr.tlength);
840             pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
841             pa_tagstruct_putu32(t, s->buffer_attr.minreq);
842             pa_tagstruct_put_usec(t, s->configured_sink_latency);
843             pa_pstream_send_tagstruct(s->connection->pstream, t);
844
845             break;
846         }
847     }
848
849     return 0;
850 }
851
852 /* Called from main context */
853 static void fix_playback_buffer_attr(playback_stream *s) {
854     size_t frame_size, max_prebuf;
855     pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
856
857     pa_assert(s);
858
859     /* This function will be called from the main thread, before as
860      * well as after the sink input has been activated using
861      * pa_sink_input_put()! That means it may not touch any
862      * ->thread_info data, such as the memblockq! */
863
864     frame_size = pa_frame_size(&s->sink_input->sample_spec);
865
866     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
867         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
868     if (s->buffer_attr.maxlength <= 0)
869         s->buffer_attr.maxlength = (uint32_t) frame_size;
870
871     if (s->buffer_attr.tlength == (uint32_t) -1)
872         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
873     if (s->buffer_attr.tlength <= 0)
874         s->buffer_attr.tlength = (uint32_t) frame_size;
875
876     if (s->buffer_attr.minreq == (uint32_t) -1)
877         s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
878     if (s->buffer_attr.minreq <= 0)
879         s->buffer_attr.minreq = (uint32_t) frame_size;
880
881     if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
882         s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
883
884     orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
885     orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
886
887     pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
888                 (double) tlength_usec / PA_USEC_PER_MSEC,
889                 (double) minreq_usec / PA_USEC_PER_MSEC);
890
891     if (s->early_requests) {
892
893         /* In early request mode we need to emulate the classic
894          * fragment-based playback model. We do this setting the sink
895          * latency to the fragment size. */
896
897         sink_usec = minreq_usec;
898         pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
899
900     } else if (s->adjust_latency) {
901
902         /* So, the user asked us to adjust the latency of the stream
903          * buffer according to the what the sink can provide. The
904          * tlength passed in shall be the overall latency. Roughly
905          * half the latency will be spent on the hw buffer, the other
906          * half of it in the async buffer queue we maintain for each
907          * client. In between we'll have a safety space of size
908          * 2*minreq. Why the 2*minreq? When the hw buffer is completey
909          * empty and needs to be filled, then our buffer must have
910          * enough data to fulfill this request immediatly and thus
911          * have at least the same tlength as the size of the hw
912          * buffer. It additionally needs space for 2 times minreq
913          * because if the buffer ran empty and a partial fillup
914          * happens immediately on the next iteration we need to be
915          * able to fulfill it and give the application also minreq
916          * time to fill it up again for the next request Makes 2 times
917          * minreq in plus.. */
918
919         if (tlength_usec > minreq_usec*2)
920             sink_usec = (tlength_usec - minreq_usec*2)/2;
921         else
922             sink_usec = 0;
923
924         pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
925
926     } else {
927
928         /* Ok, the user didn't ask us to adjust the latency, but we
929          * still need to make sure that the parameters from the user
930          * do make sense. */
931
932         if (tlength_usec > minreq_usec*2)
933             sink_usec = (tlength_usec - minreq_usec*2);
934         else
935             sink_usec = 0;
936
937         pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
938     }
939
940     s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
941
942     if (s->early_requests) {
943
944         /* Ok, we didn't necessarily get what we were asking for, so
945          * let's tell the user */
946
947         minreq_usec = s->configured_sink_latency;
948
949     } else if (s->adjust_latency) {
950
951         /* Ok, we didn't necessarily get what we were asking for, so
952          * let's subtract from what we asked for for the remaining
953          * buffer space */
954
955         if (tlength_usec >= s->configured_sink_latency)
956             tlength_usec -= s->configured_sink_latency;
957     }
958
959     /* FIXME: This is actually larger than necessary, since not all of
960      * the sink latency is actually rewritable. */
961     if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
962         tlength_usec = s->configured_sink_latency + 2*minreq_usec;
963
964     if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
965         pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
966         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
967
968     if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
969         pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
970         s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
971
972     if (s->buffer_attr.minreq <= 0) {
973         s->buffer_attr.minreq = (uint32_t) frame_size;
974         s->buffer_attr.tlength += (uint32_t) frame_size*2;
975     }
976
977     if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
978         s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
979
980     max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
981
982     if (s->buffer_attr.prebuf == (uint32_t) -1 ||
983         s->buffer_attr.prebuf > max_prebuf)
984         s->buffer_attr.prebuf = max_prebuf;
985 }
986
987 /* Called from main context */
988 static playback_stream* playback_stream_new(
989         pa_native_connection *c,
990         pa_sink *sink,
991         pa_sample_spec *ss,
992         pa_channel_map *map,
993         pa_buffer_attr *a,
994         pa_cvolume *volume,
995         pa_bool_t muted,
996         pa_bool_t muted_set,
997         uint32_t syncid,
998         uint32_t *missing,
999         pa_sink_input_flags_t flags,
1000         pa_proplist *p,
1001         pa_bool_t adjust_latency,
1002         pa_bool_t early_requests,
1003         int *ret) {
1004
1005     playback_stream *s, *ssync;
1006     pa_sink_input *sink_input = NULL;
1007     pa_memchunk silence;
1008     uint32_t idx;
1009     int64_t start_index;
1010     pa_sink_input_new_data data;
1011
1012     pa_assert(c);
1013     pa_assert(ss);
1014     pa_assert(missing);
1015     pa_assert(p);
1016     pa_assert(ret);
1017
1018     /* Find syncid group */
1019     for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
1020
1021         if (!playback_stream_isinstance(ssync))
1022             continue;
1023
1024         if (ssync->syncid == syncid)
1025             break;
1026     }
1027
1028     /* Synced streams must connect to the same sink */
1029     if (ssync) {
1030
1031         if (!sink)
1032             sink = ssync->sink_input->sink;
1033         else if (sink != ssync->sink_input->sink) {
1034             *ret = PA_ERR_INVALID;
1035             return NULL;
1036         }
1037     }
1038
1039     pa_sink_input_new_data_init(&data);
1040
1041     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
1042     data.driver = __FILE__;
1043     data.module = c->options->module;
1044     data.client = c->client;
1045     data.sink = sink;
1046     pa_sink_input_new_data_set_sample_spec(&data, ss);
1047     pa_sink_input_new_data_set_channel_map(&data, map);
1048     if (volume)
1049         pa_sink_input_new_data_set_volume(&data, volume);
1050     if (muted_set)
1051         pa_sink_input_new_data_set_muted(&data, muted);
1052     data.sync_base = ssync ? ssync->sink_input : NULL;
1053     data.flags = flags;
1054
1055     *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
1056
1057     pa_sink_input_new_data_done(&data);
1058
1059     if (!sink_input)
1060         return NULL;
1061
1062     s = pa_msgobject_new(playback_stream);
1063     s->parent.parent.parent.free = playback_stream_free;
1064     s->parent.parent.process_msg = playback_stream_process_msg;
1065     s->connection = c;
1066     s->syncid = syncid;
1067     s->sink_input = sink_input;
1068     s->is_underrun = TRUE;
1069     s->drain_request = FALSE;
1070     pa_atomic_store(&s->missing, 0);
1071     s->buffer_attr = *a;
1072     s->adjust_latency = adjust_latency;
1073     s->early_requests = early_requests;
1074
1075     s->sink_input->parent.process_msg = sink_input_process_msg;
1076     s->sink_input->pop = sink_input_pop_cb;
1077     s->sink_input->process_rewind = sink_input_process_rewind_cb;
1078     s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1079     s->sink_input->update_max_request = sink_input_update_max_request_cb;
1080     s->sink_input->kill = sink_input_kill_cb;
1081     s->sink_input->moving = sink_input_moving_cb;
1082     s->sink_input->suspend = sink_input_suspend_cb;
1083     s->sink_input->send_event = sink_input_send_event_cb;
1084     s->sink_input->userdata = s;
1085
1086     start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
1087
1088     fix_playback_buffer_attr(s);
1089
1090     pa_sink_input_get_silence(sink_input, &silence);
1091     s->memblockq = pa_memblockq_new(
1092             start_index,
1093             s->buffer_attr.maxlength,
1094             s->buffer_attr.tlength,
1095             pa_frame_size(&sink_input->sample_spec),
1096             s->buffer_attr.prebuf,
1097             s->buffer_attr.minreq,
1098             0,
1099             &silence);
1100     pa_memblock_unref(silence.memblock);
1101
1102     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1103
1104     *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
1105
1106     *ss = s->sink_input->sample_spec;
1107     *map = s->sink_input->channel_map;
1108
1109     pa_idxset_put(c->output_streams, s, &s->index);
1110
1111     pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1112                 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
1113                 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1114                 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1115                 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1116
1117     pa_sink_input_put(s->sink_input);
1118     return s;
1119 }
1120
1121 /* Called from IO context */
1122 static void playback_stream_request_bytes(playback_stream *s) {
1123     size_t m, minreq;
1124     int previous_missing;
1125
1126     playback_stream_assert_ref(s);
1127
1128     m = pa_memblockq_pop_missing(s->memblockq);
1129
1130     /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
1131     /*        (unsigned long) m, */
1132     /*        pa_memblockq_get_tlength(s->memblockq), */
1133     /*        pa_memblockq_get_minreq(s->memblockq), */
1134     /*        pa_memblockq_get_length(s->memblockq)); */
1135
1136     if (m <= 0)
1137         return;
1138
1139 /*     pa_log("request_bytes(%lu)", (unsigned long) m); */
1140
1141     previous_missing = pa_atomic_add(&s->missing, (int) m);
1142     minreq = pa_memblockq_get_minreq(s->memblockq);
1143
1144     if (pa_memblockq_prebuf_active(s->memblockq) ||
1145         (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq))
1146         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1147 }
1148
1149 /* Called from main context */
1150 static void playback_stream_send_killed(playback_stream *p) {
1151     pa_tagstruct *t;
1152     playback_stream_assert_ref(p);
1153
1154     t = pa_tagstruct_new(NULL, 0);
1155     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1156     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1157     pa_tagstruct_putu32(t, p->index);
1158     pa_pstream_send_tagstruct(p->connection->pstream, t);
1159 }
1160
1161 /* Called from main context */
1162 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1163     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1164     pa_native_connection_assert_ref(c);
1165
1166     if (!c->protocol)
1167         return -1;
1168
1169     switch (code) {
1170
1171         case CONNECTION_MESSAGE_REVOKE:
1172             pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
1173             break;
1174
1175         case CONNECTION_MESSAGE_RELEASE:
1176             pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
1177             break;
1178     }
1179
1180     return 0;
1181 }
1182
1183 /* Called from main context */
1184 static void native_connection_unlink(pa_native_connection *c) {
1185     record_stream *r;
1186     output_stream *o;
1187
1188     pa_assert(c);
1189
1190     if (!c->protocol)
1191         return;
1192
1193     pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1194
1195     if (c->options)
1196         pa_native_options_unref(c->options);
1197
1198     while ((r = pa_idxset_first(c->record_streams, NULL)))
1199         record_stream_unlink(r);
1200
1201     while ((o = pa_idxset_first(c->output_streams, NULL)))
1202         if (playback_stream_isinstance(o))
1203             playback_stream_unlink(PLAYBACK_STREAM(o));
1204         else
1205             upload_stream_unlink(UPLOAD_STREAM(o));
1206
1207     if (c->subscription)
1208         pa_subscription_free(c->subscription);
1209
1210     if (c->pstream)
1211         pa_pstream_unlink(c->pstream);
1212
1213     if (c->auth_timeout_event) {
1214         c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1215         c->auth_timeout_event = NULL;
1216     }
1217
1218     pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1219     c->protocol = NULL;
1220     pa_native_connection_unref(c);
1221 }
1222
1223 /* Called from main context */
1224 static void native_connection_free(pa_object *o) {
1225     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1226
1227     pa_assert(c);
1228
1229     native_connection_unlink(c);
1230
1231     pa_idxset_free(c->record_streams, NULL, NULL);
1232     pa_idxset_free(c->output_streams, NULL, NULL);
1233
1234     pa_pdispatch_unref(c->pdispatch);
1235     pa_pstream_unref(c->pstream);
1236     pa_client_free(c->client);
1237
1238     pa_xfree(c);
1239 }
1240
1241 /* Called from main context */
1242 static void native_connection_send_memblock(pa_native_connection *c) {
1243     uint32_t start;
1244     record_stream *r;
1245
1246     start = PA_IDXSET_INVALID;
1247     for (;;) {
1248         pa_memchunk chunk;
1249
1250         if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1251             return;
1252
1253         if (start == PA_IDXSET_INVALID)
1254             start = c->rrobin_index;
1255         else if (start == c->rrobin_index)
1256             return;
1257
1258         if (pa_memblockq_peek(r->memblockq,  &chunk) >= 0) {
1259             pa_memchunk schunk = chunk;
1260
1261             if (schunk.length > r->buffer_attr.fragsize)
1262                 schunk.length = r->buffer_attr.fragsize;
1263
1264             pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1265
1266             pa_memblockq_drop(r->memblockq, schunk.length);
1267             pa_memblock_unref(schunk.memblock);
1268
1269             return;
1270         }
1271     }
1272 }
1273
1274 /*** sink input callbacks ***/
1275
1276 /* Called from thread context */
1277 static void handle_seek(playback_stream *s, int64_t indexw) {
1278     playback_stream_assert_ref(s);
1279
1280 /*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1281
1282     if (s->sink_input->thread_info.underrun_for > 0) {
1283
1284 /*         pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1285
1286         if (pa_memblockq_is_readable(s->memblockq)) {
1287
1288             /* We just ended an underrun, let's ask the sink
1289              * for a complete rewind rewrite */
1290
1291             pa_log_debug("Requesting rewind due to end of underrun.");
1292             pa_sink_input_request_rewind(s->sink_input,
1293                                          (size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
1294                                                    s->sink_input->thread_info.underrun_for),
1295                                          FALSE, TRUE, FALSE);
1296         }
1297
1298     } else {
1299         int64_t indexr;
1300
1301         indexr = pa_memblockq_get_read_index(s->memblockq);
1302
1303         if (indexw < indexr) {
1304             /* OK, the sink already asked for this data, so
1305              * let's have it usk us again */
1306
1307             pa_log_debug("Requesting rewind due to rewrite.");
1308             pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE);
1309         }
1310     }
1311
1312     playback_stream_request_bytes(s);
1313 }
1314
1315 /* Called from thread context */
1316 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1317     pa_sink_input *i = PA_SINK_INPUT(o);
1318     playback_stream *s;
1319
1320     pa_sink_input_assert_ref(i);
1321     s = PLAYBACK_STREAM(i->userdata);
1322     playback_stream_assert_ref(s);
1323
1324     switch (code) {
1325
1326         case SINK_INPUT_MESSAGE_SEEK: {
1327             int64_t windex;
1328
1329             windex = pa_memblockq_get_write_index(s->memblockq);
1330
1331             /* The client side is incapable of accounting correctly
1332              * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1333              * able to deal with that. */
1334
1335             pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1336
1337             handle_seek(s, windex);
1338             return 0;
1339         }
1340
1341         case SINK_INPUT_MESSAGE_POST_DATA: {
1342             int64_t windex;
1343
1344             pa_assert(chunk);
1345
1346             windex = pa_memblockq_get_write_index(s->memblockq);
1347
1348 /*             pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1349
1350             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1351
1352                 if (pa_log_ratelimit())
1353                     pa_log_warn("Failed to push data into queue");
1354                 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1355                 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE);
1356             }
1357
1358             handle_seek(s, windex);
1359
1360 /*             pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1361
1362             return 0;
1363         }
1364
1365         case SINK_INPUT_MESSAGE_DRAIN:
1366         case SINK_INPUT_MESSAGE_FLUSH:
1367         case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1368         case SINK_INPUT_MESSAGE_TRIGGER: {
1369
1370             int64_t windex;
1371             pa_sink_input *isync;
1372             void (*func)(pa_memblockq *bq);
1373
1374             switch  (code) {
1375                 case SINK_INPUT_MESSAGE_FLUSH:
1376                     func = pa_memblockq_flush_write;
1377                     break;
1378
1379                 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1380                     func = pa_memblockq_prebuf_force;
1381                     break;
1382
1383                 case SINK_INPUT_MESSAGE_DRAIN:
1384                 case SINK_INPUT_MESSAGE_TRIGGER:
1385                     func = pa_memblockq_prebuf_disable;
1386                     break;
1387
1388                 default:
1389                     pa_assert_not_reached();
1390             }
1391
1392             windex = pa_memblockq_get_write_index(s->memblockq);
1393             func(s->memblockq);
1394             handle_seek(s, windex);
1395
1396             /* Do the same for all other members in the sync group */
1397             for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1398                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1399                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1400                 func(ssync->memblockq);
1401                 handle_seek(ssync, windex);
1402             }
1403
1404             for (isync = i->sync_next; isync; isync = isync->sync_next) {
1405                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1406                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1407                 func(ssync->memblockq);
1408                 handle_seek(ssync, windex);
1409             }
1410
1411             if (code == SINK_INPUT_MESSAGE_DRAIN) {
1412                 if (!pa_memblockq_is_readable(s->memblockq))
1413                     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1414                 else {
1415                     s->drain_tag = PA_PTR_TO_UINT(userdata);
1416                     s->drain_request = TRUE;
1417                 }
1418             }
1419
1420             return 0;
1421         }
1422
1423         case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1424             /* Atomically get a snapshot of all timing parameters... */
1425             s->read_index = pa_memblockq_get_read_index(s->memblockq);
1426             s->write_index = pa_memblockq_get_write_index(s->memblockq);
1427             s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1428             s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink);
1429             s->underrun_for = s->sink_input->thread_info.underrun_for;
1430             s->playing_for = s->sink_input->thread_info.playing_for;
1431
1432             return 0;
1433
1434         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1435             int64_t windex;
1436
1437             windex = pa_memblockq_get_write_index(s->memblockq);
1438
1439             pa_memblockq_prebuf_force(s->memblockq);
1440
1441             handle_seek(s, windex);
1442
1443             /* Fall through to the default handler */
1444             break;
1445         }
1446
1447         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1448             pa_usec_t *r = userdata;
1449
1450             *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1451
1452             /* Fall through, the default handler will add in the extra
1453              * latency added by the resampler */
1454             break;
1455         }
1456
1457         case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1458             pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1459             pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1460             return 0;
1461         }
1462     }
1463
1464     return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1465 }
1466
1467 /* Called from thread context */
1468 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1469     playback_stream *s;
1470
1471     pa_sink_input_assert_ref(i);
1472     s = PLAYBACK_STREAM(i->userdata);
1473     playback_stream_assert_ref(s);
1474     pa_assert(chunk);
1475
1476 /*     pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1477
1478     if (pa_memblockq_is_readable(s->memblockq))
1479         s->is_underrun = FALSE;
1480     else {
1481         if (!s->is_underrun)
1482             pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
1483
1484         if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
1485             s->drain_request = FALSE;
1486             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
1487         } else if (!s->is_underrun)
1488             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
1489
1490         s->is_underrun = TRUE;
1491
1492         playback_stream_request_bytes(s);
1493     }
1494
1495     /* This call will not fail with prebuf=0, hence we check for
1496        underrun explicitly above */
1497     if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1498         return -1;
1499
1500     chunk->length = PA_MIN(nbytes, chunk->length);
1501
1502     if (i->thread_info.underrun_for > 0)
1503         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1504
1505     pa_memblockq_drop(s->memblockq, chunk->length);
1506     playback_stream_request_bytes(s);
1507
1508     return 0;
1509 }
1510
1511 /* Called from thread context */
1512 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1513     playback_stream *s;
1514
1515     pa_sink_input_assert_ref(i);
1516     s = PLAYBACK_STREAM(i->userdata);
1517     playback_stream_assert_ref(s);
1518
1519     /* If we are in an underrun, then we don't rewind */
1520     if (i->thread_info.underrun_for > 0)
1521         return;
1522
1523     pa_memblockq_rewind(s->memblockq, nbytes);
1524 }
1525
1526 /* Called from thread context */
1527 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1528     playback_stream *s;
1529
1530     pa_sink_input_assert_ref(i);
1531     s = PLAYBACK_STREAM(i->userdata);
1532     playback_stream_assert_ref(s);
1533
1534     pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1535 }
1536
1537 /* Called from thread context */
1538 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1539     playback_stream *s;
1540     size_t new_tlength, old_tlength;
1541
1542     pa_sink_input_assert_ref(i);
1543     s = PLAYBACK_STREAM(i->userdata);
1544     playback_stream_assert_ref(s);
1545
1546     old_tlength = pa_memblockq_get_tlength(s->memblockq);
1547     new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1548
1549     if (old_tlength < new_tlength) {
1550         pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength, new_tlength);
1551         pa_memblockq_set_tlength(s->memblockq, new_tlength);
1552         new_tlength = pa_memblockq_get_tlength(s->memblockq);
1553
1554         if (new_tlength == old_tlength)
1555             pa_log_debug("Failed to increase tlength");
1556         else {
1557             pa_log_debug("Notifying client about increased tlength");
1558             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH, NULL, pa_memblockq_get_tlength(s->memblockq), NULL, NULL);
1559         }
1560     }
1561 }
1562
1563 /* Called from main context */
1564 static void sink_input_kill_cb(pa_sink_input *i) {
1565     playback_stream *s;
1566
1567     pa_sink_input_assert_ref(i);
1568     s = PLAYBACK_STREAM(i->userdata);
1569     playback_stream_assert_ref(s);
1570
1571     playback_stream_send_killed(s);
1572     playback_stream_unlink(s);
1573 }
1574
1575 /* Called from main context */
1576 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1577     playback_stream *s;
1578     pa_tagstruct *t;
1579
1580     pa_sink_input_assert_ref(i);
1581     s = PLAYBACK_STREAM(i->userdata);
1582     playback_stream_assert_ref(s);
1583
1584     if (s->connection->version < 15)
1585       return;
1586
1587     t = pa_tagstruct_new(NULL, 0);
1588     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1589     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1590     pa_tagstruct_putu32(t, s->index);
1591     pa_tagstruct_puts(t, event);
1592     pa_tagstruct_put_proplist(t, pl);
1593     pa_pstream_send_tagstruct(s->connection->pstream, t);
1594 }
1595
1596 /* Called from main context */
1597 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
1598     playback_stream *s;
1599     pa_tagstruct *t;
1600
1601     pa_sink_input_assert_ref(i);
1602     s = PLAYBACK_STREAM(i->userdata);
1603     playback_stream_assert_ref(s);
1604
1605     if (s->connection->version < 12)
1606       return;
1607
1608     t = pa_tagstruct_new(NULL, 0);
1609     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1610     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1611     pa_tagstruct_putu32(t, s->index);
1612     pa_tagstruct_put_boolean(t, suspend);
1613     pa_pstream_send_tagstruct(s->connection->pstream, t);
1614 }
1615
1616 /* Called from main context */
1617 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1618     playback_stream *s;
1619     pa_tagstruct *t;
1620
1621     pa_sink_input_assert_ref(i);
1622     s = PLAYBACK_STREAM(i->userdata);
1623     playback_stream_assert_ref(s);
1624
1625     if (!dest)
1626         return;
1627
1628     fix_playback_buffer_attr(s);
1629     pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1630     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1631
1632     if (s->connection->version < 12)
1633       return;
1634
1635     t = pa_tagstruct_new(NULL, 0);
1636     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1637     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1638     pa_tagstruct_putu32(t, s->index);
1639     pa_tagstruct_putu32(t, dest->index);
1640     pa_tagstruct_puts(t, dest->name);
1641     pa_tagstruct_put_boolean(t, pa_sink_get_state(dest) == PA_SINK_SUSPENDED);
1642
1643     if (s->connection->version >= 13) {
1644         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1645         pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1646         pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1647         pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1648         pa_tagstruct_put_usec(t, s->configured_sink_latency);
1649     }
1650
1651     pa_pstream_send_tagstruct(s->connection->pstream, t);
1652 }
1653
1654 /*** source_output callbacks ***/
1655
1656 /* Called from thread context */
1657 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1658     pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1659     record_stream *s;
1660
1661     pa_source_output_assert_ref(o);
1662     s = RECORD_STREAM(o->userdata);
1663     record_stream_assert_ref(s);
1664
1665     switch (code) {
1666         case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1667             /* Atomically get a snapshot of all timing parameters... */
1668             s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of) : 0;
1669             s->current_source_latency = pa_source_get_latency_within_thread(o->source);
1670             s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1671             return 0;
1672     }
1673
1674     return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1675 }
1676
1677 /* Called from thread context */
1678 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1679     record_stream *s;
1680
1681     pa_source_output_assert_ref(o);
1682     s = RECORD_STREAM(o->userdata);
1683     record_stream_assert_ref(s);
1684     pa_assert(chunk);
1685
1686     pa_atomic_add(&s->on_the_fly, chunk->length);
1687     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1688 }
1689
1690 static void source_output_kill_cb(pa_source_output *o) {
1691     record_stream *s;
1692
1693     pa_source_output_assert_ref(o);
1694     s = RECORD_STREAM(o->userdata);
1695     record_stream_assert_ref(s);
1696
1697     record_stream_send_killed(s);
1698     record_stream_unlink(s);
1699 }
1700
1701 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1702     record_stream *s;
1703
1704     pa_source_output_assert_ref(o);
1705     s = RECORD_STREAM(o->userdata);
1706     record_stream_assert_ref(s);
1707
1708     /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1709
1710     return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1711 }
1712
1713 /* Called from main context */
1714 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1715     record_stream *s;
1716     pa_tagstruct *t;
1717
1718     pa_source_output_assert_ref(o);
1719     s = RECORD_STREAM(o->userdata);
1720     record_stream_assert_ref(s);
1721
1722     if (s->connection->version < 15)
1723       return;
1724
1725     t = pa_tagstruct_new(NULL, 0);
1726     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1727     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1728     pa_tagstruct_putu32(t, s->index);
1729     pa_tagstruct_puts(t, event);
1730     pa_tagstruct_put_proplist(t, pl);
1731     pa_pstream_send_tagstruct(s->connection->pstream, t);
1732 }
1733
1734 /* Called from main context */
1735 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
1736     record_stream *s;
1737     pa_tagstruct *t;
1738
1739     pa_source_output_assert_ref(o);
1740     s = RECORD_STREAM(o->userdata);
1741     record_stream_assert_ref(s);
1742
1743     if (s->connection->version < 12)
1744       return;
1745
1746     t = pa_tagstruct_new(NULL, 0);
1747     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1748     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1749     pa_tagstruct_putu32(t, s->index);
1750     pa_tagstruct_put_boolean(t, suspend);
1751     pa_pstream_send_tagstruct(s->connection->pstream, t);
1752 }
1753
1754 /* Called from main context */
1755 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1756     record_stream *s;
1757     pa_tagstruct *t;
1758
1759     pa_source_output_assert_ref(o);
1760     s = RECORD_STREAM(o->userdata);
1761     record_stream_assert_ref(s);
1762
1763     if (!dest)
1764         return;
1765
1766     fix_record_buffer_attr_pre(s);
1767     pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1768     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1769     fix_record_buffer_attr_post(s);
1770
1771     if (s->connection->version < 12)
1772       return;
1773
1774     t = pa_tagstruct_new(NULL, 0);
1775     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1776     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1777     pa_tagstruct_putu32(t, s->index);
1778     pa_tagstruct_putu32(t, dest->index);
1779     pa_tagstruct_puts(t, dest->name);
1780     pa_tagstruct_put_boolean(t, pa_source_get_state(dest) == PA_SOURCE_SUSPENDED);
1781
1782     if (s->connection->version >= 13) {
1783         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1784         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1785         pa_tagstruct_put_usec(t, s->configured_source_latency);
1786     }
1787
1788     pa_pstream_send_tagstruct(s->connection->pstream, t);
1789 }
1790
1791 /*** pdispatch callbacks ***/
1792
1793 static void protocol_error(pa_native_connection *c) {
1794     pa_log("protocol error, kicking client");
1795     native_connection_unlink(c);
1796 }
1797
1798 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1799 if (!(expression)) { \
1800     pa_pstream_send_error((pstream), (tag), (error)); \
1801     return; \
1802 } \
1803 } while(0);
1804
1805 static pa_tagstruct *reply_new(uint32_t tag) {
1806     pa_tagstruct *reply;
1807
1808     reply = pa_tagstruct_new(NULL, 0);
1809     pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1810     pa_tagstruct_putu32(reply, tag);
1811     return reply;
1812 }
1813
1814 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1815     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1816     playback_stream *s;
1817     uint32_t sink_index, syncid, missing;
1818     pa_buffer_attr attr;
1819     const char *name = NULL, *sink_name;
1820     pa_sample_spec ss;
1821     pa_channel_map map;
1822     pa_tagstruct *reply;
1823     pa_sink *sink = NULL;
1824     pa_cvolume volume;
1825     pa_bool_t
1826         corked = FALSE,
1827         no_remap = FALSE,
1828         no_remix = FALSE,
1829         fix_format = FALSE,
1830         fix_rate = FALSE,
1831         fix_channels = FALSE,
1832         no_move = FALSE,
1833         variable_rate = FALSE,
1834         muted = FALSE,
1835         adjust_latency = FALSE,
1836         early_requests = FALSE,
1837         dont_inhibit_auto_suspend = FALSE,
1838         muted_set = FALSE,
1839         fail_on_suspend = FALSE;
1840     pa_sink_input_flags_t flags = 0;
1841     pa_proplist *p;
1842     pa_bool_t volume_set = TRUE;
1843     int ret = PA_ERR_INVALID;
1844
1845     pa_native_connection_assert_ref(c);
1846     pa_assert(t);
1847     memset(&attr, 0, sizeof(attr));
1848
1849     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1850         pa_tagstruct_get(
1851                 t,
1852                 PA_TAG_SAMPLE_SPEC, &ss,
1853                 PA_TAG_CHANNEL_MAP, &map,
1854                 PA_TAG_U32, &sink_index,
1855                 PA_TAG_STRING, &sink_name,
1856                 PA_TAG_U32, &attr.maxlength,
1857                 PA_TAG_BOOLEAN, &corked,
1858                 PA_TAG_U32, &attr.tlength,
1859                 PA_TAG_U32, &attr.prebuf,
1860                 PA_TAG_U32, &attr.minreq,
1861                 PA_TAG_U32, &syncid,
1862                 PA_TAG_CVOLUME, &volume,
1863                 PA_TAG_INVALID) < 0) {
1864
1865         protocol_error(c);
1866         return;
1867     }
1868
1869     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1870     CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
1871     CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
1872     CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1873     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1874     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1875     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1876     CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1877
1878     p = pa_proplist_new();
1879
1880     if (name)
1881         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1882
1883     if (c->version >= 12)  {
1884         /* Since 0.9.8 the user can ask for a couple of additional flags */
1885
1886         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1887             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1888             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1889             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1890             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1891             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1892             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1893
1894             protocol_error(c);
1895             pa_proplist_free(p);
1896             return;
1897         }
1898     }
1899
1900     if (c->version >= 13) {
1901
1902         if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1903             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1904             pa_tagstruct_get_proplist(t, p) < 0) {
1905             protocol_error(c);
1906             pa_proplist_free(p);
1907             return;
1908         }
1909     }
1910
1911     if (c->version >= 14) {
1912
1913         if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
1914             pa_tagstruct_get_boolean(t, &early_requests) < 0) {
1915             protocol_error(c);
1916             pa_proplist_free(p);
1917             return;
1918         }
1919     }
1920
1921     if (c->version >= 15) {
1922
1923         if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
1924             pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
1925             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
1926             protocol_error(c);
1927             pa_proplist_free(p);
1928             return;
1929         }
1930     }
1931
1932     if (!pa_tagstruct_eof(t)) {
1933         protocol_error(c);
1934         pa_proplist_free(p);
1935         return;
1936     }
1937
1938     if (sink_index != PA_INVALID_INDEX) {
1939
1940         if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1941             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1942             pa_proplist_free(p);
1943             return;
1944         }
1945
1946     } else if (sink_name) {
1947
1948         if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
1949             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1950             pa_proplist_free(p);
1951             return;
1952         }
1953     }
1954
1955     flags =
1956         (corked ?  PA_SINK_INPUT_START_CORKED : 0) |
1957         (no_remap ?  PA_SINK_INPUT_NO_REMAP : 0) |
1958         (no_remix ?  PA_SINK_INPUT_NO_REMIX : 0) |
1959         (fix_format ?  PA_SINK_INPUT_FIX_FORMAT : 0) |
1960         (fix_rate ?  PA_SINK_INPUT_FIX_RATE : 0) |
1961         (fix_channels ?  PA_SINK_INPUT_FIX_CHANNELS : 0) |
1962         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
1963         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0) |
1964         (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
1965         (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0);
1966
1967     /* Only since protocol version 15 there's a seperate muted_set
1968      * flag. For older versions we synthesize it here */
1969     muted_set = muted_set || muted;
1970
1971     s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
1972     pa_proplist_free(p);
1973
1974     CHECK_VALIDITY(c->pstream, s, tag, ret);
1975
1976     reply = reply_new(tag);
1977     pa_tagstruct_putu32(reply, s->index);
1978     pa_assert(s->sink_input);
1979     pa_tagstruct_putu32(reply, s->sink_input->index);
1980     pa_tagstruct_putu32(reply, missing);
1981
1982 /*     pa_log("initial request is %u", missing); */
1983
1984     if (c->version >= 9) {
1985         /* Since 0.9.0 we support sending the buffer metrics back to the client */
1986
1987         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
1988         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
1989         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
1990         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
1991     }
1992
1993     if (c->version >= 12) {
1994         /* Since 0.9.8 we support sending the chosen sample
1995          * spec/channel map/device/suspend status back to the
1996          * client */
1997
1998         pa_tagstruct_put_sample_spec(reply, &ss);
1999         pa_tagstruct_put_channel_map(reply, &map);
2000
2001         pa_tagstruct_putu32(reply, s->sink_input->sink->index);
2002         pa_tagstruct_puts(reply, s->sink_input->sink->name);
2003
2004         pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
2005     }
2006
2007     if (c->version >= 13)
2008         pa_tagstruct_put_usec(reply, s->configured_sink_latency);
2009
2010     pa_pstream_send_tagstruct(c->pstream, reply);
2011 }
2012
2013 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2014     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2015     uint32_t channel;
2016
2017     pa_native_connection_assert_ref(c);
2018     pa_assert(t);
2019
2020     if (pa_tagstruct_getu32(t, &channel) < 0 ||
2021         !pa_tagstruct_eof(t)) {
2022         protocol_error(c);
2023         return;
2024     }
2025
2026     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2027
2028     switch (command) {
2029
2030         case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2031             playback_stream *s;
2032             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2033                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2034                 return;
2035             }
2036
2037             playback_stream_unlink(s);
2038             break;
2039         }
2040
2041         case PA_COMMAND_DELETE_RECORD_STREAM: {
2042             record_stream *s;
2043             if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2044                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2045                 return;
2046             }
2047
2048             record_stream_unlink(s);
2049             break;
2050         }
2051
2052         case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2053             upload_stream *s;
2054
2055             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2056                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2057                 return;
2058             }
2059
2060             upload_stream_unlink(s);
2061             break;
2062         }
2063
2064         default:
2065             pa_assert_not_reached();
2066     }
2067
2068     pa_pstream_send_simple_ack(c->pstream, tag);
2069 }
2070
2071 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2072     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2073     record_stream *s;
2074     pa_buffer_attr attr;
2075     uint32_t source_index;
2076     const char *name = NULL, *source_name;
2077     pa_sample_spec ss;
2078     pa_channel_map map;
2079     pa_tagstruct *reply;
2080     pa_source *source = NULL;
2081     pa_bool_t
2082         corked = FALSE,
2083         no_remap = FALSE,
2084         no_remix = FALSE,
2085         fix_format = FALSE,
2086         fix_rate = FALSE,
2087         fix_channels = FALSE,
2088         no_move = FALSE,
2089         variable_rate = FALSE,
2090         adjust_latency = FALSE,
2091         peak_detect = FALSE,
2092         early_requests = FALSE,
2093         dont_inhibit_auto_suspend = FALSE,
2094         fail_on_suspend = FALSE;
2095     pa_source_output_flags_t flags = 0;
2096     pa_proplist *p;
2097     uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2098     pa_sink_input *direct_on_input = NULL;
2099     int ret = PA_ERR_INVALID;
2100
2101     pa_native_connection_assert_ref(c);
2102     pa_assert(t);
2103
2104     memset(&attr, 0, sizeof(attr));
2105
2106     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2107         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2108         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2109         pa_tagstruct_getu32(t, &source_index) < 0 ||
2110         pa_tagstruct_gets(t, &source_name) < 0 ||
2111         pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2112         pa_tagstruct_get_boolean(t, &corked) < 0 ||
2113         pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2114         protocol_error(c);
2115         return;
2116     }
2117
2118     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2119     CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
2120     CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
2121     CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2122     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2123     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2124     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2125
2126     p = pa_proplist_new();
2127
2128     if (name)
2129         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2130
2131     if (c->version >= 12)  {
2132         /* Since 0.9.8 the user can ask for a couple of additional flags */
2133
2134         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2135             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2136             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2137             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2138             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2139             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2140             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2141
2142             protocol_error(c);
2143             pa_proplist_free(p);
2144             return;
2145         }
2146     }
2147
2148     if (c->version >= 13) {
2149
2150         if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2151             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2152             pa_tagstruct_get_proplist(t, p) < 0 ||
2153             pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2154             protocol_error(c);
2155             pa_proplist_free(p);
2156             return;
2157         }
2158     }
2159
2160     if (c->version >= 14) {
2161
2162         if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2163             protocol_error(c);
2164             pa_proplist_free(p);
2165             return;
2166         }
2167     }
2168
2169     if (c->version >= 15) {
2170
2171         if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2172             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2173             protocol_error(c);
2174             pa_proplist_free(p);
2175             return;
2176         }
2177     }
2178
2179     if (!pa_tagstruct_eof(t)) {
2180         protocol_error(c);
2181         pa_proplist_free(p);
2182         return;
2183     }
2184
2185     if (source_index != PA_INVALID_INDEX) {
2186
2187         if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2188             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2189             pa_proplist_free(p);
2190             return;
2191         }
2192
2193     } else if (source_name) {
2194
2195         if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2196             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2197             pa_proplist_free(p);
2198             return;
2199         }
2200     }
2201
2202     if (direct_on_input_idx != PA_INVALID_INDEX) {
2203
2204         if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2205             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2206             pa_proplist_free(p);
2207             return;
2208         }
2209     }
2210
2211     flags =
2212         (corked ?  PA_SOURCE_OUTPUT_START_CORKED : 0) |
2213         (no_remap ?  PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2214         (no_remix ?  PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2215         (fix_format ?  PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2216         (fix_rate ?  PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2217         (fix_channels ?  PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2218         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2219         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2220         (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2221         (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0);
2222
2223     s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
2224     pa_proplist_free(p);
2225
2226     CHECK_VALIDITY(c->pstream, s, tag, ret);
2227
2228     reply = reply_new(tag);
2229     pa_tagstruct_putu32(reply, s->index);
2230     pa_assert(s->source_output);
2231     pa_tagstruct_putu32(reply, s->source_output->index);
2232
2233     if (c->version >= 9) {
2234         /* Since 0.9 we support sending the buffer metrics back to the client */
2235
2236         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2237         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2238     }
2239
2240     if (c->version >= 12) {
2241         /* Since 0.9.8 we support sending the chosen sample
2242          * spec/channel map/device/suspend status back to the
2243          * client */
2244
2245         pa_tagstruct_put_sample_spec(reply, &ss);
2246         pa_tagstruct_put_channel_map(reply, &map);
2247
2248         pa_tagstruct_putu32(reply, s->source_output->source->index);
2249         pa_tagstruct_puts(reply, s->source_output->source->name);
2250
2251         pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2252     }
2253
2254     if (c->version >= 13)
2255         pa_tagstruct_put_usec(reply, s->configured_source_latency);
2256
2257     pa_pstream_send_tagstruct(c->pstream, reply);
2258 }
2259
2260 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2261     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2262     int ret;
2263
2264     pa_native_connection_assert_ref(c);
2265     pa_assert(t);
2266
2267     if (!pa_tagstruct_eof(t)) {
2268         protocol_error(c);
2269         return;
2270     }
2271
2272     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2273     ret = pa_core_exit(c->protocol->core, FALSE, 0);
2274     CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2275
2276     pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
2277
2278     pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2279 }
2280
2281 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2282     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2283     const void*cookie;
2284     pa_tagstruct *reply;
2285     pa_bool_t shm_on_remote = FALSE, do_shm;
2286
2287     pa_native_connection_assert_ref(c);
2288     pa_assert(t);
2289
2290     if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2291         pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2292         !pa_tagstruct_eof(t)) {
2293         protocol_error(c);
2294         return;
2295     }
2296
2297     /* Minimum supported version */
2298     if (c->version < 8) {
2299         pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2300         return;
2301     }
2302
2303     /* Starting with protocol version 13 the MSB of the version tag
2304        reflects if shm is available for this pa_native_connection or
2305        not. */
2306     if (c->version >= 13) {
2307         shm_on_remote = !!(c->version & 0x80000000U);
2308         c->version &= 0x7FFFFFFFU;
2309     }
2310
2311     pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2312
2313     pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2314
2315     if (!c->authorized) {
2316         pa_bool_t success = FALSE;
2317
2318 #ifdef HAVE_CREDS
2319         const pa_creds *creds;
2320
2321         if ((creds = pa_pdispatch_creds(pd))) {
2322             if (creds->uid == getuid())
2323                 success = TRUE;
2324             else if (c->options->auth_group) {
2325                 int r;
2326                 gid_t gid;
2327
2328                 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2329                     pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2330                 else if (gid == creds->gid)
2331                     success = TRUE;
2332
2333                 if (!success) {
2334                     if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2335                         pa_log_warn("Failed to check group membership.");
2336                     else if (r > 0)
2337                         success = TRUE;
2338                 }
2339             }
2340
2341             pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2342                         (unsigned long) creds->uid,
2343                         (unsigned long) creds->gid,
2344                         (int) success);
2345         }
2346 #endif
2347
2348         if (!success && c->options->auth_cookie) {
2349             const uint8_t *ac;
2350
2351             if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2352                 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2353                     success = TRUE;
2354         }
2355
2356         if (!success) {
2357             pa_log_warn("Denied access to client with invalid authorization data.");
2358             pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2359             return;
2360         }
2361
2362         c->authorized = TRUE;
2363         if (c->auth_timeout_event) {
2364             c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2365             c->auth_timeout_event = NULL;
2366         }
2367     }
2368
2369     /* Enable shared memory support if possible */
2370     do_shm =
2371         pa_mempool_is_shared(c->protocol->core->mempool) &&
2372         c->is_local;
2373
2374     pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2375
2376     if (do_shm)
2377         if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2378             do_shm = FALSE;
2379
2380 #ifdef HAVE_CREDS
2381     if (do_shm) {
2382         /* Only enable SHM if both sides are owned by the same
2383          * user. This is a security measure because otherwise data
2384          * private to the user might leak. */
2385
2386         const pa_creds *creds;
2387         if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2388             do_shm = FALSE;
2389     }
2390 #endif
2391
2392     pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2393     pa_pstream_enable_shm(c->pstream, do_shm);
2394
2395     reply = reply_new(tag);
2396     pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2397
2398 #ifdef HAVE_CREDS
2399 {
2400     /* SHM support is only enabled after both sides made sure they are the same user. */
2401
2402     pa_creds ucred;
2403
2404     ucred.uid = getuid();
2405     ucred.gid = getgid();
2406
2407     pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2408 }
2409 #else
2410     pa_pstream_send_tagstruct(c->pstream, reply);
2411 #endif
2412 }
2413
2414 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2415     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2416     const char *name = NULL;
2417     pa_proplist *p;
2418     pa_tagstruct *reply;
2419
2420     pa_native_connection_assert_ref(c);
2421     pa_assert(t);
2422
2423     p = pa_proplist_new();
2424
2425     if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2426         (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2427         !pa_tagstruct_eof(t)) {
2428
2429         protocol_error(c);
2430         pa_proplist_free(p);
2431         return;
2432     }
2433
2434     if (name)
2435         if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2436             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2437             pa_proplist_free(p);
2438             return;
2439         }
2440
2441     pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2442     pa_proplist_free(p);
2443
2444     reply = reply_new(tag);
2445
2446     if (c->version >= 13)
2447         pa_tagstruct_putu32(reply, c->client->index);
2448
2449     pa_pstream_send_tagstruct(c->pstream, reply);
2450 }
2451
2452 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2453     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2454     const char *name;
2455     uint32_t idx = PA_IDXSET_INVALID;
2456
2457     pa_native_connection_assert_ref(c);
2458     pa_assert(t);
2459
2460     if (pa_tagstruct_gets(t, &name) < 0 ||
2461         !pa_tagstruct_eof(t)) {
2462         protocol_error(c);
2463         return;
2464     }
2465
2466     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2467     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);
2468
2469     if (command == PA_COMMAND_LOOKUP_SINK) {
2470         pa_sink *sink;
2471         if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2472             idx = sink->index;
2473     } else {
2474         pa_source *source;
2475         pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2476         if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2477             idx = source->index;
2478     }
2479
2480     if (idx == PA_IDXSET_INVALID)
2481         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2482     else {
2483         pa_tagstruct *reply;
2484         reply = reply_new(tag);
2485         pa_tagstruct_putu32(reply, idx);
2486         pa_pstream_send_tagstruct(c->pstream, reply);
2487     }
2488 }
2489
2490 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2491     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2492     uint32_t idx;
2493     playback_stream *s;
2494
2495     pa_native_connection_assert_ref(c);
2496     pa_assert(t);
2497
2498     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2499         !pa_tagstruct_eof(t)) {
2500         protocol_error(c);
2501         return;
2502     }
2503
2504     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2505     s = pa_idxset_get_by_index(c->output_streams, idx);
2506     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2507     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2508
2509     pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL);
2510 }
2511
2512 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2513     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2514     pa_tagstruct *reply;
2515     const pa_mempool_stat *stat;
2516
2517     pa_native_connection_assert_ref(c);
2518     pa_assert(t);
2519
2520     if (!pa_tagstruct_eof(t)) {
2521         protocol_error(c);
2522         return;
2523     }
2524
2525     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2526
2527     stat = pa_mempool_get_stat(c->protocol->core->mempool);
2528
2529     reply = reply_new(tag);
2530     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2531     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2532     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2533     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2534     pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2535     pa_pstream_send_tagstruct(c->pstream, reply);
2536 }
2537
2538 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2539     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2540     pa_tagstruct *reply;
2541     playback_stream *s;
2542     struct timeval tv, now;
2543     uint32_t idx;
2544
2545     pa_native_connection_assert_ref(c);
2546     pa_assert(t);
2547
2548     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2549         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2550         !pa_tagstruct_eof(t)) {
2551         protocol_error(c);
2552         return;
2553     }
2554
2555     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2556     s = pa_idxset_get_by_index(c->output_streams, idx);
2557     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2558     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2559
2560     /* Get an atomic snapshot of all timing parameters */
2561     pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2562
2563     reply = reply_new(tag);
2564     pa_tagstruct_put_usec(reply,
2565                           s->current_sink_latency +
2566                           pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2567     pa_tagstruct_put_usec(reply, 0);
2568     pa_tagstruct_put_boolean(reply,
2569                              s->playing_for > 0 &&
2570                              pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2571                              pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2572     pa_tagstruct_put_timeval(reply, &tv);
2573     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2574     pa_tagstruct_puts64(reply, s->write_index);
2575     pa_tagstruct_puts64(reply, s->read_index);
2576
2577     if (c->version >= 13) {
2578         pa_tagstruct_putu64(reply, s->underrun_for);
2579         pa_tagstruct_putu64(reply, s->playing_for);
2580     }
2581
2582     pa_pstream_send_tagstruct(c->pstream, reply);
2583 }
2584
2585 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2586     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2587     pa_tagstruct *reply;
2588     record_stream *s;
2589     struct timeval tv, now;
2590     uint32_t idx;
2591
2592     pa_native_connection_assert_ref(c);
2593     pa_assert(t);
2594
2595     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2596         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2597         !pa_tagstruct_eof(t)) {
2598         protocol_error(c);
2599         return;
2600     }
2601
2602     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2603     s = pa_idxset_get_by_index(c->record_streams, idx);
2604     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2605
2606     /* Get an atomic snapshot of all timing parameters */
2607     pa_assert_se(pa_asyncmsgq_send(s->source_output->source->asyncmsgq, PA_MSGOBJECT(s->source_output), SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2608
2609     reply = reply_new(tag);
2610     pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2611     pa_tagstruct_put_usec(reply,
2612                           s->current_source_latency +
2613                           pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
2614     pa_tagstruct_put_boolean(reply,
2615                              pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2616                              pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2617     pa_tagstruct_put_timeval(reply, &tv);
2618     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2619     pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2620     pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2621     pa_pstream_send_tagstruct(c->pstream, reply);
2622 }
2623
2624 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2625     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2626     upload_stream *s;
2627     uint32_t length;
2628     const char *name = NULL;
2629     pa_sample_spec ss;
2630     pa_channel_map map;
2631     pa_tagstruct *reply;
2632     pa_proplist *p;
2633
2634     pa_native_connection_assert_ref(c);
2635     pa_assert(t);
2636
2637     if (pa_tagstruct_gets(t, &name) < 0 ||
2638         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2639         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2640         pa_tagstruct_getu32(t, &length) < 0) {
2641         protocol_error(c);
2642         return;
2643     }
2644
2645     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2646     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2647     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2648     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2649     CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2650     CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2651
2652     p = pa_proplist_new();
2653
2654     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2655         !pa_tagstruct_eof(t)) {
2656
2657         protocol_error(c);
2658         pa_proplist_free(p);
2659         return;
2660     }
2661
2662     if (c->version < 13)
2663         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2664     else if (!name)
2665         if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2666             name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2667
2668     if (!name || !pa_namereg_is_valid_name(name)) {
2669         pa_proplist_free(p);
2670         CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
2671     }
2672
2673     s = upload_stream_new(c, &ss, &map, name, length, p);
2674     pa_proplist_free(p);
2675
2676     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2677
2678     reply = reply_new(tag);
2679     pa_tagstruct_putu32(reply, s->index);
2680     pa_tagstruct_putu32(reply, length);
2681     pa_pstream_send_tagstruct(c->pstream, reply);
2682 }
2683
2684 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2685     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2686     uint32_t channel;
2687     upload_stream *s;
2688     uint32_t idx;
2689
2690     pa_native_connection_assert_ref(c);
2691     pa_assert(t);
2692
2693     if (pa_tagstruct_getu32(t, &channel) < 0 ||
2694         !pa_tagstruct_eof(t)) {
2695         protocol_error(c);
2696         return;
2697     }
2698
2699     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2700
2701     s = pa_idxset_get_by_index(c->output_streams, channel);
2702     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2703     CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2704
2705     if (!s->memchunk.memblock)
2706         pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
2707     else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2708         pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2709     else
2710         pa_pstream_send_simple_ack(c->pstream, tag);
2711
2712     upload_stream_unlink(s);
2713 }
2714
2715 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2716     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2717     uint32_t sink_index;
2718     pa_volume_t volume;
2719     pa_sink *sink;
2720     const char *name, *sink_name;
2721     uint32_t idx;
2722     pa_proplist *p;
2723     pa_tagstruct *reply;
2724
2725     pa_native_connection_assert_ref(c);
2726     pa_assert(t);
2727
2728     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2729
2730     if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2731         pa_tagstruct_gets(t, &sink_name) < 0 ||
2732         pa_tagstruct_getu32(t, &volume) < 0 ||
2733         pa_tagstruct_gets(t, &name) < 0) {
2734         protocol_error(c);
2735         return;
2736     }
2737
2738     CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
2739     CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2740     CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2741     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2742
2743     if (sink_index != PA_INVALID_INDEX)
2744         sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2745     else
2746         sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2747
2748     CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2749
2750     p = pa_proplist_new();
2751
2752     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2753         !pa_tagstruct_eof(t)) {
2754         protocol_error(c);
2755         pa_proplist_free(p);
2756         return;
2757     }
2758
2759     pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2760
2761     if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2762         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2763         pa_proplist_free(p);
2764         return;
2765     }
2766
2767     pa_proplist_free(p);
2768
2769     reply = reply_new(tag);
2770
2771     if (c->version >= 13)
2772         pa_tagstruct_putu32(reply, idx);
2773
2774     pa_pstream_send_tagstruct(c->pstream, reply);
2775 }
2776
2777 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2778     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2779     const char *name;
2780
2781     pa_native_connection_assert_ref(c);
2782     pa_assert(t);
2783
2784     if (pa_tagstruct_gets(t, &name) < 0 ||
2785         !pa_tagstruct_eof(t)) {
2786         protocol_error(c);
2787         return;
2788     }
2789
2790     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2791     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2792
2793     if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2794         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2795         return;
2796     }
2797
2798     pa_pstream_send_simple_ack(c->pstream, tag);
2799 }
2800
2801 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
2802     pa_assert(c);
2803     pa_assert(fixed);
2804     pa_assert(original);
2805
2806     *fixed = *original;
2807
2808     if (c->version < 12) {
2809         /* Before protocol version 12 we didn't support S32 samples,
2810          * so we need to lie about this to the client */
2811
2812         if (fixed->format == PA_SAMPLE_S32LE)
2813             fixed->format = PA_SAMPLE_FLOAT32LE;
2814         if (fixed->format == PA_SAMPLE_S32BE)
2815             fixed->format = PA_SAMPLE_FLOAT32BE;
2816     }
2817
2818     if (c->version < 15) {
2819         if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
2820             fixed->format = PA_SAMPLE_FLOAT32LE;
2821         if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
2822             fixed->format = PA_SAMPLE_FLOAT32BE;
2823     }
2824 }
2825
2826 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
2827     pa_sample_spec fixed_ss;
2828
2829     pa_assert(t);
2830     pa_sink_assert_ref(sink);
2831
2832     fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
2833
2834     pa_tagstruct_put(
2835         t,
2836         PA_TAG_U32, sink->index,
2837         PA_TAG_STRING, sink->name,
2838         PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2839         PA_TAG_SAMPLE_SPEC, &fixed_ss,
2840         PA_TAG_CHANNEL_MAP, &sink->channel_map,
2841         PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
2842         PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE),
2843         PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE),
2844         PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
2845         PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
2846         PA_TAG_USEC, pa_sink_get_latency(sink),
2847         PA_TAG_STRING, sink->driver,
2848         PA_TAG_U32, sink->flags,
2849         PA_TAG_INVALID);
2850
2851     if (c->version >= 13) {
2852         pa_tagstruct_put_proplist(t, sink->proplist);
2853         pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
2854     }
2855
2856     if (c->version >= 15) {
2857         pa_tagstruct_put_volume(t, sink->base_volume);
2858         if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
2859             pa_log_error("Internal sink state is invalid.");
2860         pa_tagstruct_putu32(t, pa_sink_get_state(sink));
2861         pa_tagstruct_putu32(t, sink->n_volume_steps);
2862         pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
2863     }
2864
2865     if (c->version >= 16) {
2866         pa_tagstruct_putu32(t, sink->ports ? pa_hashmap_size(sink->ports) : 0);
2867
2868         if (sink->ports) {
2869             void *state;
2870             pa_device_port *p;
2871
2872             PA_HASHMAP_FOREACH(p, sink->ports, state) {
2873                 pa_tagstruct_puts(t, p->name);
2874                 pa_tagstruct_puts(t, p->description);
2875                 pa_tagstruct_putu32(t, p->priority);
2876             }
2877         }
2878
2879         pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
2880     }
2881 }
2882
2883 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
2884     pa_sample_spec fixed_ss;
2885
2886     pa_assert(t);
2887     pa_source_assert_ref(source);
2888
2889     fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
2890
2891     pa_tagstruct_put(
2892         t,
2893         PA_TAG_U32, source->index,
2894         PA_TAG_STRING, source->name,
2895         PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2896         PA_TAG_SAMPLE_SPEC, &fixed_ss,
2897         PA_TAG_CHANNEL_MAP, &source->channel_map,
2898         PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
2899         PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE),
2900         PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE),
2901         PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
2902         PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
2903         PA_TAG_USEC, pa_source_get_latency(source),
2904         PA_TAG_STRING, source->driver,
2905         PA_TAG_U32, source->flags,
2906         PA_TAG_INVALID);
2907
2908     if (c->version >= 13) {
2909         pa_tagstruct_put_proplist(t, source->proplist);
2910         pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
2911     }
2912
2913     if (c->version >= 15) {
2914         pa_tagstruct_put_volume(t, source->base_volume);
2915         if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
2916             pa_log_error("Internal source state is invalid.");
2917         pa_tagstruct_putu32(t, pa_source_get_state(source));
2918         pa_tagstruct_putu32(t, source->n_volume_steps);
2919         pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
2920     }
2921
2922     if (c->version >= 16) {
2923
2924         pa_tagstruct_putu32(t, source->ports ? pa_hashmap_size(source->ports) : 0);
2925
2926         if (source->ports) {
2927             void *state;
2928             pa_device_port *p;
2929
2930             PA_HASHMAP_FOREACH(p, source->ports, state) {
2931                 pa_tagstruct_puts(t, p->name);
2932                 pa_tagstruct_puts(t, p->description);
2933                 pa_tagstruct_putu32(t, p->priority);
2934             }
2935         }
2936
2937         pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
2938     }
2939 }
2940
2941 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
2942     pa_assert(t);
2943     pa_assert(client);
2944
2945     pa_tagstruct_putu32(t, client->index);
2946     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
2947     pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
2948     pa_tagstruct_puts(t, client->driver);
2949
2950     if (c->version >= 13)
2951         pa_tagstruct_put_proplist(t, client->proplist);
2952 }
2953
2954 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
2955     void *state = NULL;
2956     pa_card_profile *p;
2957
2958     pa_assert(t);
2959     pa_assert(card);
2960
2961     pa_tagstruct_putu32(t, card->index);
2962     pa_tagstruct_puts(t, card->name);
2963     pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
2964     pa_tagstruct_puts(t, card->driver);
2965
2966     pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
2967
2968     if (card->profiles) {
2969         while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
2970             pa_tagstruct_puts(t, p->name);
2971             pa_tagstruct_puts(t, p->description);
2972             pa_tagstruct_putu32(t, p->n_sinks);
2973             pa_tagstruct_putu32(t, p->n_sources);
2974             pa_tagstruct_putu32(t, p->priority);
2975         }
2976     }
2977
2978     pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
2979     pa_tagstruct_put_proplist(t, card->proplist);
2980 }
2981
2982 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
2983     pa_assert(t);
2984     pa_assert(module);
2985
2986     pa_tagstruct_putu32(t, module->index);
2987     pa_tagstruct_puts(t, module->name);
2988     pa_tagstruct_puts(t, module->argument);
2989     pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
2990
2991     if (c->version < 15)
2992         pa_tagstruct_put_boolean(t, FALSE); /* autoload is obsolete */
2993
2994     if (c->version >= 15)
2995         pa_tagstruct_put_proplist(t, module->proplist);
2996 }
2997
2998 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
2999     pa_sample_spec fixed_ss;
3000     pa_usec_t sink_latency;
3001     pa_cvolume v;
3002
3003     pa_assert(t);
3004     pa_sink_input_assert_ref(s);
3005
3006     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3007
3008     pa_tagstruct_putu32(t, s->index);
3009     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3010     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3011     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3012     pa_tagstruct_putu32(t, s->sink->index);
3013     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3014     pa_tagstruct_put_channel_map(t, &s->channel_map);
3015     pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s, &v, TRUE));
3016     pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3017     pa_tagstruct_put_usec(t, sink_latency);
3018     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3019     pa_tagstruct_puts(t, s->driver);
3020     if (c->version >= 11)
3021         pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
3022     if (c->version >= 13)
3023         pa_tagstruct_put_proplist(t, s->proplist);
3024 }
3025
3026 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3027     pa_sample_spec fixed_ss;
3028     pa_usec_t source_latency;
3029
3030     pa_assert(t);
3031     pa_source_output_assert_ref(s);
3032
3033     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3034
3035     pa_tagstruct_putu32(t, s->index);
3036     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3037     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3038     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3039     pa_tagstruct_putu32(t, s->source->index);
3040     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3041     pa_tagstruct_put_channel_map(t, &s->channel_map);
3042     pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3043     pa_tagstruct_put_usec(t, source_latency);
3044     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3045     pa_tagstruct_puts(t, s->driver);
3046
3047     if (c->version >= 13)
3048         pa_tagstruct_put_proplist(t, s->proplist);
3049 }
3050
3051 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3052     pa_sample_spec fixed_ss;
3053     pa_cvolume v;
3054
3055     pa_assert(t);
3056     pa_assert(e);
3057
3058     if (e->memchunk.memblock)
3059         fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3060     else
3061         memset(&fixed_ss, 0, sizeof(fixed_ss));
3062
3063     pa_tagstruct_putu32(t, e->index);
3064     pa_tagstruct_puts(t, e->name);
3065
3066     if (e->volume_is_set)
3067         v = e->volume;
3068     else
3069         pa_cvolume_init(&v);
3070
3071     pa_tagstruct_put_cvolume(t, &v);
3072     pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3073     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3074     pa_tagstruct_put_channel_map(t, &e->channel_map);
3075     pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3076     pa_tagstruct_put_boolean(t, e->lazy);
3077     pa_tagstruct_puts(t, e->filename);
3078
3079     if (c->version >= 13)
3080         pa_tagstruct_put_proplist(t, e->proplist);
3081 }
3082
3083 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3084     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3085     uint32_t idx;
3086     pa_sink *sink = NULL;
3087     pa_source *source = NULL;
3088     pa_client *client = NULL;
3089     pa_card *card = NULL;
3090     pa_module *module = NULL;
3091     pa_sink_input *si = NULL;
3092     pa_source_output *so = NULL;
3093     pa_scache_entry *sce = NULL;
3094     const char *name = NULL;
3095     pa_tagstruct *reply;
3096
3097     pa_native_connection_assert_ref(c);
3098     pa_assert(t);
3099
3100     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3101         (command != PA_COMMAND_GET_CLIENT_INFO &&
3102          command != PA_COMMAND_GET_MODULE_INFO &&
3103          command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3104          command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3105          pa_tagstruct_gets(t, &name) < 0) ||
3106         !pa_tagstruct_eof(t)) {
3107         protocol_error(c);
3108         return;
3109     }
3110
3111     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3112     CHECK_VALIDITY(c->pstream, !name ||
3113                    (command == PA_COMMAND_GET_SINK_INFO &&
3114                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3115                    (command == PA_COMMAND_GET_SOURCE_INFO &&
3116                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3117                    pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3118     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3119     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3120     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3121
3122     if (command == PA_COMMAND_GET_SINK_INFO) {
3123         if (idx != PA_INVALID_INDEX)
3124             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3125         else
3126             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3127     } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3128         if (idx != PA_INVALID_INDEX)
3129             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3130         else
3131             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3132     } else if (command == PA_COMMAND_GET_CARD_INFO) {
3133         if (idx != PA_INVALID_INDEX)
3134             card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3135         else
3136             card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3137     } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3138         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3139     else if (command == PA_COMMAND_GET_MODULE_INFO)
3140         module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3141     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3142         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3143     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3144         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3145     else {
3146         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3147         if (idx != PA_INVALID_INDEX)
3148             sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3149         else
3150             sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3151     }
3152
3153     if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3154         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3155         return;
3156     }
3157
3158     reply = reply_new(tag);
3159     if (sink)
3160         sink_fill_tagstruct(c, reply, sink);
3161     else if (source)
3162         source_fill_tagstruct(c, reply, source);
3163     else if (client)
3164         client_fill_tagstruct(c, reply, client);
3165     else if (card)
3166         card_fill_tagstruct(c, reply, card);
3167     else if (module)
3168         module_fill_tagstruct(c, reply, module);
3169     else if (si)
3170         sink_input_fill_tagstruct(c, reply, si);
3171     else if (so)
3172         source_output_fill_tagstruct(c, reply, so);
3173     else
3174         scache_fill_tagstruct(c, reply, sce);
3175     pa_pstream_send_tagstruct(c->pstream, reply);
3176 }
3177
3178 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3179     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3180     pa_idxset *i;
3181     uint32_t idx;
3182     void *p;
3183     pa_tagstruct *reply;
3184
3185     pa_native_connection_assert_ref(c);
3186     pa_assert(t);
3187
3188     if (!pa_tagstruct_eof(t)) {
3189         protocol_error(c);
3190         return;
3191     }
3192
3193     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3194
3195     reply = reply_new(tag);
3196
3197     if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3198         i = c->protocol->core->sinks;
3199     else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3200         i = c->protocol->core->sources;
3201     else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3202         i = c->protocol->core->clients;
3203     else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3204         i = c->protocol->core->cards;
3205     else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3206         i = c->protocol->core->modules;
3207     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3208         i = c->protocol->core->sink_inputs;
3209     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3210         i = c->protocol->core->source_outputs;
3211     else {
3212         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3213         i = c->protocol->core->scache;
3214     }
3215
3216     if (i) {
3217         for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3218             if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3219                 sink_fill_tagstruct(c, reply, p);
3220             else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3221                 source_fill_tagstruct(c, reply, p);
3222             else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3223                 client_fill_tagstruct(c, reply, p);
3224             else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3225                 card_fill_tagstruct(c, reply, p);
3226             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3227                 module_fill_tagstruct(c, reply, p);
3228             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3229                 sink_input_fill_tagstruct(c, reply, p);
3230             else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3231                 source_output_fill_tagstruct(c, reply, p);
3232             else {
3233                 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3234                 scache_fill_tagstruct(c, reply, p);
3235             }
3236         }
3237     }
3238
3239     pa_pstream_send_tagstruct(c->pstream, reply);
3240 }
3241
3242 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3243     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3244     pa_tagstruct *reply;
3245     pa_sink *def_sink;
3246     pa_source *def_source;
3247     pa_sample_spec fixed_ss;
3248     char *h, *u;
3249
3250     pa_native_connection_assert_ref(c);
3251     pa_assert(t);
3252
3253     if (!pa_tagstruct_eof(t)) {
3254         protocol_error(c);
3255         return;
3256     }
3257
3258     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3259
3260     reply = reply_new(tag);
3261     pa_tagstruct_puts(reply, PACKAGE_NAME);
3262     pa_tagstruct_puts(reply, PACKAGE_VERSION);
3263
3264     u = pa_get_user_name_malloc();
3265     pa_tagstruct_puts(reply, u);
3266     pa_xfree(u);
3267
3268     h = pa_get_host_name_malloc();
3269     pa_tagstruct_puts(reply, h);
3270     pa_xfree(h);
3271
3272     fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3273     pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3274
3275     def_sink = pa_namereg_get_default_sink(c->protocol->core);
3276     pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3277     def_source = pa_namereg_get_default_source(c->protocol->core);
3278     pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3279
3280     pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3281
3282     if (c->version >= 15)
3283         pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3284
3285     pa_pstream_send_tagstruct(c->pstream, reply);
3286 }
3287
3288 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3289     pa_tagstruct *t;
3290     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3291
3292     pa_native_connection_assert_ref(c);
3293
3294     t = pa_tagstruct_new(NULL, 0);
3295     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3296     pa_tagstruct_putu32(t, (uint32_t) -1);
3297     pa_tagstruct_putu32(t, e);
3298     pa_tagstruct_putu32(t, idx);
3299     pa_pstream_send_tagstruct(c->pstream, t);
3300 }
3301
3302 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3303     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3304     pa_subscription_mask_t m;
3305
3306     pa_native_connection_assert_ref(c);
3307     pa_assert(t);
3308
3309     if (pa_tagstruct_getu32(t, &m) < 0 ||
3310         !pa_tagstruct_eof(t)) {
3311         protocol_error(c);
3312         return;
3313     }
3314
3315     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3316     CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3317
3318     if (c->subscription)
3319         pa_subscription_free(c->subscription);
3320
3321     if (m != 0) {
3322         c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3323         pa_assert(c->subscription);
3324     } else
3325         c->subscription = NULL;
3326
3327     pa_pstream_send_simple_ack(c->pstream, tag);
3328 }
3329
3330 static void command_set_volume(
3331         pa_pdispatch *pd,
3332         uint32_t command,
3333         uint32_t tag,
3334         pa_tagstruct *t,
3335         void *userdata) {
3336
3337     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3338     uint32_t idx;
3339     pa_cvolume volume;
3340     pa_sink *sink = NULL;
3341     pa_source *source = NULL;
3342     pa_sink_input *si = NULL;
3343     const char *name = NULL;
3344     const char *client_name;
3345
3346     pa_native_connection_assert_ref(c);
3347     pa_assert(t);
3348
3349     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3350         (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3351         (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3352         pa_tagstruct_get_cvolume(t, &volume) ||
3353         !pa_tagstruct_eof(t)) {
3354         protocol_error(c);
3355         return;
3356     }
3357
3358     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3359     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);
3360     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3361     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3362     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3363     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3364
3365     switch (command) {
3366
3367         case PA_COMMAND_SET_SINK_VOLUME:
3368             if (idx != PA_INVALID_INDEX)
3369                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3370             else
3371                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3372             break;
3373
3374         case PA_COMMAND_SET_SOURCE_VOLUME:
3375             if (idx != PA_INVALID_INDEX)
3376                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3377             else
3378                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3379             break;
3380
3381         case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3382             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3383             break;
3384
3385         default:
3386             pa_assert_not_reached();
3387     }
3388
3389     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3390
3391     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3392
3393     if (sink) {
3394         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
3395
3396         pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3397         pa_sink_set_volume(sink, &volume, TRUE, TRUE);
3398     } else if (source) {
3399         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
3400
3401         pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3402         pa_source_set_volume(source, &volume, TRUE);
3403     } else if (si) {
3404         CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
3405
3406         pa_log_debug("Client %s changes volume of sink input %s.",
3407                      client_name,
3408                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3409         pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3410     }
3411
3412     pa_pstream_send_simple_ack(c->pstream, tag);
3413 }
3414
3415 static void command_set_mute(
3416         pa_pdispatch *pd,
3417         uint32_t command,
3418         uint32_t tag,
3419         pa_tagstruct *t,
3420         void *userdata) {
3421
3422     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3423     uint32_t idx;
3424     pa_bool_t mute;
3425     pa_sink *sink = NULL;
3426     pa_source *source = NULL;
3427     pa_sink_input *si = NULL;
3428     const char *name = NULL, *client_name;
3429
3430     pa_native_connection_assert_ref(c);
3431     pa_assert(t);
3432
3433     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3434         (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3435         (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3436         pa_tagstruct_get_boolean(t, &mute) ||
3437         !pa_tagstruct_eof(t)) {
3438         protocol_error(c);
3439         return;
3440     }
3441
3442     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3443     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);
3444     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3445     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3446     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3447
3448     switch (command) {
3449
3450         case PA_COMMAND_SET_SINK_MUTE:
3451             if (idx != PA_INVALID_INDEX)
3452                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3453             else
3454                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3455
3456             break;
3457
3458         case PA_COMMAND_SET_SOURCE_MUTE:
3459             if (idx != PA_INVALID_INDEX)
3460                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3461             else
3462                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3463
3464             break;
3465
3466         case PA_COMMAND_SET_SINK_INPUT_MUTE:
3467             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3468             break;
3469
3470         default:
3471             pa_assert_not_reached();
3472     }
3473
3474     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3475
3476     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3477
3478     if (sink) {
3479         pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3480         pa_sink_set_mute(sink, mute, TRUE);
3481     } else if (source) {
3482         pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3483         pa_source_set_mute(source, mute, TRUE);
3484     } else if (si) {
3485         pa_log_debug("Client %s changes mute of sink input %s.",
3486                      client_name,
3487                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3488         pa_sink_input_set_mute(si, mute, TRUE);
3489     }
3490
3491     pa_pstream_send_simple_ack(c->pstream, tag);
3492 }
3493
3494 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3495     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3496     uint32_t idx;
3497     pa_bool_t b;
3498     playback_stream *s;
3499
3500     pa_native_connection_assert_ref(c);
3501     pa_assert(t);
3502
3503     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3504         pa_tagstruct_get_boolean(t, &b) < 0 ||
3505         !pa_tagstruct_eof(t)) {
3506         protocol_error(c);
3507         return;
3508     }
3509
3510     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3511     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3512     s = pa_idxset_get_by_index(c->output_streams, idx);
3513     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3514     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3515
3516     pa_sink_input_cork(s->sink_input, b);
3517
3518     if (b)
3519         s->is_underrun = TRUE;
3520
3521     pa_pstream_send_simple_ack(c->pstream, tag);
3522 }
3523
3524 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3525     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3526     uint32_t idx;
3527     playback_stream *s;
3528
3529     pa_native_connection_assert_ref(c);
3530     pa_assert(t);
3531
3532     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3533         !pa_tagstruct_eof(t)) {
3534         protocol_error(c);
3535         return;
3536     }
3537
3538     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3539     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3540     s = pa_idxset_get_by_index(c->output_streams, idx);
3541     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3542     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3543
3544     switch (command) {
3545         case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3546             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3547             break;
3548
3549         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3550             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3551             break;
3552
3553         case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3554             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3555             break;
3556
3557         default:
3558             pa_assert_not_reached();
3559     }
3560
3561     pa_pstream_send_simple_ack(c->pstream, tag);
3562 }
3563
3564 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3565     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3566     uint32_t idx;
3567     record_stream *s;
3568     pa_bool_t b;
3569
3570     pa_native_connection_assert_ref(c);
3571     pa_assert(t);
3572
3573     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3574         pa_tagstruct_get_boolean(t, &b) < 0 ||
3575         !pa_tagstruct_eof(t)) {
3576         protocol_error(c);
3577         return;
3578     }
3579
3580     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3581     s = pa_idxset_get_by_index(c->record_streams, idx);
3582     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3583
3584     pa_source_output_cork(s->source_output, b);
3585     pa_memblockq_prebuf_force(s->memblockq);
3586     pa_pstream_send_simple_ack(c->pstream, tag);
3587 }
3588
3589 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3590     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3591     uint32_t idx;
3592     record_stream *s;
3593
3594     pa_native_connection_assert_ref(c);
3595     pa_assert(t);
3596
3597     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3598         !pa_tagstruct_eof(t)) {
3599         protocol_error(c);
3600         return;
3601     }
3602
3603     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3604     s = pa_idxset_get_by_index(c->record_streams, idx);
3605     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3606
3607     pa_memblockq_flush_read(s->memblockq);
3608     pa_pstream_send_simple_ack(c->pstream, tag);
3609 }
3610
3611 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3612     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3613     uint32_t idx;
3614     pa_buffer_attr a;
3615     pa_tagstruct *reply;
3616
3617     pa_native_connection_assert_ref(c);
3618     pa_assert(t);
3619
3620     memset(&a, 0, sizeof(a));
3621
3622     if (pa_tagstruct_getu32(t, &idx) < 0) {
3623         protocol_error(c);
3624         return;
3625     }
3626
3627     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3628
3629     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3630         playback_stream *s;
3631         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3632
3633         s = pa_idxset_get_by_index(c->output_streams, idx);
3634         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3635         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3636
3637         if (pa_tagstruct_get(
3638                     t,
3639                     PA_TAG_U32, &a.maxlength,
3640                     PA_TAG_U32, &a.tlength,
3641                     PA_TAG_U32, &a.prebuf,
3642                     PA_TAG_U32, &a.minreq,
3643                     PA_TAG_INVALID) < 0 ||
3644             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3645             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3646             !pa_tagstruct_eof(t)) {
3647             protocol_error(c);
3648             return;
3649         }
3650
3651         s->adjust_latency = adjust_latency;
3652         s->early_requests = early_requests;
3653         s->buffer_attr = a;
3654
3655         fix_playback_buffer_attr(s);
3656         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);
3657
3658         reply = reply_new(tag);
3659         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3660         pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3661         pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3662         pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3663
3664         if (c->version >= 13)
3665             pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3666
3667     } else {
3668         record_stream *s;
3669         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3670         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3671
3672         s = pa_idxset_get_by_index(c->record_streams, idx);
3673         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3674
3675         if (pa_tagstruct_get(
3676                     t,
3677                     PA_TAG_U32, &a.maxlength,
3678                     PA_TAG_U32, &a.fragsize,
3679                     PA_TAG_INVALID) < 0 ||
3680             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3681             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3682             !pa_tagstruct_eof(t)) {
3683             protocol_error(c);
3684             return;
3685         }
3686
3687         s->adjust_latency = adjust_latency;
3688         s->early_requests = early_requests;
3689         s->buffer_attr = a;
3690
3691         fix_record_buffer_attr_pre(s);
3692         pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3693         pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3694         fix_record_buffer_attr_post(s);
3695
3696         reply = reply_new(tag);
3697         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3698         pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3699
3700         if (c->version >= 13)
3701             pa_tagstruct_put_usec(reply, s->configured_source_latency);
3702     }
3703
3704     pa_pstream_send_tagstruct(c->pstream, reply);
3705 }
3706
3707 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3708     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3709     uint32_t idx;
3710     uint32_t rate;
3711
3712     pa_native_connection_assert_ref(c);
3713     pa_assert(t);
3714
3715     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3716         pa_tagstruct_getu32(t, &rate) < 0 ||
3717         !pa_tagstruct_eof(t)) {
3718         protocol_error(c);
3719         return;
3720     }
3721
3722     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3723     CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3724
3725     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3726         playback_stream *s;
3727
3728         s = pa_idxset_get_by_index(c->output_streams, idx);
3729         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3730         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3731
3732         pa_sink_input_set_rate(s->sink_input, rate);
3733
3734     } else {
3735         record_stream *s;
3736         pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3737
3738         s = pa_idxset_get_by_index(c->record_streams, idx);
3739         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3740
3741         pa_source_output_set_rate(s->source_output, rate);
3742     }
3743
3744     pa_pstream_send_simple_ack(c->pstream, tag);
3745 }
3746
3747 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3748     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3749     uint32_t idx;
3750     uint32_t mode;
3751     pa_proplist *p;
3752
3753     pa_native_connection_assert_ref(c);
3754     pa_assert(t);
3755
3756     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3757
3758     p = pa_proplist_new();
3759
3760     if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3761
3762         if (pa_tagstruct_getu32(t, &mode) < 0 ||
3763             pa_tagstruct_get_proplist(t, p) < 0 ||
3764             !pa_tagstruct_eof(t)) {
3765             protocol_error(c);
3766             pa_proplist_free(p);
3767             return;
3768         }
3769
3770     } else {
3771
3772         if (pa_tagstruct_getu32(t, &idx) < 0 ||
3773             pa_tagstruct_getu32(t, &mode) < 0 ||
3774             pa_tagstruct_get_proplist(t, p) < 0 ||
3775             !pa_tagstruct_eof(t)) {
3776             protocol_error(c);
3777             pa_proplist_free(p);
3778             return;
3779         }
3780     }
3781
3782     if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
3783         pa_proplist_free(p);
3784         CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
3785     }
3786
3787     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3788         playback_stream *s;
3789
3790         s = pa_idxset_get_by_index(c->output_streams, idx);
3791         if (!s || !playback_stream_isinstance(s)) {
3792             pa_proplist_free(p);
3793             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3794         }
3795         pa_sink_input_update_proplist(s->sink_input, mode, p);
3796
3797     } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3798         record_stream *s;
3799
3800         if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
3801             pa_proplist_free(p);
3802             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3803         }
3804         pa_source_output_update_proplist(s->source_output, mode, p);
3805
3806     } else {
3807         pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3808
3809         pa_client_update_proplist(c->client, mode, p);
3810     }
3811
3812     pa_pstream_send_simple_ack(c->pstream, tag);
3813     pa_proplist_free(p);
3814 }
3815
3816 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3817     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3818     uint32_t idx;
3819     unsigned changed = 0;
3820     pa_proplist *p;
3821     pa_strlist *l = NULL;
3822
3823     pa_native_connection_assert_ref(c);
3824     pa_assert(t);
3825
3826     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3827
3828     if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3829
3830         if (pa_tagstruct_getu32(t, &idx) < 0) {
3831             protocol_error(c);
3832             return;
3833         }
3834     }
3835
3836     if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3837         playback_stream *s;
3838
3839         s = pa_idxset_get_by_index(c->output_streams, idx);
3840         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3841         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3842
3843         p = s->sink_input->proplist;
3844
3845     } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3846         record_stream *s;
3847
3848         s = pa_idxset_get_by_index(c->record_streams, idx);
3849         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3850
3851         p = s->source_output->proplist;
3852     } else {
3853         pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3854
3855         p = c->client->proplist;
3856     }
3857
3858     for (;;) {
3859         const char *k;
3860
3861         if (pa_tagstruct_gets(t, &k) < 0) {
3862             protocol_error(c);
3863             pa_strlist_free(l);
3864             return;
3865         }
3866
3867         if (!k)
3868             break;
3869
3870         l = pa_strlist_prepend(l, k);
3871     }
3872
3873     if (!pa_tagstruct_eof(t)) {
3874         protocol_error(c);
3875         pa_strlist_free(l);
3876         return;
3877     }
3878
3879     for (;;) {
3880         char *z;
3881
3882         l = pa_strlist_pop(l, &z);
3883
3884         if (!z)
3885             break;
3886
3887         changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
3888         pa_xfree(z);
3889     }
3890
3891     pa_pstream_send_simple_ack(c->pstream, tag);
3892
3893     if (changed) {
3894         if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3895             playback_stream *s;
3896
3897             s = pa_idxset_get_by_index(c->output_streams, idx);
3898             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3899
3900         } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3901             record_stream *s;
3902
3903             s = pa_idxset_get_by_index(c->record_streams, idx);
3904             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3905
3906         } else {
3907             pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3908             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3909         }
3910     }
3911 }
3912
3913 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3914     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3915     const char *s;
3916
3917     pa_native_connection_assert_ref(c);
3918     pa_assert(t);
3919
3920     if (pa_tagstruct_gets(t, &s) < 0 ||
3921         !pa_tagstruct_eof(t)) {
3922         protocol_error(c);
3923         return;
3924     }
3925
3926     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3927     CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
3928
3929     if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
3930         pa_source *source;
3931
3932         source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
3933         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3934
3935         pa_namereg_set_default_source(c->protocol->core, source);
3936     } else {
3937         pa_sink *sink;
3938         pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
3939
3940         sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
3941         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3942
3943         pa_namereg_set_default_sink(c->protocol->core, sink);
3944     }
3945
3946     pa_pstream_send_simple_ack(c->pstream, tag);
3947 }
3948
3949 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3950     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3951     uint32_t idx;
3952     const char *name;
3953
3954     pa_native_connection_assert_ref(c);
3955     pa_assert(t);
3956
3957     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3958         pa_tagstruct_gets(t, &name) < 0 ||
3959         !pa_tagstruct_eof(t)) {
3960         protocol_error(c);
3961         return;
3962     }
3963
3964     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3965     CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3966
3967     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
3968         playback_stream *s;
3969
3970         s = pa_idxset_get_by_index(c->output_streams, idx);
3971         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3972         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3973
3974         pa_sink_input_set_name(s->sink_input, name);
3975
3976     } else {
3977         record_stream *s;
3978         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
3979
3980         s = pa_idxset_get_by_index(c->record_streams, idx);
3981         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3982
3983         pa_source_output_set_name(s->source_output, name);
3984     }
3985
3986     pa_pstream_send_simple_ack(c->pstream, tag);
3987 }
3988
3989 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3990     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3991     uint32_t idx;
3992
3993     pa_native_connection_assert_ref(c);
3994     pa_assert(t);
3995
3996     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3997         !pa_tagstruct_eof(t)) {
3998         protocol_error(c);
3999         return;
4000     }
4001
4002     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4003
4004     if (command == PA_COMMAND_KILL_CLIENT) {
4005         pa_client *client;
4006
4007         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4008         CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4009
4010         pa_native_connection_ref(c);
4011         pa_client_kill(client);
4012
4013     } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4014         pa_sink_input *s;
4015
4016         s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4017         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4018
4019         pa_native_connection_ref(c);
4020         pa_sink_input_kill(s);
4021     } else {
4022         pa_source_output *s;
4023
4024         pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4025
4026         s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4027         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4028
4029         pa_native_connection_ref(c);
4030         pa_source_output_kill(s);
4031     }
4032
4033     pa_pstream_send_simple_ack(c->pstream, tag);
4034     pa_native_connection_unref(c);
4035 }
4036
4037 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4038     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4039     pa_module *m;
4040     const char *name, *argument;
4041     pa_tagstruct *reply;
4042
4043     pa_native_connection_assert_ref(c);
4044     pa_assert(t);
4045
4046     if (pa_tagstruct_gets(t, &name) < 0 ||
4047         pa_tagstruct_gets(t, &argument) < 0 ||
4048         !pa_tagstruct_eof(t)) {
4049         protocol_error(c);
4050         return;
4051     }
4052
4053     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4054     CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4055     CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4056
4057     if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4058         pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4059         return;
4060     }
4061
4062     reply = reply_new(tag);
4063     pa_tagstruct_putu32(reply, m->index);
4064     pa_pstream_send_tagstruct(c->pstream, reply);
4065 }
4066
4067 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4068     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4069     uint32_t idx;
4070     pa_module *m;
4071
4072     pa_native_connection_assert_ref(c);
4073     pa_assert(t);
4074
4075     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4076         !pa_tagstruct_eof(t)) {
4077         protocol_error(c);
4078         return;
4079     }
4080
4081     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4082     m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4083     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4084
4085     pa_module_unload_request(m, FALSE);
4086     pa_pstream_send_simple_ack(c->pstream, tag);
4087 }
4088
4089 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4090     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4091     uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4092     const char *name_device = NULL;
4093
4094     pa_native_connection_assert_ref(c);
4095     pa_assert(t);
4096
4097     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4098         pa_tagstruct_getu32(t, &idx_device) < 0 ||
4099         pa_tagstruct_gets(t, &name_device) < 0 ||
4100         !pa_tagstruct_eof(t)) {
4101         protocol_error(c);
4102         return;
4103     }
4104
4105     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4106     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4107
4108     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);
4109     CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4110     CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4111     CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4112
4113     if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4114         pa_sink_input *si = NULL;
4115         pa_sink *sink = NULL;
4116
4117         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4118
4119         if (idx_device != PA_INVALID_INDEX)
4120             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4121         else
4122             sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4123
4124         CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4125
4126         if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4127             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4128             return;
4129         }
4130     } else {
4131         pa_source_output *so = NULL;
4132         pa_source *source;
4133
4134         pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4135
4136         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4137
4138         if (idx_device != PA_INVALID_INDEX)
4139             source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4140         else
4141             source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4142
4143         CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4144
4145         if (pa_source_output_move_to(so, source, TRUE) < 0) {
4146             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4147             return;
4148         }
4149     }
4150
4151     pa_pstream_send_simple_ack(c->pstream, tag);
4152 }
4153
4154 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4155     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4156     uint32_t idx = PA_INVALID_INDEX;
4157     const char *name = NULL;
4158     pa_bool_t b;
4159
4160     pa_native_connection_assert_ref(c);
4161     pa_assert(t);
4162
4163     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4164         pa_tagstruct_gets(t, &name) < 0 ||
4165         pa_tagstruct_get_boolean(t, &b) < 0 ||
4166         !pa_tagstruct_eof(t)) {
4167         protocol_error(c);
4168         return;
4169     }
4170
4171     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4172     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);
4173     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4174     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4175     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4176
4177     if (command == PA_COMMAND_SUSPEND_SINK) {
4178
4179         if (idx == PA_INVALID_INDEX && name && !*name) {
4180
4181             pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4182
4183             if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4184                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4185                 return;
4186             }
4187         } else {
4188             pa_sink *sink = NULL;
4189
4190             if (idx != PA_INVALID_INDEX)
4191                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4192             else
4193                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4194
4195             CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4196
4197             if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4198                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4199                 return;
4200             }
4201         }
4202     } else {
4203
4204         pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4205
4206         if (idx == PA_INVALID_INDEX && name && !*name) {
4207
4208             pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4209
4210             if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4211                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4212                 return;
4213             }
4214
4215         } else {
4216             pa_source *source;
4217
4218             if (idx != PA_INVALID_INDEX)
4219                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4220             else
4221                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4222
4223             CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4224
4225             if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4226                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4227                 return;
4228             }
4229         }
4230     }
4231
4232     pa_pstream_send_simple_ack(c->pstream, tag);
4233 }
4234
4235 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4236     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4237     uint32_t idx = PA_INVALID_INDEX;
4238     const char *name = NULL;
4239     pa_module *m;
4240     pa_native_protocol_ext_cb_t cb;
4241
4242     pa_native_connection_assert_ref(c);
4243     pa_assert(t);
4244
4245     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4246         pa_tagstruct_gets(t, &name) < 0) {
4247         protocol_error(c);
4248         return;
4249     }
4250
4251     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4252     CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4253     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4254     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4255     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4256
4257     if (idx != PA_INVALID_INDEX)
4258         m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4259     else {
4260         for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4261             if (strcmp(name, m->name) == 0)
4262                 break;
4263     }
4264
4265     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4266     CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4267
4268     cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4269     CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4270
4271     if (cb(c->protocol, m, c, tag, t) < 0)
4272         protocol_error(c);
4273 }
4274
4275 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4276     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4277     uint32_t idx = PA_INVALID_INDEX;
4278     const char *name = NULL, *profile = NULL;
4279     pa_card *card = NULL;
4280     int ret;
4281
4282     pa_native_connection_assert_ref(c);
4283     pa_assert(t);
4284
4285     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4286         pa_tagstruct_gets(t, &name) < 0 ||
4287         pa_tagstruct_gets(t, &profile) < 0 ||
4288         !pa_tagstruct_eof(t)) {
4289         protocol_error(c);
4290         return;
4291     }
4292
4293     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4294     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4295     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4296     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4297     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4298
4299     if (idx != PA_INVALID_INDEX)
4300         card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4301     else
4302         card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4303
4304     CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4305
4306     if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) {
4307         pa_pstream_send_error(c->pstream, tag, -ret);
4308         return;
4309     }
4310
4311     pa_pstream_send_simple_ack(c->pstream, tag);
4312 }
4313
4314 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4315     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4316     uint32_t idx = PA_INVALID_INDEX;
4317     const char *name = NULL, *port = NULL;
4318     int ret;
4319
4320     pa_native_connection_assert_ref(c);
4321     pa_assert(t);
4322
4323     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4324         pa_tagstruct_gets(t, &name) < 0 ||
4325         pa_tagstruct_gets(t, &port) < 0 ||
4326         !pa_tagstruct_eof(t)) {
4327         protocol_error(c);
4328         return;
4329     }
4330
4331     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4332     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);
4333     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4334     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4335     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4336
4337     if (command == PA_COMMAND_SET_SINK_PORT) {
4338         pa_sink *sink;
4339
4340         if (idx != PA_INVALID_INDEX)
4341             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4342         else
4343             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4344
4345         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4346
4347         if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) {
4348             pa_pstream_send_error(c->pstream, tag, -ret);
4349             return;
4350         }
4351     } else {
4352         pa_source *source;
4353
4354         pa_assert(command = PA_COMMAND_SET_SOURCE_PORT);
4355
4356         if (idx != PA_INVALID_INDEX)
4357             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4358         else
4359             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4360
4361         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4362
4363         if ((ret = pa_source_set_port(source, port, TRUE)) < 0) {
4364             pa_pstream_send_error(c->pstream, tag, -ret);
4365             return;
4366         }
4367     }
4368
4369     pa_pstream_send_simple_ack(c->pstream, tag);
4370 }
4371
4372 /*** pstream callbacks ***/
4373
4374 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4375     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4376
4377     pa_assert(p);
4378     pa_assert(packet);
4379     pa_native_connection_assert_ref(c);
4380
4381     if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4382         pa_log("invalid packet.");
4383         native_connection_unlink(c);
4384     }
4385 }
4386
4387 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) {
4388     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4389     output_stream *stream;
4390
4391     pa_assert(p);
4392     pa_assert(chunk);
4393     pa_native_connection_assert_ref(c);
4394
4395     if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4396         pa_log_debug("Client sent block for invalid stream.");
4397         /* Ignoring */
4398         return;
4399     }
4400
4401 /*     pa_log("got %lu bytes", (unsigned long) chunk->length); */
4402
4403     if (playback_stream_isinstance(stream)) {
4404         playback_stream *ps = PLAYBACK_STREAM(stream);
4405
4406         if (chunk->memblock) {
4407             if (seek != PA_SEEK_RELATIVE || offset != 0)
4408                 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
4409
4410             pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4411         } else
4412             pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset+chunk->length, NULL, NULL);
4413
4414     } else {
4415         upload_stream *u = UPLOAD_STREAM(stream);
4416         size_t l;
4417
4418         if (!u->memchunk.memblock) {
4419             if (u->length == chunk->length && chunk->memblock) {
4420                 u->memchunk = *chunk;
4421                 pa_memblock_ref(u->memchunk.memblock);
4422                 u->length = 0;
4423             } else {
4424                 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4425                 u->memchunk.index = u->memchunk.length = 0;
4426             }
4427         }
4428
4429         pa_assert(u->memchunk.memblock);
4430
4431         l = u->length;
4432         if (l > chunk->length)
4433             l = chunk->length;
4434
4435         if (l > 0) {
4436             void *dst;
4437             dst = pa_memblock_acquire(u->memchunk.memblock);
4438
4439             if (chunk->memblock) {
4440                 void *src;
4441                 src = pa_memblock_acquire(chunk->memblock);
4442
4443                 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4444                        (uint8_t*) src + chunk->index, l);
4445
4446                 pa_memblock_release(chunk->memblock);
4447             } else
4448                 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4449
4450             pa_memblock_release(u->memchunk.memblock);
4451
4452             u->memchunk.length += l;
4453             u->length -= l;
4454         }
4455     }
4456 }
4457
4458 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4459     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4460
4461     pa_assert(p);
4462     pa_native_connection_assert_ref(c);
4463
4464     native_connection_unlink(c);
4465     pa_log_info("Connection died.");
4466 }
4467
4468 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4469     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4470
4471     pa_assert(p);
4472     pa_native_connection_assert_ref(c);
4473
4474     native_connection_send_memblock(c);
4475 }
4476
4477 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4478     pa_thread_mq *q;
4479
4480     if (!(q = pa_thread_mq_get()))
4481         pa_pstream_send_revoke(p, block_id);
4482     else
4483         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4484 }
4485
4486 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4487     pa_thread_mq *q;
4488
4489     if (!(q = pa_thread_mq_get()))
4490         pa_pstream_send_release(p, block_id);
4491     else
4492         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4493 }
4494
4495 /*** client callbacks ***/
4496
4497 static void client_kill_cb(pa_client *c) {
4498     pa_assert(c);
4499
4500     native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4501     pa_log_info("Connection killed.");
4502 }
4503
4504 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4505     pa_tagstruct *t;
4506     pa_native_connection *c;
4507
4508     pa_assert(client);
4509     c = PA_NATIVE_CONNECTION(client->userdata);
4510     pa_native_connection_assert_ref(c);
4511
4512     if (c->version < 15)
4513       return;
4514
4515     t = pa_tagstruct_new(NULL, 0);
4516     pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4517     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4518     pa_tagstruct_puts(t, event);
4519     pa_tagstruct_put_proplist(t, pl);
4520     pa_pstream_send_tagstruct(c->pstream, t);
4521 }
4522
4523 /*** module entry points ***/
4524
4525 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4526     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4527
4528     pa_assert(m);
4529     pa_native_connection_assert_ref(c);
4530     pa_assert(c->auth_timeout_event == e);
4531
4532     if (!c->authorized) {
4533         native_connection_unlink(c);
4534         pa_log_info("Connection terminated due to authentication timeout.");
4535     }
4536 }
4537
4538 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4539     pa_native_connection *c;
4540     char pname[128];
4541     pa_client *client;
4542     pa_client_new_data data;
4543
4544     pa_assert(p);
4545     pa_assert(io);
4546     pa_assert(o);
4547
4548     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4549         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4550         pa_iochannel_free(io);
4551         return;
4552     }
4553
4554     pa_client_new_data_init(&data);
4555     data.module = o->module;
4556     data.driver = __FILE__;
4557     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4558     pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4559     pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4560     client = pa_client_new(p->core, &data);
4561     pa_client_new_data_done(&data);
4562
4563     if (!client)
4564         return;
4565
4566     c = pa_msgobject_new(pa_native_connection);
4567     c->parent.parent.free = native_connection_free;
4568     c->parent.process_msg = native_connection_process_msg;
4569     c->protocol = p;
4570     c->options = pa_native_options_ref(o);
4571     c->authorized = FALSE;
4572
4573     if (o->auth_anonymous) {
4574         pa_log_info("Client authenticated anonymously.");
4575         c->authorized = TRUE;
4576     }
4577
4578     if (!c->authorized &&
4579         o->auth_ip_acl &&
4580         pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4581
4582         pa_log_info("Client authenticated by IP ACL.");
4583         c->authorized = TRUE;
4584     }
4585
4586     if (!c->authorized)
4587         c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
4588     else
4589         c->auth_timeout_event = NULL;
4590
4591     c->is_local = pa_iochannel_socket_is_local(io);
4592     c->version = 8;
4593
4594     c->client = client;
4595     c->client->kill = client_kill_cb;
4596     c->client->send_event = client_send_event_cb;
4597     c->client->userdata = c;
4598
4599     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4600     pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4601     pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4602     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4603     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4604     pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4605     pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4606
4607     c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX);
4608
4609     c->record_streams = pa_idxset_new(NULL, NULL);
4610     c->output_streams = pa_idxset_new(NULL, NULL);
4611
4612     c->rrobin_index = PA_IDXSET_INVALID;
4613     c->subscription = NULL;
4614
4615     pa_idxset_put(p->connections, c, NULL);
4616
4617 #ifdef HAVE_CREDS
4618     if (pa_iochannel_creds_supported(io))
4619         pa_iochannel_creds_enable(io);
4620 #endif
4621
4622     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4623 }
4624
4625 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4626     pa_native_connection *c;
4627     void *state = NULL;
4628
4629     pa_assert(p);
4630     pa_assert(m);
4631
4632     while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4633         if (c->options->module == m)
4634             native_connection_unlink(c);
4635 }
4636
4637 static pa_native_protocol* native_protocol_new(pa_core *c) {
4638     pa_native_protocol *p;
4639     pa_native_hook_t h;
4640
4641     pa_assert(c);
4642
4643     p = pa_xnew(pa_native_protocol, 1);
4644     PA_REFCNT_INIT(p);
4645     p->core = c;
4646     p->connections = pa_idxset_new(NULL, NULL);
4647
4648     p->servers = NULL;
4649
4650     p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4651
4652     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4653         pa_hook_init(&p->hooks[h], p);
4654
4655     pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4656
4657     return p;
4658 }
4659
4660 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4661     pa_native_protocol *p;
4662
4663     if ((p = pa_shared_get(c, "native-protocol")))
4664         return pa_native_protocol_ref(p);
4665
4666     return native_protocol_new(c);
4667 }
4668
4669 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4670     pa_assert(p);
4671     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4672
4673     PA_REFCNT_INC(p);
4674
4675     return p;
4676 }
4677
4678 void pa_native_protocol_unref(pa_native_protocol *p) {
4679     pa_native_connection *c;
4680     pa_native_hook_t h;
4681
4682     pa_assert(p);
4683     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4684
4685     if (PA_REFCNT_DEC(p) > 0)
4686         return;
4687
4688     while ((c = pa_idxset_first(p->connections, NULL)))
4689         native_connection_unlink(c);
4690
4691     pa_idxset_free(p->connections, NULL, NULL);
4692
4693     pa_strlist_free(p->servers);
4694
4695     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4696         pa_hook_done(&p->hooks[h]);
4697
4698     pa_hashmap_free(p->extensions, NULL, NULL);
4699
4700     pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4701
4702     pa_xfree(p);
4703 }
4704
4705 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
4706     pa_assert(p);
4707     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4708     pa_assert(name);
4709
4710     p->servers = pa_strlist_prepend(p->servers, name);
4711
4712     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4713 }
4714
4715 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
4716     pa_assert(p);
4717     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4718     pa_assert(name);
4719
4720     p->servers = pa_strlist_remove(p->servers, name);
4721
4722     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4723 }
4724
4725 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
4726     pa_assert(p);
4727     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4728
4729     return p->hooks;
4730 }
4731
4732 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
4733     pa_assert(p);
4734     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4735
4736     return p->servers;
4737 }
4738
4739 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
4740     pa_assert(p);
4741     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4742     pa_assert(m);
4743     pa_assert(cb);
4744     pa_assert(!pa_hashmap_get(p->extensions, m));
4745
4746     pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
4747     return 0;
4748 }
4749
4750 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
4751     pa_assert(p);
4752     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4753     pa_assert(m);
4754
4755     pa_assert_se(pa_hashmap_remove(p->extensions, m));
4756 }
4757
4758 pa_native_options* pa_native_options_new(void) {
4759     pa_native_options *o;
4760
4761     o = pa_xnew0(pa_native_options, 1);
4762     PA_REFCNT_INIT(o);
4763
4764     return o;
4765 }
4766
4767 pa_native_options* pa_native_options_ref(pa_native_options *o) {
4768     pa_assert(o);
4769     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4770
4771     PA_REFCNT_INC(o);
4772
4773     return o;
4774 }
4775
4776 void pa_native_options_unref(pa_native_options *o) {
4777     pa_assert(o);
4778     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4779
4780     if (PA_REFCNT_DEC(o) > 0)
4781         return;
4782
4783     pa_xfree(o->auth_group);
4784
4785     if (o->auth_ip_acl)
4786         pa_ip_acl_free(o->auth_ip_acl);
4787
4788     if (o->auth_cookie)
4789         pa_auth_cookie_unref(o->auth_cookie);
4790
4791     pa_xfree(o);
4792 }
4793
4794 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
4795     pa_bool_t enabled;
4796     const char *acl;
4797
4798     pa_assert(o);
4799     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4800     pa_assert(ma);
4801
4802     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
4803         pa_log("auth-anonymous= expects a boolean argument.");
4804         return -1;
4805     }
4806
4807     enabled = TRUE;
4808     if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
4809         pa_log("auth-group-enabled= expects a boolean argument.");
4810         return -1;
4811     }
4812
4813     pa_xfree(o->auth_group);
4814     o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
4815
4816 #ifndef HAVE_CREDS
4817     if (o->auth_group)
4818         pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4819 #endif
4820
4821     if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
4822         pa_ip_acl *ipa;
4823
4824         if (!(ipa = pa_ip_acl_new(acl))) {
4825             pa_log("Failed to parse IP ACL '%s'", acl);
4826             return -1;
4827         }
4828
4829         if (o->auth_ip_acl)
4830             pa_ip_acl_free(o->auth_ip_acl);
4831
4832         o->auth_ip_acl = ipa;
4833     }
4834
4835     enabled = TRUE;
4836     if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
4837         pa_log("auth-cookie-enabled= expects a boolean argument.");
4838         return -1;
4839     }
4840
4841     if (o->auth_cookie)
4842         pa_auth_cookie_unref(o->auth_cookie);
4843
4844     if (enabled) {
4845         const char *cn;
4846
4847         /* The new name for this is 'auth-cookie', for compat reasons
4848          * we check the old name too */
4849         if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
4850             if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
4851                 cn = PA_NATIVE_COOKIE_FILE;
4852
4853         if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
4854             return -1;
4855
4856     } else
4857           o->auth_cookie = NULL;
4858
4859     return 0;
4860 }
4861
4862 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
4863     pa_native_connection_assert_ref(c);
4864
4865     return c->pstream;
4866 }
4867
4868 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
4869    pa_native_connection_assert_ref(c);
4870
4871    return c->client;
4872 }