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