~diwic/ubuntu/lucid/pulseaudio/bugfixes

« back to all changes in this revision

Viewing changes to src/pulsecore/sink-input.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-05-05 14:18:20 UTC
  • mfrom: (1.2.4 upstream) (1.1.8 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090505141820-rrr2mtdd1jkllvr8
Tags: 1:0.9.15-1ubuntu1
* Merge from unreleased Debian pulseaudio git, remaining changes:
  - epoch (my stupid fault :S)
  - Don't build against, and create jack package. Jack is not in main
  - use linear resampler to work better with lack of PREEMPT in jaunty's
    -generic kernel config, also change buffer size
  - Add alsa configuration files to route alsa applications via pulseaudio
  - Move libasound2-plugins from Recommends to Depends
  - Add pm-utils sleep hook to suspend (and resume) users' pulseaudio
    daemons
  - patch to fix source/sink and suspend-on-idle race
  - Make initscript more informative in the default case of per-user
    sessions
  - create /var/run/pulse, and make restart more robust
  - add status check for system wide pulseaudio instance
  - LSB {Required-*,Should-*} should specify hal instead of dbus,
    since hal is required (and already requires dbus)
  - indicate that the system pulseaudio instance is being started from the init
    script
  - Install more upstream man pages
  - Link to pacat for parec man page
  - check whether pulseaudio is running before preloading the padsp library
  - Add DEB_OPT_FLAG = -O3 as per recommendation from
    pulseaudio-discuss/2007-December/001017.html
  - cache /usr/share/sounds/ubuntu/stereo/ wav files on pulseaudio load
  - disable glitch free (use tsched=0)
  - Generate a PO template on build
  - add special case to disable pulseaudio loading if accessibility/speech
    is being used
  - the sd wrapper script should not load pulseaudio if pulseaudio is being
    used as a system service
  - add a pulseaudio apport hook
  - fix some typos in README.Debian
  - demote paprefs to suggests
  - drop padevchooser(Recommends) and pavucontrol (Suggests)
  - drop libasyncns-dev build dependency, its in universe
* add libudev-dev as a build-dependency

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 
7
7
  PulseAudio is free software; you can redistribute it and/or modify
8
8
  it under the terms of the GNU Lesser General Public License as published
9
 
  by the Free Software Foundation; either version 2 of the License,
 
9
  by the Free Software Foundation; either version 2.1 of the License,
10
10
  or (at your option) any later version.
11
11
 
12
12
  PulseAudio is distributed in the hope that it will be useful, but
30
30
 
31
31
#include <pulse/utf8.h>
32
32
#include <pulse/xmalloc.h>
 
33
#include <pulse/util.h>
33
34
 
34
35
#include <pulsecore/sample-util.h>
35
36
#include <pulsecore/core-subscribe.h>
78
79
        data->volume = *volume;
79
80
}
80
81
 
 
82
void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
 
83
    pa_assert(data);
 
84
    pa_assert(volume_factor);
 
85
 
 
86
    if (data->volume_factor_is_set)
 
87
        pa_sw_cvolume_multiply(&data->volume_factor, &data->volume_factor, volume_factor);
 
88
    else {
 
89
        data->volume_factor_is_set = TRUE;
 
90
        data->volume_factor = *volume_factor;
 
91
    }
 
92
}
 
93
 
81
94
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
82
95
    pa_assert(data);
83
96
 
104
117
    i->attach = NULL;
105
118
    i->detach = NULL;
106
119
    i->suspend = NULL;
107
 
    i->moved = NULL;
 
120
    i->suspend_within_thread = NULL;
 
121
    i->moving = NULL;
108
122
    i->kill = NULL;
109
123
    i->get_latency = NULL;
110
124
    i->state_change = NULL;
 
125
    i->may_move_to = NULL;
 
126
    i->send_event = NULL;
111
127
}
112
128
 
113
129
/* Called from main context */
114
 
pa_sink_input* pa_sink_input_new(
 
130
int pa_sink_input_new(
 
131
        pa_sink_input **_i,
115
132
        pa_core *core,
116
133
        pa_sink_input_new_data *data,
117
134
        pa_sink_input_flags_t flags) {
120
137
    pa_resampler *resampler = NULL;
121
138
    char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
122
139
    pa_channel_map original_cm;
 
140
    int r;
123
141
 
 
142
    pa_assert(_i);
124
143
    pa_assert(core);
125
144
    pa_assert(data);
126
145
 
127
 
    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data) < 0)
128
 
        return NULL;
129
 
 
130
 
    pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
131
 
 
132
 
    if (!data->sink)
133
 
        data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, TRUE);
134
 
 
135
 
    pa_return_null_if_fail(data->sink);
136
 
    pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED);
137
 
    pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED));
 
146
    if (data->client)
 
147
        pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
 
148
 
 
149
    if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
 
150
        return r;
 
151
 
 
152
    pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
 
153
 
 
154
    if (!data->sink) {
 
155
        data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
 
156
        data->save_sink = FALSE;
 
157
    }
 
158
 
 
159
    pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY);
 
160
    pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
 
161
    pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED), -PA_ERR_INVALID);
138
162
 
139
163
    if (!data->sample_spec_is_set)
