Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pipewire for openSUSE:Factory checked in at 2025-03-07 16:39:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pipewire (Old) and /work/SRC/openSUSE:Factory/.pipewire.new.19136 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pipewire" Fri Mar 7 16:39:21 2025 rev:130 rq:1250760 version:1.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/pipewire/pipewire.changes 2025-02-22 19:04:33.329798796 +0100 +++ /work/SRC/openSUSE:Factory/.pipewire.new.19136/pipewire.changes 2025-03-07 16:40:34.601359716 +0100 @@ -1,0 +2,104 @@ +Thu Mar 6 16:07:59 UTC 2025 - Antonio Larrosa <alarr...@suse.com> + +- Update to version 1.4.0 (): + * This is the 1.4 release that is API and ABI compatible with + previous 1.2.x and 1.0.x releases. + * This release contains some of the bigger changes that happened + since the 1.2 release last year, including: + - client-rt.conf was removed, all clients now use client.conf + and are given RT priority in the data threads. + - UMP (aka MIDI2) support was added and is now the default + format to carry MIDI1 and MIDI2 around in PipeWire. There + are helper functions to convert between legacy MIDI and UMP. + - The resampler can now precompute (at compile time) some + common conversion filters. Delay reporting in the resampler + was fixed and improved. + - Bluetooth support for BAP broadcast links and support for + hearing aids using ASHA was added. A new G722 codec was also + added. + - Delay reporting and configuration in Bluetooth was improved. + - The ALSA plugin now supports DSD playback when explicitly + allowed with the alsa.formats property. + - A PipeWire JACK control API was added. + - A system service was added for pipewire-pulse. + - Many documentation and translation updates. + - Many of the SPA macros are converted to inline functions. + All SPA inline functions are now also compiled into a + libspa.so library to make it easier to access them from + bindings. + - The module-filter-chain graph code was moved to a separate + filter-graph SPA plugin so that it becomes usable in more + places. EBUR128, param_eq and dcblock plugins were added to + filter-graph. The filter graph can now also use fftw for + doing convolutions. The audioconvert plugin was optimized and + support was added to audioconvert to insert extra + filter-graphs in the processing pipeline. + - New helper functions were added to parse JSON format + descriptions. + - The profiler now also includes the clock of the followers. + - RISCV CPU support and assembler optimisations were added. + - The clock used for logging timestamps can be configured now. + - The JSON parser was split into core functions and helper. + - Support for UCM split PCMs was added. Instead of alsa-lib + splitting up PCMs, PipeWire can mark the PCMs with the + correct metadata so that the session manager can use native + PipeWire features to do this. + - Support for webrtc2 was added to echo-cancel. + - IEC958 codecs are now detected from the HDMI ELD data. + - Conversion between floating point and 32 bits now preserve + 25 bits of precision instead of 24 bits. + - A new Telephony D-BUS API compatible with ofono was added. + - The invoke queues are now more efficient and can be called + from multiple threads concurrently. + - Clock information in v4l2 was improved. + - An ffmpeg based videoconvert plugin was added that can be + used with the videoadapter. + - The GStreamer elements have improved buffer pool handling + and rate matching. + - The combine-stream module can now also mix streams. + - link-factory now checks that the port and node belong + together. + - The netjack-manager module has support for autoconnecting + streams. + - The native-protocol has support for abstract sockets. + - The pulse server has support for blocking playback and + capture in pulse.rules. + - The corked state of stream is now reported correctly in + pulse-server. + - Fix backwards jumps in pulse-server. + - Latency configuration support was added in loopback and + raop-sink. + - The ROC module has more configuration options. + - The SAP module now only send updated SDP when something + changed. + - RTP source now has a standby mode where it idles when there + is no data received. + - Support for PTP clocking was added the RTP streams. + - The VBAN receiver can now dynamically create streams when + they are detected. + - Error reporting when making links was improved. + - Support for returning (canceling) a dequeued buffer in + pw-stream. + - Support for emiting events in pw-stream was added. + - pw-cat now support stdin and stdout. + * Highlights (since the previous 1.3.83 release) + - Small fixes and improvements. + * PipeWire + - Fix some missing includes in metadata.h + - Pass the current error in errno when a stream is in error + (#4574) + * modules + - Evaluate node rules before loading adapter follower to ensure + properties are set correctly. (#4562) + * SPA + - Avoid a use after free when building PODs. (#4445) + - Take headroom into account when calculating resync. + * Bluetooth + - Fix +CLCC parsing. + * GStreamer + - Notify about default device changes in deviceprovider. + - Copy frames between pools and avoid splitting video buffers. + * JACK + - Add an option to disable the MIDI2 port flags. (#4584) + +------------------------------------------------------------------- Old: ---- pipewire-1.3.83.obscpio New: ---- pipewire-1.4.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pipewire.spec ++++++ --- /var/tmp/diff_new_pack.bxQ3R7/_old 2025-03-07 16:40:35.325390013 +0100 +++ /var/tmp/diff_new_pack.bxQ3R7/_new 2025-03-07 16:40:35.329390181 +0100 @@ -69,7 +69,7 @@ %bcond_with aptx Name: pipewire -Version: 1.3.83 +Version: 1.4.0 Release: 0 Summary: A Multimedia Framework designed to be an audio and video server and more License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.bxQ3R7/_old 2025-03-07 16:40:35.361391520 +0100 +++ /var/tmp/diff_new_pack.bxQ3R7/_new 2025-03-07 16:40:35.365391687 +0100 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gitlab.freedesktop.org/pipewire/pipewire.git</param> - <param name="revision">1.3.83</param> + <param name="revision">1.4.0</param> <param name="versionformat">@PARENT_TAG@</param> <!-- <param name="revision">60deeb25558a794e6e664bb832318b87958c18ea</param> ++++++ pipewire-1.3.83.obscpio -> pipewire-1.4.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/NEWS new/pipewire-1.4.0/NEWS --- old/pipewire-1.3.83/NEWS 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/NEWS 2025-03-06 13:11:38.000000000 +0100 @@ -1,3 +1,107 @@ +# PipeWire 1.4.0 (2025-03-06) + +This is the 1.4 release that is API and ABI compatible with previous +1.2.x and 1.0.x releases. + +This release contains some of the bigger changes that happened since +the 1.2 release last year, including: + + * client-rt.conf was removed, all clients now use client.conf and + are given RT priority in the data threads. + * UMP (aka MIDI2) support was added and is now the default format + to carry MIDI1 and MIDI2 around in PipeWire. There are helper + functions to convert between legacy MIDI and UMP. + * The resampler can now precompute (at compile time) some common + conversion filters. Delay reporting in the resampler was fixed and + improved. + * Bluetooth support for BAP broadcast links and support for hearing aids + using ASHA was added. A new G722 codec was also added. + Delay reporting and configuration in Bluetooth was improved. + * The ALSA plugin now supports DSD playback when explicitly allowed + with the alsa.formats property. + * A PipeWire JACK control API was added. + * A system service was added for pipewire-pulse. + * Many documentation and translation updates. + * Many of the SPA macros are converted to inline functions. All SPA + inline functions are now also compiled into a libspa.so library to + make it easier to access them from bindings. + * The module-filter-chain graph code was moved to a separate + filter-graph SPA plugin so that it becomes usable in more places. + EBUR128, param_eq and dcblock plugins were added to filter-graph. + The filter graph can now also use fftw for doing convolutions. + The audioconvert plugin was optimized and support was added to + audioconvert to insert extra filter-graphs in the processing pipeline. + * New helper functions were added to parse JSON format descriptions. + * The profiler now also includes the clock of the followers. + * RISCV CPU support and assembler optimisations were added. + * The clock used for logging timestamps can be configured now. + * The JSON parser was split into core functions and helper. + * Support for UCM split PCMs was added. Instead of alsa-lib splitting + up PCMs, PipeWire can mark the PCMs with the correct metadata so that + the session manager can use native PipeWire features to do this. + * Support for webrtc2 was added to echo-cancel. + * IEC958 codecs are now detected from the HDMI ELD data. + * Conversion between floating point and 32 bits now preserve 25 bits of + precision instead of 24 bits. + * A new Telephony D-BUS API compatible with ofono was added. + * The invoke queues are now more efficient and can be called from multiple + threads concurrently. + * Clock information in v4l2 was improved. + * An ffmpeg based videoconvert plugin was added that can be used with the + videoadapter. + * The GStreamer elements have improved buffer pool handling and rate + matching. + * The combine-stream module can now also mix streams. + * link-factory now checks that the port and node belong together. + * The netjack-manager module has support for autoconnecting streams. + * The native-protocol has support for abstract sockets. + * The pulse server has support for blocking playback and capture in + pulse.rules. + * The corked state of stream is now reported correctly in pulse-server. + * Fix backwards jumps in pulse-server. + * Latency configuration support was added in loopback and raop-sink. + * The ROC module has more configuration options. + * The SAP module now only send updated SDP when something changed. + * RTP source now has a standby mode where it idles when there is no + data received. + * Support for PTP clocking was added the RTP streams. + * The VBAN receiver can now dynamically create streams when they are + detected. + * Error reporting when making links was improved. + * Support for returning (canceling) a dequeued buffer in pw-stream. + * Support for emiting events in pw-stream was added. + * pw-cat now support stdin and stdout. + + +## Highlights (since the previous 1.3.83 release) + - Small fixes and improvements. + +## PipeWire + - Fix some missing includes in metadata.h + - Pass the current error in errno when a stream is in error (#4574) + + +## modules + - Evaluate node rules before loading adapter follower to ensure + properties are set correctly. (#4562) + +## SPA + - Avoid a use after free when building PODs. (#4445) + - Take headroom into account when calculating resync. + +## Bluetooth + - Fix +CLCC parsing. + +## GStreamer + - Notify about default device changes in deviceprovider. + - Copy frames between pools and avoid splitting video buffers. + +## JACK + - Add an option to disable the MIDI2 port flags. (#4584) + + +Older versions: + # PipeWire 1.3.83 (2025-02-20) This is the third and hopefully last 1.4 release candidate that @@ -43,9 +147,6 @@ - Specify the bluetooth source latency property in the rate of the stream to avoid conversions and rounding errors. - -Older versions: - # PipeWire 1.3.82 (2025-02-06) This is the second 1.4 release candidate that is API and ABI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/doc/dox/config/pipewire-jack.conf.5.md new/pipewire-1.4.0/doc/dox/config/pipewire-jack.conf.5.md --- old/pipewire-1.3.83/doc/dox/config/pipewire-jack.conf.5.md 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/doc/dox/config/pipewire-jack.conf.5.md 2025-03-06 13:11:38.000000000 +0100 @@ -70,7 +70,7 @@ #jack.max-client-ports = 768 #jack.fill-aliases = false #jack.writable-input = false - + #jack.flag-midi2 = false } ``` @@ -198,6 +198,14 @@ Set this to true to avoid buffer corruption if you are only dealing with non-buggy clients. \endparblock +@PAR@ jack.conf jack.flag-midi2 +\parblock +Use the new JACK MIDI2 port flag on MIDI2 (UMP) ports. This is disabled by default because most +JACK apps don't know about this flag yet and refuse to show the port. + +Set this to true for applications that know how to handle MIDI2 ports. +\endparblock + # MATCH RULES @IDX@ jack.conf `jack.rules` provides an `update-props` action that takes an object with properties that are updated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/meson.build new/pipewire-1.4.0/meson.build --- old/pipewire-1.3.83/meson.build 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/meson.build 2025-03-06 13:11:38.000000000 +0100 @@ -1,5 +1,5 @@ project('pipewire', ['c' ], - version : '1.3.83', + version : '1.4.0', license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ], meson_version : '>= 0.61.1', default_options : [ 'warning_level=3', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/pipewire-alsa/alsa-plugins/pcm_pipewire.c new/pipewire-1.4.0/pipewire-alsa/alsa-plugins/pcm_pipewire.c --- old/pipewire-1.3.83/pipewire-alsa/alsa-plugins/pcm_pipewire.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/pipewire-alsa/alsa-plugins/pcm_pipewire.c 2025-03-06 13:11:38.000000000 +0100 @@ -391,7 +391,7 @@ if (state == PW_STREAM_STATE_ERROR) { pw_log_warn("%s", error); - pw->error = -EIO; + pw->error = -errno; update_active(&pw->io); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/pipewire-jack/src/pipewire-jack.c new/pipewire-1.4.0/pipewire-jack/src/pipewire-jack.c --- old/pipewire-1.3.83/pipewire-jack/src/pipewire-jack.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/pipewire-jack/src/pipewire-jack.c 2025-03-06 13:11:38.000000000 +0100 @@ -472,6 +472,7 @@ unsigned int fill_aliases:1; unsigned int writable_input:1; unsigned int async:1; + unsigned int flag_midi2:1; uint32_t max_frames; uint32_t max_align; @@ -3818,7 +3819,7 @@ if ((str = spa_dict_lookup(props, PW_KEY_PORT_NAME)) == NULL) goto exit; - if (type_id == TYPE_ID_UMP) + if (type_id == TYPE_ID_UMP && c->flag_midi2) flags |= JackPortIsMIDI2; spa_dict_for_each(item, props) { @@ -4400,6 +4401,7 @@ client->fill_aliases = pw_properties_get_bool(client->props, "jack.fill-aliases", false); client->writable_input = pw_properties_get_bool(client->props, "jack.writable-input", true); client->async = pw_properties_get_bool(client->props, PW_KEY_NODE_ASYNC, false); + client->flag_midi2 = pw_properties_get_bool(client->props, "jack.flag-midi2", false); client->self_connect_mode = SELF_CONNECT_ALLOW; if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/pipewire-v4l2/src/pipewire-v4l2.c new/pipewire-1.4.0/pipewire-v4l2/src/pipewire-v4l2.c --- old/pipewire-1.3.83/pipewire-v4l2/src/pipewire-v4l2.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/pipewire-v4l2/src/pipewire-v4l2.c 2025-03-06 13:11:38.000000000 +0100 @@ -1696,7 +1696,7 @@ break; if (state == PW_STREAM_STATE_ERROR) { - res = -EIO; + res = -errno; goto exit; } if (file->error < 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/spa/include/spa/monitor/device.h new/pipewire-1.4.0/spa/include/spa/monitor/device.h --- old/pipewire-1.3.83/spa/include/spa/monitor/device.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/spa/include/spa/monitor/device.h 2025-03-06 13:11:38.000000000 +0100 @@ -293,7 +293,7 @@ * "webcam", "microphone", "headset", * "headphone", "hands-free", "car", "hifi", * "computer", "portable" */ -#define SPA_KEY_DEVICE_PROFILE "device.profile " /**< profile for the device */ +#define SPA_KEY_DEVICE_PROFILE "device.profile" /**< profile for the device */ #define SPA_KEY_DEVICE_PROFILE_SET "device.profile-set" /**< profile set for the device */ #define SPA_KEY_DEVICE_STRING "device.string" /**< device string in the underlying * layer's format. E.g. "surround51:0" */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/spa/include/spa/pod/builder.h new/pipewire-1.4.0/spa/include/spa/pod/builder.h --- old/pipewire-1.3.83/spa/include/spa/pod/builder.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/spa/include/spa/pod/builder.h 2025-03-06 13:11:38.000000000 +0100 @@ -128,16 +128,25 @@ int res = 0; struct spa_pod_frame *f; uint32_t offset = builder->state.offset; + size_t data_offset = -1; if (offset + size > builder->size) { + /* data could be inside the data we will realloc */ + if (spa_ptrinside(builder->data, builder->size, data, size, NULL)) + data_offset = SPA_PTRDIFF(data, builder->data); + res = -ENOSPC; if (offset <= builder->size) spa_callbacks_call_res(&builder->callbacks, struct spa_pod_builder_callbacks, res, overflow, 0, offset + size); } - if (res == 0 && data) + if (res == 0 && data) { + if (data_offset != (size_t) -1) + data = SPA_PTROFF(builder->data, data_offset, const void); + memcpy(SPA_PTROFF(builder->data, offset, void), data, size); + } builder->state.offset += size; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/spa/plugins/alsa/alsa-pcm.c new/pipewire-1.4.0/spa/plugins/alsa/alsa-pcm.c --- old/pipewire-1.3.83/spa/plugins/alsa/alsa-pcm.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/spa/plugins/alsa/alsa-pcm.c 2025-03-06 13:11:38.000000000 +0100 @@ -2844,10 +2844,10 @@ bw = (fabs(state->err_avg) + sqrt(fabs(state->err_var)))/1000.0; spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f " - "bw:%f thr:%u del:%ld target:%ld err:%f max:%f var:%f:%f:%f", + "bw:%f thr:%u del:%ld target:%ld err:%f max_err:%f max_resync: %f var:%f:%f:%f", state->name, follower, state->matching, corr, state->dll.bw, state->threshold, delay, target, - err, state->max_error, state->err_avg, state->err_var, bw); + err, state->max_error, state->max_resync, state->err_avg, state->err_var, bw); spa_dll_set_bw(&state->dll, SPA_CLAMPD(bw, 0.001, SPA_DLL_BW_MAX), @@ -2954,8 +2954,8 @@ state->driver_duration = target_duration; state->driver_rate = target_rate; state->threshold = SPA_SCALE32_UP(state->driver_duration, state->rate, state->driver_rate.denom); - state->max_error = SPA_MAX(256.0f, state->threshold / 2.0f); - state->max_resync = SPA_MIN(state->threshold, state->max_error); + state->max_error = SPA_MAX(256.0f, (state->threshold + state->headroom) / 2.0f); + state->max_resync = SPA_MIN(state->threshold + state->headroom, state->max_error); state->err_wdw = (double)state->driver_rate.denom/state->driver_duration; state->resample = !state->pitch_elem && (((uint32_t)state->rate != state->driver_rate.denom) || state->matching); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/spa/plugins/bluez5/backend-native.c new/pipewire-1.4.0/spa/plugins/bluez5/backend-native.c --- old/pipewire-1.3.83/spa/plugins/bluez5/backend-native.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/spa/plugins/bluez5/backend-native.c 2025-03-06 13:11:38.000000000 +0100 @@ -2149,6 +2149,8 @@ unsigned int status, mpty; bool parsed = false, found = false; + number[0] = '\0'; + token[strcspn(token, "\r")] = 0; token[strcspn(token, "\n")] = 0; token_end = token + strlen(token); @@ -2181,13 +2183,13 @@ token[pos] = '\0'; mpty = atoi(token); token += pos + 1; + parsed = true; } if (token < token_end) { if (sscanf(token, "\"%16[^\"]\",%u", number, &type) != 2) { spa_log_warn(backend->log, "Failed to parse number: %s", token); number[0] = '\0'; } - parsed = true; } if (SPA_LIKELY (parsed)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/daemon/jack.conf.in new/pipewire-1.4.0/src/daemon/jack.conf.in --- old/pipewire-1.3.83/src/daemon/jack.conf.in 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/daemon/jack.conf.in 2025-03-06 13:11:38.000000000 +0100 @@ -95,6 +95,7 @@ #jack.max-client-ports = 768 #jack.fill-aliases = false #jack.writable-input = true + #jack.flag-midi2 = false } # client specific properties diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/gst/gstpipewiredeviceprovider.c new/pipewire-1.4.0/src/gst/gstpipewiredeviceprovider.c --- old/pipewire-1.3.83/src/gst/gstpipewiredeviceprovider.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/gst/gstpipewiredeviceprovider.c 2025-03-06 13:11:38.000000000 +0100 @@ -204,6 +204,28 @@ return NULL; } +static GstPipeWireDevice * +gst_pipewire_device_new (int fd, uint32_t id, uint64_t serial, + GstPipeWireDeviceType type, const gchar * element, int priority, + const gchar * klass, const gchar * display_name, const GstCaps * caps, + const GstStructure * props) +{ + GstPipeWireDevice *gstdev; + + gstdev = + g_object_new (GST_TYPE_PIPEWIRE_DEVICE, "display-name", display_name, + "caps", caps, "device-class", klass, "id", id, "serial", serial, "fd", fd, + "properties", props, NULL); + + gstdev->id = id; + gstdev->serial = serial; + gstdev->type = type; + gstdev->element = element; + gstdev->priority = priority; + + return gstdev; +} + static GstDevice * new_node (GstPipeWireDeviceProvider *self, struct node_data *data) { @@ -255,16 +277,8 @@ if (name == NULL) name = "unknown"; - gstdev = g_object_new (GST_TYPE_PIPEWIRE_DEVICE, - "display-name", name, "caps", data->caps, "device-class", klass, - "id", data->id, "serial", data->serial, "fd", self->fd, - "properties", props, NULL); - - gstdev->id = data->id; - gstdev->serial = data->serial; - gstdev->type = type; - gstdev->element = element; - gstdev->priority = priority; + gstdev = gst_pipewire_device_new (self->fd, data->id, data->serial, type, + element, priority, klass, name, data->caps, props); if (props) gst_structure_free (props); @@ -510,6 +524,87 @@ .destroy = destroy_port, }; +static gboolean +is_default_device_name (GstPipeWireDeviceProvider * self, + const gchar * name, const gchar * klass, GstPipeWireDeviceType type) +{ + gboolean ret = FALSE; + + GST_OBJECT_LOCK (self); + switch (type) { + case GST_PIPEWIRE_DEVICE_TYPE_SINK: + if (g_str_has_prefix (klass, "Audio")) + ret = !g_strcmp0 (name, self->default_audio_sink_name); + break; + case GST_PIPEWIRE_DEVICE_TYPE_SOURCE: + if (g_str_has_prefix (klass, "Audio")) + ret = !g_strcmp0 (name, self->default_audio_source_name); + else if (g_str_has_prefix (klass, "Video")) + ret = !g_strcmp0 (name, self->default_video_source_name); + break; + default: + GST_ERROR_OBJECT (self, "Unknown pipewire device type!"); + break; + } + GST_OBJECT_UNLOCK (self); + + return ret; +} + +static void +sync_default_devices (GstPipeWireDeviceProvider * self) +{ + GList *tmp, *devices = NULL; + + for (tmp = GST_DEVICE_PROVIDER_CAST (self)->devices; tmp; tmp = tmp->next) + devices = g_list_prepend (devices, gst_object_ref (tmp->data)); + + for (tmp = devices; tmp; tmp = tmp->next) { + GstPipeWireDevice *dev = tmp->data; + GstStructure *props = gst_device_get_properties (GST_DEVICE_CAST (dev)); + gboolean was_default = FALSE, is_default = FALSE; + const gchar *name; + gchar *klass = gst_device_get_device_class (GST_DEVICE_CAST (dev)); + + g_assert (props); + gst_structure_get_boolean (props, "is-default", &was_default); + name = gst_structure_get_string (props, "node.name"); + + switch (dev->type) { + case GST_PIPEWIRE_DEVICE_TYPE_SINK: + is_default = + is_default_device_name (self, name, klass, dev->type); + break; + case GST_PIPEWIRE_DEVICE_TYPE_SOURCE: + is_default = + is_default_device_name (self, name, klass, dev->type); + break; + case GST_PIPEWIRE_DEVICE_TYPE_UNKNOWN: + break; + } + + if (was_default != is_default) { + GstPipeWireDevice *updated_device; + gchar *display_name = gst_device_get_display_name (GST_DEVICE_CAST (dev)); + GstCaps *caps = gst_device_get_caps (GST_DEVICE_CAST (dev)); + + gst_structure_set (props, "is-default", G_TYPE_BOOLEAN, is_default, NULL); + updated_device = + gst_pipewire_device_new (self->fd, dev->id, dev->serial, dev->type, + dev->element, dev->priority, klass, display_name, caps, props); + + gst_device_provider_device_changed (GST_DEVICE_PROVIDER_CAST (self), + GST_DEVICE_CAST (updated_device), GST_DEVICE_CAST (dev)); + + g_free (display_name); + gst_caps_unref (caps); + } + gst_structure_free (props); + g_free (klass); + } + g_list_free_full (devices, gst_object_unref); +} + static int metadata_property(void *data, uint32_t id, const char *key, const char *type, const char *value) { GstPipeWireDeviceProvider *self = data; @@ -525,7 +620,7 @@ g_free(self->default_audio_source_name); if (spa_json_str_object_find(value, strlen(value), "name", name, sizeof(name)) >= 0) self->default_audio_source_name = g_strdup(name); - return 0; + goto sync_devices; } if (spa_streq(key, "default.audio.sink")) { if (!spa_streq(type, "Spa:String:JSON")) @@ -534,7 +629,7 @@ g_free(self->default_audio_sink_name); if (spa_json_str_object_find(value, strlen(value), "name", name, sizeof(name)) >= 0) self->default_audio_sink_name = g_strdup(name); - return 0; + goto sync_devices; } if (spa_streq(key, "default.video.source")) { if (!spa_streq(type, "Spa:String:JSON")) @@ -543,10 +638,14 @@ g_free(self->default_video_source_name); if (spa_json_str_object_find(value, strlen(value), "name", name, sizeof(name)) >= 0) self->default_video_source_name = g_strdup(name); - return 0; + goto sync_devices; } return 0; + + sync_devices: + sync_default_devices (self); + return 0; } static const struct pw_metadata_events metadata_events = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/gst/gstpipewiresink.c new/pipewire-1.4.0/src/gst/gstpipewiresink.c --- old/pipewire-1.3.83/src/gst/gstpipewiresink.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/gst/gstpipewiresink.c 2025-03-06 13:11:38.000000000 +0100 @@ -356,6 +356,7 @@ sink->mode = DEFAULT_PROP_MODE; sink->use_bufferpool = DEFAULT_PROP_USE_BUFFERPOOL; + sink->is_video = false; GST_OBJECT_FLAG_SET (sink, GST_ELEMENT_FLAG_PROVIDE_CLOCK); @@ -366,12 +367,14 @@ gst_pipewire_sink_sink_fixate (GstBaseSink * bsink, GstCaps * caps) { GstStructure *structure; + GstPipeWireSink *pwsink = GST_PIPEWIRE_SINK(bsink); caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw")) { + pwsink->is_video = true; gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "height", 240); gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); @@ -755,6 +758,7 @@ } else { pwsink->rate = rate = 0; pwsink->rate_match = false; + pwsink->is_video = true; } spa_dll_set_bw(&pwsink->stream->dll, SPA_DLL_BW_MIN, 4096, rate); @@ -834,6 +838,8 @@ config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pwsink->stream->pool)); gst_buffer_pool_config_get_params (config, NULL, &size, &min_buffers, &max_buffers); gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); + if(pwsink->is_video) + gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pwsink->stream->pool), config); pw_thread_loop_unlock (pwsink->stream->core->loop); @@ -891,6 +897,8 @@ gsize offset = 0; gsize buf_size = gst_buffer_get_size (buffer); + GST_TRACE_OBJECT(pwsink, "Buffer is not from pipewirepool, copying into our pool"); + /* For some streams, the buffer size is changed and may exceed the acquired * buffer size which is acquired from the pool of pipewiresink. Need split * the buffer and send them in turn for this case */ @@ -913,14 +921,51 @@ if (res != GST_FLOW_OK) goto done; - gst_buffer_map (b, &info, GST_MAP_WRITE); - gsize extract_size = (buf_size <= info.maxsize) ? buf_size: info.maxsize; - gst_buffer_extract (buffer, offset, info.data, info.maxsize); - gst_buffer_unmap (b, &info); - gst_buffer_resize (b, 0, extract_size); - gst_buffer_copy_into(b, buffer, GST_BUFFER_COPY_METADATA, 0, -1); - buf_size -= extract_size; - offset += extract_size; + if (pwsink->is_video) { + GstVideoFrame src, dst; + gboolean copied = FALSE; + buf_size = 0; // to break from the loop + + /* + splitting of buffers in the case of video might break the frame layout + and that seems to be causing issues while retrieving the buffers on the receiver + side. Hence use the video_frame_map to copy the buffer of bigger size into the + pipewirepool's buffer + */ + + if (!gst_video_frame_map (&dst, &pwsink->stream->pool->video_info, b, + GST_MAP_WRITE)) { + GST_ERROR_OBJECT(pwsink, "Failed to map dest buffer"); + return GST_FLOW_ERROR; + } + + if (!gst_video_frame_map (&src, &pwsink->stream->pool->video_info, buffer, GST_MAP_READ)) { + gst_video_frame_unmap (&dst); + GST_ERROR_OBJECT(pwsink, "Failed to map src buffer"); + return GST_FLOW_ERROR; + } + + copied = gst_video_frame_copy (&dst, &src); + + gst_video_frame_unmap (&src); + gst_video_frame_unmap (&dst); + + if (!copied) { + GST_ERROR_OBJECT(pwsink, "Failed to copy the frame"); + return GST_FLOW_ERROR; + } + + gst_buffer_copy_into(b, buffer, GST_BUFFER_COPY_METADATA, 0, -1); + } else { + gst_buffer_map (b, &info, GST_MAP_WRITE); + gsize extract_size = (buf_size <= info.maxsize) ? buf_size: info.maxsize; + gst_buffer_extract (buffer, offset, info.data, info.maxsize); + gst_buffer_unmap (b, &info); + gst_buffer_resize (b, 0, extract_size); + gst_buffer_copy_into(b, buffer, GST_BUFFER_COPY_METADATA, 0, -1); + buf_size -= extract_size; + offset += extract_size; + } pw_thread_loop_lock (pwsink->stream->core->loop); if (pw_stream_get_state (pwsink->stream->pwstream, &error) != PW_STREAM_STATE_STREAMING) { @@ -935,6 +980,8 @@ pw_stream_trigger_process (pwsink->stream->pwstream); } } else { + GST_TRACE_OBJECT(pwsink, "Buffer is from pipewirepool"); + do_send_buffer (pwsink, buffer); if (pw_stream_is_driving (pwsink->stream->pwstream)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/gst/gstpipewiresink.h new/pipewire-1.4.0/src/gst/gstpipewiresink.h --- old/pipewire-1.3.83/src/gst/gstpipewiresink.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/gst/gstpipewiresink.h 2025-03-06 13:11:38.000000000 +0100 @@ -69,6 +69,7 @@ gboolean negotiated; gboolean rate_match; gint rate; + gboolean is_video; GstPipeWireSinkMode mode; GstPipeWireSinkSlaveMethod slave_method; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/modules/module-adapter.c new/pipewire-1.4.0/src/modules/module-adapter.c --- old/pipewire-1.3.83/src/modules/module-adapter.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/modules/module-adapter.c 2025-03-06 13:11:38.000000000 +0100 @@ -147,6 +147,22 @@ .initialized = node_initialized, }; +struct match { + struct pw_properties *props; + int count; +}; +#define MATCH_INIT(p) ((struct match){ .props = (p) }) + +static int execute_match(void *data, const char *location, const char *action, + const char *val, size_t len) +{ + struct match *match = data; + if (spa_streq(action, "update-props")) { + match->count += pw_properties_update_string(match->props, val, len); + } + return 1; +} + static void *create_object(void *_data, struct pw_resource *resource, const char *type, @@ -197,14 +213,20 @@ if (sscanf(str, "pointer:%p", &spa_follower) != 1) goto error_properties; } + if (spa_follower == NULL) { void *iface; const char *factory_name; + struct match match; factory_name = pw_properties_get(properties, SPA_KEY_FACTORY_NAME); if (factory_name == NULL) goto error_properties; + match = MATCH_INIT(properties); + pw_context_conf_section_match_rules(d->context, "node.rules", + &properties->dict, execute_match, &match); + handle = pw_context_load_spa_handle(d->context, factory_name, &properties->dict); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/modules/module-protocol-pulse/pulse-server.c new/pipewire-1.4.0/src/modules/module-protocol-pulse/pulse-server.c --- old/pipewire-1.3.83/src/modules/module-protocol-pulse/pulse-server.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/modules/module-protocol-pulse/pulse-server.c 2025-03-06 13:11:38.000000000 +0100 @@ -1109,7 +1109,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/pipewire/extensions/metadata.h new/pipewire-1.4.0/src/pipewire/extensions/metadata.h --- old/pipewire-1.3.83/src/pipewire/extensions/metadata.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/pipewire/extensions/metadata.h 2025-03-06 13:11:38.000000000 +0100 @@ -10,6 +10,9 @@ #endif #include <spa/utils/defs.h> +#include <spa/utils/hook.h> + +#include <errno.h> /** \defgroup pw_metadata Metadata * Metadata interface diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/pipewire/filter.c new/pipewire-1.4.0/src/pipewire/filter.c --- old/pipewire-1.3.83/src/pipewire/filter.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/pipewire/filter.c 2025-03-06 13:11:38.000000000 +0100 @@ -407,8 +407,10 @@ 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_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 @@ { if (error) *error = filter->error; + if (filter->state == PW_FILTER_STATE_ERROR) + errno = -filter->error_res; return filter->state; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/pipewire/filter.h new/pipewire-1.4.0/src/pipewire/filter.h --- old/pipewire-1.3.83/src/pipewire/filter.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/pipewire/filter.h 2025-03-06 13:11:38.000000000 +0100 @@ -62,7 +62,8 @@ 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 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/pipewire/stream.c new/pipewire-1.4.0/src/pipewire/stream.c --- old/pipewire-1.3.83/src/pipewire/stream.c 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/pipewire/stream.c 2025-03-06 13:11:38.000000000 +0100 @@ -400,8 +400,10 @@ 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_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 @@ { if (error) *error = stream->error; + if (stream->state == PW_STREAM_STATE_ERROR) + errno = -stream->error_res; return stream->state; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.3.83/src/pipewire/stream.h new/pipewire-1.4.0/src/pipewire/stream.h --- old/pipewire-1.3.83/src/pipewire/stream.h 2025-02-20 15:19:41.000000000 +0100 +++ new/pipewire-1.4.0/src/pipewire/stream.h 2025-03-06 13:11:38.000000000 +0100 @@ -412,7 +412,8 @@ 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 @@ 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); ++++++ pipewire.obsinfo ++++++ --- /var/tmp/diff_new_pack.bxQ3R7/_old 2025-03-07 16:40:36.013418804 +0100 +++ /var/tmp/diff_new_pack.bxQ3R7/_new 2025-03-07 16:40:36.017418971 +0100 @@ -1,5 +1,5 @@ name: pipewire -version: 1.3.83 -mtime: 1740061181 -commit: e67c1bc73452274da1a91a1fa62984d5e151b5a7 +version: 1.4.0 +mtime: 1741263098 +commit: df1c36aec2aaf9e2eb1596b6b55e72c15fb2088a