diff --git a/src/modules/module-protocol-pulse/module.c b/src/modules/module-protocol-pulse/module.c index 70afff66a..7601f38b8 100644 --- a/src/modules/module-protocol-pulse/module.c +++ b/src/modules/module-protocol-pulse/module.c @@ -163,41 +163,48 @@ void module_args_add_props(struct pw_properties *props, const char *str) free(s); } -int module_args_to_audioinfo(struct impl *impl, struct pw_properties *props, struct spa_audio_info_raw *info) +int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props, + const char *key_format, const char *key_rate, + const char *key_channels, const char *key_channel_map, + struct spa_audio_info_raw *info) { const char *str; uint32_t i; - /* We don't use any incoming format setting and use our native format */ - spa_zero(*info); - info->flags = SPA_AUDIO_FLAG_UNPOSITIONED; - info->format = SPA_AUDIO_FORMAT_F32P; - - if ((str = pw_properties_get(props, "channels")) != NULL) { - info->channels = pw_properties_parse_int(str); - if (info->channels == 0 || info->channels > SPA_AUDIO_MAX_CHANNELS) { - pw_log_error("invalid channels '%s'", str); + if (key_format && (str = pw_properties_get(props, key_format)) != NULL) { + info->format = format_paname2id(str, strlen(str)); + if (info->format == SPA_AUDIO_FORMAT_UNKNOWN) { + pw_log_error("invalid %s '%s'", key_format, str); return -EINVAL; } - pw_properties_set(props, "channels", NULL); + pw_properties_set(props, key_format, NULL); } - if ((str = pw_properties_get(props, "channel_map")) != NULL) { + if (key_channels && (str = pw_properties_get(props, key_channels)) != NULL) { + info->channels = pw_properties_parse_int(str); + if (info->channels == 0 || info->channels > SPA_AUDIO_MAX_CHANNELS) { + pw_log_error("invalid %s '%s'", key_channels, str); + return -EINVAL; + } + pw_properties_set(props, key_channels, NULL); + } + if (key_channel_map && (str = pw_properties_get(props, key_channel_map)) != NULL) { struct channel_map map; channel_map_parse(str, &map); if (map.channels == 0 || map.channels > SPA_AUDIO_MAX_CHANNELS) { - pw_log_error("invalid channel_map '%s'", str); + pw_log_error("invalid %s '%s'", key_channel_map, str); return -EINVAL; } if (info->channels == 0) info->channels = map.channels; if (info->channels != map.channels) { - pw_log_error("Mismatched channel map"); + pw_log_error("Mismatched %s and %s (%d vs %d)", + key_channels, key_channel_map, + info->channels, map.channels); return -EINVAL; } channel_map_to_positions(&map, info->position); - info->flags &= ~SPA_AUDIO_FLAG_UNPOSITIONED; - pw_properties_set(props, "channel_map", NULL); + pw_properties_set(props, key_channel_map, NULL); } else { if (info->channels == 0) info->channels = impl->defs.sample_spec.channels; @@ -214,19 +221,25 @@ int module_args_to_audioinfo(struct impl *impl, struct pw_properties *props, str for (i = 0; i < info->channels; i++) info->position[i] = SPA_AUDIO_CHANNEL_UNKNOWN; } - if (info->position[0] != SPA_AUDIO_CHANNEL_UNKNOWN) - info->flags &= ~SPA_AUDIO_FLAG_UNPOSITIONED; + if (info->position[0] == SPA_AUDIO_CHANNEL_UNKNOWN) + info->flags |= SPA_AUDIO_FLAG_UNPOSITIONED; } - - if ((str = pw_properties_get(props, "rate")) != NULL) { + if (key_rate && (str = pw_properties_get(props, key_rate)) != NULL) { info->rate = pw_properties_parse_int(str); - pw_properties_set(props, "rate", NULL); - } else { - info->rate = 0; + pw_properties_set(props, key_rate, NULL); } return 0; } +int module_args_to_audioinfo(struct impl *impl, struct pw_properties *props, struct spa_audio_info_raw *info) +{ + /* We don't use any incoming format setting and use our native format */ + spa_zero(*info); + info->format = SPA_AUDIO_FORMAT_F32P; + return module_args_to_audioinfo_keys(impl, props, + NULL, "rate", "channels", "channel_map", info); +} + bool module_args_parse_bool(const char *v) { if (spa_streq(v, "1") || !strcasecmp(v, "y") || !strcasecmp(v, "t") || @@ -235,6 +248,28 @@ bool module_args_parse_bool(const char *v) return false; } +void audioinfo_to_properties(struct spa_audio_info_raw *info, struct pw_properties *props) +{ + uint32_t i; + + if (info->format) + pw_properties_setf(props, SPA_KEY_AUDIO_FORMAT, "%s", + format_id2name(info->format)); + if (info->rate) + pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info->rate); + if (info->channels) { + char *s, *p; + + pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); + + p = s = alloca(info->channels * 8); + for (i = 0; i < info->channels; i++) + p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", + channel_id2name(info->position[i])); + pw_properties_setf(props, SPA_KEY_AUDIO_POSITION, "[ %s ]", s); + } +} + static const struct module_info *find_module_info(const char *name) { extern const struct module_info __start_pw_mod_pulse_modules[]; diff --git a/src/modules/module-protocol-pulse/module.h b/src/modules/module-protocol-pulse/module.h index bfb745057..20ad90faf 100644 --- a/src/modules/module-protocol-pulse/module.h +++ b/src/modules/module-protocol-pulse/module.h @@ -70,5 +70,12 @@ void module_add_listener(struct module *module, void module_args_add_props(struct pw_properties *props, const char *str); int module_args_to_audioinfo(struct impl *impl, struct pw_properties *props, struct spa_audio_info_raw *info); bool module_args_parse_bool(const char *str); +int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props, + const char *key_format, const char *key_rate, + const char *key_channels, const char *key_channel_map, + struct spa_audio_info_raw *info); + +void audioinfo_to_properties(struct spa_audio_info_raw *info, struct pw_properties *props); + #endif diff --git a/src/modules/module-protocol-pulse/modules/module-combine-sink.c b/src/modules/module-protocol-pulse/modules/module-combine-sink.c index 136dc36ba..82a8c2266 100644 --- a/src/modules/module-protocol-pulse/modules/module-combine-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-combine-sink.c @@ -49,17 +49,16 @@ struct module_combine_sink_data { struct pw_impl_module *mod; struct spa_hook mod_listener; - char *sink_name; char **sink_names; + struct pw_properties *props; struct pw_properties *combine_props; + struct pw_properties *stream_props; struct spa_source *sinks_timeout; struct spa_audio_info_raw info; unsigned int sinks_pending; - unsigned int remix:1; - unsigned int latency_compensate:1; unsigned int load_emitted:1; unsigned int start_error:1; }; @@ -150,33 +149,20 @@ static int module_combine_sink_load(struct module *module) if (data->core == NULL) return -errno; + pw_properties_setf(data->combine_props, "pulse.module.id", "%u", + module->index); + pw_properties_setf(data->stream_props, "pulse.module.id", "%u", + module->index); + if ((f = open_memstream(&args, &size)) == NULL) return -errno; fprintf(f, "{"); - fprintf(f, " node.name = %s", data->sink_name); - fprintf(f, " node.description = %s", data->sink_name); - if (data->latency_compensate) - fprintf(f, " combine.latency-compensate = true"); - if (data->info.rate != 0) - fprintf(f, " audio.rate = %u", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " audio.channels = %u", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " audio.position = [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s%s", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ]"); - } - } + pw_properties_serialize_dict(f, &data->props->dict, 0); fprintf(f, " combine.props = {"); - fprintf(f, " pulse.module.id = %u", module->index); pw_properties_serialize_dict(f, &data->combine_props->dict, 0); fprintf(f, " } stream.props = {"); - if (!data->remix) - fprintf(f, " "PW_KEY_STREAM_DONT_REMIX" = true"); - fprintf(f, " pulse.module.id = %u", module->index); + pw_properties_serialize_dict(f, &data->stream_props->dict, 0); fprintf(f, " } stream.rules = ["); if (data->sink_names == NULL) { fprintf(f, " { matches = [ { media.class = \"Audio/Sink\" } ]"); @@ -244,8 +230,9 @@ static int module_combine_sink_unload(struct module *module) pw_core_disconnect(d->core); } pw_free_strv(d->sink_names); - free(d->sink_name); + pw_properties_free(d->stream_props); pw_properties_free(d->combine_props); + pw_properties_free(d->props); return 0; } @@ -253,39 +240,51 @@ static int module_combine_sink_prepare(struct module * const module) { struct module_combine_sink_data * const d = module->user_data; struct pw_properties * const props = module->props; - struct pw_properties *combine_props = NULL; + struct pw_properties *combine_props = NULL, *global_props = NULL, *stream_props = NULL; const char *str; - char *sink_name = NULL, **sink_names = NULL; + char **sink_names = NULL; struct spa_audio_info_raw info = { 0 }; int res; int num_sinks = 0; PW_LOG_TOPIC_INIT(mod_topic); + global_props = pw_properties_new(NULL, NULL); combine_props = pw_properties_new(NULL, NULL); - - if ((str = pw_properties_get(props, "sink_name")) != NULL) { - sink_name = strdup(str); - pw_properties_set(props, "sink_name", NULL); - } else { - sink_name = strdup("combined"); + stream_props = pw_properties_new(NULL, NULL); + if (global_props == NULL || combine_props == NULL || stream_props == NULL) { + res = -ENOMEM; + goto out; } - if ((str = pw_properties_get(module->props, "sink_properties")) != NULL) + if ((str = pw_properties_get(props, "sink_name")) != NULL) { + pw_properties_set(global_props, PW_KEY_NODE_NAME, str); + pw_properties_set(global_props, PW_KEY_NODE_DESCRIPTION, str); + pw_properties_set(props, "sink_name", NULL); + } else { + str = "combined"; + pw_properties_set(global_props, PW_KEY_NODE_NAME, str); + pw_properties_set(global_props, PW_KEY_NODE_DESCRIPTION, str); + } + + if ((str = pw_properties_get(props, "sink_properties")) != NULL) module_args_add_props(combine_props, str); if ((str = pw_properties_get(props, "slaves")) != NULL) { sink_names = pw_split_strv(str, ",", MAX_SINKS, &num_sinks); pw_properties_set(props, "slaves", NULL); } - d->remix = true; if ((str = pw_properties_get(props, "remix")) != NULL) { - d->remix = pw_properties_parse_bool(str); + pw_properties_set(stream_props, PW_KEY_STREAM_DONT_REMIX, + module_args_parse_bool(str) ? "false" : "true"); pw_properties_set(props, "remix", NULL); } - if ((str = pw_properties_get(props, "latency_compensate")) != NULL) - d->latency_compensate = pw_properties_parse_bool(str); + if ((str = pw_properties_get(props, "latency_compensate")) != NULL) { + pw_properties_set(global_props, "combine.latency-compensate", + module_args_parse_bool(str) ? "true" : "false"); + pw_properties_set(props, "latency_compensate", NULL); + } if ((str = pw_properties_get(props, "adjust_time")) != NULL) { pw_log_info("The `adjust_time` modarg is ignored"); @@ -297,23 +296,27 @@ static int module_combine_sink_prepare(struct module * const module) pw_properties_set(props, "resample_method", NULL); } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, "rate", "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, global_props); d->module = module; d->info = info; - d->sink_name = sink_name; d->sink_names = sink_names; d->sinks_pending = (sink_names == NULL) ? 0 : num_sinks; + d->stream_props = stream_props; d->combine_props = combine_props; + d->props = global_props; return 0; out: - free(sink_name); pw_free_strv(sink_names); + pw_properties_free(stream_props); pw_properties_free(combine_props); + pw_properties_free(global_props); return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-echo-cancel.c b/src/modules/module-protocol-pulse/modules/module-echo-cancel.c index 2341cdd60..a6b5966cb 100644 --- a/src/modules/module-protocol-pulse/modules/module-echo-cancel.c +++ b/src/modules/module-protocol-pulse/modules/module-echo-cancel.c @@ -22,6 +22,7 @@ struct module_echo_cancel_data { struct pw_impl_module *mod; struct spa_hook mod_listener; + struct pw_properties *global_props; struct pw_properties *props; struct pw_properties *capture_props; struct pw_properties *source_props; @@ -58,26 +59,10 @@ static int module_echo_cancel_load(struct module *module) return -errno; fprintf(f, "{"); - if ((method = pw_properties_get(props, "aec_method")) == NULL) - method = "webrtc"; - - fprintf(f, " library.name = \"aec/libspa-aec-%s\"", method); - + pw_properties_serialize_dict(f, &data->global_props->dict, 0); fprintf(f, " aec.args = {"); pw_properties_serialize_dict(f, &data->props->dict, 0); fprintf(f, " }"); - if (data->info.rate != 0) - fprintf(f, " audio.rate = %u", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " audio.channels = %u", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " audio.position = [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s%s", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ]"); - } - } fprintf(f, " capture.props = {"); pw_properties_serialize_dict(f, &data->capture_props->dict, 0); fprintf(f, " } source.props = {"); @@ -114,6 +99,7 @@ static int module_echo_cancel_unload(struct module *module) d->mod = NULL; } + pw_properties_free(d->global_props); pw_properties_free(d->props); pw_properties_free(d->capture_props); pw_properties_free(d->source_props); @@ -231,22 +217,28 @@ static int module_echo_cancel_prepare(struct module * const module) struct pw_properties * const props = module->props; struct pw_properties *aec_props = NULL, *sink_props = NULL, *source_props = NULL; struct pw_properties *playback_props = NULL, *capture_props = NULL; + struct pw_properties *global_props = NULL; const char *str, *method; struct spa_audio_info_raw info = { 0 }; int res; PW_LOG_TOPIC_INIT(mod_topic); + global_props = pw_properties_new(NULL, NULL); aec_props = pw_properties_new(NULL, NULL); capture_props = pw_properties_new(NULL, NULL); source_props = pw_properties_new(NULL, NULL); sink_props = pw_properties_new(NULL, NULL); playback_props = pw_properties_new(NULL, NULL); - if (!aec_props || !source_props || !sink_props || !capture_props || !playback_props) { + if (!global_props || !aec_props || !source_props || !sink_props || !capture_props || !playback_props) { res = -EINVAL; goto out; } + if ((str = pw_properties_get(props, "aec_method")) == NULL) + str = "webrtc"; + pw_properties_setf(global_props, "library.name", "aec/libspa-aec-%s", str); + if ((str = pw_properties_get(props, "source_name")) != NULL) { pw_properties_set(source_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "source_name", NULL); @@ -282,6 +274,7 @@ static int module_echo_cancel_prepare(struct module * const module) res = -EINVAL; goto out; } + audioinfo_to_properties(&info, global_props); if ((str = pw_properties_get(props, "source_properties")) != NULL) { module_args_add_props(source_props, str); @@ -314,6 +307,7 @@ static int module_echo_cancel_prepare(struct module * const module) } d->module = module; + d->global_props = global_props; d->props = aec_props; d->capture_props = capture_props; d->source_props = source_props; @@ -323,6 +317,7 @@ static int module_echo_cancel_prepare(struct module * const module) return 0; out: + pw_properties_free(global_props); pw_properties_free(aec_props); pw_properties_free(playback_props); pw_properties_free(sink_props); diff --git a/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c b/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c index 99227524c..5dd26567b 100644 --- a/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c @@ -144,19 +144,6 @@ static const struct spa_dict_item module_ladspa_sink_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void position_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_ladspa_sink_prepare(struct module * const module) { struct module_ladspa_sink_data * const d = module->user_data; @@ -203,14 +190,15 @@ static int module_ladspa_sink_prepare(struct module * const module) pw_properties_set(props, "master", NULL); } - if (module_args_to_audioinfo(module->impl, props, &capture_info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &capture_info) < 0) { res = -EINVAL; goto out; } playback_info = capture_info; - position_to_props(&capture_info, capture_props); - position_to_props(&playback_info, playback_props); + audioinfo_to_properties(&capture_info, capture_props); + audioinfo_to_properties(&playback_info, playback_props); if (pw_properties_get(playback_props, PW_KEY_NODE_PASSIVE) == NULL) pw_properties_set(playback_props, PW_KEY_NODE_PASSIVE, "true"); diff --git a/src/modules/module-protocol-pulse/modules/module-ladspa-source.c b/src/modules/module-protocol-pulse/modules/module-ladspa-source.c index 2a0040066..2e876ae4c 100644 --- a/src/modules/module-protocol-pulse/modules/module-ladspa-source.c +++ b/src/modules/module-protocol-pulse/modules/module-ladspa-source.c @@ -144,19 +144,6 @@ static const struct spa_dict_item module_ladspa_source_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void position_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_ladspa_source_prepare(struct module * const module) { struct module_ladspa_source_data * const d = module->user_data; @@ -211,14 +198,15 @@ static int module_ladspa_source_prepare(struct module * const module) pw_properties_set(props, "master", NULL); } - if (module_args_to_audioinfo(module->impl, props, &playback_info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &playback_info) < 0) { res = -EINVAL; goto out; } capture_info = playback_info; - position_to_props(&capture_info, capture_props); - position_to_props(&playback_info, playback_props); + audioinfo_to_properties(&capture_info, capture_props); + audioinfo_to_properties(&playback_info, playback_props); if (pw_properties_get(capture_props, PW_KEY_NODE_PASSIVE) == NULL) pw_properties_set(capture_props, PW_KEY_NODE_PASSIVE, "true"); diff --git a/src/modules/module-protocol-pulse/modules/module-loopback.c b/src/modules/module-protocol-pulse/modules/module-loopback.c index 60ff42487..d1285d309 100644 --- a/src/modules/module-protocol-pulse/modules/module-loopback.c +++ b/src/modules/module-protocol-pulse/modules/module-loopback.c @@ -22,11 +22,9 @@ struct module_loopback_data { struct pw_impl_module *mod; struct spa_hook mod_listener; + struct pw_properties *global_props; struct pw_properties *capture_props; struct pw_properties *playback_props; - - struct spa_audio_info_raw info; - uint32_t latency_msec; }; static void module_destroy(void *data) @@ -48,7 +46,6 @@ static int module_loopback_load(struct module *module) FILE *f; char *args; size_t size, i; - char val[256]; pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); @@ -59,20 +56,7 @@ static int module_loopback_load(struct module *module) return -errno; fprintf(f, "{"); - if (data->info.channels != 0) { - fprintf(f, " audio.channels = %u", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " audio.position = [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s%s", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ]"); - } - } - if (data->latency_msec != 0) - fprintf(f, " target.delay.sec = %s", - spa_json_format_float(val, sizeof(val), - data->latency_msec / 1000.0f)); + pw_properties_serialize_dict(f, &data->global_props->dict, 0); fprintf(f, " capture.props = {"); pw_properties_serialize_dict(f, &data->capture_props->dict, 0); fprintf(f, " } playback.props = {"); @@ -107,6 +91,7 @@ static int module_loopback_unload(struct module *module) pw_properties_free(d->capture_props); pw_properties_free(d->playback_props); + pw_properties_free(d->global_props); return 0; } @@ -132,16 +117,17 @@ static int module_loopback_prepare(struct module * const module) { struct module_loopback_data * const d = module->user_data; struct pw_properties * const props = module->props; - struct pw_properties *playback_props = NULL, *capture_props = NULL; + struct pw_properties *global_props = NULL, *playback_props = NULL, *capture_props = NULL; const char *str; struct spa_audio_info_raw info = { 0 }; int res; PW_LOG_TOPIC_INIT(mod_topic); + global_props = pw_properties_new(NULL, NULL); capture_props = pw_properties_new(NULL, NULL); playback_props = pw_properties_new(NULL, NULL); - if (!capture_props || !playback_props) { + if (!global_props || !capture_props || !playback_props) { res = -EINVAL; goto out; } @@ -167,10 +153,12 @@ static int module_loopback_prepare(struct module * const module) pw_properties_set(props, "sink", NULL); } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, global_props); if ((str = pw_properties_get(props, "source_dont_move")) != NULL) { pw_properties_set(capture_props, PW_KEY_NODE_DONT_RECONNECT, str); @@ -189,8 +177,13 @@ static int module_loopback_prepare(struct module * const module) pw_properties_set(props, "remix", NULL); } - if ((str = pw_properties_get(props, "latency_msec")) != NULL) - d->latency_msec = atoi(str); + if ((str = pw_properties_get(props, "latency_msec")) != NULL) { + uint32_t latency_msec = atoi(str); + char val[256]; + pw_properties_setf(global_props, "target.delay.sec", + "%s", spa_json_format_float(val, sizeof(val), + latency_msec / 1000.0f)); + } if ((str = pw_properties_get(props, "sink_input_properties")) != NULL) { module_args_add_props(playback_props, str); @@ -203,12 +196,13 @@ static int module_loopback_prepare(struct module * const module) } d->module = module; + d->global_props = global_props; d->capture_props = capture_props; d->playback_props = playback_props; - d->info = info; return 0; out: + pw_properties_free(global_props); pw_properties_free(playback_props); pw_properties_free(capture_props); diff --git a/src/modules/module-protocol-pulse/modules/module-null-sink.c b/src/modules/module-protocol-pulse/modules/module-null-sink.c index 5af46aac6..15e679d38 100644 --- a/src/modules/module-protocol-pulse/modules/module-null-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-null-sink.c @@ -160,35 +160,11 @@ static int module_null_sink_prepare(struct module * const module) pw_properties_set(props, "sink_properties", NULL); } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) return -EINVAL; - info.format = module->impl->defs.sample_spec.format; - if ((str = pw_properties_get(props, "format")) != NULL) { - info.format = format_paname2id(str, strlen(str)); - if (info.format == SPA_AUDIO_FORMAT_UNKNOWN) { - pw_log_error("invalid format '%s'", str); - return -EINVAL; - } - pw_properties_set(props, "format", NULL); - } - - if (info.format) - pw_properties_setf(props, SPA_KEY_AUDIO_FORMAT, "%s", - format_id2name(info.format)); - if (info.rate) - pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info.rate); - if (info.channels) { - char *s, *p; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info.channels); - - p = s = alloca(info.channels * 8); - for (i = 0; i < info.channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info.position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); - } + audioinfo_to_properties(&info, props); if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); diff --git a/src/modules/module-protocol-pulse/modules/module-pipe-sink.c b/src/modules/module-protocol-pulse/modules/module-pipe-sink.c index beb7462c3..80f2fb40f 100644 --- a/src/modules/module-protocol-pulse/modules/module-pipe-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-pipe-sink.c @@ -25,9 +25,8 @@ struct module_pipesink_data { struct spa_hook mod_listener; struct pw_impl_module *mod; + struct pw_properties *global_props; struct pw_properties *capture_props; - struct spa_audio_info_raw info; - char *filename; }; static void module_destroy(void *data) @@ -49,7 +48,6 @@ static int module_pipe_sink_load(struct module *module) FILE *f; char *args; size_t size; - uint32_t i; pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); @@ -58,23 +56,7 @@ static int module_pipe_sink_load(struct module *module) return -errno; fprintf(f, "{"); - fprintf(f, " \"tunnel.mode\" = \"sink\" "); - if (data->filename != NULL) - fprintf(f, " \"pipe.filename\": \"%s\"", data->filename); - if (data->info.format != 0) - fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format)); - if (data->info.rate != 0) - fprintf(f, " \"audio.rate\": %u,", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " \"audio.channels\": %u,", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " \"audio.position\": [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s\"%s\"", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ],"); - } - } + pw_properties_serialize_dict(f, &data->global_props->dict, 0); fprintf(f, " \"stream.props\": {"); pw_properties_serialize_dict(f, &data->capture_props->dict, 0); fprintf(f, " } }"); @@ -105,7 +87,7 @@ static int module_pipe_sink_unload(struct module *module) d->mod = NULL; } pw_properties_free(d->capture_props); - free(d->filename); + pw_properties_free(d->global_props); return 0; } @@ -126,35 +108,30 @@ static int module_pipe_sink_prepare(struct module * const module) { struct module_pipesink_data * const d = module->user_data; struct pw_properties * const props = module->props; - struct pw_properties *capture_props = NULL; + struct pw_properties *global_props = NULL, *capture_props = NULL; struct spa_audio_info_raw info = { 0 }; const char *str; - char *filename = NULL; int res = 0; PW_LOG_TOPIC_INIT(mod_topic); + global_props = pw_properties_new(NULL, NULL); capture_props = pw_properties_new(NULL, NULL); - if (!capture_props) { + if (!global_props || !capture_props) { res = -EINVAL; goto out; } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { - res = -EINVAL; - goto out; - } + pw_properties_set(global_props, "tunnel.mode", "sink"); info.format = SPA_AUDIO_FORMAT_S16; - if ((str = pw_properties_get(props, "format")) != NULL) { - info.format = format_paname2id(str, strlen(str)); - if (info.format == SPA_AUDIO_FORMAT_UNKNOWN) { - pw_log_error("invalid format '%s'", str); - res = -EINVAL; - goto out; - } - pw_properties_set(props, "format", NULL); + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) { + res = -EINVAL; + goto out; } + audioinfo_to_properties(&info, global_props); + if ((str = pw_properties_get(props, "sink_name")) != NULL) { pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "sink_name", NULL); @@ -163,7 +140,7 @@ static int module_pipe_sink_prepare(struct module * const module) module_args_add_props(capture_props, str); if ((str = pw_properties_get(props, "file")) != NULL) { - filename = strdup(str); + pw_properties_set(global_props, "pipe.filename", str); pw_properties_set(props, "file", NULL); } if ((str = pw_properties_get(capture_props, PW_KEY_DEVICE_ICON_NAME)) == NULL) @@ -174,14 +151,13 @@ static int module_pipe_sink_prepare(struct module * const module) "fifo_output"); d->module = module; + d->global_props = global_props; d->capture_props = capture_props; - d->info = info; - d->filename = filename; return 0; out: + pw_properties_free(global_props); pw_properties_free(capture_props); - free(filename); return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-pipe-source.c b/src/modules/module-protocol-pulse/modules/module-pipe-source.c index be3bbfd84..0769e1199 100644 --- a/src/modules/module-protocol-pulse/modules/module-pipe-source.c +++ b/src/modules/module-protocol-pulse/modules/module-pipe-source.c @@ -25,9 +25,8 @@ struct module_pipesrc_data { struct spa_hook mod_listener; struct pw_impl_module *mod; + struct pw_properties *global_props; struct pw_properties *playback_props; - struct spa_audio_info_raw info; - char *filename; }; static void module_destroy(void *data) @@ -49,7 +48,6 @@ static int module_pipe_source_load(struct module *module) FILE *f; char *args; size_t size; - uint32_t i; pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); @@ -58,23 +56,7 @@ static int module_pipe_source_load(struct module *module) return -errno; fprintf(f, "{"); - fprintf(f, " \"tunnel.mode\" = \"source\" "); - if (data->filename != NULL) - fprintf(f, " \"pipe.filename\": \"%s\"", data->filename); - if (data->info.format != 0) - fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format)); - if (data->info.rate != 0) - fprintf(f, " \"audio.rate\": %u,", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " \"audio.channels\": %u,", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " \"audio.position\": [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s\"%s\"", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ],"); - } - } + pw_properties_serialize_dict(f, &data->global_props->dict, 0); fprintf(f, " \"stream.props\": {"); pw_properties_serialize_dict(f, &data->playback_props->dict, 0); fprintf(f, " } }"); @@ -105,7 +87,7 @@ static int module_pipe_source_unload(struct module *module) d->mod = NULL; } pw_properties_free(d->playback_props); - free(d->filename); + pw_properties_free(d->global_props); return 0; } @@ -126,35 +108,30 @@ static int module_pipe_source_prepare(struct module * const module) { struct module_pipesrc_data * const d = module->user_data; struct pw_properties * const props = module->props; - struct pw_properties *playback_props = NULL; + struct pw_properties *global_props = NULL, *playback_props = NULL; struct spa_audio_info_raw info = { 0 }; const char *str; - char *filename = NULL; int res = 0; PW_LOG_TOPIC_INIT(mod_topic); + global_props = pw_properties_new(NULL, NULL); playback_props = pw_properties_new(NULL, NULL); - if (!playback_props) { + if (!global_props || !playback_props) { res = -errno; goto out; } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + pw_properties_set(global_props, "tunnel.mode", "source"); + + info.format = SPA_AUDIO_FORMAT_S16; + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, global_props); - info.format = SPA_AUDIO_FORMAT_S16; - if ((str = pw_properties_get(props, "format")) != NULL) { - info.format = format_paname2id(str, strlen(str)); - if (info.format == SPA_AUDIO_FORMAT_UNKNOWN) { - pw_log_error("invalid format '%s'", str); - res = -EINVAL; - goto out; - } - pw_properties_set(props, "format", NULL); - } if ((str = pw_properties_get(props, "source_name")) != NULL) { pw_properties_set(playback_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "source_name", NULL); @@ -163,7 +140,7 @@ static int module_pipe_source_prepare(struct module * const module) module_args_add_props(playback_props, str); if ((str = pw_properties_get(props, "file")) != NULL) { - filename = strdup(str); + pw_properties_set(global_props, "pipe.filename", str); pw_properties_set(props, "file", NULL); } if ((str = pw_properties_get(playback_props, PW_KEY_DEVICE_ICON_NAME)) == NULL) @@ -175,13 +152,12 @@ static int module_pipe_source_prepare(struct module * const module) d->module = module; d->playback_props = playback_props; - d->info = info; - d->filename = filename; + d->global_props = global_props; return 0; out: + pw_properties_free(global_props); pw_properties_free(playback_props); - free(filename); return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-remap-sink.c b/src/modules/module-protocol-pulse/modules/module-remap-sink.c index 8b509fa4a..1f40c6520 100644 --- a/src/modules/module-protocol-pulse/modules/module-remap-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-remap-sink.c @@ -109,19 +109,6 @@ static const struct spa_dict_item module_remap_sink_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void position_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_remap_sink_prepare(struct module * const module) { struct module_remap_sink_data * const d = module->user_data; @@ -180,26 +167,19 @@ static int module_remap_sink_prepare(struct module * const module) pw_properties_set(props, "master", NULL); } - if (module_args_to_audioinfo(module->impl, props, &capture_info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &capture_info) < 0) { res = -EINVAL; goto out; } playback_info = capture_info; - - if ((str = pw_properties_get(props, "master_channel_map")) != NULL) { - struct channel_map map; - - channel_map_parse(str, &map); - if (map.channels == 0 || map.channels > SPA_AUDIO_MAX_CHANNELS) { - pw_log_error("invalid channel_map '%s'", str); - res = -EINVAL; - goto out; - } - channel_map_to_positions(&map, playback_info.position); - pw_properties_set(props, "master_channel_map", NULL); + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, NULL, "master_channel_map", &playback_info) < 0) { + res = -EINVAL; + goto out; } - position_to_props(&capture_info, capture_props); - position_to_props(&playback_info, playback_props); + audioinfo_to_properties(&capture_info, capture_props); + audioinfo_to_properties(&playback_info, playback_props); if ((str = pw_properties_get(props, "remix")) != NULL) { /* Note that the boolean is inverted */ @@ -219,7 +199,6 @@ static int module_remap_sink_prepare(struct module * const module) out: pw_properties_free(playback_props); pw_properties_free(capture_props); - return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-remap-source.c b/src/modules/module-protocol-pulse/modules/module-remap-source.c index 0778c5f1a..6e806d1b6 100644 --- a/src/modules/module-protocol-pulse/modules/module-remap-source.c +++ b/src/modules/module-protocol-pulse/modules/module-remap-source.c @@ -109,19 +109,6 @@ static const struct spa_dict_item module_remap_source_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void position_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_remap_source_prepare(struct module * const module) { struct module_remap_source_data * const d = module->user_data; @@ -187,26 +174,19 @@ static int module_remap_source_prepare(struct module * const module) pw_properties_set(props, "master", NULL); } - if (module_args_to_audioinfo(module->impl, props, &playback_info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &playback_info) < 0) { res = -EINVAL; goto out; } capture_info = playback_info; - - if ((str = pw_properties_get(props, "master_channel_map")) != NULL) { - struct channel_map map; - - channel_map_parse(str, &map); - if (map.channels == 0 || map.channels > SPA_AUDIO_MAX_CHANNELS) { - pw_log_error("invalid channel_map '%s'", str); - res = -EINVAL; - goto out; - } - channel_map_to_positions(&map, capture_info.position); - pw_properties_set(props, "master_channel_map", NULL); + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, NULL, "master_channel_map", &capture_info) < 0) { + res = -EINVAL; + goto out; } - position_to_props(&playback_info, playback_props); - position_to_props(&capture_info, capture_props); + audioinfo_to_properties(&playback_info, playback_props); + audioinfo_to_properties(&capture_info, capture_props); if ((str = pw_properties_get(props, "remix")) != NULL) { /* Note that the boolean is inverted */ @@ -226,7 +206,6 @@ static int module_remap_source_prepare(struct module * const module) out: pw_properties_free(playback_props); pw_properties_free(capture_props); - return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-rtp-send.c b/src/modules/module-protocol-pulse/modules/module-rtp-send.c index fad626304..5479f0857 100644 --- a/src/modules/module-protocol-pulse/modules/module-rtp-send.c +++ b/src/modules/module-protocol-pulse/modules/module-rtp-send.c @@ -25,8 +25,6 @@ struct module_rtp_send_data { struct pw_properties *stream_props; struct pw_properties *global_props; struct pw_properties *sap_props; - - struct spa_audio_info_raw info; }; static void module_destroy(void *data) @@ -71,20 +69,6 @@ static int module_rtp_send_load(struct module *module) fprintf(f, "{"); pw_properties_serialize_dict(f, &data->global_props->dict, 0); - if (data->info.format != 0) - fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format)); - if (data->info.rate != 0) - fprintf(f, " \"audio.rate\": %u,", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " \"audio.channels\": %u,", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " \"audio.position\": [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s\"%s\"", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ],"); - } - } fprintf(f, " stream.props = {"); pw_properties_serialize_dict(f, &data->stream_props->dict, 0); fprintf(f, " } }"); @@ -198,19 +182,13 @@ static int module_rtp_send_prepare(struct module * const module) pw_properties_set(stream_props, PW_KEY_TARGET_OBJECT, str); } } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } - info.format = 0; - if ((str = pw_properties_get(props, "format")) != NULL) { - if ((info.format = format_paname2id(str, strlen(str))) == - SPA_AUDIO_FORMAT_UNKNOWN) { - pw_log_error("unknown format %s", str); - res = -EINVAL; - goto out; - } - } + audioinfo_to_properties(&info, global_props); pw_properties_set(global_props, "sess.media", "audio"); if ((str = pw_properties_get(props, "enable_opus")) != NULL) { @@ -245,7 +223,6 @@ static int module_rtp_send_prepare(struct module * const module) d->stream_props = stream_props; d->global_props = global_props; d->sap_props = sap_props; - d->info = info; return 0; out: diff --git a/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c b/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c index 247159d81..d0479a788 100644 --- a/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c +++ b/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c @@ -44,25 +44,12 @@ static int module_simple_protocol_tcp_load(struct module *module) struct impl *impl = module->impl; char *args; size_t size; - uint32_t i; FILE *f; if ((f = open_memstream(&args, &size)) == NULL) return -errno; fprintf(f, "{"); - if (data->info.rate != 0) - fprintf(f, " \"audio.rate\": %u,", data->info.rate); - if (data->info.channels != 0) { - fprintf(f, " \"audio.channels\": %u,", data->info.channels); - if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { - fprintf(f, " \"audio.position\": [ "); - for (i = 0; i < data->info.channels; i++) - fprintf(f, "%s\"%s\"", i == 0 ? "" : ",", - channel_id2name(data->info.position[i])); - fprintf(f, " ],"); - } - } pw_properties_serialize_dict(f, &data->module_props->dict, 0); fprintf(f, "}"); fclose(f); @@ -127,15 +114,13 @@ static int module_simple_protocol_tcp_prepare(struct module * const module) goto out; } - if ((str = pw_properties_get(props, "format")) != NULL) { - pw_properties_set(module_props, "audio.format", - format_id2name(format_paname2id(str, strlen(str)))); - pw_properties_set(props, "format", NULL); - } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, module_props); + if ((str = pw_properties_get(props, "playback")) != NULL) { pw_properties_set(module_props, "playback", str); pw_properties_set(props, "playback", NULL); diff --git a/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c b/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c index b3f63f61b..758f71c2c 100644 --- a/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c @@ -23,8 +23,6 @@ struct module_tunnel_sink_data { struct pw_impl_module *mod; struct spa_hook mod_listener; - uint32_t latency_msec; - struct pw_properties *stream_props; }; @@ -47,9 +45,6 @@ static int module_tunnel_sink_load(struct module *module) FILE *f; char *args; size_t size; - const char *server; - - server = pw_properties_get(module->props, "server"); pw_properties_setf(data->stream_props, "pulse.module.id", "%u", module->index); @@ -59,10 +54,6 @@ static int module_tunnel_sink_load(struct module *module) fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); - fprintf(f, " pulse.server.address = \"%s\" ", server); - fprintf(f, " tunnel.mode = sink "); - if (data->latency_msec > 0) - fprintf(f, " pulse.latency = %u ", data->latency_msec); fprintf(f, " stream.props = {"); pw_properties_serialize_dict(f, &data->stream_props->dict, 0); fprintf(f, " } }"); @@ -115,19 +106,6 @@ static const struct spa_dict_item module_tunnel_sink_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void audio_info_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_tunnel_sink_prepare(struct module * const module) { struct module_tunnel_sink_data * const d = module->user_data; @@ -145,6 +123,8 @@ static int module_tunnel_sink_prepare(struct module * const module) goto out; } + pw_properties_set(props, "tunnel.mode", "sink"); + remote_sink_name = pw_properties_get(props, "sink"); if (remote_sink_name) pw_properties_set(props, PW_KEY_TARGET_OBJECT, remote_sink_name); @@ -153,6 +133,8 @@ static int module_tunnel_sink_prepare(struct module * const module) pw_log_error("no server given"); res = -EINVAL; goto out; + } else { + pw_properties_set(props, "pulse.server.address", server); } pw_properties_setf(stream_props, PW_KEY_NODE_DESCRIPTION, @@ -167,36 +149,30 @@ static int module_tunnel_sink_prepare(struct module * const module) pw_properties_setf(stream_props, PW_KEY_NODE_NAME, "tunnel-sink.%s", server); } + pw_properties_set(props, "server", NULL); if ((str = pw_properties_get(props, "sink_properties")) != NULL) { module_args_add_props(stream_props, str); pw_properties_set(props, "sink_properties", NULL); } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, stream_props); - audio_info_to_props(&info, stream_props); - if ((str = pw_properties_get(props, "format")) != NULL) { - uint32_t id = format_paname2id(str, strlen(str)); - if (id == SPA_AUDIO_FORMAT_UNKNOWN) { - res = -EINVAL; - goto out; - } - - pw_properties_set(stream_props, PW_KEY_AUDIO_FORMAT, format_id2name(id)); + if ((str = pw_properties_get(props, "latency_msec")) != NULL) { + pw_properties_set(props, "pulse.latency", str); + pw_properties_set(props, "latency_msec", NULL); } d->module = module; d->stream_props = stream_props; - pw_properties_fetch_uint32(props, "latency_msec", &d->latency_msec); - return 0; out: pw_properties_free(stream_props); - return res; } diff --git a/src/modules/module-protocol-pulse/modules/module-tunnel-source.c b/src/modules/module-protocol-pulse/modules/module-tunnel-source.c index fba392499..1e4a4c19a 100644 --- a/src/modules/module-protocol-pulse/modules/module-tunnel-source.c +++ b/src/modules/module-protocol-pulse/modules/module-tunnel-source.c @@ -23,8 +23,6 @@ struct module_tunnel_source_data { struct pw_impl_module *mod; struct spa_hook mod_listener; - uint32_t latency_msec; - struct pw_properties *stream_props; }; @@ -47,22 +45,15 @@ static int module_tunnel_source_load(struct module *module) FILE *f; char *args; size_t size; - const char *server; pw_properties_setf(data->stream_props, "pulse.module.id", "%u", module->index); - server = pw_properties_get(module->props, "server"); - if ((f = open_memstream(&args, &size)) == NULL) return -errno; fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); - fprintf(f, " pulse.server.address = \"%s\" ", server); - fprintf(f, " tunnel.mode = source "); - if (data->latency_msec > 0) - fprintf(f, " pulse.latency = %u ", data->latency_msec); fprintf(f, " stream.props = {"); pw_properties_serialize_dict(f, &data->stream_props->dict, 0); fprintf(f, " } }"); @@ -115,19 +106,6 @@ static const struct spa_dict_item module_tunnel_source_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void audio_info_to_props(struct spa_audio_info_raw *info, struct pw_properties *props) -{ - char *s, *p; - uint32_t i; - - pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); - p = s = alloca(info->channels * 8); - for (i = 0; i < info->channels; i++) - p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(info->position[i])); - pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); -} - static int module_tunnel_source_prepare(struct module * const module) { struct module_tunnel_source_data * const d = module->user_data; @@ -145,6 +123,8 @@ static int module_tunnel_source_prepare(struct module * const module) goto out; } + pw_properties_set(props, "tunnel.mode", "source"); + remote_source_name = pw_properties_get(props, "source"); if (remote_source_name) pw_properties_set(props, PW_KEY_TARGET_OBJECT, remote_source_name); @@ -153,6 +133,8 @@ static int module_tunnel_source_prepare(struct module * const module) pw_log_error("no server given"); res = -EINVAL; goto out; + } else { + pw_properties_set(props, "pulse.server.address", server); } pw_properties_setf(stream_props, PW_KEY_NODE_DESCRIPTION, @@ -171,22 +153,24 @@ static int module_tunnel_source_prepare(struct module * const module) module_args_add_props(stream_props, str); pw_properties_set(props, "source_properties", NULL); } - if (module_args_to_audioinfo(module->impl, props, &info) < 0) { + if (module_args_to_audioinfo_keys(module->impl, props, + NULL, NULL, "channels", "channel_map", &info) < 0) { res = -EINVAL; goto out; } + audioinfo_to_properties(&info, stream_props); - audio_info_to_props(&info, stream_props); + if ((str = pw_properties_get(props, "latency_msec")) != NULL) { + pw_properties_set(props, "pulse.latency", str); + pw_properties_set(props, "latency_msec", NULL); + } d->module = module; d->stream_props = stream_props; - pw_properties_fetch_uint32(props, "latency_msec", &d->latency_msec); - return 0; out: pw_properties_free(stream_props); - return res; }