140
164
        data->sample_spec = data->sink->sample_spec;
141
165
 
142
 
    pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
 
166
    pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
143
167
 
144
168
    if (!data->channel_map_is_set) {
145
 
        if (data->sink->channel_map.channels == data->sample_spec.channels)
 
169
        if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
146
170
            data->channel_map = data->sink->channel_map;
147
171
        else
148
172
            pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
149
173
    }
150
174
 
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);
 
175
    pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
 
176
    pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
153
177
 
154
178
    if (!data->volume_is_set) {
155
179
        pa_cvolume_reset(&data->volume, data->sample_spec.channels);
 
180
        data->volume_is_absolute = FALSE;
 
181
        data->save_volume = FALSE;
156
182
    }
157
183
 
158
 
    pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
159
 
    pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec));
 
184
    pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID);
 
185
    pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
 
186
 
 
187
    if (!data->volume_factor_is_set)
 
188
        pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
 
189
 
 
190
    pa_return_val_if_fail(pa_cvolume_valid(&data->volume_factor), -PA_ERR_INVALID);
 
191
    pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
160
192
 
161
193
    if (!data->muted_is_set)
162
194
        data->muted = FALSE;
183
215
    if (data->resample_method == PA_RESAMPLER_INVALID)
184
216
        data->resample_method = core->resample_method;
185
217
 
186
 
    pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
187
 
 
188
 
    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data) < 0)
189
 
        return NULL;
 
218
    pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
 
219
 
 
220
    if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
 
221
        return r;
 
222
 
 
223
    if ((flags & PA_SINK_INPUT_FAIL_ON_SUSPEND) &&
 
224
        pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
 
225
        pa_log_warn("Failed to create sink input: sink is suspended.");
 
226
        return -PA_ERR_BADSTATE;
 
227
    }
190
228
 
191
229
    if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
192
230
        pa_log_warn("Failed to create sink input: too many inputs per sink.");
193
 
        return NULL;
 
231
        return -PA_ERR_TOOLARGE;
194
232
    }
195
233
 
196
234
    if ((flags & PA_SINK_INPUT_VARIABLE_RATE) ||
207
245
                      (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
208
246
                      (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
209
247
            pa_log_warn("Unsupported resampling operation.");
210
 
            return NULL;
 
248
            return -PA_ERR_NOTSUPPORTED;
211
249
        }
212
 
 
213
 
        data->resample_method = pa_resampler_get_method(resampler);
214
250
    }
215
251
 
216
252
    i = pa_msgobject_new(pa_sink_input);
221
257
    i->state = PA_SINK_INPUT_INIT;
222
258
    i->flags = flags;
223
259
    i->proplist = pa_proplist_copy(data->proplist);
224
 
    i->driver = pa_xstrdup(data->driver);
 
260
    i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
225
261
    i->module = data->module;
226
262
    i->sink = data->sink;
227
263
    i->client = data->client;
228
264
 
229
 
    i->resample_method = data->resample_method;
 
265
    i->requested_resample_method = data->resample_method;
 
266
    i->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID;
230
267
    i->sample_spec = data->sample_spec;
231
268
    i->channel_map = data->channel_map;
232
269
 
233
 
    i->volume = data->volume;
 
270
    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !data->volume_is_absolute) {
 
271
        /* When the 'absolute' bool is not set then we'll treat the volume
 
272
         * as relative to the sink volume even in flat volume mode */
 
273
 
 
274
        pa_cvolume v = data->sink->reference_volume;
 
275
        pa_cvolume_remap(&v, &data->sink->channel_map, &data->channel_map);
 
276
        pa_sw_cvolume_multiply(&i->virtual_volume, &data->volume, &v);
 
277
    } else
 
278
        i->virtual_volume = data->volume;
 
279
 
 
280
    i->volume_factor = data->volume_factor;
 
281
    pa_cvolume_init(&i->soft_volume);
 
282
    memset(i->relative_volume, 0, sizeof(i->relative_volume));
 
283
    i->save_volume = data->save_volume;
 
284
    i->save_sink = data->save_sink;
 
285
    i->save_muted = data->save_muted;
 
286
 
234
287
    i->muted = data->muted;
235
288
 
236
289
    if (data->sync_base) {
253
306
    pa_atomic_store(&i->thread_info.drained, 1);
254
307
    i->thread_info.sample_spec = i->sample_spec;
255
308
    i->thread_info.resampler = resampler;
256
 
    i->thread_info.volume = i->volume;
 
309
    i->thread_info.soft_volume = i->soft_volume;
257
310
    i->thread_info.muted = i->muted;
258
311
    i->thread_info.requested_sink_latency = (pa_usec_t) -1;
259
312
    i->thread_info.rewrite_nbytes = 0;
260
313
    i->thread_info.rewrite_flush = FALSE;
 
314
    i->thread_info.dont_rewind_render = FALSE;
261
315
    i->thread_info.underrun_for = (uint64_t) -1;
262
316
    i->thread_info.playing_for = 0;
263
317
    i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
272
326
            0,
273
327
            &i->sink->silence);
274
328
 
275
 
    pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0);
276
 
    pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0);
 
329
    pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
 
330
    pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
 
331
 
 
332
    if (i->client)
 
333
        pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
277
334
 
278
335
    pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s",
279
336
                i->index,
284
341
 
285
342
    /* Don't forget to call pa_sink_input_put! */
286
343
 
287
 
    return i;
 
344
    *_i = i;
 
345
    return 0;
288
346
}
289
347
 
290
348
/* Called from main context */
291
349
static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
292
350
    pa_assert(i);
293
351
 
 
352
    if (!i->sink)
 
353
        return;
 
354
 
294
355
    if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED)
295
356
        pa_assert_se(i->sink->n_corked -- >= 1);
296
357
    else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED)
297
358
        i->sink->n_corked++;
298
 
 
299
 
    pa_sink_update_status(i->sink);
300
359
}
301
360
 
302
361
/* Called from main context */
303
 
static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
 
362
static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
304
363
    pa_sink_input *ssync;
305
364
    pa_assert(i);
306
365
 
308
367
        state = PA_SINK_INPUT_RUNNING;
309
368
 
310
369
    if (i->state == state)
311
 
        return 0;
 
370
        return;
312
371
 
313
372
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
314
373
 
325
384
    }
326
385
 
327
386
    if (state != PA_SINK_INPUT_UNLINKED) {
328
 
        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
 
387
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
329
388
 
330
389
        for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
331
 
            pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
 
390
            pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
332
391
 
333
392
        for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
334
 
            pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
 
393
            pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
335
394
    }
336
395
 
337
 
    return 0;
 
396
    pa_sink_update_status(i->sink);
338
397
}
339
398
 
340
399
/* Called from main context */
351
410
    linked = PA_SINK_INPUT_IS_LINKED(i->state);
352
411
 
353
412
    if (linked)
354
 
        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
 
413
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
355
414
 
356
415
    if (i->sync_prev)
357
416
        i->sync_prev->sync_next = i->sync_next;
360
419
 
361
420
    i->sync_prev = i->sync_next = NULL;
362
421
 
363
 
    pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
364
 
    if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
365
 
        pa_sink_input_unref(i);
 
422
    pa_idxset_remove_by_data(i->core->sink_inputs, i, NULL);
 
423
 
 
424
    if (i->sink)
 
425
        if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
 
426
            pa_sink_input_unref(i);
 
427
 
 
428
    if (i->client)
 
429
        pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL);
366
430
 
367
431
    while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
368
432
        pa_assert(o != p);
373
437
    update_n_corked(i, PA_SINK_INPUT_UNLINKED);
374
438
    i->state = PA_SINK_INPUT_UNLINKED;
375
439
 
376
 
    if (linked)
 
440
    if (linked && i->sink) {
 
441
        /* We might need to update the sink's volume if we are in flat volume mode. */
 
442
        if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
 
443
            pa_cvolume new_volume;
 
444
            pa_sink_update_flat_volume(i->sink, &new_volume);
 
445
            pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE);
 
446
        }
 
447
 
377
448
        if (i->sink->asyncmsgq)
378
449
            pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
 
450
    }
379
451
 
380
452
    reset_callbacks(i);
381
453
 
382
454
    if (linked) {
383
 
        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
384
 
        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
385
 
    }
386
 
 
387
 
    i->sink = NULL;
 
455
        pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
 
456
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
 
457
    }
 
458
 
 
459
    if (i->sink) {
 
460
        pa_sink_update_status(i->sink);
 
461
        i->sink = NULL;
 
462
    }
 
463
 
 
464
    pa_core_maybe_vacuum(i->core);
 
465
 
388
466
    pa_sink_input_unref(i);
389
467
}
390
468
 
433
511
    pa_assert(i->process_rewind);
434
512
    pa_assert(i->kill);
435
513
 
436
 
    i->thread_info.volume = i->volume;
437
 
    i->thread_info.muted = i->muted;
438
 
 
439
514
    state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
440
515
 
441
516
    update_n_corked(i, state);
442
517
    i->state = state;
443
518
 
 
519
    /* We might need to update the sink's volume if we are in flat volume mode. */
 
520
    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
 
521
        pa_cvolume new_volume;
 
522
        pa_sink_update_flat_volume(i->sink, &new_volume);
 
523
        pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE);
 
524
    } else
 
525
        pa_sink_input_set_relative_volume(i, &i->virtual_volume);
 
526
 
 
527
    i->thread_info.soft_volume = i->soft_volume;
 
528
    i->thread_info.muted = i->muted;
 
529
 
444
530
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
445
531
 
446
 
    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
447
 
    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
 
532
    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
 
533
    pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
 
534
 
 
535
    pa_sink_update_status(i->sink);
448
536
}
449
537
 
450
538
/* Called from main context */
474
562
}
475
563
 
476
564
/* Called from thread context */
477
 
int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
 
565
void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
478
566
    pa_bool_t do_volume_adj_here;
479
567
    pa_bool_t volume_is_norm;
480
568
    size_t block_size_max_sink, block_size_max_sink_input;
488
576
 
489
577
/*     pa_log_debug("peek"); */
490
578
 
491
 
    if (!i->pop)
492
 
        return -1;
493
 
 
494
579
    pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
495
580
              i->thread_info.state == PA_SINK_INPUT_CORKED ||
496
581
              i->thread_info.state == PA_SINK_INPUT_DRAINED);
