101
106
pa_source_output *o;
102
107
pa_resampler *resampler = NULL;
103
108
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
108
if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data) < 0)
111
pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
114
data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, TRUE);
116
pa_return_null_if_fail(data->source);
117
pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_UNLINKED);
119
pa_return_null_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of);
116
pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
118
if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data)) < 0)
121
pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
124
data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE);
125
data->save_source = FALSE;
128
pa_return_val_if_fail(data->source, -PA_ERR_NOENTITY);
129
pa_return_val_if_fail(PA_SOURCE_IS_LINKED(pa_source_get_state(data->source)), -PA_ERR_BADSTATE);
130
pa_return_val_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of, -PA_ERR_INVALID);
121
132
if (!data->sample_spec_is_set)
122
133
data->sample_spec = data->source->sample_spec;
124
pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
135
pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
126
137
if (!data->channel_map_is_set) {
127
if (data->source->channel_map.channels == data->sample_spec.channels)
138
if (pa_channel_map_compatible(&data->source->channel_map, &data->sample_spec))
128
139
data->channel_map = data->source->channel_map;
130
141
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
133
pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
134
pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
144
pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
145
pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
136
147
if (flags & PA_SOURCE_OUTPUT_FIX_FORMAT)
137
148
data->sample_spec.format = data->source->sample_spec.format;
150
161
if (data->resample_method == PA_RESAMPLER_INVALID)
151
162
data->resample_method = core->resample_method;
153
pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
155
if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data) < 0)
164
pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
166
if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data)) < 0)
169
if ((flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND) &&
170
pa_source_get_state(data->source) == PA_SOURCE_SUSPENDED) {
171
pa_log("Failed to create source output: source is suspended.");
172
return -PA_ERR_BADSTATE;
158
175
if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
159
176
pa_log("Failed to create source output: too many outputs per source.");
177
return -PA_ERR_TOOLARGE;
163
180
if ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
188
203
o->state = PA_SOURCE_OUTPUT_INIT;
189
204
o->flags = flags;
190
205
o->proplist = pa_proplist_copy(data->proplist);
191
o->driver = pa_xstrdup(data->driver);
206
o->driver = pa_xstrdup(pa_path_get_filename(data->driver));
192
207
o->module = data->module;
193
208
o->source = data->source;
194
209
o->client = data->client;
196
o->resample_method = data->resample_method;
211
o->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
212
o->requested_resample_method = data->resample_method;
197
213
o->sample_spec = data->sample_spec;
198
214
o->channel_map = data->channel_map;
200
216
o->direct_on_input = data->direct_on_input;
218
o->save_source = data->save_source;
202
220
reset_callbacks(o);
203
221
o->userdata = NULL;
235
256
/* Don't forget to call pa_source_output_put! */
240
262
/* Called from main context */
241
263
static void update_n_corked(pa_source_output *o, pa_source_output_state_t state) {
244
269
if (o->state == PA_SOURCE_OUTPUT_CORKED && state != PA_SOURCE_OUTPUT_CORKED)
245
270
pa_assert_se(o->source->n_corked -- >= 1);
246
271
else if (o->state != PA_SOURCE_OUTPUT_CORKED && state == PA_SOURCE_OUTPUT_CORKED)
247
272
o->source->n_corked++;
249
pa_source_update_status(o->source);
252
275
/* Called from main context */
253
static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
276
static void source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
256
279
if (o->state == state)
259
282
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
280
303
linked = PA_SOURCE_OUTPUT_IS_LINKED(o->state);
283
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
306
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
285
308
if (o->direct_on_input)
286
309
pa_idxset_remove_by_data(o->direct_on_input->direct_outputs, o, NULL);
287
pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
288
if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
289
pa_source_output_unref(o);
311
pa_idxset_remove_by_data(o->core->source_outputs, o, NULL);
314
if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
315
pa_source_output_unref(o);
318
pa_idxset_remove_by_data(o->client->source_outputs, o, NULL);
291
320
update_n_corked(o, PA_SOURCE_OUTPUT_UNLINKED);
292
321
o->state = PA_SOURCE_OUTPUT_UNLINKED;
323
if (linked && o->source)
295
324
if (o->source->asyncmsgq)
296
325
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0);
298
327
reset_callbacks(o);
301
pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
302
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o);
330
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
331
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o);
335
pa_source_update_status(o->source);
339
pa_core_maybe_vacuum(o->core);
306
341
pa_source_output_unref(o);
352
387
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);
354
pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
355
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
389
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
390
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
392
pa_source_update_status(o->source);
358
395
/* Called from main context */
399
436
if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) {
400
437
pa_log_debug("Delay queue overflow!");
401
pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE);
438
pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE);
404
441
limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind;
443
if (limit > 0 && o->source->monitor_of) {
447
/* Hmm, check the latency for knowing how much of the buffered
448
* data is actually still unplayed and might hence still
449
* change. This is suboptimal. Ideally we'd have a call like
450
* pa_sink_get_changeable_size() or so that tells us how much
451
* of the queued data is actually still changeable. Hence
454
latency = pa_sink_get_latency_within_thread(o->source->monitor_of);
456
n = pa_usec_to_bytes(latency, &o->source->sample_spec);
406
462
/* Implement the delay queue */
407
463
while ((length = pa_memblockq_get_length(o->thread_info.delay_memblockq)) > limit) {
408
464
pa_memchunk qchunk;
482
538
/* Called from thread context */
483
static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) {
484
pa_source_assert_ref(s);
486
if (usec == (pa_usec_t) -1)
489
if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
490
usec = s->thread_info.max_latency;
492
if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
493
usec = s->thread_info.min_latency;
498
/* Called from thread context */
499
539
pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
500
540
pa_source_output_assert_ref(o);
502
usec = fixup_latency(o->source, usec);
542
if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
543
usec = o->source->fixed_latency;
545
if (usec != (pa_usec_t) -1)
546
usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
503
548
o->thread_info.requested_source_latency = usec;
504
549
pa_source_invalidate_requested_latency(o->source);
510
555
pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
511
556
pa_source_output_assert_ref(o);
513
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
558
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
514
559
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
516
/* If this source output is not realized yet, we have to touch
517
* the thread info data directly */
519
o->thread_info.requested_source_latency = usec;
563
/* If this source output is not realized yet or is being moved, we
564
* have to touch the thread info data directly */
567
if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
568
usec = o->source->fixed_latency;
570
if (usec != (pa_usec_t) -1) {
571
pa_usec_t min_latency, max_latency;
572
pa_source_get_latency_range(o->source, &min_latency, &max_latency);
573
usec = PA_CLAMP(usec, min_latency, max_latency);
577
o->thread_info.requested_source_latency = usec;
524
582
/* Called from main context */
525
583
pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) {
528
584
pa_source_output_assert_ref(o);
530
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
586
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
531
588
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
533
/* If this source output is not realized yet, we have to touch
534
* the thread info data directly */
535
usec = o->thread_info.requested_source_latency;
592
/* If this source output is not realized yet or is being moved, we
593
* have to touch the thread info data directly */
595
return o->thread_info.requested_source_latency;
540
598
/* Called from main context */
581
639
pa_proplist_unset(o->proplist, PA_PROP_MEDIA_NAME);
583
641
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) {
584
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
585
pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
642
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
643
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
647
/* Called from main thread */
648
void pa_source_output_update_proplist(pa_source_output *o, pa_update_mode_t mode, pa_proplist *p) {
649
pa_source_output_assert_ref(o);
652
pa_proplist_update(o->proplist, mode, p);
654
if (PA_SINK_IS_LINKED(o->state)) {
655
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
656
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
590
661
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
591
662
pa_source_output_assert_ref(o);
593
return o->resample_method;
664
return o->actual_resample_method;
596
667
/* Called from main context */
597
int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
599
pa_resampler *new_resampler;
600
pa_source_output_move_hook_data hook_data;
668
pa_bool_t pa_source_output_may_move(pa_source_output *o) {
602
669
pa_source_output_assert_ref(o);
603
670
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
604
pa_source_assert_ref(dest);
611
672
if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE)
614
675
if (o->direct_on_input)
681
/* Called from main context */
682
pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) {
683
pa_source_output_assert_ref(o);
684
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
685
pa_source_assert_ref(dest);
687
if (dest == o->source)
690
if (!pa_source_output_may_move(o))
617
693
if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
618
694
pa_log_warn("Failed to move source output: too many outputs per source.");
699
if (!o->may_move_to(o, dest))
705
/* Called from main context */
706
int pa_source_output_start_move(pa_source_output *o) {
710
pa_source_output_assert_ref(o);
711
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
712
pa_assert(o->source);
714
if (!pa_source_output_may_move(o))
715
return -PA_ERR_NOTSUPPORTED;
717
if ((r = pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], o)) < 0)
722
pa_idxset_remove_by_data(o->source->outputs, o, NULL);
724
if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
725
pa_assert_se(origin->n_corked-- >= 1);
727
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0);
729
pa_source_update_status(o->source);
732
pa_source_output_unref(o);
737
/* Called from main context */
738
int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t save) {
739
pa_resampler *new_resampler;
741
pa_source_output_assert_ref(o);
742
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
743
pa_assert(!o->source);
744
pa_source_assert_ref(dest);
746
if (!pa_source_output_may_move_to(o, dest))
622
749
if (o->thread_info.resampler &&
623
pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
624
pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
750
pa_sample_spec_equal(pa_resampler_input_sample_spec(o->thread_info.resampler), &dest->sample_spec) &&
751
pa_channel_map_equal(pa_resampler_input_channel_map(o->thread_info.resampler), &dest->channel_map))
626
753
/* Try to reuse the old resampler if possible */
627
754
new_resampler = o->thread_info.resampler;
633
760
/* Okey, we need a new resampler for the new source */
635
762
if (!(new_resampler = pa_resampler_new(
637
764
&dest->sample_spec, &dest->channel_map,
638
765
&o->sample_spec, &o->channel_map,
766
o->requested_resample_method,
640
767
((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
641
768
((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
642
769
(o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
643
770
pa_log_warn("Unsupported resampling operation.");
771
return -PA_ERR_NOTSUPPORTED;
647
774
new_resampler = NULL;
649
hook_data.source_output = o;
650
hook_data.destination = dest;
651
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], &hook_data);
653
/* Okey, let's move it */
654
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0);
656
pa_idxset_remove_by_data(origin->outputs, o, NULL);
657
pa_idxset_put(dest->outputs, o, NULL);
658
779
o->source = dest;
780
o->save_source = save;
781
pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL);
660
if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) {
661
pa_assert_se(origin->n_corked-- >= 1);
783
if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
784
o->source->n_corked++;
665
786
/* Replace resampler */
666
787
if (new_resampler != o->thread_info.resampler) {
681
802
&o->source->silence);
684
pa_source_update_status(origin);
685
805
pa_source_update_status(dest);
687
807
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);
692
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o);
694
pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name);
809
pa_log_debug("Successfully moved source output %i to %s.", o->index, dest->name);
696
811
/* Notify everyone */
697
pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
812
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], o);
813
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
818
/* Called from main context */
819
int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t save) {
822
pa_source_output_assert_ref(o);
823
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
824
pa_assert(o->source);
825
pa_source_assert_ref(dest);
827
if (dest == o->source)
830
if (!pa_source_output_may_move_to(o, dest))
831
return -PA_ERR_NOTSUPPORTED;
833
pa_source_output_ref(o);
835
if ((r = pa_source_output_start_move(o)) < 0) {
836
pa_source_output_unref(o);
840
if ((r = pa_source_output_finish_move(o, dest, save)) < 0) {
841
pa_source_output_unref(o);
845
pa_source_output_unref(o);
906
return -PA_ERR_NOTIMPLEMENTED;
909
void pa_source_output_send_event(pa_source_output *o, const char *event, pa_proplist *data) {
910
pa_proplist *pl = NULL;
911
pa_source_output_send_event_hook_data hook_data;
913
pa_source_output_assert_ref(o);
920
data = pl = pa_proplist_new();
922
hook_data.source_output = o;
923
hook_data.data = data;
924
hook_data.event = event;
926
if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], &hook_data) < 0)
929
o->send_event(o, event, data);
933
pa_proplist_free(pl);