Changes of Revision 35

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Sun Oct  8 16:26:36 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.81
6
+
7
+-------------------------------------------------------------------
8
 Fri Sep 22 17:21:32 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.80
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.80
6
+Version:        0.3.81
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.80.tar.gz/.gitlab-ci.yml -> pipewire-0.3.81.tar.gz/.gitlab-ci.yml Changed
18
 
1
@@ -458,8 +458,15 @@
2
   extends:
3
     - .build_on_fedora
4
   stage: analysis
5
+  variables:
6
+    MESON_OPTIONS: >-
7
+        -Dpipewire-v4l2=enabled
8
+        -Dpipewire-jack=enabled
9
   script:
10
-    - shellcheck $(git grep -l "#\!/.*bin/.*sh")
11
+    - echo "Configuring with meson options $MESON_OPTIONS"
12
+    - meson setup "$BUILD_DIR" --prefix="$PREFIX" $MESON_OPTIONS
13
+    - shellcheck $(git ls-files '*.sh')
14
+    - shellcheck $(grep -rl "#\!/.*bin/.*sh" "$BUILD_DIR")
15
 
16
 spellcheck:
17
   extends:
18
pipewire-0.3.80.tar.gz/NEWS -> pipewire-0.3.81.tar.gz/NEWS Changed
100
 
1
@@ -1,3 +1,88 @@
2
+# PipeWire 0.3.81 (2023-10-06)
3
+
4
+This is the first 1.0 release candidate that is API and ABI compatible
5
+with previous 0.3.x releases.
6
+
7
+## Highlights
8
+  - jackdbus support is now enabled by default.
9
+  - IRQ based scheduling in ALSA was improved and enabled by default for
10
+    Pro-Audio profile. It will also link the pcms together to get lower
11
+    latency. This now matches what JACK does and gives equal latency to
12
+    PipeWire for Pro-Audio profiles.
13
+  - Support both old and new versions of webrtc-audio-processing to make
14
+    the transition easier.
15
+  - Forced quantum changes by nodes or metadata will now also force a
16
+    suspend and resume of the graph, like the rate changes to make sure all
17
+    nodes adapt to the new quantum. This is important for Pro-Audio nodes
18
+    that need to reconfigure the hardware to a new period in IRQ based
19
+    scheduling.
20
+  - Fix a regression in regex parsing.
21
+  - Many bugfixes and improvements.
22
+
23
+
24
+## PipeWire
25
+  - jackdbus is by default enabled now. The idea is that when jackdbus is
26
+    installed, the real libjack.so is in the path and we can become a
27
+    real JACK client.
28
+  - Forces quantum changes by nodes or metadata will now also force a
29
+    suspend and resume in the graph, like the rate changes to make sure all
30
+    nodes adapt to the new quantum. This is important for Pro-Audio nodes
31
+    that need to reconfigure the hardware to a new period.
32
+  - The stream now has an EARLY_PROCESS option that can be used to implement
33
+    custum buffer fill levels. (#3480)
34
+  - Fix a regression in regex parsing. (#3528)
35
+  - Fix a bug in position reporting in the driver node. (#3189) (#3544)
36
+  - Destroying a link will now recalculate the graph correctly.
37
+  - Fix the rate comparison for finding the best rate in the graph.
38
+  - Use malloc_trim() when available to release memory. (#1840)
39
+
40
+## Tools
41
+  - pw-cat now supports DFF DSD files.
42
+  - pw-cli avoid some NULL derefs in some cases.
43
+
44
+## Modules
45
+  - The RAOP sink has seen some cleanups and improvements. It will now ask
46
+    for feedback every 2 seconds to keep some devices alive.
47
+  - A bug in filter-chain was fixed where it would fail to apply the gain
48
+    when mixing just one source.
49
+  - The filter-chain can now pass the stream volume to a control in the
50
+    filter-chain graph. (#3434)
51
+  - Improve volume handling in RAOP sink.
52
+
53
+## Pulse-server
54
+  - Some cleanup in the pending_stream handling.
55
+  - Fix a regression in the event emission code where it failed to emit
56
+    a changed event when a node was linked. (#3522)
57
+  - Lower the realtime priority of pulseaudio clients.
58
+  - Set pulse.module.id on the echo-cancel streams. (#3541)
59
+
60
+## SPA
61
+  - Support both old and new versions of webrtc-audio-processing to make
62
+    the transition easier.
63
+  - The ALSA driver now does the sync of all followers directly from the
64
+    wakeup event. This results in more stable rate matching.
65
+  - IRQ based scheduling in ALSA was improved and enabled by default for
66
+    Pro-Audio profile. It will also link the pcms together to get lower
67
+    latency. This now matches what JACK does and gives equal latency to
68
+    PipeWire for Pro-Audio profiles.
69
+  - GNU/Hurd support was added.
70
+  - Some improvements to passthrough handling.
71
+
72
+## Bluetooth
73
+  - Improvements to the codec handling when PipeWire is used as Audio
74
+    Gateway.
75
+  - Adapt to new Bluez API for BAP devices.
76
+
77
+## JACK
78
+  - When the jack library is set in the default library path, avoid using
79
+    LD_LIBRARY_PATH because this can cause confusion.
80
+  - Handle clearing the latency on a port.
81
+  - jack_property now always manages to actually change the metadata because
82
+    it waits for a roundtrip before exiting.
83
+
84
+Older versions:
85
+
86
+
87
 # PipeWire 0.3.80 (2023-09-14)
88
 
89
 This is a bugfix release that is API and ABI compatible with previous
90
@@ -63,9 +148,6 @@
91
   - The mixer io areas are updated and handled safely now to avoid
92
     crashes. (#3506)
93
 
94
-Older versions:
95
-
96
-
97
 # PipeWire 0.3.79 (2023-08-29)
98
 
99
 This is a quick bugfix release that is API and ABI compatible with previous
100
pipewire-0.3.80.tar.gz/doc/input-filter-h.sh -> pipewire-0.3.81.tar.gz/doc/input-filter-h.sh Changed
9
 
1
@@ -11,6 +11,7 @@
2
 # Add \ingroup commands for the file, for each \addgroup in it
3
 BASEFILE=$(echo "$FILENAME" | sed -e 's@.*src/pipewire/@pipewire/@; s@.*spa/include/spa/@spa/@; s@.*src/test/@test/@;')
4
 
5
+# shellcheck disable=SC2028 # \file is not an escape sequence
6
 echo "/** \file"
7
 echo "\`$BASEFILE\`"
8
 sed -n -e '/.*\\addtogroup a-zA-Z0-9_.*/ { s/.*addtogroup /\\ingroup /; p; }' < "$FILENAME" | sort | uniq
9
pipewire-0.3.80.tar.gz/meson.build -> pipewire-0.3.81.tar.gz/meson.build Changed
57
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.80',
4
+  version : '0.3.81',
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
@@ -23,15 +23,15 @@
9
 spaversion = '0.2'
10
 apiversion = '0.3'
11
 soversion = 0
12
-libversion = '@0@.@1@.0'.format(soversion, pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int())
13
+libversion_minor = pipewire_version_major.to_int() * 1000 + pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()
14
+libversion = '@0@.@1@.0'.format(soversion, libversion_minor)
15
 
16
 # LADI/jack
17
 # 3, for PipeWire being the third JACK implementation, after JACK1 and jackdmp/JACK2)
18
 jack_version_major = 3
19
-jack_version_minor = pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()
20
+jack_version_minor = libversion_minor
21
 # libjackserver version has 0 for major (for compatibility with other implementations),
22
-# 3 for minor, and "100*pipewire_version_minor + pipewire_version_micro"
23
-# as micro version (the minor libpipewire soversion number)
24
+# 3 for minor, and "1000*major + 100*minor + micro" as micro version (the minor libpipewire soversion number)
25
 libjackversion = '@0@.@1@.@2@'.format(soversion, jack_version_major, jack_version_minor)
26
 
27
 pipewire_name = 'pipewire-@0@'.format(apiversion)
28
@@ -377,9 +377,17 @@
29
 
30
 webrtc_dep = dependency('webrtc-audio-processing-1',
31
   version : '>= 1.2' ,
32
-  required : get_option('echo-cancel-webrtc'))
33
-summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
34
-cdata.set('HAVE_WEBRTC', webrtc_dep.found())
35
+  required : false)
36
+cdata.set('HAVE_WEBRTC1', webrtc_dep.found())
37
+if webrtc_dep.found()
38
+  summary({'WebRTC Echo Canceling >= 1.2': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
39
+else
40
+  webrtc_dep = dependency('webrtc-audio-processing',
41
+    version : '>= 0.2', '< 1.0',
42
+    required : get_option('echo-cancel-webrtc'))
43
+  cdata.set('HAVE_WEBRTC', webrtc_dep.found())
44
+  summary({'WebRTC Echo Canceling < 1.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
45
+endif
46
 
47
 # On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd()
48
 epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
49
@@ -427,6 +435,7 @@
50
   'reallocarray', '#include <stdlib.h>', '-D_GNU_SOURCE', ,
51
   'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', ,
52
   'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep,
53
+  'malloc_trim', '#include <malloc.h>', , ,
54
 
55
 
56
 foreach f : check_functions
57
pipewire-0.3.80.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.81.tar.gz/pipewire-jack/src/meson.build Changed
21
 
1
@@ -21,12 +21,19 @@
2
 if libjack_path == ''
3
   libjack_path = modules_install_dir / 'jack'
4
   libjack_path_dlopen = modules_install_dir_dlopen / 'jack'
5
+  libjack_path_enable = ''
6
+elif libjack_path == get_option('libdir') or libjack_path == pipewire_libdir
7
+  libjack_path = pipewire_libdir
8
+  libjack_path_dlopen = libjack_path
9
+  libjack_path_enable = '#'
10
 else
11
   libjack_path_dlopen = libjack_path
12
+  libjack_path_enable = ''
13
 endif
14
 
15
 tools_config = configuration_data()
16
 tools_config.set('LIBJACK_PATH', libjack_path_dlopen)
17
+tools_config.set('LIBJACK_PATH_ENABLE', libjack_path_enable)
18
 
19
 configure_file(input : 'pw-jack.in',
20
                output : 'pw-jack',
21
pipewire-0.3.80.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/metadata.c Changed
47
 
1
@@ -230,7 +230,7 @@
2
    pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", o->id, subject, key, value, type);
3
    if (update_property(c, subject, key, type, value))
4
        pw_metadata_set_property(c->metadata->proxy, o->id, key, type, value);
5
-   res = 0;
6
+   res = do_sync(c);
7
 done:
8
    pw_thread_loop_unlock(c->context.loop);
9
 
10
@@ -340,7 +340,7 @@
11
    pw_log_info("remove id:%u (%"PRIu64") '%s'", id, subject, key);
12
    pw_metadata_set_property(c->metadata->proxy,
13
            id, key, NULL, NULL);
14
-   res = 0;
15
+   res = do_sync(c);
16
 done:
17
    pw_thread_loop_unlock(c->context.loop);
18
 
19
@@ -365,7 +365,7 @@
20
    pw_log_info("remove id:%u (%"PRIu64")", id, subject);
21
    pw_metadata_set_property(c->metadata->proxy,
22
            id, NULL, NULL, NULL);
23
-   res = 0;
24
+   res = do_sync(c);
25
 done:
26
    pw_thread_loop_unlock(c->context.loop);
27
 
28
@@ -375,15 +375,17 @@
29
 SPA_EXPORT
30
 int jack_remove_all_properties (jack_client_t* client)
31
 {
32
+   int res;
33
    struct client *c = (struct client *) client;
34
 
35
    spa_return_val_if_fail(c != NULL, -EINVAL);
36
 
37
    pw_thread_loop_lock(c->context.loop);
38
    pw_metadata_clear(c->metadata->proxy);
39
+   res = do_sync(c);
40
    pw_thread_loop_unlock(c->context.loop);
41
 
42
-   return 0;
43
+   return res;
44
 }
45
 
46
 SPA_EXPORT
47
pipewire-0.3.80.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
24
 
1
@@ -2441,9 +2441,11 @@
2
    int res;
3
 
4
    if (param == NULL)
5
-       return 0;
6
-   if ((res = spa_latency_parse(param, &info)) < 0)
7
+       info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(p->direction));
8
+   else if ((res = spa_latency_parse(param, &info)) < 0)
9
        return res;
10
+   if (info.direction == p->direction)
11
+       return 0;
12
 
13
    current = &p->object->port.latencyinfo.direction;
14
    if (spa_latency_info_compare(current, &info) == 0)
15
@@ -2457,8 +2459,6 @@
16
            info.min_rate, info.max_rate,
17
            info.min_ns, info.max_ns);
18
 
19
-   if (info.direction == p->direction)
20
-       return 0;
21
 
22
    if (info.direction == SPA_DIRECTION_INPUT)
23
        mode = JackPlaybackLatency;
24
pipewire-0.3.80.tar.gz/pipewire-jack/src/pw-jack.in -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pw-jack.in Changed
13
 
1
@@ -52,7 +52,9 @@
2
    fi
3
    export PIPEWIRE_QUANTUM
4
 fi
5
-LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
6
-export LD_LIBRARY_PATH
7
+
8
+# shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell
9
+@LIBJACK_PATH_ENABLE@LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
10
+@LIBJACK_PATH_ENABLE@export LD_LIBRARY_PATH
11
 
12
 exec "$@"
13
pipewire-0.3.80.tar.gz/pipewire-v4l2/src/pw-v4l2.in -> pipewire-0.3.81.tar.gz/pipewire-v4l2/src/pw-v4l2.in Changed
9
 
1
@@ -37,6 +37,7 @@
2
 if  "$PW_UNINSTALLED" = 1  ; then
3
    PW_V4L2_LD_PRELOAD="$PW_BUILDDIR"'/pipewire-v4l2/src/libpw-v4l2.so'
4
 else
5
+   # shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell
6
    PW_V4L2_LD_PRELOAD='@LIBV4L2_PATH@/libpw-v4l2.so'
7
 fi
8
 
9
pipewire-0.3.80.tar.gz/spa/examples/adapter-control.c -> pipewire-0.3.81.tar.gz/spa/examples/adapter-control.c Changed
13
 
1
@@ -906,9 +906,9 @@
2
        printf("got error %d\n", res);
3
 }
4
 
5
-static char *getscale(uint32_t scale)
6
+static const char *getscale(uint32_t scale)
7
 {
8
-   char *scale_s = NULL;
9
+   const char *scale_s = NULL;
10
 
11
    if (scale == SPA_AUDIO_VOLUME_RAMP_LINEAR)
12
        scale_s = LINEAR;
13
pipewire-0.3.80.tar.gz/spa/include/spa/debug/log.h -> pipewire-0.3.81.tar.gz/spa/include/spa/debug/log.h Changed
12
 
1
@@ -15,6 +15,10 @@
2
 #include <spa/utils/defs.h>
3
 #include <spa/support/log.h>
4
 #include <spa/debug/context.h>
5
+#include <spa/debug/dict.h>
6
+#include <spa/debug/format.h>
7
+#include <spa/debug/mem.h>
8
+#include <spa/debug/pod.h>
9
 
10
 /**
11
  * \addtogroup spa_debug
12
pipewire-0.3.80.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-0.3.81.tar.gz/spa/include/spa/utils/cleanup.h Changed
47
 
1
@@ -35,15 +35,16 @@
2
 
3
 #define spa_exchange(var, new_value) \
4
 __extension__ ({ \
5
-   __typeof__(var) _old_value = (var); \
6
-   (var) = (new_value); \
7
+   __typeof__(var) *_ptr = &(var); \
8
+   __typeof__(var) _old_value = *_ptr; \
9
+   *_ptr = (new_value); \
10
    _old_value; \
11
 })
12
 
13
-#if __GNUC__ > 10 || defined(__clang__)
14
+#if __GNUC__ >= 10 || defined(__clang__)
15
 #define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
16
 #else
17
-#define spa_steal_ptr(ptr) ((__typeof__(ptr)) spa_exchange((ptr), NULL))
18
+#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
19
 #endif
20
 
21
 #define spa_steal_fd(fd) spa_exchange((fd), -1)
22
@@ -52,16 +53,6 @@
23
 
24
 #include <stdlib.h>
25
 
26
-
27
-#if __GNUC__ > 10 || defined(__clang__)
28
-#define spa_clear_ptr(ptr, destructor) \
29
-__extension__ ({ \
30
-   __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \
31
-   if (_old_value) \
32
-       destructor(_old_value); \
33
-   (void) 0; \
34
-})
35
-#else
36
 #define spa_clear_ptr(ptr, destructor) \
37
 __extension__ ({ \
38
    __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
39
@@ -69,7 +60,6 @@
40
        destructor(_old_value); \
41
    (void) 0; \
42
 })
43
-#endif
44
 
45
 static inline void _spa_autofree_cleanup_func(void *p)
46
 {
47
pipewire-0.3.80.tar.gz/spa/plugins/aec/aec-webrtc.cpp -> pipewire-0.3.81.tar.gz/spa/plugins/aec/aec-webrtc.cpp Changed
196
 
1
@@ -3,6 +3,8 @@
2
 /* SPDX-FileCopyrightText: Copyright © 2021 Arun Raghavan <arun@asymptotic.io> */
3
 /* SPDX-License-Identifier: MIT */
4
 
5
+#include "config.h"
6
+
7
 #include <memory>
8
 #include <utility>
9
 
10
@@ -13,7 +15,13 @@
11
 #include <spa/utils/json.h>
12
 #include <spa/support/plugin.h>
13
 
14
+#ifdef HAVE_WEBRTC
15
+#include <webrtc/modules/audio_processing/include/audio_processing.h>
16
+#include <webrtc/modules/interface/module_common_types.h>
17
+#include <webrtc/system_wrappers/include/trace.h>
18
+#else
19
 #include <modules/audio_processing/include/audio_processing.h>
20
+#endif
21
 
22
 struct impl_data {
23
    struct spa_handle handle;
24
@@ -39,6 +47,54 @@
25
    return default_value;
26
 }
27
 
28
+#ifdef HAVE_WEBRTC
29
+/*  f0 f1 f2  */
30
+static int parse_point(struct spa_json *it, float (&f)3)
31
+{
32
+   struct spa_json arr;
33
+   int i, res;
34
+
35
+   if (spa_json_enter_array(it, &arr) <= 0)
36
+       return -EINVAL;
37
+
38
+   for (i = 0; i < 3; i++) {
39
+       if ((res = spa_json_get_float(&arr, &fi)) <= 0)
40
+           return -EINVAL;
41
+   }
42
+   return 0;
43
+}
44
+
45
+/*  point1 point2 ...  */
46
+static int parse_mic_geometry(struct impl_data *impl, const char *mic_geometry,
47
+       std::vector<webrtc::Point>& geometry)
48
+{
49
+   int res;
50
+   size_t i;
51
+   struct spa_json it2;
52
+
53
+   spa_json_init(&it0, mic_geometry, strlen(mic_geometry));
54
+   if (spa_json_enter_array(&it0, &it1) <= 0) {
55
+       spa_log_error(impl->log, "Error: webrtc.mic-geometry expects an array");
56
+       return -EINVAL;
57
+   }
58
+
59
+   for (i = 0; i < geometry.size(); i++) {
60
+       float f3;
61
+
62
+       if ((res = parse_point(&it1, f)) < 0) {
63
+           spa_log_error(impl->log, "Error: can't parse webrtc.mic-geometry points: %d", res);
64
+           return res;
65
+       }
66
+
67
+       spa_log_info(impl->log, "mic %zd position: (%g %g %g)", i, f0, f1, f2);
68
+       geometryi.c0 = f0;
69
+       geometryi.c1 = f1;
70
+       geometryi.c2 = f2;
71
+   }
72
+   return 0;
73
+}
74
+#endif
75
+
76
 static int webrtc_init2(void *object, const struct spa_dict *args,
77
        struct spa_audio_info_raw *rec_info, struct spa_audio_info_raw *out_info,
78
        struct spa_audio_info_raw *play_info)
79
@@ -48,9 +104,18 @@
80
 
81
    bool high_pass_filter = webrtc_get_spa_bool(args, "webrtc.high_pass_filter", true);
82
    bool noise_suppression = webrtc_get_spa_bool(args, "webrtc.noise_suppression", true);
83
-   bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true);
84
    bool voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true);
85
-
86
+#ifdef HAVE_WEBRTC
87
+   bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true);
88
+   bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true);
89
+   // Disable experimental flags by default
90
+   bool experimental_agc = webrtc_get_spa_bool(args, "webrtc.experimental_agc", false);
91
+   bool experimental_ns = webrtc_get_spa_bool(args, "webrtc.experimental_ns", false);
92
+
93
+   bool beamforming = webrtc_get_spa_bool(args, "webrtc.beamforming", false);
94
+#else
95
+   bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true);
96
+#endif
97
    // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech,
98
    // result in very poor performance, disable by default
99
    bool gain_control = webrtc_get_spa_bool(args, "webrtc.gain_control", false);
100
@@ -59,6 +124,51 @@
101
    // This filter will modify playback buffer (when calling ProcessReverseStream), but now
102
    // playback buffer modifications are discarded.
103
 
104
+#ifdef HAVE_WEBRTC
105
+   webrtc::Config config;
106
+   config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(extended_filter));
107
+   config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(delay_agnostic));
108
+   config.Set<webrtc::ExperimentalAgc>(new webrtc::ExperimentalAgc(experimental_agc));
109
+   config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(experimental_ns));
110
+
111
+   if (beamforming) {
112
+       std::vector<webrtc::Point> geometry(rec_info->channels);
113
+       const char *mic_geometry, *target_direction;
114
+
115
+       /* The beamformer gives a single mono channel */
116
+       out_info->channels = 1;
117
+       out_info->position0 = SPA_AUDIO_CHANNEL_MONO;
118
+
119
+       if ((mic_geometry = spa_dict_lookup(args, "webrtc.mic-geometry")) == NULL) {
120
+           spa_log_error(impl->log, "Error: webrtc.beamforming requires webrtc.mic-geometry");
121
+           return -EINVAL;
122
+       }
123
+
124
+       if ((res = parse_mic_geometry(impl, mic_geometry, geometry)) < 0)
125
+           return res;
126
+
127
+       if ((target_direction = spa_dict_lookup(args, "webrtc.target-direction")) != NULL) {
128
+           webrtc::SphericalPointf direction(0.0f, 0.0f, 0.0f);
129
+           struct spa_json it;
130
+           float f3;
131
+
132
+           spa_json_init(&it, target_direction, strlen(target_direction));
133
+           if (parse_point(&it, f) < 0) {
134
+               spa_log_error(impl->log, "Error: can't parse target-direction %s",
135
+                       target_direction);
136
+               return -EINVAL;
137
+           }
138
+
139
+           direction.s0 = f0;
140
+           direction.s1 = f1;
141
+           direction.s2 = f2;
142
+
143
+           config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry, direction));
144
+       } else {
145
+           config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
146
+       }
147
+   }
148
+#else
149
    webrtc::AudioProcessing::Config config;
