Changes of Revision 44

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Mon Sep 16 18:48:10 UTC 2024 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 1.2.3
6
+
7
+-------------------------------------------------------------------
8
 Mon Aug 19 20:39:19 UTC 2024 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 1.2.2
11
pipewire-aptx.spec Changed
10
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        1.2.2
6
+Version:        1.2.3
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-1.2.2.tar.bz2/NEWS -> pipewire-1.2.3.tar.bz2/NEWS Changed
59
 
1
@@ -1,3 +1,47 @@
2
+# PipeWire 1.2.3 (2024-08-22)
3
+
4
+This is a bugfix release that is API and ABI compatible with the
5
+previous 1.2.x and 1.0.x releases.
6
+
7
+## Highlights
8
+  - Implement freewheeling support in the FFADO driver. Also improve
9
+    buffersize and samplerate handling.
10
+  - Improve some locking on spa_loop. Remove a possible deadlock when
11
+    the queue was full.
12
+  - Allocate more space for the libcamera devices string to properly
13
+    deduplicate libcamera and v4l2 devices.
14
+  - Some more bugfixes and improvements.
15
+
16
+
17
+## PipeWire
18
+  - Improve activation state changes and xrun detection some more.
19
+    (#4182)
20
+  - Avoid a memory leak when a link in error is destroyed.
21
+
22
+## Modules
23
+  - Improve samplerate and buffersize handling in FFADO driver so that
24
+    it is possible to force a rate and buffer size.
25
+  - Implement freewheeling support in the ffado driver.
26
+  - Always set the server side clock.quantum-limit on nodes. This fixes
27
+    a buffer size problem in Midi-bridge. (#4005)
28
+
29
+## SPA
30
+  - Improve some locking on spa_loop. Remove a possible deadlock when
31
+    the queue was full. (#4114)
32
+  - Allocate more space for the libcamera devices string to properly
33
+    deduplicate libcamera and v4l2 devices.
34
+  - Fix a potential race when enumerating v4l2 udev devices. (#3960)
35
+
36
+## Bluetooth
37
+  - Improve compatibility with some devices (Soundcore Motion 300).
38
+
39
+## Tools
40
+  - pw-cli can now handle arbitrarily large input and params. (#4166)
41
+  - Avoid some compiler warnings in pw-top.
42
+
43
+Older versions:
44
+
45
+
46
 # PipeWire 1.2.2 (2024-07-31)
47
 
48
 This is a bugfix release that is API and ABI compatible with the
49
@@ -44,9 +88,6 @@
50
   - Fix the jack_get_time() function, it was returning nano instead of micro
51
     seconds.
52
 
53
-Older versions:
54
-
55
-
56
 # PipeWire 1.2.1 (2024-07-12)
57
 
58
 This is a bugfix release that is API and ABI compatible with previous
59
pipewire-1.2.2.tar.bz2/meson.build -> pipewire-1.2.3.tar.bz2/meson.build Changed
26
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '1.2.2',
4
+  version : '1.2.3',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.61.1',
7
   default_options :  'warning_level=3',
8
@@ -284,10 +284,14 @@
9
 sdl_dep = dependency('sdl2', required : get_option('sdl2'))
10
 summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
11
 drm_dep = dependency('libdrm', required : false)
12
-readline_dep = dependency('readline', required : get_option('readline'))
13
 
14
-if not readline_dep.found()
15
-  readline_dep = cc.find_library('readline', required : get_option('readline'))
16
+if get_option('readline').disabled()
17
+  readline_dep = dependency('', required: false)
18
+else
19
+  readline_dep = dependency('readline', required : false)
20
+  if not readline_dep.found()
21
+    readline_dep = cc.find_library('readline', required : get_option('readline'))
22
+  endif
23
 endif
24
 
25
 # Both the FFmpeg SPA plugin and the pw-cat FFmpeg integration use libavcodec.
26
pipewire-1.2.2.tar.bz2/pipewire-jack/src/pipewire-jack.c -> pipewire-1.2.3.tar.bz2/pipewire-jack/src/pipewire-jack.c Changed
18
 
1
@@ -2314,13 +2314,14 @@
2
    struct link *l;
3
 
4
    pw_log_debug("%p prepared:%d ", c, c->rt.prepared);
5
-   if (!c->rt.prepared)
6
-       return 0;
7
 
8
    old_state = SPA_ATOMIC_XCHG(c->activation->status, PW_NODE_ACTIVATION_INACTIVE);
9
    if (old_state != PW_NODE_ACTIVATION_FINISHED)
10
        trigger = get_time_ns(c->l->system);
11
 
12
+   if (!c->rt.prepared)
13
+       return 0;
14
+
15
    spa_list_for_each(l, &c->rt.target_links, target_link) {
16
        if (!c->async && trigger != 0)
17
            l->trigger(l, trigger);
18
pipewire-1.2.2.tar.bz2/spa/plugins/alsa/alsa-pcm.c -> pipewire-1.2.3.tar.bz2/spa/plugins/alsa/alsa-pcm.c Changed
14
 
1
@@ -2292,8 +2292,10 @@
2
        last_pitch = (uint64_t)(1000000 / state->last_rate);
3
    }
4
 
5
-   /* The pitch adjustment is limited to 1 ppm */
6
-   if (pitch == last_pitch)
7
+   /* The pitch adjustment is limited to 1 ppm according to the spec, but
8
+    * let's avoid very granular changes so that we don't spam the host
9
+    * (and ourselves, if bind-ctls are enabled). */
10
+   if (SPA_ABS((int)pitch - (int)last_pitch) < 10)
11
        return 0;
12
 
13
    snd_ctl_elem_value_set_integer(state->pitch_elem, 0, pitch);
14
pipewire-1.2.2.tar.bz2/spa/plugins/bluez5/backend-native.c -> pipewire-1.2.3.tar.bz2/spa/plugins/bluez5/backend-native.c Changed
15
 
1
@@ -1012,6 +1012,13 @@
2
        }
3
 
4
        rfcomm_send_reply(rfcomm, "OK");
5
+   } else if (spa_strstartswith(buf, "AT+CCWA=")) {
6
+       /*
7
+        * Claim that call waiting notifications are supported.
8
+        * Required for some devices (e.g. Soundcore Motion 300),
9
+        * as they stop sending commands if the reply to CCWA is not OK.
10
+        */
11
+       rfcomm_send_reply(rfcomm, "OK");
12
    } else if (spa_strstartswith(buf, "AT+CLCC")) {
13
        struct spa_list *calls;
14
        struct call *call;
15
pipewire-1.2.2.tar.bz2/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-1.2.3.tar.bz2/spa/plugins/libcamera/libcamera-device.cpp Changed
10
 
1
@@ -119,7 +119,7 @@
2
    uint32_t n_items = 0;
3
    struct spa_device_info info;
4
    struct spa_param_info params2;
5
-   char path256, name256, devices_str128;
6
+   char path256, name256, devices_str256;
7
    struct spa_strbuf buf;
8
 
9
    info = SPA_DEVICE_INFO_INIT();
10
pipewire-1.2.2.tar.bz2/spa/plugins/support/loop.c -> pipewire-1.2.3.tar.bz2/spa/plugins/support/loop.c Changed
201
 
1
@@ -35,7 +35,6 @@
2
 #define ITEM_ALIGN 8
3
 #define DATAS_SIZE (4096*8)
4
 #define MAX_EP     32
5
-#define DEFAULT_RETRY  (1 * SPA_USEC_PER_SEC)
6
 
7
 /** \cond */
8
 
9
@@ -66,7 +65,6 @@
10
    struct spa_list destroy_list;
11
    struct spa_list queue_list;
12
    struct spa_hook_list hooks_list;
13
-   int retry_timeout;
14
 
15
    int poll_fd;
16
    pthread_t thread;
17
@@ -86,6 +84,11 @@
18
    struct impl *impl;
19
    struct spa_list link;
20
 
21
+#define QUEUE_FLAG_NONE        (0)
22
+#define QUEUE_FLAG_ACK_FD  (1<<0)
23
+   uint32_t flags;
24
+   struct queue *overflow;
25
+
26
    int ack_fd;
27
    struct spa_ratelimit rate_limit;
28
 
29
@@ -172,6 +175,52 @@
30
    return res;
31
 }
32
 
33
+static struct queue *loop_create_queue(void *object, uint32_t flags)
34
+{
35
+   struct impl *impl = object;
36
+   struct queue *queue;
37
+   int res;
38
+
39
+   queue = calloc(1, sizeof(struct queue));
40
+   if (queue == NULL)
41
+       return NULL;
42
+
43
+   queue->impl = impl;
44
+   queue->flags = flags;
45
+
46
+   queue->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
47
+   queue->rate_limit.burst = 1;
48
+
49
+   queue->buffer_data = SPA_PTR_ALIGN(queue->buffer_mem, MAX_ALIGN, uint8_t);
50
+   spa_ringbuffer_init(&queue->buffer);
51
+
52
+   if (flags & QUEUE_FLAG_ACK_FD) {
53
+       if ((res = spa_system_eventfd_create(impl->system,
54
+               SPA_FD_EVENT_SEMAPHORE | SPA_FD_CLOEXEC)) < 0) {
55
+           spa_log_error(impl->log, "%p: can't create ack event: %s",
56
+                   impl, spa_strerror(res));
57
+           goto error;
58
+       }
59
+       queue->ack_fd = res;
60
+   } else {
61
+       queue->ack_fd = -1;
62
+   }
63
+
64
+   pthread_mutex_lock(&impl->queue_lock);
65
+   spa_list_append(&impl->queue_list, &queue->link);
66
+   pthread_mutex_unlock(&impl->queue_lock);
67
+
68
+   spa_log_info(impl->log, "%p created queue %p", impl, queue);
69
+
70
+   return queue;
71
+
72
+error:
73
+   free(queue);
74
+   errno = -res;
75
+   return NULL;
76
+}
77
+
78
+
79
 static inline int32_t item_compare(struct invoke_item *a, struct invoke_item *b)
80
 {
81
    return (int32_t)(a->count - b->count);
82
@@ -185,7 +234,7 @@
83
    pthread_mutex_lock(&impl->queue_lock);
84
    flush_count = ++impl->flush_count;
85
    while (true) {
86
-       struct queue *cqueue, *queue;
87
+       struct queue *cqueue, *queue = NULL;
88
        struct invoke_item *citem, *item = NULL;
89
        uint32_t cindex, index;
90
        spa_invoke_func_t func;
91
@@ -228,7 +277,7 @@
92
        block = item->block;
93
        spa_ringbuffer_read_update(&queue->buffer, index);
94
 
95
-       if (block) {
96
+       if (block && queue->ack_fd != -1) {
97
            if ((res = spa_system_eventfd_write(impl->system, queue->ack_fd, 1)) < 0)
98
                spa_log_warn(impl->log, "%p: failed to write event fd:%d: %s",
99
                        queue, queue->ack_fd, spa_strerror(res));
100
@@ -313,7 +362,7 @@
101
    } else {
102
        loop_signal_event(impl, impl->wakeup);
103
 
104
-       if (block) {
105
+       if (block && queue->ack_fd != -1) {
106
            uint64_t count = 1;
107
 
108
            spa_loop_control_hook_before(&impl->hooks_list);
109
@@ -336,15 +385,18 @@
110
    return res;
111
 
112
 xrun:
113
-   nsec = get_time_ns(impl->system);
114
-   if ((suppressed = spa_ratelimit_test(&queue->rate_limit, nsec)) >= 0) {
115
-       spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)",
116
-               queue, avail, need, suppressed);
117
+   if (queue->overflow == NULL) {
118
+       nsec = get_time_ns(impl->system);
119
+       if ((suppressed = spa_ratelimit_test(&queue->rate_limit, nsec)) >= 0) {
120
+           spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)",
121
+                   queue, avail, need, suppressed);
122
+       }
123
+       queue->overflow = loop_create_queue(impl, QUEUE_FLAG_NONE);
124
+       if (queue->overflow == NULL)
125
+           return -errno;
126
+       queue->overflow->ack_fd = queue->ack_fd;
127
    }
128
-   loop_signal_event(impl, impl->wakeup);
129
-   if (impl->retry_timeout == 0)
130
-       return -EPIPE;
131
-   usleep(impl->retry_timeout);
132
+   queue = queue->overflow;
133
    goto retry;
134
 }
135
 
136
@@ -363,50 +415,11 @@
137
    spa_list_remove(&queue->link);
138
    pthread_mutex_unlock(&impl->queue_lock);
139
 
140
-   spa_system_close(impl->system, queue->ack_fd);
141
+   if (queue->flags & QUEUE_FLAG_ACK_FD)
142
+       spa_system_close(impl->system, queue->ack_fd);
143
    free(queue);
144
 }
145
 
146
-static struct queue *loop_create_queue(void *object, uint32_t flags)
147
-{
148
-   struct impl *impl = object;
149
-   struct queue *queue;
150
-   int res;
151
-
152
-   queue = calloc(1, sizeof(struct queue));
153
-   if (queue == NULL)
154
-       return NULL;
155
-
156
-   queue->impl = impl;
157
-
158
-   queue->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
159
-   queue->rate_limit.burst = 1;
160
-
161
-   queue->buffer_data = SPA_PTR_ALIGN(queue->buffer_mem, MAX_ALIGN, uint8_t);
162
-   spa_ringbuffer_init(&queue->buffer);
163
-
164
-   if ((res = spa_system_eventfd_create(impl->system,
165
-           SPA_FD_EVENT_SEMAPHORE | SPA_FD_CLOEXEC)) < 0) {
166
-       spa_log_error(impl->log, "%p: can't create ack event: %s",
167
-               impl, spa_strerror(res));
168
-       goto error;
169
-   }
170
-   queue->ack_fd = res;
171
-
172
-   pthread_mutex_lock(&impl->queue_lock);
173
-   spa_list_append(&impl->queue_list, &queue->link);
174
-   pthread_mutex_unlock(&impl->queue_lock);
175
-
176
-   spa_log_info(impl->log, "%p created queue %p", impl, queue);
177
-
178
-   return queue;
179
-
180
-error:
181
-   free(queue);
182
-   errno = -res;
183
-   return NULL;
184
-}
185
-
186
 static int loop_invoke(void *object, spa_invoke_func_t func, uint32_t seq,
187
        const void *data, size_t size, bool block, void *user_data)
188
 {
189
@@ -414,7 +427,7 @@
190
    struct queue *local_queue = tss_get(impl->queue_tss_id);
191
 
192
    if (local_queue == NULL) {
193
-       local_queue = loop_create_queue(impl, 0);
194
+       local_queue = loop_create_queue(impl, QUEUE_FLAG_ACK_FD);
195
        if (local_queue == NULL)
196
            return -errno;
197
        tss_set(impl->queue_tss_id, local_queue);
198
@@ -1120,13 +1133,10 @@
199
            SPA_VERSION_LOOP_UTILS,
200
            &impl_loop_utils, impl);
201
pipewire-1.2.2.tar.bz2/spa/plugins/v4l2/v4l2-udev.c -> pipewire-1.2.3.tar.bz2/spa/plugins/v4l2/v4l2-udev.c Changed
24
 
1
@@ -477,9 +477,6 @@
2
 
3
    spa_loop_add_source(this->main_loop, &this->notify);
4
 
5
-   for (size_t i = 0; i < this->n_devices; i++)
6
-       start_watching_device(this, &this->devicesi);
7
-
8
    return 0;
9
 }
10
 
11
@@ -628,10 +625,10 @@
12
 
13
    emit_device_info(this, true);
14
 
15
-   if ((res = enum_devices(this)) < 0)
16
+   if ((res = start_monitor(this)) < 0)
17
        return res;
18
 
19
-   if ((res = start_monitor(this)) < 0)
20
+   if ((res = enum_devices(this)) < 0)
21
        return res;
22
 
23
         spa_hook_list_join(&this->hooks, &save);
24
pipewire-1.2.2.tar.bz2/src/daemon/pipewire.conf.in -> pipewire-1.2.3.tar.bz2/src/daemon/pipewire.conf.in Changed
19
 
1
@@ -254,7 +254,7 @@
2
             node.name       = Dummy-Driver
3
             node.group      = pipewire.dummy
4
             node.sync-group  = sync.dummy
5
-            priority.driver = 20000
6
+            priority.driver = 200000
7
             #clock.id       = monotonic # realtime | tai | monotonic-raw | boottime
8
             #clock.name     = "clock.system.monotonic"
9
         }
10
@@ -263,7 +263,7 @@
11
         args = {
12
             factory.name    = support.node.driver
13
             node.name       = Freewheel-Driver
14
-            priority.driver = 19000
15
+            priority.driver = 190000
16
             node.group      = pipewire.freewheel
17
             node.sync-group  = sync.dummy
18
             node.freewheel  = true
19
pipewire-1.2.2.tar.bz2/src/modules/module-ffado-driver.c -> pipewire-1.2.3.tar.bz2/src/modules/module-ffado-driver.c Changed
201
 
1
@@ -44,9 +44,9 @@
2
  *
3
  * - `driver.mode`: the driver mode, sink|source|duplex, default duplex
4
  * - `ffado.devices`: array of devices to open, default "hw:0"
5
- * - `ffado.period-size`: period size,default 1024
6
+ * - `ffado.period-size`: period size,default 1024. A value of 0 will use the graph duration.
7
  * - `ffado.period-num`: period number,default 3
8
- * - `ffado.sample-rate`: sample-rate, default 48000
9
+ * - `ffado.sample-rate`: sample-rate, default 48000. A value of 0 will use the graph rate.
10
  * - `ffado.slave-mode`: slave mode
11
  * - `ffado.snoop-mode`: snoop mode
12
  * - `ffado.verbose`: ffado verbose level
13
@@ -192,7 +192,10 @@
14
 
15
    unsigned int ready:1;
16
    unsigned int running:1;
17
-   unsigned int transfered:1;
18
+
19
+   struct {
20
+       unsigned int transfered:1;
21
+   } rt;
22
 };
23
 
24
 struct impl {
25
@@ -244,19 +247,22 @@
26
    uint32_t output_latency;
27
    uint32_t quantum_limit;
28
 
29
-   uint32_t pw_xrun;
30
-   uint32_t ffado_xrun;
31
    uint32_t frame_time;
32
 
33
    unsigned int do_disconnect:1;
34
    unsigned int fix_midi:1;
35
    unsigned int started:1;
36
+   unsigned int freewheel:1;
37
 
38
    pthread_t thread;
39
 
40
-   unsigned int done:1;
41
-   unsigned int triggered:1;
42
-   unsigned int new_xrun:1;
43
+   struct {
44
+       unsigned int done:1;
45
+       unsigned int triggered:1;
46
+       unsigned int new_xrun:1;
47
+       uint32_t pw_xrun;
48
+       uint32_t ffado_xrun;
49
+   } rt;
50
 };
51
 
52
 static int stop_ffado_device(struct impl *impl);
53
@@ -573,9 +579,9 @@
54
    struct impl *impl = s->impl;
55
    uint32_t i, n_samples = position->clock.duration;
56
 
57
-   pw_log_trace_fp("process %d", impl->triggered);
58
-   if (impl->mode == MODE_SINK && impl->triggered) {
59
-       impl->triggered = false;
60
+   pw_log_trace_fp("process %d", impl->rt.triggered);
61
+   if (impl->mode == MODE_SINK && impl->rt.triggered) {
62
+       impl->rt.triggered = false;
63
        return;
64
    }
65
 
66
@@ -599,11 +605,11 @@
67
        p->cleared = false;
68
    }
69
    ffado_streaming_transfer_playback_buffers(impl->dev);
70
-   s->transfered = true;
71
+   s->rt.transfered = true;
72
 
73
    if (impl->mode == MODE_SINK) {
74
        pw_log_trace_fp("done %u", impl->frame_time);
75
-       impl->done = true;
76
+       impl->rt.done = true;
77
        set_timeout(impl, position->clock.nsec);
78
    }
79
 }
80
@@ -616,10 +622,10 @@
81
    for (i = 0; i < s->n_ports; i++) {
82
        struct port *p = s->portsi;
83
        if (p != NULL)
84
-           clear_port_buffer(p, impl->period_size);
85
+           clear_port_buffer(p, impl->device_options.period_size);
86
    }
87
    ffado_streaming_transfer_playback_buffers(impl->dev);
88
-   s->transfered = true;
89
+   s->rt.transfered = true;
90
 }
91
 
92
 static void source_process(void *d, struct spa_io_position *position)
93
@@ -628,21 +634,24 @@
94
    struct impl *impl = s->impl;
95
    uint32_t i, n_samples = position->clock.duration;
96
 
97
-   pw_log_trace_fp("process %d", impl->triggered);
98
+   pw_log_trace_fp("process %d", impl->rt.triggered);
99
+
100
+   if (SPA_FLAG_IS_SET(impl->position->clock.flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER))
101
+       return;
102
 
103
-   if (!impl->triggered) {
104
+   if (!impl->rt.triggered) {
105
        pw_log_trace_fp("done %u", impl->frame_time);
106
-       impl->done = true;
107
-       if (!impl->sink.transfered)
108
+       impl->rt.done = true;
109
+       if (!impl->sink.rt.transfered)
110
            silence_playback(impl);
111
        set_timeout(impl, position->clock.nsec);
112
        return;
113
    }
114
 
115
-   impl->triggered = false;
116
+   impl->rt.triggered = false;
117
 
118
    ffado_streaming_transfer_capture_buffers(impl->dev);
119
-   s->transfered = true;
120
+   s->rt.transfered = true;
121
 
122
    for (i = 0; i < s->n_ports; i++) {
123
        struct port *p = s->portsi;
124
@@ -666,10 +675,28 @@
125
 {
126
    struct stream *s = data;
127
    struct impl *impl = s->impl;
128
+   bool freewheel;
129
+
130
    if (port_data == NULL) {
131
        switch (id) {
132
        case SPA_IO_Position:
133
            impl->position = area;
134
+           freewheel = impl->position != NULL &&
135
+               SPA_FLAG_IS_SET(impl->position->clock.flags, SPA_IO_CLOCK_FLAG_FREEWHEEL);
136
+           if (impl->freewheel != freewheel) {
137
+               pw_log_info("freewheel: %d -> %d", impl->freewheel, freewheel);
138
+               impl->freewheel = freewheel;
139
+               if (impl->started) {
140
+                   if (freewheel) {
141
+                       set_timeout(impl, 0);
142
+                       ffado_streaming_stop(impl->dev);
143
+                   } else {
144
+                       ffado_streaming_start(impl->dev);
145
+                       impl->rt.done = true;
146
+                       set_timeout(impl, get_time_ns(impl));
147
+                   }
148
+               }
149
+           }
150
            break;
151
        default:
152
            break;
153
@@ -895,6 +922,31 @@
154
    .process = source_process,
155
 };
156
 
157
+static int update_stream_format(struct stream *s, uint32_t samplerate)
158
+{
159
+   uint8_t buffer1024;
160
+   struct spa_pod_builder b;
161
+   uint32_t n_params;
162
+   const struct spa_pod *params2;
163
+
164
+   if (s->info.rate == samplerate)
165
+       return 0;
166
+
167
+   s->info.rate = samplerate;
168
+
169
+   if (s->filter == NULL)
170
+       return 0;
171
+
172
+   n_params = 0;
173
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
174
+   paramsn_params++ = spa_format_audio_raw_build(&b,
175
+           SPA_PARAM_EnumFormat, &s->info);
176
+   paramsn_params++ = spa_format_audio_raw_build(&b,
177
+           SPA_PARAM_Format, &s->info);
178
+
179
+   return pw_filter_update_params(s->filter, NULL, params, n_params);
180
+}
181
+
182
 static int make_stream(struct stream *s, const char *name)
183
 {
184
    struct impl *impl = s->impl;
185
@@ -902,11 +954,6 @@
186
    const struct spa_pod *params4;
187
    uint8_t buffer1024;
188
    struct spa_pod_builder b;
189
-   struct spa_latency_info latency;
190
-
191
-   spa_zero(latency);
192
-   n_params = 0;
193
-   spa_pod_builder_init(&b, buffer, sizeof(buffer));
194
 
195
    s->filter = pw_filter_new(impl->core, name, pw_properties_copy(s->props));
196
    if (s->filter == NULL)
197
@@ -923,6 +970,8 @@
198
 
199
    reset_volume(&s->volume, s->info.channels);
200
 
201
pipewire-1.2.2.tar.bz2/src/modules/module-portal.c -> pipewire-1.2.3.tar.bz2/src/modules/module-portal.c Changed
10
 
1
@@ -58,7 +58,7 @@
2
  * ## Example configuration
3
  *\code{.unparsed}
4
  * context.modules = 
5
- *  {   name = libpipewire-portal }
6
+ *  {   name = libpipewire-module-portal }
7
  * 
8
  *\endcode
9
  *
10
pipewire-1.2.2.tar.bz2/src/modules/module-raop-discover.c -> pipewire-1.2.3.tar.bz2/src/modules/module-raop-discover.c Changed
10
 
1
@@ -56,7 +56,7 @@
2
  *
3
  *\code{.unparsed}
4
  * context.modules = 
5
- * {   name = libpipewire-raop-discover
6
+ * {   name = libpipewire-module-raop-discover
7
  *     args = {
8
  *         #roap.discover-local = false;
9
  *         #raop.latency.ms = 1000
10
pipewire-1.2.2.tar.bz2/src/modules/module-x11-bell.c -> pipewire-1.2.3.tar.bz2/src/modules/module-x11-bell.c Changed
10
 
1
@@ -50,7 +50,7 @@
2
  * ## Example configuration
3
  *\code{.unparsed}
4
  * context.modules = 
5
- *  {   name = libpipewire-x11-bell }
6
+ *  {   name = libpipewire-module-x11-bell }
7
  *      args = {
8
  *          #sink.name = @DEFAULT_SINK@
9
  *          sample.name = "bell-window-system"
10
pipewire-1.2.2.tar.bz2/src/modules/spa/spa-node.c -> pipewire-1.2.3.tar.bz2/src/modules/spa/spa-node.c Changed
21
 
1
@@ -243,15 +243,14 @@
2
    struct pw_loop *loop;
3
    struct match match;
4
 
5
-   if (properties) {
6
-       p = pw_context_get_properties(context);
7
-       pw_properties_set(properties, "clock.quantum-limit",
8
-               pw_properties_get(p, "default.clock.quantum-limit"));
9
-   } else {
10
+   if (properties == NULL) {
11
        properties = pw_properties_new(NULL, NULL);
12
        if (properties == NULL)
13
            return NULL;
14
    }
15
+   p = pw_context_get_properties(context);
16
+   pw_properties_set(properties, "clock.quantum-limit",
17
+           pw_properties_get(p, "default.clock.quantum-limit"));
18
 
19
    match = MATCH_INIT(properties);
20
    pw_context_conf_section_match_rules(context, "node.rules",
21
pipewire-1.2.2.tar.bz2/src/pipewire/impl-link.c -> pipewire-1.2.3.tar.bz2/src/pipewire/impl-link.c Changed
9
 
1
@@ -1557,6 +1557,7 @@
2
 
3
    free(link->name);
4
    free(link->info.format);
5
+   free((char *) link->info.error);
6
    free(impl);
7
 }
8
 
9
pipewire-1.2.2.tar.bz2/src/pipewire/impl-node.c -> pipewire-1.2.3.tar.bz2/src/pipewire/impl-node.c Changed
182
 
1
@@ -222,15 +222,14 @@
2
    pw_log_trace("%p: unprepare %d remote:%d exported:%d", this, this->rt.prepared,
3
            this->remote, this->exported);
4
 
5
-   if (!this->exported) {
6
-       /* We mark ourself as finished now, this will avoid going further into the process loop
7
-        * in case our fd was ready (removing ourselfs from the loop should avoid that as well).
8
-        * If we were supposed to be scheduled make sure we continue the graph for the peers we
9
-        * were supposed to trigger */
10
-       old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, PW_NODE_ACTIVATION_INACTIVE);
11
-       if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state))
12
-           trigger = get_time_ns(this->rt.target.system);
13
-   }
14
+   /* We mark ourself as finished now, this will avoid going further into the process loop
15
+    * in case our fd was ready (removing ourselfs from the loop should avoid that as well).
16
+    * If we were supposed to be scheduled make sure we continue the graph for the peers we
17
+    * were supposed to trigger */
18
+   old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, PW_NODE_ACTIVATION_INACTIVE);
19
+   if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state))
20
+       trigger = get_time_ns(this->rt.target.system);
21
+
22
    if (!this->rt.prepared)
23
        return 0;
24
 
25
@@ -1345,7 +1344,7 @@
26
        str_status(status), suppressed);
27
 }
28
 
29
-static inline void debug_xrun_graph(struct pw_impl_node *driver, uint64_t nsec)
30
+static inline void debug_xrun_graph(struct pw_impl_node *driver, uint64_t nsec, uint32_t old_status)
31
 {
32
    int suppressed;
33
    enum spa_log_level level = SPA_LOG_LEVEL_DEBUG;
34
@@ -1354,15 +1353,16 @@
35
    if ((suppressed = spa_ratelimit_test(&driver->rt.rate_limit, nsec)) >= 0)
36
        level = SPA_LOG_LEVEL_WARN;
37
 
38
-   pw_log(level, "(%s-%u) graph xrun (%d suppressed)",
39
-           driver->name, driver->info.id, suppressed);
40
+   pw_log(level, "(%s-%u) graph xrun %s (%d suppressed)",
41
+           driver->name, driver->info.id, str_status(old_status), suppressed);
42
 
43
    spa_list_for_each(t, &driver->rt.target_list, link) {
44
        struct pw_node_activation *a = t->activation;
45
        struct pw_node_activation_state *state = &a->state0;
46
+       uint32_t status = SPA_ATOMIC_LOAD(a->status);
47
 
48
-       if (a->status == PW_NODE_ACTIVATION_TRIGGERED ||
49
-           a->status == PW_NODE_ACTIVATION_AWAKE) {
50
+       if (status == PW_NODE_ACTIVATION_TRIGGERED ||
51
+           status == PW_NODE_ACTIVATION_AWAKE) {
52
            pw_log(level, "(%s-%u) xrun state:%p pending:%d/%d s:%"PRIu64" a:%"PRIu64" f:%"PRIu64
53
                    " waiting:%"PRIu64" process:%"PRIu64" status:%s",
54
                    t->name, t->id, state,
55
@@ -1372,7 +1372,7 @@
56
                    a->finish_time,
57
                    a->awake_time - a->signal_time,
58
                    a->finish_time - a->awake_time,
59
-                   str_status(a->status));
60
+                   str_status(status));
61
 
62
        }
63
    }
64
@@ -1393,6 +1393,7 @@
65
    spa_list_for_each(t, &driver->rt.target_list, link) {
66
        struct pw_node_activation *a = t->activation;
67
        struct pw_node_activation_state *state = &a->state0;
68
+       uint32_t status = SPA_ATOMIC_LOAD(a->status);
69
 
70
        if (!a->pending_sync)
71
            continue;
72
@@ -1406,7 +1407,7 @@
73
                a->finish_time,
74
                a->awake_time - a->signal_time,
75
                a->finish_time - a->awake_time,
76
-               str_status(a->status));
77
+               str_status(status));
78
    }
79
 }
80
 
81
@@ -1442,7 +1443,8 @@
82
    struct pw_impl_port *p;
83
    struct pw_node_activation *a = this->rt.target.activation;
84
    struct spa_system *data_system = this->rt.target.system;
85
-   int status, old_status;
86
+   int status;
87
+   bool was_awake;
88
 
89
    if (!SPA_ATOMIC_CAS(a->status,
90
                PW_NODE_ACTIVATION_TRIGGERED,
91
@@ -1450,8 +1452,8 @@
92
        return 0;
93
 
94
    a->awake_time = nsec;
95
-   pw_log_trace_fp("%p: %s process remote:%u exported:%u %"PRIu64" %"PRIu64,
96
-           this, this->name, this->remote, this->exported,
97
+   pw_log_trace_fp("%p: %s-%d process remote:%u exported:%u %"PRIu64" %"PRIu64,
98
+           this, this->name, this->info.id, this->remote, this->exported,
99
            a->signal_time, nsec);
100
 
101
    /* when transport sync is not supported, just clear the flag */
102
@@ -1481,15 +1483,18 @@
103
    a->state0.status = status;
104
 
105
    nsec = get_time_ns(data_system);
106
-   old_status = SPA_ATOMIC_XCHG(a->status, PW_NODE_ACTIVATION_FINISHED);
107
+   was_awake = SPA_ATOMIC_CAS(a->status,
108
+               PW_NODE_ACTIVATION_AWAKE,
109
+               PW_NODE_ACTIVATION_FINISHED);
110
    a->finish_time = nsec;
111
 
112
-   pw_log_trace_fp("%p: finished status:%d %"PRIu64, this, status, nsec);
113
+   pw_log_trace_fp("%p: finished status:%d %"PRIu64" was_awake:%d",
114
+           this, status, nsec, was_awake);
115
 
116
    /* we don't need to trigger targets when the node was driving the
117
     * graph because that means we finished the graph. */
118
    if (SPA_LIKELY(!this->driving)) {
119
-       if ((!this->async || a->server_version < 1) && old_status == PW_NODE_ACTIVATION_AWAKE)
120
+       if ((!this->async || a->server_version < 1) && was_awake)
121
            trigger_targets(this, status, nsec);
122
    } else {
123
        /* calculate CPU time when finished */
124
@@ -1535,8 +1540,9 @@
125
                    nsec / 1000, 0);
126
        }
127
 
128
-       pw_log_trace_fp("%p: remote:%u exported:%u %s got process %"PRIu64,
129
-               this, this->remote, this->exported, this->name, nsec);
130
+       pw_log_trace_fp("%p: remote:%u exported:%u %s-%d got process %"PRIu64,
131
+               this, this->remote, this->exported, this->name, this->info.id,
132
+               nsec);
133
 
134
        process_node(this, nsec);
135
    }
136
@@ -2004,13 +2010,12 @@
137
    struct pw_impl_node *node = data;
138
    struct pw_impl_node *driver = node->driver_node;
139
    struct pw_node_activation *a = node->rt.target.activation;
140
-   struct pw_node_activation_state *state = &a->state0;
141
    struct spa_system *data_system = node->rt.target.system;
142
    struct pw_node_target *t, *reposition_target = NULL;;
143
    struct pw_impl_port *p;
144
    struct spa_io_clock *cl = &node->rt.position->clock;
145
    int sync_type, all_ready, update_sync, target_sync, old_status;
146
-   uint32_t owner2, reposition_owner, pending;
147
+   uint32_t owner2, reposition_owner;
148
    uint64_t min_timeout = UINT64_MAX, nsec;
149
 
150
    pw_log_trace_fp("%p: ready driver:%d exported:%d %p status:%d prepared:%d", node,
151
@@ -2031,15 +2036,25 @@
152
 
153
    nsec = get_time_ns(data_system);
154
 
155
-   if (SPA_UNLIKELY((pending = pw_node_activation_state_xchg(state)) > 0)) {
156
-       pw_impl_node_rt_emit_incomplete(driver);
157
+   while (true) {
158
        old_status = SPA_ATOMIC_LOAD(a->status);
159
-       if (old_status != PW_NODE_ACTIVATION_FINISHED) {
160
-           SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED);
161
+       if (SPA_LIKELY(old_status == PW_NODE_ACTIVATION_FINISHED))
162
+           /* all good, graph completed */
163
+           break;
164
+       if (SPA_ATOMIC_CAS(a->status, old_status, PW_NODE_ACTIVATION_TRIGGERED)) {
165
+           /* if we got triggered but did not run the processing yet we don't
166
+            * really have an error so we can skip the error reporting. We need
167
+            * to run recovery anyway because the ready callback is already
168
+            * emitted */
169
+           if (old_status != PW_NODE_ACTIVATION_TRIGGERED) {
170
+               /* otherwise, something was wrong and we debug */
171
+               debug_xrun_graph(node, nsec, old_status);
172
+               pw_impl_node_rt_emit_incomplete(driver);
173
+           }
174
            SPA_FLAG_SET(cl->flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER);
175
            process_node(node, nsec);
176
            SPA_FLAG_CLEAR(cl->flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER);
177
-           debug_xrun_graph(node, nsec);
178
+           break;
179
        }
180
    }
181
 
182
pipewire-1.2.2.tar.bz2/src/pipewire/keys.h -> pipewire-1.2.3.tar.bz2/src/pipewire/keys.h Changed
23
 
1
@@ -74,9 +74,6 @@
2
 #define PW_KEY_LOOP_CLASS      "loop.class"        /**< the classes this loop handles, array of strings */
3
 #define PW_KEY_LOOP_RT_PRIO        "loop.rt-prio"      /**< realtime priority of the loop */
4
 #define PW_KEY_LOOP_CANCEL     "loop.cancel"       /**< if the loop can be canceled */
5
-#define PW_KEY_LOOP_RETRY_TIMEOUT  "loop.retry-timeout"    /**< when the loop invoke queue is full, the timeout
6
-                                 *  in microseconds before retrying.
7
-                                 *  default = 1 second, 0 = disable */
8
 
9
 /* context */
10
 #define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules"   /**< a context profile for modules, deprecated */
11
@@ -368,9 +365,11 @@
12
 # ifdef PW_ENABLE_DEPRECATED
13
 #  define PW_KEY_PRIORITY_MASTER   "priority.master"   /**< deprecated, use priority.driver */
14
 #  define PW_KEY_NODE_TARGET       "node.target"       /**< deprecated since 0.3.64, use target.object. */
15
+#  define PW_KEY_LOOP_RETRY_TIMEOUT    "loop.retry-timeout"    /**< deprecated since 1.3.0 */
16
 # else
17
 #  define PW_KEY_PRIORITY_MASTER   PW_DEPRECATED("priority.master")
18
 #  define PW_KEY_NODE_TARGET       PW_DEPRECATED("node.target")
19
+#  define PW_KEY_LOOP_RETRY_TIMEOUT    PW_DEPRECATED("loop.retry-timeout")
20
 # endif /* PW_ENABLE_DEPRECATED */
21
 #endif /* PW_REMOVE_DEPRECATED */
22
 
23
pipewire-1.2.2.tar.bz2/src/pipewire/private.h -> pipewire-1.2.3.tar.bz2/src/pipewire/private.h Changed
40
 
1
@@ -654,17 +654,21 @@
2
 {
3
    struct pw_node_activation *a = t->activation;
4
    struct pw_node_activation_state *state = &a->state0;
5
+   int32_t pending = SPA_ATOMIC_DEC(state->pending);
6
 
7
    pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node,
8
-           t->name, t->id, state, state->pending, state->required);
9
+               t->name, t->id, state, pending, state->required);
10
 
11
-   if (pw_node_activation_state_dec(state)) {
12
+   if (pending == 0) {
13
        if (SPA_ATOMIC_CAS(a->status,
14
                    PW_NODE_ACTIVATION_NOT_TRIGGERED,
15
                    PW_NODE_ACTIVATION_TRIGGERED)) {
16
            a->signal_time = nsec;
17
            if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
18
                pw_log_warn("%p: write failed %m", t->node);
19
+       } else {
20
+           pw_log_trace_fp("%p: (%s-%u) not ready %d", t->node,
21
+                   t->name, t->id, a->status);
22
        }
23
    }
24
 }
25
@@ -673,11 +677,12 @@
26
 {
27
    struct pw_node_activation *a = t->activation;
28
    struct pw_node_activation_state *state = &a->state0;
29
+   int32_t pending = SPA_ATOMIC_DEC(state->pending);
30
 
31
    pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node,
32
-           t->name, t->id, state, state->pending, state->required);
33
+           t->name, t->id, state, pending, state->required);
34
 
35
-   if (pw_node_activation_state_dec(state)) {
36
+   if (pending == 0) {
37
        SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED);
38
        a->signal_time = nsec;
39
        if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
40
pipewire-1.2.2.tar.bz2/src/tools/pw-cli.c -> pipewire-1.2.3.tar.bz2/src/tools/pw-cli.c Changed
100
 
1
@@ -32,7 +32,7 @@
2
 #include <spa/debug/pod.h>
3
 #include <spa/utils/keys.h>
4
 #include <spa/utils/json-pod.h>
5
-#include <spa/pod/builder.h>
6
+#include <spa/pod/dynamic.h>
7
 
8
 #include <pipewire/impl.h>
9
 #include <pipewire/i18n.h>
10
@@ -1777,10 +1777,12 @@
11
    uint32_t param_id;
12
    struct global *global;
13
    uint8_t buffer1024;
14
-   struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
15
+   spa_auto(spa_pod_dynamic_builder) b = { 0 };
16
    const struct spa_type_info *ti;
17
    struct spa_pod *pod;
18
 
19
+   spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
20
+
21
    n = pw_split_ip(args, WHITESPACE, 3, a);
22
    if (n < 3) {
23
        *error = spa_aprintf("%s <object-id> <param-id> <param-json>", cmd);
24
@@ -1802,11 +1804,11 @@
25
        *error = spa_aprintf("%s: unknown param type: %s", cmd, a1);
26
        return false;
27
    }
28
-   if ((res = spa_json_to_pod(&b, 0, ti, a2, strlen(a2))) < 0) {
29
+   if ((res = spa_json_to_pod(&b.b, 0, ti, a2, strlen(a2))) < 0) {
30
        *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
31
        return false;
32
    }
33
-   if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) {
34
+   if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) {
35
        *error = spa_aprintf("%s: can't make pod", cmd);
36
        return false;
37
    }
38
@@ -1911,10 +1913,12 @@
39
    int res, n;
40
    struct global *global;
41
    uint8_t buffer1024;
42
-   struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
43
+   spa_auto(spa_pod_dynamic_builder) b = { 0 };
44
    const struct spa_type_info *ti;
45
    struct spa_pod *pod;
46
 
47
+   spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
48
+
49
    n = pw_split_ip(args, WHITESPACE, 3, a);
50
    if (n < 3) {
51
        *error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd);
52
@@ -1943,11 +1947,11 @@
53
        *error = spa_aprintf("%s: unknown node command type: %s", cmd, a1);
54
        return false;
55
    }
56
-   if ((res = spa_json_to_pod(&b, 0, ti, a2, strlen(a2))) < 0) {
57
+   if ((res = spa_json_to_pod(&b.b, 0, ti, a2, strlen(a2))) < 0) {
58
        *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
59
        return false;
60
    }
61
-   if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) {
62
+   if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) {
63
        *error = spa_aprintf("%s: can't make pod", cmd);
64
        return false;
65
    }
66
@@ -2387,23 +2391,26 @@
67
        readline_cleanup();
68
 #endif
69
    } else {
70
-       char buf4096, *p, *error;
71
+       FILE *buf;
72
+       char *error, *ptr;
73
+       size_t size;
74
 
75
-       p = buf;
76
-       for (i = optind; i < argc; i++) {
77
-           p = stpcpy(p, argvi);
78
-           p = stpcpy(p, " ");
79
-       }
80
+       buf = open_memstream(&ptr, &size);
81
+       for (i = optind; i < argc; i++)
82
+           fprintf(buf, "%s%s", i == optind ? "" : " ", argvi);
83
+       fclose(buf);
84
 
85
        // If we're monitoring, surface info changes as well
86
        data.monitoring_info = monitor;
87
 
88
        pw_main_loop_run(data.loop);
89
 
90
-       if (!parse(&data, buf, &error)) {
91
+       if (!parse(&data, ptr, &error)) {
92
            fprintf(stderr, "Error: \"%s\"\n", error);
93
            free(error);
94
        }
95
+       free(ptr);
96
+
97
        if (data.current != NULL)
98
            data.current->prompt_pending = pw_core_sync(data.current->core, 0, 0);
99
 
100
pipewire-1.2.2.tar.bz2/src/tools/pw-top.c -> pipewire-1.2.3.tar.bz2/src/tools/pw-top.c Changed
12
 
1
@@ -253,7 +253,9 @@
2
            {
3
                struct spa_audio_info_iec958 info = { 0 };
4
                if (spa_format_audio_iec958_parse(param, &info) >= 0) {
5
-                   snprintf(n->format, sizeof(n->format), "IEC958 %s %d",
6
+                   /* MAX_FORMAT is 16 bytes + \0: 8 bytes in this string, upto 6 bytes for the rate,
7
+                    * leaving us 2 for the format */
8
+                   snprintf(n->format, sizeof(n->format), "IEC958 %2.2s %d",
9
                        spa_debug_type_find_short_name(
10
                            spa_type_audio_iec958_codec, info.codec),
11
                        info.rate);
12