diff --git a/spa/include/spa/node/command.h b/spa/include/spa/node/command.h index 571c10499..f630a6412 100644 --- a/spa/include/spa/node/command.h +++ b/spa/include/spa/node/command.h @@ -33,14 +33,22 @@ extern "C" { /* object id of SPA_TYPE_COMMAND_Node */ enum spa_node_command { - SPA_NODE_COMMAND_Suspend, - SPA_NODE_COMMAND_Pause, - SPA_NODE_COMMAND_Start, + SPA_NODE_COMMAND_Suspend, /**< suspend a node, this removes all configured + * formats and closes any devices */ + SPA_NODE_COMMAND_Pause, /**< pause a node. this makes it stop emiting + * scheduling events */ + SPA_NODE_COMMAND_Start, /**< start a node, this makes it start emiting + * scheduling events */ SPA_NODE_COMMAND_Enable, SPA_NODE_COMMAND_Disable, SPA_NODE_COMMAND_Flush, SPA_NODE_COMMAND_Drain, SPA_NODE_COMMAND_Marker, + SPA_NODE_COMMAND_ParamBegin, /**< begin a set of parameter enumerations or + * configuration that require the device to + * remain opened, like query formats and then + * set a format */ + SPA_NODE_COMMAND_ParamEnd, /**< end a transaction */ }; #define SPA_NODE_COMMAND_ID(cmd) SPA_COMMAND_ID(cmd, SPA_TYPE_COMMAND_Node) diff --git a/spa/include/spa/node/type-info.h b/spa/include/spa/node/type-info.h index 9bda06631..60db9f664 100644 --- a/spa/include/spa/node/type-info.h +++ b/spa/include/spa/node/type-info.h @@ -79,6 +79,8 @@ static const struct spa_type_info spa_type_node_command_id[] = { { SPA_NODE_COMMAND_Flush, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL }, { SPA_NODE_COMMAND_Drain, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL }, { SPA_NODE_COMMAND_Marker, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL }, + { SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL }, + { SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL }, { 0, 0, NULL, NULL }, }; diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index 450ecd73a..a87cc72cb 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -239,6 +239,16 @@ static int impl_node_send_command(void *object, const struct spa_command *comman spa_return_val_if_fail(command != NULL, -EINVAL); switch (SPA_NODE_COMMAND_ID(command)) { + case SPA_NODE_COMMAND_ParamBegin: + if ((res = spa_alsa_open(this)) < 0) + return res; + break; + case SPA_NODE_COMMAND_ParamEnd: + if (this->have_format) + return 0; + if ((res = spa_alsa_close(this)) < 0) + return res; + break; case SPA_NODE_COMMAND_Start: if (!this->have_format) return -EIO; diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index 2773ab153..bda70844a 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -241,6 +241,16 @@ static int impl_node_send_command(void *object, const struct spa_command *comman spa_return_val_if_fail(command != NULL, -EINVAL); switch (SPA_NODE_COMMAND_ID(command)) { + case SPA_NODE_COMMAND_ParamBegin: + if ((res = spa_alsa_open(this)) < 0) + return res; + break; + case SPA_NODE_COMMAND_ParamEnd: + if (this->have_format) + return 0; + if ((res = spa_alsa_close(this)) < 0) + return res; + break; case SPA_NODE_COMMAND_Start: if (!this->have_format) return -EIO; diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index a106ea7e4..6a427ab88 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -17,7 +17,7 @@ #define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; } -static int spa_alsa_open(struct state *state) +int spa_alsa_open(struct state *state) { int err; struct props *props = &state->props; @@ -28,7 +28,7 @@ static int spa_alsa_open(struct state *state) CHECK(snd_output_stdio_attach(&state->output, stderr, 0), "attach failed"); - spa_log_debug(state->log, NAME" %p: ALSA device open '%s' %s", state, props->device, + spa_log_info(state->log, NAME" %p: ALSA device open '%s' %s", state, props->device, state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback"); CHECK(snd_pcm_open(&state->hndl, props->device, @@ -73,7 +73,7 @@ int spa_alsa_close(struct state *state) if (!state->opened) return 0; - spa_log_debug(state->log, NAME" %p: Device '%s' closing", state, state->props.device); + spa_log_info(state->log, NAME" %p: Device '%s' closing", state, state->props.device); if ((err = snd_pcm_close(state->hndl)) < 0) spa_log_warn(state->log, "%s: close failed: %s", state->props.device, snd_strerror(err)); @@ -539,6 +539,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ CHECK(snd_pcm_hw_params_set_period_size_near(hndl, params, &period_size, &dir), "set_period_size_near"); CHECK(snd_pcm_hw_params_get_buffer_size_max(params, &state->buffer_frames), "get_buffer_size_max"); CHECK(snd_pcm_hw_params_set_buffer_size_near(hndl, params, &state->buffer_frames), "set_buffer_size_near"); + state->period_frames = period_size; periods = state->buffer_frames / state->period_frames; diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 2bf6a7e49..001ac415a 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -171,6 +171,7 @@ spa_alsa_enum_format(struct state *state, int seq, int spa_alsa_set_format(struct state *state, struct spa_audio_info *info, uint32_t flags); +int spa_alsa_open(struct state *state); int spa_alsa_start(struct state *state); int spa_alsa_reassign_follower(struct state *state); int spa_alsa_pause(struct state *state); diff --git a/spa/plugins/audioconvert/audioadapter.c b/spa/plugins/audioconvert/audioadapter.c index 10a27f8fd..390ae153a 100644 --- a/spa/plugins/audioconvert/audioadapter.c +++ b/spa/plugins/audioconvert/audioadapter.c @@ -459,6 +459,9 @@ static int negotiate_format(struct impl *this) state = 0; format = NULL; + spa_node_send_command(this->follower, + &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_ParamBegin)); + if (this->have_format) format = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &this->follower_current_format.info.raw); @@ -471,7 +474,7 @@ static int negotiate_format(struct impl *this) else { debug_params(this, this->follower, this->direction, 0, SPA_PARAM_EnumFormat, format, "follower format", res); - return res; + goto done; } } @@ -484,16 +487,23 @@ static int negotiate_format(struct impl *this) debug_params(this, this->convert, SPA_DIRECTION_REVERSE(this->direction), 0, SPA_PARAM_EnumFormat, format, "convert format", res); - return -ENOTSUP; + res = -ENOTSUP; + goto done; } } - if (format == NULL) - return -ENOTSUP; + if (format == NULL) { + res = -ENOTSUP; + goto done; + } spa_pod_fixate(format); res = configure_format(this, 0, format); +done: + spa_node_send_command(this->follower, + &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_ParamEnd)); + return res; } diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 916e69c18..5da8dc765 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -410,6 +410,9 @@ static int impl_send_command(void *object, const struct spa_command *command) stream_set_state(stream, PW_STREAM_STATE_STREAMING, NULL); } break; + case SPA_NODE_COMMAND_ParamBegin: + case SPA_NODE_COMMAND_ParamEnd: + break; default: pw_log_warn(NAME" %p: unhandled node command %d", stream, SPA_NODE_COMMAND_ID(command));