497
582
 
498
583
    block_size_max_sink_input = i->thread_info.resampler ?
499
584
        pa_resampler_max_block_size(i->thread_info.resampler) :
500
 
        pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec);
 
585
        pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sample_spec);
501
586
 
502
 
    block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sink->sample_spec);
 
587
    block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->core->mempool), &i->sink->sample_spec);
503
588
 
504
589
    /* Default buffer size */
505
590
    if (slength <= 0)
524
609
     * it after and leave it for the sink code */
525
610
 
526
611
    do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
527
 
    volume_is_norm = pa_cvolume_is_norm(&i->thread_info.volume) && !i->thread_info.muted;
 
612
    volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
528
613
 
529
614
    while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
530
615
        pa_memchunk tchunk;
539
624
             * data, so let's just hand out silence */
540
625
            pa_atomic_store(&i->thread_info.drained, 1);
541
626
 
542
 
            pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE);
 
627
            pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE);
543
628
            i->thread_info.playing_for = 0;
544
629
            if (i->thread_info.underrun_for != (uint64_t) -1)
545
630
                i->thread_info.underrun_for += ilength;
570
655
                if (i->thread_info.muted)
571
656
                    pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
572
657
                else
573
 
                    pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.volume);
 
658
                    pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
574
659
            }
575
660
 
576
661
            if (!i->thread_info.resampler)
616
701
        /* We've both the same channel map, so let's have the sink do the adjustment for us*/
617
702
        pa_cvolume_mute(volume, i->sink->sample_spec.channels);
618
703
    else
619
 
        *volume = i->thread_info.volume;
620
 
 
621
 
    return 0;
 
704
        *volume = i->thread_info.soft_volume;
622
705
}
623
706
 
624
707
/* Called from thread context */
647
730
 
648
731
    lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
649
732
 
650
 
    if (nbytes > 0) {
 
733
    if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
651
734
        pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
652
735
        pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
653
736
    }
686
769
 
687
770
            if (amount > 0)
688
771
                /* Ok, now update the write pointer */
689
 
                pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE);
 
772
                pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE);
690
773
 
691
774
            if (i->thread_info.rewrite_flush)
692
775
                pa_memblockq_silence(i->thread_info.render_memblockq);
703
786
 
704
787
    i->thread_info.rewrite_nbytes = 0;
705
788
    i->thread_info.rewrite_flush = FALSE;
 
789
    i->thread_info.dont_rewind_render = FALSE;
706
790
}
707
791
 
708
792
/* Called from thread context */
728
812
}
729
813
 
730
814
/* Called from thread context */
731
 
static pa_usec_t fixup_latency(pa_sink *s, pa_usec_t usec) {
732
 
    pa_sink_assert_ref(s);
733
 
 
734
 
    if (usec == (pa_usec_t) -1)
735
 
        return usec;
736
 
 
737
 
    if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
738
 
        usec = s->thread_info.max_latency;
739
 
 
740
 
    if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
741
 
        usec = s->thread_info.min_latency;
742
 
 
743
 
    return usec;
744
 
}
745
 
 
746
 
/* Called from thread context */
747
815
pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
748
816
    pa_sink_input_assert_ref(i);
749
817
 
750
 
    usec = fixup_latency(i->sink, usec);
 
818
    if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
 
819
        usec = i->sink->fixed_latency;
 
820
 
 
821
    if (usec != (pa_usec_t) -1)
 
822
        usec =  PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
 
823
 
751
824
    i->thread_info.requested_sink_latency = usec;
752
825
    pa_sink_invalidate_requested_latency(i->sink);
753
826
 
758
831
pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
759
832
    pa_sink_input_assert_ref(i);
760
833
 
761
 
    if (PA_SINK_INPUT_IS_LINKED(i->state))
 
834
    if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
762
835
        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
763
 
    else
764
 
        /* If this sink input is not realized yet, we have to touch
765
 
         * the thread info data directly */
766
 
 
767
 
        i->thread_info.requested_sink_latency = usec;
 
836
        return usec;
 
837
    }
 
838
 
 
839
    /* If this sink input is not realized yet or we are being moved,
 
840
     * we have to touch the thread info data directly */
 
841
 
 
842
    if (i->sink) {
 
843
        if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
 
844
            usec = i->sink->fixed_latency;
 
845
 
 
846
        if (usec != (pa_usec_t) -1) {
 
847
            pa_usec_t min_latency, max_latency;
 
848
            pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
 
849
            usec =  PA_CLAMP(usec, min_latency, max_latency);
 
850
        }
 
851
    }
 
852
 
 
853
    i->thread_info.requested_sink_latency = usec;
768
854
 
769
855
    return usec;
770
856
}
771
857
 
772
858
/* Called from main context */
773
859
pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
774
 
    pa_usec_t usec = 0;
775
 
 
776
860
    pa_sink_input_assert_ref(i);
777
861
 
778
 
    if (PA_SINK_INPUT_IS_LINKED(i->state))
 
862
    if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
 
863
        pa_usec_t usec = 0;
779
864
        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
780
 
    else
781
 
        /* If this sink input is not realized yet, we have to touch
782
 
         * the thread info data directly */
783
 
        usec = i->thread_info.requested_sink_latency;
