Changes of Revision 20

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Tue Dec 20 18:46:39 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.63
6
+
7
+-------------------------------------------------------------------
8
 Fri Dec 16 18:14:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.62
11
pipewire-aptx.spec Changed
10
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        0.3.62
6
+Version:        0.3.63
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.62.tar.gz/Makefile.in -> pipewire-0.3.63.tar.gz/Makefile.in Changed
10
 
1
@@ -38,7 +38,7 @@
2
    $(MAKE) run DBG=gdb
3
 
4
 valgrind:
5
-   $(MAKE) run DBG="DISABLE_RTKIT=1 valgrind --trace-children=yes"
6
+   $(MAKE) run DBG="DISABLE_RTKIT=1 PIPEWIRE_DLCLOSE=false valgrind --trace-children=yes"
7
 
8
 test: all
9
    ninja -C $(BUILD_ROOT) test
10
pipewire-0.3.62.tar.gz/NEWS -> pipewire-0.3.63.tar.gz/NEWS Changed
59
 
1
@@ -1,3 +1,47 @@
2
+# PipeWire 0.3.63 (2022-12-15)
3
+
4
+This is a quick bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - Fix a critical bug that causes audio distortion in some cases when using
9
+    AVX2.
10
+  - Fix a crash in mpv caused by deinit of PipeWire.
11
+  - Resample the convolver IR to match the graph samplerate for better
12
+    results.
13
+  - Many more small bugfixes and improvements.
14
+
15
+
16
+## PipeWire
17
+  - Fix a segfault in the PipeWire deinit code triggered by mpv in some
18
+    cases. (#2881)
19
+  - Fix docs about SPA_PLUGIN_DIR.
20
+  - Always dlclose by default (even under valgrind). Add an option with
21
+    PIPEWIRE_DLCLOSE to select alternative behaviour.
22
+  - Improve PIPEWIRE_DEBUG category handling.
23
+
24
+## modules
25
+  - Resample the IR for the convolver when the IR samplerate and graph rate
26
+    don't match.
27
+
28
+## SPA
29
+  - Handle spurious reads from timerfd gracefully.
30
+  - Fix potential stack-use-after-scope when starting Audacity.
31
+  - Fix distorted audio when using AVX2. (#2885)
32
+  - Remove fallback to default channel map in channelmix.
33
+  - Improve sorting of MIDI events, use the same order as Ardour. (#1816)
34
+  - Enable LFE downmixing by default. (#2425)
35
+  - Make IEC958/AC3 and IEC958/DTS work better by enforcing a fixed minimal
36
+    buffering for the encoder to avoid stuttering. (#2650)
37
+
38
+## Pulse-Server
39
+  - Add a new pulse.cmd config section to execute pulse commands, currently
40
+    only for loading modules. This removes the dependency on pactl.
41
+  - Improve debug of messages.
42
+
43
+
44
+Older versions:
45
+
46
 # PipeWire 0.3.62 (2022-12-09)
47
 
48
 This is a bugfix release that is API and ABI compatible with previous
49
@@ -72,9 +116,6 @@
50
   - Support was added for offloading bluetooth handling. Some hardware can
51
     receive, decode and play the bluetooth audio directly in hardware.
52
 
53
-
54
-Older versions:
55
-
56
 # PipeWire 0.3.61 (2022-11-24)
57
 
58
 This is a bugfix release that is API and ABI compatible with previous
59
pipewire-0.3.62.tar.gz/doc/spa-plugins.dox -> pipewire-0.3.63.tar.gz/doc/spa-plugins.dox Changed
36
 
1
@@ -19,7 +19,7 @@
2
 In pseudo-code, loading a logger interface looks like this:
3
 
4
 \code{.py}
5
-handle = dlopen("$SPA_PLUGIN_PATH/support/libspa-support.so")
6
+handle = dlopen("$SPA_PLUGIN_DIR/support/libspa-support.so")
7
 factory_enumeration_func = dlsym(handle, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)
8
 spa_log *logger = NULL
9
 
10
@@ -49,8 +49,8 @@
11
 The `spa-inspect` tool provides a CLI interface to inspect SPA plugins:
12
 
13
 \verbatim
14
-$ export SPA_PLUGIN_PATH=$(pkg-config --variable plugindir libspa-0.2)
15
-$ spa-inspect ${SPA_PLUGIN_PATH}/support/libspa-support.so
16
+$ export SPA_PLUGIN_DIR=$(pkg-config --variable plugindir libspa-0.2)
17
+$ spa-inspect ${SPA_PLUGIN_DIR}/support/libspa-support.so
18
 ...
19
 factory version:       1
20
 factory name:      'support.cpu'
21
@@ -87,11 +87,11 @@
22
 To `dlopen` a plugin we then need to prefix the plugin path like this:
23
 
24
 \code{.c}
25
-#define SPA_PLUGIN_PATH    /usr/lib64/spa-0.2/"
26
-void *hnd = dlopen(SPA_PLUGIN_PATH"/support/libspa-support.so", RTLD_NOW);
27
+#define SPA_PLUGIN_DIR /usr/lib64/spa-0.2/"
28
+void *hnd = dlopen(SPA_PLUGIN_DIR"/support/libspa-support.so", RTLD_NOW);
29
 \endcode
30
 
31
-The environment variable `SPA_PLUGIN_PATH` and `pkg-config` variable
32
+The environment variable `SPA_PLUGIN_DIR` and `pkg-config` variable
33
 `plugindir` are usually used to find the location of the plugins. You will
34
 have to do some more work to construct the shared object path.
35
 
36
pipewire-0.3.62.tar.gz/meson.build -> pipewire-0.3.63.tar.gz/meson.build Changed
8
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.62',
4
+  version : '0.3.63',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.59.0',
7
   default_options :  'warning_level=3',
8
pipewire-0.3.62.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.63.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
81
 
1
@@ -1002,6 +1002,38 @@
2
    }
3
 }
4
 
5
+static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
6
+{
7
+   if (a->offset < b->offset)
8
+       return -1;
9
+   if (a->offset > b->offset)
10
+       return 1;
11
+   if (a->type != b->type)
12
+       return 0;
13
+   switch(a->type) {
14
+   case SPA_CONTROL_Midi:
15
+   {
16
+       /* 11 (controller) > 12 (program change) >
17
+        * 8 (note off) > 9 (note on) > 10 (aftertouch) >
18
+        * 13 (channel pressure) > 14 (pitch bend) */
19
+       static int priotab = { 5,4,3,7,6,2,1,0 };
20
+       uint8_t *da, *db;
21
+
22
+       if (SPA_POD_BODY_SIZE(&a->value) < 1 ||
23
+           SPA_POD_BODY_SIZE(&b->value) < 1)
24
+           return 0;
25
+
26
+       da = SPA_POD_BODY(&a->value);
27
+       db = SPA_POD_BODY(&b->value);
28
+       if ((da0 & 0xf) != (db0 & 0xf))
29
+           return 0;
30
+       return priotab(db0>>4) & 7 - priotab(da0>>4) & 7;
31
+   }
32
+   default:
33
+       return 0;
34
+   }
35
+}
36
+
37
 static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix)
38
 {
39
    struct spa_pod_control *cn_seq;
40
@@ -1014,15 +1046,13 @@
41
    while (true) {
42
        struct spa_pod_control *next = NULL;
43
        uint32_t next_index = 0;
44
-       uint8_t *data;
45
-       size_t size;
46
 
47
        for (i = 0; i < n_seq; i++) {
48
            if (!spa_pod_control_is_inside(&seqi->body,
49
                        SPA_POD_BODY_SIZE(seqi), ci))
50
                continue;
51
 
52
-           if (next == NULL || ci->offset < next->offset) {
53
+           if (next == NULL || event_sort(ci, next) <= 0) {
54
                next = ci;
55
                next_index = i;
56
            }
57
@@ -1030,11 +1060,12 @@
58
        if (SPA_UNLIKELY(next == NULL))
59
            break;
60
 
61
-       data = SPA_POD_BODY(&next->value);
62
-       size = SPA_POD_BODY_SIZE(&next->value);
63
-
64
        switch(next->type) {
65
        case SPA_CONTROL_Midi:
66
+       {
67
+           uint8_t *data = SPA_POD_BODY(&next->value);
68
+           size_t size = SPA_POD_BODY_SIZE(&next->value);
69
+
70
            if (fix)
71
                fix_midi_event(data, size);
72
 
73
@@ -1043,6 +1074,7 @@
74
                        spa_strerror(res));
75
            break;
76
        }
77
+       }
78
        cnext_index = spa_pod_control_next(cnext_index);
79
    }
80
 }
81
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
63
 
1
@@ -1583,11 +1583,18 @@
2
    if (is_batch)
3
        state->headroom += period_size;
4
 
5
+   if (spa_strstartswith(state->props.device, "a52") ||
6
+       spa_strstartswith(state->props.device, "dca"))
7
+       state->min_delay = SPA_MIN(2048u, state->buffer_frames);
8
+   else
9
+       state->min_delay = 0;
10
+
11
    state->headroom = SPA_MIN(state->headroom, state->buffer_frames);
12
    state->start_delay = state->default_start_delay;
13
 
14
-   state->latencystate->port_direction.min_rate = state->headroom;
15
-   state->latencystate->port_direction.max_rate = state->headroom;
16
+   state->latencystate->port_direction.min_rate =
17
+       state->latencystate->port_direction.max_rate =
18
+           SPA_MAX(state->min_delay, state->headroom);
19
 
20
    spa_log_info(state->log, "%s (%s): format:%s access:%s-%s rate:%d channels:%d "
21
            "buffer frames %lu, period frames %lu, periods %u, frame_size %zd "
22
@@ -1859,7 +1866,7 @@
23
        *delay = avail;
24
        *target = SPA_MAX(*target, state->read_size);
25
    }
26
-   *target = SPA_MIN(*target, state->buffer_frames);
27
+   *target = SPA_CLAMP(*target, state->min_delay, state->buffer_frames);
28
    return 0;
29
 }
30
 
31
@@ -2428,9 +2435,20 @@
32
    struct state *state = source->data;
33
    snd_pcm_uframes_t delay, target;
34
    uint64_t expire, current_time;
35
+   int res;
36
 
37
-   if (SPA_UNLIKELY(state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0))
38
-       spa_log_warn(state->log, "%p: error reading timerfd: %m", state);
39
+   if (SPA_LIKELY(state->started)) {
40
+       if (SPA_UNLIKELY((res = spa_system_timerfd_read(state->data_system,
41
+                       state->timerfd, &expire)) < 0)) {
42
+           /* we can get here when the timer is changed since the last
43
+            * timerfd wakeup, for example by do_reassign_follower() executed
44
+            * in the same epoll wakeup cycle */
45
+           if (res != -EAGAIN)
46
+               spa_log_warn(state->log, "%p: error reading timerfd: %s",
47
+                       state, spa_strerror(res));
48
+           return;
49
+       }
50
+   }
51
 
52
    check_position_config(state);
53
 
54
@@ -2610,6 +2628,8 @@
55
        else
56
            snd_pcm_pause(state->hndl, 0);
57
    }
58
+
59
+   state->alsa_sync_warning = false;
60
    return 0;
61
 }
