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