784
 
 
785
 
    return usec;
 
865
        return usec;
 
866
    }
 
867
 
 
868
    /* If this sink input is not realized yet or we are being moved,
 
869
     * we have to touch the thread info data directly */
 
870
 
 
871
    return i->thread_info.requested_sink_latency;
786
872
}
787
873
 
788
874
/* Called from main context */
789
 
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
 
875
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
 
876
    pa_cvolume v;
 
877
 
790
878
    pa_sink_input_assert_ref(i);
791
879
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
792
880
    pa_assert(volume);
793
 
 
794
 
    if (pa_cvolume_equal(&i->volume, volume))
 
881
    pa_assert(pa_cvolume_valid(volume));
 
882
    pa_assert(pa_cvolume_compatible(volume, &i->sample_spec));
 
883
 
 
884
    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
 
885
        v = i->sink->reference_volume;
 
886
        pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
 
887
        volume = pa_sw_cvolume_multiply(&v, &v, volume);
 
888
    }
 
889
 
 
890
    if (pa_cvolume_equal(volume, &i->virtual_volume))
795
891
        return;
796
892
 
797
 
    i->volume = *volume;
798
 
 
799
 
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &i->volume, 0, NULL) == 0);
800
 
    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
801
 
}
802
 
 
803
 
/* Called from main context */
804
 
const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
805
 
    pa_sink_input_assert_ref(i);
806
 
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
807
 
 
808
 
    return &i->volume;
809
 
}
810
 
 
811
 
/* Called from main context */
812
 
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) {
 
893
    i->virtual_volume = *volume;
 
894
    i->save_volume = save;
 
895
 
 
896
    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
 
897
        pa_cvolume new_volume;
 
898
 
 
899
        /* We are in flat volume mode, so let's update all sink input
 
900
         * volumes and update the flat volume of the sink */
 
901
 
 
902
        pa_sink_update_flat_volume(i->sink, &new_volume);
 
903
        pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE, FALSE);
 
904
 
 
905
    } else {
 
906
 
 
907
        /* OK, we are in normal volume mode. The volume only affects
 
908
         * ourselves */
 
909
        pa_sink_input_set_relative_volume(i, volume);
 
910
 
 
911
        /* Hooks have the ability to play games with i->soft_volume */
 
912
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
 
913
 
 
914
        /* Copy the new soft_volume to the thread_info struct */
 
915
        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
 
916
    }
 
917
 
 
918
    /* The virtual volume changed, let's tell people so */
 
919
    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
920
}
 
921
 
 
922
/* Called from main context */
 
923
pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) {
 
924
    pa_sink_input_assert_ref(i);
 
925
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
926
 
 
927
    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
 
928
        pa_cvolume v = i->sink->reference_volume;
 
929
        pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
 
930
        pa_sw_cvolume_divide(volume, &i->virtual_volume, &v);
 
931
    } else
 
932
        *volume = i->virtual_volume;
 
933
 
 
934
    return volume;
 
935
}
 
936
 
 
937
/* Called from main context */
 
938
pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) {
 
939
    unsigned c;
 
940
 
 
941
    pa_sink_input_assert_ref(i);
 
942
    pa_assert(v);
 
943
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
944
 
 
945
    /* This always returns the relative volume. Converts the float
 
946
     * version into a pa_cvolume */
 
947
 
 
948
    v->channels = i->sample_spec.channels;
 
949
 
 
950
    for (c = 0; c < v->channels; c++)
 
951
        v->values[c] = pa_sw_volume_from_linear(i->relative_volume[c]);
 
952
 
 
953
    return v;
 
954
}
 
955
 
 
956
/* Called from main context */
 
957
void pa_sink_input_set_relative_volume(pa_sink_input *i, const pa_cvolume *v) {
 
958
    unsigned c;
 
959
    pa_cvolume _v;
 
960
 
 
961
    pa_sink_input_assert_ref(i);
 
962
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
963
    pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
 
964
 
 
965
    if (!v)
 
966
        v = pa_cvolume_reset(&_v, i->sample_spec.channels);
 
967
 
 
968
    /* This basically calculates:
 
969
     *
 
970
     * i->relative_volume := v
 
971
     * i->soft_volume := i->relative_volume * i->volume_factor */
 
972
 
 
973
    i->soft_volume.channels = i->sample_spec.channels;
 
974
 
 
975
    for (c = 0; c < i->sample_spec.channels; c++) {
 
976
        i->relative_volume[c] = pa_sw_volume_to_linear(v->values[c]);
 
977
 
 
978
        i->soft_volume.values[c] = pa_sw_volume_from_linear(
 
979
                i->relative_volume[c] *
 
980
                pa_sw_volume_to_linear(i->volume_factor.values[c]));
 
981
    }
 
982
 
 
983
    /* We don't copy the data to the thread_info data. That's left for someone else to do */
 
984
}
 
985
 
 
986
/* Called from main context */
 
987
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
813
988
    pa_assert(i);
814
989
    pa_sink_input_assert_ref(i);
815
990
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
818
993
        return;
819
994
 
820
995
    i->muted = mute;
 
996
    i->save_muted = save;
821
997
 
822
 
    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
823
 
    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
998
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0);
 
999
    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
