From d673158db1a71dc020a2795bcb9cf0738eadf5bf Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 30 Nov 2021 17:43:07 +0100 Subject: [PATCH] alsa: expose all config options as params Add PropInfo for all the params that we can configure at construct time and also add them as PROP_params. This way you can configure the headroom at runtime with this: pw-cli s Props '{ params = [ "api.alsa.headroom" 1024 ] }' --- spa/plugins/alsa/alsa-pcm-sink.c | 41 ++--- spa/plugins/alsa/alsa-pcm-source.c | 47 +++--- spa/plugins/alsa/alsa-pcm.c | 257 ++++++++++++++++++++++++++--- spa/plugins/alsa/alsa-pcm.h | 8 +- 4 files changed, 286 insertions(+), 67 deletions(-) diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index 277893774..b8d6385cc 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -141,64 +141,64 @@ static int impl_node_enum_params(void *object, int seq, param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA device"), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA device"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device))); break; case 1: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA device name"), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name))); break; case 2: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA card name"), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name))); break; case 3: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_name, SPA_POD_String("The minimum latency"), + SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); break; case 4: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_name, SPA_POD_String("The maximum latency"), + SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); break; case 5: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_START_CUSTOM), - SPA_PROP_INFO_name, SPA_POD_String("Use the driver channelmap"), - SPA_PROP_INFO_type, SPA_POD_Bool(p->use_chmap)); - break; - case 6: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), - SPA_PROP_INFO_name, SPA_POD_String("Latency offset (ns)"), + SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX)); break; - case 7: + case 6: if (this->is_iec958 || this->is_hdmi) { param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_iec958Codecs), - SPA_PROP_INFO_name, SPA_POD_String("Enabled IEC958 (S/PDIF) codecs"), + SPA_PROP_INFO_name, SPA_POD_String("iec958.codecs"), + SPA_PROP_INFO_description, SPA_POD_String("Enabled IEC958 (S/PDIF) codecs"), SPA_PROP_INFO_type, SPA_POD_Id(SPA_AUDIO_IEC958_CODEC_UNKNOWN), + SPA_PROP_INFO_params, SPA_POD_Bool(true), SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); + break; } SPA_FALLTHROUGH default: - return 0; + param = spa_alsa_enum_propinfo(this, result.index - 7, + SPA_PROP_START_CUSTOM + result.index - 6, &b); + if (param == NULL) + return 0; } break; } @@ -218,7 +218,6 @@ static int impl_node_enum_params(void *object, int seq, SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency), - SPA_PROP_START_CUSTOM, SPA_POD_Bool(p->use_chmap), SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns), 0); @@ -228,6 +227,7 @@ static int impl_node_enum_params(void *object, int seq, spa_pod_builder_array(&b, sizeof(uint32_t), SPA_TYPE_Id, n_codecs, codecs); } + spa_alsa_add_prop_params(this, &b); param = spa_pod_builder_pop(&b, &f); break; default: @@ -334,7 +334,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, { struct props *p = &this->props; struct spa_process_latency_info info; - struct spa_pod *iec958_codecs = NULL; + struct spa_pod *iec958_codecs = NULL, *params = NULL; if (param == NULL) { reset_props(p); @@ -349,8 +349,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&info.ns), - SPA_PROP_START_CUSTOM, SPA_POD_OPT_Bool(&p->use_chmap), - SPA_PROP_iec958Codecs, SPA_POD_OPT_Pod(&iec958_codecs)); + SPA_PROP_iec958Codecs, SPA_POD_OPT_Pod(&iec958_codecs), + SPA_PROP_params, SPA_POD_OPT_Pod(¶ms)); if ((this->is_iec958 || this->is_hdmi) && iec958_codecs != NULL) { uint32_t i, codecs[16], n_codecs; @@ -367,6 +367,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, this->port_params[PORT_EnumFormat].user++; } handle_process_latency(this, &info); + spa_alsa_parse_prop_params(this, params); emit_node_info(this, false); emit_port_info(this, false); diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index c1d9dc092..e3e8a447e 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -116,7 +116,7 @@ static int impl_node_enum_params(void *object, int seq, { struct state *this = object; struct spa_pod *param; - uint8_t buffer[1024]; + uint8_t buffer[4096]; struct spa_pod_builder b = { 0 }; struct props *p; struct spa_result_node_params result; @@ -141,74 +141,77 @@ static int impl_node_enum_params(void *object, int seq, param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA device"), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA device"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device))); break; case 1: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA device name"), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name))); break; case 2: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName), - SPA_PROP_INFO_name, SPA_POD_String("The ALSA card name"), + SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name))); break; case 3: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_name, SPA_POD_String("The minimum latency"), + SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); break; case 4: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_name, SPA_POD_String("The maximum latency"), + SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); break; case 5: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_START_CUSTOM), - SPA_PROP_INFO_name, SPA_POD_String("Use the driver channelmap"), - SPA_PROP_INFO_type, SPA_POD_Bool(p->use_chmap)); - break; - case 6: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), - SPA_PROP_INFO_name, SPA_POD_String("Latency offset (ns)"), + SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX)); break; default: - return 0; + param = spa_alsa_enum_propinfo(this, result.index - 6, + SPA_PROP_START_CUSTOM + result.index - 5, &b); + if (param == NULL) + return 0; } break; case SPA_PARAM_Props: + { + struct spa_pod_frame f; + switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_Props, id, + spa_pod_builder_push_object(&b, &f, + SPA_TYPE_OBJECT_Props, id); + spa_pod_builder_add(&b, SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)), SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)), SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency), - SPA_PROP_START_CUSTOM, SPA_POD_Bool(p->use_chmap), - SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns)); + SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns), + 0); + spa_alsa_add_prop_params(this, &b); + param = spa_pod_builder_pop(&b, &f); break; default: return 0; } break; - + } case SPA_PARAM_IO: switch (result.index) { case 0: @@ -309,6 +312,7 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, { struct props *p = &this->props; struct spa_process_latency_info info; + struct spa_pod *params = NULL; if (param == NULL) { reset_props(p); @@ -323,9 +327,10 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&info.ns), - SPA_PROP_START_CUSTOM, SPA_POD_OPT_Bool(&p->use_chmap)); + SPA_PROP_params, SPA_POD_OPT_Pod(¶ms)); handle_process_latency(this, &info); + spa_alsa_parse_prop_params(this, params); emit_node_info(this, false); emit_port_info(this, false); diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index b093b3bee..ab0de5aaf 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -89,6 +89,237 @@ static void release_card(uint32_t index) free(c); } +int spa_alsa_set_param(struct state *state, const char *k, const char *s) +{ + if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) { + state->default_channels = atoi(s); + } else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) { + state->default_rate = atoi(s); + } else if (spa_streq(k, SPA_KEY_AUDIO_FORMAT)) { + state->default_format = spa_alsa_format_from_name(s, strlen(s)); + } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { + spa_alsa_parse_position(&state->default_pos, s, strlen(s)); + } else if (spa_streq(k, "iec958.codecs")) { + spa_alsa_parse_iec958_codecs(&state->iec958_codecs, s, strlen(s)); + } else if (spa_streq(k, "api.alsa.period-size")) { + state->default_period_size = atoi(s); + } else if (spa_streq(k, "api.alsa.headroom")) { + state->default_headroom = atoi(s); + } else if (spa_streq(k, "api.alsa.start-delay")) { + state->default_start_delay = atoi(s); + } else if (spa_streq(k, "api.alsa.disable-mmap")) { + state->disable_mmap = spa_atob(s); + } else if (spa_streq(k, "api.alsa.disable-batch")) { + state->disable_batch = spa_atob(s); + } else if (spa_streq(k, "api.alsa.use-chmap")) { + state->props.use_chmap = spa_atob(s); + } else if (spa_streq(k, "api.alsa.multi-rate")) { + state->multi_rate = spa_atob(s); + } + return 0; +} + +struct spa_pod *spa_alsa_enum_propinfo(struct state *state, + uint32_t idx, uint32_t id, struct spa_pod_builder *b) +{ + struct spa_pod *param; + + switch (idx) { + case 0: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_AUDIO_CHANNELS), + SPA_PROP_INFO_description, SPA_POD_String("Audio Channels"), + SPA_PROP_INFO_type, SPA_POD_Int(state->default_channels), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 1: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_AUDIO_RATE), + SPA_PROP_INFO_description, SPA_POD_String("Audio Rate"), + SPA_PROP_INFO_type, SPA_POD_Int(state->default_rate), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 2: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_AUDIO_FORMAT), + SPA_PROP_INFO_description, SPA_POD_String("Audio Format"), + SPA_PROP_INFO_type, SPA_POD_String(""), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 3: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_AUDIO_POSITION), + SPA_PROP_INFO_description, SPA_POD_String("Audio Position"), + SPA_PROP_INFO_type, SPA_POD_String("[ ]"), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 4: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.period-size"), + SPA_PROP_INFO_description, SPA_POD_String("Period Size"), + SPA_PROP_INFO_type, SPA_POD_Int(state->default_period_size), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 5: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.headroom"), + SPA_PROP_INFO_description, SPA_POD_String("Headroom"), + SPA_PROP_INFO_type, SPA_POD_Int(state->default_headroom), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 6: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.start-delay"), + SPA_PROP_INFO_description, SPA_POD_String("Start Delay"), + SPA_PROP_INFO_type, SPA_POD_Int(state->default_start_delay), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 7: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.disable-mmap"), + SPA_PROP_INFO_description, SPA_POD_String("Disable MMAP"), + SPA_PROP_INFO_type, SPA_POD_Bool(state->disable_mmap), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 8: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.disable-batch"), + SPA_PROP_INFO_description, SPA_POD_String("Disable Batch"), + SPA_PROP_INFO_type, SPA_POD_Bool(state->disable_batch), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 9: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.use-chmap"), + SPA_PROP_INFO_description, SPA_POD_String("Use the driver channelmap"), + SPA_PROP_INFO_type, SPA_POD_Bool(state->props.use_chmap), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 10: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(id), + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.multi-rate"), + SPA_PROP_INFO_description, SPA_POD_String("Support multiple rates"), + SPA_PROP_INFO_type, SPA_POD_Bool(state->multi_rate), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + default: + return NULL; + } + return param; +} + +int spa_alsa_add_prop_params(struct state *state, struct spa_pod_builder *b) +{ + struct spa_pod_frame f[1]; + + spa_pod_builder_prop(b, SPA_PROP_params, 0); + spa_pod_builder_push_struct(b, &f[0]); + + spa_pod_builder_string(b, SPA_KEY_AUDIO_CHANNELS); + spa_pod_builder_int(b, state->default_channels); + + spa_pod_builder_string(b, SPA_KEY_AUDIO_RATE); + spa_pod_builder_int(b, state->default_rate); + + spa_pod_builder_string(b, SPA_KEY_AUDIO_FORMAT); + spa_pod_builder_string(b, ""); + + spa_pod_builder_string(b, SPA_KEY_AUDIO_POSITION); + spa_pod_builder_string(b, "[ ]"); + + spa_pod_builder_string(b, "api.alsa.period-size"); + spa_pod_builder_int(b, state->default_period_size); + + spa_pod_builder_string(b, "api.alsa.headroom"); + spa_pod_builder_int(b, state->default_headroom); + + spa_pod_builder_string(b, "api.alsa.start-delay"); + spa_pod_builder_int(b, state->default_start_delay); + + spa_pod_builder_string(b, "api.alsa.disable-mmap"); + spa_pod_builder_bool(b, state->disable_mmap); + + spa_pod_builder_string(b, "api.alsa.disable-batch"); + spa_pod_builder_bool(b, state->disable_batch); + + spa_pod_builder_string(b, "api.alsa.use-chmap"); + spa_pod_builder_bool(b, state->props.use_chmap); + + spa_pod_builder_string(b, "api.alsa.multi-rate"); + spa_pod_builder_bool(b, state->multi_rate); + + spa_pod_builder_pop(b, &f[0]); + return 0; +} + +int spa_alsa_parse_prop_params(struct state *state, struct spa_pod *params) +{ + struct spa_pod_parser prs; + struct spa_pod_frame f; + int changed = 0; + + if (params == NULL) + return 0; + + spa_pod_parser_pod(&prs, params); + if (spa_pod_parser_push_struct(&prs, &f) < 0) + return 0; + + while (true) { + const char *name; + struct spa_pod *pod; + char value[512]; + + if (spa_pod_parser_get_string(&prs, &name) < 0) + break; + spa_log_info(state->log, "%s", name); + + if (spa_pod_parser_get_pod(&prs, &pod) < 0) + break; + if (spa_pod_is_string(pod)) { + spa_pod_copy_string(pod, sizeof(value), value); + } else if (spa_pod_is_int(pod)) { + snprintf(value, sizeof(value), "%u", + SPA_POD_VALUE(struct spa_pod_int, pod)); + } else if (spa_pod_is_bool(pod)) { + snprintf(value, sizeof(value), "%s", + SPA_POD_VALUE(struct spa_pod_bool, pod) ? + "true" : "false"); + } else + continue; + + spa_alsa_set_param(state, name, value); + changed++; + } + if (changed > 0) { + state->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + state->params[NODE_Props].user++; + } + return changed; +} + int spa_alsa_init(struct state *state, const struct spa_dict *info) { uint32_t i; @@ -104,34 +335,12 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info) state->card_index = atoi(s); } else if (spa_streq(k, SPA_KEY_API_ALSA_OPEN_UCM)) { state->open_ucm = spa_atob(s); - } else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) { - state->default_channels = atoi(s); - } else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) { - state->default_rate = atoi(s); - } else if (spa_streq(k, SPA_KEY_AUDIO_FORMAT)) { - state->default_format = spa_alsa_format_from_name(s, strlen(s)); - } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { - spa_alsa_parse_position(&state->default_pos, s, strlen(s)); } else if (spa_streq(k, "latency.internal.rate")) { state->process_latency.rate = atoi(s); } else if (spa_streq(k, "latency.internal.ns")) { state->process_latency.ns = atoi(s); - } else if (spa_streq(k, "iec958.codecs")) { - spa_alsa_parse_iec958_codecs(&state->iec958_codecs, s, strlen(s)); - } else if (spa_streq(k, "api.alsa.period-size")) { - state->default_period_size = atoi(s); - } else if (spa_streq(k, "api.alsa.headroom")) { - state->default_headroom = atoi(s); - } else if (spa_streq(k, "api.alsa.start-delay")) { - state->default_start_delay = atoi(s); - } else if (spa_streq(k, "api.alsa.disable-mmap")) { - state->disable_mmap = spa_atob(s); - } else if (spa_streq(k, "api.alsa.disable-batch")) { - state->disable_batch = spa_atob(s); - } else if (spa_streq(k, "api.alsa.use-chmap")) { - state->props.use_chmap = spa_atob(s); - } else if (spa_streq(k, "api.alsa.multi-rate")) { - state->multi_rate = spa_atob(s); + } else { + spa_alsa_set_param(state, k, s); } } diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 5046cc646..fe35ee639 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -221,8 +221,12 @@ struct state { struct spa_process_latency_info process_latency; }; -int -spa_alsa_enum_format(struct state *state, int seq, +struct spa_pod *spa_alsa_enum_propinfo(struct state *state, + uint32_t idx, uint32_t id, struct spa_pod_builder *b); +int spa_alsa_add_prop_params(struct state *state, struct spa_pod_builder *b); +int spa_alsa_parse_prop_params(struct state *state, struct spa_pod *params); + +int spa_alsa_enum_format(struct state *state, int seq, uint32_t start, uint32_t num, const struct spa_pod *filter);