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