stream: keep error res around

So that we can return it when there is an error instead of the generic
-EIO.
This commit is contained in:
Wim Taymans 2023-05-17 11:00:52 +02:00
parent ca17672871
commit 65a5272a9f
3 changed files with 34 additions and 28 deletions

View file

@ -357,26 +357,28 @@ static inline void clear_queue(struct port *port, struct queue *queue)
spa_ringbuffer_init(&queue->ring); spa_ringbuffer_init(&queue->ring);
} }
static bool filter_set_state(struct pw_filter *filter, enum pw_filter_state state, const char *error) static bool filter_set_state(struct pw_filter *filter, enum pw_filter_state state,
int res, const char *error)
{ {
enum pw_filter_state old = filter->state; enum pw_filter_state old = filter->state;
bool res = old != state; bool changed = old != state;
if (res) { if (res) {
free(filter->error); free(filter->error);
filter->error = error ? strdup(error) : NULL; filter->error = error ? strdup(error) : NULL;
filter->error_res = res;
pw_log_debug("%p: update state from %s -> %s (%s)", filter, pw_log_debug("%p: update state from %s -> %s: (%d) %s", filter,
pw_filter_state_as_string(old), pw_filter_state_as_string(old),
pw_filter_state_as_string(state), filter->error); pw_filter_state_as_string(state), res, error);
if (state == PW_FILTER_STATE_ERROR) if (state == PW_FILTER_STATE_ERROR)
pw_log_error("%p: error %s", filter, error); pw_log_error("%p: error (%d) %s", filter, res, error);
filter->state = state; filter->state = state;
pw_filter_emit_state_changed(filter, old, state, error); pw_filter_emit_state_changed(filter, old, state, error);
} }
return res; return changed;
} }
static int enum_params(struct filter *d, struct spa_list *param_list, int seq, static int enum_params(struct filter *d, struct spa_list *param_list, int seq,
@ -490,13 +492,13 @@ static int impl_send_command(void *object, const struct spa_command *command)
NULL, 0, NULL, 0, false, impl); NULL, 0, NULL, 0, false, impl);
if (filter->state == PW_FILTER_STATE_STREAMING) { if (filter->state == PW_FILTER_STATE_STREAMING) {
pw_log_debug("%p: pause", filter); pw_log_debug("%p: pause", filter);
filter_set_state(filter, PW_FILTER_STATE_PAUSED, NULL); filter_set_state(filter, PW_FILTER_STATE_PAUSED, 0, NULL);
} }
break; break;
case SPA_NODE_COMMAND_Start: case SPA_NODE_COMMAND_Start:
if (filter->state == PW_FILTER_STATE_PAUSED) { if (filter->state == PW_FILTER_STATE_PAUSED) {
pw_log_debug("%p: start", filter); pw_log_debug("%p: start", filter);
filter_set_state(filter, PW_FILTER_STATE_STREAMING, NULL); filter_set_state(filter, PW_FILTER_STATE_STREAMING, 0, NULL);
} }
break; break;
default: default:
@ -849,7 +851,7 @@ static int impl_port_set_param(void *object,
pw_filter_emit_param_changed(filter, port->user_data, id, param); pw_filter_emit_param_changed(filter, port->user_data, id, param);
if (filter->state == PW_FILTER_STATE_ERROR) if (filter->state == PW_FILTER_STATE_ERROR)
return -EIO; return filter->error_res;
emit_port_info(impl, port, false); emit_port_info(impl, port, false);
@ -1094,7 +1096,7 @@ static void proxy_removed(void *_data)
pw_log_debug("%p: removed", filter); pw_log_debug("%p: removed", filter);
spa_hook_remove(&filter->proxy_listener); spa_hook_remove(&filter->proxy_listener);
filter->node_id = SPA_ID_INVALID; filter->node_id = SPA_ID_INVALID;
filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, NULL); filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, 0, NULL);
} }
static void proxy_destroy(void *_data) static void proxy_destroy(void *_data)
@ -1120,7 +1122,7 @@ static void proxy_bound_props(void *_data, uint32_t global_id, const struct spa_
filter->node_id = global_id; filter->node_id = global_id;
if (props) if (props)
pw_properties_update(filter->properties, props); pw_properties_update(filter->properties, props);
filter_set_state(filter, PW_FILTER_STATE_PAUSED, NULL); filter_set_state(filter, PW_FILTER_STATE_PAUSED, 0, NULL);
} }
static const struct pw_proxy_events proxy_events = { static const struct pw_proxy_events proxy_events = {
@ -1139,7 +1141,7 @@ static void on_core_error(void *_data, uint32_t id, int seq, int res, const char
id, seq, res, spa_strerror(res), message); id, seq, res, spa_strerror(res), message);
if (id == PW_ID_CORE && res == -EPIPE) { if (id == PW_ID_CORE && res == -EPIPE) {
filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, message); filter_set_state(filter, PW_FILTER_STATE_UNCONNECTED, res, message);
} }
} }
@ -1587,7 +1589,7 @@ pw_filter_connect(struct pw_filter *filter,
impl->disconnecting = false; impl->disconnecting = false;
impl->draining = false; impl->draining = false;
impl->driving = false; impl->driving = false;
filter_set_state(filter, PW_FILTER_STATE_CONNECTING, NULL); filter_set_state(filter, PW_FILTER_STATE_CONNECTING, 0, NULL);
if (flags & PW_FILTER_FLAG_DRIVER) if (flags & PW_FILTER_FLAG_DRIVER)
pw_properties_set(filter->properties, PW_KEY_NODE_DRIVER, "true"); pw_properties_set(filter->properties, PW_KEY_NODE_DRIVER, "true");
@ -1840,7 +1842,7 @@ int pw_filter_set_error(struct pw_filter *filter,
if (filter->proxy) if (filter->proxy)
pw_proxy_error(filter->proxy, res, value); pw_proxy_error(filter->proxy, res, value);
filter_set_state(filter, PW_FILTER_STATE_ERROR, value); filter_set_state(filter, PW_FILTER_STATE_ERROR, res, value);
free(value); free(value);
} }

View file

@ -1088,6 +1088,7 @@ struct pw_stream {
* CONFIGURE state and higher */ * CONFIGURE state and higher */
enum pw_stream_state state; /**< stream state */ enum pw_stream_state state; /**< stream state */
char *error; /**< error reason when state is in error */ char *error; /**< error reason when state is in error */
int error_res; /**< error code when in error */
struct spa_hook_list listener_list; struct spa_hook_list listener_list;
@ -1125,6 +1126,7 @@ struct pw_filter {
* CONFIGURE state and higher */ * CONFIGURE state and higher */
enum pw_filter_state state; /**< filter state */ enum pw_filter_state state; /**< filter state */
char *error; /**< error reason when state is in error */ char *error; /**< error reason when state is in error */
int error_res; /**< error code when in error */
struct spa_hook_list listener_list; struct spa_hook_list listener_list;

View file

@ -352,26 +352,28 @@ static inline void clear_queue(struct stream *stream, struct queue *queue)
queue->incount = queue->outcount; queue->incount = queue->outcount;
} }
static bool stream_set_state(struct pw_stream *stream, enum pw_stream_state state, const char *error) static bool stream_set_state(struct pw_stream *stream, enum pw_stream_state state,
int res, const char *error)
{ {
enum pw_stream_state old = stream->state; enum pw_stream_state old = stream->state;
bool res = old != state; bool changed = old != state;
if (res) { if (res) {
free(stream->error); free(stream->error);
stream->error = error ? strdup(error) : NULL; stream->error = error ? strdup(error) : NULL;
stream->error_res = res;
pw_log_debug("%p: update state from %s -> %s (%s)", stream, pw_log_debug("%p: update state from %s -> %s (%d) %s", stream,
pw_stream_state_as_string(old), pw_stream_state_as_string(old),
pw_stream_state_as_string(state), stream->error); pw_stream_state_as_string(state), res, stream->error);
if (state == PW_STREAM_STATE_ERROR) if (state == PW_STREAM_STATE_ERROR)
pw_log_error("%p: error %s", stream, error); pw_log_error("%p: error (%d) %s", stream, res, error);
stream->state = state; stream->state = state;
pw_stream_emit_state_changed(stream, old, state, error); pw_stream_emit_state_changed(stream, old, state, error);
} }
return res; return changed;
} }
static struct buffer *get_buffer(struct pw_stream *stream, uint32_t id) static struct buffer *get_buffer(struct pw_stream *stream, uint32_t id)
@ -613,7 +615,7 @@ static int impl_send_command(void *object, const struct spa_command *command)
if (stream->state == PW_STREAM_STATE_STREAMING) { if (stream->state == PW_STREAM_STATE_STREAMING) {
pw_log_debug("%p: pause", stream); pw_log_debug("%p: pause", stream);
stream_set_state(stream, PW_STREAM_STATE_PAUSED, NULL); stream_set_state(stream, PW_STREAM_STATE_PAUSED, 0, NULL);
} }
break; break;
case SPA_NODE_COMMAND_Start: case SPA_NODE_COMMAND_Start:
@ -629,7 +631,7 @@ static int impl_send_command(void *object, const struct spa_command *command)
call_process(impl); call_process(impl);
} }
stream_set_state(stream, PW_STREAM_STATE_STREAMING, NULL); stream_set_state(stream, PW_STREAM_STATE_STREAMING, 0, NULL);
} }
break; break;
default: default:
@ -884,7 +886,7 @@ static int impl_port_set_param(void *object,
pw_stream_emit_param_changed(stream, id, param); pw_stream_emit_param_changed(stream, id, param);
if (stream->state == PW_STREAM_STATE_ERROR) if (stream->state == PW_STREAM_STATE_ERROR)
return -EIO; return stream->error_res;
emit_node_info(impl, false); emit_node_info(impl, false);
emit_port_info(impl, false); emit_port_info(impl, false);
@ -1120,7 +1122,7 @@ static void proxy_removed(void *_data)
pw_log_debug("%p: removed", stream); pw_log_debug("%p: removed", stream);
spa_hook_remove(&stream->proxy_listener); spa_hook_remove(&stream->proxy_listener);
stream->node_id = SPA_ID_INVALID; stream->node_id = SPA_ID_INVALID;
stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, NULL); stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, 0, NULL);
} }
static void proxy_destroy(void *_data) static void proxy_destroy(void *_data)
@ -1146,7 +1148,7 @@ static void proxy_bound_props(void *data, uint32_t global_id, const struct spa_d
stream->node_id = global_id; stream->node_id = global_id;
if (props) if (props)
pw_properties_update(stream->properties, props); pw_properties_update(stream->properties, props);
stream_set_state(stream, PW_STREAM_STATE_PAUSED, NULL); stream_set_state(stream, PW_STREAM_STATE_PAUSED, 0, NULL);
} }
static const struct pw_proxy_events proxy_events = { static const struct pw_proxy_events proxy_events = {
@ -1382,7 +1384,7 @@ static void on_core_error(void *data, uint32_t id, int seq, int res, const char
id, seq, res, spa_strerror(res), message); id, seq, res, spa_strerror(res), message);
if (id == PW_ID_CORE && res == -EPIPE) { if (id == PW_ID_CORE && res == -EPIPE) {
stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, message); stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, res, message);
} }
} }
@ -1943,7 +1945,7 @@ pw_stream_connect(struct pw_stream *stream,
impl->driving = false; impl->driving = false;
impl->trigger = false; impl->trigger = false;
impl->using_trigger = false; impl->using_trigger = false;
stream_set_state(stream, PW_STREAM_STATE_CONNECTING, NULL); stream_set_state(stream, PW_STREAM_STATE_CONNECTING, 0, NULL);
if ((str = getenv("PIPEWIRE_NODE")) != NULL) if ((str = getenv("PIPEWIRE_NODE")) != NULL)
pw_properties_set(stream->properties, PW_KEY_TARGET_OBJECT, str); pw_properties_set(stream->properties, PW_KEY_TARGET_OBJECT, str);
@ -2114,7 +2116,7 @@ int pw_stream_set_error(struct pw_stream *stream,
if (stream->proxy) if (stream->proxy)
pw_proxy_error(stream->proxy, res, value); pw_proxy_error(stream->proxy, res, value);
stream_set_state(stream, PW_STREAM_STATE_ERROR, value); stream_set_state(stream, PW_STREAM_STATE_ERROR, res, value);
free(value); free(value);
} }