62
 
63
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
9
 
1
@@ -197,6 +197,7 @@
2
    uint32_t last_threshold;
3
    uint32_t headroom;
4
    uint32_t start_delay;
5
+   uint32_t min_delay;
6
 
7
    uint32_t duration;
8
    unsigned int alsa_started:1;
9
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-seq.c -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-seq.c Changed
18
 
1
@@ -800,8 +800,14 @@
2
    uint64_t expire;
3
    int res;
4
 
5
-   if (state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0)
6
-       spa_log_warn(state->log, "error reading timerfd: %m");
7
+   if (state->started) {
8
+       if ((res = spa_system_timerfd_read(state->data_system, state->timerfd, &expire)) < 0) {
9
+           if (res != -EAGAIN)
10
+               spa_log_warn(state->log, "%p: error reading timerfd: %s",
11
+                       state, spa_strerror(res));
12
+           return;
13
+       }
14
+   }
15
 
16
    state->current_time = state->next_time;
17
 
18
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
26
 
1
@@ -473,6 +473,7 @@
2
 
3
 static int configure_format(struct impl *this, uint32_t flags, const struct spa_pod *format)
4
 {
5
+   uint8_t buffer4096;
6
    int res;
7
 
8
    if (format == NULL && !this->have_format)
9
@@ -487,14 +488,13 @@
10
                       SPA_PARAM_Format, flags,
11
                       format)) < 0)
12
            return res;
13
+
14
    if (res > 0) {
15
-       uint8_t buffer4096;
16
-       struct spa_pod_builder b = { 0 };
17
+       struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
18
        uint32_t state = 0;
19
        struct spa_pod *fmt;
20
 
21
        /* format was changed to nearest compatible format */
22
-       spa_pod_builder_init(&b, buffer, sizeof(buffer));
23
 
24
        if ((res = spa_node_port_enum_params_sync(this->follower,
25
                    this->direction, 0,
26
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
68
 
1
@@ -1178,45 +1178,6 @@
2
    return 0;
3
 }
4
 
5
-#define _MASK(ch)  (1ULL << SPA_AUDIO_CHANNEL_ ## ch)
6
-#define STEREO (_MASK(FL)|_MASK(FR))
7
-
8
-static uint64_t default_mask(uint32_t channels)
9
-{
10
-   uint64_t mask = 0;
11
-   switch (channels) {
12
-   case 7:
13
-   case 8:
14
-       mask |= _MASK(RL);
15
-       mask |= _MASK(RR);
16
-       SPA_FALLTHROUGH
17
-   case 5:
18
-   case 6:
19
-       mask |= _MASK(SL);
20
-       mask |= _MASK(SR);
21
-       if ((channels & 1) == 0)
22
-           mask |= _MASK(LFE);
23
-       SPA_FALLTHROUGH
24
-   case 3:
25
-       mask |= _MASK(FC);
26
-       SPA_FALLTHROUGH
27
-   case 2:
28
-       mask |= _MASK(FL);
29
-       mask |= _MASK(FR);
30
-       break;
31
-   case 1:
32
-       mask |= _MASK(MONO);
33
-       break;
34
-   case 4:
35
-       mask |= _MASK(FL);
36
-       mask |= _MASK(FR);
37
-       mask |= _MASK(RL);
38
-       mask |= _MASK(RR);
39
-       break;
40
-   }
41
-   return mask;
42
-}
43
-
44
 static void fix_volumes(struct impl *this, struct volumes *vols, uint32_t channels)
45
 {
46
    float s;
47
@@ -1337,11 +1298,6 @@
48
    spa_log_info(this->log, "out %s (%016"PRIx64")", format_position(str, sizeof(str),
49
                dst_chan, out->format.info.raw.position), dst_mask);
50
 
51
-   if (src_mask & 1)
52
-       src_mask = default_mask(src_chan);
53
-   if (dst_mask & 1)
54
-       dst_mask = default_mask(dst_chan);
55
-
56
    spa_log_info(this->log, "%p: %s/%d@%d->%s/%d@%d %08"PRIx64":%08"PRIx64, this,
57
            spa_debug_type_find_name(spa_type_audio_format, SPA_AUDIO_FORMAT_DSP_F32),
58
            src_chan,
59
@@ -2879,7 +2835,7 @@
60
 
61
    props_reset(&this->props);
62
 
63
-   this->mix.options = CHANNELMIX_OPTION_UPMIX;
64
+   this->mix.options = CHANNELMIX_OPTION_UPMIX | CHANNELMIX_OPTION_MIX_LFE;
65
    this->mix.upmix = CHANNELMIX_UPMIX_PSD;
66
    this->mix.log = this->log;
67
    this->mix.lfe_cutoff = 150.0f;
68
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/channelmix-ops.c Changed
17
 
1
@@ -522,6 +522,7 @@
2
 
3
            if (i == 0)
4
                idx2 += snprintf(str2 + idx2, sizeof(str2) - idx2, "%-4.4s  ",
5
+                       src_mask == ~0LU ? "MONO" :
6
                        spa_debug_type_find_short_name(spa_type_audio_channel, j + 3));
7
 
8
            mix->matrix_origicjc++ = matrixij;
9
@@ -536,6 +537,7 @@
10
            if (i == 0)
11
                spa_log_info(mix->log, "     %s", str2);
12
            spa_log_info(mix->log, "%-4.4s %s   %f",
13
+                   dst_mask == ~0LU ? "MONO" :
14
                    spa_debug_type_find_short_name(spa_type_audio_channel, i + 3),
15
                    str, sum);
16
        }
17
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c Changed
28
 
1
@@ -339,7 +339,7 @@
2
    __m256i in4;
3
    __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
4
    __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
5
-                     3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
6
+                     4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
7
 
8
    if (SPA_IS_ALIGNED(d0, 32) &&
9
        SPA_IS_ALIGNED(d1, 32) &&
10
@@ -405,7 +405,7 @@
11
    __m256i in4;
12
    __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
13
    __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
14
-                     3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
15
+                     4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
16
 
17
    if (SPA_IS_ALIGNED(d0, 32) &&
18
        SPA_IS_ALIGNED(d1, 32))
19
@@ -453,7 +453,7 @@
20
    __m256i in2;
21
    __m256 out2, factor = _mm256_set1_ps(1.0f / S24_SCALE);
22
    __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
23
-                     3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
24
+                     4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
25
 
26
    if (SPA_IS_ALIGNED(d0, 32))
27
        unrolled = n_samples & ~15;
28
pipewire-0.3.62.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c Changed
43
 
1
@@ -34,6 +34,7 @@
2
 #include <spa/support/loop.h>
3
 #include <spa/utils/list.h>
4
 #include <spa/utils/keys.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -348,14 +349,20 @@
10
    }
11
 }
12
 
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
 {
16
    uint64_t expirations;
17
+   int res = 0;
18
 
19
    if (this->async || this->props.live) {
20
-       if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
-           perror("read timerfd");
22
+       if ((res = spa_system_timerfd_read(this->data_system,
23
+               this->timer_source.fd, &expirations)) < 0) {
24
+           if (res != -EAGAIN)
25
+               spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+                       this, spa_strerror(res));
27
+       }
28
    }
29
+   return 0;
30
 }
31
 
32
 static int make_buffer(struct impl *this)
33
@@ -369,7 +376,8 @@
34
    uint32_t filled, avail;
35
    uint32_t index, offset, l0, l1;
36
 
37
-   read_timer(this);
38
+   if (read_timer(this) < 0)
39
+       return 0;
40
 
41
    if (spa_list_is_empty(&port->empty)) {
42
        set_timer(this, false);
43
pipewire-0.3.62.tar.gz/spa/plugins/avb/avb-pcm.c -> pipewire-0.3.63.tar.gz/spa/plugins/avb/avb-pcm.c Changed
30
 
1
@@ -36,6 +36,7 @@
2
 #include <arpa/inet.h>
3
 
4
 #include <spa/pod/filter.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/support/system.h>
8
 #include <spa/utils/keys.h>
9
@@ -1048,14 +1049,15 @@
10
    struct state *state = source->data;
11
    uint64_t expirations, current_time, duration;
12
    uint32_t rate;
13
+   int res;
14
 
15
    spa_log_trace(state->log, "timeout");
16
 
17
-   if (spa_system_timerfd_read(state->data_system,
18
-               state->timer_source.fd, &expirations) < 0) {
19
-       if (errno == EAGAIN)
20
-           return;
21
-       spa_log_error(state->log, "read timerfd: %m");
22
+   if ((res = spa_system_timerfd_read(state->data_system,
23
+               state->timer_source.fd, &expirations)) < 0) {
24
+       if (res != -EAGAIN)
25
+           spa_log_error(state->log, "read timerfd: %s", spa_strerror(res));
26
+       return;
27
    }
28
 
29
    current_time = state->next_time;
30
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/media-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/media-sink.c Changed
41
 
1
@@ -839,11 +839,15 @@
2
 {
3
    struct impl *this = source->data;
4
    uint64_t exp;
5
+   int res;
6
 
7
    spa_log_trace(this->log, "%p: flush on timeout", this);
8
 
9
-   if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
10
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
11
+   if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
12
+       if (res != -EAGAIN)
13
+           spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
14
+       return;
15
+   }
16
 
17
    if (this->transport == NULL) {
18
        enable_flush_timer(this, false);
19
@@ -864,12 +868,19 @@
20
    uint32_t rate;
21
    struct spa_io_buffers *io = port->io;
22
    uint64_t prev_time, now_time;
23
+   int res;
24
 
25
    if (this->transport == NULL)
26
        return;
27
 
28
-   if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
29
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
30
+   if (this->started) {
31
+       if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
32
+           if (res != -EAGAIN)
33
+               spa_log_warn(this->log, "error reading timerfd: %s",
34
+                       spa_strerror(res));
35
+           return;
36
+       }
37
+   }
38
 
39
    prev_time = this->current_time;
40
    now_time = this->current_time = this->next_time;
41
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/media-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/media-source.c Changed
38
 
1
@@ -538,9 +538,13 @@
2
 {
3
    struct impl *this = source->data;
4
    uint64_t exp;
5
+   int res;
6
 
7
-   if (spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp) < 0)
8
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
9
+   if ((res = spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp)) < 0) {
10
+       if (res != -EAGAIN)
11
+           spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
12
+       return;
13
+   }
14
 
15
    set_duplex_timeout(this, this->duplex_timeout);
16
 
17
@@ -577,12 +581,18 @@
18
    uint64_t exp, duration;
19
    uint32_t rate;
20
    uint64_t prev_time, now_time;
21
+   int res;
22
 
23
    if (this->transport == NULL)
24
        return;
25
 
26
-   if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
27
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
28
+   if (this->started) {
29
+       if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
30
+           if (res != -EAGAIN)
31
+               spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
32
+           return;
33
+       }
34
+   }
35
 
36
    prev_time = this->current_time;
37
    now_time = this->current_time = this->next_time;
38
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/sco-sink.c Changed
45
 
1
@@ -567,16 +567,19 @@
2
    enable_flush_timer(this, false);
3
 }
4
 
5
-
6
 static void sco_on_flush_timeout(struct spa_source *source)
7
 {
8
    struct impl *this = source->data;
9
    uint64_t exp;
10
+   int res;
11
 
12
    spa_log_trace(this->log, "%p: flush on timeout", this);
13
 
14
-   if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
15
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
16
+   if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
17
+       if (res != -EAGAIN)
18
+           spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
19
+       return;
20
+   }
21
 
22
    if (this->transport == NULL) {
23
        enable_flush_timer(this, false);
24
@@ -597,12 +600,18 @@
25
    uint32_t rate;
26
    struct spa_io_buffers *io = port->io;
27
    uint64_t prev_time, now_time;
28
+   int res;
29
 
30
    if (this->transport == NULL)
31
        return;
32
 
33
-   if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
34
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
35
+   if (this->started) {
36
+       if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
37
+           if (res != -EAGAIN)
38
+               spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
39
+           return;
40
+       }
41
+   }
42
 
43
    prev_time = this->current_time;
44
    now_time = this->current_time = this->next_time;
45
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/sco-source.c Changed
31
 
1
@@ -34,6 +34,7 @@
2
 #include <spa/support/loop.h>
3
 #include <spa/support/log.h>
4
 #include <spa/support/system.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/list.h>
7
 #include <spa/utils/keys.h>
8
 #include <spa/utils/names.h>
9
@@ -600,12 +601,19 @@
10
    uint64_t exp, duration;
11
    uint32_t rate;
12
    uint64_t prev_time, now_time;
13
+   int res;
14
 
15
    if (this->transport == NULL)
16
        return;
17
 
18
-   if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
19
-       spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
20
+   if (this->started) {
21
+       if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
22
+           if (res != -EAGAIN)
23
+               spa_log_warn(this->log, "error reading timerfd: %s",
24
+                       spa_strerror(res));
25
+           return;
26
+       }
27
+   }
28
 
29
    prev_time = this->current_time;
30
    now_time = this->current_time = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/control/mixer.c -> pipewire-0.3.63.tar.gz/spa/plugins/control/mixer.c Changed
57
 
1
@@ -37,6 +37,7 @@
2
 #include <spa/node/io.h>
3
 #include <spa/param/audio/format-utils.h>
4
 #include <spa/param/param.h>
5
+#include <spa/control/control.h>
6
 #include <spa/pod/filter.h>
7
 
8
 #define NAME "control-mixer"
9
@@ -571,6 +572,38 @@
10
    return queue_buffer(this, port, &port->buffersbuffer_id);
11
 }
12
 
13
+static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
14
+{
15
+   if (a->offset < b->offset)
16
+       return -1;
17
+   if (a->offset > b->offset)
18
+       return 1;
19
+   if (a->type != b->type)
20
+       return 0;
21
+   switch(a->type) {
22
+   case SPA_CONTROL_Midi:
23
+   {
24
+       /* 11 (controller) > 12 (program change) >
25
+        * 8 (note off) > 9 (note on) > 10 (aftertouch) >
26
+        * 13 (channel pressure) > 14 (pitch bend) */
27
+       static int priotab = { 5,4,3,7,6,2,1,0 };
28
+       uint8_t *da, *db;
29
+
30
+       if (SPA_POD_BODY_SIZE(&a->value) < 1 ||
31
+           SPA_POD_BODY_SIZE(&b->value) < 1)
32
+           return 0;
33
+
34
+       da = SPA_POD_BODY(&a->value);
35
+       db = SPA_POD_BODY(&b->value);
36
+       if ((da0 & 0xf) != (db0 & 0xf))
37
+           return 0;
38
+       return priotab(db0>>4) & 7 - priotab(da0>>4) & 7;
39
+   }
40
+   default:
41
+       return 0;
42
+   }
43
+}
44
+
45
 static int impl_node_process(void *object)
46
 {
47
    struct impl *this = object;
48
@@ -664,7 +697,7 @@
49
                    SPA_POD_BODY_SIZE(seqi), ctrli))
50
                continue;
51
 
52
-           if (next == NULL || ctrli->offset < next->offset) {
53
+           if (next == NULL || event_sort(ctrli, next) <= 0) {
54
                next = ctrli;
55
                next_index = i;
56
            }
57
pipewire-0.3.62.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.63.tar.gz/spa/plugins/support/node-driver.c Changed
31
 
1
@@ -32,6 +32,7 @@
2
 #include <spa/support/log.h>
3
 #include <spa/support/loop.h>
4
 #include <spa/utils/names.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/keys.h>
9
@@ -180,14 +181,16 @@
10
    struct impl *this = source->data;
11
    uint64_t expirations, nsec, duration;
12
    uint32_t rate;
13
+   int res;
14
 
15
    spa_log_trace(this->log, "timeout");
16
 
17
-   if (spa_system_timerfd_read(this->data_system,
18
-               this->timer_source.fd, &expirations) < 0) {
19
-       if (errno == EAGAIN)
20
-           return;
21
-       perror("read timerfd");
22
+   if ((res = spa_system_timerfd_read(this->data_system,
23
+               this->timer_source.fd, &expirations)) < 0) {
24
+       if (res != EAGAIN)
25
+           spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+                   this, spa_strerror(res));
27
+       return;
28
    }
29
 
30
    nsec = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/support/null-audio-sink.c Changed
31
 
1
@@ -35,6 +35,7 @@
2
 #include <spa/utils/list.h>
3
 #include <spa/utils/keys.h>
4
 #include <spa/utils/json.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -282,14 +283,16 @@
10
    struct impl *this = source->data;
11
    uint64_t expirations, nsec, duration = 10;
12
    uint32_t rate;
13
+   int res;
14
 
15
    spa_log_trace(this->log, "timeout");
16
 
17
-   if (spa_system_timerfd_read(this->data_system,
18
-               this->timer_source.fd, &expirations) < 0) {
19
-       if (errno == EAGAIN)
20
-           return;
21
-       perror("read timerfd");
22
+   if ((res = spa_system_timerfd_read(this->data_system,
23
+               this->timer_source.fd, &expirations)) < 0) {
24
+       if (res != EAGAIN)
25
+           spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+                   this, spa_strerror(res));
27
+       return;
28
    }
29
 
30
    nsec = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/test/fakesink.c -> pipewire-0.3.63.tar.gz/spa/plugins/test/fakesink.c Changed
44
 
1
@@ -32,6 +32,7 @@
2
 #include <spa/support/log.h>
3
 #include <spa/support/loop.h>
4
 #include <spa/utils/list.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -215,15 +216,20 @@
10
    }
11
 }
12
 
13
-static inline void read_timer(struct impl *this)
14
+static inline int read_timer(struct impl *this)
15
 {
16
    uint64_t expirations;
17
+   int res = 0;
18
 
19
    if (this->callbacks.funcs || this->props.live) {
20
-       if (spa_system_timerfd_read(this->data_system,
21
-                   this->timer_source.fd, &expirations) < 0)
22
-           perror("read timerfd");
23
+       if ((res = spa_system_timerfd_read(this->data_system,
24
+                   this->timer_source.fd, &expirations)) < 0) {
25
+           if (res != -EAGAIN)
26
+               spa_log_error(this->log, NAME " %p: timerfd error: %s",
27
+                       this, spa_strerror(res));
28
+       }
29
    }
30
+   return res;
31
 }
32
 
33
 static void render_buffer(struct impl *this, struct buffer *b)
34
@@ -237,7 +243,8 @@
35
    struct spa_io_buffers *io = port->io;
36
    int n_bytes;
37
 
38
-   read_timer(this);
39
+   if (read_timer(this) < 0)
40
+       return 0;
41
 
42
    if (spa_list_is_empty(&port->ready)) {
43
        io->status = SPA_STATUS_NEED_DATA;
44
pipewire-0.3.62.tar.gz/spa/plugins/test/fakesrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/test/fakesrc.c Changed
44
 
1
@@ -32,6 +32,7 @@
2
 #include <spa/support/log.h>
3
 #include <spa/support/loop.h>
4
 #include <spa/utils/list.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -230,15 +231,20 @@
10
    }
11
 }
12
 
13
-static inline void read_timer(struct impl *this)
14
+static inline int read_timer(struct impl *this)
15
 {
16
    uint64_t expirations;
17
+   int res = 0;
18
 
19
    if (this->callbacks.funcs || this->props.live) {
20
-       if (spa_system_timerfd_read(this->data_system,
21
-                   this->timer_source.fd, &expirations) < 0)
22
-           perror("read timerfd");
23
+       if ((res = spa_system_timerfd_read(this->data_system,
24
+                   this->timer_source.fd, &expirations)) < 0) {
25
+           if (res != -EAGAIN)
26
+               spa_log_error(this->log, NAME " %p: timerfd error: %s",
27
+                       this, spa_strerror(res));
28
+       }
29
    }
30
+   return res;
31
 }
32
 
33
 static int make_buffer(struct impl *this)
34
@@ -248,7 +254,8 @@
35
    struct spa_io_buffers *io = port->io;
36
    int n_bytes;
37
 
38
-   read_timer(this);
39
+   if (read_timer(this) < 0)
40
+       return 0;
41
 
