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