824
1000
}
825
1001
 
826
1002
/* Called from main context */
831
1007
    return i->muted;
832
1008
}
833
1009
 
 
1010
/* Called from main thread */
 
1011
void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
 
1012
    pa_sink_input_assert_ref(i);
 
1013
 
 
1014
    if (p)
 
1015
        pa_proplist_update(i->proplist, mode, p);
 
1016
 
 
1017
    if (PA_SINK_IS_LINKED(i->state)) {
 
1018
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
 
1019
        pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
1020
    }
 
1021
}
 
1022
 
834
1023
/* Called from main context */
835
1024
void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
836
1025
    pa_sink_input_assert_ref(i);
843
1032
int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
844
1033
    pa_sink_input_assert_ref(i);
845
1034
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
846
 
    pa_return_val_if_fail(i->thread_info.resampler, -1);
 
1035
    pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
847
1036
 
848
1037
    if (i->sample_spec.rate == rate)
849
1038
        return 0;
852
1041
 
853
1042
    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL);
854
1043
 
855
 
    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
1044
    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
856
1045
    return 0;
857
1046
}
858
1047
 
875
1064
        pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
876
1065
 
877
1066
    if (PA_SINK_INPUT_IS_LINKED(i->state)) {
878
 
        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
879
 
        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
1067
        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
 
1068
        pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
880
1069
    }
881
1070
}
882
1071
 
884
1073
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
885
1074
    pa_sink_input_assert_ref(i);
886
1075
 
887
 
    return i->resample_method;
 
1076
    return i->actual_resample_method;
888
1077
}
889
1078
 
890
1079
/* Called from main context */
891
 
int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
892
 
    pa_resampler *new_resampler;
893
 
    pa_sink *origin;
894
 
    pa_sink_input_move_hook_data hook_data;
895
 
    pa_source_output *o, *p = NULL;
896
 
 
 
1080
pa_bool_t pa_sink_input_may_move(pa_sink_input *i) {
897
1081
    pa_sink_input_assert_ref(i);
898
1082
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
899
 
    pa_sink_assert_ref(dest);
900
 
 
901
 
    origin = i->sink;
902
 
 
903
 
    if (dest == origin)
904
 
        return 0;
905
1083
 
906
1084
    if (i->flags & PA_SINK_INPUT_DONT_MOVE)
907
 
        return -1;
 
1085
        return FALSE;
908
1086
 
909
1087
    if (i->sync_next || i->sync_prev) {
910
1088
        pa_log_warn("Moving synchronised streams not supported.");
911
 
        return -1;
 
1089
        return FALSE;
912
1090
    }
913
1091
 
 
1092
    return TRUE;
 
1093
}
 
1094
 
 
1095
/* Called from main context */
 
1096
pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
 
1097
    pa_sink_input_assert_ref(i);
 
1098
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
1099
    pa_sink_assert_ref(dest);
 
1100
 
 
1101
    if (dest == i->sink)
 
1102
        return TRUE;
 
1103
 
 
1104
    if (!pa_sink_input_may_move(i))
 
1105
        return FALSE;
 
1106
 
914
1107
    if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) {
915
1108
        pa_log_warn("Failed to move sink input: too many inputs per sink.");
916
 
        return -1;
 
1109
        return FALSE;
917
1110
    }
918
1111
 
 
1112
    if (i->may_move_to)
 
1113
        if (!i->may_move_to(i, dest))
 
1114
            return FALSE;
 
1115
 
 
1116
    return TRUE;
 
1117
}
 
1118
 
 
1119
/* Called from main context */
 
1120
int pa_sink_input_start_move(pa_sink_input *i) {
 
1121
    pa_source_output *o, *p = NULL;
 
1122
    pa_sink *origin;
 
1123
    int r;
 
1124
 
 
1125
    pa_sink_input_assert_ref(i);
 
1126
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
1127
    pa_assert(i->sink);
 
1128
 
 
1129
    if (!pa_sink_input_may_move(i))
 
1130
        return -PA_ERR_NOTSUPPORTED;
 
1131
 
 
1132
    if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
 
1133
        return r;
 
1134
 
 
1135
    origin = i->sink;
 
1136
 
919
1137
    /* Kill directly connected outputs */
920
1138
    while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
921
1139
        pa_assert(o != p);
922
1140
        pa_source_output_kill(o);
923
1141
        p = o;
924
1142
    }
 
1143
    pa_assert(pa_idxset_isempty(i->direct_outputs));
 
1144
 
 
1145
    pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
 
1146
 
 
1147
    if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
 
1148
        pa_assert_se(i->sink->n_corked-- >= 1);
 
1149
 
 
1150
    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
 
1151
        pa_cvolume new_volume;
 
1152
 
 
1153
        /* Make the virtual volume relative */
 
1154
        pa_sink_input_get_relative_volume(i, &i->virtual_volume);
 
1155
 
 
1156
        /* And reset the the relative volume */
 
1157
        pa_sink_input_set_relative_volume(i, NULL);
 
1158
 
 
1159
        /* We might need to update the sink's volume if we are in flat
 
1160
         * volume mode. */
 
1161
        pa_sink_update_flat_volume(i->sink, &new_volume);
 
1162
        pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE);
 
1163
    }
 
1164
 
 
1165
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
 
1166
 
 
1167
    pa_sink_update_status(i->sink);
 
1168
    i->sink = NULL;
 
1169
 
 
1170
    pa_sink_input_unref(i);
 
1171
 
 
1172
    return 0;
 
1173
}
 
1174
 
 
1175
/* Called from main context */
 
1176
int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
 
1177
    pa_resampler *new_resampler;
 
1178
 
 
1179
    pa_sink_input_assert_ref(i);
 
1180
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
1181
    pa_assert(!i->sink);
 
1182
    pa_sink_assert_ref(dest);
 
1183
 
 
1184
    if (!pa_sink_input_may_move_to(i, dest))
 
1185
        return -PA_ERR_NOTSUPPORTED;
925
1186
 
926
1187
    if (i->thread_info.resampler &&
927
 
        pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
928
 
        pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
 
1188
        pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
 
1189
        pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map))
929
1190
 
930
1191
        /* Try to reuse the old resampler if possible */
931
1192
        new_resampler = i->thread_info.resampler;
937
1198
        /* Okey, we need a new resampler for the new sink */
938
1199
 
939
1200
        if (!(new_resampler = pa_resampler_new(
940
 
                      dest->core->mempool,
 
1201
                      i->core->mempool,
941
1202
                      &i->sample_spec, &i->channel_map,
942
1203
                      &dest->sample_spec, &dest->channel_map,
943
 
                      i->resample_method,
 
1204
                      i->requested_resample_method,
944
1205
                      ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
945
1206
                      ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
946
1207
                      (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
947
1208
            pa_log_warn("Unsupported resampling operation.");
948
 
            return -1;
 
1209
            return -PA_ERR_NOTSUPPORTED;
949
1210
        }
950
1211
    } else
951
1212
        new_resampler = NULL;
952
1213
 
953
 
    hook_data.sink_input = i;
954
 
    hook_data.destination = dest;
955
 
    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], &hook_data);
956
 
 
957
 
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
958
 
 
959
 
    pa_idxset_remove_by_data(origin->inputs, i, NULL);
960
 
    pa_idxset_put(dest->inputs, i, NULL);
 
1214
    if (i->moving)
 
1215
        i->moving(i, dest);
 
1216
 
961
1217
    i->sink = dest;
 
1218
    i->save_sink = save;
 
1219
    pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
962
1220
 
963
 
    if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) {
964
 
        pa_assert_se(origin->n_corked-- >= 1);
965
 
        dest->n_corked++;
966
 
    }
 
1221
    if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
 
1222
        i->sink->n_corked++;
967
1223
 
968
1224
    /* Replace resampler and render queue */
969
1225
    if (new_resampler != i->thread_info.resampler) {
984
1240
                0,
985
1241
                &i->sink->silence);
986
1242
    }
987
 
 
988
 
    pa_sink_update_status(origin);
989
1243
    pa_sink_update_status(dest);
990
1244
 
 
1245
    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
 
1246
        pa_cvolume new_volume;
 
1247
 
 
1248
        /* Make relative volume absolute again */
 
1249
        pa_cvolume t = dest->reference_volume;
 
1250
        pa_cvolume_remap(&t, &dest->channel_map, &i->channel_map);
 
1251
        pa_sw_cvolume_multiply(&i->virtual_volume, &i->virtual_volume, &t);
 
1252
 
 
1253
        /* We might need to update the sink's volume if we are in flat volume mode. */
 
1254
        pa_sink_update_flat_volume(i->sink, &new_volume);
 
1255
        pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE);
 
1256
    }
 
1257
 
991
1258
    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
992
1259
 
993
 
    if (i->moved)
994
 
        i->moved(i);
995
 
 
996
 
    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], i);
997
 
 
998
 
    pa_log_debug("Successfully moved sink input %i from %s to %s.", i->index, origin->name, dest->name);
 
1260
    pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
999
1261
 
1000
1262
    /* Notify everyone */
1001
 
    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
1263
    pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
 
1264
    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 
1265
 
 
1266
    return 0;
 
1267
}
 
1268
 
 
1269
/* Called from main context */
 
1270
int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
 
1271
    int r;
 
1272
 
 
1273
    pa_sink_input_assert_ref(i);
 
1274
    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
1275
    pa_assert(i->sink);
 
1276
    pa_sink_assert_ref(dest);
 
1277
 
 
1278
    if (dest == i->sink)
 
1279
        return 0;
 
1280
 
 
1281
    if (!pa_sink_input_may_move_to(i, dest))
 
1282
        return -PA_ERR_NOTSUPPORTED;
 
1283
 
 
1284
    pa_sink_input_ref(i);
 
1285
 
 
1286
    if ((r = pa_sink_input_start_move(i)) < 0) {
 
1287
        pa_sink_input_unref(i);
 
1288
        return r;
 
1289
    }
 
1290
 
 
1291
    if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
 
1292
        pa_sink_input_unref(i);
 
1293
        return r;
 
1294
    }
 
1295
 
 
1296
    pa_sink_input_unref(i);
1002
1297
 
1003
1298
    return 0;
1004
1299
}
1029
1324
 
1030
1325
        /* This will tell the implementing sink input driver to rewind
1031
1326
         * so that the unplayed already mixed data is not lost */
1032
 
        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
 
1327
        pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
1033
1328
 
1034
1329
    } else if (uncorking) {
1035
1330
 
1040
1335
 
1041
1336
        /* OK, we're being uncorked. Make sure we're not rewound when
1042
1337
         * the hw buffer is remixed and request a remix. */
1043
 
        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
 
1338
        pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1044
1339
    }
1045
1340
}
1046
1341
 
1051
1346
 
1052
1347
    switch (code) {
1053
1348
 
1054
 
        case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
1055
 
            i->thread_info.volume = *((pa_cvolume*) userdata);
1056
 
            pa_sink_input_request_rewind(i, 0, TRUE, FALSE);
 
1349
        case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME:
 
1350
            if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) {
 
1351
                i->thread_info.soft_volume = i->soft_volume;
 
1352
                pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
 
1353
            }
1057
1354
            return 0;
1058
1355
 
1059
 
        case PA_SINK_INPUT_MESSAGE_SET_MUTE:
1060
 
            i->thread_info.muted = PA_PTR_TO_UINT(userdata);
1061
 
            pa_sink_input_request_rewind(i, 0, TRUE, FALSE);
 
1356
        case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
 
1357
            if (i->thread_info.muted != i->muted) {
 
1358
                i->thread_info.muted = i->muted;
 
1359
                pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
 
1360
            }
1062
1361
            return 0;
1063
1362
 
1064
1363
        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1065
1364
            pa_usec_t *r = userdata;
1066
 
            pa_usec_t sink_usec = 0;
1067
1365
 
1068
1366
            r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
1069
 
 
1070
 
            if (i->sink->parent.process_msg(PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_usec, 0, NULL) >= 0)
1071
 
                r[1] += sink_usec;
 
1367
            r[1] += pa_sink_get_latency_within_thread(i->sink);
1072
1368
 
1073
1369
            return 0;
1074
1370
        }
1109
1405
        }
1110
1406
    }
1111
1407
 
1112
 
    return -1;
 
1408
    return -PA_ERR_NOTIMPLEMENTED;
1113
1409
}
1114
1410
 
1115
1411
/* Called from main thread */
1133
1429
}
1134
1430
 
1135
1431
/* Called from IO context */
1136
 
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush) {
 
1432
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render) {
1137
1433
    size_t lbq;
1138
1434
 
1139
1435
    /* If 'rewrite' is TRUE the sink is rewound as far as requested
1144
1440
     * If 'rewrite' is FALSE the sink is rewound as far as requested
1145
1441
     * and possible and the already rendered data is dropped so that
1146
1442
     * in the next iteration we read new data from the
1147
 
     * implementor. This implies 'flush' is TRUE. */
 
1443
     * implementor. This implies 'flush' is TRUE.  If
 
1444
     * dont_rewind_render is TRUE then the render memblockq is not
 
1445
     * rewound. */
1148
1446
 
1149
1447
    pa_sink_input_assert_ref(i);
1150
1448
 
1157
1455
        return;
1158
1456
 
1159
1457
    pa_assert(rewrite || flush);
 
1458
    pa_assert(!dont_rewind_render || !rewrite);
1160
1459
 
1161
1460
    /* Calculate how much we can rewind locally without having to
1162
1461
     * touch the sink */
1191
1490
        i->thread_info.rewrite_flush ||
1192
1491
        (flush && i->thread_info.rewrite_nbytes != 0);
1193
1492
 
 
1493
    i->thread_info.dont_rewind_render =
 
1494
        i->thread_info.dont_rewind_render ||
 
1495
        dont_rewind_render;
 
1496
 
1194
1497
    if (nbytes != (size_t) -1) {
1195
1498
 
1196
1499
        /* Transform to sink domain */
1211
1514
    pa_assert(ret);
1212
1515
 
1213
1516
    pa_silence_memchunk_get(
1214
 
                &i->sink->core->silence_cache,
1215
 
                i->sink->core->mempool,
 
1517
                &i->core->silence_cache,
 
1518
                i->core->mempool,
1216
1519
                ret,
1217
1520
                &i->sample_spec,
1218
1521
                i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
1219
1522
 
1220
1523
    return ret;
1221
1524
}
 
1525
 
 
1526
/* Called from main context */
 
1527
void pa_sink_input_send_event(pa_sink_input *i, const char *event, pa_proplist *data) {
 
1528
    pa_proplist *pl = NULL;
 
1529
    pa_sink_input_send_event_hook_data hook_data;
 
1530
 
 
1531
    pa_sink_input_assert_ref(i);
 
1532
    pa_assert(event);
 
1533
 
 
1534
    if (!i->send_event)
 
1535
        return;
 
1536
 
 
1537
    if (!data)
 
1538
        data = pl = pa_proplist_new();
 
1539
 
 
1540
    hook_data.sink_input = i;
 
1541
    hook_data.data = data;
 
1542
    hook_data.event = event;
 
1543
 
 
1544
    if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], &hook_data) < 0)
 
1545
        goto finish;
 
1546
 
 
1547
    i->send_event(i, event, data);
 
1548
 
 
1549
finish:
 
1550
    if (pl)
 
1551
        pa_proplist_free(pl);
 
1552
}