42
    if (spa_list_is_empty(&port->empty)) {
43
        set_timer(this, false);
44
pipewire-0.3.62.tar.gz/spa/plugins/videotestsrc/videotestsrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/videotestsrc/videotestsrc.c Changed
43
 
1
@@ -33,6 +33,7 @@
2
 #include <spa/support/loop.h>
3
 #include <spa/utils/list.h>
4
 #include <spa/utils/keys.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -280,14 +281,20 @@
10
    }
11
 }
12
 
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
 {
16
    uint64_t expirations;
17
+   int res = 0;
18
 
19
    if (this->async || this->props.live) {
20
-       if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
-           perror("read timerfd");
22
+       if ((res = spa_system_timerfd_read(this->data_system,
23
+                       this->timer_source.fd, &expirations)) < 0) {
24
+           if (res != -EAGAIN)
25
+               spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+                       this, spa_strerror(res));
27
+       }
28
    }
29
+   return res;
30
 }
31
 
32
 static int make_buffer(struct impl *this)
33
@@ -297,7 +304,8 @@
34
    struct spa_io_buffers *io = port->io;
35
    uint32_t n_bytes;
36
 
37
-   read_timer(this);
38
+   if (read_timer(this) < 0)
39
+       return 0;
40
 
41
    if (spa_list_is_empty(&port->empty)) {
42
        set_timer(this, false);
43
pipewire-0.3.62.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c Changed
43
 
1
@@ -34,6 +34,7 @@
2
 #include <spa/utils/list.h>
3
 #include <spa/utils/keys.h>
4
 #include <spa/utils/names.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/string.h>
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -267,14 +268,20 @@
10
    }
11
 }
12
 
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
 {
16
    uint64_t expirations;
17
+   int res = 0;
18
 
19
    if (this->async || this->props.live) {
20
-       if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
-           perror("read timerfd");
22
+       if ((res = spa_system_timerfd_read(this->data_system,
23
+                       this->timer_source.fd, &expirations)) < 0) {
24
+           if (res != -EAGAIN)
25
+               spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+                       this, spa_strerror(res));
27
+       }
28
    }
29
+   return res;
30
 }
31
 
32
 static int make_buffer(struct impl *this)
33
@@ -284,7 +291,8 @@
34
    uint32_t n_bytes;
35
    int res;
36
 
37
-   read_timer(this);
38
+   if (read_timer(this) < 0)
39
+       return 0;
40
 
41
    if ((res = spa_vulkan_ready(&this->state)) < 0) {
42
        res = SPA_STATUS_OK;
43
pipewire-0.3.62.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/client-rt.conf.in Changed
10
 
1
@@ -82,7 +82,7 @@
2
     #node.autoconnect      = true
3
     #resample.quality      = 4
4
     #channelmix.normalize  = false
5
-    #channelmix.mix-lfe    = false
6
+    #channelmix.mix-lfe    = true
7
     #channelmix.upmix      = true
8
     #channelmix.upmix-method = psd  # none, simple
9
     #channelmix.lfe-cutoff = 150
10
pipewire-0.3.62.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/client.conf.in Changed
10
 
1
@@ -73,7 +73,7 @@
2
     #node.autoconnect      = true
3
     #resample.quality      = 4
4
     #channelmix.normalize  = false
5
-    #channelmix.mix-lfe    = false
6
+    #channelmix.mix-lfe    = true
7
     #channelmix.upmix      = true
8
     #channelmix.upmix-method = psd  # none, simple
9
     #channelmix.lfe-cutoff = 150
10
pipewire-0.3.62.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/minimal.conf.in Changed
19
 
1
@@ -203,7 +203,7 @@
2
             resample.disable       = true
3
             #monitor.channel-volumes = false
4
             #channelmix.normalize   = false
5
-            #channelmix.mix-lfe     = false
6
+            #channelmix.mix-lfe     = true
7
             #channelmix.upmix       = true
8
             #channelmix.upmix-method = psd  # none, simple
9
             #channelmix.lfe-cutoff  = 150
10
@@ -265,7 +265,7 @@
11
             #resample.quality      = 4
12
             resample.disable      = true
13
             #channelmix.normalize  = false
14
-            #channelmix.mix-lfe    = false
15
+            #channelmix.mix-lfe    = true
16
             #channelmix.upmix      = true
17
             #channelmix.upmix-method = psd  # none, simple
18
             #channelmix.lfe-cutoff = 150
19
pipewire-0.3.62.tar.gz/src/daemon/pipewire-avb.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/pipewire-avb.conf.in Changed
10
 
1
@@ -54,7 +54,7 @@
2
     #node.autoconnect      = true
3
     #resample.quality      = 4
4
     #channelmix.normalize  = false
5
-    #channelmix.mix-lfe    = false
6
+    #channelmix.mix-lfe    = true
7
     #channelmix.upmix      = true
8
     #channelmix.lfe-cutoff = 120
9
     #channelmix.fc-cutoff  = 6000
10
pipewire-0.3.62.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
36
 
1
@@ -46,19 +46,30 @@
2
     }
3
 
4
 
5
-# Extra modules can be loaded here. Setup in default.pa can be moved here
6
+# Extra scripts can be started here. Setup in default.pa can be moved in
7
+# a script or in pulse.cmd below
8
 context.exec = 
9
-    { path = "pactl"        args = "load-module module-always-sink" }
10
-    #{ path = "pactl"        args = "load-module module-switch-on-connect" }
11
+    #{ path = "pactl"        args = "load-module module-always-sink" }
12
+    #{ path = "pactl"        args = "upload-sample my-sample.wav my-sample" }
13
     #{ path = "/usr/bin/sh"  args = "~/.config/pipewire/default.pw" }
14
 
15
 
16
+# Extra commands can be executed here.
17
+#   load-module : loads a module with args and flags
18
+#      args = "<module-name> <module-args>"
19
+#      flags =  "no-fail" 
20
+pulse.cmd = 
21
+    { cmd = "load-module" args = "module-always-sink" flags =   }
22
+    #{ cmd = "load-module" args = "module-switch-on-connect" }
23
+    #{ cmd = "load-module" args = "module-gsettings" flags =  "nofail"  }
24
+
25
+
26
 stream.properties = {
27
     #node.latency          = 1024/48000
28
     #node.autoconnect      = true
29
     #resample.quality      = 4
30
     #channelmix.normalize  = false
31
-    #channelmix.mix-lfe    = false
32
+    #channelmix.mix-lfe    = true
33
     #channelmix.upmix      = true
34
     #channelmix.upmix-method = psd  # none, simple
35
     #channelmix.lfe-cutoff = 150
36
pipewire-0.3.62.tar.gz/src/modules/meson.build -> pipewire-0.3.63.tar.gz/src/modules/meson.build Changed
18
 
1
@@ -100,7 +100,7 @@
2
   'module-filter-chain/convolver.c'
3
 
4
 filter_chain_dependencies = 
5
-  mathlib, dl_lib, pipewire_dep, sndfile_dep
6
+  mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep
7
 
8
 
9
 if lilv_lib.found()
10
@@ -226,6 +226,7 @@
11
   'module-protocol-pulse.c',
12
   'module-protocol-pulse/client.c',
13
   'module-protocol-pulse/collect.c',
14
+  'module-protocol-pulse/cmd.c',
15
   'module-protocol-pulse/extension.c',
16
   'module-protocol-pulse/extensions/ext-device-manager.c',
17
   'module-protocol-pulse/extensions/ext-device-restore.c',
18
pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.63.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
118
 
1
@@ -31,7 +31,9 @@
2
 #endif
3
 
4
 #include <spa/utils/json.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/support/cpu.h>
7
+#include <spa/plugins/audioconvert/resample.h>
8
 
9
 #include <pipewire/log.h>
10
 
11
@@ -539,6 +541,71 @@
12
    return samples;
13
 }
14
 
15
+static float *resample_buffer(float *samples, int *n_samples,
16
+       unsigned long in_rate, unsigned long out_rate, uint32_t quality)
17
+{
18
+   uint32_t in_len, out_len, total_out = 0;
19
+   int out_n_samples;
20
+   float *out_samples, *out_buf, *in_buf;
21
+   struct resample r;
22
+   int res;
23
+
24
+   spa_zero(r);
25
+   r.channels = 1;
26
+   r.i_rate = in_rate;
27
+   r.o_rate = out_rate;
28
+   r.cpu_flags = dsp_ops.cpu_flags;
29
+   r.quality = quality;
30
+   if ((res = resample_native_init(&r)) < 0) {
31
+       pw_log_error("resampling failed: %s", spa_strerror(res));
32
+       errno = -res;
33
+       return NULL;
34
+   }
35
+
36
+   out_n_samples = SPA_ROUND_UP(*n_samples * out_rate, in_rate) / in_rate;
37
+   out_samples = calloc(out_n_samples, sizeof(float));
38
+   if (out_samples == NULL)
39
+       goto error;
40
+
41
+   in_len = *n_samples;
42
+   in_buf = samples;
43
+   out_len = out_n_samples;
44
+   out_buf = out_samples;
45
+
46
+   pw_log_info("Resampling filter: rate: %lu => %lu, n_samples: %u => %u, q:%u",
47
+           in_rate, out_rate, in_len, out_len, quality);
48
+
49
+   resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len);
50
+   pw_log_debug("resampled: %u -> %u samples", in_len, out_len);
51
+   total_out += out_len;
52
+
53
+   in_len = resample_delay(&r);
54
+   in_buf = calloc(in_len, sizeof(float));
55
+   if (in_buf == NULL)
56
+       goto error;
57
+
58
+   out_buf = out_samples + total_out;
59
+   out_len = out_n_samples - total_out;
60
+
61
+   pw_log_debug("flushing resampler: %u in %u out", in_len, out_len);
62
+   resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len);
63
+   pw_log_debug("flushed: %u -> %u samples", in_len, out_len);
64
+   total_out += out_len;
65
+
66
+   free(in_buf);
67
+   free(samples);
68
+   resample_free(&r);
69
+
70
+   *n_samples = total_out;
71
+   return out_samples;
72
+
73
+error:
74
+   resample_free(&r);
75
+   free(samples);
76
+   free(out_samples);
77
+   return NULL;
78
+}
79
+
80
 static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
81
        unsigned long SampleRate, int index, const char *config)
82
 {
83
@@ -551,6 +618,7 @@
84
    char filenamePATH_MAX = "";
85
    int blocksize = 0, tailsize = 0;
86
    int delay = 0;
87
+   int resample_quality = RESAMPLE_DEFAULT_QUALITY;
88
    float gain = 1.0f;
89
    unsigned long rate;
90
 
91
@@ -611,6 +679,12 @@
92
                return NULL;
93
            }
94
        }
95
+       else if (spa_streq(key, "resample_quality")) {
96
+           if (spa_json_get_int(&it1, &resample_quality) <= 0) {
97
+               pw_log_error("convolver:resample_quality requires a number");
98
+               return NULL;
99
+           }
100
+       }
101
        else if (spa_json_next(&it1, &val) < 0)
102
            break;
103
    }
104
@@ -634,10 +708,9 @@
105
        rate = SampleRate;
106
        samples = read_samples(filename, gain, delay, offset,
107
                length, channel, &rate, &n_samples);
108
-       if (rate != SampleRate) {
109
-           pw_log_warn("Convolver samplerate %lu doesn't match filter rate %lu. "
110
-                   "Consider forcing a filter rate.", rate, SampleRate);
111
-       }
112
+       if (rate != SampleRate)
113
+           samples = resample_buffer(samples, &n_samples,
114
+                   rate, SampleRate, resample_quality);
115
    }
116
    if (samples == NULL) {
117
        errno = ENOENT;
118
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse.c Changed
17
 
1
@@ -305,6 +305,7 @@
2
 
3
 PW_LOG_TOPIC(mod_topic, "mod." NAME);
4
 #define PW_LOG_TOPIC_DEFAULT mod_topic
5
+PW_LOG_TOPIC(pulse_conn, "conn." NAME);
6
 PW_LOG_TOPIC(pulse_ext_dev_restore, "mod." NAME ".device-restore");
7
 PW_LOG_TOPIC(pulse_ext_stream_restore, "mod." NAME ".stream-restore");
8
 
9
@@ -354,6 +355,7 @@
10
    int res;
11
 
12
    PW_LOG_TOPIC_INIT(mod_topic);
13
+   PW_LOG_TOPIC_INIT(pulse_conn);
14
    /* it's easier to init these here than adding an init() call to the
15
     * extensions */
16
    PW_LOG_TOPIC_INIT(pulse_ext_dev_restore);
17
pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/cmd.c Added
138
 
1
@@ -0,0 +1,136 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/utils/json.h>
27
+
28
+#include <pipewire/utils.h>
29
+
30
+#include "module.h"
31
+#include "cmd.h"
32
+
33
+static const char WHITESPACE = " \t\n\r";
34
+
35
+static int do_load_module(struct impl *impl, char *args, const char *flags)
36
+{
37
+   int res, n;
38
+   struct module *module;
39
+   char *a2 = { NULL };
40
+
41
+   n = pw_split_ip(args, WHITESPACE, 2, a);
42
+   if (n < 1) {
43
+       pw_log_info("load-module expects module name");
44
+       return -EINVAL;
45
+   }
46
+
47
+   module = module_create(impl, a0, a1);
48
+   if (module == NULL)
49
+       return -errno;
50
+   if ((res = module_load(module)) < 0)
51
+       return res;
52
+
53
+   return res;
54
+}
55
+
56
+static int do_cmd(struct impl *impl, const char *cmd, char *args, const char *flags)
57
+{
58
+   int res = 0;
59
+   if (spa_streq(cmd, "load-module")) {
60
+       res = do_load_module(impl, args, flags);
61
+   } else {
62
+       pw_log_warn("ignoring unknown command `%s` with args `%s`",
63
+               cmd, args);
64
+   }
65
+   if (res < 0) {
66
+       if (flags && strstr(flags, "nofail")) {
67
+           pw_log_info("nofail command %s %s: %s",
68
+                   cmd, args, spa_strerror(res));
69
+           res = 0;
70
+       } else {
71
+           pw_log_error("can't run command %s %s: %s",
72
+                   cmd, args, spa_strerror(res));
73
+       }
74
+   }
75
+   return res;
76
+}
77
+
78
+/*
79
+ * pulse.cmd = 
80
+ *   { cmd = <command>  args = "<arguments>"  }
81
+ *   ...
82
+ * 
83
+ */
84
+static int parse_cmd(void *user_data, const char *location,
85
+       const char *section, const char *str, size_t len)
86
+{
87
+   struct impl *impl = user_data;
88
+   struct spa_json it3;
89
+   char key512, *s;
90
+   int res = 0;
91
+
92
+   s = strndup(str, len);
93
+   spa_json_init(&it0, s, len);
94
+   if (spa_json_enter_array(&it0, &it1) < 0) {
95
+       pw_log_error("config file error: pulse.cmd is not an array");
96
+       res = -EINVAL;
97
+       goto exit;
98
+   }
99
+
100
+   while (spa_json_enter_object(&it1, &it2) > 0) {
101
+       char *cmd = NULL, *args = NULL, *flags = NULL;
102
+
103
+       while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
104
+           const char *val;
105
+           int len;
106
+
107
+           if ((len = spa_json_next(&it2, &val)) <= 0)
108
+               break;
109
+
110
+           if (spa_streq(key, "cmd")) {
111
+               cmd = (char*)val;
112
+               spa_json_parse_stringn(val, len, cmd, len+1);
113
+           } else if (spa_streq(key, "args")) {
114
+               args = (char*)val;
115
+               spa_json_parse_stringn(val, len, args, len+1);
116
+           } else if (spa_streq(key, "flags")) {
117
+               if (spa_json_is_container(val, len))
118
+                   len = spa_json_container_len(&it2, val, len);
119
+               flags = (char*)val;
120
+               spa_json_parse_stringn(val, len, flags, len+1);
121
+           }
122
+       }
123
+       if (cmd != NULL)
124
+           res = do_cmd(impl, cmd, args, flags);
125
+       if (res < 0)
126
+           break;
127
+   }
128
+exit:
129
+   free(s);
130
+   return res;
131
+}
132
+
133
+int cmd_run(struct impl *impl)
134
+{
135
+   return pw_context_conf_section_for_each(impl->context, "pulse.cmd",
136
+               parse_cmd, impl);
137
+}
138
pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/cmd.h Added
34
 
