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