pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
break;
- case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
- pa_tagstruct *t;
+ case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
s->buffer_attr.tlength = (uint32_t) offset;
- t = pa_tagstruct_new(NULL, 0);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
- pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
- pa_tagstruct_putu32(t, s->index);
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- pa_tagstruct_put_usec(t, s->configured_sink_latency);
- pa_pstream_send_tagstruct(s->connection->pstream, t);
+ if (s->connection->version >= 15) {
+ pa_tagstruct *t;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
+ pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+ pa_tagstruct_putu32(t, s->index);
+ pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.tlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(t, s->buffer_attr.minreq);
+ pa_tagstruct_put_usec(t, s->configured_sink_latency);
+ pa_pstream_send_tagstruct(s->connection->pstream, t);
+ }
break;
- }
}
return 0;
pa_assert(s);
+ /* pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes", */
+ /* (long) s->buffer_attr.maxlength, */
+ /* (long) s->buffer_attr.tlength, */
+ /* (long) s->buffer_attr.minreq, */
+ /* (long) s->buffer_attr.prebuf); */
+
+ /* pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
+
/* This function will be called from the main thread, before as
* well as after the sink input has been activated using
* pa_sink_input_put()! That means it may not touch any
if (s->buffer_attr.prebuf == (uint32_t) -1 ||
s->buffer_attr.prebuf > max_prebuf)
s->buffer_attr.prebuf = max_prebuf;
+
+ /* pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
+ /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
}
/* Called from main context */
pa_proplist *p,
pa_bool_t adjust_latency,
pa_bool_t early_requests,
+ pa_bool_t relative_volume,
int *ret) {
playback_stream *s, *ssync;
pa_assert(ret);
/* Find syncid group */
- for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
+ PA_IDXSET_FOREACH(ssync, c->output_streams, idx) {
if (!playback_stream_isinstance(ssync))
continue;
data.driver = __FILE__;
data.module = c->options->module;
data.client = c->client;
- data.sink = sink;
+ if (sink) {
+ data.sink = sink;
+ data.save_sink = TRUE;
+ }
pa_sink_input_new_data_set_sample_spec(&data, ss);
pa_sink_input_new_data_set_channel_map(&data, map);
- if (volume)
+ if (volume) {
pa_sink_input_new_data_set_volume(&data, volume);
- if (muted_set)
+ data.volume_is_absolute = !relative_volume;
+ data.save_volume = TRUE;
+ }
+ if (muted_set) {
pa_sink_input_new_data_set_muted(&data, muted);
+ data.save_muted = TRUE;
+ }
data.sync_base = ssync ? ssync->sink_input : NULL;
data.flags = flags;
*missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
+ /* pa_log("missing original: %li", (long int) *missing); */
+
*ss = s->sink_input->sample_spec;
*map = s->sink_input->channel_map;
m = pa_memblockq_pop_missing(s->memblockq);
- /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
+ /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
/* (unsigned long) m, */
/* pa_memblockq_get_tlength(s->memblockq), */
/* pa_memblockq_get_minreq(s->memblockq), */
- /* pa_memblockq_get_length(s->memblockq)); */
+ /* pa_memblockq_get_length(s->memblockq), */
+ /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
if (m <= 0)
return;
playback_stream_request_bytes(s);
}
+static void flush_write_no_account(pa_memblockq *q) {
+ pa_memblockq_flush_write(q, FALSE);
+}
+
/* Called from thread context */
static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_sink_input *i = PA_SINK_INPUT(o);
switch (code) {
case SINK_INPUT_MESSAGE_FLUSH:
- func = pa_memblockq_flush_write;
+ func = flush_write_no_account;
break;
case SINK_INPUT_MESSAGE_PREBUF_FORCE:
early_requests = FALSE,
dont_inhibit_auto_suspend = FALSE,
muted_set = FALSE,
- fail_on_suspend = FALSE;
+ fail_on_suspend = FALSE,
+ relative_volume = FALSE,
+ passthrough = FALSE;
+
pa_sink_input_flags_t flags = 0;
pa_proplist *p;
pa_bool_t volume_set = TRUE;
}
}
+ if (c->version >= 17) {
+
+ if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
+ protocol_error(c);
+ pa_proplist_free(p);
+ return;
+ }
+ }
+
+ if (c->version >= 18) {
+
+ if (pa_tagstruct_get_boolean(t, &passthrough) < 0 ) {
+ protocol_error(c);
+ pa_proplist_free(p);
+ return;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
protocol_error(c);
pa_proplist_free(p);
(no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
(variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
(dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
- (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0);
+ (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0) |
+ (passthrough ? PA_SINK_INPUT_PASSTHROUGH : 0);
/* Only since protocol version 15 there's a seperate muted_set
* flag. For older versions we synthesize it here */
muted_set = muted_set || muted;
- s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
+ s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, relative_volume, &ret);
pa_proplist_free(p);
CHECK_VALIDITY(c->pstream, s, tag, ret);
pa_tagstruct_put_usec(reply, s->current_monitor_latency);
pa_tagstruct_put_usec(reply,
s->current_source_latency +
- pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
+ pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec));
pa_tagstruct_put_boolean(reply,
pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
if (c->version >= 13)
pa_tagstruct_put_proplist(t, s->proplist);
+ if (c->version >= 19)
+ pa_tagstruct_put_boolean(t, (pa_sink_input_get_state(s) == PA_SINK_INPUT_CORKED));
}
static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
pa_tagstruct_put_usec(t, source_latency);
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
pa_tagstruct_puts(t, s->driver);
-
if (c->version >= 13)
pa_tagstruct_put_proplist(t, s->proplist);
+ if (c->version >= 19)
+ pa_tagstruct_put_boolean(t, (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_CORKED));
}
static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {