diff --git a/pipewire-alsa/alsa-plugins/pcm_pipewire.c b/pipewire-alsa/alsa-plugins/pcm_pipewire.c index e51cf1b56..bd6836e53 100644 --- a/pipewire-alsa/alsa-plugins/pcm_pipewire.c +++ b/pipewire-alsa/alsa-plugins/pcm_pipewire.c @@ -391,7 +391,7 @@ static void on_stream_state_changed(void *data, enum pw_stream_state old, enum p if (state == PW_STREAM_STATE_ERROR) { pw_log_warn("%s", error); - pw->error = -EIO; + pw->error = -errno; update_active(&pw->io); } } diff --git a/pipewire-v4l2/src/pipewire-v4l2.c b/pipewire-v4l2/src/pipewire-v4l2.c index 2e5a4045d..691c8ec37 100644 --- a/pipewire-v4l2/src/pipewire-v4l2.c +++ b/pipewire-v4l2/src/pipewire-v4l2.c @@ -1696,7 +1696,7 @@ static int connect_stream(struct file *file) break; if (state == PW_STREAM_STATE_ERROR) { - res = -EIO; + res = -errno; goto exit; } if (file->error < 0) { diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 5b156fb94..cb66f75e2 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -1109,7 +1109,7 @@ static void stream_state_changed(void *data, enum pw_stream_state old, switch (state) { case PW_STREAM_STATE_ERROR: - reply_error(client, -1, stream->create_tag, -EIO); + reply_error(client, -1, stream->create_tag, -errno); destroy_stream = true; break; case PW_STREAM_STATE_UNCONNECTED: diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 18ffb4e2a..519c1e2f7 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -407,8 +407,10 @@ static bool filter_set_state(struct pw_filter *filter, enum pw_filter_state stat pw_filter_state_as_string(old), 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 (%d) %s", filter, res, error); + errno = -res; + } filter->state = state; pw_filter_emit_state_changed(filter, old, state, error); @@ -1126,11 +1128,14 @@ static void proxy_destroy(void *_data) static void proxy_error(void *_data, int seq, int res, const char *message) { struct pw_filter *filter = _data; + int old_errno = errno; /* we just emit the state change here to inform the application. * If this is supposed to be a permanent error, the app should * do a pw_filter_set_error() */ + errno = -res; pw_filter_emit_state_changed(filter, filter->state, PW_FILTER_STATE_ERROR, message); + errno = old_errno; } static void proxy_bound_props(void *_data, uint32_t global_id, const struct spa_dict *props) @@ -1474,6 +1479,8 @@ enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char ** { if (error) *error = filter->error; + if (filter->state == PW_FILTER_STATE_ERROR) + errno = -filter->error_res; return filter->state; } diff --git a/src/pipewire/filter.h b/src/pipewire/filter.h index 97a1f9303..8298b6549 100644 --- a/src/pipewire/filter.h +++ b/src/pipewire/filter.h @@ -62,7 +62,8 @@ struct pw_filter_events { uint32_t version; void (*destroy) (void *data); - /** when the filter state changes */ + /** when the filter state changes. Since 1.4 this also sets errno when the + * new state is PW_FILTER_STATE_ERROR */ void (*state_changed) (void *data, enum pw_filter_state old, enum pw_filter_state state, const char *error); @@ -153,6 +154,8 @@ void pw_filter_add_listener(struct pw_filter *filter, const struct pw_filter_events *events, void *data); +/** Get the current filter state. Since 1.4 this also sets errno when the + * state is PW_FILTER_STATE_ERROR */ enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char **error); const char *pw_filter_get_name(struct pw_filter *filter); diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index c2186996f..5e5aed3b7 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -400,8 +400,10 @@ static bool stream_set_state(struct pw_stream *stream, enum pw_stream_state stat pw_stream_state_as_string(old), 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 (%d) %s", stream, res, error); + errno = -res; + } stream->state = state; pw_stream_emit_state_changed(stream, old, state, error); @@ -1169,11 +1171,14 @@ static void proxy_destroy(void *_data) static void proxy_error(void *_data, int seq, int res, const char *message) { struct pw_stream *stream = _data; + int old_errno = errno; /* we just emit the state change here to inform the application. * If this is supposed to be a permanent error, the app should * do a pw_stream_set_error() */ + errno = -res; pw_stream_emit_state_changed(stream, stream->state, PW_STREAM_STATE_ERROR, message); + errno = old_errno; } static void proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) @@ -1772,6 +1777,8 @@ enum pw_stream_state pw_stream_get_state(struct pw_stream *stream, const char ** { if (error) *error = stream->error; + if (stream->state == PW_STREAM_STATE_ERROR) + errno = -stream->error_res; return stream->state; } diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 1a84f30ff..8e8ba0950 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -412,7 +412,8 @@ struct pw_stream_events { uint32_t version; void (*destroy) (void *data); - /** when the stream state changes */ + /** when the stream state changes. Since 1.4 this also sets errno when the + * new state is PW_STREAM_STATE_ERROR */ void (*state_changed) (void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error); @@ -517,6 +518,8 @@ void pw_stream_add_listener(struct pw_stream *stream, const struct pw_stream_events *events, void *data); +/** Get the current stream state. Since 1.4 this also sets errno when the + * state is PW_STREAM_STATE_ERROR */ enum pw_stream_state pw_stream_get_state(struct pw_stream *stream, const char **error); const char *pw_stream_get_name(struct pw_stream *stream);