1
@@ -0,0 +1,32 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef PULSER_SERVER_CMD_H
27
+#define PULSER_SERVER_CMD_H
28
+
29
+#include "internal.h"
30
+
31
+int cmd_run(struct impl *impl);
32
+
33
+#endif /* PULSER_SERVER_CMD_H */
34
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/message.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/message.c Changed
19
 
1
@@ -33,7 +33,6 @@
2
 #include "defs.h"
3
 #include "format.h"
4
 #include "internal.h"
5
-#include "log.h"
6
 #include "message.h"
7
 #include "remap.h"
8
 #include "volume.h"
9
@@ -47,6 +46,9 @@
10
 
11
 #define PA_CHANNELS_MAX    (32u)
12
 
13
+PW_LOG_TOPIC_EXTERN(pulse_conn);
14
+#define PW_LOG_TOPIC_DEFAULT pulse_conn
15
+
16
 static inline uint32_t volume_from_linear(float vol)
17
 {
18
    uint32_t v;
19
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
35
 
1
@@ -57,6 +57,7 @@
2
 #include "client.h"
3
 #include "collect.h"
4
 #include "commands.h"
5
+#include "cmd.h"
6
 #include "dbus-name.h"
7
 #include "defs.h"
8
 #include "extension.h"
9
@@ -94,6 +95,8 @@
10
 
11
 #define TEMPORARY_MOVE_TIMEOUT (SPA_NSEC_PER_SEC)
12
 
13
+PW_LOG_TOPIC_EXTERN(pulse_conn);
14
+
15
 bool debug_messages = false;
16
 
17
 struct latency_offset_data {
18
@@ -5625,7 +5628,7 @@
19
 
20
    load_defaults(&impl->defs, props);
21
 
22
-   debug_messages = pw_debug_is_category_enabled("connection");
23
+   debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
24
 
25
    impl->context = context;
26
    impl->loop = pw_context_get_main_loop(context);
27
@@ -5670,6 +5673,7 @@
28
 #ifdef HAVE_DBUS
29
    impl->dbus_name = dbus_request_name(context, "org.pulseaudio.Server");
30
 #endif
31
+   cmd_run(impl);
32
 
33
    return (struct pw_protocol_pulse *) impl;
34
 
35
pipewire-0.3.62.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.63.tar.gz/src/pipewire/pipewire.c Changed
201
 
1
@@ -64,7 +64,6 @@
2
    char *filename;
3
    void *hnd;
4
    spa_handle_factory_enum_func_t enum_func;
5
-   struct spa_list handles;
6
    int ref;
7
 };
8
 
9
@@ -78,10 +77,10 @@
10
 
11
 struct registry {
12
    struct spa_list plugins;
13
+   struct spa_list handles; /* all handles across all plugins by age (youngest first) */
14
 };
15
 
16
 struct support {
17
-   char **categories;
18
    const char *plugin_dir;
19
    const char *support_lib;
20
    struct registry registry;
21
@@ -93,6 +92,7 @@
22
    unsigned int in_valgrind:1;
23
    unsigned int no_color:1;
24
    unsigned int no_config:1;
25
+   unsigned int do_dlclose:1;
26
 };
27
 
28
 static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
29
@@ -149,7 +149,6 @@
30
    plugin->filename = strdup(filename);
31
    plugin->hnd = hnd;
32
    plugin->enum_func = enum_func;
33
-   spa_list_init(&plugin->handles);
34
 
35
    spa_list_append(&registry->plugins, &plugin->link);
36
 
37
@@ -168,7 +167,7 @@
38
    if (--plugin->ref == 0) {
39
        spa_list_remove(&plugin->link);
40
        pw_log_debug("unloaded plugin:'%s'", plugin->filename);
41
-       if (!global_support.in_valgrind)
42
+       if (global_support.do_dlclose)
43
            dlclose(plugin->hnd);
44
        free(plugin->filename);
45
        free(plugin);
46
@@ -290,7 +289,7 @@
47
    handle->ref = 1;
48
    handle->plugin = plugin;
49
    handle->factory_name = strdup(factory_name);
50
-   spa_list_append(&plugin->handles, &handle->link);
51
+   spa_list_prepend(&sup->registry.handles, &handle->link);
52
 
53
    return &handle->handle;
54
 
55
@@ -321,15 +320,13 @@
56
 static struct handle *find_handle(struct spa_handle *handle)
57
 {
58
    struct registry *registry = &global_support.registry;
59
-   struct plugin *p;
60
    struct handle *h;
61
 
62
-   spa_list_for_each(p, &registry->plugins, link) {
63
-       spa_list_for_each(h, &p->handles, link) {
64
-           if (&h->handle == handle)
65
-               return h;
66
-       }
67
+   spa_list_for_each(h, &registry->handles, link) {
68
+       if (&h->handle == handle)
69
+           return h;
70
    }
71
+
72
    return NULL;
73
 }
74
 
75
@@ -490,22 +487,30 @@
76
 }
77
 #endif
78
 
79
-static enum spa_log_level
80
-parse_log_level(const char *str)
81
-{
82
-   enum spa_log_level l = SPA_LOG_LEVEL_NONE;
83
-   switch(str0) {
84
-       case 'X': l = SPA_LOG_LEVEL_NONE; break;
85
-       case 'E': l = SPA_LOG_LEVEL_ERROR; break;
86
-       case 'W': l = SPA_LOG_LEVEL_WARN; break;
87
-       case 'I': l = SPA_LOG_LEVEL_INFO; break;
88
-       case 'D': l = SPA_LOG_LEVEL_DEBUG; break;
89
-       case 'T': l = SPA_LOG_LEVEL_TRACE; break;
90
+static bool
91
+parse_log_level(const char *str, enum spa_log_level *l)
92
+{
93
+   uint32_t lvl;
94
+   if (strlen(str) == 1) {
95
+       switch(str0) {
96
+       case 'X': lvl = SPA_LOG_LEVEL_NONE; break;
97
+       case 'E': lvl = SPA_LOG_LEVEL_ERROR; break;
98
+       case 'W': lvl = SPA_LOG_LEVEL_WARN; break;
99
+       case 'I': lvl = SPA_LOG_LEVEL_INFO; break;
100
+       case 'D': lvl = SPA_LOG_LEVEL_DEBUG; break;
101
+       case 'T': lvl = SPA_LOG_LEVEL_TRACE; break;
102
        default:
103
-             l = atoi(str);
104
-             break;
105
+             goto check_int;
106
+       }
107
+   } else {
108
+check_int:
109
+         if (!spa_atou32(str, &lvl, 0))
110
+             return false;
111
+         if (lvl > SPA_LOG_LEVEL_TRACE)
112
+             return false;
113
    }
114
-   return l;
115
+   *l = lvl;
116
+   return true;
117
 }
118
 
119
 static char *
120
@@ -518,6 +523,7 @@
121
    char json1024 = {0};
122
    char *pos = json;
123
    char *end = pos + sizeof(json) - 1;
124
+   enum spa_log_level lvl;
125
 
126
    str = getenv("PIPEWIRE_DEBUG");
127
 
128
@@ -530,13 +536,6 @@
129
     */
130
    pos += spa_scnprintf(pos, end - pos, " { conn.* = %d },", SPA_LOG_LEVEL_NONE);
131
 
132
-   /* We only have single-digit log levels, so any single-character
133
-    * string is of the form PIPEWIRE_DEBUG=<N> */
134
-   if (slen == 1) {
135
-       pw_log_set_level(parse_log_level(str));
136
-       goto out;
137
-   }
138
-
139
    tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens);
140
    if (n_tokens > 0) {
141
        int i;
142
@@ -544,24 +543,23 @@
143
            int n_tok;
144
            char **tok;
145
            char *pattern;
146
-           enum spa_log_level lvl;
147
 
148
            tok = pw_split_strv(tokensi, ":", 2, &n_tok);
149
-           if (n_tok == 2) {
150
+           if (n_tok == 2 && parse_log_level(tok1, &lvl)) {
151
                pattern = tok0;
152
-               lvl = parse_log_level(tok1);
153
-
154
                pos += spa_scnprintf(pos, end - pos, "{ %s = %d },",
155
                             pattern, lvl);
156
+           } else if (n_tok == 1 && parse_log_level(tok0, &lvl)) {
157
+               pw_log_set_level(lvl);
158
            } else {
159
-               pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'\n", tokensi);
160
+               pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'",
161
+                       tokensi);
162
            }
163
 
164
            pw_free_strv(tok);
165
        }
166
    }
167
    pw_free_strv(tokens);
168
-out:
169
    pos += spa_scnprintf(pos, end - pos, "");
170
    return strdup(json);
171
 }
172
@@ -594,6 +592,10 @@
173
    pthread_mutex_lock(&support_lock);
174
    support->in_valgrind = RUNNING_ON_VALGRIND;
175
 
176
+   support->do_dlclose = true;
177
+   if ((str = getenv("PIPEWIRE_DLCLOSE")) != NULL)
178
+       support->do_dlclose = pw_properties_parse_bool(str);
179
+
180
    if (getenv("NO_COLOR") != NULL)
181
        support->no_color = true;
182
 
183
@@ -611,6 +613,7 @@
184
    support->support_lib = str;
185
 
186
    spa_list_init(&support->registry.plugins);
187
+   spa_list_init(&support->registry.handles);
188
 
189
    if (pw_log_is_default()) {
190
        char *patterns = NULL;
191
@@ -684,7 +687,7 @@
192
 {
193
    struct support *support = &global_support;
194
    struct registry *registry = &support->registry;
195
-   struct plugin *p;
196
+   struct handle *h;
197
 
198
    pthread_mutex_lock(&init_lock);
199
    if (support->init_count == 0)
200
@@ -694,14 +697,10 @@
201
pipewire-0.3.62.tar.gz/src/pipewire/utils.c -> pipewire-0.3.63.tar.gz/src/pipewire/utils.c Changed
39
 
1
@@ -97,6 +97,37 @@
2
    return arr.data;
3
 }
4
 
5
+/** Split a string in-place based on delimiters
6
+ * \param str a string to split
7
+ * \param delimiter delimiter characters to split on
8
+ * \param max_tokens the max number of tokens to split
9
+ * \paramout tokens an array to hold up to \a max_tokens of strings
10
+ * \return the number of tokens in \a tokens
11
+ *
12
+ * \a str will be modified in-place so that \a tokens will contain zero terminated
13
+ * strings split at \a delimiter characters.
14
+ */
15
+SPA_EXPORT
16
+int pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens)
17
+{
18
+   const char *state = NULL;
19
+   char *s, *t;
20
+   size_t len, l2;
21
+   int n = 0;
22
+
23
+   s = (char *)pw_split_walk(str, delimiter, &len, &state);
24
+   while (s && n + 1 < max_tokens) {
25
+       t = (char*)pw_split_walk(str, delimiter, &l2, &state);
26
+       slen = '\0';
27
+       tokensn++ = s;
28
+       s = t;
29
+       len = l2;
30
+   }
31
+   if (s)
32
+       tokensn++ = s;
33
+   return n;
34
+}
35
+
36
 /** Free a NULL terminated array of strings
37
  * \param str a NULL terminated array of string
38
  *
39
pipewire-0.3.62.tar.gz/src/pipewire/utils.h -> pipewire-0.3.63.tar.gz/src/pipewire/utils.h Changed
11
 
1
@@ -58,6 +58,9 @@
2
 char **
3
 pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens);
4
 
5
+int
6
+pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens);
7
+
8
 void
9
 pw_free_strv(char **str);
10
 
11
pipewire-0.3.62.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.63.tar.gz/src/tools/pw-cli.c Changed
28
 
1
@@ -142,26 +142,6 @@
2
 static int children_of(struct remote_data *rd, uint32_t parent_id,
3
    const char *child_type, uint32_t **children);
4
 
5
-static int pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens)
6
-{
7
-   const char *state = NULL;
8
-   char *s, *t;
9
-   size_t len, l2;
10
-   int n = 0;
11
-
12
-   s = (char *)pw_split_walk(str, delimiter, &len, &state);
13
-   while (s && n + 1 < max_tokens) {
14
-       t = (char*)pw_split_walk(str, delimiter, &l2, &state);
15
-       slen = '\0';
16
-       tokensn++ = s;
17
-       s = t;
18
-       len = l2;
19
-   }
20
-   if (s)
21
-       tokensn++ = s;
22
-   return n;
23
-}
24
-
25
 static void print_properties(struct spa_dict *props, char mark, bool header)
26
 {
27
    const struct spa_dict_item *item;
28
pipewire-0.3.62.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.63.tar.gz/src/tools/pw-mon.c Changed
10
 
1
@@ -780,7 +780,7 @@
2
    if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL)
3
        colors = true;
4
 
5
-   while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) {
6
+   while ((c = getopt_long(argc, argv, "hVr:NC", long_options, NULL)) != -1) {
7
        switch (c) {
8
        case 'h':
9
            show_help(argv0, false);
10
pipewire-0.3.62.tar.gz/test/test-logger.c -> pipewire-0.3.63.tar.gz/test/test-logger.c Changed
23
 
1
@@ -350,8 +350,10 @@
2
        "invalid value",
3
        "*:5,some invalid value",
4
        "*:W,foo.bar:3,invalid:",
5
-       "*:W,1,foo.bar:D",
6
-       "*:W,D,foo.bar:3",
7
+       "*:W,2,foo.bar:Q",
8
+       "*:W,7,foo.bar:D",
9
+       "*:W,Q,foo.bar:5",
10
+       "*:W,D,foo.bar:8",
11
    };
12
 
13
    pwtest_int_lt(which, SPA_N_ELEMENTS(envvars));
14
@@ -644,7 +646,7 @@
15
           PWTEST_ARG_RANGE, SPA_LOG_LEVEL_NONE, SPA_LOG_LEVEL_TRACE + 1,
16
           PWTEST_NOARG);
17
    pwtest_add(logger_debug_env_invalid,
18
-          PWTEST_ARG_RANGE, 0, 5, /* see the test */
19
+          PWTEST_ARG_RANGE, 0, 7, /* see the test */
20
           PWTEST_NOARG);
21
    pwtest_add(logger_topics, PWTEST_NOARG);
22
    pwtest_add(logger_journal, PWTEST_NOARG);
23
pipewire-0.3.62.tar.gz/test/test-utils.c -> pipewire-0.3.63.tar.gz/test/test-utils.c Changed
24
 
1
@@ -193,6 +193,8 @@
2
 {
3
    const char *test1 = "a \n test string  \n \r ";
4
    const char *del = "\n\r ";
5
+   const char *test2 = "a:";
6
+   const char *del2 = ":";
7
    int n_tokens;
8
    char **res;
9
 
10
@@ -212,6 +214,13 @@
11
    pwtest_str_eq(res1, "test string  \n \r ");
12
    pwtest_ptr_null(res2);
13
    pw_free_strv(res);
14
+
15
+   res = pw_split_strv(test2, del2, 2, &n_tokens);
16
+   pwtest_ptr_notnull(res);
17
+   pwtest_int_eq(n_tokens, 1);
18
+   pwtest_str_eq(res0, "a");
19
+   pwtest_ptr_null(res1);
20
+   pw_free_strv(res);
21
 }
22
 
23
 PWTEST(utils_split)
24