]> code.delx.au - pulseaudio/blob - src/pulsecore/source.c
ac1ef1e72a67ab16c57b3ad7bca0c83bcb546d0c
[pulseaudio] / src / pulsecore / source.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35
36 #include <pulsecore/source-output.h>
37 #include <pulsecore/namereg.h>
38 #include <pulsecore/core-subscribe.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/sample-util.h>
41
42 #include "source.h"
43
44 #define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
45
46 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
47
48 static void source_free(pa_object *o);
49
50 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
51 pa_assert(data);
52
53 memset(data, 0, sizeof(*data));
54 data->proplist = pa_proplist_new();
55
56 return data;
57 }
58
59 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
60 pa_assert(data);
61
62 pa_xfree(data->name);
63 data->name = pa_xstrdup(name);
64 }
65
66 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
67 pa_assert(data);
68
69 if ((data->sample_spec_is_set = !!spec))
70 data->sample_spec = *spec;
71 }
72
73 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
74 pa_assert(data);
75
76 if ((data->channel_map_is_set = !!map))
77 data->channel_map = *map;
78 }
79
80 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
81 pa_assert(data);
82
83 if ((data->volume_is_set = !!volume))
84 data->volume = *volume;
85 }
86
87 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
88 pa_assert(data);
89
90 data->muted_is_set = TRUE;
91 data->muted = !!mute;
92 }
93
94 void pa_source_new_data_done(pa_source_new_data *data) {
95 pa_assert(data);
96
97 pa_xfree(data->name);
98 pa_proplist_free(data->proplist);
99 }
100
101 /* Called from main context */
102 static void reset_callbacks(pa_source *s) {
103 pa_assert(s);
104
105 s->set_state = NULL;
106 s->get_volume = NULL;
107 s->set_volume = NULL;
108 s->get_mute = NULL;
109 s->set_mute = NULL;
110 s->update_requested_latency = NULL;
111 }
112
113 /* Called from main context */
114 pa_source* pa_source_new(
115 pa_core *core,
116 pa_source_new_data *data,
117 pa_source_flags_t flags) {
118
119 pa_source *s;
120 const char *name;
121 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
122 char *pt;
123
124 pa_assert(core);
125 pa_assert(data);
126 pa_assert(data->name);
127
128 s = pa_msgobject_new(pa_source);
129
130 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
131 pa_xfree(s);
132 return NULL;
133 }
134
135 pa_source_new_data_set_name(data, name);
136
137 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
138 pa_xfree(s);
139 pa_namereg_unregister(core, name);
140 return NULL;
141 }
142
143 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
144 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
145
146 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
147
148 if (!data->channel_map_is_set)
149 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
150
151 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
152 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
153
154 if (!data->volume_is_set)
155 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
156
157 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
158 pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
159
160 if (!data->muted_is_set)
161 data->muted = FALSE;
162
163 if (data->card)
164 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
165
166 pa_device_init_description(data->proplist);
167 pa_device_init_icon(data->proplist, FALSE);
168
169 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
170 pa_xfree(s);
171 pa_namereg_unregister(core, name);
172 return NULL;
173 }
174
175 s->parent.parent.free = source_free;
176 s->parent.process_msg = pa_source_process_msg;
177
178 s->core = core;
179 s->state = PA_SOURCE_INIT;
180 s->flags = flags;
181 s->name = pa_xstrdup(name);
182 s->proplist = pa_proplist_copy(data->proplist);
183 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
184 s->module = data->module;
185 s->card = data->card;
186
187 s->sample_spec = data->sample_spec;
188 s->channel_map = data->channel_map;
189
190 s->outputs = pa_idxset_new(NULL, NULL);
191 s->n_corked = 0;
192 s->monitor_of = NULL;
193
194 s->virtual_volume = data->volume;
195 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
196 s->base_volume = PA_VOLUME_NORM;
197 s->n_volume_steps = PA_VOLUME_NORM+1;
198 s->muted = data->muted;
199 s->refresh_volume = s->refresh_muted = FALSE;
200
201 reset_callbacks(s);
202 s->userdata = NULL;
203
204 s->asyncmsgq = NULL;
205 s->rtpoll = NULL;
206
207 pa_silence_memchunk_get(
208 &core->silence_cache,
209 core->mempool,
210 &s->silence,
211 &s->sample_spec,
212 0);
213
214 s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
215 s->thread_info.soft_volume = s->soft_volume;
216 s->thread_info.soft_muted = s->muted;
217 s->thread_info.state = s->state;
218 s->thread_info.max_rewind = 0;
219 s->thread_info.requested_latency_valid = FALSE;
220 s->thread_info.requested_latency = 0;
221 s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
222 s->thread_info.max_latency = 0;
223
224 pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
225
226 if (s->card)
227 pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
228
229 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
230 pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
231 s->index,
232 s->name,
233 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
234 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
235 pt);
236 pa_xfree(pt);
237
238 return s;
239 }
240
241 /* Called from main context */
242 static int source_set_state(pa_source *s, pa_source_state_t state) {
243 int ret;
244 pa_bool_t suspend_change;
245 pa_source_state_t original_state;
246
247 pa_assert(s);
248
249 if (s->state == state)
250 return 0;
251
252 original_state = s->state;
253
254 suspend_change =
255 (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
256 (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
257
258 if (s->set_state)
259 if ((ret = s->set_state(s, state)) < 0)
260 return ret;
261
262 if (s->asyncmsgq)
263 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
264
265 if (s->set_state)
266 s->set_state(s, original_state);
267
268 return ret;
269 }
270
271 s->state = state;
272
273 if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
274 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
275 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
276 }
277
278 if (suspend_change) {
279 pa_source_output *o;
280 uint32_t idx;
281
282 /* We're suspending or resuming, tell everyone about it */
283
284 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
285 if (s->state == PA_SOURCE_SUSPENDED &&
286 (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
287 pa_source_output_kill(o);
288 else if (o->suspend)
289 o->suspend(o, state == PA_SOURCE_SUSPENDED);
290 }
291
292
293 return 0;
294 }
295
296 /* Called from main context */
297 void pa_source_put(pa_source *s) {
298 pa_source_assert_ref(s);
299
300 pa_assert(s->state == PA_SOURCE_INIT);
301
302 /* The following fields must be initialized properly when calling _put() */
303 pa_assert(s->asyncmsgq);
304 pa_assert(s->rtpoll);
305 pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
306 s->thread_info.min_latency <= s->thread_info.max_latency);
307
308 if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL)) {
309 s->flags |= PA_SOURCE_DECIBEL_VOLUME;
310
311 s->thread_info.soft_volume = s->soft_volume;
312 s->thread_info.soft_muted = s->muted;
313 }
314
315 if (s->flags & PA_SOURCE_DECIBEL_VOLUME)
316 s->n_volume_steps = PA_VOLUME_NORM+1;
317
318 pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
319
320 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
321 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
322 }
323
324 /* Called from main context */
325 void pa_source_unlink(pa_source *s) {
326 pa_bool_t linked;
327 pa_source_output *o, *j = NULL;
328
329 pa_assert(s);
330
331 /* See pa_sink_unlink() for a couple of comments how this function
332 * works. */
333
334 linked = PA_SOURCE_IS_LINKED(s->state);
335
336 if (linked)
337 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
338
339 if (s->state != PA_SOURCE_UNLINKED)
340 pa_namereg_unregister(s->core, s->name);
341 pa_idxset_remove_by_data(s->core->sources, s, NULL);
342
343 if (s->card)
344 pa_idxset_remove_by_data(s->card->sources, s, NULL);
345
346 while ((o = pa_idxset_first(s->outputs, NULL))) {
347 pa_assert(o != j);
348 pa_source_output_kill(o);
349 j = o;
350 }
351
352 if (linked)
353 source_set_state(s, PA_SOURCE_UNLINKED);
354 else
355 s->state = PA_SOURCE_UNLINKED;
356
357 reset_callbacks(s);
358
359 if (linked) {
360 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
361 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
362 }
363 }
364
365 /* Called from main context */
366 static void source_free(pa_object *o) {
367 pa_source_output *so;
368 pa_source *s = PA_SOURCE(o);
369
370 pa_assert(s);
371 pa_assert(pa_source_refcnt(s) == 0);
372
373 if (PA_SOURCE_IS_LINKED(s->state))
374 pa_source_unlink(s);
375
376 pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
377
378 pa_idxset_free(s->outputs, NULL, NULL);
379
380 while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
381 pa_source_output_unref(so);
382
383 pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
384
385 if (s->silence.memblock)
386 pa_memblock_unref(s->silence.memblock);
387
388 pa_xfree(s->name);
389 pa_xfree(s->driver);
390
391 if (s->proplist)
392 pa_proplist_free(s->proplist);
393
394 pa_xfree(s);
395 }
396
397 /* Called from main context */
398 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
399 pa_source_assert_ref(s);
400
401 s->asyncmsgq = q;
402 }
403
404 /* Called from main context */
405 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
406 pa_source_assert_ref(s);
407
408 s->rtpoll = p;
409 }
410
411 /* Called from main context */
412 int pa_source_update_status(pa_source*s) {
413 pa_source_assert_ref(s);
414 pa_assert(PA_SOURCE_IS_LINKED(s->state));
415
416 if (s->state == PA_SOURCE_SUSPENDED)
417 return 0;
418
419 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
420 }
421
422 /* Called from main context */
423 int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
424 pa_source_assert_ref(s);
425 pa_assert(PA_SOURCE_IS_LINKED(s->state));
426
427 if (s->monitor_of)
428 return -PA_ERR_NOTSUPPORTED;
429
430 if (suspend)
431 return source_set_state(s, PA_SOURCE_SUSPENDED);
432 else
433 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
434 }
435
436 /* Called from main context */
437 int pa_source_sync_suspend(pa_source *s) {
438 pa_sink_state_t state;
439
440 pa_source_assert_ref(s);
441 pa_assert(PA_SOURCE_IS_LINKED(s->state));
442 pa_assert(s->monitor_of);
443
444 state = pa_sink_get_state(s->monitor_of);
445
446 if (state == PA_SINK_SUSPENDED)
447 return source_set_state(s, PA_SOURCE_SUSPENDED);
448
449 pa_assert(PA_SINK_IS_OPENED(state));
450
451 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
452 }
453
454 /* Called from main context */
455 pa_queue *pa_source_move_all_start(pa_source *s) {
456 pa_queue *q;
457 pa_source_output *o, *n;
458 uint32_t idx;
459
460 pa_source_assert_ref(s);
461 pa_assert(PA_SOURCE_IS_LINKED(s->state));
462
463 q = pa_queue_new();
464
465 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
466 n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
467
468 if (pa_source_output_start_move(o) >= 0)
469 pa_queue_push(q, pa_source_output_ref(o));
470 }
471
472 return q;
473 }
474
475 /* Called from main context */
476 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
477 pa_source_output *o;
478
479 pa_source_assert_ref(s);
480 pa_assert(PA_SOURCE_IS_LINKED(s->state));
481 pa_assert(q);
482
483 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
484 if (pa_source_output_finish_move(o, s, save) < 0)
485 pa_source_output_kill(o);
486
487 pa_source_output_unref(o);
488 }
489
490 pa_queue_free(q, NULL, NULL);
491 }
492
493 /* Called from main context */
494 void pa_source_move_all_fail(pa_queue *q) {
495 pa_source_output *o;
496 pa_assert(q);
497
498 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
499 if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
500 pa_source_output_kill(o);
501 pa_source_output_unref(o);
502 }
503 }
504
505 pa_queue_free(q, NULL, NULL);
506 }
507
508 /* Called from IO thread context */
509 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
510 pa_source_output *o;
511 void *state = NULL;
512
513 pa_source_assert_ref(s);
514 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
515
516 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
517 return;
518
519 if (nbytes <= 0)
520 return;
521
522 pa_log_debug("Processing rewind...");
523
524 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
525 pa_source_output_assert_ref(o);
526 pa_source_output_process_rewind(o, nbytes);
527 }
528 }
529
530 /* Called from IO thread context */
531 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
532 pa_source_output *o;
533 void *state = NULL;
534
535 pa_source_assert_ref(s);
536 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
537 pa_assert(chunk);
538
539 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
540 return;
541
542 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
543 pa_memchunk vchunk = *chunk;
544
545 pa_memblock_ref(vchunk.memblock);
546 pa_memchunk_make_writable(&vchunk, 0);
547
548 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
549 pa_silence_memchunk(&vchunk, &s->sample_spec);
550 else
551 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
552
553 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
554 pa_source_output_assert_ref(o);
555
556 if (!o->thread_info.direct_on_input)
557 pa_source_output_push(o, &vchunk);
558 }
559
560 pa_memblock_unref(vchunk.memblock);
561 } else {
562
563 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
564 pa_source_output_assert_ref(o);
565
566 if (!o->thread_info.direct_on_input)
567 pa_source_output_push(o, chunk);
568 }
569 }
570 }
571
572 /* Called from IO thread context */
573 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
574 pa_source_assert_ref(s);
575 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
576 pa_source_output_assert_ref(o);
577 pa_assert(o->thread_info.direct_on_input);
578 pa_assert(chunk);
579
580 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
581 return;
582
583 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
584 pa_memchunk vchunk = *chunk;
585
586 pa_memblock_ref(vchunk.memblock);
587 pa_memchunk_make_writable(&vchunk, 0);
588
589 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
590 pa_silence_memchunk(&vchunk, &s->sample_spec);
591 else
592 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
593
594 pa_source_output_push(o, &vchunk);
595
596 pa_memblock_unref(vchunk.memblock);
597 } else
598 pa_source_output_push(o, chunk);
599 }
600
601 /* Called from main thread */
602 pa_usec_t pa_source_get_latency(pa_source *s) {
603 pa_usec_t usec;
604
605 pa_source_assert_ref(s);
606 pa_assert(PA_SOURCE_IS_LINKED(s->state));
607
608 if (s->state == PA_SOURCE_SUSPENDED)
609 return 0;
610
611 if (!(s->flags & PA_SOURCE_LATENCY))
612 return 0;
613
614 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
615
616 return usec;
617 }
618
619 /* Called from main thread */
620 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
621 pa_cvolume old_virtual_volume;
622 pa_bool_t virtual_volume_changed;
623
624 pa_source_assert_ref(s);
625 pa_assert(PA_SOURCE_IS_LINKED(s->state));
626 pa_assert(volume);
627 pa_assert(pa_cvolume_valid(volume));
628 pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
629
630 old_virtual_volume = s->virtual_volume;
631 s->virtual_volume = *volume;
632 virtual_volume_changed = !pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume);
633
634 if (s->set_volume) {
635 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
636 s->set_volume(s);
637 } else
638 s->soft_volume = s->virtual_volume;
639
640 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
641
642 if (virtual_volume_changed)
643 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
644 }
645
646 /* Called from main thread. Only to be called by source implementor */
647 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
648 pa_source_assert_ref(s);
649 pa_assert(volume);
650
651 if (PA_SOURCE_IS_LINKED(s->state))
652 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
653 else
654 s->thread_info.soft_volume = *volume;
655 }
656
657 /* Called from main thread */
658 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
659 pa_source_assert_ref(s);
660 pa_assert(PA_SOURCE_IS_LINKED(s->state));
661
662 if (s->refresh_volume || force_refresh) {
663 pa_cvolume old_virtual_volume = s->virtual_volume;
664
665 if (s->get_volume)
666 s->get_volume(s);
667
668 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
669
670 if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume))
671 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
672 }
673
674 return &s->virtual_volume;
675 }
676
677 /* Called from main thread */
678 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
679 pa_source_assert_ref(s);
680
681 /* The source implementor may call this if the volume changed to make sure everyone is notified */
682
683 if (pa_cvolume_equal(&s->virtual_volume, new_volume))
684 return;
685
686 s->virtual_volume = *new_volume;
687 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
688 }
689
690 /* Called from main thread */
691 void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
692 pa_bool_t old_muted;
693
694 pa_source_assert_ref(s);
695 pa_assert(PA_SOURCE_IS_LINKED(s->state));
696
697 old_muted = s->muted;
698 s->muted = mute;
699
700 if (s->set_mute)
701 s->set_mute(s);
702
703 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
704
705 if (old_muted != s->muted)
706 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
707 }
708
709 /* Called from main thread */
710 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
711 pa_source_assert_ref(s);
712 pa_assert(PA_SOURCE_IS_LINKED(s->state));
713
714 if (s->refresh_muted || force_refresh) {
715 pa_bool_t old_muted = s->muted;
716
717 if (s->get_mute)
718 s->get_mute(s);
719
720 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
721
722 if (old_muted != s->muted)
723 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
724 }
725
726 return s->muted;
727 }
728
729 /* Called from main thread */
730 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
731 pa_source_assert_ref(s);
732
733 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
734
735 if (s->muted == new_muted)
736 return;
737
738 s->muted = new_muted;
739 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
740 }
741
742 /* Called from main thread */
743 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
744 pa_source_assert_ref(s);
745 pa_assert(p);
746
747 pa_proplist_update(s->proplist, mode, p);
748
749 if (PA_SOURCE_IS_LINKED(s->state)) {
750 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
751 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
752 }
753
754 return TRUE;
755 }
756
757 /* Called from main thread */
758 void pa_source_set_description(pa_source *s, const char *description) {
759 const char *old;
760 pa_source_assert_ref(s);
761
762 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
763 return;
764
765 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
766
767 if (old && description && !strcmp(old, description))
768 return;
769
770 if (description)
771 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
772 else
773 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
774
775 if (PA_SOURCE_IS_LINKED(s->state)) {
776 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
777 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
778 }
779 }
780
781 /* Called from main thread */
782 unsigned pa_source_linked_by(pa_source *s) {
783 pa_source_assert_ref(s);
784 pa_assert(PA_SOURCE_IS_LINKED(s->state));
785
786 return pa_idxset_size(s->outputs);
787 }
788
789 /* Called from main thread */
790 unsigned pa_source_used_by(pa_source *s) {
791 unsigned ret;
792
793 pa_source_assert_ref(s);
794 pa_assert(PA_SOURCE_IS_LINKED(s->state));
795
796 ret = pa_idxset_size(s->outputs);
797 pa_assert(ret >= s->n_corked);
798
799 return ret - s->n_corked;
800 }
801
802 /* Called from main thread */
803 unsigned pa_source_check_suspend(pa_source *s) {
804 unsigned ret;
805 pa_source_output *o;
806 uint32_t idx;
807
808 pa_source_assert_ref(s);
809
810 if (!PA_SOURCE_IS_LINKED(s->state))
811 return 0;
812
813 ret = 0;
814
815 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) {
816 pa_source_output_state_t st;
817
818 st = pa_source_output_get_state(o);
819 pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(st));
820
821 if (st == PA_SOURCE_OUTPUT_CORKED)
822 continue;
823
824 if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
825 continue;
826
827 ret ++;
828 }
829
830 return ret;
831 }
832
833 /* Called from IO thread, except when it is not */
834 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
835 pa_source *s = PA_SOURCE(object);
836 pa_source_assert_ref(s);
837
838 switch ((pa_source_message_t) code) {
839
840 case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
841 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
842
843 pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
844
845 if (o->direct_on_input) {
846 o->thread_info.direct_on_input = o->direct_on_input;
847 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
848 }
849
850 pa_assert(!o->thread_info.attached);
851 o->thread_info.attached = TRUE;
852
853 if (o->attach)
854 o->attach(o);
855
856 pa_source_output_set_state_within_thread(o, o->state);
857
858 if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
859 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
860
861 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
862
863 /* We don't just invalidate the requested latency here,
864 * because if we are in a move we might need to fix up the
865 * requested latency. */
866 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
867
868 return 0;
869 }
870
871 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
872 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
873
874 pa_source_output_set_state_within_thread(o, o->state);
875
876 if (o->detach)
877 o->detach(o);
878
879 pa_assert(o->thread_info.attached);
880 o->thread_info.attached = FALSE;
881
882 if (o->thread_info.direct_on_input) {
883 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
884 o->thread_info.direct_on_input = NULL;
885 }
886
887 if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
888 pa_source_output_unref(o);
889
890 pa_source_invalidate_requested_latency(s);
891
892 return 0;
893 }
894
895 case PA_SOURCE_MESSAGE_SET_VOLUME:
896 s->thread_info.soft_volume = s->soft_volume;
897 return 0;
898
899 case PA_SOURCE_MESSAGE_GET_VOLUME:
900 return 0;
901
902 case PA_SOURCE_MESSAGE_SET_MUTE:
903 s->thread_info.soft_muted = s->muted;
904 return 0;
905
906 case PA_SOURCE_MESSAGE_GET_MUTE:
907 return 0;
908
909 case PA_SOURCE_MESSAGE_SET_STATE:
910 s->thread_info.state = PA_PTR_TO_UINT(userdata);
911 return 0;
912
913 case PA_SOURCE_MESSAGE_DETACH:
914
915 /* Detach all streams */
916 pa_source_detach_within_thread(s);
917 return 0;
918
919 case PA_SOURCE_MESSAGE_ATTACH:
920
921 /* Reattach all streams */
922 pa_source_attach_within_thread(s);
923 return 0;
924
925 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
926
927 pa_usec_t *usec = userdata;
928 *usec = pa_source_get_requested_latency_within_thread(s);
929
930 if (*usec == (pa_usec_t) -1)
931 *usec = s->thread_info.max_latency;
932
933 return 0;
934 }
935
936 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
937 pa_usec_t *r = userdata;
938
939 pa_source_update_latency_range(s, r[0], r[1]);
940
941 return 0;
942 }
943
944 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
945 pa_usec_t *r = userdata;
946
947 r[0] = s->thread_info.min_latency;
948 r[1] = s->thread_info.max_latency;
949
950 return 0;
951 }
952
953 case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
954
955 *((size_t*) userdata) = s->thread_info.max_rewind;
956 return 0;
957
958 case PA_SOURCE_MESSAGE_GET_LATENCY:
959
960 if (s->monitor_of) {
961 *((pa_usec_t*) userdata) = 0;
962 return 0;
963 }
964
965 /* Implementors need to overwrite this implementation! */
966 return -1;
967
968 case PA_SOURCE_MESSAGE_MAX:
969 ;
970 }
971
972 return -1;
973 }
974
975 /* Called from main thread */
976 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
977 uint32_t idx;
978 pa_source *source;
979 int ret = 0;
980
981 pa_core_assert_ref(c);
982
983 for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
984 int r;
985
986 if (source->monitor_of)
987 continue;
988
989 if ((r = pa_source_suspend(source, suspend)) < 0)
990 ret = r;
991 }
992
993 return ret;
994 }
995
996 /* Called from main thread */
997 void pa_source_detach(pa_source *s) {
998 pa_source_assert_ref(s);
999 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1000
1001 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1002 }
1003
1004 /* Called from main thread */
1005 void pa_source_attach(pa_source *s) {
1006 pa_source_assert_ref(s);
1007 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1008
1009 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1010 }
1011
1012 /* Called from IO thread */
1013 void pa_source_detach_within_thread(pa_source *s) {
1014 pa_source_output *o;
1015 void *state = NULL;
1016
1017 pa_source_assert_ref(s);
1018 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1019
1020 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1021 if (o->detach)
1022 o->detach(o);
1023 }
1024
1025 /* Called from IO thread */
1026 void pa_source_attach_within_thread(pa_source *s) {
1027 pa_source_output *o;
1028 void *state = NULL;
1029
1030 pa_source_assert_ref(s);
1031 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1032
1033 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1034 if (o->attach)
1035 o->attach(o);
1036 }
1037
1038 /* Called from IO thread */
1039 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1040 pa_usec_t result = (pa_usec_t) -1;
1041 pa_source_output *o;
1042 void *state = NULL;
1043
1044 pa_source_assert_ref(s);
1045
1046 if (s->thread_info.requested_latency_valid)
1047 return s->thread_info.requested_latency;
1048
1049 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1050
1051 if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1052 (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1053 result = o->thread_info.requested_source_latency;
1054
1055 if (result != (pa_usec_t) -1) {
1056 if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
1057 result = s->thread_info.max_latency;
1058
1059 if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
1060 result = s->thread_info.min_latency;
1061 }
1062
1063 s->thread_info.requested_latency = result;
1064 s->thread_info.requested_latency_valid = TRUE;
1065
1066 return result;
1067 }
1068
1069 /* Called from main thread */
1070 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1071 pa_usec_t usec;
1072
1073 pa_source_assert_ref(s);
1074 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1075
1076 if (s->state == PA_SOURCE_SUSPENDED)
1077 return 0;
1078
1079 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1080
1081 return usec;
1082 }
1083
1084 /* Called from IO thread */
1085 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1086 pa_source_output *o;
1087 void *state = NULL;
1088
1089 pa_source_assert_ref(s);
1090
1091 if (max_rewind == s->thread_info.max_rewind)
1092 return;
1093
1094 s->thread_info.max_rewind = max_rewind;
1095
1096 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1097 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1098 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1099 }
1100 }
1101
1102 void pa_source_invalidate_requested_latency(pa_source *s) {
1103 pa_source_output *o;
1104 void *state = NULL;
1105
1106 pa_source_assert_ref(s);
1107
1108 s->thread_info.requested_latency_valid = FALSE;
1109
1110 if (s->update_requested_latency)
1111 s->update_requested_latency(s);
1112
1113 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1114 if (o->update_source_requested_latency)
1115 o->update_source_requested_latency(o);
1116
1117 if (s->monitor_of)
1118 pa_sink_invalidate_requested_latency(s->monitor_of);
1119 }
1120
1121 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1122 pa_source_assert_ref(s);
1123
1124 /* min_latency == 0: no limit
1125 * min_latency == (size_t) -1: default limit
1126 * min_latency anything else: specified limit
1127 *
1128 * Similar for max_latency */
1129
1130 if (min_latency == (pa_usec_t) -1)
1131 min_latency = DEFAULT_MIN_LATENCY;
1132
1133 if (max_latency == (pa_usec_t) -1)
1134 max_latency = min_latency;
1135
1136 pa_assert(!min_latency || !max_latency ||
1137 min_latency <= max_latency);
1138
1139 if (PA_SOURCE_IS_LINKED(s->state)) {
1140 pa_usec_t r[2];
1141
1142 r[0] = min_latency;
1143 r[1] = max_latency;
1144
1145 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1146 } else {
1147 s->thread_info.min_latency = min_latency;
1148 s->thread_info.max_latency = max_latency;
1149
1150 s->thread_info.requested_latency_valid = FALSE;
1151 }
1152 }
1153
1154 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1155 pa_source_assert_ref(s);
1156 pa_assert(min_latency);
1157 pa_assert(max_latency);
1158
1159 if (PA_SOURCE_IS_LINKED(s->state)) {
1160 pa_usec_t r[2] = { 0, 0 };
1161
1162 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1163
1164 *min_latency = r[0];
1165 *max_latency = r[1];
1166 } else {
1167 *min_latency = s->thread_info.min_latency;
1168 *max_latency = s->thread_info.max_latency;
1169 }
1170 }
1171
1172 /* Called from IO thread */
1173 void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1174 pa_source_output *o;
1175 void *state = NULL;
1176
1177 pa_source_assert_ref(s);
1178
1179 pa_assert(!min_latency || !max_latency ||
1180 min_latency <= max_latency);
1181
1182 s->thread_info.min_latency = min_latency;
1183 s->thread_info.max_latency = max_latency;
1184
1185 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1186 if (o->update_source_latency_range)
1187 o->update_source_latency_range(o);
1188
1189 pa_source_invalidate_requested_latency(s);
1190 }
1191
1192 size_t pa_source_get_max_rewind(pa_source *s) {
1193 size_t r;
1194 pa_source_assert_ref(s);
1195
1196 if (!PA_SOURCE_IS_LINKED(s->state))
1197 return s->thread_info.max_rewind;
1198
1199 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1200
1201 return r;
1202 }