summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/protocol-native.c
diff options
context:
space:
mode:
authorColin Guthrie <colin@mageia.org>2011-05-17 21:56:10 +0100
committerColin Guthrie <colin@mageia.org>2011-06-22 21:55:27 +0100
commit5d35375aa758fde7d9f3d6467e2506aca9784597 (patch)
tree13a5eef2e1a06d0d5a9a76a83f0c90d085819e06 /src/pulsecore/protocol-native.c
parent30597b7c2747a52b1025e1172d73825e148fdec9 (diff)
capture: Add the passthrough format negotiation to capture streams.
This helps to keep the API more symmetrical and also potentially allows support for passthrough monitor sources at some point in the future.
Diffstat (limited to 'src/pulsecore/protocol-native.c')
-rw-r--r--src/pulsecore/protocol-native.c129
1 files changed, 90 insertions, 39 deletions
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index b16793d9..501ff378 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -629,13 +629,14 @@ static record_stream* record_stream_new(
pa_source *source,
pa_sample_spec *ss,
pa_channel_map *map,
- pa_bool_t peak_detect,
+ pa_idxset *formats,
pa_buffer_attr *attr,
pa_source_output_flags_t flags,
pa_proplist *p,
pa_bool_t adjust_latency,
- pa_sink_input *direct_on_input,
pa_bool_t early_requests,
+ pa_bool_t peak_detect,
+ pa_sink_input *direct_on_input,
int *ret) {
record_stream *s;
@@ -653,10 +654,15 @@ static record_stream* record_stream_new(
data.driver = __FILE__;
data.module = c->options->module;
data.client = c->client;
- data.source = source;
+ if (source)
+ pa_source_output_new_data_set_source(&data, source, TRUE);
+ if (pa_sample_spec_valid(ss))
+ pa_source_output_new_data_set_sample_spec(&data, ss);
+ if (pa_channel_map_valid(map))
+ pa_source_output_new_data_set_channel_map(&data, map);
+ if (formats)
+ pa_source_output_new_data_set_formats(&data, formats);
data.direct_on_input = direct_on_input;
- pa_source_output_new_data_set_sample_spec(&data, ss);
- pa_source_output_new_data_set_channel_map(&data, map);
if (peak_detect)
data.resample_method = PA_RESAMPLER_PEAKS;
data.flags = flags;
@@ -1028,13 +1034,13 @@ static playback_stream* playback_stream_new(
pa_cvolume *volume,
pa_bool_t muted,
pa_bool_t muted_set,
- uint32_t syncid,
- uint32_t *missing,
pa_sink_input_flags_t flags,
pa_proplist *p,
pa_bool_t adjust_latency,
pa_bool_t early_requests,
pa_bool_t relative_volume,
+ uint32_t syncid,
+ uint32_t *missing,
int *ret) {
/* Note: This function takes ownership of the 'formats' param, so we need
@@ -1900,6 +1906,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
adjust_latency = FALSE,
early_requests = FALSE,
dont_inhibit_auto_suspend = FALSE,
+ volume_set = TRUE,
muted_set = FALSE,
fail_on_suspend = FALSE,
relative_volume = FALSE,
@@ -1907,7 +1914,6 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
pa_sink_input_flags_t flags = 0;
pa_proplist *p = NULL;
- pa_bool_t volume_set = TRUE;
int ret = PA_ERR_INVALID;
uint8_t n_formats = 0;
pa_format_info *format;
@@ -2081,7 +2087,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
* flag. For older versions we synthesize it here */
muted_set = muted_set || muted;
- s = playback_stream_new(c, sink, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, relative_volume, &ret);
+ s = playback_stream_new(c, sink, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, flags, p, adjust_latency, early_requests, relative_volume, syncid, &missing, &ret);
/* We no longer own the formats idxset */
formats = NULL;
@@ -2222,12 +2228,18 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
peak_detect = FALSE,
early_requests = FALSE,
dont_inhibit_auto_suspend = FALSE,
- fail_on_suspend = FALSE;
+ fail_on_suspend = FALSE,
+ passthrough = FALSE;
+
pa_source_output_flags_t flags = 0;
- pa_proplist *p;
+ pa_proplist *p = NULL;
uint32_t direct_on_input_idx = PA_INVALID_INDEX;
pa_sink_input *direct_on_input = NULL;
int ret = PA_ERR_INVALID;
+ uint8_t n_formats = 0;
+ pa_format_info *format;
+ pa_idxset *formats = NULL;
+ uint32_t i;
pa_native_connection_assert_ref(c);
pa_assert(t);
@@ -2242,17 +2254,15 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
pa_tagstruct_get_boolean(t, &corked) < 0 ||
pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
+
protocol_error(c);
- return;
+ goto finish;
}
- CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
- CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
- CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
- CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
- CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
- CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
- CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
+ CHECK_VALIDITY_GOTO(c->pstream, c->authorized, tag, PA_ERR_ACCESS, finish);
+ CHECK_VALIDITY_GOTO(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID, finish);
+ CHECK_VALIDITY_GOTO(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID, finish);
+ CHECK_VALIDITY_GOTO(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID, finish);
p = pa_proplist_new();
@@ -2271,8 +2281,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
protocol_error(c);
- pa_proplist_free(p);
- return;
+ goto finish;
}
}
@@ -2282,9 +2291,9 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
pa_tagstruct_get_proplist(t, p) < 0 ||
pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
+
protocol_error(c);
- pa_proplist_free(p);
- return;
+ goto finish;
}
}
@@ -2292,8 +2301,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
protocol_error(c);
- pa_proplist_free(p);
- return;
+ goto finish;
}
}
@@ -2301,32 +2309,59 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
+
protocol_error(c);
- pa_proplist_free(p);
- return;
+ goto finish;
+ }
+ }
+
+ if (c->version >= 22) {
+
+ if (pa_tagstruct_getu8(t, &n_formats) < 0) {
+ protocol_error(c);
+ goto finish;
+ }
+
+ if (n_formats)
+ formats = pa_idxset_new(NULL, NULL);
+
+ for (i = 0; i < n_formats; i++) {
+ format = pa_format_info_new();
+ if (pa_tagstruct_get_format_info(t, format) < 0) {
+ protocol_error(c);
+ goto finish;
+ }
+ pa_idxset_put(formats, format, NULL);
}
}
+ if (n_formats == 0) {
+ CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
+ CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
+ } else {
+ PA_IDXSET_FOREACH(format, formats, i) {
+ CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
+ }
+ }
+
+
if (!pa_tagstruct_eof(t)) {
protocol_error(c);
- pa_proplist_free(p);
- return;
+ goto finish;
}
if (source_index != PA_INVALID_INDEX) {
if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
- pa_proplist_free(p);
- return;
+ goto finish;
}
} else if (source_name) {
if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
- pa_proplist_free(p);
- return;
+ goto finish;
}
}
@@ -2334,8 +2369,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
- pa_proplist_free(p);
- return;
+ goto finish;
}
}
@@ -2349,12 +2383,12 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
(no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
(variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
(dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
- (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0);
+ (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0) |
+ (passthrough ? PA_SOURCE_OUTPUT_PASSTHROUGH : 0);
- s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
- pa_proplist_free(p);
+ s = record_stream_new(c, source, &ss, &map, formats, &attr, flags, p, adjust_latency, early_requests, peak_detect, direct_on_input, &ret);
- CHECK_VALIDITY(c->pstream, s, tag, ret);
+ CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
@@ -2385,7 +2419,24 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (c->version >= 13)
pa_tagstruct_put_usec(reply, s->configured_source_latency);
+ if (c->version >= 22) {
+ /* Send back the format we negotiated */
+ if (s->source_output->format)
+ pa_tagstruct_put_format_info(reply, s->source_output->format);
+ else {
+ pa_format_info *f = pa_format_info_new();
+ pa_tagstruct_put_format_info(reply, f);
+ pa_format_info_free(f);
+ }
+ }
+
pa_pstream_send_tagstruct(c->pstream, reply);
+
+finish:
+ if (p)
+ pa_proplist_free(p);
+ if (formats)
+ pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
}
static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {