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