diff --git a/0001-alsa-improve-rate-selection.patch b/0001-alsa-improve-rate-selection.patch new file mode 100644 index 0000000..0519168 --- /dev/null +++ b/0001-alsa-improve-rate-selection.patch @@ -0,0 +1,75 @@ +From d8c867b51508b7337507e04648ace5df21bde048 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Wed, 5 Jan 2022 11:53:47 +0100 +Subject: [PATCH] alsa: improve rate selection + +Make sure we don't select an invalid rate when the default is set or +when the card is already opened in some unsupported rate. + +See #1975 +--- + spa/plugins/alsa/alsa-pcm.c | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c +index a4ea34a94..8e8834ebb 100644 +--- a/spa/plugins/alsa/alsa-pcm.c ++++ b/spa/plugins/alsa/alsa-pcm.c +@@ -734,31 +734,32 @@ static int add_rate(struct state *state, uint32_t scale, bool all, uint32_t inde + CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min"); + CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max"); + +- rate = state->default_rate; + if (!state->multi_rate && state->card->format_ref > 0) + rate = state->card->rate; ++ else ++ rate = state->default_rate; + +- if (rate != 0 && !all) { +- if (min < rate) +- min = rate; +- if (max > rate) +- max = rate; +- } ++ if (rate < min || rate > max) ++ rate = 0; ++ ++ if (rate != 0 && !all) ++ min = max = rate; ++ ++ if (rate == 0) ++ rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE; ++ ++ rate = SPA_CLAMP(rate, min, max); + + spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0); + + spa_pod_builder_push_choice(b, &f[0], SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f[0]); + +- if (rate == 0) +- rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE; +- + if (state->n_allowed_rates > 0) { + uint32_t i, v, last = 0, count = 0; + +- v = SPA_CLAMP(rate, min, max); +- if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, v)) { +- spa_pod_builder_int(b, v * scale); ++ if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, rate)) { ++ spa_pod_builder_int(b, rate * scale); + count++; + } + for (i = 0; i < state->n_allowed_rates; i++) { +@@ -775,7 +776,7 @@ static int add_rate(struct state *state, uint32_t scale, bool all, uint32_t inde + if (count > 1) + choice->body.type = SPA_CHOICE_Enum; + } else { +- spa_pod_builder_int(b, SPA_CLAMP(rate, min, max) * scale); ++ spa_pod_builder_int(b, rate * scale); + + if (min != max) { + spa_pod_builder_int(b, min * scale); +-- +GitLab + diff --git a/0001-audioconvert-avoid-infinite-loop.patch b/0001-audioconvert-avoid-infinite-loop.patch new file mode 100644 index 0000000..2474281 --- /dev/null +++ b/0001-audioconvert-avoid-infinite-loop.patch @@ -0,0 +1,48 @@ +From af11fb4804c97ad0dee73dba059b7a3d42d15bad Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Wed, 5 Jan 2022 17:02:40 +0100 +Subject: [PATCH] audioconvert: avoid infinite loop + +When the follower has no param to enumerate we would keep on enumerating +the params of the converter forever. Fix this by setting the next value +to something that would then stop the iteration. + +Also increase the amount of bits for the follower because it might need +them. +--- + spa/plugins/audioconvert/audioadapter.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/spa/plugins/audioconvert/audioadapter.c b/spa/plugins/audioconvert/audioadapter.c +index b7f80feca..34622a66c 100644 +--- a/spa/plugins/audioconvert/audioadapter.c ++++ b/spa/plugins/audioconvert/audioadapter.c +@@ -118,19 +118,20 @@ static int follower_enum_params(struct impl *this, + struct spa_pod_builder *builder) + { + int res; +- if (result->next < 0x10000) { ++ if (result->next < 0x100000) { + if ((res = spa_node_enum_params_sync(this->convert, + id, &result->next, filter, &result->param, builder)) == 1) + return res; +- result->next = 0x10000; ++ result->next = 0x100000; + } +- if (result->next >= 0x10000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) { +- result->next &= 0xffff; ++ if (result->next < 0x200000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) { ++ result->next &= 0xfffff; + if ((res = spa_node_enum_params_sync(this->follower, + id, &result->next, filter, &result->param, builder)) == 1) { +- result->next |= 0x10000; ++ result->next |= 0x100000; + return res; + } ++ result->next = 0x200000; + } + return 0; + } +-- +GitLab + diff --git a/0001-bluez5-dont-create-device-if-adapter-is-missing.patch b/0001-bluez5-dont-create-device-if-adapter-is-missing.patch new file mode 100644 index 0000000..782c973 --- /dev/null +++ b/0001-bluez5-dont-create-device-if-adapter-is-missing.patch @@ -0,0 +1,57 @@ +From 67dcc0d29120572048f71fd40ab924a01ddd42fa Mon Sep 17 00:00:00 2001 +From: Pauli Virtanen +Date: Mon, 17 Jan 2022 19:10:14 +0200 +Subject: [PATCH] bluez5: don't create device if adapter is missing + +BlueZ may be missing adapter information for devices in some cases. +Ignore devices without specified adapter. +--- + spa/plugins/bluez5/bluez5-dbus.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c +index 2b7f20162..f355b08d3 100644 +--- a/spa/plugins/bluez5/bluez5-dbus.c ++++ b/spa/plugins/bluez5/bluez5-dbus.c +@@ -1470,6 +1470,15 @@ static int device_update_props(struct spa_bt_device *device, + return 0; + } + ++static bool device_props_ready(struct spa_bt_device *device) ++{ ++ /* ++ * In some cases, BlueZ device props may be missing part of ++ * the information required when the interface first appears. ++ */ ++ return device->adapter && device->address; ++} ++ + bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec) + { + struct spa_bt_monitor *monitor = device->monitor; +@@ -3622,6 +3631,9 @@ static void interface_added(struct spa_bt_monitor *monitor, + device_update_props(d, props_iter, NULL); + d->reconnect_state = BT_DEVICE_RECONNECT_INIT; + ++ if (!device_props_ready(d)) ++ return; ++ + device_update_hw_volume_profiles(d); + + /* Trigger bluez device creation before bluez profile negotiation started so that +@@ -3978,6 +3990,12 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us + spa_log_debug(monitor->log, "Properties changed in device %s", path); + + device_update_props(d, &it[1], NULL); ++ ++ if (!device_props_ready(d)) ++ goto finish; ++ ++ device_update_hw_volume_profiles(d); ++ + spa_bt_device_add_profile(d, SPA_BT_PROFILE_NULL); + } + else if (spa_streq(iface, BLUEZ_MEDIA_ENDPOINT_INTERFACE)) { +-- +GitLab + diff --git a/0001-bluez5-handle-missing-device-and-adapter-in-quirks.patch b/0001-bluez5-handle-missing-device-and-adapter-in-quirks.patch new file mode 100644 index 0000000..6a880e5 --- /dev/null +++ b/0001-bluez5-handle-missing-device-and-adapter-in-quirks.patch @@ -0,0 +1,38 @@ +From 140c8d0cd95523815d42dbca10ef9457780f6636 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Tue, 11 Jan 2022 21:33:35 +0100 +Subject: [PATCH] bluez5: handle missing device and adapter in quirks + +When the device or adapter is NULL, skip the quirk checks instead of +crashing. + +Fixes https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/155 +--- + spa/plugins/bluez5/quirks.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/spa/plugins/bluez5/quirks.c b/spa/plugins/bluez5/quirks.c +index 217bb61f6..16a8ebaa9 100644 +--- a/spa/plugins/bluez5/quirks.c ++++ b/spa/plugins/bluez5/quirks.c +@@ -332,7 +332,7 @@ int spa_bt_quirks_get_features(const struct spa_bt_quirks *this, + } + + /* Adapter */ +- if (this->adapter_rules) { ++ if (this->adapter_rules && adapter) { + uint32_t no_features = 0; + int nitems = 0; + char vendor_id[64], product_id[64], address[64]; +@@ -357,7 +357,7 @@ int spa_bt_quirks_get_features(const struct spa_bt_quirks *this, + } + + /* Device */ +- if (this->device_rules) { ++ if (this->device_rules && device) { + uint32_t no_features = 0; + int nitems = 0; + char vendor_id[64], product_id[64], version_id[64], address[64]; +-- +GitLab + diff --git a/0001-jack-remember-last-return-from-jack_get_buffer_size.patch b/0001-jack-remember-last-return-from-jack_get_buffer_size.patch new file mode 100644 index 0000000..9d4ca97 --- /dev/null +++ b/0001-jack-remember-last-return-from-jack_get_buffer_size.patch @@ -0,0 +1,40 @@ +From 2b102a1046630b072d80e36c872e2aa4e28052ca Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Fri, 7 Jan 2022 17:12:43 +0100 +Subject: [PATCH] jack: remember last return from jack_get_buffer_size + +Remember what we last returned from jack_get_buffer_size and only +emit a buffersize change event when somwthing new is configured. + +Fixes startup of jconvolver. + +Fixes #1989 +--- + pipewire-jack/src/pipewire-jack.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c +index 595d786f6..f338d2469 100644 +--- a/pipewire-jack/src/pipewire-jack.c ++++ b/pipewire-jack/src/pipewire-jack.c +@@ -1227,7 +1227,8 @@ do_buffer_frames(struct spa_loop *loop, + { + uint32_t buffer_frames = *((uint32_t*)data); + struct client *c = user_data; +- do_callback_expr(c, c->buffer_frames = buffer_frames, bufsize_callback, buffer_frames, c->bufsize_arg); ++ if (c->buffer_frames != buffer_frames) ++ do_callback_expr(c, c->buffer_frames = buffer_frames, bufsize_callback, buffer_frames, c->bufsize_arg); + recompute_latencies(c); + return 0; + } +@@ -3985,6 +3986,7 @@ jack_nframes_t jack_get_buffer_size (jack_client_t *client) + res = c->position->clock.duration; + } + } ++ c->buffer_frames = res; + pw_log_debug("buffer_frames: %u", res); + return res; + } +-- +GitLab + diff --git a/0001-loop-invoke-immediately-when-loop-is-not-running.patch b/0001-loop-invoke-immediately-when-loop-is-not-running.patch new file mode 100644 index 0000000..3652e87 --- /dev/null +++ b/0001-loop-invoke-immediately-when-loop-is-not-running.patch @@ -0,0 +1,27 @@ +From 6ece5d810ce7090be07d22808f48caef96cb790d Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Tue, 18 Jan 2022 20:03:01 +0100 +Subject: [PATCH] loop: invoke immediately when loop is not running + +Or else we might never get our callback called or worse, block forever, +waiting for the response. +--- + spa/plugins/support/loop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/spa/plugins/support/loop.c b/spa/plugins/support/loop.c +index 94f4b321f..c8bcc5b08 100644 +--- a/spa/plugins/support/loop.c ++++ b/spa/plugins/support/loop.c +@@ -187,7 +187,7 @@ loop_invoke(void *object, + int32_t filled; + uint32_t avail, idx, offset, l0; + +- if (pthread_equal(impl->thread, pthread_self())) ++ if (impl->thread == 0 || pthread_equal(impl->thread, pthread_self())) + return loop_invoke_inthread(impl, func, seq, data, size, block, user_data); + + filled = spa_ringbuffer_get_write_index(&impl->buffer, &idx); +-- +GitLab + diff --git a/0001-merger-also-reconfigure-when-monitor-changes.patch b/0001-merger-also-reconfigure-when-monitor-changes.patch new file mode 100644 index 0000000..21e7b70 --- /dev/null +++ b/0001-merger-also-reconfigure-when-monitor-changes.patch @@ -0,0 +1,28 @@ +From dec7f7a608fc2f8aac1338d398ae30ba5a592e64 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Mon, 17 Jan 2022 16:28:06 +0100 +Subject: [PATCH] merger: also reconfigure when monitor changes + +So that monitor ports are added/removed. +--- + spa/plugins/audioconvert/merger.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c +index 9ebf040e9..c0b979997 100644 +--- a/spa/plugins/audioconvert/merger.c ++++ b/spa/plugins/audioconvert/merger.c +@@ -624,7 +624,9 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, + + info.info.raw.rate = 0; + +- if (this->have_profile && memcmp(&this->format, &info, sizeof(info)) == 0) ++ if (this->have_profile && ++ memcmp(&this->format, &info, sizeof(info)) == 0 && ++ this->monitor == monitor) + return 0; + + spa_log_debug(this->log, "%p: port config %d/%d %d", this, +-- +GitLab + diff --git a/0001-pulse-server-show-monitor-sources-with-device_class_monitor.patch b/0001-pulse-server-show-monitor-sources-with-device_class_monitor.patch new file mode 100644 index 0000000..bde7ea3 --- /dev/null +++ b/0001-pulse-server-show-monitor-sources-with-device_class_monitor.patch @@ -0,0 +1,57 @@ +From 9eddd0474f55c4dda713511a14a1e15a4b4c685e Mon Sep 17 00:00:00 2001 +From: Pauli Virtanen +Date: Thu, 6 Jan 2022 21:27:40 +0200 +Subject: [PATCH] pulse-server: show monitor sources with device.class=monitor + +Pulseaudio shows monitors with device.class=monitor, so we follow. +--- + .../module-protocol-pulse/pulse-server.c | 25 ++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c +index 9747e5ae9..d0ebaeefd 100644 +--- a/src/modules/module-protocol-pulse/pulse-server.c ++++ b/src/modules/module-protocol-pulse/pulse-server.c +@@ -3670,6 +3670,27 @@ static int fill_sink_info(struct client *client, struct message *m, + return 0; + } + ++static int fill_source_info_proplist(struct message *m, struct pw_manager_object *o, ++ struct pw_node_info *info) ++{ ++ struct pw_properties *props = NULL; ++ struct spa_dict *props_dict = info->props; ++ ++ if (pw_manager_object_is_monitor(o)) { ++ props = pw_properties_new_dict(info->props); ++ if (props == NULL) ++ return -ENOMEM; ++ ++ pw_properties_set(props, PW_KEY_DEVICE_CLASS, "monitor"); ++ props_dict = &props->dict; ++ } ++ ++ message_put(m, TAG_PROPLIST, props_dict, TAG_INVALID); ++ pw_properties_free(props); ++ ++ return 0; ++} ++ + static int fill_source_info(struct client *client, struct message *m, + struct pw_manager_object *o) + { +@@ -3762,8 +3783,10 @@ static int fill_source_info(struct client *client, struct message *m, + TAG_INVALID); + + if (client->version >= 13) { ++ int res; ++ if ((res = fill_source_info_proplist(m, o, info)) < 0) ++ return res; + message_put(m, +- TAG_PROPLIST, info->props, + TAG_USEC, 0LL, /* requested latency */ + TAG_INVALID); + } +-- +GitLab + diff --git a/0001-pw-metadata-handle-NULL-props-from-metadata-object.patch b/0001-pw-metadata-handle-NULL-props-from-metadata-object.patch new file mode 100644 index 0000000..6b2abd4 --- /dev/null +++ b/0001-pw-metadata-handle-NULL-props-from-metadata-object.patch @@ -0,0 +1,26 @@ +From a8bafa063137c78cd191837598fae3c6c6392b68 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Tue, 18 Jan 2022 12:41:17 +0100 +Subject: [PATCH] pw-metadata: handle NULL props from metadata object + +--- + src/tools/pw-metadata.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/tools/pw-metadata.c b/src/tools/pw-metadata.c +index 97fda6744..e0aca1366 100644 +--- a/src/tools/pw-metadata.c ++++ b/src/tools/pw-metadata.c +@@ -96,7 +96,8 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions, + if (!spa_streq(type, PW_TYPE_INTERFACE_Metadata)) + return; + +- if ((str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL && ++ if (props != NULL && ++ (str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL && + !spa_streq(str, d->opt_name)) + return; + +-- +GitLab + diff --git a/0001-raop-fix-errno-check.patch b/0001-raop-fix-errno-check.patch new file mode 100644 index 0000000..388cbf5 --- /dev/null +++ b/0001-raop-fix-errno-check.patch @@ -0,0 +1,44 @@ +From 8e3eaf79528006ed7940a525aab343b3812e8b19 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Wed, 12 Jan 2022 10:08:40 +0100 +Subject: [PATCH] raop: fix errno check + +--- + src/modules/module-raop/rtsp-client.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/modules/module-raop/rtsp-client.c b/src/modules/module-raop/rtsp-client.c +index c1740ea5f..9bb888773 100644 +--- a/src/modules/module-raop/rtsp-client.c ++++ b/src/modules/module-raop/rtsp-client.c +@@ -203,9 +203,12 @@ static int read_line(struct pw_rtsp_client *client, char **buf) + if (res == 0) + return -EPIPE; + if (res < 0) { +- if (res == EAGAIN) +- return 0; +- return -errno; ++ res = -errno; ++ if (res == -EINTR) ++ continue; ++ if (res != -EAGAIN && res != -EWOULDBLOCK) ++ return res; ++ return 0; + } + if (c == '\n') { + client->line_buf[client->line_pos] = '\0'; +@@ -435,9 +438,10 @@ int pw_rtsp_client_connect(struct pw_rtsp_client *client, + true, on_source_io, client); + + if (client->source == NULL) { ++ res = -errno; + pw_log_error("%p: source create failed: %m", client); + close(fd); +- return -errno; ++ return res; + } + client->connecting = true; + free(client->session_id); +-- +GitLab + diff --git a/baselibs.conf b/baselibs.conf index c6af069..9ffb024 100644 --- a/baselibs.conf +++ b/baselibs.conf @@ -1,5 +1,14 @@ libpipewire-0_3-0 + requires "pipewire-spa-plugins-0_2- = " + requires "pipewire-modules-0_3- = " pipewire-alsa requires "libpipewire-0_3-0- = " pipewire-libjack-0_3 requires "libpipewire-0_3-0- = " +pipewire-modules-0_3 + requires "libpipewire-0_3-0- = " + provides "pipewire-modules- = " + obsoletes "pipewire-modules- < " +pipewire-spa-plugins-0_2 + requires "libpipewire-0_3-0- = " + diff --git a/pipewire.changes b/pipewire.changes index 3268797..89e9598 100644 --- a/pipewire.changes +++ b/pipewire.changes @@ -1,3 +1,46 @@ +------------------------------------------------------------------- +Wed Jan 19 16:49:42 UTC 2022 - Antonio Larrosa + +- Add several more patches from upstream +- BlueZ may be missing adapter information for devices in some cases. + Ignore devices without specified adapter: + * 0001-bluez5-dont-create-device-if-adapter-is-missing.patch +- Fix a case when pipewwire could never call callbacks or even + block forever when loop is not running: + * 0001-loop-invoke-immediately-when-loop-is-not-running.patch +- Reconfigure when monitor changes + * 0001-merger-also-reconfigure-when-monitor-changes.patch +- Handle NULL props from metadata object + * 0001-pw-metadata-handle-NULL-props-from-metadata-object.patch +- Improve rate selection so we don't select an invalid rate when + the default is set or the card is already opened in an + unsupported rate: + * 0001-alsa-improve-rate-selection.patch + +------------------------------------------------------------------- +Fri Jan 14 16:34:05 UTC 2022 - Antonio Larrosa + +- Add several patches from upstream +- Avoid an infinite loop when enumerating params of the converter: + * 0001-audioconvert-avoid-infinite-loop.patch +- When the device or adapter is NULL, skip the quirk checks instead + of crashing: + * 0001-bluez5-handle-missing-device-and-adapter-in-quirks.patch +- Remember the last returned value from jack_get_buffer_size and + only emit a buffersize change event when something new is + configured. This fixes startup of jconvolver. + * 0001-jack-remember-last-return-from-jack_get_buffer_size.patch +- Better emulation of pulseaudio which shows monitor sources with + device.class=monitor so now pipewire does that too: + * 0001-pulse-server-show-monitor-sources-with-device_class_monitor.patch +- Fix an errno check: + * 0001-raop-fix-errno-check.patch + +------------------------------------------------------------------- +Wed Jan 12 12:48:21 UTC 2022 - Antonio Larrosa + +- Added more baselibs packages and their dependencies + ------------------------------------------------------------------- Wed Jan 5 16:23:30 UTC 2022 - Bjørn Lie diff --git a/pipewire.spec b/pipewire.spec index 1c306a3..b005ba1 100644 --- a/pipewire.spec +++ b/pipewire.spec @@ -61,7 +61,16 @@ Group: Development/Libraries/C and C++ URL: https://pipewire.org/ Source0: %{name}-%{version}.tar.xz Source99: baselibs.conf - +Patch0: 0001-audioconvert-avoid-infinite-loop.patch +Patch1: 0001-bluez5-handle-missing-device-and-adapter-in-quirks.patch +Patch2: 0001-jack-remember-last-return-from-jack_get_buffer_size.patch +Patch3: 0001-pulse-server-show-monitor-sources-with-device_class_monitor.patch +Patch4: 0001-raop-fix-errno-check.patch +Patch5: 0001-bluez5-dont-create-device-if-adapter-is-missing.patch +Patch6: 0001-loop-invoke-immediately-when-loop-is-not-running.patch +Patch7: 0001-merger-also-reconfigure-when-monitor-changes.patch +Patch8: 0001-pw-metadata-handle-NULL-props-from-metadata-object.patch +Patch9: 0001-alsa-improve-rate-selection.patch BuildRequires: docutils BuildRequires: doxygen BuildRequires: fdupes