Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pipewire for openSUSE:Factory checked in at 2026-10-27 16:46:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pipewire (Old) and /work/SRC/openSUSE:Factory/.pipewire.new.2252680 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pipewire" Tue Oct 27 16:46:25 2026 rev:164 rq:1392726 version:1.6.10 Changes: -------- --- /work/SRC/openSUSE:Factory/pipewire/pipewire.changes 2026-10-21 20:51:45.242545410 +0200 +++ /work/SRC/openSUSE:Factory/.pipewire.new.2252680/pipewire.changes 2026-10-27 16:46:29.899288353 +0100 @@ -1,0 +2,45 @@ +Mon Oct 26 12:04:02 UTC 2026 - Antonio Larrosa <[email protected]> + +- Update to version 1.6.10: + * This is a bugfix release that is API and ABI compatible with + the previous 1.6.x releases. + * Highlights + - Fix some potential crashes in the JACK layer. + - Fix a regression in the PSD rear delay upmixing code. + - Avoid pops and clicks when playing unsigned formats. + - More small fixes and backports. + * PipeWire + - Initialize the error location in all cases when parsing + properties. + - Don't try to unlink ports without a node. (#5540 (closed)) + * Modules + - Fix a potential crash in the X11 module because error + handlers can be called twice. + * SPA + - Fix a regression in the PSD rear delay upmixing code. A delay + of 0 was not working and would result in a big delay instead. + (#5490 (closed)) + - Use per audio format clear function to avoid pops when + draining on unsigned formats. (#5531 (closed)) + * Pulse-server + - Avoid queueing an unlimited amount of REQUEST commands for + paused clients in some cases. (#5541 (closed)) + * Bluetooth + - Remove some old deprecated functions. + - cancel RegisterApplication calls when adapter goes away. + (#5096 (closed)) + * JACK + - Add locking around the port array and mixer list. + (#5499 (closed)) + - Avoid possible infinite loop. + - Free port and buffers before disconnect. (#5455) + * GStreamer + - Set the plane strides and offsets correctly. + - Avoid setting invalid max resolution values. + * ALSA Plugin + - Handle the XRUN case better. (#5524 (closed)) + * Tools + - Support more output formats by letting sndfile choose the + byte order. + +------------------------------------------------------------------- Old: ---- pipewire-1.6.9.tar.xz New: ---- pipewire-1.6.10.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pipewire.spec ++++++ --- /var/tmp/diff_new_pack.gvKCYT/_old 2026-10-27 16:46:31.063337111 +0100 +++ /var/tmp/diff_new_pack.gvKCYT/_new 2026-10-27 16:46:31.064337152 +0100 @@ -75,7 +75,7 @@ %endif Name: pipewire -Version: 1.6.9 +Version: 1.6.10 Release: 0 Summary: A Multimedia Framework designed to be an audio and video server and more License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.gvKCYT/_old 2026-10-27 16:46:31.110339079 +0100 +++ /var/tmp/diff_new_pack.gvKCYT/_new 2026-10-27 16:46:31.114339247 +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.6.9</param> + <param name="revision">1.6.10</param> <param name="versionformat">@PARENT_TAG@</param> <!-- <param name="revision">636cbae9b6cebc4ba55903e2a686f4c4a2bd4193</param> ++++++ pipewire-1.6.9.tar.xz -> pipewire-1.6.10.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/NEWS new/pipewire-1.6.10/NEWS --- old/pipewire-1.6.9/NEWS 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/NEWS 2026-10-22 18:00:36.000000000 +0200 @@ -1,3 +1,54 @@ +# PipeWire 1.6.10 (2026-10-22) + +This is a bugfix release that is API and ABI compatible with the previous +1.6.x releases. + +## Highlights + - Fix some potential crashes in the JACK layer. + - Fix a regression in the PSD rear delay upmixing code. + - Avoid pops and clicks when playing unsigned formats. + - More small fixes and backports. + +## PipeWire + - Initialize the error location in all cases when parsing properties. + - Don't try to unlink ports without a node. (#5540) + +## Modules + - Fix a potential crash in the X11 module because error handlers can be + called twice. + +## SPA + - Fix a regression in the PSD rear delay upmixing code. A delay of 0 + was not working and would result in a big delay instead. (#5490) + - Use per audio format clear function to avoid pops when draining on + unsigned formats. (#5531) + +## Pulse-server + - Avoid queueing an unlimited amount of REQUEST commands for paused + clients in some cases. (#5541) + +## Bluetooth + - Remove some old deprecated functions. + - cancel `RegisterApplication` calls when adapter goes away. (#5096) + +## JACK + - Add locking around the port array and mixer list. (#5499) + - Avoid possible infinite loop. + - Free port and buffers before disconnect. (#5455) + +## GStreamer + - Set the plane strides and offsets correctly. + - Avoid setting invalid max resolution values. + +## ALSA Plugin + - Handle the XRUN case better. (#5524) + +## Tools + - Support more output formats by letting sndfile choose the byte order. + + +Older versions: + # PipeWire 1.6.9 (2026-09-17) This is a bugfix release that is API and ABI compatible with the previous @@ -56,8 +107,6 @@ - Fix mp3 encoding in pw-record. - Support A-law in pw-record. -Older versions: - # PipeWire 1.6.8 (2026-07-09) This is a bugfix release that is API and ABI compatible with the previous diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/meson.build new/pipewire-1.6.10/meson.build --- old/pipewire-1.6.9/meson.build 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/meson.build 2026-10-22 18:00:36.000000000 +0200 @@ -1,5 +1,5 @@ project('pipewire', ['c' ], - version : '1.6.9', + version : '1.6.10', license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ], meson_version : '>= 0.61.1', default_options : [ 'warning_level=3', @@ -412,7 +412,7 @@ 'gio-unix-2.0': {}, 'gstreamer-1.0': {'version': '>= 1.10.0'}, 'gstreamer-base-1.0': {}, - 'gstreamer-video-1.0': {}, + 'gstreamer-video-1.0': {'version': '>= 1.22.0'}, 'gstreamer-audio-1.0': {}, 'gstreamer-allocators-1.0': {}, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/pipewire-alsa/alsa-plugins/pcm_pipewire.c new/pipewire-1.6.10/pipewire-alsa/alsa-plugins/pcm_pipewire.c --- old/pipewire-1.6.9/pipewire-alsa/alsa-plugins/pcm_pipewire.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/pipewire-alsa/alsa-plugins/pcm_pipewire.c 2026-10-22 18:00:36.000000000 +0200 @@ -52,7 +52,6 @@ unsigned int activated:1; /* PipeWire is activated? */ unsigned int drained:1; unsigned int draining:1; - unsigned int xrun_detected:1; unsigned int hw_params_changed:1; unsigned int negotiated:1; @@ -98,7 +97,7 @@ if (pw->error > 0 || force_wakeup || io->state == SND_PCM_STATE_SETUP || - pw->xrun_detected) { + io->state == SND_PCM_STATE_XRUN) { active = true; } else if (io->state == SND_PCM_STATE_DRAINING) { @@ -171,7 +170,7 @@ *revents = pfds[0].revents & ~(POLLIN | POLLOUT); if (pfds[0].revents & POLLIN && update_active(io, false)) *revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN; - if (io->state == SND_PCM_STATE_SETUP || pw->xrun_detected) + if (io->state == SND_PCM_STATE_SETUP || io->state == SND_PCM_STATE_XRUN) *revents |= POLLERR; pw_log_trace_fp("poll %d", *revents); @@ -182,7 +181,7 @@ static snd_pcm_sframes_t snd_pcm_pipewire_pointer(snd_pcm_ioplug_t *io) { snd_pcm_pipewire_t *pw = io->private_data; - if (pw->xrun_detected) + if (io->state == SND_PCM_STATE_XRUN) return -EPIPE; if (pw->error < 0) return pw->error; @@ -330,7 +329,7 @@ if (io->state == SND_PCM_STATE_RUNNING || io->state == SND_PCM_STATE_DRAINING) { /* report Xrun to user application */ - pw->xrun_detected = true; + snd_pcm_ioplug_set_state(io, SND_PCM_STATE_XRUN); } } return xfer; @@ -581,7 +580,6 @@ done: pw->hw_ptr = 0; pw->now = 0; - pw->xrun_detected = false; pw->drained = false; pw->draining = false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/pipewire-jack/src/pipewire-jack.c new/pipewire-1.6.10/pipewire-jack/src/pipewire-jack.c --- old/pipewire-1.6.9/pipewire-jack/src/pipewire-jack.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/pipewire-jack/src/pipewire-jack.c 2026-10-22 18:00:36.000000000 +0200 @@ -710,10 +710,12 @@ spa_list_remove(&mix->link); spa_list_append(&c->mix, &mix->link); - spa_list_append(&port->mix, &mix->port_link); - init_mix(mix, mix_id, port, peer_id); + pw_loop_lock(c->loop->loop); + spa_list_append(&port->mix, &mix->port_link); + pw_loop_unlock(c->loop->loop); + return mix; } @@ -796,7 +798,9 @@ p->direction = direction; p->emptyptr = SPA_PTR_ALIGN(p->empty, c->max_align, float); + pw_loop_lock(c->loop->loop); p->port_id = pw_map_insert_new(&c->ports[direction], p); + pw_loop_unlock(c->loop->loop); c->n_ports++; pthread_mutex_lock(&c->context.lock); @@ -1761,7 +1765,7 @@ SPA_ATOMIC_STORE(io->status, SPA_STATUS_HAVE_DATA); SPA_ATOMIC_STORE(mix->io_busy, 0); } else { - while (SPA_ATOMIC_LOAD(io->status) != SPA_STATUS_HAVE_DATA) + while (SPA_ATOMIC_LOAD(mix->io_busy) != 0) ; if (SPA_UNLIKELY(io->buffer_id >= mix->n_buffers)) return NULL; @@ -4643,6 +4647,16 @@ pw_thread_loop_stop(c->context.notify); } + pw_array_for_each(item, &c->ports[SPA_DIRECTION_OUTPUT].items) { + if (pw_map_item_is_free(item)) + continue; + free_port(c, item->data, false); + } + pw_array_for_each(item, &c->ports[SPA_DIRECTION_INPUT].items) { + if (pw_map_item_is_free(item)) + continue; + free_port(c, item->data, false); + } if (c->registry) { spa_hook_remove(&c->registry_listener); pw_proxy_destroy((struct pw_proxy*)c->registry); @@ -4675,16 +4689,6 @@ pw_log_debug("%p: free", client); - pw_array_for_each(item, &c->ports[SPA_DIRECTION_OUTPUT].items) { - if (pw_map_item_is_free(item)) - continue; - free_port(c, item->data, false); - } - pw_array_for_each(item, &c->ports[SPA_DIRECTION_INPUT].items) { - if (pw_map_item_is_free(item)) - continue; - free_port(c, item->data, false); - } pthread_mutex_lock(&globals.lock); spa_list_consume(o, &c->context.objects, link) { bool to_free = o->to_free; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/audioconvert.c new/pipewire-1.6.10/spa/plugins/audioconvert/audioconvert.c --- old/pipewire-1.6.9/spa/plugins/audioconvert/audioconvert.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/audioconvert.c 2026-10-22 18:00:36.000000000 +0200 @@ -1252,6 +1252,8 @@ float *empty, *scratch, *tmp[2]; if (maxsize > this->scratch_size) { + struct dir *in = &this->dir[SPA_DIRECTION_INPUT]; + spa_log_info(this->log, "resize tmp %d -> %d", this->scratch_size, maxsize); if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL) @@ -1262,7 +1264,10 @@ free_tmp(this); return -ENOMEM; } - memset(this->empty, 0, maxsize + MAX_ALIGN); + if (in->conv.empty) + convert_empty(&in->conv, this->empty, maxsize + MAX_ALIGN); + else + memset(this->empty, 0, maxsize + MAX_ALIGN); for (i = 0; i < this->scratch_ports; i++) { if ((tmp[0] = realloc(this->tmp[0][i], maxsize + MAX_ALIGN)) != NULL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/channelmix-ops-sse.c new/pipewire-1.6.10/spa/plugins/audioconvert/channelmix-ops-sse.c --- old/pipewire-1.6.9/spa/plugins/audioconvert/channelmix-ops-sse.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/channelmix-ops-sse.c 2026-10-22 18:00:36.000000000 +0200 @@ -273,7 +273,7 @@ const float *taps, uint32_t n_taps, float *dst, const float *src, const float vol, uint32_t n_samples) { - __m128 t[2]; + __m128 t[1]; const __m128 v = _mm_set1_ps(vol); uint32_t i; uint32_t w = *pos; @@ -281,18 +281,19 @@ uint32_t n, unrolled; if (SPA_IS_ALIGNED(src, 16) && - SPA_IS_ALIGNED(dst, 16)) + SPA_IS_ALIGNED(dst, 16) && + delay >= 4) unrolled = n_samples & ~3; else unrolled = 0; if (n_taps == 1) { for(n = 0; n < unrolled; n += 4) { - t[1] = _mm_loadu_ps(&buffer[w+o]); t[0] = _mm_load_ps(&src[n]); _mm_storeu_ps(&buffer[w], t[0]); _mm_storeu_ps(&buffer[w+n_buffer], t[0]); - t[0] = _mm_mul_ps(t[1], v); + t[0] = _mm_loadu_ps(&buffer[w+o]); + t[0] = _mm_mul_ps(t[0], v); _mm_store_ps(&dst[n], t[0]); w += 4; if (w >= n_buffer) { @@ -302,21 +303,21 @@ } } for(; n < n_samples; n++) { - t[1] = _mm_load_ss(&buffer[w+o]); t[0] = _mm_load_ss(&src[n]); _mm_store_ss(&buffer[w], t[0]); _mm_store_ss(&buffer[w+n_buffer], t[0]); - t[0] = _mm_mul_ss(t[1], v); + t[0] = _mm_load_ss(&buffer[w+o]); + t[0] = _mm_mul_ss(t[0], v); _mm_store_ss(&dst[n], t[0]); w = w + 1 >= n_buffer ? 0 : w + 1; } } else { for(n = 0; n < unrolled; n += 4) { t[0] = _mm_load_ps(&src[n]); - for(i = 0; i < 4; i++) - convolver_run(&buffer[w+o+i], &dst[n+i], taps, n_taps, v); _mm_storeu_ps(&buffer[w], t[0]); _mm_storeu_ps(&buffer[w+n_buffer], t[0]); + for(i = 0; i < 4; i++) + convolver_run(&buffer[w+o+i], &dst[n+i], taps, n_taps, v); w += 4; if (w >= n_buffer) { w -= n_buffer; @@ -326,9 +327,9 @@ } for(; n < n_samples; n++) { t[0] = _mm_load_ss(&src[n]); - convolver_run(&buffer[w+o], &dst[n], taps, n_taps, v); _mm_store_ss(&buffer[w], t[0]); _mm_store_ss(&buffer[w+n_buffer], t[0]); + convolver_run(&buffer[w+o], &dst[n], taps, n_taps, v); w = w + 1 >= n_buffer ? 0 : w + 1; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops-c.c new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops-c.c --- old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops-c.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops-c.c 2026-10-22 18:00:36.000000000 +0200 @@ -461,3 +461,25 @@ MAKE_CLEAR_VAL(u24_32, uint32_t, 0x800000); MAKE_CLEAR_VAL(u32, uint32_t, 0x80000000); +void conv_empty_c(struct convert *conv, void * SPA_RESTRICT dst, uint32_t n_bytes) +{ + memset(dst, 0, n_bytes); +} + +#define MAKE_EMPTY_VAL(size,dtype,val) \ +void conv_empty_ ##size##_c(struct convert *conv, \ + void * SPA_RESTRICT dst, uint32_t n_bytes) \ +{ \ + uint32_t i, n_samples = n_bytes / sizeof(dtype); \ + dtype *d = dst; \ + for (i = 0; i < n_samples; i++) \ + d[i] = val; \ +} \ + +MAKE_EMPTY_VAL(alaw, uint8_t, 0x55); +MAKE_EMPTY_VAL(ulaw, uint8_t, 0xff); +MAKE_EMPTY_VAL(u8, uint8_t, 0x80); +MAKE_EMPTY_VAL(u16, uint16_t, 0x8000); +MAKE_EMPTY_VAL(u24, uint24_t, U32_TO_U24(0x800000)); +MAKE_EMPTY_VAL(u24_32, uint32_t, 0x800000); +MAKE_EMPTY_VAL(u32, uint32_t, 0x80000000); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops.c new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops.c --- old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops.c 2026-10-22 18:00:36.000000000 +0200 @@ -379,48 +379,52 @@ typedef void (*clear_func_t) (struct convert *conv, void * SPA_RESTRICT dst[], uint32_t n_samples); +typedef void (*empty_func_t) (struct convert *conv, void * SPA_RESTRICT dst, + uint32_t n_bytes); struct clear_info { uint32_t fmt; clear_func_t clear; - const char *name; + const char *clear_name; + empty_func_t empty; + const char *empty_name; uint32_t cpu_flags; }; -#define MAKE(fmt,func,...) \ - { SPA_AUDIO_FORMAT_ ##fmt, func, #func , __VA_ARGS__ } +#define MAKE(fmt,func,empty,...) \ + { SPA_AUDIO_FORMAT_ ##fmt, func, #func, empty, #empty, __VA_ARGS__ } static struct clear_info clear_table[] = { - MAKE(U8, conv_clear_u8_c), - MAKE(U8P, conv_clear_u8d_c), - MAKE(S8, conv_clear_8_c), - MAKE(S8P, conv_clear_8d_c), - MAKE(U16, conv_clear_u16_c), - MAKE(S16, conv_clear_16_c), - MAKE(S16_OE, conv_clear_16_c), - MAKE(S16P, conv_clear_16d_c), - MAKE(U24, conv_clear_u24_c), - MAKE(S24, conv_clear_24_c), - MAKE(S24_OE, conv_clear_24_c), - MAKE(S24P, conv_clear_24d_c), - MAKE(U24_32, conv_clear_u24_32_c), - MAKE(S24_32, conv_clear_32_c), - MAKE(S24_32_OE, conv_clear_32_c), - MAKE(U32, conv_clear_u32_c), - MAKE(S32, conv_clear_32_c), - MAKE(S32_OE, conv_clear_32_c), - MAKE(S32P, conv_clear_32d_c), - MAKE(F32, conv_clear_32_c), - MAKE(F32_OE, conv_clear_32_c), - MAKE(F32P, conv_clear_32d_c), - MAKE(F64, conv_clear_64_c), - MAKE(F64_OE, conv_clear_64_c), - MAKE(F64P, conv_clear_64d_c), - MAKE(ALAW, conv_clear_alaw_c), - MAKE(ULAW, conv_clear_ulaw_c), + MAKE(U8, conv_clear_u8_c, conv_empty_u8_c), + MAKE(U8P, conv_clear_u8d_c, conv_empty_u8_c), + MAKE(S8, conv_clear_8_c, conv_empty_c), + MAKE(S8P, conv_clear_8d_c, conv_empty_c,), + MAKE(U16, conv_clear_u16_c, conv_empty_c), + MAKE(S16, conv_clear_16_c, conv_empty_c), + MAKE(S16_OE, conv_clear_16_c, conv_empty_c), + MAKE(S16P, conv_clear_16d_c, conv_empty_c), + MAKE(U24, conv_clear_u24_c, conv_empty_u24_c,), + MAKE(S24, conv_clear_24_c, conv_empty_c), + MAKE(S24_OE, conv_clear_24_c, conv_empty_c), + MAKE(S24P, conv_clear_24d_c, conv_empty_c), + MAKE(U24_32, conv_clear_u24_32_c, conv_empty_u24_32_c), + MAKE(S24_32, conv_clear_32_c, conv_empty_c), + MAKE(S24_32_OE, conv_clear_32_c, conv_empty_c), + MAKE(U32, conv_clear_u32_c, conv_empty_u32_c), + MAKE(S32, conv_clear_32_c, conv_empty_c), + MAKE(S32_OE, conv_clear_32_c, conv_empty_c), + MAKE(S32P, conv_clear_32d_c, conv_empty_c), + MAKE(F32, conv_clear_32_c, conv_empty_c), + MAKE(F32_OE, conv_clear_32_c, conv_empty_c), + MAKE(F32P, conv_clear_32d_c, conv_empty_c), + MAKE(F64, conv_clear_64_c, conv_empty_c), + MAKE(F64_OE, conv_clear_64_c, conv_empty_c), + MAKE(F64P, conv_clear_64d_c, conv_empty_c), + MAKE(ALAW, conv_clear_alaw_c, conv_empty_alaw_c), + MAKE(ULAW, conv_clear_ulaw_c, conv_empty_ulaw_c), }; #undef MAKE @@ -477,6 +481,7 @@ static void impl_convert_free(struct convert *conv) { conv->process = NULL; + conv->clear = NULL; free(conv->data); conv->data = NULL; } @@ -550,7 +555,7 @@ const struct conv_info *info; const struct dither_info *dinfo; const struct noise_info *ninfo; - const struct clear_info *cinfo; + const struct clear_info *cinfo_src, *cinfo_dst; uint32_t i, conv_flags, data_size[4]; /* we generate int32 bits of random values. With this scale @@ -608,7 +613,8 @@ if (ninfo == NULL) return -ENOTSUP; - cinfo = find_clear_info(conv->dst_fmt, conv->cpu_flags); + cinfo_src = find_clear_info(conv->src_fmt, conv->cpu_flags); + cinfo_dst = find_clear_info(conv->dst_fmt, conv->cpu_flags); conv->noise_size = NOISE_SIZE; @@ -635,7 +641,8 @@ conv->cpu_flags = info->cpu_flags; conv->update_noise = ninfo->noise; conv->process = info->process; - conv->clear = cinfo ? cinfo->clear : NULL; + conv->clear = cinfo_dst ? cinfo_dst->clear : NULL; + conv->empty = cinfo_src ? cinfo_src->empty : NULL; conv->free = impl_convert_free; conv->func_name = info->name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops.h new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops.h --- old/pipewire-1.6.9/spa/plugins/audioconvert/fmt-ops.h 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/fmt-ops.h 2026-10-22 18:00:36.000000000 +0200 @@ -244,6 +244,7 @@ void (*process) (struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples); void (*clear) (struct convert *conv, void * SPA_RESTRICT dst[], uint32_t n_samples); + void (*empty) (struct convert *conv, void * dst, uint32_t n_bytes); void (*free) (struct convert *conv); void *data; @@ -282,6 +283,7 @@ #define convert_update_noise(conv,...) (conv)->update_noise(conv, __VA_ARGS__) #define convert_process(conv,...) (conv)->process(conv, __VA_ARGS__) #define convert_clear(conv,...) (conv)->clear(conv, __VA_ARGS__) +#define convert_empty(conv,...) (conv)->empty(conv, __VA_ARGS__) #define convert_free(conv) (conv)->free(conv) #define convert_is_passthrough(conv) SPA_FLAG_IS_SET((conv)->flags, CONVERT_FLAG_PASSTHROUGH) @@ -522,3 +524,19 @@ DEFINE_CLEAR_FUNCTION(u32, c); #undef DEFINE_CLEAR_FUNCTION + +void conv_empty_c(struct convert *conv, void * SPA_RESTRICT dst, uint32_t n_bytes); + +#define DEFINE_EMPTY_FUNCTION(name,arch) \ +void conv_empty_##name##_##arch(struct convert *conv, void * SPA_RESTRICT dst, \ + uint32_t n_bytes) + +DEFINE_EMPTY_FUNCTION(alaw, c); +DEFINE_EMPTY_FUNCTION(ulaw, c); +DEFINE_EMPTY_FUNCTION(u8, c); +DEFINE_EMPTY_FUNCTION(u16, c); +DEFINE_EMPTY_FUNCTION(u24, c); +DEFINE_EMPTY_FUNCTION(u24_32, c); +DEFINE_EMPTY_FUNCTION(u32, c); + +#undef DEFINE_EMPTY_FUNCTION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/audioconvert/wavfile.c new/pipewire-1.6.10/spa/plugins/audioconvert/wavfile.c --- old/pipewire-1.6.9/spa/plugins/audioconvert/wavfile.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/audioconvert/wavfile.c 2026-10-22 18:00:36.000000000 +0200 @@ -130,7 +130,7 @@ MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F32P, 32, true, 3, writen_32), MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F32_LE, 32, false, 3, writei), MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F64P, 64, true, 3, writen_64), - MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F64_LE, 32, false, 3, writei), + MAKE_AUDIO_RAW(SPA_AUDIO_FORMAT_F64_LE, 64, false, 3, writei), }; #define CHECK_RES(expr) if ((res = (expr)) < 0) return res diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/bluez5/bluez5-dbus.c new/pipewire-1.6.10/spa/plugins/bluez5/bluez5-dbus.c --- old/pipewire-1.6.9/spa/plugins/bluez5/bluez5-dbus.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/bluez5/bluez5-dbus.c 2026-10-22 18:00:36.000000000 +0200 @@ -1696,6 +1696,9 @@ } } + SPA_FOR_EACH_ELEMENT_VAR(adapter->apps, app) + cancel_and_unref(&app->register_call); + spa_bt_player_destroy(adapter->dummy_player); spa_list_remove(&adapter->link); @@ -2813,12 +2816,9 @@ if (!codec_target_profile) return false; - if (!device->adapter->a2dp_application_registered && is_a2dp) { - /* Codec switching not supported: only plain SBC allowed */ - return (codec->codec_id == A2DP_CODEC_SBC && spa_streq(codec->name, "sbc") && - device->adapter->legacy_endpoints_registered); - } - if (!device->adapter->bap_application_registered && codec->kind == MEDIA_CODEC_BAP) + if (is_a2dp && !device->adapter->apps[BLUEZ_APP_A2DP].registered) + return false; + if (is_bap && !device->adapter->apps[BLUEZ_APP_BAP].registered) return false; /* Check codec quirks */ @@ -5100,8 +5100,8 @@ size_t i, j, num_eps, res; uint32_t remaining = 0; - if (!device->adapter->a2dp_application_registered && - !device->adapter->bap_application_registered) { + if (!device->adapter->apps[BLUEZ_APP_A2DP].registered && + !device->adapter->apps[BLUEZ_APP_BAP].registered) { /* Codec switching not supported */ return -ENOTSUP; } @@ -5495,28 +5495,6 @@ return res; } -static void bluez_register_endpoint_legacy_reply(DBusPendingCall *pending, void *user_data) -{ - struct spa_bt_adapter *adapter = user_data; - struct spa_bt_monitor *monitor = adapter->monitor; - - spa_autoptr(DBusMessage) r = steal_reply_and_unref(&pending); - if (r == NULL) - return; - - if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) { - spa_log_warn(monitor->log, "BlueZ D-Bus ObjectManager not available"); - return; - } - if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { - spa_log_error(monitor->log, "RegisterEndpoint() failed: %s", - dbus_message_get_error_name(r)); - return; - } - - adapter->legacy_endpoints_registered = true; -} - static void append_basic_variant_dict_entry(DBusMessageIter *dict, const char* key, int variant_type_int, const char* variant_type_str, void* variant) { DBusMessageIter dict_entry_it, variant_it; dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_it); @@ -5541,112 +5519,6 @@ dbus_message_iter_close_container(dict, &dict_entry_it); } -static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter, - enum spa_bt_media_direction direction, - const char *uuid, const struct media_codec *codec) -{ - struct spa_bt_monitor *monitor = adapter->monitor; - const char *path = adapter->path; - spa_autofree char *object_path = NULL; - spa_autoptr(DBusMessage) m = NULL; - DBusMessageIter object_it, dict_it; - uint8_t caps[A2DP_MAX_CAPS_SIZE]; - int ret, caps_size; - uint16_t codec_id = codec->codec_id; - bool sink = (direction == SPA_BT_MEDIA_SINK); - - spa_assert(codec->fill_caps); - - ret = media_codec_to_endpoint(codec, direction, &object_path); - if (ret < 0) - return ret; - - ret = caps_size = codec->fill_caps(codec, sink ? MEDIA_CODEC_FLAG_SINK : 0, &monitor->global_settings, caps); - if (ret < 0) - return ret; - - m = dbus_message_new_method_call(BLUEZ_SERVICE, - path, - BLUEZ_MEDIA_INTERFACE, - "RegisterEndpoint"); - if (m == NULL) - return -EIO; - - dbus_message_iter_init_append(m, &object_it); - dbus_message_iter_append_basic(&object_it, DBUS_TYPE_OBJECT_PATH, &object_path); - - dbus_message_iter_open_container(&object_it, DBUS_TYPE_ARRAY, "{sv}", &dict_it); - - append_basic_variant_dict_entry(&dict_it,"UUID", DBUS_TYPE_STRING, "s", &uuid); - append_basic_variant_dict_entry(&dict_it, "Codec", DBUS_TYPE_BYTE, "y", &codec_id); - append_basic_array_variant_dict_entry(&dict_it, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, caps, caps_size); - - dbus_message_iter_close_container(&object_it, &dict_it); - - if (!send_with_reply(monitor->conn, m, bluez_register_endpoint_legacy_reply, adapter)) - return -EIO; - - return 0; -} - -static int adapter_register_endpoints_legacy(struct spa_bt_adapter *a) -{ - struct spa_bt_monitor *monitor = a->monitor; - const struct media_codec * const * const media_codecs = monitor->media_codecs; - int i; - int err = 0; - bool registered = false; - - if (a->legacy_endpoints_registered) - return err; - - /* The legacy bluez5 api doesn't support codec switching - * It doesn't make sense to register codecs other than SBC - * as bluez5 will probably use SBC anyway and we have no control over it - * let's incentivize users to upgrade their bluez5 daemon - * if they want proper media codec support - * */ - spa_log_warn(monitor->log, - "Using legacy bluez5 API for A2DP - only SBC will be supported. " - "Please upgrade bluez5."); - - for (i = 0; media_codecs[i]; i++) { - const struct media_codec *codec = media_codecs[i]; - - if (codec->id != SPA_BLUETOOTH_AUDIO_CODEC_SBC) - continue; - - if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE)) { - if ((err = bluez_register_endpoint_legacy(a, SPA_BT_MEDIA_SOURCE, - SPA_BT_UUID_A2DP_SOURCE, - codec))) - goto out; - } - - if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK)) { - if ((err = bluez_register_endpoint_legacy(a, SPA_BT_MEDIA_SINK, - SPA_BT_UUID_A2DP_SINK, - codec))) - goto out; - } - - registered = true; - break; - } - - if (!registered) { - /* Should never happen as SBC support is always enabled */ - spa_log_error(monitor->log, "Broken PipeWire build - unable to locate SBC codec"); - err = -ENOSYS; - } - -out: - if (err) { - spa_log_error(monitor->log, "Failed to register bluez5 endpoints"); - } - return err; -} - static void append_supported_features(DBusMessageIter *dict, struct bap_features *features) { const char *key = "SupportedFeatures"; @@ -5902,37 +5774,35 @@ { struct spa_bt_adapter *adapter = user_data; struct spa_bt_monitor *monitor = adapter->monitor; - bool fallback = true; + struct bluez_app *app = &adapter->apps[BLUEZ_APP_A2DP]; - spa_autoptr(DBusMessage) r = steal_reply_and_unref(&pending); + spa_assert(app->register_call == pending); + spa_autoptr(DBusMessage) r = steal_reply_and_unref(&app->register_call); if (r == NULL) return; if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_SUPPORTED)) { spa_log_warn(monitor->log, "Registering media applications for adapter %s is disabled in bluez5", adapter->path); - goto finish; + return; } if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { spa_log_error(monitor->log, "RegisterApplication() failed: %s", dbus_message_get_error_name(r)); - goto finish; + return; } - fallback = false; - adapter->a2dp_application_registered = true; - -finish: - if (fallback) - adapter_register_endpoints_legacy(adapter); + app->registered = true; } static void bluez_register_application_bap_reply(DBusPendingCall *pending, void *user_data) { struct spa_bt_adapter *adapter = user_data; struct spa_bt_monitor *monitor = adapter->monitor; + struct bluez_app *app = &adapter->apps[BLUEZ_APP_BAP]; - spa_autoptr(DBusMessage) r = steal_reply_and_unref(&pending); + spa_assert(app->register_call == pending); + spa_autoptr(DBusMessage) r = steal_reply_and_unref(&app->register_call); if (r == NULL) return; @@ -5942,7 +5812,7 @@ return; } - adapter->bap_application_registered = true; + app->registered = true; } static int register_media_endpoint(struct spa_bt_monitor *monitor, @@ -6048,14 +5918,13 @@ dbus_connection_unregister_object_path(monitor->conn, A2DP_OBJECT_MANAGER_PATH); } -static bool have_codec_endpoints(struct spa_bt_monitor *monitor, bool bap) +static bool have_codec_endpoints(struct spa_bt_monitor *monitor, enum media_codec_kind kind) { const struct media_codec * const * const media_codecs = monitor->media_codecs; int i; for (i = 0; media_codecs[i]; i++) { const struct media_codec *codec = media_codecs[i]; - enum media_codec_kind kind = bap ? MEDIA_CODEC_BAP : MEDIA_CODEC_A2DP; if (codec->kind != kind) continue; @@ -6068,33 +5937,58 @@ return false; } -static int adapter_register_application(struct spa_bt_adapter *a, bool bap) +static int adapter_register_application(struct spa_bt_adapter *a, enum bluez_app_id app_id) { - const char *object_manager_path = bap ? BAP_OBJECT_MANAGER_PATH : A2DP_OBJECT_MANAGER_PATH; + static const struct app_info { + const char *ep_type_name; + const char *object_manager_path; + void (*reply_callback)(DBusPendingCall *, void *); + enum media_codec_kind codec_kind; + } app_infos[] = { + [BLUEZ_APP_A2DP] = { + .ep_type_name = "A2DP", + .object_manager_path = A2DP_OBJECT_MANAGER_PATH, + .reply_callback = bluez_register_application_a2dp_reply, + .codec_kind = MEDIA_CODEC_A2DP, + }, + [BLUEZ_APP_BAP] = { + .ep_type_name = "LE Audio", + .object_manager_path = BAP_OBJECT_MANAGER_PATH, + .reply_callback = bluez_register_application_bap_reply, + .codec_kind = MEDIA_CODEC_BAP, + }, + }; + SPA_STATIC_ASSERT(SPA_N_ELEMENTS(app_infos) == SPA_N_ELEMENTS(a->apps)); + SPA_STATIC_ASSERT(BLUEZ_APP_LAST == SPA_N_ELEMENTS(a->apps)); + + spa_assert(0 <= app_id && app_id < SPA_N_ELEMENTS(app_infos)); + const struct app_info *info = &app_infos[app_id]; + struct bluez_app *app = &a->apps[app_id]; struct spa_bt_monitor *monitor = a->monitor; - const char *ep_type_name = (bap ? "LE Audio" : "A2DP"); spa_autoptr(DBusMessage) m = NULL; DBusMessageIter i, d; - if (bap && a->bap_application_registered) - return 0; - if (!bap && a->a2dp_application_registered) + if (app->registered) return 0; + if (app->register_call) + return -EINPROGRESS; - if ((bap && !a->le_audio_supported) && (bap && !a->le_audio_bcast_supported)) { - spa_log_info(monitor->log, "Adapter %s indicates LE Audio unsupported: not registering application", - a->path); - return -ENOTSUP; + if (app_id == BLUEZ_APP_BAP) { + if (!a->le_audio_supported && !a->le_audio_bcast_supported) { + spa_log_info(monitor->log, "Adapter %s indicates LE Audio unsupported: not registering application", + a->path); + return -ENOTSUP; + } } - if (!have_codec_endpoints(monitor, bap)) { + if (!have_codec_endpoints(monitor, info->codec_kind)) { spa_log_warn(monitor->log, "No available %s codecs to register on adapter %s", - ep_type_name, a->path); + info->ep_type_name, a->path); return -ENOENT; } spa_log_debug(monitor->log, "Registering bluez5 %s media application on adapter %s", - ep_type_name, a->path); + info->ep_type_name, a->path); m = dbus_message_new_method_call(BLUEZ_SERVICE, a->path, @@ -6104,11 +5998,12 @@ return -EIO; dbus_message_iter_init_append(m, &i); - dbus_message_iter_append_basic(&i, DBUS_TYPE_OBJECT_PATH, &object_manager_path); + dbus_message_iter_append_basic(&i, DBUS_TYPE_OBJECT_PATH, &info->object_manager_path); dbus_message_iter_open_container(&i, DBUS_TYPE_ARRAY, "{sv}", &d); dbus_message_iter_close_container(&i, &d); - if (!send_with_reply(monitor->conn, m, bap ? bluez_register_application_bap_reply : bluez_register_application_a2dp_reply, a)) + app->register_call = send_with_reply(monitor->conn, m, info->reply_callback, a); + if (!app->register_call) return -EIO; return 0; @@ -6380,8 +6275,8 @@ } if (a->has_adapter1_interface && a->has_media1_interface) { - adapter_register_application(a, false); - adapter_register_application(a, true); + adapter_register_application(a, BLUEZ_APP_A2DP); + adapter_register_application(a, BLUEZ_APP_BAP); adapter_register_player(a); adapter_update_devices(a); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/spa/plugins/bluez5/defs.h new/pipewire-1.6.10/spa/plugins/bluez5/defs.h --- old/pipewire-1.6.9/spa/plugins/bluez5/defs.h 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/spa/plugins/bluez5/defs.h 2026-10-22 18:00:36.000000000 +0200 @@ -350,6 +350,12 @@ struct spa_bt_backend; struct spa_bt_player; +enum bluez_app_id { + BLUEZ_APP_A2DP, + BLUEZ_APP_BAP, + BLUEZ_APP_LAST +}; + struct spa_bt_adapter { struct spa_list link; struct spa_bt_monitor *monitor; @@ -366,11 +372,14 @@ uint32_t bluetooth_class; uint32_t profiles; int powered; + + struct bluez_app { + DBusPendingCall *register_call; + bool registered; + } apps[BLUEZ_APP_LAST]; + unsigned int has_msbc:1; unsigned int msbc_probed:1; - unsigned int legacy_endpoints_registered:1; - unsigned int a2dp_application_registered:1; - unsigned int bap_application_registered:1; unsigned int player_registered:1; unsigned int has_battery_provider:1; unsigned int battery_provider_unavailable:1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/gst/gstpipewireformat.c new/pipewire-1.6.10/src/gst/gstpipewireformat.c --- old/pipewire-1.6.9/src/gst/gstpipewireformat.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/gst/gstpipewireformat.c 2026-10-22 18:00:36.000000000 +0200 @@ -1172,9 +1172,12 @@ height, G_TYPE_INT, rect[1].height, NULL); } else { + struct spa_rectangle max = SPA_RECTANGLE( + SPA_MIN(rect[2].width, (uint32_t)INT_MAX), + SPA_MIN(rect[2].height, (uint32_t)INT_MAX)); gst_caps_set_simple (res, - width, GST_TYPE_INT_RANGE, rect[1].width, rect[2].width, - height, GST_TYPE_INT_RANGE, rect[1].height, rect[2].height, + width, GST_TYPE_INT_RANGE, rect[1].width, max.width, + height, GST_TYPE_INT_RANGE, rect[1].height, max.height, NULL); } break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/gst/gstpipewiresrc.c new/pipewire-1.6.10/src/gst/gstpipewiresrc.c --- old/pipewire-1.6.9/src/gst/gstpipewiresrc.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/gst/gstpipewiresrc.c 2026-10-22 18:00:36.000000000 +0200 @@ -839,6 +839,17 @@ video_size += d->chunk->size; } + + /* If the buffer number is smaller than the plane number, + * update the stride and offset for the remaining planes. + */ + if (n_datas && n_datas < n_planes) { + for (i = n_datas; i < n_planes; i++) { + meta->stride[i] = gst_video_format_info_extrapolate_stride (info->finfo, i, b->buffer->datas[0].chunk->stride); + meta->offset[i] = meta->offset[i-1] + + meta->stride[i-1] * GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, i-1, GST_VIDEO_INFO_HEIGHT(info)); + } + } } if (b->buffer->n_datas != gst_buffer_n_memory(data->buf)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-protocol-pulse/client.c new/pipewire-1.6.10/src/modules/module-protocol-pulse/client.c --- old/pipewire-1.6.9/src/modules/module-protocol-pulse/client.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-protocol-pulse/client.c 2026-10-22 18:00:36.000000000 +0200 @@ -402,3 +402,42 @@ return client_queue_message(client, reply); } + +int client_queue_request_command(struct client *client, uint32_t channel, uint32_t size) +{ + struct message *msg, *m, *t; + + spa_list_for_each_safe(m, t, &client->out_messages, link) { + uint32_t s; + + if (m->type != MESSAGE_TYPE_REQUEST_COMMAND) + continue; + if (m->u.request_command.channel != channel) + continue; + + s = m->u.request_command.size; + + if (drop_from_out_queue(client, m)) { + size = (size > UINT32_MAX - s) ? UINT32_MAX : size + s; + pw_log_debug("client %p: merged redundant request command %u to %u", + client, s, size); + } + } + + msg = message_alloc(client->impl, -1, 0); + if (!msg) + return -errno; + + msg->type = MESSAGE_TYPE_REQUEST_COMMAND; + msg->u.request_command.channel = channel; + msg->u.request_command.size = size; + + message_put(msg, + TAG_U32, COMMAND_REQUEST, + TAG_U32, -1, + TAG_U32, channel, + TAG_U32, size, + TAG_INVALID); + + return client_queue_message(client, msg); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-protocol-pulse/client.h new/pipewire-1.6.10/src/modules/module-protocol-pulse/client.h --- old/pipewire-1.6.9/src/modules/module-protocol-pulse/client.h 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-protocol-pulse/client.h 2026-10-22 18:00:36.000000000 +0200 @@ -108,7 +108,9 @@ void client_free(struct client *client); int client_queue_message(struct client *client, struct message *msg); int client_flush_messages(struct client *client); + int client_queue_subscribe_event(struct client *client, uint32_t facility, uint32_t type, uint32_t index); +int client_queue_request_command(struct client *client, uint32_t channel, uint32_t size); void client_update_routes(struct client *client, const char *key, const char *value); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-protocol-pulse/message.h new/pipewire-1.6.10/src/modules/module-protocol-pulse/message.h --- old/pipewire-1.6.9/src/modules/module-protocol-pulse/message.h 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-protocol-pulse/message.h 2026-10-22 18:00:36.000000000 +0200 @@ -16,6 +16,7 @@ enum message_type { MESSAGE_TYPE_UNSPECIFIED, MESSAGE_TYPE_SUBSCRIPTION_EVENT, + MESSAGE_TYPE_REQUEST_COMMAND, }; struct message { @@ -33,6 +34,10 @@ uint32_t event; uint32_t index; } subscription_event; + struct { + uint32_t channel; + uint32_t size; + } request_command; } u; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-protocol-pulse/pulse-server.c new/pipewire-1.6.10/src/modules/module-protocol-pulse/pulse-server.c --- old/pipewire-1.6.9/src/modules/module-protocol-pulse/pulse-server.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-protocol-pulse/pulse-server.c 2026-10-22 18:00:36.000000000 +0200 @@ -1381,9 +1381,14 @@ } else { if ((uint32_t)avail > stream->attr.maxlength) { uint32_t skip = avail - stream->attr.fragsize; + int suppressed; /* overrun, catch up to latest fragment and send it */ - pw_log_warn("%p: [%s] overrun recover read:%u avail:%d max:%u skip:%u", - stream, client->name, index, avail, stream->attr.maxlength, skip); + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, stream->timestamp)) >= 0) { + pw_log_warn("%p: [%s] overrun recover read:%u avail:%d max:%u" + " skip:%u (%d suppressed)", + stream, client->name, index, avail, + stream->attr.maxlength, skip, suppressed); + } index += skip; stream->read_index += skip; avail = stream->attr.fragsize; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-protocol-pulse/stream.c new/pipewire-1.6.10/src/modules/module-protocol-pulse/stream.c --- old/pipewire-1.6.9/src/modules/module-protocol-pulse/stream.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-protocol-pulse/stream.c 2026-10-22 18:00:36.000000000 +0200 @@ -285,9 +285,12 @@ struct client *client = stream->client; struct impl *impl = client->impl; struct message *reply; + int suppressed; - pw_log_warn("client %p [%s]: stream %p OVERFLOW channel:%u", - client, client->name, stream, stream->channel); + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, stream->timestamp)) >= 0) { + pw_log_warn("[%s]: OVERFLOW channel:%u (%d suppressed)", + client->name, stream->channel, suppressed); + } reply = message_alloc(impl, -1, 0); message_put(reply, @@ -373,8 +376,6 @@ int stream_send_request(struct stream *stream) { struct client *client = stream->client; - struct impl *impl = client->impl; - struct message *msg; uint32_t size; size = stream_pop_missing(stream); @@ -384,15 +385,7 @@ pw_log_debug("stream %p: REQUEST channel:%d %u", stream, stream->channel, size); - msg = message_alloc(impl, -1, 0); - message_put(msg, - TAG_U32, COMMAND_REQUEST, - TAG_U32, -1, - TAG_U32, stream->channel, - TAG_U32, size, - TAG_INVALID); - - return client_queue_message(client, msg); + return client_queue_request_command(client, stream->channel, size); } int stream_update_minreq(struct stream *stream, uint32_t minreq) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/modules/module-x11-bell.c new/pipewire-1.6.10/src/modules/module-x11-bell.c --- old/pipewire-1.6.9/src/modules/module-x11-bell.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/modules/module-x11-bell.c 2026-10-22 18:00:36.000000000 +0200 @@ -161,8 +161,12 @@ pw_log_warn("X11 display (%s) has encountered a fatal I/O error", DisplayString(display)); - pw_loop_destroy_source(impl->loop, impl->source); - impl->source = NULL; + /* _XIOError() can be entered more than once for the same dead + * connection, so only destroy the source while it is still valid */ + if (impl->source) { + pw_loop_destroy_source(impl->loop, impl->source); + impl->source = NULL; + } pw_impl_module_schedule_destroy(impl->module); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/pipewire/impl-port.c new/pipewire-1.6.10/src/pipewire/impl-port.c --- old/pipewire-1.6.9/src/pipewire/impl-port.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/pipewire/impl-port.c 2026-10-22 18:00:36.000000000 +0200 @@ -1505,9 +1505,14 @@ return 0; } -void pw_impl_port_unlink(struct pw_impl_port *port) +static void pw_impl_port_unlink(struct pw_impl_port *port) { - struct pw_context *context = port->node->context; + struct pw_context *context; + + if (port->node == NULL) + return; + + context = port->node->context; pw_context_freeze_recalc_graph(context); pw_impl_port_for_each_link(port, do_destroy_link, port); pw_context_thaw_recalc_graph(context, "port unlink"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/pipewire/private.h new/pipewire-1.6.10/src/pipewire/private.h --- old/pipewire-1.6.9/src/pipewire/private.h 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/pipewire/private.h 2026-10-22 18:00:36.000000000 +0200 @@ -1292,9 +1292,6 @@ void pw_impl_port_update_state(struct pw_impl_port *port, enum pw_impl_port_state state, int res, char *error); -/** Unlink a port */ -void pw_impl_port_unlink(struct pw_impl_port *port); - /** Destroy a port */ void pw_impl_port_destroy(struct pw_impl_port *port); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/pipewire/properties.c new/pipewire-1.6.10/src/pipewire/properties.c --- old/pipewire-1.6.9/src/pipewire/properties.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/pipewire/properties.c 2026-10-22 18:00:36.000000000 +0200 @@ -219,8 +219,11 @@ struct properties changes; const char *value; - if ((res = spa_json_begin_object_relax(&it[0], str, size)) <= 0) + if ((res = spa_json_begin_object_relax(&it[0], str, size)) <= 0) { + if (loc) + *loc = (struct spa_error_location){ 0, 0, 0, NULL, "Invalid object" }; return res; + } if (props) properties_init(&changes, 16); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pipewire-1.6.9/src/tools/pw-cat.c new/pipewire-1.6.10/src/tools/pw-cat.c --- old/pipewire-1.6.9/src/tools/pw-cat.c 2026-09-17 12:10:22.000000000 +0200 +++ new/pipewire-1.6.10/src/tools/pw-cat.c 2026-10-22 18:00:36.000000000 +0200 @@ -1815,19 +1815,9 @@ if (format == SF_FORMAT_WAV && info->channels > 2) format = SF_FORMAT_WAVEX; - switch (format & SF_FORMAT_TYPEMASK) { - case SF_FORMAT_OGG: - case SF_FORMAT_FLAC: - case SF_FORMAT_MPEG: - case SF_FORMAT_AIFF: - case SF_FORMAT_WAVEX: - info->format |= SF_ENDIAN_FILE; - break; - default: - info->format |= SF_ENDIAN_CPU; - break; - } - info->format |= format; + /* Let libsndfile pick the container's native byte order; many + * containers (W64, RF64, WAVEX, FLAC, ...) reject SF_ENDIAN_CPU. */ + info->format |= SF_ENDIAN_FILE | format; } static void list_containers(struct data *d) ++++++ pipewire.obsinfo ++++++ --- /var/tmp/diff_new_pack.gvKCYT/_old 2026-10-27 16:46:32.009376737 +0100 +++ /var/tmp/diff_new_pack.gvKCYT/_new 2026-10-27 16:46:32.015376988 +0100 @@ -1,5 +1,5 @@ name: pipewire -version: 1.6.9 -mtime: 1789639822 -commit: 8fa27cabdc6c0c1350c69c026af5850ef0af1e26 +version: 1.6.10 +mtime: 1792684836 +commit: f9d6cbc99c354b9b0ad1d37245dc3ab0fb9f9171