150
    config.echo_canceller.enabled = true;
151
    // FIXME: Example code enables both gain controllers, but that seems sus
152
@@ -73,6 +183,7 @@
153
    // FIXME: expose pre/postamp gain
154
    config.transient_suppression.enabled = transient_suppression;
155
    config.voice_detection.enabled = voice_detection;
156
+#endif
157
 
158
    webrtc::ProcessingConfig pconfig = {{
159
        webrtc::StreamConfig(rec_info->rate, rec_info->channels, false), /* input stream */
160
@@ -81,15 +192,35 @@
161
        webrtc::StreamConfig(play_info->rate, play_info->channels, false), /* reverse output stream */
162
    }};
163
 
164
+#ifdef HAVE_WEBRTC
165
+   auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
166
+#else
167
    auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessingBuilder().Create());
168
 
169
    apm->ApplyConfig(config);
170
+#endif
171
 
172
    if ((res = apm->Initialize(pconfig)) != webrtc::AudioProcessing::kNoError) {
173
        spa_log_error(impl->log, "Error initialising webrtc audio processing module: %d", res);
174
        return -EINVAL;
175
    }
176
 
177
+#ifdef HAVE_WEBRTC
178
+   apm->high_pass_filter()->Enable(high_pass_filter);
179
+   // Always disable drift compensation since PipeWire will already do
180
+   // drift compensation on all sinks and sources linked to this echo-canceler
181
+   apm->echo_cancellation()->enable_drift_compensation(false);
182
+   apm->echo_cancellation()->Enable(true);
183
+   // TODO: wire up supression levels to args
184
+   apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression);
185
+   apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh);
186
+   apm->noise_suppression()->Enable(noise_suppression);
187
+   apm->voice_detection()->Enable(voice_detection);
188
+   // TODO: wire up AGC parameters to args
189
+   apm->gain_control()->set_analog_level_limits(0, 255);
190
+   apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
191
+   apm->gain_control()->Enable(gain_control);
192
+#endif
193
    impl->apm = std::move(apm);
194
    impl->rec_info = *rec_info;
195
    impl->out_info = *out_info;
196
pipewire-0.3.80.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/acp/acp.c Changed
19
 
1
@@ -388,6 +388,8 @@
2
                pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
3
                pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
4
                pa_proplist_setf(m->output_proplist, "device.profile.pro", "true");
5
+               pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
6
+               pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
7
                pa_alsa_close(&m->output_pcm);
8
                m->supported = true;
9
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
10
@@ -419,6 +421,8 @@
11
                pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
12
                pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
13
                pa_proplist_setf(m->input_proplist, "device.profile.pro", "true");
14
+               pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
15
+               pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
16
                pa_alsa_close(&m->input_pcm);
17
                m->supported = true;
18
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
19
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c Changed
16
 
1
@@ -843,12 +843,12 @@
2
 
3
    nextptr = device + 3;
4
    for (value_index = 0; ; ++value_index) {
5
-       char *value_label;
6
+       const char *value_label;
7
 
8
        switch (value_index) {
9
        case 0: value_label = "card"; break;
10
        case 1: value_label = "device"; break;
11
-       default: assert(false);
12
+       default: spa_assert_not_reached();
13
        }
14
 
15
        errno = 0;
16
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c Changed
15
 
1
@@ -252,9 +252,13 @@
2
 
3
    switch (id) {
4
    case SPA_IO_Clock:
5
+       if (size > 0 && size < sizeof(struct spa_io_clock))
6
+           return -EINVAL;
7
        this->clock = data;
8
        break;
9
    case SPA_IO_Position:
10
+       if (size > 0 && size < sizeof(struct spa_io_position))
11
+           return -EINVAL;
12
        this->position = data;
13
        break;
14
    default:
15
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-source.c Changed
10
 
1
@@ -235,6 +235,8 @@
2
        this->clock = data;
3
        break;
4
    case SPA_IO_Position:
5
+       if (size > 0 && size < sizeof(struct spa_io_position))
6
+           return -EINVAL;
7
        this->position = data;
8
        break;
9
    default:
10
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
201
 
1
@@ -17,6 +17,7 @@
2
 #include "alsa-pcm.h"
3
 
4
 static struct spa_list cards = SPA_LIST_INIT(&cards);
5
+static struct spa_list states = SPA_LIST_INIT(&states);
6
 
7
 static struct card *find_card(uint32_t index)
8
 {
9
@@ -501,6 +502,9 @@
10
    int err;
11
    const char *str;
12
 
13
+   spa_list_init(&state->followers);
14
+   spa_list_init(&state->rt.followers);
15
+
16
    snd_config_update_free_global();
17
 
18
    if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL)
19
@@ -508,6 +512,7 @@
20
 
21
    state->multi_rate = true;
22
    state->htimestamp = false;
23
+   state->disable_tsched = state->is_pro;
24
    for (i = 0; info && i < info->n_items; i++) {
25
        const char *k = info->itemsi.key;
26
        const char *s = info->itemsi.value;
27
@@ -547,6 +552,8 @@
28
    }
29
    CHECK(snd_output_stdio_attach(&state->output, state->log_file, 0), "attach failed");
30
 
31
+   spa_list_append(&states, &state->link);
32
+
33
    state->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
34
    state->rate_limit.burst = 1;
35
 
36
@@ -557,6 +564,7 @@
37
 {
38
    int err;
39
 
40
+   spa_list_remove(&state->link);
41
    release_card(state->card);
42
 
43
    state->card = NULL;
44
@@ -584,7 +592,7 @@
45
    err = snd_ctl_open(&state->ctl, device_name, SND_CTL_NONBLOCK);
46
    if (err < 0) {
47
        spa_log_info(state->log, "%s could not find ctl device: %s",
48
-               state->props.device, snd_strerror(err));
49
+               device_name, snd_strerror(err));
50
        state->ctl = NULL;
51
        goto error;
52
    }
53
@@ -599,7 +607,7 @@
54
    err = snd_ctl_elem_read(state->ctl, state->pitch_elem);
55
    if (err < 0) {
56
        spa_log_debug(state->log, "%s: did not find ctl %s: %s",
57
-               state->props.device, elem_name, snd_strerror(err));
58
+               device_name, elem_name, snd_strerror(err));
59
 
60
        snd_ctl_elem_value_free(state->pitch_elem);
61
        state->pitch_elem = NULL;
62
@@ -613,13 +621,34 @@
63
    CHECK(snd_ctl_elem_write(state->ctl, state->pitch_elem), "snd_ctl_elem_write");
64
    state->last_rate = 1.0;
65
 
66
-   spa_log_info(state->log, "%s: found ctl %s", state->props.device, elem_name);
67
+   spa_log_info(state->log, "%s: found ctl %s", device_name, elem_name);
68
    err = 0;
69
 error:
70
    snd_lib_error_set_handler(NULL);
71
    return err;
72
 }
73
 
74
+static int do_link(struct state *driver, struct state *state)
75
+{
76
+   int res;
77
+   snd_pcm_status_t *status;
78
+
79
+   snd_pcm_status_alloca(&status);
80
+   snd_pcm_status(driver->hndl, status);
81
+   snd_pcm_status_dump(status, state->output);
82
+   snd_pcm_status(state->hndl, status);
83
+   snd_pcm_status_dump(status, state->output);
84
+   fflush(state->log_file);
85
+
86
+   res = snd_pcm_link(driver->hndl, state->hndl);
87
+   if (res >= 0 || res == -EALREADY)
88
+       state->linked = true;
89
+
90
+   spa_log_info(state->log, "%p: linked to driver %p: %u (%s)",
91
+           state, driver, state->linked, snd_strerror(res));
92
+   return 0;
93
+}
94
+
95
 int spa_alsa_open(struct state *state, const char *params)
96
 {
97
    int err;
98
@@ -632,6 +661,8 @@
99
    spa_scnprintf(device_name, sizeof(device_name), "%s%s%s",
100
            state->card->ucm_prefix ? state->card->ucm_prefix : "",
101
            props->device, params ? params : "");
102
+   spa_scnprintf(state->name, sizeof(state->name), "%s%s",
103
+           props->device, state->stream == SND_PCM_STREAM_CAPTURE ? "c" : "p");
104
 
105
    spa_log_info(state->log, "%p: ALSA device open '%s' %s", state, device_name,
106
            state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback");
107
@@ -655,9 +686,6 @@
108
         * these are initialised in spa_alsa_start() */
109
    }
110
 
111
-   if (state->clock)
112
-       spa_scnprintf(state->clock->name, sizeof(state->clock->name),
113
-               "%s", state->clock_name);
114
    state->opened = true;
115
    state->sample_count = 0;
116
    state->sample_time = 0;
117
@@ -667,12 +695,32 @@
118
    return 0;
119
 
120
 error_exit_close:
121
-   spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->props.device,
122
+   spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->name,
123
            spa_strerror(err));
124
    snd_pcm_close(state->hndl);
125
    return err;
126
 }
127
 
128
+static void try_unlink(struct state *state)
129
+{
130
+   struct state *follower;
131
+
132
+   if (state->driver != NULL && state->linked) {
133
+       snd_pcm_unlink(state->hndl);
134
+       spa_log_info(state->log, "%p: unlinked from driver %p",
135
+               state, state->driver);
136
+       state->linked = false;
137
+   }
138
+   spa_list_for_each(follower, &state->followers, driver_link) {
139
+       if (follower->opened && follower->linked) {
140
+           snd_pcm_unlink(follower->hndl);
141
+           spa_log_info(state->log, "%p: follower unlinked from driver %p",
142
+               follower, state);
143
+           follower->linked = false;
144
+       }
145
+   }
146
+}
147
+
148
 int spa_alsa_close(struct state *state)
149
 {
150
    int err = 0;
151
@@ -680,11 +728,13 @@
152
    if (!state->opened)
153
        return 0;
154
 
155
+   try_unlink(state);
156
+
157
    spa_alsa_pause(state);
158
 
159
-   spa_log_info(state->log, "%p: Device '%s' closing", state, state->props.device);
160
+   spa_log_info(state->log, "%p: Device '%s' closing", state, state->name);
161
    if ((err = snd_pcm_close(state->hndl)) < 0)
162
-       spa_log_warn(state->log, "%s: close failed: %s", state->props.device,
163
+       spa_log_warn(state->log, "%s: close failed: %s", state->name,
164
                snd_strerror(err));
165
 
166
    if (!state->disable_tsched)
167
@@ -697,6 +747,7 @@
168
 
169
    state->have_format = false;
170
    state->opened = false;
171
+   state->linked = false;
172
 
173
    if (state->pitch_elem) {
174
        snd_ctl_elem_value_free(state->pitch_elem);
175
@@ -1094,7 +1145,7 @@
176
        CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &rchannels), "set_channels");
177
        if (state->default_channels != rchannels) {
178
            spa_log_warn(state->log, "%s: Channels doesn't match (requested %u, got %u)",
179
-               state->props.device, state->default_channels, rchannels);
180
+               state->name, state->default_channels, rchannels);
181
        }
182
    }
183
    if (state->default_rate != 0) {
184
@@ -1102,7 +1153,7 @@
185
        CHECK(snd_pcm_hw_params_set_rate_near(hndl, params, &rrate, 0), "set_rate_near");
186
        if (state->default_rate != rrate) {
187
            spa_log_warn(state->log, "%s: Rate doesn't match (requested %u, got %u)",
188
-               state->props.device, state->default_rate, rrate);
189
+               state->name, state->default_rate, rrate);
190
        }
191
    }
192
 
193
@@ -1164,7 +1215,7 @@
194
            }
195
        }
196
        spa_log_warn(state->log, "%s: no format found (def:%d) formats:%s",
197
-               state->props.device, state->default_format, buf);
198
+               state->name, state->default_format, buf);
199
 
200
        for (i = 0, offs = 0; i <= SND_PCM_ACCESS_LAST; i++) {
201
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
111
 
1
@@ -82,6 +82,15 @@
2
    uint32_t rate;
3
 };
4
 
5
+struct rt_state {
6
+   struct spa_list followers;
7
+   struct state *driver;
8
+   struct spa_list driver_link;
9
+
10
+   unsigned int sources_added:1;
11
+   unsigned int following:1;
12
+};
13
+
14
 struct state {
15
    struct spa_handle handle;
16
    struct spa_node node;
17
@@ -97,6 +106,7 @@
18
    struct card *card;
19
    snd_pcm_stream_t stream;
20
    snd_output_t *output;
21
+   char name64;
22
 
23
    struct spa_hook_list hooks;
24
    struct spa_callbacks callbacks;
25
@@ -111,7 +121,9 @@
26
    struct spa_param_info paramsN_NODE_PARAMS;
27
    struct props props;
28
 
29
-   bool opened;
30
+   unsigned int opened:1;
31
+   unsigned int prepared:1;
32
+   unsigned int started:1;
33
    snd_pcm_t *hndl;
34
 
35
    bool have_format;
36
@@ -127,9 +139,9 @@
37
    uint32_t allowed_ratesMAX_RATES;
38
    uint32_t n_allowed_rates;
39
    struct channel_map default_pos;
40
-   unsigned int disable_mmap;
41
-   unsigned int disable_batch;
42
-   unsigned int disable_tsched;
43
+   unsigned int disable_mmap:1;
44
+   unsigned int disable_batch:1;
45
+   unsigned int disable_tsched:1;
46
    char clock_name64;
47
    uint32_t quantum_limit;
48
 
49
@@ -141,9 +153,9 @@
50
    size_t frame_size;
51
    size_t frame_scale;
52
    int blocks;
53
-   uint32_t rate_denom;
54
    uint32_t delay;
55
    uint32_t read_size;
56
+   uint32_t max_read;
57
 
58
    uint64_t port_info_all;
59
    struct spa_port_info port_info;
60
@@ -169,7 +181,6 @@
61
 
62
    size_t ready_offset;
63
 
64
-   bool started;
65
    /* Either a single source for tsched, or a set of pollfds from ALSA */
66
    struct spa_source sourceMAX_POLL;
67
    int timerfd;
68
@@ -183,7 +194,9 @@
69
    uint32_t max_delay;
70
    uint32_t htimestamp_error;
71
 
72
-   uint32_t duration;
73
+   struct spa_fraction driver_rate;
74
+   uint32_t driver_duration;
75
+
76
    unsigned int alsa_started:1;
77
    unsigned int alsa_sync:1;
78
    unsigned int alsa_sync_warning:1;
79
@@ -200,6 +213,8 @@
80
    unsigned int multi_rate:1;
81
    unsigned int htimestamp:1;
82
    unsigned int is_pro:1;
83
+   unsigned int sources_added:1;
84
+   unsigned int linked:1;
85
 
86
    uint64_t iec958_codecs;
87
 
88
@@ -222,6 +237,14 @@
89
    snd_ctl_t *ctl;
90
    snd_ctl_elem_value_t *pitch_elem;
91
    double last_rate;
92
+
93
+   struct spa_list link;
94
+
95
+   struct spa_list followers;
96
+   struct state *driver;
97
+   struct spa_list driver_link;
98
+
99
+   struct rt_state rt;
100
 };
101
 
102
 struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
103
@@ -240,6 +263,7 @@
104
 int spa_alsa_clear(struct state *state);
105
 
106
 int spa_alsa_open(struct state *state, const char *params);
107
+int spa_alsa_prepare(struct state *state);
108
 int spa_alsa_start(struct state *state);
109
 int spa_alsa_reassign_follower(struct state *state);
110
 int spa_alsa_pause(struct state *state);
111
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
79
 
1
@@ -373,9 +373,6 @@
2
    struct spa_data *datas;
3
    uint64_t follower_flags, conv_flags;
4
 
5
-   if (this->target == this->follower)
6
-       return 0;
7
-
8
    spa_log_debug(this->log, "%p: n_buffers:%d", this, this->n_buffers);
9
 
10
    if (this->n_buffers > 0)
11
@@ -516,10 +513,9 @@
12
    this->have_format = format != NULL;
13
    if (format == NULL) {
14
        this->n_buffers = 0;
15
-   } else {
16
+   } else if (this->target != this->follower) {
17
        res = negotiate_buffers(this);
18
    }
19
-
20
    return res;
21
 }
22
 
23
@@ -555,7 +551,7 @@
24
    struct spa_latency_info latency;
25
    int res;
26
 
27
-   spa_log_info(this->log, "%p: %d:%d", this, direction, port_id);
28
+   spa_log_debug(this->log, "%p: %d:%d", this, direction, port_id);
29
 
30
    if (this->target == this->follower)
31
        return 0;
32
@@ -625,7 +621,7 @@
33
    int res = 0;
34
    struct spa_hook l;
35
 
36
-   spa_log_info(this->log, "%p: passthrough mode %d", this, passthrough);
37
+   spa_log_debug(this->log, "%p: passthrough mode %d", this, passthrough);
38
 
39
    if (this->passthrough != passthrough) {
40
        if (passthrough) {
41
@@ -846,9 +842,6 @@
42
    struct spa_pod_builder b = { 0 };
43
    int res;
44
 
45
-   if (this->target == this->follower)
46
-       return 0;
47
-
48
    spa_log_debug(this->log, "%p: have_format:%d", this, this->have_format);
49
 
50
    if (this->have_format)
51
@@ -920,12 +913,12 @@
52
    switch (SPA_NODE_COMMAND_ID(command)) {
53
    case SPA_NODE_COMMAND_Start:
54
        spa_log_debug(this->log, "%p: starting %d", this, this->started);
55
-       if (this->started)
56
-           return 0;
57
-       if ((res = negotiate_format(this)) < 0)
58
-           return res;
59
-       if ((res = negotiate_buffers(this)) < 0)
60
-           return res;
61
+       if (this->target != this->follower) {
62
+           if (this->started)
63
+               return 0;
64
+           if ((res = negotiate_format(this)) < 0)
65
+               return res;
66
+       }
67
        this->ready = true;
68
        this->warned = false;
69
        break;
70
@@ -1043,7 +1036,7 @@
71
    uint32_t i;
72
    int res;
73
 
74
-   spa_log_info(this->log, "%p: convert port info %s %p %08"PRIx64, this,
75
+   spa_log_debug(this->log, "%p: convert port info %s %p %08"PRIx64, this,
76
            this->direction == SPA_DIRECTION_INPUT ?
77
                "Input" : "Output", info, info->change_mask);
78
 
79
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
120
 
1
@@ -370,8 +370,9 @@
2
    }
3
    spa_list_init(&port->queue);
4
 
5
-   spa_log_info(this->log, "%p: add port %d:%d position:%s %d %d %d",
6
-           this, direction, port_id, port->position, is_dsp, is_monitor, is_control);
7
+   spa_log_debug(this->log, "%p: add port %d:%d position:%s %d %d %d",
8
+           this, direction, port_id, port->position, is_dsp,
9
+           is_monitor, is_control);
10
    emit_port_info(this, port, true);
11
 
12
    return 0;
13
@@ -1266,8 +1267,9 @@
14
        (info == NULL || memcmp(&dir->format, info, sizeof(*info)) == 0))
15
        return 0;
16
 
17
-   spa_log_info(this->log, "%p: port config direction:%d monitor:%d control:%d mode:%d %d", this,
18
-           direction, monitor, control, mode, dir->n_ports);
19
+   spa_log_debug(this->log, "%p: port config direction:%d monitor:%d "
20
+           "control:%d mode:%d %d", this, direction, monitor,
21
+           control, mode, dir->n_ports);
22
 
23
    for (i = 0; i < dir->n_ports; i++) {
24
        spa_node_emit_port_info(&this->hooks, direction, i, NULL);
25
@@ -2443,6 +2445,53 @@
26
    SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_QUEUED);
27
 }
28
 
29
+static void free_tmp(struct impl *this)
30
+{
31
+   uint32_t i;
32
+
33
+   spa_log_debug(this->log, "free tmp %d", this->empty_size);
34
+
35
+   free(this->empty);
36
+   this->empty = NULL;
37
+   this->empty_size = 0;
38
+   free(this->scratch);
39
+   this->scratch = NULL;
40
+   free(this->tmp0);
41
+   this->tmp0 = NULL;
42
+   free(this->tmp1);
43
+   this->tmp1 = NULL;
44
+   for (i = 0; i < MAX_PORTS; i++) {
45
+       this->tmp_datas0i = NULL;
46
+       this->tmp_datas1i = NULL;
47
+   }
48
+}
49
+
50
+static int ensure_tmp(struct impl *this, uint32_t maxsize)
51
+{
52
+   if (maxsize > this->empty_size) {
53
+       float *empty, *scratch, *tmp2;
54
+
55
+       spa_log_debug(this->log, "resize tmp %d -> %d", this->empty_size, maxsize);
56
+
57
+       if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL)
58
+           this->empty = empty;
59
+       if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL)
60
+           this->scratch = scratch;
61
+       if ((tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL)
62
+           this->tmp0 = tmp0;
63
+       if ((tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL)
64
+           this->tmp1 = tmp1;
65
+
66
+       if (empty == NULL || scratch == NULL || tmp0 == NULL || tmp1 == NULL) {
67
+           free_tmp(this);
68
+           return -ENOMEM;
69
+       }
70
+       memset(this->empty, 0, maxsize + MAX_ALIGN);
71
+       this->empty_size = maxsize;
72
+   }
73
+   return 0;
74
+}
75
+
76
 static int
77
 impl_node_port_use_buffers(void *object,
78
               enum spa_direction direction,
79
@@ -2454,6 +2503,7 @@
80
    struct impl *this = object;
81
    struct port *port;
82
    uint32_t i, j, maxsize;
83
+   int res;
84
 
85
    spa_return_val_if_fail(this != NULL, -EINVAL);
86
 
87
@@ -2510,17 +2560,9 @@
88
        if (direction == SPA_DIRECTION_OUTPUT)
89
            queue_buffer(this, port, i);
90
    }
91
-   if (maxsize > this->empty_size) {
92
-       this->empty = realloc(this->empty, maxsize + MAX_ALIGN);
93
-       this->scratch = realloc(this->scratch, maxsize + MAX_ALIGN);
94
-       this->tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS);
95
-       this->tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS);
96
-       if (this->empty == NULL || this->scratch == NULL ||
97
-           this->tmp0 == NULL || this->tmp1 == NULL)
98
-           return -errno;
99
-       memset(this->empty, 0, maxsize + MAX_ALIGN);
100
-       this->empty_size = maxsize;
101
-   }
102
+   if ((res = ensure_tmp(this, maxsize)) < 0)
103
+       return res;
104
+
105
    port->n_buffers = n_buffers;
106
 
107
    return 0;
108
@@ -3248,10 +3290,7 @@
109
    free_dir(&this->dirSPA_DIRECTION_INPUT);
110
    free_dir(&this->dirSPA_DIRECTION_OUTPUT);
111
 
112
-   free(this->empty);
113
-   free(this->scratch);
114
-   free(this->tmp0);
115
-   free(this->tmp1);
116
+   free_tmp(this);
117
 
118
    if (this->resample.free)
119
        resample_free(&this->resample);
120
pipewire-0.3.80.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/audiomixer.c Changed
14
 
1
@@ -920,6 +920,12 @@
2
    this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
3
    spa_log_topic_init(this->log, log_topic);
4
 
5
+   this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
6
+   if (this->data_loop == NULL) {
7
+       spa_log_error(this->log, "a data loop is needed");
8
+       return -EINVAL;
9
+   }
10
+
11
    this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
12
    if (this->cpu) {
13
        this->cpu_flags = spa_cpu_get_flags(this->cpu);
14
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c Changed
10
 
1
@@ -443,7 +443,7 @@
2
        OPUS_05_SET_LOCATION(caps->bidi, props->bidi_location);
3
        break;
4
    default:
5
-       spa_assert(false);
6
+       spa_assert_not_reached();
7
    };
8
 
9
    return 0;
10
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/backend-native.c Changed
51
 
1
@@ -1915,11 +1915,12 @@
2
    .destroy = sco_destroy_cb,
3
 };
4
 
5
-static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device)
6
+static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device,
7
+       enum spa_bt_profile profile)
8
 {
9
    struct rfcomm *rfcomm;
10
    spa_list_for_each(rfcomm, &backend->rfcomm_list, link) {
11
-       if (rfcomm->device == device)
12
+       if (rfcomm->device == device && (rfcomm->profile & profile))
13
            return rfcomm;
14
    }
15
    return NULL;
16
@@ -1931,8 +1932,8 @@
17
    struct impl *backend = data;
18
    struct rfcomm *rfcomm;
19
 
20
-   rfcomm = device_find_rfcomm(backend, device);
21
-   if (rfcomm == NULL || rfcomm->profile != SPA_BT_PROFILE_HFP_HF)
22
+   rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF);
23
+   if (rfcomm == NULL)
24
        return -ENOTSUP;
25
 
26
    if (codec == HFP_AUDIO_CODEC_CVSD)
27
@@ -2097,10 +2098,12 @@
28
    int res;
29
 
30
    res = backend_native_supports_codec(data, device, codec);
31
-   if (res <= 0)
32
+   if (res < 0)
33
+       return res;
34
+   else if (!res)
35
        return -EINVAL;
36
 
37
-   rfcomm = device_find_rfcomm(backend, device);
38
+   rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF);
39
    if (rfcomm == NULL)
40
        return -ENOTSUP;
41
 
42
@@ -2399,7 +2402,7 @@
43
    DBusMessageIter it4;
44
    dbus_bool_t autoconnect;
45
    dbus_uint16_t version, chan, features;
46
-   char *str;
47
+   const char *str;
48
 
49
    if (!(backend->enabled_profiles & spa_bt_profile_from_uuid(uuid)))
50
        return -ECANCELED;
51
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bap-codec-caps.h -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bap-codec-caps.h Changed
40
 
1
@@ -97,14 +97,17 @@
2
 };
3
 
4
 struct bap_endpoint_qos {
5
-        uint8_t  framing;
6
-        uint8_t  phy;
7
-        uint8_t  retransmission;
8
-        uint16_t latency;
9
-        uint32_t delay_min;
10
-        uint32_t delay_max;
11
-        uint32_t preferred_delay_min;
12
-        uint32_t preferred_delay_max;
13
+   uint8_t framing;
14
+   uint8_t phy;
15
+   uint8_t retransmission;
16
+   uint16_t latency;
17
+   uint32_t delay_min;
18
+   uint32_t delay_max;
19
+   uint32_t preferred_delay_min;
20
+   uint32_t preferred_delay_max;
21
+   uint32_t locations;
22
+   uint16_t supported_context;
23
+   uint16_t context;
24
 };
25
 
26
 struct bap_codec_qos {
27
@@ -118,4 +121,12 @@
28
    uint8_t target_latency;
29
 };
30
 
31
+struct bap_codec_qos_full {
32
+   uint8_t cig;
33
+   uint8_t cis;
34
+   uint8_t big;
35
+   uint8_t bis;
36
+   struct bap_codec_qos qos;
37
+};
38
+
39
 #endif
40
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
201
 
1
@@ -627,6 +627,242 @@
2
 static void append_basic_array_variant_dict_entry(DBusMessageIter *dict, const char* key, const char* variant_type_str, const char* array_type_str, int array_type_int, void* data, int data_size);
3
 static struct spa_bt_remote_endpoint *remote_endpoint_find(struct spa_bt_monitor *monitor, const char *path);
4
 
5
+static bool check_iter_signature(DBusMessageIter *it, const char *sig)
6
+{
7
+   char *v;
8
+   bool res;
9
+   v = dbus_message_iter_get_signature(it);
10
+   res = spa_streq(v, sig);
11
+   dbus_free(v);
12
+   return res;
13
+}
14
+
15
+static void parse_codec_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter, struct bap_codec_qos_full *qos)
16
+{
17
+   DBusMessageIter dict_iter = *iter;
18
+
19
+   memset(qos, 0, sizeof(*qos));
20
+   qos->cig = 0xff;
21
+   qos->cis = 0xff;
22
+   qos->big = 0xff;
23
+   qos->bis = 0xff;
24
+
25
+   if (!check_iter_signature(&dict_iter, "{sv}")) {
26
+       spa_log_warn(monitor->log, "Invalid BAP QoS in DBus");
27
+       return;
28
+   }
29
+
30
+   while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
31
+       DBusMessageIter it2;
32
+       const char *key;
33
+       int type;
34
+
35
+       dbus_message_iter_recurse(&dict_iter, &it0);
36
+       dbus_message_iter_get_basic(&it0, &key);
37
+       dbus_message_iter_next(&it0);
38
+       dbus_message_iter_recurse(&it0, &it1);
39
+
40
+       type = dbus_message_iter_get_arg_type(&it1);
41
+
42
+       if (type == DBUS_TYPE_BYTE) {
43
+           uint8_t value;
44
+
45
+           dbus_message_iter_get_basic(&it1, &value);
46
+           spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
47
+
48
+           if (spa_streq(key, "PHY"))
49
+               qos->qos.phy = value;
50
+           else if (spa_streq(key, "Retransmissions"))
51
+               qos->qos.retransmission = value;
52
+           else if (spa_streq(key, "CIG"))
53
+               qos->cig = value;
54
+           else if (spa_streq(key, "CIS"))
55
+               qos->cis = value;
56
+           else if (spa_streq(key, "BIG"))
57
+               qos->big = value;
58
+           else if (spa_streq(key, "BIS"))
59
+               qos->bis = value;
60
+           else if (spa_streq(key, "TargetLatency"))
61
+               qos->qos.target_latency = value;
62
+           else if (spa_streq(key, "Framing"))
63
+               qos->qos.framing = value;
64
+       }
65
+       else if (type == DBUS_TYPE_UINT16) {
66
+           dbus_uint16_t value;
67
+
68
+           dbus_message_iter_get_basic(&it1, &value);
69
+           spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
70
+
71
+           if (spa_streq(key, "SDU"))
72
+               qos->qos.sdu = value;
73
+           else if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency"))
74
+               qos->qos.latency = value;
75
+       }
76
+       else if (type == DBUS_TYPE_UINT32) {
77
+           dbus_uint32_t value;
78
+
79
+           dbus_message_iter_get_basic(&it1, &value);
80
+           spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
81
+
82
+           if (spa_streq(key, "Interval"))
83
+               qos->qos.interval = value;
84
+           else if (spa_streq(key, "PresentationDelay"))
85
+               qos->qos.delay = value;
86
+       }
87
+
88
+       dbus_message_iter_next(&dict_iter);
89
+   }
90
+}
91
+
92
+static void parse_endpoint_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter,
93
+       struct bap_endpoint_qos *qos)
94
+{
95
+   DBusMessageIter dict_iter = *iter;
96
+
97
+   if (!check_iter_signature(&dict_iter, "{sv}")) {
98
+       spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus");
99
+       return;
100
+   }
101
+
102
+   while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
103
+       DBusMessageIter it2;
104
+       const char *key;
105
+       int type;
106
+
107
+       dbus_message_iter_recurse(&dict_iter, &it0);
108
+       dbus_message_iter_get_basic(&it0, &key);
109
+       dbus_message_iter_next(&it0);
110
+       dbus_message_iter_recurse(&it0, &it1);
111
+
112
+       type = dbus_message_iter_get_arg_type(&it1);
113
+
114
+       if (type == DBUS_TYPE_BYTE) {
115
+           uint8_t value;
116
+
117
+           dbus_message_iter_get_basic(&it1, &value);
118
+           spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
119
+
120
+           if (spa_streq(key, "Framing"))
121
+               qos->framing = value;
122
+           else if (spa_streq(key, "PHY"))
123
+               qos->phy = value;
124
+           else if (spa_streq(key, "Retransmissions"))
125
+               qos->retransmission = value;
126
+       } else if (type == DBUS_TYPE_UINT16) {
127
+           dbus_uint16_t value;
128
+
129
+           dbus_message_iter_get_basic(&it1, &value);
130
+           spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
131
+
132
+           if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency"))
133
+               qos->latency = value;
134
+           else if (spa_streq(key, "Context"))
135
+               qos->context = value;
136
+           else if (spa_streq(key, "SupportedContext"))
137
+               qos->supported_context = value;
138
+       } else if (type == DBUS_TYPE_UINT32) {
139
+           dbus_uint32_t value;
140
+
141
+           dbus_message_iter_get_basic(&it1, &value);
142
+           spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
143
+
144
+           if (spa_streq(key, "MinimumDelay"))
145
+               qos->delay_min = value;
146
+           else if (spa_streq(key, "MaximumDelay"))
147
+               qos->delay_max = value;
148
+           else if (spa_streq(key, "PreferredMinimumDelay"))
149
+               qos->preferred_delay_min = value;
150
+           else if (spa_streq(key, "PreferredMaximumDelay"))
151
+               qos->preferred_delay_max = value;
152
+           else if (spa_streq(key, "Locations") || spa_streq(key, "Location"))
153
+               qos->locations = value;
154
+       }
155
+
156
+       dbus_message_iter_next(&dict_iter);
157
+   }
158
+}
159
+
160
+static int parse_endpoint_props(struct spa_bt_monitor *monitor, DBusMessageIter *iter,
161
+       uint8_t capsA2DP_MAX_CAPS_SIZE, int *caps_size, const char **endpoint_path,
162
+       struct bap_endpoint_qos *qos)
163
+{
164
+   DBusMessageIter dict_iter = *iter;
165
+   const char *key = NULL;
166
+   int type = 0;
167
+
168
+   memset(caps, 0, A2DP_MAX_CAPS_SIZE);
169
+   *endpoint_path = NULL;
170
+   memset(qos, 0, sizeof(*qos));
171
+
172
+   if (!check_iter_signature(&dict_iter, "{sv}")) {
173
+       spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus");
174
+       return -EINVAL;
175
+   }
176
+
177
+   while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
178
+       DBusMessageIter it3;
179
+
180
+       dbus_message_iter_recurse(&dict_iter, &it0);
181
+       dbus_message_iter_get_basic(&it0, &key);
182
+       dbus_message_iter_next(&it0);
183
+       dbus_message_iter_recurse(&it0, &it1);
184
+
185
+       type = dbus_message_iter_get_arg_type(&it1);
186
+
187
+       if (spa_streq(key, "Capabilities")) {
188
+           uint8_t *buf;
189
+
190
+           if (type != DBUS_TYPE_ARRAY)
191
+               goto bad_property;
192
+
193
+           dbus_message_iter_recurse(&it1, &it2);
194
+           type = dbus_message_iter_get_arg_type(&it2);
195
+           if (type != DBUS_TYPE_BYTE)
196
+               goto bad_property;
197
+
198
+           dbus_message_iter_get_fixed_array(&it2, &buf, caps_size);
199
+           if (*caps_size > A2DP_MAX_CAPS_SIZE) {
200
+               spa_log_error(monitor->log, "%s size:%d too large", key, (int)*caps_size);
201
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
20
 
1
@@ -1608,7 +1608,17 @@
2
            name = "audio-gateway";
3
            desc = _("Audio Gateway (A2DP Source & HSP/HFP AG)");
4
        }
5
-       priority = 256;
6
+
7
+       /*
8
+        * If the remote is A2DP sink and HF, we likely should prioritize being
9
+        * A2DP sender, not gateway. This can occur in PW<->PW if RFCOMM gets
10
+        * connected both as AG and HF.
11
+        */
12
+       if ((device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) &&
13
+               (device->connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT))
14
+           priority = 15;
15
+       else
16
+           priority = 256;
17
        break;
18
    }
19
    case DEVICE_PROFILE_A2DP:
20
pipewire-0.3.80.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/loop.c Changed
55
 
1
@@ -16,6 +16,7 @@
2
 #include <spa/support/plugin.h>
3
 #include <spa/utils/list.h>
4
 #include <spa/utils/names.h>
5
+#include <spa/utils/ratelimit.h>
6
 #include <spa/utils/result.h>
7
 #include <spa/utils/type.h>
8
 #include <spa/utils/ringbuffer.h>
9
@@ -64,6 +65,7 @@
10
 
11
    struct spa_source *wakeup;
12
    int ack_fd;
13
+   struct spa_ratelimit rate_limit;
14
 
15
    struct spa_ringbuffer buffer;
16
    uint8_t *buffer_data;
17
@@ -94,6 +96,13 @@
18
 };
19
 /** \endcond */
20
 
21
+static inline uint64_t get_time_ns(struct spa_system *system)
22
+{
23
+   struct timespec ts;
24
+   spa_system_clock_gettime(system, CLOCK_MONOTONIC, &ts);
25
+   return SPA_TIMESPEC_TO_NSEC(&ts);
26
+}
27
+
28
 static int loop_add_source(void *object, struct spa_source *source)
29
 {
30
    struct impl *impl = object;
31
@@ -267,8 +276,12 @@
32
        item->item_size = SPA_ROUND_UP_N(l0 + size, ITEM_ALIGN);
33
    }
34
    if (avail < item->item_size) {
35
-       spa_log_warn(impl->log, "%p: queue full %d, need %zd", impl, avail,
36
-               item->item_size);
37
+       int suppressed;
38
+       uint64_t nsec = get_time_ns(impl->system);
39
+       if ((suppressed = spa_ratelimit_test(&impl->rate_limit, nsec)) >= 0) {
40
+           spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)",
41
+                   impl, avail, item->item_size, suppressed);
42
+       }
43
        return -EPIPE;
44
    }
45
    if (data && size > 0)
46
@@ -1004,6 +1017,8 @@
47
        res = -EINVAL;
48
        goto error_exit;
49
    }
50
+   impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
51
+   impl->rate_limit.burst = 1;
52
 
53
    if ((res = spa_system_pollfd_create(impl->system, SPA_FD_CLOEXEC)) < 0) {
54
        spa_log_error(impl->log, "%p: can't create pollfd: %s",
55
pipewire-0.3.80.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/node-driver.c Changed
22
 
1
@@ -95,14 +95,18 @@
2
 #ifdef CLOCK_MONOTONIC_RAW
3
    { "monotonic-raw", CLOCK_MONOTONIC_RAW },
4
 #endif
5
+#ifdef CLOCK_BOOTTIME
6
    { "boottime", CLOCK_BOOTTIME },
7
+#endif
8
 };
9
 
10
 static bool clock_for_timerfd(clockid_t id)
11
 {
12
    return id == CLOCK_REALTIME ||
13
-       id == CLOCK_MONOTONIC ||
14
-       id == CLOCK_BOOTTIME;
15
+#ifdef CLOCK_BOOTTIME
16
+       id == CLOCK_BOOTTIME ||
17
+#endif
18
+       id == CLOCK_MONOTONIC;
19
 }
20
 
21
 static clockid_t clock_name_to_id(const char *name)
22
pipewire-0.3.80.tar.gz/spa/tests/stress-ringbuffer.c -> pipewire-0.3.81.tar.gz/spa/tests/stress-ringbuffer.c Changed
15
 
1
@@ -11,10 +11,11 @@
2
 #define ARRAY_SIZE 63
3
 #define MAX_VALUE 0x10000
4
 
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined (__GNU__)
7
 #include <sys/param.h>
8
 #if (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400043) \
9
-    || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__)
10
+    || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__) \
11
+    || defined (__GNU__)
12
 static int sched_getcpu(void) { return -1; };
13
 #endif
14
 #endif
15
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/demonic.conf Changed
13
 
1
@@ -4,8 +4,9 @@
2
 # ~/.config/pipewire/filter-chain.conf.d/
3
 #
4
 context.modules = 
5
-    { name = libpipewire-module-filter-chain
6
-        args = {
7
+  { name = libpipewire-module-filter-chain
8
+    flags =  nofail 
9
+    args = {
10
             #audio.format    = F32
11
             #audio.rate      = 48000
12
             audio.channels   = 2
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf Changed
9
 
1
@@ -5,6 +5,7 @@
2
 #
3
 context.modules = 
4
     { name = libpipewire-module-filter-chain
5
+        flags =  nofail 
6
         args = {
7
             node.description = "Dolby Surround Sink"
8
             media.name       = "Dolby Surround Sink"
9
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf Changed
9
 
1
@@ -8,6 +8,7 @@
2
 
3
 context.modules = 
4
     { name = libpipewire-module-filter-chain
5
+        flags =  nofail 
6
         args = {
7
             node.description = "Matrix Spatialiser"
8
             media.name       = "Matrix Spatialiser"
9
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf Changed
13
 
1
@@ -3,8 +3,11 @@
2
 # Copy this file into a conf.d/ directory such as
3
 # ~/.config/pipewire/filter-chain.conf.d/
4
 #
5
+# Adjust the paths to the convolver files to match your system
6
+#
7
 context.modules = 
8
     { name = libpipewire-module-filter-chain
9
+        flags =  nofail 
10
         args = {
11
             node.description = "Virtual Surround Sink"
12
             media.name       = "Virtual Surround Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf Changed
13
 
1
@@ -3,8 +3,11 @@
2
 # Copy this file into a conf.d/ directory such as
3
 # ~/.config/pipewire/filter-chain.conf.d/
4
 #
5
+# Adjust the paths to the convolver files to match your system
6
+#
7
 context.modules = 
8
     { name = libpipewire-module-filter-chain
9
+        flags =  nofail 
10
         args = {
11
             node.description = "Virtual Surround Sink"
12
             media.name       = "Virtual Surround Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/source-rnnoise.conf Changed
28
 
1
@@ -3,8 +3,11 @@
2
 # Copy this file into a conf.d/ directory such as
3
 # ~/.config/pipewire/filter-chain.conf.d/
4
 #
5
+# Adjust the paths to the rnnoise plugin to match your system
6
+#
7
 context.modules = 
8
     { name = libpipewire-module-filter-chain
9
+        flags =  nofail 
10
         args = {
11
             node.description = "Noise Canceling source"
12
             media.name       = "Noise Canceling source"
13
@@ -13,7 +16,13 @@
14
                     {
15
                         type   = ladspa
16
                         name   = rnnoise
17
-                        plugin = librnnoise_ladspa
18
+           # The path to the plugin. The suffix .so is appended to
19
+           # this string and then the file is then located in the directories
20
+           # listed in the environment variable LADSPA_PATH or 
21
+           # /usr/lib64/ladspa, /usr/lib/ladspa or the system library directory
22
+           # as a fallback.
23
+           # You might want to use an absolute path here to avoid problems.
24
+                        plugin = "librnnoise_ladspa"
25
                         label  = noise_suppressor_stereo
26
                         control = {
27
                             "VAD Threshold (%)" 50.0
28
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf Changed
13
 
1
@@ -3,8 +3,11 @@
2
 # Copy this file into a conf.d/ directory such as
3
 # ~/.config/pipewire/filter-chain.conf.d/
4
 #
5
+# Adjust the paths to the sofa file to match your system.
6
+#
7
 context.modules = 
8
     { name = libpipewire-module-filter-chain
9
+        flags =  nofail 
10
         args = {
11
             node.description = "Spatial Sink"
12
             media.name       = "Spatial Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-single.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-single.conf Changed
13
 
1
@@ -4,8 +4,11 @@
2
 # Copy this file into a conf.d/ directory such as
3
 # ~/.config/pipewire/filter-chain.conf.d/
4
 #
5
+# Adjust the paths to the sofa files to match your system
6
+#
7
 context.modules = 
8
     { name = libpipewire-module-filter-chain
9
+        flags =  nofail 
10
         args = {
11
             node.description = "3D Sink"
12
             media.name       = "3D Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
9
 
1
@@ -28,6 +28,7 @@
2
         args = {
3
             nice.level   = -11
4
             #rt.prio      = 88
5
+            rt.prio      = 65
6
             #rt.time.soft = -1
7
             #rt.time.hard = -1
8
         }
9
pipewire-0.3.80.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire.conf.in Changed
40
 
1
@@ -50,6 +50,8 @@
2
     # enables autoloading of access module, when disabled an alternative
3
     # access module needs to be loaded.
4
     module.access = true
5
+    # enables autoloading of module-jackdbus-detect
6
+    module.jackdbus-detect = true
7
 }
8
 
9
 context.spa-libs = {
10
@@ -179,6 +181,29 @@
11
         flags =  ifexists nofail 
12
         condition =  { module.x11.bell = true } 
13
     }
14
+    { name = libpipewire-module-jackdbus-detect
15
+        args {
16
+            #jack.library     = libjack.so.0
17
+            #jack.server      = null
18
+            #jack.client-name = PipeWire
19
+            #jack.connect     = true
20
+            #tunnel.mode      = duplex  # source|sink|duplex
21
+            source.props = {
22
+                #audio.channels = 2
23
+       #midi.ports = 1
24
+                #audio.position =  FL FR 
25
+                # extra sink properties
26
+            }
27
+            sink.props = {
28
+                #audio.channels = 2
29
+       #midi.ports = 1
30
+                #audio.position =  FL FR 
31
+                # extra sink properties
32
+            }
33
+        }
34
+        flags =  ifexists nofail 
35
+        condition =  { module.jackdbus-detect = true } 
36
+    }
37
 
38
 
39
 context.objects = 
40
pipewire-0.3.80.tar.gz/src/modules/module-access.c -> pipewire-0.3.81.tar.gz/src/modules/module-access.c Changed
10
 
1
@@ -143,7 +143,7 @@
2
     * (in the current namespace).
3
     */
4
 
5
-#if defined(__linux__)
6
+#if defined(__linux__) || defined(__GNU__)
7
    spa_scnprintf(path, sizeof(path), "/proc/%u/exe", pid);
8
 #elif defined(__FreeBSD__) || defined(__MidnightBSD__)
9
    spa_scnprintf(path, sizeof(path), "/proc/%u/file", pid);
10
pipewire-0.3.80.tar.gz/src/modules/module-ffado-driver.c -> pipewire-0.3.81.tar.gz/src/modules/module-ffado-driver.c Changed
37
 
1
@@ -39,7 +39,7 @@
2
  * ## Module Options
3
  *
4
  * - `driver.mode`: the driver mode, sink|source|duplex, default duplex
5
- * - `ffado.devices`: array of devices to open, default hw:0
6
+ * - `ffado.devices`: array of devices to open, default "hw:0"
7
  * - `ffado.period-size`: period size,default 1024
8
  * - `ffado.period-num`: period number,default 3
9
  * - `ffado.sample-rate`: sample-rate, default 48000
10
@@ -71,7 +71,7 @@
11
  * {   name = libpipewire-module-ffado-driver
12
  *     args = {
13
  *         #driver.mode       = duplex
14
- *         #ffado.devices     =  hw:0 
15
+ *         #ffado.devices     =  "hw:0" 
16
  *         #ffado.period-size = 1024
17
  *         #ffado.period-num  = 3
18
  *         #ffado.sample-rate = 48000
19
@@ -100,7 +100,7 @@
20
 
21
 #define MAX_PORTS  128
22
 
23
-#define DEFAULT_DEVICES        " hw:0 "
24
+#define DEFAULT_DEVICES        " \"hw:0\" "
25
 #define DEFAULT_PERIOD_SIZE    1024
26
 #define DEFAULT_PERIOD_NUM 3
27
 #define DEFAULT_SAMPLE_RATE    48000
28
@@ -113,7 +113,7 @@
29
 
30
 #define MODULE_USAGE   "( remote.name=<remote> ) "             \
31
            "( driver.mode=<sink|source|duplex> ) "         \
32
-           "( ffado.devices=<devices array size, default hw:0> ) " \
33
+           "( ffado.devices=<devices array size, default \"hw:0\"> ) " \
34
            "( ffado.period-size=<period size, default 1024> ) "    \
35
            "( ffado.period-num=<period num, default 3> ) "     \
36
            "( ffado.sample-rate=<sampe rate, default 48000> ) "    \
37
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain.c Changed
201
 
1
@@ -82,6 +82,12 @@
2
  *         
3
  *         inputs =  <portname> ... 
4
  *         outputs =  <portname> ... 
5
+ *         capture.volumes = 
6
+ *             { control = <portname>  min = <value>  max = <value>  scale = <scale> } ...
7
+ *         
8
+ *         playback.volumes = 
9
+ *             { control = <portname>  min = <value>  max = <value>  scale = <scale> } ...
10
+ *         
11
  *    }
12
  *\endcode
13
  *
14
@@ -137,6 +143,20 @@
15
  * graph will then be duplicated as many times to match the number of input/output
16
  * channels of the streams.
17
  *
18
+ * ### Volumes
19
+ *
20
+ * Normally the volume of the sink/source is handled by the stream software volume.
21
+ * With the capture.volumes and playback.volumes properties this can be handled
22
+ * by a control port in the graph instead.
23
+ *
24
+ * The min and max values (defaults 0.0 and 1.0) respectively can be used to scale
25
+ * and translate the volume min and max values.
26
+ *
27
+ * Normally the control values are linear and it is assumed that the plugin does not
28
+ * perform any scaling to the values. This can be changed with the scale property. By
29
+ * default this is linear but it can be set to cubic when the control applies a
30
+ * cubic transformation.
31
+ *
32
  * ## Builtin filters
33
  *
34
  * There are some useful builtin filters available. You select them with the label
35
@@ -576,7 +596,7 @@
36
    uint32_t n_links;
37
    uint32_t external;
38
 
39
-   float control_data;
40
+   float control_dataMAX_HNDL;
41
    float *audio_dataMAX_HNDL;
42
 };
43
 
44
@@ -625,6 +645,20 @@
45
    void **hndl;
46
 };
47
 
48
+struct volume {
49
+   bool mute;
50
+   uint32_t n_volumes;
51
+   float volumesSPA_AUDIO_MAX_CHANNELS;
52
+
53
+   uint32_t n_ports;
54
+   struct port *portsSPA_AUDIO_MAX_CHANNELS;
55
+   float minSPA_AUDIO_MAX_CHANNELS;
56
+   float maxSPA_AUDIO_MAX_CHANNELS;
57
+#define SCALE_LINEAR   0
58
+#define SCALE_CUBIC    1
59
+   int scaleSPA_AUDIO_MAX_CHANNELS;
60
+};
61
+
62
 struct graph {
63
    struct impl *impl;
64
 
65
@@ -643,6 +677,9 @@
66
    uint32_t n_control;
67
    struct port **control_port;
68
 
69
+   struct volume capture_volume;
70
+   struct volume playback_volume;
71
+
72
    unsigned instantiated:1;
73
 };
74
 
75
@@ -962,35 +999,48 @@
76
 
77
        spa_pod_builder_string(b, name);
78
        if (p->hint & FC_HINT_BOOLEAN) {
79
-           spa_pod_builder_bool(b, port->control_data <= 0.0f ? false : true);
80
+           spa_pod_builder_bool(b, port->control_data0 <= 0.0f ? false : true);
81
        } else if (p->hint & FC_HINT_INTEGER) {
82
-           spa_pod_builder_int(b, port->control_data);
83
+           spa_pod_builder_int(b, port->control_data0);
84
        } else {
85
-           spa_pod_builder_float(b, port->control_data);
86
+           spa_pod_builder_float(b, port->control_data0);
87
        }
88
    }
89
    spa_pod_builder_pop(b, &f1);
90
    return spa_pod_builder_pop(b, &f0);
91
 }
92
 
93
+static int port_set_control_value(struct port *port, float *value, uint32_t id)
94
+{
95
+   struct node *node = port->node;
96
+   struct descriptor *desc = node->desc;
97
+   float old;
98
+
99
+   old = port->control_dataid;
100
+   port->control_dataid = value ? *value : desc->default_controlport->idx;
101
+   pw_log_info("control %d %d ('%s') from %f to %f", port->idx, id,
102
+           desc->desc->portsport->p.name, old, port->control_dataid);
103
+   node->control_changed = old != port->control_dataid;
104
+   return node->control_changed ? 1 : 0;
105
+}
106
+
107
 static int set_control_value(struct node *node, const char *name, float *value)
108
 {
109
-   struct descriptor *desc;
110
    struct port *port;
111
-   float old;
112
+   int count = 0;
113
+   uint32_t i, n_hndl;
114
 
115
    port = find_port(node, name, FC_PORT_INPUT | FC_PORT_CONTROL);
116
    if (port == NULL)
117
        return -ENOENT;
118
 
119
-   node = port->node;
120
-   desc = node->desc;
121
+   /* if we don't have any instances yet, set the first control value, we will
122
+    * copy to other instances later */
123
+   n_hndl = SPA_MAX(1u, port->node->n_hndl);
124
+   for (i = 0; i < n_hndl; i++)
125
+       count += port_set_control_value(port, value, i);
126
 
127
-   old = port->control_data;
128
-   port->control_data = value ? *value : desc->default_controlport->idx;
129
-   pw_log_info("control %d ('%s') from %f to %f", port->idx, name, old, port->control_data);
130
-   node->control_changed = old != port->control_data;
131
-   return node->control_changed ? 1 : 0;
132
+   return count;
133
 }
134
 
135
 static int parse_params(struct graph *graph, const struct spa_pod *pod)
136
@@ -1082,17 +1132,115 @@
137
    spa_pod_dynamic_builder_clean(&b);
138
 }
139
 
140
-static void param_props_changed(struct impl *impl, const struct spa_pod *param)
141
+static int sync_volume(struct graph *graph, struct volume *vol)
142
+{
143
+   uint32_t i;
144
+   int res = 0;
145
+
146
+   if (vol->n_ports == 0)
147
+       return 0;
148
+   for (i = 0; i < vol->n_volumes; i++) {
149
+       uint32_t n_port = i % vol->n_ports, n_hndl;
150
+       struct port *p = vol->portsn_port;
151
+       float v = vol->mute ? 0.0f : vol->volumesi;
152
+       switch (vol->scalen_port) {
153
+       case SCALE_CUBIC:
154
+           v = cbrt(v);
155
+           break;
156
+       }
157
+       v = v * (vol->maxn_port - vol->minn_port) + vol->minn_port;
158
+
159
+       n_hndl = SPA_MAX(1u, p->node->n_hndl);
160
+       res += port_set_control_value(p, &v, i % n_hndl);
161
+   }
162
+   return res;
163
+}
164
+
165
+static void param_props_changed(struct impl *impl, const struct spa_pod *param,
166
+       bool capture)
167
 {
168
    struct spa_pod_object *obj = (struct spa_pod_object *) param;
169
+   struct spa_pod_frame f1;
170
    const struct spa_pod_prop *prop;
171
    struct graph *graph = &impl->graph;
172
    int changed = 0;
173
+   char buf1024;
174
+   struct spa_pod_dynamic_builder b;
175
+   struct volume *vol = capture ? &graph->capture_volume :
176
+       &graph->playback_volume;
177
+   bool do_volume = false;
178
+
179
+   spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 1024);
180
+   spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
181
 
182
    SPA_POD_OBJECT_FOREACH(obj, prop) {
183
-       if (prop->key == SPA_PROP_params)
184
+       switch (prop->key) {
185
+       case SPA_PROP_params:
186
            changed += parse_params(graph, &prop->value);
187
+           spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop));
188
+           break;
189
+       case SPA_PROP_mute:
190
+       {
191
+           bool mute;
192
+           if (spa_pod_get_bool(&prop->value, &mute) == 0) {
193
+               if (vol->mute != mute) {
194
+                   vol->mute = mute;
195
+                   do_volume = true;
196
+               }
197
+           }
198
+           spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop));
199
+           break;
200
+       }
201
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c Changed
11
 
1
@@ -63,9 +63,6 @@
2
    uint32_t i;
3
    if (n_src == 0) {
4
        dsp_clear_c(ops, dst, n_samples);
5
-   } else if (n_src == 1) {
6
-       if (dst != src0)
7
-           dsp_copy_c(ops, dst, src0, n_samples);
8
    } else {
9
        if (gain0 == 1.0f)
10
            dsp_copy_c(ops, dst, src0, n_samples);
11
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c Changed
10
 
1
@@ -19,7 +19,7 @@
2
 {
3
    if (n_src == 0) {
4
        memset(dst, 0, n_samples * sizeof(float));
5
-   } else if (n_src == 1) {
6
+   } else if (n_src == 1 && gain0 == 1.0f) {
7
        if (dst != src0)
8
            spa_memcpy(dst, src0, n_samples * sizeof(float));
9
    } else {
10
pipewire-0.3.80.tar.gz/src/modules/module-pipe-tunnel.c -> pipewire-0.3.81.tar.gz/src/modules/module-pipe-tunnel.c Changed
9
 
1
@@ -8,6 +8,7 @@
2
 #include <errno.h>
3
 #include <sys/types.h>
4
 #include <sys/stat.h>
5
+#include <sys/uio.h>
6
 #include <fcntl.h>
7
 #include <unistd.h>
8
 #include <stdlib.h>
9
pipewire-0.3.80.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.81.tar.gz/src/modules/module-profiler.c Changed
10
 
1
@@ -269,7 +269,7 @@
2
    n->count++;
3
 }
4
 
5
-static struct pw_impl_node_rt_events node_rt_events = {
6
+static const struct pw_impl_node_rt_events node_rt_events = {
7
    PW_VERSION_IMPL_NODE_RT_EVENTS,
8
    .complete = context_do_profile,
9
    .incomplete = context_do_profile,
10
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.c Changed
9
 
1
@@ -46,7 +46,6 @@
2
    spa_list_init(&client->out_messages);
3
    spa_list_init(&client->operations);
4
    spa_list_init(&client->pending_samples);
5
-   spa_list_init(&client->pending_streams);
6
    spa_hook_list_init(&client->listener_list);
7
 
8
    spa_list_append(&server->clients, &client->link);
9
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.h Changed
10
 
1
@@ -74,8 +74,6 @@
2
 
3
    struct spa_list pending_samples;
4
 
5
-   struct spa_list pending_streams;
6
-
7
    unsigned int disconnect:1;
8
    unsigned int new_msg_since_last_flush:1;
9
    unsigned int authenticated:1;
10
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/manager.c Changed
12
 
1
@@ -440,6 +440,10 @@
2
            case SPA_PARAM_PropInfo:
3
            case SPA_PARAM_Format:
4
            case SPA_PARAM_EnumFormat:
5
+           /* also emit changed for the Latency param because the stream might
6
+            * now be linked. FIXME, we should check if a new link is made for
7
+            * a stream and only emit a changed event in that case. */
8
+           case SPA_PARAM_Latency:
9
                changed++;
10
                break;
11
            default:
12
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c Changed
13
 
1
@@ -52,6 +52,11 @@
2
    char *args;
3
    size_t size;
4
 
5
+   pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+   pw_properties_setf(data->source_props, "pulse.module.id", "%u", module->index);
7
+   pw_properties_setf(data->sink_props, "pulse.module.id", "%u", module->index);
8
+   pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
9
+
10
    if ((f = open_memstream(&args, &size)) == NULL)
11
        return -errno;
12
 
13
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
160
 
1
@@ -832,42 +832,43 @@
2
    }
3
 
4
    if (spa_streq(o->type, PW_TYPE_INTERFACE_Link)) {
5
-       struct stream *s, *t;
6
        struct pw_manager_object *peer = NULL;
7
        union pw_map_item *item;
8
        pw_array_for_each(item, &client->streams.items) {
9
            struct stream *s = item->data;
10
            const char *peer_name;
11
 
12
-           if (pw_map_item_is_free(item) || s->pending)
13
+           if (pw_map_item_is_free(item))
14
                continue;
15
-           if (s->peer_index == SPA_ID_INVALID)
16
+
17
+           if (!s->pending && s->peer_index == SPA_ID_INVALID)
18
                continue;
19
 
20
            peer = find_peer_for_link(manager, o, s->id, s->direction);
21
-           if (peer == NULL || peer->props == NULL ||
22
-               peer->index == s->peer_index)
23
+           if (peer == NULL)
24
                continue;
25
 
26
-           s->peer_index = peer->index;
27
-
28
-           peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
29
-           if (peer_name && s->direction == PW_DIRECTION_INPUT &&
30
-               pw_manager_object_is_monitor(peer)) {
31
-               int len = strlen(peer_name) + 10;
32
-               char *tmp = alloca(len);
33
-               snprintf(tmp, len, "%s.monitor", peer_name);
34
-               peer_name = tmp;
35
-           }
36
-           if (peer_name != NULL)
37
-               stream_send_moved(s, peer->index, peer_name);
38
-       }
39
-       spa_list_for_each_safe(s, t, &client->pending_streams, link) {
40
-           peer = find_peer_for_link(manager, o, s->id, s->direction);
41
-           if (peer) {
42
+           if (s->pending) {
43
                reply_create_stream(s, peer);
44
-               spa_list_remove(&s->link);
45
                s->pending = false;
46
+           } else {
47
+               if (s->peer_index == peer->index)
48
+                   continue;
49
+               if (peer->props == NULL)
50
+                   continue;
51
+
52
+               s->peer_index = peer->index;
53
+
54
+               peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
55
+               if (peer_name && s->direction == PW_DIRECTION_INPUT &&
56
+                   pw_manager_object_is_monitor(peer)) {
57
+                   int len = strlen(peer_name) + 10;
58
+                   char *tmp = alloca(len);
59
+                   snprintf(tmp, len, "%s.monitor", peer_name);
60
+                   peer_name = tmp;
61
+               }
62
+               if (peer_name != NULL)
63
+                   stream_send_moved(s, peer->index, peer_name);
64
            }
65
        }
66
    }
67
@@ -1244,7 +1245,6 @@
68
        if (peer) {
69
            reply_create_stream(stream, peer);
70
        } else {
71
-           spa_list_append(&stream->client->pending_streams, &stream->link);
72
            stream->pending = true;
73
        }
74
    }
75
@@ -5483,9 +5483,23 @@
76
    const char *str;
77
    int res = 0;
78
 
79
+   debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
80
+
81
    impl = calloc(1, sizeof(*impl) + user_data_size);
82
    if (impl == NULL)
83
-       goto error_exit;
84
+       goto error_free_props;
85
+
86
+   impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
87
+   impl->rate_limit.burst = 1;
88
+   spa_hook_list_init(&impl->hooks);
89
+   spa_list_init(&impl->servers);
90
+   pw_map_init(&impl->samples, 16, 16);
91
+   pw_map_init(&impl->modules, 16, 16);
92
+   spa_list_init(&impl->cleanup_clients);
93
+   spa_list_init(&impl->free_messages);
94
+
95
+   impl->loop = pw_context_get_main_loop(context);
96
+   impl->work_queue = pw_context_get_work_queue(context);
97
 
98
    if (props == NULL)
99
        props = pw_properties_new(NULL, NULL);
100
@@ -5503,25 +5517,6 @@
101
        pw_properties_set(props, "vm.overrides", NULL);
102
    }
103
 
104
-   load_defaults(&impl->defs, props);
105
-
106
-   debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
107
-
108
-   impl->context = context;
109
-   impl->loop = pw_context_get_main_loop(context);
110
-   impl->props = props;
111
-
112
-   impl->work_queue = pw_context_get_work_queue(context);
113
-
114
-   spa_hook_list_init(&impl->hooks);
115
-   spa_list_init(&impl->servers);
116
-   impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
117
-   impl->rate_limit.burst = 1;
118
-   pw_map_init(&impl->samples, 16, 16);
119
-   pw_map_init(&impl->modules, 16, 16);
120
-   spa_list_init(&impl->cleanup_clients);
121
-   spa_list_init(&impl->free_messages);
122
-
123
    str = pw_properties_get(props, "server.address");
124
    if (str == NULL) {
125
        pw_properties_setf(props, "server.address",
126
@@ -5544,8 +5539,6 @@
127
        pw_log_warn("%p: can't create pid file: %s",
128
                impl, spa_strerror(res));
129
    }
130
-   pw_context_add_listener(context, &impl->context_listener,
131
-           &context_events, impl);
132
 
133
 #ifdef HAVE_DBUS
134
    str = pw_properties_get(props, "server.dbus-name");
135
@@ -5554,14 +5547,22 @@
136
    if (strlen(str) > 0)
137
        impl->dbus_name = dbus_request_name(context, str);
138
 #endif
139
+
140
+   load_defaults(&impl->defs, props);
141
+   impl->props = spa_steal_ptr(props);
142
+
143
+   pw_context_add_listener(context, &impl->context_listener,
144
+           &context_events, impl);
145
+   impl->context = context;
146
+
147
    cmd_run(impl);
148
 
149
    return (struct pw_protocol_pulse *) impl;
150
 
151
 error_free:
152
-   free(impl);
153
+   impl_free(impl);
154
 
155
-error_exit:
156
+error_free_props:
157
    pw_properties_free(props);
158
 
159
    if (res < 0)
160
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.c Changed
11
 
1
@@ -103,9 +103,6 @@
2
 
3
    pw_log_debug("client %p: stream %p channel:%d", client, stream, stream->channel);
4
 
5
-   if (stream->pending)
6
-       spa_list_remove(&stream->link);
7
-
8
    if (stream->drain_tag)
9
        reply_error(client, -1, stream->drain_tag, -ENOENT);
10
 
11
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.h Changed
9
 
1
@@ -34,7 +34,6 @@
2
 };
3
 
4
 struct stream {
5
-   struct spa_list link;
6
    uint32_t create_tag;
7
    uint32_t channel;   /* index in map */
8
    uint32_t id;        /* id of global */
9
pipewire-0.3.80.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop-sink.c Changed
201
 
1
@@ -44,6 +44,7 @@
2
 #include <pipewire/i18n.h>
3
 
4
 #include "module-raop/rtsp-client.h"
5
+#include "module-rtp/rtp.h"
6
 
7
 /** \page page_module_raop_sink PipeWire Module: AirPlay Sink
8
  *
9
@@ -137,8 +138,8 @@
10
 #endif
11
 #define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH)
12
 
13
-#define DEFAULT_USER_AGENT "iTunes/11.0.4 (Windows; N)"
14
-#define DEFAULT_USER_NAME  "iTunes"
15
+#define DEFAULT_USER_NAME  "PipeWire"
16
+#define RAOP_AUTH_USER_NAME    "iTunes"
17
 
18
 #define MAX_PORT_RETRY 128
19
 
20
@@ -147,9 +148,9 @@
21
 #define DEFAULT_CHANNELS 2
22
 #define DEFAULT_POSITION " FL FR "
23
 
24
-#define VOLUME_MAX  0.0
25
-#define VOLUME_DEF -30.0
26
-#define VOLUME_MIN -144.0
27
+#define VOLUME_MAX 0.0
28
+#define VOLUME_MIN -30.0
29
+#define VOLUME_MUTE    -144.0
30
 
31
 #define MODULE_USAGE   "( raop.ip=<ip address of host> ) "                 \
32
            "( raop.port=<remote port> ) "                      \
33
@@ -228,13 +229,14 @@
34
 
35
    unsigned int do_disconnect:1;
36
 
37
-   uint8_t keyAES_CHUNK_SIZE; /* Key for aes-cbc */
38
-   uint8_t ivAES_CHUNK_SIZE;  /* Initialization vector for cbc */
39
+   uint8_t aes_keyAES_CHUNK_SIZE; /* Key for aes-cbc */
40
+   uint8_t aes_ivAES_CHUNK_SIZE;  /* Initialization vector for cbc */
41
    EVP_CIPHER_CTX *ctx;
42
 
43
    uint16_t control_port;
44
    int control_fd;
45
    struct spa_source *control_source;
46
+   struct spa_source *feedback_timer;
47
 
48
    uint16_t timing_port;
49
    int timing_fd;
50
@@ -247,7 +249,7 @@
51
    uint32_t block_size;
52
    uint32_t latency;
53
 
54
-   uint16_t seq;
55
+   uint16_t seq, cseq;
56
    uint32_t rtptime;
57
    uint32_t ssrc;
58
    uint32_t sync;
59
@@ -287,7 +289,7 @@
60
 static int aes_encrypt(struct impl *impl, uint8_t *data, int len)
61
 {
62
    int i = len & ~0xf, clen = i;
63
-   EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->key, impl->iv);
64
+   EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->aes_key, impl->aes_iv);
65
    EVP_EncryptUpdate(impl->ctx, data, &clen, data, i);
66
    return i;
67
 }
68
@@ -308,46 +310,104 @@
69
 static int send_udp_sync_packet(struct impl *impl,
70
        struct sockaddr *dest_addr, socklen_t addrlen)
71
 {
72
-   uint32_t pkt5;
73
+   uint32_t out3;
74
    uint32_t rtptime = impl->rtptime;
75
    uint32_t latency = impl->latency;
76
    uint64_t transmitted;
77
+   struct rtp_header header;
78
+   struct iovec iov2;
79
+   struct msghdr msg;
80
+   int res;
81
 
82
-   pkt0 = htonl(0x80d40007);
83
+   spa_zero(header);
84
+   header.v = 2;
85
    if (impl->first)
86
-       pkt0 |= htonl(0x10000000);
87
-   pkt1 = htonl(rtptime - latency);
88
+       header.x = 1;
89
+   header.m = 1;
90
+   header.pt = 84;
91
+   header.sequence_number = htons(impl->cseq);
92
+   header.timestamp = htonl(rtptime - latency);
93
+
94
+   iov0.iov_base = &header;
95
+   iov0.iov_len = 8;
96
+
97
    transmitted = ntp_now();
98
-   pkt2 = htonl(transmitted >> 32);
99
-   pkt3 = htonl(transmitted & 0xffffffff);
100
-   pkt4 = htonl(rtptime);
101
+   out0 = htonl(transmitted >> 32);
102
+   out1 = htonl(transmitted & 0xffffffff);
103
+   out2 = htonl(rtptime);
104
+
105
+   iov1.iov_base = out;
106
+   iov1.iov_len = sizeof(out);
107
+
108
+   msg.msg_name = dest_addr;
109
+   msg.msg_namelen = addrlen;
110
+   msg.msg_iov = iov;
111
+   msg.msg_iovlen = 2;
112
+   msg.msg_control = NULL;
113
+   msg.msg_controllen = 0;
114
+   msg.msg_flags = 0;
115
+
116
+   res = sendmsg(impl->control_fd, &msg, MSG_NOSIGNAL);
117
+   if (res < 0) {
118
+       res = -errno;
119
+       pw_log_warn("error sending control packet: %d", res);
120
+   }
121
+
122
+   impl->cseq = (impl->cseq + 1) & 0xffff;
123
 
124
-   pw_log_debug("sync: first:%d latency:%u now:%"PRIx64" rtptime:%u",
125
-           impl->first, latency, transmitted, rtptime);
126
+   pw_log_debug("raop control sync: cseq:%d first:%d latency:%u now:%"PRIx64" rtptime:%u",
127
+           impl->cseq, impl->first, latency, transmitted, rtptime);
128
 
129
-   return sendto(impl->control_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen);
130
+   return res;
131
 }
132
 
133
 static int send_udp_timing_packet(struct impl *impl, uint64_t remote, uint64_t received,
134
        struct sockaddr *dest_addr, socklen_t addrlen)
135
 {
136
-   uint32_t pkt8;
137
+   uint32_t out6;
138
    uint64_t transmitted;
139
+   struct rtp_header header;
140
+   struct iovec iov2;
141
+   struct msghdr msg;
142
+   int res;
143
 
144
-   pkt0 = htonl(0x80d30007);
145
-   pkt1 = 0x00000000;
146
-   pkt2 = htonl(remote >> 32);
147
-   pkt3 = htonl(remote & 0xffffffff);
148
-   pkt4 = htonl(received >> 32);
149
-   pkt5 = htonl(received & 0xffffffff);
150
-   transmitted = ntp_now();
151
-   pkt6 = htonl(transmitted >> 32);
152
-   pkt7 = htonl(transmitted & 0xffffffff);
153
+   spa_zero(header);
154
+   header.v = 2;
155
+   header.pt = 83;
156
+   header.m = 1;
157
+
158
+   iov0.iov_base = &header;
159
+   iov0.iov_len = 8;
160
+
161
+   out0 = htonl(remote >> 32);
162
+   out1 = htonl(remote & 0xffffffff);
163
 
164
-   pw_log_debug("sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64,
165
+   out2 = htonl(received >> 32);
166
+   out3 = htonl(received & 0xffffffff);
167
+   transmitted = ntp_now();
168
+   out4 = htonl(transmitted >> 32);
169
+   out5 = htonl(transmitted & 0xffffffff);
170
+
171
+   iov1.iov_base = out;
172
+   iov1.iov_len = sizeof(out);
173
+
174
+   msg.msg_name = dest_addr;
175
+   msg.msg_namelen = addrlen;
176
+   msg.msg_iov = iov;
177
+   msg.msg_iovlen = 2;
178
+   msg.msg_control = NULL;
179
+   msg.msg_controllen = 0;
180
+   msg.msg_flags = 0;
181
+
182
+   res = sendmsg(impl->timing_fd, &msg, MSG_NOSIGNAL);
183
+   if (res < 0) {
184
+       res = -errno;
185
+       pw_log_warn("error sending timing packet: %d", res);
186
+   }
187
+   pw_log_debug("raop timing sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64,
188
            remote, received, transmitted);
189
 
190
-   return sendto(impl->timing_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen);
191
+   return res;
192
 }
193
 
194
 static int write_codec_pcm(void *dst, void *frames, uint32_t n_frames)
195
@@ -382,8 +442,11 @@
196
 
197
 static int flush_to_udp_packet(struct impl *impl)
198
 {
199
-   const size_t max = 12 + 8 + impl->block_size;
200
-   uint32_t pktmax, len, n_frames;
201
pipewire-0.3.80.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop/rtsp-client.c Changed
23
 
1
@@ -21,12 +21,12 @@
2
 
3
 struct message {
4
    struct spa_list link;
5
-   void *data;
6
    size_t len;
7
    size_t offset;
8
    uint32_t cseq;
9
    int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content);
10
    void *user_data;
11
+   unsigned char data;
12
 };
13
 
14
 enum client_recv_state {
15
@@ -598,7 +598,6 @@
16
 
17
    fclose(f);
18
 
19
-   msg->data = SPA_PTROFF(msg, sizeof(*msg), void);
20
    msg->len = len - sizeof(*msg);
21
    msg->offset = 0;
22
    msg->reply = reply;
23
pipewire-0.3.80.tar.gz/src/modules/module-rt.c -> pipewire-0.3.81.tar.gz/src/modules/module-rt.c Changed
21
 
1
@@ -35,6 +35,9 @@
2
 #if defined(__FreeBSD__) || defined(__MidnightBSD__)
3
 #include <sys/thr.h>
4
 #endif
5
+#if defined(__GNU__)
6
+#include <mach.h>
7
+#endif
8
 #include <fcntl.h>
9
 #include <unistd.h>
10
 #include <pthread.h>
11
@@ -221,6 +224,9 @@
12
    long pid;
13
    thr_self(&pid);
14
    return (pid_t)pid;
15
+#elif defined(__GNU__)
16
+       mach_port_t thread = mach_thread_self();
17
+       return (pid_t)thread;
18
 #else
19
 #error "No gettid impl"
20
 #endif
21
pipewire-0.3.80.tar.gz/src/modules/module-rtp-session.c -> pipewire-0.3.81.tar.gz/src/modules/module-rtp-session.c Changed
11
 
1
@@ -1335,7 +1335,8 @@
2
    if (spa_streq(service_name, "_pipewire-audio._udp")) {
3
        uint32_t mask = 0;
4
        for (l = txt; l && compatible; l = l->next) {
5
-           char *key, *value, *k = NULL;
6
+           const char *k = NULL;
7
+           char *key, *value;
8
 
9
            if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0)
10
                break;
11
pipewire-0.3.80.tar.gz/src/pipewire/conf.c -> pipewire-0.3.81.tar.gz/src/pipewire/conf.c Changed
23
 
1
@@ -18,7 +18,7 @@
2
 #ifdef HAVE_PWD_H
3
 #include <pwd.h>
4
 #endif
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
7
 #ifndef O_PATH
8
 #define O_PATH 0
9
 #endif
10
@@ -599,10 +599,11 @@
11
        char key256, val1024;
12
        const char *str, *value;
13
        int match = 0, fail = 0;
14
-       int len, skip = 0;
15
+       int len;
16
 
17
        while (spa_json_get_string(&it0, key, sizeof(key)) > 0) {
18
            bool success = false;
19
+           int skip = 0;
20
 
21
            if ((len = spa_json_next(&it0, &value)) <= 0)
22
                break;
23
pipewire-0.3.80.tar.gz/src/pipewire/context.c -> pipewire-0.3.81.tar.gz/src/pipewire/context.c Changed
145
 
1
@@ -1306,9 +1306,10 @@
2
        struct spa_fraction latency = SPA_FRACTION(0, 0);
3
        struct spa_fraction max_latency = SPA_FRACTION(0, 0);
4
        struct spa_fraction rate = SPA_FRACTION(0, 0);
5
-       uint32_t quantum, target_rate, current_rate;
6
+       uint32_t target_quantum, target_rate, current_rate, current_quantum;
7
        uint64_t quantum_stamp = 0, rate_stamp = 0;
8
-       bool force_rate, force_quantum, restore_rate = false;
9
+       bool force_rate, force_quantum, restore_rate = false, restore_quantum = false;
10
+       bool do_reconfigure = false, was_target_pending;
11
        const uint32_t *node_rates;
12
        uint32_t node_n_rates, node_def_rate;
13
        uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum;
14
@@ -1364,10 +1365,10 @@
15
                 fraction_compare(&s->max_latency, &max_latency) < 0))
16
                max_latency = s->max_latency;
17
 
18
-           /* largest rate */
19
+           /* largest rate, which is in fact the smallest fraction */
20
            if (rate.denom == 0 ||
21
                (s->rate.denom > 0 &&
22
-                fraction_compare(&s->rate, &rate) > 0))
23
+                fraction_compare(&s->rate, &rate) < 0))
24
                rate = s->rate;
25
 
26
            if (s->active)
27
@@ -1386,6 +1387,12 @@
28
            pw_log_info("(%s-%u) restore rate", n->name, n->info.id);
29
            restore_rate = true;
30
        }
31
+       if (n->forced_quantum && !force_quantum && n->runnable) {
32
+           /* A node that was forced to a quantum but is no longer being
33
+            * forced can restore its quantum */
34
+           pw_log_info("(%s-%u) restore quantum", n->name, n->info.id);
35
+           restore_quantum = true;
36
+       }
37
 
38
        if (force_quantum)
39
            lock_quantum = false;
40
@@ -1416,8 +1423,9 @@
41
                        rate.denom, target_rate);
42
        }
43
 
44
+       was_target_pending = n->target_pending;
45
+
46
        if (target_rate != current_rate) {
47
-           bool do_reconfigure = false;
48
            /* we doing a rate switch */
49
            pw_log_info("(%s-%u) state:%s new rate:%u/(%u)->%u",
50
                    n->name, n->info.id,
51
@@ -1427,23 +1435,17 @@
52
 
53
            if (force_rate) {
54
                if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD)
55
-                   do_reconfigure = !n->target_pending;
56
+                   do_reconfigure |= !was_target_pending;
57
            } else {
58
                if (n->info.state >= PW_NODE_STATE_SUSPENDED)
59
-                   do_reconfigure = !n->target_pending;
60
+                   do_reconfigure |= !was_target_pending;
61
            }
62
-           if (do_reconfigure)
63
-               reconfigure_driver(context, n);
64
-
65
            /* we're setting the pending rate. This will become the new
66
             * current rate in the next iteration of the graph. */
67
            n->target_rate = SPA_FRACTION(1, target_rate);
68
-           n->target_pending = true;
69
            n->forced_rate = force_rate;
70
+           n->target_pending = true;
71
            current_rate = target_rate;
72
-           /* we might be suspended now and the links need to be prepared again */
73
-           if (do_reconfigure)
74
-               goto again;
75
        }
76
 
77
        if (node_rate_quantum != 0 && current_rate != node_rate_quantum) {
78
@@ -1460,26 +1462,42 @@
79
                node_max_quantum = tmp;
80
        }
81
 
82
-       quantum = node_def_quantum;
83
-       if (latency.denom != 0)
84
-           quantum = (latency.num * current_rate / latency.denom);
85
-       quantum = SPA_CLAMP(quantum, node_min_quantum, node_max_quantum);
86
-       quantum = SPA_MIN(quantum, lim_quantum);
87
-
88
-       if (settings->clock_power_of_two_quantum)
89
-           quantum = flp2(quantum);
90
+       current_quantum = n->target_quantum;
91
+       if (!restore_quantum &&
92
+          (lock_quantum || n->reconfigure || !running ||
93
+           (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE))))
94
+           target_quantum = current_quantum;
95
+       else {
96
+           target_quantum = node_def_quantum;
97
+           if (latency.denom != 0)
98
+               target_quantum = (latency.num * current_rate / latency.denom);
99
+           target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum);
100
+           target_quantum = SPA_MIN(target_quantum, lim_quantum);
101
+
102
+           if (settings->clock_power_of_two_quantum)
103
+               target_quantum = flp2(target_quantum);
104
+       }
105
 
106
-       if (running && quantum != n->target_quantum && !lock_quantum) {
107
+       if (target_quantum != current_quantum) {
108
            pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u",
109
                    n->name, n->info.id,
110
                    n->target_quantum,
111
-                   quantum);
112
+                   target_quantum);
113
            /* this is the new pending quantum */
114
-           n->target_quantum = quantum;
115
+           n->target_quantum = target_quantum;
116
+           n->forced_quantum = force_quantum;
117
            n->target_pending = true;
118
+
119
+           if (force_quantum)
120
+               do_reconfigure |= !was_target_pending;
121
        }
122
 
123
        if (n->target_pending) {
124
+           if (do_reconfigure) {
125
+               reconfigure_driver(context, n);
126
+               /* we might be suspended now and the links need to be prepared again */
127
+               goto again;
128
+           }
129
            /* we have a pending change. We place the new values in the
130
             * pending fields so that they are picked up by the driver in
131
             * the next cycle */
132
@@ -1501,8 +1519,10 @@
133
            n->target_rate = n->rt.position->clock.target_rate;
134
        }
135
 
136
-       pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u '%s'",
137
-               context, n, running, n->runnable, quantum, n->name);
138
+       pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u rate:%u (%"PRIu64"/%u)'%s'",
139
+               context, n, running, n->runnable, target_quantum, target_rate,
140
+               n->rt.position->clock.target_duration,
141
+               n->rt.position->clock.target_rate.denom, n->name);
142
 
143
        /* first change the node states of the followers to the new target */
144
        spa_list_for_each(s, &n->follower_list, follower_link) {
145
pipewire-0.3.80.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-link.c Changed
18
 
1
@@ -1545,6 +1545,7 @@
2
 void pw_impl_link_destroy(struct pw_impl_link *link)
3
 {
4
    struct impl *impl = SPA_CONTAINER_OF(link, struct impl, this);
5
+   bool was_prepared = link->prepared;
6
 
7
    pw_log_debug("%p: destroy", impl);
8
    pw_log_info("(%s) destroy", link->name);
9
@@ -1570,7 +1571,7 @@
10
        pw_global_destroy(link->global);
11
    }
12
 
13
-   if (link->prepared)
14
+   if (was_prepared)
15
        pw_context_recalc_graph(link->context, "link destroy");
16
 
17
    pw_log_debug("%p: free", impl);
18
pipewire-0.3.80.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-node.c Changed
42
 
1
@@ -8,6 +8,7 @@
2
 #include <unistd.h>
3
 #include <errno.h>
4
 #include <time.h>
5
+#include <malloc.h>
6
 
7
 #include <spa/support/system.h>
8
 #include <spa/pod/parser.h>
9
@@ -1321,6 +1322,7 @@
10
 
11
    this->target_rate = SPA_FRACTION(1, rate);
12
    this->target_quantum = quantum;
13
+   this->elapsed = 0;
14
 
15
    pos->clock.rate = pos->clock.target_rate = this->target_rate;
16
    pos->clock.duration = pos->clock.target_duration = this->target_quantum;
17
@@ -1744,8 +1746,10 @@
18
        if (all_ready)
19
            a->position.state = SPA_IO_POSITION_STATE_RUNNING;
20
    }
21
-   if (SPA_LIKELY(a->position.state != SPA_IO_POSITION_STATE_RUNNING))
22
-       a->position.offset += a->position.clock.duration;
23
+   if (SPA_LIKELY(a->position.state == SPA_IO_POSITION_STATE_RUNNING))
24
+       node->elapsed += a->position.clock.duration;
25
+
26
+   a->position.offset = a->position.clock.position - node->elapsed;
27
 }
28
 
29
 /* Called from the data-loop and it is the starting point for driver nodes.
30
@@ -2103,6 +2107,11 @@
31
 
32
    spa_system_close(node->data_system, node->source.fd);
33
    free(impl);
34
+
35
+#ifdef HAVE_MALLOC_TRIM
36
+   int res = malloc_trim(0);
37
+   pw_log_debug("malloc_trim(): %d", res);
38
+#endif
39
 }
40
 
41
 SPA_EXPORT
42
pipewire-0.3.80.tar.gz/src/pipewire/mem.c -> pipewire-0.3.81.tar.gz/src/pipewire/mem.c Changed
20
 
1
@@ -25,7 +25,8 @@
2
 PW_LOG_TOPIC_EXTERN(log_mem);
3
 #define PW_LOG_TOPIC_DEFAULT log_mem
4
 
5
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(HAVE_MEMFD_CREATE)
6
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__) \
7
+       && !defined(HAVE_MEMFD_CREATE)
8
 /*
9
  * No glibc wrappers exist for memfd_create(2), so provide our own.
10
  *
11
@@ -42,7 +43,7 @@
12
 #define HAVE_MEMFD_CREATE 1
13
 #endif
14
 
15
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
16
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
17
 #define MAP_LOCKED 0
18
 #endif
19
 
20
pipewire-0.3.80.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.81.tar.gz/src/pipewire/pipewire.c Changed
28
 
1
@@ -7,7 +7,7 @@
2
 #include <unistd.h>
3
 #include <limits.h>
4
 #include <stdio.h>
5
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
6
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__)
7
 #include <sys/prctl.h>
8
 #endif
9
 #include <pwd.h>
10
@@ -720,7 +720,7 @@
11
    static char namePATH_MAX;
12
 
13
    spa_memzero(name, sizeof(name));
14
-#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__)
15
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__) || defined(__GNU__)
16
    {
17
        if (readlink("/proc/self/exe", name, sizeof(name)-1) > 0) {
18
            prgname = strrchr(name, '/') + 1;
19
@@ -738,7 +738,7 @@
20
        }
21
    }
22
 #endif
23
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
24
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__)
25
    {
26
        if (prctl(PR_GET_NAME, (unsigned long) name, 0, 0, 0) == 0) {
27
            prgname = name;
28
pipewire-0.3.80.tar.gz/src/pipewire/private.h -> pipewire-0.3.81.tar.gz/src/pipewire/private.h Changed
26
 
1
@@ -22,7 +22,7 @@
2
 #include <spa/utils/result.h>
3
 #include <spa/utils/type-info.h>
4
 
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
7
 struct ucred {
8
 };
9
 #endif
10
@@ -673,6 +673,7 @@
11
    unsigned int suspend_on_idle:1;
12
    unsigned int reconfigure:1;
13
    unsigned int forced_rate:1;
14
+   unsigned int forced_quantum:1;
15
    unsigned int trigger:1;     /**< has the TRIGGER property and needs an extra
16
                      *  trigger to start processing. */
17
    unsigned int can_suspend:1;
18
@@ -731,6 +732,7 @@
19
    uint64_t target_quantum;
20
 
21
    uint64_t driver_start;
22
+   uint64_t elapsed;       /* elapsed time in playing */
23
 
24
    void *user_data;                /**< extra user data */
25
 };
26
pipewire-0.3.80.tar.gz/src/pipewire/stream.c -> pipewire-0.3.81.tar.gz/src/pipewire/stream.c Changed
35
 
1
@@ -157,6 +157,7 @@
2
    unsigned int driving:1;
3
    unsigned int using_trigger:1;
4
    unsigned int trigger:1;
5
+   unsigned int early_process:1;
6
    int in_set_param;
7
    int in_emit_param_changed;
8
 };
9
@@ -1103,7 +1104,7 @@
10
             * rate matching node (audioconvert) has been scheduled to
11
             * update the values. */
12
            ask_more = !impl->process_rt && impl->rate_match == NULL &&
13
-               queue_is_empty(impl, &impl->queued) &&
14
+               (impl->early_process || queue_is_empty(impl, &impl->queued)) &&
15
                !queue_is_empty(impl, &impl->dequeued);
16
            pw_log_trace_fp("%p: pop %d %p ask_more:%u %p", stream, b->id, io,
17
                    ask_more, impl->rate_match);
18
@@ -1121,7 +1122,7 @@
19
        }
20
    } else {
21
        ask_more = !impl->process_rt &&
22
-           queue_is_empty(impl, &impl->queued) &&
23
+           (impl->early_process || queue_is_empty(impl, &impl->queued)) &&
24
            !queue_is_empty(impl, &impl->dequeued);
25
    }
26
 
27
@@ -1912,6 +1913,7 @@
28
        impl->node_methods.process = impl_node_process_output;
29
 
30
    impl->process_rt = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_RT_PROCESS);
31
+   impl->early_process = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_EARLY_PROCESS);
32
 
33
    impl->impl_node.iface = SPA_INTERFACE_INIT(
34
            SPA_TYPE_INTERFACE_Node,
35
pipewire-0.3.80.tar.gz/src/pipewire/stream.h -> pipewire-0.3.81.tar.gz/src/pipewire/stream.h Changed
13
 
1
@@ -394,6 +394,11 @@
2
                              *  does a trigger_process() that will then
3
                              *  dequeue/queue a buffer from another process()
4
                              *  function. since 0.3.73 */
5
+   PW_STREAM_FLAG_EARLY_PROCESS    = (1 << 11),    /**< Call process as soon as there is a buffer
6
+                             *  to dequeue. This is only relevant for
7
+                             *  playback and when not using RT_PROCESS. It
8
+                             *  can be used to keep the maximum number of
9
+                             *  buffers queued. Since 0.3.81 */
10
 };
11
 
12
 /** Create a new unconneced \ref pw_stream
13
pipewire-0.3.80.tar.gz/src/pipewire/thread.c -> pipewire-0.3.81.tar.gz/src/pipewire/thread.c Changed
11
 
1
@@ -53,6 +53,9 @@
2
 }
3
 #endif
4
 #endif
5
+#if defined(__GNU__)
6
+int pthread_setname_np(pthread_t thread, const char *name) { return 0; }
7
+#endif
8
 
9
 static struct spa_thread *impl_create(void *object,
10
            const struct spa_dict *props,
11
pipewire-0.3.80.tar.gz/src/pipewire/utils.h -> pipewire-0.3.81.tar.gz/src/pipewire/utils.h Changed
9
 
1
@@ -15,6 +15,7 @@
2
 #ifndef _POSIX_C_SOURCE
3
 # include <sys/mount.h>
4
 #endif
5
+#include <errno.h>
6
 
7
 #ifndef ENODATA
8
 #define ENODATA 9919
9
pipewire-0.3.81.tar.gz/src/tools/dfffile.c Added
201
 
1
@@ -0,0 +1,313 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <errno.h>
7
+#include <sys/mman.h>
8
+#include <sys/stat.h>
9
+#include <unistd.h>
10
+#include <fcntl.h>
11
+#include <math.h>
12
+
13
+#include <spa/utils/string.h>
14
+#include <spa/debug/mem.h>
15
+
16
+#include "dfffile.h"
17
+
18
+struct dff_file {
19
+   uint8_t *data;
20
+   size_t size;
21
+
22
+   int mode;
23
+   int fd;
24
+
25
+   struct dff_file_info info;
26
+
27
+   uint8_t *p;
28
+   size_t offset;
29
+};
30
+
31
+struct dff_chunk {
32
+   uint32_t id;
33
+   uint64_t size;
34
+   void *data;
35
+};
36
+
37
+#define FOURCC(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
38
+
39
+static inline uint16_t parse_be16(const uint8_t *in)
40
+{
41
+   return (in0 << 8) | in1;
42
+}
43
+static inline uint32_t parse_be32(const uint8_t *in)
44
+{
45
+   return FOURCC(in0, in1, in2, in3);
46
+}
47
+
48
+static inline uint64_t parse_be64(const uint8_t *in)
49
+{
50
+   uint64_t res = in7;
51
+   res |= ((uint64_t)in6) << 8;
52
+   res |= ((uint64_t)in5) << 16;
53
+   res |= ((uint64_t)in4) << 24;
54
+   res |= ((uint64_t)in3) << 32;
55
+   res |= ((uint64_t)in2) << 40;
56
+   res |= ((uint64_t)in1) << 48;
57
+   res |= ((uint64_t)in0) << 56;
58
+   return res;
59
+}
60
+
61
+static inline int f_avail(struct dff_file *f)
62
+{
63
+   if (f->p < f->data + f->size)
64
+       return f->size + f->data - f->p;
65
+   return 0;
66
+}
67
+
68
+static int read_chunk(struct dff_file *f, struct dff_chunk *c)
69
+{
70
+   if (f_avail(f) < 12)
71
+       return -ENOSPC;
72
+
73
+   c->id = parse_be32(f->p);   /* id of this chunk */
74
+   c->size = parse_be64(f->p + 4); /* size of this chunk */
75
+   f->p += 12;
76
+   c->data = f->p;
77
+   return 0;
78
+}
79
+
80
+static int skip_chunk(struct dff_file *f, const struct dff_chunk *c)
81
+{
82
+   f->p = SPA_PTROFF(c->data, c->size, uint8_t);
83
+   return 0;
84
+}
85
+
86
+static int read_PROP(struct dff_file *f, struct dff_chunk *prop)
87
+{
88
+   struct dff_chunk c1;
89
+   int res;
90
+
91
+   if (f_avail(f) < 4 ||
92
+       memcmp(prop->data, "SND ", 4) != 0)
93
+       return -EINVAL;
94
+   f->p += 4;
95
+
96
+   while (f->p < SPA_PTROFF(prop->data, prop->size, uint8_t)) {
97
+       if ((res = read_chunk(f, &c0)) < 0)
98
+           return res;
99
+
100
+       switch (c0.id) {
101
+       case FOURCC('F', 'S', ' ', ' '):
102
+           f->info.rate = parse_be32(f->p);
103
+           break;
104
+       case FOURCC('C', 'H', 'N', 'L'):
105
+           f->info.channels = parse_be16(f->p);
106
+           switch (f->info.channels) {
107
+           case 2:
108
+               f->info.channel_type = 2;
109
+               break;
110
+           case 5:
111
+               f->info.channel_type = 6;
112
+               break;
113
+           case 6:
114
+               f->info.channel_type = 7;
115
+               break;
116
+           }
117
+           break;
118
+       case FOURCC('C', 'M', 'P', 'R'):
119
+       {
120
+           uint32_t cmpr = parse_be32(f->p);
121
+           if (cmpr != FOURCC('D', 'S', 'D', ' '))
122
+               return -ENOTSUP;
123
+           break;
124
+       }
125
+       case FOURCC('A', 'B', 'S', 'S'):
126
+           break;
127
+       case FOURCC('L', 'S', 'C', 'O'):
128
+           break;
129
+       default:
130
+           break;
131
+       }
132
+       skip_chunk(f, &c0);
133
+   }
134
+   return 0;
135
+}
136
+
137
+static int read_FRM8(struct dff_file *f)
138
+{
139
+   struct dff_chunk c2;
140
+   int res;
141
+   bool found_dsd = false;
142
+
143
+   if ((res = read_chunk(f, &c0)) < 0)
144
+       return res;
145
+   if (c0.id != FOURCC('F','R','M','8'))
146
+       return -EINVAL;
147
+   if (f_avail(f) < 4 ||
148
+       memcmp(c0.data, "DSD ", 4) != 0)
149
+       return -EINVAL;
150
+   f->p += 4;
151
+
152
+   while (true) {
153
+       if ((res = read_chunk(f, &c1)) < 0)
154
+           return res;
155
+
156
+       switch (c1.id) {
157
+       case FOURCC('F', 'V', 'E', 'R'):
158
+           break;
159
+       case FOURCC('P', 'R', 'O', 'P'):
160
+           read_PROP(f, &c1);
161
+           break;
162
+       case FOURCC('D', 'S', 'D', ' '):
163
+       {
164
+           f->info.length = c1.size;
165
+           f->info.samples = c1.size / f->info.channels;
166
+           f->info.lsb = 0;
167
+           f->info.blocksize = 1;
168
+           found_dsd = true;
169
+           break;
170
+       }
171
+       default:
172
+           break;
173
+       }
174
+       if (found_dsd)
175
+           break;
176
+
177
+       skip_chunk(f, &c1);
178
+   }
179
+   return 0;
180
+}
181
+
182
+static int open_read(struct dff_file *f, const char *filename, struct dff_file_info *info)
183
+{
184
+   int res;
185
+   struct stat st;
186
+
187
+   if ((f->fd = open(filename, O_RDONLY)) < 0) {
188
+       res = -errno;
189
+       goto exit;
190
+   }
191
+   if (fstat(f->fd, &st) < 0) {
192
+       res = -errno;
193
+       goto exit_close;
194
+   }
195
+   f->size = st.st_size;
196
+
197
+   f->data = mmap(NULL, f->size, PROT_READ, MAP_SHARED, f->fd, 0);
198
+   if (f->data == MAP_FAILED) {
199
+       res = -errno;
200
+       goto exit_close;
201
pipewire-0.3.81.tar.gz/src/tools/dfffile.h Added
33
 
1
@@ -0,0 +1,31 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <stdio.h>
7
+
8
+#include <spa/utils/defs.h>
9
+
10
+struct dff_file;
11
+
12
+struct dff_file_info {
13
+   uint32_t channel_type;
14
+   uint32_t channels;
15
+   uint32_t rate;
16
+   bool lsb;
17
+   uint64_t samples;
18
+   uint64_t length;
19
+   uint32_t blocksize;
20
+};
21
+
22
+struct dff_layout {
23
+   int32_t interleave;
24
+   uint32_t channels;
25
+   bool lsb;
26
+};
27
+
28
+struct dff_file * dff_file_open(const char *filename, const char *mode, struct dff_file_info *info);
29
+
30
+ssize_t dff_file_read(struct dff_file *f, void *data, size_t samples, const struct dff_layout *layout);
31
+
32
+int dff_file_close(struct dff_file *f);
33
pipewire-0.3.80.tar.gz/src/tools/meson.build -> pipewire-0.3.81.tar.gz/src/tools/meson.build Changed
9
 
1
@@ -47,6 +47,7 @@
2
   pwcat_sources = 
3
     'pw-cat.c',
4
     'midifile.c',
5
+    'dfffile.c',
6
     'dsffile.c',
7
   
8
 
9
pipewire-0.3.80.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cat.c Changed
130
 
1
@@ -41,6 +41,7 @@
2
 #endif
3
 
4
 #include "midifile.h"
5
+#include "dfffile.h"
6
 #include "dsffile.h"
7
 
8
 #define DEFAULT_MEDIA_TYPE "Audio"
9
@@ -143,6 +144,11 @@
10
        struct dsf_file_info info;
11
        struct dsf_layout layout;
12
    } dsf;
13
+   struct {
14
+       struct dff_file *file;
15
+       struct dff_file_info info;
16
+       struct dff_layout layout;
17
+   } dff;
18
 
19
 #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
20
    struct {
21
@@ -798,6 +804,10 @@
22
    data->dsf.layout.channels = info.info.dsd.channels;
23
    data->dsf.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb;
24
 
25
+   data->dff.layout.interleave = info.info.dsd.interleave,
26
+   data->dff.layout.channels = info.info.dsd.channels;
27
+   data->dff.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb;
28
+
29
    data->stride = data->dsf.layout.channels * SPA_ABS(data->dsf.layout.interleave);
30
 
31
    if (data->verbose) {
32
@@ -1164,26 +1174,46 @@
33
    return dsf_file_read(d->dsf.file, src, n_frames, &d->dsf.layout);
34
 }
35
 
36
-static int setup_dsffile(struct data *data)
37
+static int dff_play(struct data *d, void *src, unsigned int n_frames, bool *null_frame)
38
+{
39
+   return dff_file_read(d->dff.file, src, n_frames, &d->dff.layout);
40
+}
41
+
42
+static int setup_dsdfile(struct data *data)
43
 {
44
    if (data->mode == mode_record)
45
        return -ENOTSUP;
46
 
47
    data->dsf.file = dsf_file_open(data->filename, "r", &data->dsf.info);
48
    if (data->dsf.file == NULL) {
49
-       fprintf(stderr, "dsffile: can't read dsf file '%s': %m\n", data->filename);
50
-       return -errno;
51
+       data->dff.file = dff_file_open(data->filename, "r", &data->dff.info);
52
+       if (data->dff.file == NULL) {
53
+           fprintf(stderr, "dsdfile: can't read dsd file '%s': %m\n", data->filename);
54
+           return -errno;
55
+       }
56
    }
57
 
58
-   if (data->verbose)
59
-       printf("dsffile: opened file \"%s\" channels:%d rate:%d samples:%"PRIu64" bitorder:%s\n",
60
+   if (data->dsf.file != NULL) {
61
+       if (data->verbose)
62
+           printf("dsffile: opened file \"%s\" channels:%d rate:%d "
63
+                   "samples:%"PRIu64" bitorder:%s\n",
64
                data->filename,
65
                data->dsf.info.channels, data->dsf.info.rate,
66
                data->dsf.info.samples,
67
                data->dsf.info.lsb ? "lsb" : "msb");
68
 
69
-   data->fill = dsf_play;
70
+       data->fill = dsf_play;
71
+   } else {
72
+       if (data->verbose)
73
+           printf("dfffile: opened file \"%s\" channels:%d rate:%d "
74
+                   "samples:%"PRIu64" bitorder:%s\n",
75
+               data->filename,
76
+               data->dff.info.channels, data->dff.info.rate,
77
+               data->dff.info.samples,
78
+               data->dff.info.lsb ? "lsb" : "msb");
79
 
80
+       data->fill = dff_play;
81
+   }
82
    return 0;
83
 }
84
 
85
@@ -1839,7 +1869,7 @@
86
            ret = setup_midifile(&data);
87
            break;
88
        case TYPE_DSD:
89
-           ret = setup_dsffile(&data);
90
+           ret = setup_dsdfile(&data);
91
            break;
92
 #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
93
        case TYPE_ENCODED:
94
@@ -1918,13 +1948,21 @@
95
    case TYPE_DSD:
96
    {
97
        struct spa_audio_info_dsd info;
98
+       uint32_t channel_type;
99
 
100
        spa_zero(info);
101
-       info.channels = data.dsf.info.channels;
102
-       info.rate = data.dsf.info.rate / 8;
103
+       if (data.dsf.file != NULL) {
104
+           info.channels = data.dsf.info.channels;
105
+           info.rate = data.dsf.info.rate / 8;
106
+           channel_type = data.dsf.info.channel_type;
107
+       } else {
108
+           info.channels = data.dff.info.channels;
109
+           info.rate = data.dff.info.rate / 8;
110
+           channel_type = data.dff.info.channel_type;
111
+       }
112
 
113
        SPA_FOR_EACH_ELEMENT_VAR(dsd_layouts, i) {
114
-           if (i->type != data.dsf.info.channel_type)
115
+           if (i->type != channel_type)
116
                continue;
117
            info.channels = i->info.n_channels;
118
            memcpy(info.position, i->info.position,
119
@@ -2020,6 +2058,10 @@
120
        sf_close(data.file);
121
    if (data.midi.file)
122
        midi_file_close(data.midi.file);
123
+   if (data.dsf.file)
124
+       dsf_file_close(data.dsf.file);
125
+   if (data.dff.file)
126
+       dff_file_close(data.dff.file);
127
 #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
128
    if (data.encoded.packet)
129
        av_packet_free(&data.encoded.packet);
130
pipewire-0.3.80.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cli.c Changed
201
 
1
@@ -348,6 +348,10 @@
2
    bool ret;
3
 
4
    global = calloc(1, sizeof(struct global));
5
+   if (global == NULL) {
6
+       fprintf(stderr, "Allocation failed: %m");
7
+       return;
8
+   }
9
    global->rd = rd;
10
    global->id = id;
11
    global->permissions = permissions;
12
@@ -615,6 +619,8 @@
13
    struct pw_core_info *info = pd->info;
14
 
15
    info_global(pd);
16
+   if (info == NULL)
17
+       return;
18
    printf("\tcookie: %u\n", info->cookie);
19
    printf("\tuser-name: \"%s\"\n", info->user_name);
20
    printf("\thost-name: \"%s\"\n", info->host_name);
21
@@ -629,6 +635,8 @@
22
    struct pw_module_info *info = pd->info;
23
 
24
    info_global(pd);
25
+   if (info == NULL)
26
+       return;
27
    printf("\tname: \"%s\"\n", info->name);
28
    printf("\tfilename: \"%s\"\n", info->filename);
29
    printf("\targs: \"%s\"\n", info->args);
30
@@ -641,6 +649,8 @@
31
    struct pw_node_info *info = pd->info;
32
 
33
    info_global(pd);
34
+   if (info == NULL)
35
+       return;
36
    printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS),
37
            info->n_input_ports, info->max_input_ports);
38
    printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS),
39
@@ -661,6 +671,8 @@
40
    struct pw_port_info *info = pd->info;
41
 
42
    info_global(pd);
43
+   if (info == NULL)
44
+       return;
45
    printf("\tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
46
    print_properties(info->props, MARK_CHANGE(PW_PORT_CHANGE_MASK_PROPS), true);
47
    print_params(info->params, info->n_params, MARK_CHANGE(PW_PORT_CHANGE_MASK_PARAMS), true);
48
@@ -672,6 +684,8 @@
49
    struct pw_factory_info *info = pd->info;
50
 
51
    info_global(pd);
52
+   if (info == NULL)
53
+       return;
54
    printf("\tname: \"%s\"\n", info->name);
55
    printf("\tobject-type: %s/%d\n", info->type, info->version);
56
    print_properties(info->props, MARK_CHANGE(PW_FACTORY_CHANGE_MASK_PROPS), true);
57
@@ -683,6 +697,8 @@
58
    struct pw_client_info *info = pd->info;
59
 
60
    info_global(pd);
61
+   if (info == NULL)
62
+       return;
63
    print_properties(info->props, MARK_CHANGE(PW_CLIENT_CHANGE_MASK_PROPS), true);
64
    info->change_mask = 0;
65
 }
66
@@ -692,6 +708,8 @@
67
    struct pw_link_info *info = pd->info;
68
 
69
    info_global(pd);
70
+   if (info == NULL)
71
+       return;
72
    printf("\toutput-node-id: %u\n", info->output_node_id);
73
    printf("\toutput-port-id: %u\n", info->output_port_id);
74
    printf("\tinput-node-id: %u\n", info->input_node_id);
75
@@ -717,6 +735,8 @@
76
    struct pw_device_info *info = pd->info;
77
 
78
    info_global(pd);
79
+   if (info == NULL)
80
+       return;
81
    print_properties(info->props, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PROPS), true);
82
    print_params(info->params, info->n_params, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PARAMS), true);
83
    info->change_mask = 0;
84
@@ -727,6 +747,8 @@
85
    struct pw_session_info *info = pd->info;
86
 
87
    info_global(pd);
88
+   if (info == NULL)
89
+       return;
90
    print_properties(info->props, MARK_CHANGE(0), true);
91
    print_params(info->params, info->n_params, MARK_CHANGE(1), true);
92
    info->change_mask = 0;
93
@@ -738,6 +760,8 @@
94
    const char *direction;
95
 
96
    info_global(pd);
97
+   if (info == NULL)
98
+       return;
99
    printf("\tname: %s\n", info->name);
100
    printf("\tmedia-class: %s\n",  info->media_class);
101
    switch(info->direction) {
102
@@ -765,6 +789,8 @@
103
    struct pw_endpoint_stream_info *info = pd->info;
104
 
105
    info_global(pd);
106
+   if (info == NULL)
107
+       return;
108
    printf("\tid: %u\n", info->id);
109
    printf("\tendpoint-id: %u\n", info->endpoint_id);
110
    printf("\tname: %s\n", info->name);
111
@@ -987,25 +1013,25 @@
112
    struct remote_data *rd = pd->rd;
113
    struct pw_session_info *info = pd->info;
114
 
115
-   if (!info) {
116
+   if (info == NULL)
117
        info = pd->info = calloc(1, sizeof(*info));
118
+   if (info != NULL) {
119
        info->id = update->id;
120
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
121
+           info->n_params = update->n_params;
122
+           free(info->params);
123
+           info->params = malloc(info->n_params * sizeof(struct spa_param_info));
124
+           memcpy(info->params, update->params,
125
+               info->n_params * sizeof(struct spa_param_info));
126
+       }
127
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
128
+           pw_properties_free ((struct pw_properties *)info->props);
129
+           info->props =
130
+               (struct spa_dict *) pw_properties_new_dict (update->props);
131
+       }
132
    }
133
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
134
-       info->n_params = update->n_params;
135
-       free(info->params);
136
-       info->params = malloc(info->n_params * sizeof(struct spa_param_info));
137
-       memcpy(info->params, update->params,
138
-           info->n_params * sizeof(struct spa_param_info));
139
-   }
140
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
141
-       pw_properties_free ((struct pw_properties *)info->props);
142
-       info->props =
143
-           (struct spa_dict *) pw_properties_new_dict (update->props);
144
-   }
145
-
146
    if (pd->global == NULL)
147
-       pd->global = pw_map_lookup(&rd->globals, info->id);
148
+       pd->global = pw_map_lookup(&rd->globals, update->id);
149
    if (pd->global && pd->global->info_pending) {
150
        info_session(pd);
151
        pd->global->info_pending = false;
152
@@ -1034,33 +1060,34 @@
153
    struct remote_data *rd = pd->rd;
154
    struct pw_endpoint_info *info = pd->info;
155
 
156
-   if (!info) {
157
+   if (info == NULL)
158
        info = pd->info = calloc(1, sizeof(*info));
159
+   if (info != NULL) {
160
        info->id = update->id;
161
        info->name = update->name ? strdup(update->name) : NULL;
162
        info->media_class = update->media_class ? strdup(update->media_class) : NULL;
163
        info->direction = update->direction;
164
        info->flags = update->flags;
165
-   }
166
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS)
167
-       info->n_streams = update->n_streams;
168
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION)
169
-       info->session_id = update->session_id;
170
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
171
-       info->n_params = update->n_params;
172
-       free(info->params);
173
-       info->params = malloc(info->n_params * sizeof(struct spa_param_info));
174
-       memcpy(info->params, update->params,
175
-           info->n_params * sizeof(struct spa_param_info));
176
-   }
177
-   if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
178
-       pw_properties_free ((struct pw_properties *)info->props);
179
-       info->props =
180
-           (struct spa_dict *) pw_properties_new_dict (update->props);
181
-   }
182
 
183
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS)
184
+           info->n_streams = update->n_streams;
185
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION)
186
+           info->session_id = update->session_id;
187
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
188
+           info->n_params = update->n_params;
189
+           free(info->params);
190
+           info->params = malloc(info->n_params * sizeof(struct spa_param_info));
191
+           memcpy(info->params, update->params,
192
+               info->n_params * sizeof(struct spa_param_info));
193
+       }
194
+       if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
195
+           pw_properties_free ((struct pw_properties *)info->props);
196
+           info->props =
197
+               (struct spa_dict *) pw_properties_new_dict (update->props);
198
+       }
199
+   }
200
    if (pd->global == NULL)
201
pipewire-0.3.80.tar.gz/src/tools/pw-link.c -> pipewire-0.3.81.tar.gz/src/tools/pw-link.c Changed
12
 
1
@@ -197,7 +197,9 @@
2
 static void print_port(struct data *data, const char *prefix, struct object *n,
3
        struct object *p, bool verbose)
4
 {
5
-   char buffer1024, id64 = "", *prefix2 = "";
6
+   char buffer1024, id64 = "";
7
+   const char *prefix2 = "";
8
+
9
    if (data->opt_id) {
10
        snprintf(id, sizeof(id), "%4d ", p->id);
11
        prefix2 = "     ";
12
pipewire-0.3.80.tar.gz/test/pwtest.c -> pipewire-0.3.81.tar.gz/test/pwtest.c Changed
10
 
1
@@ -1207,7 +1207,7 @@
2
    time_t t = time(NULL);
3
    struct tm *tm = localtime(&t);
4
    char *dir;
5
-   char *tmpdir = getenv("TMPDIR");
6
+   const char *tmpdir = getenv("TMPDIR");
7
    char pathPATH_MAX;
8
    FILE *fp;
9
 
10
pipewire-0.3.80.tar.gz/test/test-logger.c -> pipewire-0.3.81.tar.gz/test/test-logger.c Changed
19
 
1
@@ -232,7 +232,7 @@
2
    enum spa_log_level level = pwtest_get_iteration(current_test);
3
    enum spa_log_level default_level = pw_log_level;
4
    struct spa_log *default_logger = pw_log_get();
5
-   char *lvl = NULL;
6
+   const char *lvl = NULL;
7
    char *oldenv = getenv("PIPEWIRE_DEBUG");
8
 
9
    if (oldenv)
10
@@ -276,7 +276,7 @@
11
    struct spa_log *default_logger = pw_log_get();
12
    char *oldenv = getenv("PIPEWIRE_DEBUG");
13
    char lvlstr32;
14
-   char *lvl = "X";
15
+   const char *lvl = "X";
16
 
17
    if (oldenv)
18
        oldenv = strdup(oldenv);
19
pipewire-0.3.80.tar.gz/test/test-spa-json.c -> pipewire-0.3.81.tar.gz/test/test-spa-json.c Changed
29
 
1
@@ -166,7 +166,7 @@
2
    return PWTEST_PASS;
3
 }
4
 
5
-static void test_array(char *str, char **vals)
6
+static void test_array(const char *str, const char * const vals)
7
 {
8
    struct spa_json it2;
9
    char val256;
10
@@ -183,12 +183,12 @@
11
 
12
 PWTEST(json_array)
13
 {
14
-   test_array("FL,FR", (char *){ "FL", "FR", NULL });
15
-   test_array(" FL , FR ", (char *){ "FL", "FR", NULL });
16
-   test_array(" FL , FR ", (char *){ "FL", "FR", NULL });
17
-   test_array("FL FR", (char *){ "FL", "FR", NULL });
18
-   test_array("FL FR", (char *){ "FL", "FR", NULL });
19
-   test_array(" FL FR ", (char *){ "FL", "FR", NULL });
20
+   test_array("FL,FR", (const char *){ "FL", "FR", NULL });
21
+   test_array(" FL , FR ", (const char *){ "FL", "FR", NULL });
22
+   test_array(" FL , FR ", (const char *){ "FL", "FR", NULL });
23
+   test_array("FL FR", (const char *){ "FL", "FR", NULL });
24
+   test_array("FL FR", (const char *){ "FL", "FR", NULL });
25
+   test_array(" FL FR ", (const char *){ "FL", "FR", NULL });
26
 
27
    return PWTEST_PASS;
28
 }
29