Overview

Request 5812 (accepted)

New upstream release

Submit package home:zaitor:...s:Essentials / pipewire-aptx to package Essentials / pipewire-aptx

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Wed Jul 26 14:05:18 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.74
6
+
7
+-------------------------------------------------------------------
8
 Thu Jun 29 10:47:58 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.72
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.72
6
+Version:        0.3.74
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.72.tar.gz/.gitignore -> pipewire-0.3.74.tar.gz/.gitignore Changed
10
 
1
@@ -1,7 +1,5 @@
2
 .*
3
-.tarball-version
4
-.version
5
-.*.swp
6
+!.gitlab
7
 ABOUT-NLS
8
 *~
9
 *.tar.gz
10
pipewire-0.3.72.tar.gz/.gitlab/ci/check_missing_headers.sh -> pipewire-0.3.74.tar.gz/.gitlab/ci/check_missing_headers.sh Changed
16
 
1
@@ -5,12 +5,12 @@
2
 
3
 LIST=""
4
 
5
-for i in $(find spa/include -name '*.h' | sed s#spa/include/##);
6
+for i in $(find spa/include -name '*.h' -a -not -path 'spa/include/spa/utils/cleanup.h' | sed s#spa/include/##);
7
 do
8
     -f "$PREFIX/include/spa-0.2/$i"  || LIST="$i $LIST"
9
 done
10
 
11
-for i in $(find src/pipewire -name '*.h' -a -not -name '*private.h' | sed s#src/##);
12
+for i in $(find src/pipewire -name '*.h' -a -not -name '*private.h' -a -not -name 'cleanup.h' | sed s#src/##);
13
 do
14
     -f "$PREFIX/include/pipewire-0.3/$i"  || LIST="$i $LIST"
15
 done
16
pipewire-0.3.72.tar.gz/NEWS -> pipewire-0.3.74.tar.gz/NEWS Changed
124
 
1
@@ -1,3 +1,112 @@
2
+# PipeWire 0.3.74 (2023-07-12)
3
+
4
+This is a quick bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - Fix a critical bug where audio to bluetooth devices would cut out
9
+    randomly. (#3316)
10
+  - Improve RAOP compatibility.
11
+  - Avoid crashes after an update.
12
+  - Small fixes and improvements.
13
+
14
+
15
+## PipeWire
16
+  - Mix info on port is now created explicitly.
17
+  - Remove the node as a driver peer when stopping. This caused some problem
18
+    with playback on and other remote bluetooth devices. (#3316)
19
+  - Work on avoiding crashes when loading new modules that use internal API
20
+    with old libpipewire. This is typical after an update where the old library is
21
+    still loaded by an application but when a new stream is created, updated
22
+    modules are loaded. (#3243)
23
+
24
+## Modules
25
+  - The RTP source module now has an option to ignore the SSRC, which is
26
+    useful to continue to receive the stream when the sender is restarted.
27
+  - The native protocol will refuse to load twice now instead of silently
28
+    ignoring the error.
29
+  - module-raop is compatible with more devices. (#3247)
30
+
31
+## SPA
32
+  - plugins will now warn when running out of buffers. This is always a bad
33
+    thing.
34
+  - Merge scope based cleanup macros.
35
+  - Add ratelimit function.
36
+
37
+Older versions:
38
+
39
+
40
+# PipeWire 0.3.73 (2023-07-06)
41
+
42
+This is a bugfix release that is API and ABI compatible with previous
43
+0.3.x releases.
44
+
45
+## Highlights
46
+  - Fixes an ALSA resume after suspend error.
47
+  - Handle and disable seemingly wrong hires timestamps from ALSA.
48
+  - Filter-chain now has loadable plugin modules. The LV2 and sofa plugins are
49
+    moved to a separate .so file to make things more modular.
50
+  - Rate changes in the graph should now be handled more gracefully by loopback
51
+    and filter-chain.
52
+  - A regression in the rtp-sap module was fixed where it would in some cases
53
+    fail to start.
54
+  - A potential crash in the peaks resampler was fixed.
55
+  - Many cleanups and other small bug fixes.
56
+
57
+
58
+## PipeWire
59
+  - Fix a potential segfault when no fallback driver was set in the config.
60
+  - Improve OPUS detection.
61
+  - Add ASYNC flag to pw-filter and pw-stream when queue/dequeue is not called
62
+    from the process function. This ensure we allocate an extra buffer.
63
+  - Discard pending process callbacks when disconnecting. (#3314)
64
+  - Cleanups and improvements to the debug environment variable parsing.
65
+  - The graph rate was tweaked to better handle very low rates such as those
66
+    requested by pavucontrol when it does the signal monitoring.
67
+
68
+## Modules
69
+  - An example filter module was added.
70
+  - Filter-chain and loopback now disable the resamplers if no rate is specified
71
+    and will always follow the graph rate.
72
+  - Improve setup of filter-chain. The graph is now created when starting
73
+    because this ensure the target graph rate is known.
74
+  - Filter-chain can now link notify ports to control ports in the graph.
75
+  - Filter-chain now has loadable plugin modules. The LV2 and sofa plugins are
76
+    moved to a separate .so file.
77
+  - A regression in the rtp-sap module was fixed where it would in some cases
78
+    fail to start.
79
+  - Module-rt now has options to disable rlimits, portal and rtkit.
80
+  - module-raop-discover now has an options to set the latency. (#3247)
81
+
82
+## Tools
83
+  - pw-cat now supports overriding all stream properties.
84
+
85
+## SPA
86
+  - Disable rate negotiation when the resampler is disabled. We will always
87
+    follow the graph rate. 
88
+  - Set device.icon property for UCM ports as well.
89
+  - Improve ALSA recover when using hires timestamps. This fixes some problems
90
+    after resume from suspend. (#3315)
91
+  - ALSA will now warn and disable hires timestamp when they seem wrong.
92
+    They can also be disabled manually with a property.
93
+  - V4l2 will now gracefully handle ENOTTY when enumerating frame sizes and
94
+    frame rates. (#3325)
95
+  - A potential crash in the peaks resampler was fixed. (#3320)
96
+
97
+## pulse-server
98
+  - A client crash in pavucontrol is avoided by always setting a card name.
99
+  - The graph rate is now taken correctly when using the FIX flags. (#3317)
100
+  - An option was added to ignore the FIX flags of a stream. Also the
101
+    documentation for those options was updated. (#3317)
102
+  - module-raop-discover now support latency_msec. (#3247)
103
+
104
+## Bluetooth
105
+  - Remove an assert and issue a warning/recover instead when a buffer is too
106
+    small.
107
+
108
+## GStreamer
109
+  - The device provider does locking when destroying the registry.
110
+
111
 # PipeWire 0.3.72 (2023-06-26)
112
 
113
 This is a bugfix release that is API and ABI compatible with previous
114
@@ -101,9 +210,6 @@
115
 ## GStreamer
116
   - Fill default strides instead of 0 on pipewire video buffers. (#3236)
117
 
118
-Older versions:
119
-
120
-
121
 # PipeWire 0.3.71 (2023-05-17)
122
 
123
 This is a bugfix release that is API and ABI compatible with previous
124
pipewire-0.3.72.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.74.tar.gz/doc/pipewire-modules.dox Changed
9
 
1
@@ -56,6 +56,7 @@
2
 - \subpage page_module_client_node
3
 - \subpage page_module_combine_stream
4
 - \subpage page_module_echo_cancel
5
+- \subpage page_module_example_filter
6
 - \subpage page_module_example_sink
7
 - \subpage page_module_example_source
8
 - \subpage page_module_fallback_sink
9
pipewire-0.3.72.tar.gz/meson.build -> pipewire-0.3.74.tar.gz/meson.build Changed
46
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.72',
4
+  version : '0.3.74',
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
@@ -82,9 +82,9 @@
9
   '-Wno-missing-field-initializers',
10
   '-Wno-unused-parameter',
11
   '-Wno-pedantic',
12
-  '-Wold-style-declaration',
13
   '-Wdeprecated-declarations',
14
   '-Wunused-result',
15
+  '-Werror=return-type',
16
 
17
 
18
 cc_flags = common_flags + 
19
@@ -93,6 +93,10 @@
20
 # '-DSPA_DEBUG_MEMCPY',
21
   '-Werror=implicit-function-declaration',
22
   '-Werror=int-conversion',
23
+  '-Werror=old-style-declaration',
24
+  '-Werror=old-style-definition',
25
+  '-Werror=missing-parameter-type',
26
+  '-Werror=strict-prototypes',
27
 
28
 add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
29
 
30
@@ -295,7 +299,6 @@
31
 cdata.set('HAVE_SNDFILE', sndfile_dep.found())
32
 libmysofa_dep = dependency('libmysofa', required : get_option('libmysofa'))
33
 summary({'libmysofa': libmysofa_dep.found()}, bool_yn: true, section: 'filter-chain')
34
-cdata.set('HAVE_LIBMYSOFA', libmysofa_dep.found())
35
 pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
36
 summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
37
 avahi_dep = dependency('avahi-client', required : get_option('avahi'))
38
@@ -403,7 +406,6 @@
39
 
40
 lilv_lib = dependency('lilv-0', required: get_option('lv2'))
41
 summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true)
42
-cdata.set('HAVE_LILV', lilv_lib.found())
43
 
44
 libffado_dep = dependency('libffado', required: get_option('libffado'))
45
 summary({'ffado': libffado_dep.found()}, bool_yn: true)
46
pipewire-0.3.72.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.74.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
120
 
1
@@ -11,6 +11,7 @@
2
 #include <math.h>
3
 
4
 #include <jack/jack.h>
5
+#include <jack/intclient.h>
6
 #include <jack/session.h>
7
 #include <jack/thread.h>
8
 #include <jack/midiport.h>
9
@@ -20,9 +21,11 @@
10
 #include <spa/support/cpu.h>
11
 #include <spa/param/audio/format-utils.h>
12
 #include <spa/param/video/format-utils.h>
13
+#include <spa/param/latency-utils.h>
14
 #include <spa/debug/types.h>
15
 #include <spa/debug/pod.h>
16
 #include <spa/utils/json.h>
17
+#include <spa/utils/result.h>
18
 #include <spa/utils/string.h>
19
 #include <spa/utils/ringbuffer.h>
20
 
21
@@ -297,6 +300,7 @@
22
    char *load_init;        /* initialization string */
23
    jack_uuid_t session_id;     /* requested session_id */
24
 
25
+   struct pw_loop *l;
26
    struct pw_data_loop *loop;
27
    struct pw_properties *props;
28
 
29
@@ -586,14 +590,6 @@
30
    return mix;
31
 }
32
 
33
-static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_id)
34
-{
35
-   struct mix *mix;
36
-   if ((mix = find_mix(c, port, mix_id)) != NULL)
37
-       return mix;
38
-   return create_mix(c, port, mix_id, SPA_ID_INVALID);
39
-}
40
-
41
 static int clear_buffers(struct client *c, struct mix *mix)
42
 {
43
    struct port *port = mix->port;
44
@@ -1239,7 +1235,7 @@
45
 static void client_remove_source(struct client *c)
46
 {
47
    if (c->socket_source) {
48
-       pw_loop_destroy_source(c->loop->loop, c->socket_source);
49
+       pw_loop_destroy_source(c->l, c->socket_source);
50
        c->socket_source = NULL;
51
    }
52
 }
53
@@ -1867,7 +1863,7 @@
54
            c, readfd, writefd, c->node_id);
55
 
56
    close(writefd);
57
-   c->socket_source = pw_loop_add_io(c->loop->loop,
58
+   c->socket_source = pw_loop_add_io(c->l,
59
                      readfd,
60
                      SPA_IO_ERR | SPA_IO_HUP,
61
                      true, on_rtsocket_condition, c);
62
@@ -2027,7 +2023,7 @@
63
    case SPA_NODE_COMMAND_Suspend:
64
    case SPA_NODE_COMMAND_Pause:
65
        if (c->started) {
66
-           pw_loop_update_io(c->loop->loop,
67
+           pw_loop_update_io(c->l,
68
                      c->socket_source, SPA_IO_ERR | SPA_IO_HUP);
69
 
70
            c->started = false;
71
@@ -2036,7 +2032,7 @@
72
 
73
    case SPA_NODE_COMMAND_Start:
74
        if (!c->started) {
75
-           pw_loop_update_io(c->loop->loop,
76
+           pw_loop_update_io(c->l,
77
                      c->socket_source,
78
                      SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP);
79
            c->started = true;
80
@@ -2482,7 +2478,7 @@
81
        res = -EINVAL;
82
        goto done;
83
    }
84
-   if ((mix = ensure_mix(c, p, mix_id)) == NULL) {
85
+   if ((mix = find_mix(c, p, mix_id)) == NULL) {
86
        res = -ENOMEM;
87
        goto done;
88
    }
89
@@ -2632,7 +2628,7 @@
90
        goto exit;
91
    }
92
 
93
-   if ((mix = ensure_mix(c, p, mix_id)) == NULL) {
94
+   if ((mix = find_mix(c, p, mix_id)) == NULL) {
95
        res = -ENOMEM;
96
        goto exit;
97
    }
98
@@ -3645,6 +3641,7 @@
99
            &thread_utils_impl, client);
100
 
101
    client->loop = pw_context_get_data_loop(client->context.context);
102
+   client->l = pw_data_loop_get_loop(client->loop);
103
    pw_data_loop_stop(client->loop);
104
 
105
    pw_context_set_object(client->context.context,
106
@@ -4736,6 +4733,13 @@
107
    param_latency_other(c, p, &paramsn_params++, &b);
108
 
109
    pw_thread_loop_lock(c->context.loop);
110
+   if (create_mix(c, p, SPA_ID_INVALID, SPA_ID_INVALID) == NULL) {
111
+       res = -errno;
112
+       pw_log_warn("can't create mix for port %s: %m", port_name);
113
+       pw_thread_loop_unlock(c->context.loop);
114
+       goto error_free;
115
+   }
116
+
117
    freeze_callbacks(c);
118
 
119
    pw_client_node_port_update(c->node,
120
pipewire-0.3.72.tar.gz/spa/examples/adapter-control.c -> pipewire-0.3.74.tar.gz/spa/examples/adapter-control.c Changed
10
 
1
@@ -176,7 +176,7 @@
2
    return res;
3
 }
4
 
5
-int init_data(struct data *data)
6
+static int init_data(struct data *data)
7
 {
8
    int res;
9
    const char *str;
10
pipewire-0.3.72.tar.gz/spa/examples/example-control.c -> pipewire-0.3.74.tar.gz/spa/examples/example-control.c Changed
10
 
1
@@ -457,7 +457,7 @@
2
    return -EBADF;
3
 }
4
 
5
-int init_data(struct data *data)
6
+static int init_data(struct data *data)
7
 {
8
    int res;
9
    const char *str;
10
pipewire-0.3.72.tar.gz/spa/include/meson.build -> pipewire-0.3.74.tar.gz/spa/include/meson.build Changed
11
 
1
@@ -14,5 +14,8 @@
2
 
3
 spa_headers = 'spa'  # used by doxygen
4
 install_subdir('spa',
5
-  install_dir : get_option('includedir') / spa_name
6
+  install_dir : get_option('includedir') / spa_name,
7
+  exclude_files : 
8
+    'utils/cleanup.h',
9
+  ,
10
 )
11
pipewire-0.3.74.tar.gz/spa/include/spa/utils/cleanup.h Added
100
 
1
@@ -0,0 +1,98 @@
2
+/* Simple Plugin API */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#ifndef SPA_UTILS_CLEANUP_H
7
+#define SPA_UTILS_CLEANUP_H
8
+
9
+#if !defined(__has_attribute) || !__has_attribute(__cleanup__)
10
+#error "attribute `cleanup` is required"
11
+#endif
12
+
13
+#define spa_cleanup(func) __attribute__((__cleanup__(func)))
14
+
15
+#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
16
+typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
17
+static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \
18
+{ \
19
+   __VA_ARGS__ \
20
+}
21
+
22
+#define spa_auto(name) \
23
+   spa_cleanup(_spa_auto_cleanup_func_ ## name) \
24
+   _spa_auto_cleanup_type_ ## name
25
+
26
+#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \
27
+typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \
28
+static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \
29
+{ \
30
+   __VA_ARGS__ \
31
+}
32
+
33
+#define spa_autoptr(name) \
34
+   spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
35
+   _spa_autoptr_cleanup_type_ ## name
36
+
37
+#define spa_exchange(var, new_value) \
38
+__extension__ ({ \
39
+   __typeof__(var) _old_value = (var); \
40
+   (var) = (new_value); \
41
+   _old_value; \
42
+})
43
+
44
+#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
45
+#define spa_steal_fd(fd) spa_exchange((fd), -1)
46
+
47
+/* ========================================================================== */
48
+
49
+#include <stdlib.h>
50
+
51
+#define spa_clear_ptr(ptr, destructor) \
52
+__extension__ ({ \
53
+   __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \
54
+   if (_old_value) \
55
+       destructor(_old_value); \
56
+   (void) 0; \
57
+})
58
+
59
+static inline void _spa_autofree_cleanup_func(void *p)
60
+{
61
+   free(*(void **) p);
62
+}
63
+#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func)
64
+
65
+/* ========================================================================== */
66
+
67
+#include <unistd.h>
68
+
69
+#define spa_clear_fd(fd) \
70
+__extension__ ({ \
71
+   int _old_value = spa_steal_fd(fd), _res = 0; \
72
+   if (_old_value >= 0) \
73
+       _res = close(_old_value); \
74
+   _res; \
75
+})
76
+
77
+static inline void _spa_autoclose_cleanup_func(int *fd)
78
+{
79
+   spa_clear_fd(*fd);
80
+}
81
+#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
82
+
83
+/* ========================================================================== */
84
+
85
+#include <stdio.h>
86
+
87
+SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, {
88
+   spa_clear_ptr(*thing, fclose);
89
+})
90
+
91
+/* ========================================================================== */
92
+
93
+#include <dirent.h>
94
+
95
+SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, {
96
+   spa_clear_ptr(*thing, closedir);
97
+})
98
+
99
+#endif /* SPA_UTILS_CLEANUP_H */
100
pipewire-0.3.74.tar.gz/spa/include/spa/utils/ratelimit.h Added
45
 
1
@@ -0,0 +1,43 @@
2
+/* Ratelimit */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#ifndef SPA_RATELIMIT_H
7
+#define SPA_RATELIMIT_H
8
+
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+
13
+#include <inttypes.h>
14
+#include <stddef.h>
15
+
16
+struct spa_ratelimit {
17
+   uint64_t interval;
18
+   uint64_t begin;
19
+   unsigned burst;
20
+   unsigned n_printed;
21
+   unsigned n_missed;
22
+};
23
+
24
+static inline int spa_ratelimit_test(struct spa_ratelimit *r, uint64_t now)
25
+{
26
+   unsigned missed = 0;
27
+   if (r->begin + r->interval < now) {
28
+       missed = r->n_missed;
29
+       r->begin = now;
30
+       r->n_printed = 0;
31
+       r->n_missed = 0;
32
+   } else if (r->n_printed >= r->burst) {
33
+       r->n_missed++;
34
+       return -1;
35
+   }
36
+   r->n_printed++;
37
+   return missed;
38
+}
39
+
40
+#ifdef __cplusplus
41
+} /* extern "C" */
42
+#endif
43
+
44
+#endif /* SPA_RATELIMIT_H */
45
pipewire-0.3.72.tar.gz/spa/include/spa/utils/ringbuffer.h -> pipewire-0.3.74.tar.gz/spa/include/spa/utils/ringbuffer.h Changed
19
 
1
@@ -85,7 +85,7 @@
2
  * \param len number of bytes to read
3
  */
4
 static inline void
5
-spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf,
6
+spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf SPA_UNUSED,
7
             const void *buffer, uint32_t size,
8
             uint32_t offset, void *data, uint32_t len)
9
 {
10
@@ -135,7 +135,7 @@
11
  * \param len number of bytes to write
12
  */
13
 static inline void
14
-spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf,
15
+spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf SPA_UNUSED,
16
              void *buffer, uint32_t size,
17
              uint32_t offset, const void *data, uint32_t len)
18
 {
19
pipewire-0.3.72.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c Changed
50
 
1
@@ -991,6 +991,40 @@
2
     }
3
 }
4
 
5
+static void ucm_add_port_props(
6
+       pa_device_port *port,
7
+       bool is_sink)
8
+{
9
+    const char *icon;
10
+
11
+    if (is_sink) {
12
+        switch (port->type) {
13
+            case PA_DEVICE_PORT_TYPE_HEADPHONES:
14
+                icon = "audio-headphones";
15
+                break;
16
+            case PA_DEVICE_PORT_TYPE_HDMI:
17
+                icon = "video-display";
18
+                break;
19
+            case PA_DEVICE_PORT_TYPE_SPEAKER:
20
+            default:
21
+                icon = "audio-speakers";
22
+                break;
23
+        }
24
+    } else {
25
+        switch (port->type) {
26
+            case PA_DEVICE_PORT_TYPE_HEADSET:
27
+                icon = "audio-headset";
28
+                break;
29
+            case PA_DEVICE_PORT_TYPE_MIC:
30
+            default:
31
+                icon = "audio-input-microphone";
32
+                break;
33
+        }
34
+    }
35
+
36
+    pa_proplist_sets(port->proplist, "device.icon_name", icon);
37
+}
38
+
39
 static void ucm_add_port_combination(
40
         pa_hashmap *hash,
41
         pa_alsa_ucm_mapping_context *context,
42
@@ -1097,6 +1131,7 @@
43
 
44
         pa_hashmap_put(ports, port->name, port);
45
         pa_log_debug("Add port %s: %s", port->name, port->description);
46
+        ucm_add_port_props(port, is_sink);
47
 
48
         if (num == 1) {
49
             /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
50
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
202
 
1
@@ -128,6 +128,8 @@
2
        state->props.use_chmap = spa_atob(s);
3
    } else if (spa_streq(k, "api.alsa.multi-rate")) {
4
        state->multi_rate = spa_atob(s);
5
+   } else if (spa_streq(k, "api.alsa.htimestamp")) {
6
+       state->htimestamp = spa_atob(s);
7
    } else if (spa_streq(k, "latency.internal.rate")) {
8
        state->process_latency.rate = atoi(s);
9
    } else if (spa_streq(k, "latency.internal.ns")) {
10
@@ -310,13 +312,21 @@
11
    case 14:
12
        param = spa_pod_builder_add_object(b,
13
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
14
+           SPA_PROP_INFO_name, SPA_POD_String("api.alsa.htimestamp"),
15
+           SPA_PROP_INFO_description, SPA_POD_String("Use hires timestamps"),
16
+           SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(state->htimestamp),
17
+           SPA_PROP_INFO_params, SPA_POD_Bool(true));
18
+       break;
19
+   case 15:
20
+       param = spa_pod_builder_add_object(b,
21
+           SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
22
            SPA_PROP_INFO_name, SPA_POD_String("latency.internal.rate"),
23
            SPA_PROP_INFO_description, SPA_POD_String("Internal latency in samples"),
24
            SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(state->process_latency.rate,
25
                0, 65536),
26
            SPA_PROP_INFO_params, SPA_POD_Bool(true));
27
        break;
28
-   case 15:
29
+   case 16:
30
        param = spa_pod_builder_add_object(b,
31
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
32
            SPA_PROP_INFO_name, SPA_POD_String("latency.internal.ns"),
33
@@ -325,7 +335,7 @@
34
                0LL, 2 * SPA_NSEC_PER_SEC),
35
            SPA_PROP_INFO_params, SPA_POD_Bool(true));
36
        break;
37
-   case 16:
38
+   case 17:
39
        param = spa_pod_builder_add_object(b,
40
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
41
            SPA_PROP_INFO_name, SPA_POD_String("clock.name"),
42
@@ -394,6 +404,9 @@
43
    spa_pod_builder_string(b, "api.alsa.multi-rate");
44
    spa_pod_builder_bool(b, state->multi_rate);
45
 
46
+   spa_pod_builder_string(b, "api.alsa.htimestamp");
47
+   spa_pod_builder_bool(b, state->htimestamp);
48
+
49
    spa_pod_builder_string(b, "latency.internal.rate");
50
    spa_pod_builder_int(b, state->process_latency.rate);
51
 
52
@@ -490,6 +503,7 @@
53
    snd_config_update_free_global();
54
 
55
    state->multi_rate = true;
56
+   state->htimestamp = true;
57
    for (i = 0; info && i < info->n_items; i++) {
58
        const char *k = info->itemsi.key;
59
        const char *s = info->itemsi.value;
60
@@ -1957,7 +1971,6 @@
61
    return do_start(state);
62
 }
63
 
64
-#if 0
65
 static int get_avail(struct state *state, uint64_t current_time, snd_pcm_uframes_t *delay)
66
 {
67
    int res, missed;
68
@@ -1967,7 +1980,7 @@
69
        if ((res = alsa_recover(state, avail)) < 0)
70
            return res;
71
        if ((avail = snd_pcm_avail(state->hndl)) < 0) {
72
-           if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) {
73
+           if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
74
                spa_log_warn(state->log, "%s: (%d missed) snd_pcm_avail after recover: %s",
75
                        state->props.device, missed, snd_strerror(avail));
76
            }
77
@@ -1977,48 +1990,50 @@
78
        state->alsa_recovering = false;
79
    }
80
    *delay = avail;
81
-   return avail;
82
-}
83
 
84
-#else
85
-static int get_avail(struct state *state, uint64_t current_time, snd_pcm_uframes_t *delay)
86
-{
87
-   int res, missed;
88
-   snd_pcm_uframes_t avail;
89
-   snd_htimestamp_t tstamp;
90
-   uint64_t then;
91
+   if (state->htimestamp) {
92
+       snd_pcm_uframes_t havail;
93
+       snd_htimestamp_t tstamp;
94
+       uint64_t then;
95
 
96
-   avail = snd_pcm_avail(state->hndl);
97
-   if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) {
98
-       if ((res = alsa_recover(state, res)) < 0)
99
-           return res;
100
-       if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) {
101
-           if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) {
102
+       if ((res = snd_pcm_htimestamp(state->hndl, &havail, &tstamp)) < 0) {
103
+           if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
104
                spa_log_warn(state->log, "%s: (%d missed) snd_pcm_htimestamp error: %s",
105
                    state->props.device, missed, snd_strerror(res));
106
            }
107
-           avail = state->threshold * 2;
108
+           return avail;
109
        }
110
-   } else {
111
-       state->alsa_recovering = false;
112
-   }
113
-   *delay = avail;
114
-
115
-   if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) {
116
-       int64_t diff;
117
+       avail = havail;
118
+       *delay = havail;
119
+       if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) {
120
+           int64_t diff;
121
 
122
-       if (then < current_time)
123
-           diff = ((int64_t)(current_time - then)) * state->rate / SPA_NSEC_PER_SEC;
124
-       else
125
-           diff = -((int64_t)(then - current_time)) * state->rate / SPA_NSEC_PER_SEC;
126
+           if (then < current_time)
127
+               diff = ((int64_t)(current_time - then)) * state->rate / SPA_NSEC_PER_SEC;
128
+           else
129
+               diff = -((int64_t)(then - current_time)) * state->rate / SPA_NSEC_PER_SEC;
130
 
131
-       spa_log_trace_fp(state->log, "%"PRIu64" %"PRIu64" %"PRIi64, current_time, then, diff);
132
+           spa_log_trace_fp(state->log, "%"PRIu64" %"PRIu64" %"PRIi64, current_time, then, diff);
133
 
134
-       *delay += diff;
135
+           if (SPA_ABS(diff) < state->threshold * 3) {
136
+               *delay += SPA_CLAMP(diff, -((int64_t)state->threshold), (int64_t)state->threshold);
137
+               state->htimestamp_error = 0;
138
+           } else {
139
+               if (++state->htimestamp_error > MAX_HTIMESTAMP_ERROR) {
140
+                   spa_log_error(state->log, "%s: wrong htimestamps from driver, disabling",
141
+                       state->props.device);
142
+                   state->htimestamp_error = 0;
143
+                   state->htimestamp = false;
144
+               }
145
+               else if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
146
+                   spa_log_warn(state->log, "%s: (%d missed) impossible htimestamp diff:%"PRIi64,
147
+                       state->props.device, missed, diff);
148
+               }
149
+           }
150
+       }
151
    }
152
-   return SPA_MIN(avail, state->buffer_frames);
153
+   return avail;
154
 }
155
-#endif
156
 
157
 static int get_status(struct state *state, uint64_t current_time, snd_pcm_uframes_t *avail,
158
        snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target)
159
@@ -2238,7 +2253,7 @@
160
            else
161
                lev = SPA_LOG_LEVEL_INFO;
162
 
163
-           if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) {
164
+           if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
165
                spa_log_lev(state->log, lev, "%s: follower avail:%lu delay:%ld "
166
                        "target:%ld thr:%u, resync (%d missed)",
167
                        state->props.device, avail, delay,
168
@@ -2263,6 +2278,7 @@
169
        if (SPA_UNLIKELY((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0)) {
170
            spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s",
171
                    state->props.device, snd_strerror(res));
172
+           alsa_recover(state, res);
173
            return res;
174
        }
175
        spa_log_trace_fp(state->log, "%p: begin offset:%ld avail:%ld threshold:%d",
176
@@ -2474,7 +2490,7 @@
177
            else
178
                lev = SPA_LOG_LEVEL_INFO;
179
 
180
-           if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) {
181
+           if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
182
                spa_log_lev(state->log, lev, "%s: follower delay:%ld target:%ld thr:%u, "
183
                        "resync (%d missed)", state->props.device, delay,
184
                        target, state->threshold, missed);
185
@@ -2500,6 +2516,7 @@
186
        if ((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &to_read)) < 0) {
187
            spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s",
188
                    state->props.device, snd_strerror(res));
189
+           alsa_recover(state, res);
190
            return res;
191
        }
192
        spa_log_trace_fp(state->log, "%p: begin offs:%ld frames:%ld to_read:%ld thres:%d", state,
193
@@ -2726,7 +2743,7 @@
194
    if (!state->disable_tsched &&
195
            (state->next_time > current_time + SPA_NSEC_PER_SEC ||
196
             current_time > state->next_time + SPA_NSEC_PER_SEC)) {
197
-       if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) {
198
+       if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) {
199
            spa_log_error(state->log, "%s: impossible timeout %lu %lu %lu %"
200
                    PRIu64" %"PRIu64" %"PRIi64" %d %"PRIi64" (%d missed)",
201
                    state->props.device, avail, delay, target,
202
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
80
 
1
@@ -21,6 +21,7 @@
2
 #include <spa/utils/list.h>
3
 #include <spa/utils/json.h>
4
 #include <spa/utils/dll.h>
5
+#include <spa/utils/ratelimit.h>
6
 
7
 #include <spa/node/node.h>
8
 #include <spa/node/utils.h>
9
@@ -40,6 +41,8 @@
10
 #define DEFAULT_CHANNELS   2u
11
 #define DEFAULT_USE_CHMAP  false
12
 
13
+#define MAX_HTIMESTAMP_ERROR   64
14
+
15
 struct props {
16
    char device64;
17
    char device_name128;
18
@@ -79,13 +82,6 @@
19
    uint32_t rate;
20
 };
21
 
22
-struct ratelimit {
23
-   uint64_t interval;
24
-   uint64_t begin;
25
-   unsigned burst;
26
-   unsigned n_printed, n_missed;
27
-};
28
-
29
 struct state {
30
    struct spa_handle handle;
31
    struct spa_node node;
32
@@ -95,7 +91,7 @@
33
    struct spa_loop *data_loop;
34
 
35
    FILE *log_file;
36
-   struct ratelimit rate_limit;
37
+   struct spa_ratelimit rate_limit;
38
 
39
    uint32_t card_index;
40
    struct card *card;
41
@@ -185,6 +181,7 @@
42
    uint32_t start_delay;
43
    uint32_t min_delay;
44
    uint32_t max_delay;
45
+   uint32_t htimestamp_error;
46
 
47
    uint32_t duration;
48
    unsigned int alsa_started:1;
49
@@ -201,6 +198,7 @@
50
    unsigned int is_iec958:1;
51
    unsigned int is_hdmi:1;
52
    unsigned int multi_rate:1;
53
+   unsigned int htimestamp:1;
54
 
55
    uint64_t iec958_codecs;
56
 
57
@@ -344,22 +342,6 @@
58
    return i;
59
 }
60
 
61
-static inline int ratelimit_test(struct ratelimit *r, uint64_t now)
62
-{
63
-   unsigned missed = 0;
64
-   if (r->begin + r->interval < now) {
65
-       missed = r->n_missed;
66
-       r->begin = now;
67
-       r->n_printed = 0;
68
-       r->n_missed = 0;
69
-   } else if (r->n_printed >= r->burst) {
70
-       r->n_missed++;
71
-       return -1;
72
-   }
73
-   r->n_printed++;
74
-   return missed;
75
-}
76
-
77
 /* This function is also as snd_pcm_channel_area_addr() since 1.2.6 which is not yet
78
  * in ubuntu and I can't figure out how to do the ALSA version check. */
79
 static inline void *channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
80
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-udev.c Changed
146
 
1
@@ -14,6 +14,7 @@
2
 #include <libudev.h>
3
 #include <alsa/asoundlib.h>
4
 
5
+#include <spa/utils/cleanup.h>
6
 #include <spa/utils/type.h>
7
 #include <spa/utils/keys.h>
8
 #include <spa/utils/names.h>
9
@@ -228,27 +229,24 @@
10
 
11
 static int check_device_pcm_class(const char *devname)
12
 {
13
-   FILE *f;
14
    char pathPATH_MAX;
15
    char buf16;
16
    size_t sz;
17
 
18
    /* Check device class */
19
-   spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class",
20
-           devname);
21
-   f = fopen(path, "re");
22
+   spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class", devname);
23
+
24
+   spa_autoptr(FILE) f = fopen(path, "re");
25
    if (f == NULL)
26
        return -errno;
27
    sz = fread(buf, 1, sizeof(buf) - 1, f);
28
    bufsz = '\0';
29
-   fclose(f);
30
    return spa_strstartswith(buf, "modem") ? -ENXIO : 0;
31
 }
32
 
33
 static int get_num_pcm_devices(unsigned int card_id)
34
 {
35
    char prefix32;
36
-   DIR *snd = NULL;
37
    struct dirent *entry;
38
    int num_dev = 0;
39
    int res;
40
@@ -257,7 +255,8 @@
41
 
42
    spa_scnprintf(prefix, sizeof(prefix), "pcmC%uD", card_id);
43
 
44
-   if ((snd = opendir("/dev/snd")) == NULL)
45
+   spa_autoptr(DIR) snd = opendir("/dev/snd");
46
+   if (snd == NULL)
47
        return -errno;
48
 
49
    while ((errno = 0, entry = readdir(snd)) != NULL) {
50
@@ -271,20 +270,13 @@
51
            ++num_dev;
52
        }
53
    }
54
-   if (errno != 0)
55
-       res = -errno;
56
-   else
57
-       res = num_dev;
58
 
59
-   closedir(snd);
60
-   return res;
61
+   return errno != 0 ? -errno : num_dev;
62
 }
63
 
64
 static int check_device_available(struct impl *this, struct device *device, int *num_pcm)
65
 {
66
    char pathPATH_MAX;
67
-   DIR *card = NULL, *pcm = NULL;
68
-   FILE *f;
69
    char buf16;
70
    size_t sz;
71
    struct dirent *entry, *entry_pcm;
72
@@ -314,7 +306,8 @@
73
 
74
    spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id);
75
 
76
-   if ((card = opendir(path)) == NULL)
77
+   spa_autoptr(DIR) card = opendir(path);
78
+   if (card == NULL)
79
        goto done;
80
 
81
    while ((errno = 0, entry = readdir(card)) != NULL) {
82
@@ -330,7 +323,9 @@
83
        /* Check busy status */
84
        spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s",
85
                (unsigned int)device->id, entry->d_name);
86
-       if ((pcm = opendir(path)) == NULL)
87
+
88
+       spa_autoptr(DIR) pcm = opendir(path);
89
+       if (pcm == NULL)
90
            goto done;
91
 
92
        while ((errno = 0, entry_pcm = readdir(pcm)) != NULL) {
93
@@ -341,12 +336,11 @@
94
            spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s/%s/status",
95
                    (unsigned int)device->id, entry->d_name, entry_pcm->d_name);
96
 
97
-           f = fopen(path, "re");
98
+           spa_autoptr(FILE) f = fopen(path, "re");
99
            if (f == NULL)
100
                goto done;
101
            sz = fread(buf, 1, 6, f);
102
            bufsz = '\0';
103
-           fclose(f);
104
 
105
            if (!spa_strstartswith(buf, "closed")) {
106
                spa_log_debug(this->log, "card %u pcm device %s busy",
107
@@ -359,9 +353,6 @@
108
        }
109
        if (errno != 0)
110
            goto done;
111
-
112
-       closedir(pcm);
113
-       pcm = NULL;
114
    }
115
    if (errno != 0)
116
        goto done;
117
@@ -371,10 +362,7 @@
118
        spa_log_info(this->log, "card %u: failed to find busy status (%s)",
119
                (unsigned int)device->id, spa_strerror(-errno));
120
    }
121
-   if (card)
122
-       closedir(card);
123
-   if (pcm)
124
-       closedir(pcm);
125
+
126
    return res;
127
 }
128
 
129
@@ -519,7 +507,7 @@
130
 static bool check_access(struct impl *this, struct device *device)
131
 {
132
    char path128, prefix32;
133
-   DIR *snd = NULL;
134
+   spa_autoptr(DIR) snd = NULL;
135
    struct dirent *entry;
136
    bool accessible = false;
137
 
138
@@ -544,7 +532,6 @@
139
                break;
140
            }
141
        }
142
-       closedir(snd);
143
    }
144
 
145
    if (accessible != device->accessible)
146
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
60
 
1
@@ -1893,11 +1893,13 @@
2
                SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_application),
3
                SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
4
        } else {
5
+           struct spa_pod_frame f1;
6
            uint32_t rate = this->io_position ?
7
                this->io_position->clock.target_rate.denom : DEFAULT_RATE;
8
 
9
-           *param = spa_pod_builder_add_object(builder,
10
-               SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
11
+           spa_pod_builder_push_object(builder, &f0,
12
+                   SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
13
+           spa_pod_builder_add(builder,
14
                SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
15
                SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
16
                SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(25,
17
@@ -1926,10 +1928,18 @@
18
                            SPA_AUDIO_FORMAT_U8,
19
                            SPA_AUDIO_FORMAT_ULAW,
20
                            SPA_AUDIO_FORMAT_ALAW),
21
-               SPA_FORMAT_AUDIO_rate,     SPA_POD_CHOICE_RANGE_Int(
22
-                   rate, 1, INT32_MAX),
23
+               0);
24
+           if (!this->props.resample_disabled) {
25
+               spa_pod_builder_add(builder,
26
+                   SPA_FORMAT_AUDIO_rate,     SPA_POD_CHOICE_RANGE_Int(
27
+                       rate, 1, INT32_MAX),
28
+                   0);
29
+           }
30
+           spa_pod_builder_add(builder,
31
                SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
32
-                   DEFAULT_CHANNELS, 1, SPA_AUDIO_MAX_CHANNELS));
33
+                   DEFAULT_CHANNELS, 1, SPA_AUDIO_MAX_CHANNELS),
34
+               0);
35
+           *param = spa_pod_builder_pop(builder, &f0);
36
        }
37
        break;
38
    default:
39
@@ -2205,7 +2215,7 @@
40
                return res;
41
            }
42
            if (info.info.raw.format == 0 ||
43
-               info.info.raw.rate == 0 ||
44
+               (!this->props.resample_disabled && info.info.raw.rate == 0) ||
45
                info.info.raw.channels == 0 ||
46
                info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) {
47
                spa_log_error(this->log, "invalid format:%d rate:%d channels:%d",
48
@@ -2288,8 +2298,9 @@
49
    struct buffer *b;
50
 
51
    if (spa_list_is_empty(&port->queue)) {
52
-       spa_log_trace_fp(this->log, "%p: out of buffers on port %d %d",
53
-           this, port->id, port->n_buffers);
54
+       if (port->n_buffers > 0)
55
+           spa_log_warn(this->log, "%p: out of buffers on port %d %d",
56
+               this, port->id, port->n_buffers);
57
        return NULL;
58
    }
59
 
60
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/crossover.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/crossover.c Changed
65
 
1
@@ -22,17 +22,16 @@
2
 
3
 void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples)
4
 {
5
-   float lx1 = lr4->x1;
6
-   float lx2 = lr4->x2;
7
-   float ly1 = lr4->y1;
8
-   float ly2 = lr4->y2;
9
-   float lz1 = lr4->z1;
10
-   float lz2 = lr4->z2;
11
-   float lb0 = lr4->bq.b0;
12
-   float lb1 = lr4->bq.b1;
13
-   float lb2 = lr4->bq.b2;
14
-   float la1 = lr4->bq.a1;
15
-   float la2 = lr4->bq.a2;
16
+   float x1 = lr4->x1;
17
+   float x2 = lr4->x2;
18
+   float y1 = lr4->y1;
19
+   float y2 = lr4->y2;
20
+   float b0 = lr4->bq.b0;
21
+   float b1 = lr4->bq.b1;
22
+   float b2 = lr4->bq.b2;
23
+   float a1 = lr4->bq.a1;
24
+   float a2 = lr4->bq.a2;
25
+   float x, y, z;
26
    int i;
27
 
28
    if (vol == 0.0f) {
29
@@ -47,24 +46,19 @@
30
    }
31
 
32
    for (i = 0; i < samples; i++) {
33
-       float x, y, z;
34
-       x = srci;
35
-       y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2;
36
-       z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2;
37
-       lx2 = lx1;
38
-       lx1 = x;
39
-       ly2 = ly1;
40
-       ly1 = y;
41
-       lz2 = lz1;
42
-       lz1 = z;
43
+       x  = srci;
44
+       y  = b0 * x          + x1;
45
+       x1 = b1 * x - a1 * y + x2;
46
+       x2 = b2 * x - a2 * y;
47
+       z  = b0 * y          + y1;
48
+       y1 = b1 * y - a1 * z + y2;
49
+       y2 = b2 * y - a2 * z;
50
        dsti = z * vol;
51
    }
52
 #define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
53
-   lr4->x1 = F(lx1);
54
-   lr4->x2 = F(lx2);
55
-   lr4->y1 = F(ly1);
56
-   lr4->y2 = F(ly2);
57
-   lr4->z1 = F(lz1);
58
-   lr4->z2 = F(lz2);
59
+   lr4->x1 = F(x1);
60
+   lr4->x2 = F(x2);
61
+   lr4->y1 = F(y1);
62
+   lr4->y2 = F(y2);
63
 #undef F
64
 }
65
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c Changed
38
 
1
@@ -132,7 +132,7 @@
2
    }
3
 }
4
 
5
-void
6
+static void
7
 conv_s24_to_f32d_1s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
8
        uint32_t n_channels, uint32_t n_samples)
9
 {
10
@@ -308,8 +308,7 @@
11
        conv_s24_to_f32d_1s_avx2(conv, &dsti, &s3*i, n_channels, n_samples);
12
 }
13
 
14
-
15
-void
16
+static void
17
 conv_s32_to_f32d_4s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
18
        uint32_t n_channels, uint32_t n_samples)
19
 {
20
@@ -375,7 +374,7 @@
21
    }
22
 }
23
 
24
-void
25
+static void
26
 conv_s32_to_f32d_2s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
27
        uint32_t n_channels, uint32_t n_samples)
28
 {
29
@@ -423,7 +422,7 @@
30
    }
31
 }
32
 
33
-void
34
+static void
35
 conv_s32_to_f32d_1s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
36
        uint32_t n_channels, uint32_t n_samples)
37
 {
38
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c Changed
11
 
1
@@ -315,8 +315,7 @@
2
        conv_s24_to_f32d_1s_sse2(conv, &dsti, &s3*i, n_channels, n_samples);
3
 }
4
 
5
-
6
-void
7
+static void
8
 conv_s32_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
9
        uint32_t n_channels, uint32_t n_samples)
10
 {
11
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/resample-peaks.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/resample-peaks.c Changed
31
 
1
@@ -39,13 +39,14 @@
2
            end = ((uint64_t) (o_count + 1)
3
                * r->i_rate) / r->o_rate;
4
            end = end > i_count ? end - i_count : 0;
5
-           chunk = SPA_MIN(end, *in_len);
6
+           chunk = SPA_MIN(end, *in_len - i);
7
 
8
-           m = peaks_abs_max(&pd->peaks, &si, chunk - i, m);
9
+           m = peaks_abs_max(&pd->peaks, &si, chunk, m);
10
 
11
            i += chunk;
12
+           i_count += chunk;
13
 
14
-           if (i == end) {
15
+           if (chunk == end) {
16
                do++ = m;
17
                m = 0.0f;
18
                o_count++;
19
@@ -56,9 +57,9 @@
20
    *out_len = o;
21
    *in_len = i;
22
    pd->o_count = o_count;
23
-   pd->i_count = i_count + i;
24
+   pd->i_count = i_count;
25
 
26
-   while (pd->i_count >= r->i_rate) {
27
+   while (pd->i_count >= r->i_rate && pd->o_count >= r->o_rate) {
28
        pd->i_count -= r->i_rate;
29
        pd->o_count -= r->o_rate;
30
    }
31
pipewire-0.3.72.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.74.tar.gz/spa/plugins/audiomixer/audiomixer.c Changed
13
 
1
@@ -786,8 +786,9 @@
2
 
3
    outb = dequeue_buffer(this, outport);
4
         if (SPA_UNLIKELY(outb == NULL)) {
5
-                spa_log_trace(this->log, "%p: out of buffers (%d)", this,
6
-               outport->n_buffers);
7
+       if (outport->n_buffers > 0)
8
+           spa_log_warn(this->log, "%p: out of buffers (%d)", this,
9
+                   outport->n_buffers);
10
                 return -EPIPE;
11
         }
12
 
13
pipewire-0.3.72.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.74.tar.gz/spa/plugins/audiomixer/mixer-dsp.c Changed
12
 
1
@@ -722,7 +722,9 @@
2
 
3
    outb = dequeue_buffer(this, outport);
4
    if (SPA_UNLIKELY(outb == NULL)) {
5
-       spa_log_trace(this->log, "%p: out of buffers", this);
6
+       if (outport->n_buffers > 0)
7
+           spa_log_warn(this->log, "%p: out of buffers (%d)", this,
8
+                   outport->n_buffers);
9
        return -EPIPE;
10
    }
11
 
12
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-native.c Changed
31
 
1
@@ -216,8 +216,10 @@
2
        return NULL;
3
 
4
    t = spa_bt_transport_create(backend->monitor, pathfd, sizeof(struct transport_data));
5
-   if (t == NULL)
6
-       goto finish;
7
+   if (t == NULL) {
8
+       free(pathfd);
9
+       return NULL;
10
+   }
11
    spa_bt_transport_set_implementation(t, &sco_transport_impl, t);
12
 
13
    t->device = rfcomm->device;
14
@@ -248,7 +250,6 @@
15
 
16
    spa_bt_transport_add_listener(t, &rfcomm->transport_listener, &transport_events, rfcomm);
17
 
18
-finish:
19
    return t;
20
 }
21
 
22
@@ -2707,7 +2708,7 @@
23
    }
24
 }
25
 
26
-void set_battery_level(unsigned int level, void *user_data)
27
+static void set_battery_level(unsigned int level, void *user_data)
28
 {
29
    struct impl *backend = user_data;
30
 
31
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/backend-ofono.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-ofono.c Changed
10
 
1
@@ -307,7 +307,7 @@
2
    .release = ofono_audio_release,
3
 };
4
 
5
-bool activate_transport(struct spa_bt_transport *t, const void *data)
6
+static bool activate_transport(struct spa_bt_transport *t, const void *data)
7
 {
8
    struct impl *backend = (void *)data;
9
    struct transport_data *td = t->user_data;
10
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
65
 
1
@@ -208,15 +208,15 @@
2
 static int device_start_timer(struct spa_bt_device *device);
3
 static int device_stop_timer(struct spa_bt_device *device);
4
 
5
+static void media_codec_switch_free(struct spa_bt_media_codec_switch *sw);
6
+
7
 // Working with BlueZ Battery Provider.
8
 // Developed using https://github.com/dgreid/adhd/commit/655b58f as an example of DBus calls.
9
 
10
 // Name of battery, formatted as /org/freedesktop/pipewire/battery/org/bluez/hciX/dev_XX_XX_XX_XX_XX_XX
11
 static char *battery_get_name(const char *device_path)
12
 {
13
-   char *path = malloc(strlen(PIPEWIRE_BATTERY_PROVIDER) + strlen(device_path) + 1);
14
-   sprintf(path, PIPEWIRE_BATTERY_PROVIDER "%s", device_path);
15
-   return path;
16
+   return spa_aprintf(PIPEWIRE_BATTERY_PROVIDER "%s", device_path);
17
 }
18
 
19
 // Unregister virtual battery of device
20
@@ -1287,10 +1287,6 @@
21
    return d;
22
 }
23
 
24
-static int device_stop_timer(struct spa_bt_device *device);
25
-
26
-static void media_codec_switch_free(struct spa_bt_media_codec_switch *sw);
27
-
28
 static void device_clear_sub(struct spa_bt_device *device)
29
 {
30
    battery_remove(device);
31
@@ -3269,7 +3265,6 @@
32
    struct spa_bt_monitor *monitor = transport->monitor;
33
    DBusMessage *m;
34
    DBusMessageIter it2;
35
-   DBusError err;
36
    const char *interface = BLUEZ_MEDIA_TRANSPORT_INTERFACE;
37
    const char *name = "Volume";
38
    int res = 0;
39
@@ -3298,8 +3293,6 @@
40
    dbus_message_iter_append_basic(&it1, DBUS_TYPE_UINT16, &value);
41
    dbus_message_iter_close_container(&it0, &it1);
42
 
43
-   dbus_error_init(&err);
44
-
45
    ret = dbus_connection_send_with_reply(monitor->conn, m, &transport->volume_call, -1);
46
    dbus_message_unref(m);
47
 
48
@@ -3513,7 +3506,6 @@
49
 {
50
    struct spa_bt_monitor *monitor = transport->monitor;
51
    DBusMessage *m;
52
-   DBusError err;
53
    dbus_bool_t ret;
54
    struct spa_bt_transport *t_linked;
55
 
56
@@ -3539,8 +3531,6 @@
57
    if (m == NULL)
58
        return -ENOMEM;
59
 
60
-   dbus_error_init(&err);
61
-
62
    ret = dbus_connection_send_with_reply(monitor->conn, m, &transport->acquire_call, -1);
63
    dbus_message_unref(m);
64
 
65
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/iso-io.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/iso-io.c Changed
10
 
1
@@ -308,7 +308,7 @@
2
    free(group);
3
 }
4
 
5
-struct stream *stream_create(struct spa_bt_transport *t, struct group *group)
6
+static struct stream *stream_create(struct spa_bt_transport *t, struct group *group)
7
 {
8
    struct stream *stream;
9
    void *codec_data = NULL;
10
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/media-source.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/media-source.c Changed
45
 
1
@@ -1342,6 +1342,9 @@
2
    spa_bt_decode_buffer_set_target_latency(&port->buffer, samples);
3
 }
4
 
5
+#define WARN_ONCE(cond, ...) \
6
+   if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } }
7
+
8
 static void process_buffering(struct impl *this)
9
 {
10
    struct port *port = &this->port;
11
@@ -1364,13 +1367,21 @@
12
        struct spa_data *datas;
13
        uint32_t data_size;
14
 
15
+       buffer = spa_list_first(&port->free, struct buffer, link);
16
+       datas = buffer->buf->datas;
17
+
18
        data_size = samples * port->frame_size;
19
 
20
+       WARN_ONCE(datas0.maxsize < data_size && !this->following,
21
+               this->log, "source buffer too small (%u < %u)",
22
+               datas0.maxsize, data_size);
23
+
24
+       data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas0.maxsize, port->frame_size));
25
+
26
        avail = SPA_MIN(avail, data_size);
27
 
28
        spa_bt_decode_buffer_read(&port->buffer, avail);
29
 
30
-       buffer = spa_list_first(&port->free, struct buffer, link);
31
        spa_list_remove(&buffer->link);
32
 
33
        spa_log_trace(this->log, "dequeue %d", buffer->id);
34
@@ -1381,10 +1392,6 @@
35
            buffer->h->dts_offset = 0;
36
        }
37
 
38
-       datas = buffer->buf->datas;
39
-
40
-       spa_assert(datas0.maxsize >= data_size);
41
-
42
        datas0.chunk->offset = 0;
43
        datas0.chunk->size = data_size;
44
        datas0.chunk->stride = port->frame_size;
45
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/meson.build Changed
27
 
1
@@ -118,16 +118,14 @@
2
 
3
 if ldac_dep.found()
4
   ldac_args = codec_args
5
-  ldac_dep =  ldac_dep 
6
   if ldac_abr_dep.found()
7
     ldac_args +=  '-DENABLE_LDAC_ABR' 
8
-    ldac_dep += ldac_abr_dep
9
   endif
10
   bluez_codec_ldac = shared_library('spa-codec-bluez5-ldac',
11
      'a2dp-codec-ldac.c', 'media-codecs.c' ,
12
     include_directories :  configinc ,
13
     c_args : ldac_args,
14
-    dependencies :  spa_dep, ldac_dep ,
15
+    dependencies :  spa_dep, ldac_dep, ldac_abr_dep ,
16
     install : true,
17
     install_dir : spa_plugindir / 'bluez5')
18
 endif
19
@@ -144,7 +142,6 @@
20
 
21
 if get_option('bluez5-codec-opus').allowed() and opus_dep.found()
22
   opus_args = codec_args
23
-  opus_dep =  opus_dep 
24
   bluez_codec_opus = shared_library('spa-codec-bluez5-opus',
25
      'a2dp-codec-opus.c', 'media-codecs.c' ,
26
     include_directories :  configinc ,
27
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/midi-enum.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/midi-enum.c Changed
10
 
1
@@ -202,7 +202,7 @@
2
    return 0;
3
 }
4
 
5
-Bluez5GattDescriptor1 *find_dsc(struct impl *impl, MidiEnumCharacteristicProxy *chr)
6
+static Bluez5GattDescriptor1 *find_dsc(struct impl *impl, MidiEnumCharacteristicProxy *chr)
7
 {
8
    const char *path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(chr));
9
    Bluez5GattDescriptor1 *found = NULL;;
10
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/modemmanager.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/modemmanager.c Changed
10
 
1
@@ -771,7 +771,7 @@
2
    return this->modem.path != NULL;
3
 }
4
 
5
-unsigned int mm_supported_features()
6
+unsigned int mm_supported_features(void)
7
 {
8
    return SPA_BT_HFP_AG_FEATURE_REJECT_CALL | SPA_BT_HFP_AG_FEATURE_ENHANCED_CALL_STATUS;
9
 }
10
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/modemmanager.h -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/modemmanager.h Changed
81
 
1
@@ -71,7 +71,7 @@
2
                   const struct mm_ops *ops, void *user_data);
3
 void mm_unregister(void *data);
4
 bool mm_is_available(void *modemmanager);
5
-unsigned int mm_supported_features();
6
+unsigned int mm_supported_features(void);
7
 bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error);
8
 bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error);
9
 bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error);
10
@@ -79,60 +79,60 @@
11
 const char *mm_get_incoming_call_number(void *modemmanager);
12
 struct spa_list *mm_get_calls(void *modemmanager);
13
 #else
14
-void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info,
15
+static inline void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info,
16
                   const struct mm_ops *ops, void *user_data)
17
 {
18
    return NULL;
19
 }
20
 
21
-void mm_unregister(void *data)
22
+static inline void mm_unregister(void *data)
23
 {
24
 }
25
 
26
-bool mm_is_available(void *modemmanager)
27
+static inline bool mm_is_available(void *modemmanager)
28
 {
29
    return false;
30
 }
31
 
32
-unsigned int mm_supported_features(void)
33
+static inline unsigned int mm_supported_features(void)
34
 {
35
    return 0;
36
 }
37
 
38
-bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error)
39
+static inline bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error)
40
 {
41
    if (error)
42
        *error = CMEE_OPERATION_NOT_SUPPORTED;
43
    return false;
44
 }
45
 
46
-bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error)
47
+static inline bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error)
48
 {
49
    if (error)
50
        *error = CMEE_OPERATION_NOT_SUPPORTED;
51
    return false;
52
 }
53
 
54
-bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error)
55
+static inline bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error)
56
 {
57
    if (error)
58
        *error = CMEE_OPERATION_NOT_SUPPORTED;
59
    return false;
60
 }
61
 
62
-bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
63
+static inline bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
64
 {
65
    if (error)
66
        *error = CMEE_OPERATION_NOT_SUPPORTED;
67
    return false;
68
 }
69
 
70
-const char *mm_get_incoming_call_number(void *modemmanager)
71
+static inline const char *mm_get_incoming_call_number(void *modemmanager)
72
 {
73
    return NULL;
74
 }
75
 
76
-struct spa_list *mm_get_calls(void *modemmanager)
77
+static inline struct spa_list *mm_get_calls(void *modemmanager)
78
 {
79
    return NULL;
80
 }
81
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/sco-source.c Changed
42
 
1
@@ -1298,6 +1298,9 @@
2
    return samples;
3
 }
4
 
5
+#define WARN_ONCE(cond, ...) \
6
+   if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } }
7
+
8
 static void process_buffering(struct impl *this)
9
 {
10
    struct port *port = &this->port;
11
@@ -1318,21 +1321,25 @@
12
        struct spa_data *datas;
13
        uint32_t data_size;
14
 
15
+       buffer = spa_list_first(&port->free, struct buffer, link);
16
+       datas = buffer->buf->datas;
17
+
18
        data_size = samples * port->frame_size;
19
 
20
+       WARN_ONCE(datas0.maxsize < data_size && !this->following,
21
+               this->log, "source buffer too small (%u < %u)",
22
+               datas0.maxsize, data_size);
23
+
24
+       data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas0.maxsize, port->frame_size));
25
+
26
        avail = SPA_MIN(avail, data_size);
27
 
28
        spa_bt_decode_buffer_read(&port->buffer, avail);
29
 
30
-       buffer = spa_list_first(&port->free, struct buffer, link);
31
        spa_list_remove(&buffer->link);
32
 
33
        spa_log_trace(this->log, "dequeue %d", buffer->id);
34
 
35
-       datas = buffer->buf->datas;
36
-
37
-       spa_assert(datas0.maxsize >= data_size);
38
-
39
        datas0.chunk->offset = 0;
40
        datas0.chunk->size = data_size;
41
        datas0.chunk->stride = port->frame_size;
42
pipewire-0.3.72.tar.gz/spa/plugins/control/mixer.c -> pipewire-0.3.74.tar.gz/spa/plugins/control/mixer.c Changed
12
 
1
@@ -623,7 +623,9 @@
2
 
3
    /* get output buffer */
4
    if ((outb = dequeue_buffer(this, outport)) == NULL) {
5
-                spa_log_trace(this->log, NAME " %p: out of buffers", this);
6
+       if (outport->n_buffers > 0)
7
+                   spa_log_warn(this->log, NAME " %p: out of buffers (%d)",
8
+                   this, outport->n_buffers);
9
                 return -EPIPE;
10
         }
11
 
12
pipewire-0.3.72.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.74.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp Changed
12
 
1
@@ -53,9 +53,7 @@
2
    if (impl->config)
3
        return;
4
 
5
-   StreamRoles roles;
6
-   roles.push_back(StreamRole::VideoRecording);
7
-   impl->config = impl->camera->generateConfiguration(roles);
8
+   impl->config = impl->camera->generateConfiguration({ StreamRole::VideoRecording });
9
 }
10
 
11
 static int spa_libcamera_buffer_recycle(struct impl *impl, struct port *port, uint32_t buffer_id)
12
pipewire-0.3.72.tar.gz/spa/plugins/support/cpu.c -> pipewire-0.3.74.tar.gz/spa/plugins/support/cpu.c Changed
10
 
1
@@ -39,7 +39,7 @@
2
    uint32_t vm_type;
3
 };
4
 
5
-char *spa_cpu_read_file(const char *name, char *buffer, size_t len)
6
+static char *spa_cpu_read_file(const char *name, char *buffer, size_t len)
7
 {
8
    int n, fd;
9
 
10
pipewire-0.3.72.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-0.3.74.tar.gz/spa/plugins/v4l2/v4l2-utils.c Changed
19
 
1
@@ -627,7 +627,7 @@
2
        }
3
          do_frmsize:
4
        if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMESIZES, &port->frmsize)) < 0) {
5
-           if (errno == EINVAL)
6
+           if (errno == EINVAL || errno == ENOTTY)
7
                goto next_fmtdesc;
8
 
9
            res = -errno;
10
@@ -745,7 +745,7 @@
11
    while (true) {
12
        if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMEINTERVALS, &port->frmival)) < 0) {
13
            res = -errno;
14
-           if (errno == EINVAL) {
15
+           if (errno == EINVAL || errno == ENOTTY) {
16
                port->frmsize.index++;
17
                port->next_frmsize = true;
18
                if (port->frmival.index == 0)
19
pipewire-0.3.72.tar.gz/src/gst/gstpipewiredeviceprovider.c -> pipewire-0.3.74.tar.gz/src/gst/gstpipewiredeviceprovider.c Changed
13
 
1
@@ -665,9 +665,11 @@
2
 {
3
   GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider);
4
 
5
+  pw_thread_loop_lock (self->core->loop);
6
   GST_DEBUG_OBJECT (self, "stopping provider");
7
 
8
   g_clear_pointer ((struct pw_proxy**)&self->registry, pw_proxy_destroy);
9
+  pw_thread_loop_unlock (self->core->loop);
10
   g_clear_pointer (&self->core, gst_pipewire_core_release);
11
 }
12
 
13
pipewire-0.3.72.tar.gz/src/modules/flatpak-utils.h -> pipewire-0.3.74.tar.gz/src/modules/flatpak-utils.h Changed
62
 
1
@@ -5,6 +5,8 @@
2
 #ifndef FLATPAK_UTILS_H
3
 #define FLATPAK_UTILS_H
4
 
5
+#include "config.h"
6
+
7
 #include <stdio.h>
8
 #include <string.h>
9
 #include <fcntl.h>
10
@@ -20,6 +22,7 @@
11
 #include <glib.h>
12
 #endif
13
 
14
+#include <spa/utils/cleanup.h>
15
 #include <spa/utils/result.h>
16
 #include <pipewire/log.h>
17
 
18
@@ -60,8 +63,8 @@
19
 {
20
 #if defined(__linux__)
21
    char root_path2048;
22
-   int root_fd, info_fd, res;
23
    struct stat stat_buf;
24
+   int res;
25
 
26
    if (app_id)
27
        *app_id = NULL;
28
@@ -69,8 +72,9 @@
29
        *devices = NULL;
30
 
31
    snprintf(root_path, sizeof(root_path), "/proc/%d/root", (int)pid);
32
-   root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
33
-   if (root_fd == -1) {
34
+
35
+   spa_autoclose int root_fd = openat(AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
36
+   if (root_fd < 0) {
37
        res = -errno;
38
        if (res == -EACCES) {
39
            struct statfs buf;
40
@@ -88,9 +92,9 @@
41
        pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res));
42
        return res;
43
    }
44
-   info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
45
-   close (root_fd);
46
-   if (info_fd == -1) {
47
+
48
+   spa_autoclose int info_fd = openat(root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
49
+   if (info_fd < 0) {
50
        if (errno == ENOENT) {
51
            pw_log_debug("no .flatpak-info, client on the host");
52
            /* No file => on the host */
53
@@ -126,7 +130,7 @@
54
            pw_log_error("PID %d .flatpak-info parsing failed: %s",
55
                    (int)pid, spa_strerror(res));
56
    }
57
-   close(info_fd);
58
+
59
    return 1;
60
 #else
61
    return 0;
62
pipewire-0.3.72.tar.gz/src/modules/meson.build -> pipewire-0.3.74.tar.gz/src/modules/meson.build Changed
101
 
1
@@ -11,6 +11,7 @@
2
   'module-client-node.c',
3
   'module-combine-stream.c',
4
   'module-echo-cancel.c',
5
+  'module-example-filter.c',
6
   'module-example-sink.c',
7
   'module-example-source.c',
8
   'module-fallback-sink.c',
9
@@ -116,21 +117,12 @@
10
   'module-filter-chain/biquad.c',
11
   'module-filter-chain/ladspa_plugin.c',
12
   'module-filter-chain/builtin_plugin.c',
13
-  'module-filter-chain/sofa_plugin.c',
14
   'module-filter-chain/convolver.c'
15
 
16
 filter_chain_dependencies = 
17
-  mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep, libmysofa_dep
18
+  mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep
19
 
20
 
21
-if lilv_lib.found()
22
-  filter_chain_sources += 
23
-    'module-filter-chain/lv2_plugin.c'
24
-  
25
-  filter_chain_dependencies +=  lilv_lib 
26
-endif
27
-
28
-
29
 pipewire_module_filter_chain = shared_library('pipewire-module-filter-chain',
30
   filter_chain_sources,
31
   include_directories : configinc,
32
@@ -141,9 +133,30 @@
33
   dependencies : filter_chain_dependencies,
34
 )
35
 
36
-pipewire_module_echo_cancel_sources = 
37
-  'module-echo-cancel.c',
38
-
39
+if libmysofa_dep.found()
40
+pipewire_module_filter_chain_sofa = shared_library('pipewire-module-filter-chain-sofa',
41
+   'module-filter-chain/sofa_plugin.c',
42
+    'module-filter-chain/convolver.c' ,
43
+  include_directories : configinc,
44
+  install : true,
45
+  install_dir : modules_install_dir,
46
+  install_rpath: modules_install_dir,
47
+  link_with : simd_dependencies,
48
+  dependencies :  filter_chain_dependencies, libmysofa_dep 
49
+)
50
+endif
51
+
52
+if lilv_lib.found()
53
+pipewire_module_filter_chain_lv2 = shared_library('pipewire-module-filter-chain-lv2',
54
+   'module-filter-chain/lv2_plugin.c' ,
55
+  include_directories : configinc,
56
+  install : true,
57
+  install_dir : modules_install_dir,
58
+  install_rpath: modules_install_dir,
59
+  dependencies :  filter_chain_dependencies, lilv_lib 
60
+)
61
+endif
62
+
63
 
64
 pipewire_module_combine_stream = shared_library('pipewire-module-combine-stream',
65
    'module-combine-stream.c' ,
66
@@ -155,7 +168,7 @@
67
 )
68
 
69
 pipewire_module_echo_cancel = shared_library('pipewire-module-echo-cancel',
70
-  pipewire_module_echo_cancel_sources,
71
+   'module-echo-cancel.c' ,
72
   include_directories : configinc,
73
   install : true,
74
   install_dir : modules_install_dir,
75
@@ -203,7 +216,8 @@
76
 summary({'ffado-driver': build_module_ffado_driver}, bool_yn: true, section: 'Optional Modules')
77
 
78
 opus_custom_h = cc.has_header('opus/opus_custom.h', dependencies: opus_dep)
79
-if opus_custom_h
80
+# One would imagine that opus_dep is a requirement but for some reason it's not, so we need to manually check that
81
+if opus_dep.found() and opus_custom_h
82
   opus_custom_dep = declare_dependency(compile_args: '-DHAVE_OPUS_CUSTOM', dependencies: opus_dep)
83
 else
84
   opus_custom_dep = dependency('', required: false)
85
@@ -438,6 +452,15 @@
86
   dependencies : pipewire_module_protocol_deps,
87
 )
88
 
89
+pipewire_module_example_filter = shared_library('pipewire-module-example-filter',
90
+   'module-example-filter.c' ,
91
+  include_directories : configinc,
92
+  install : false,
93
+  install_dir : modules_install_dir,
94
+  install_rpath: modules_install_dir,
95
+  dependencies : spa_dep, mathlib, dl_lib, pipewire_dep,
96
+)
97
+
98
 pipewire_module_example_sink = shared_library('pipewire-module-example-sink',
99
    'module-example-sink.c' ,
100
   include_directories : configinc,
101
pipewire-0.3.72.tar.gz/src/modules/module-avb/acmp.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/acmp.h Changed
8
 
1
@@ -75,5 +75,6 @@
2
 #define AVB_PACKET_ACMP_GET_STATUS(p)          AVB_PACKET_GET_SUB2(&(p)->hdr)
3
 
4
 struct avb_acmp *avb_acmp_register(struct server *server);
5
+void avb_acmp_unregister(struct avb_acmp *acmp);
6
 
7
 #endif /* AVB_ACMP_H */
8
pipewire-0.3.72.tar.gz/src/modules/module-avb/adp.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/adp.h Changed
8
 
1
@@ -81,5 +81,6 @@
2
 #define AVB_PACKET_ADP_GET_VALID_TIME(p)       AVB_PACKET_GET_SUB2(&(p)->hdr)
3
 
4
 struct avb_adp *avb_adp_register(struct server *server);
5
+void avb_adp_unregister(struct avb_adp *adp);
6
 
7
 #endif /* AVB_ADP_H */
8
pipewire-0.3.72.tar.gz/src/modules/module-avb/avb.c -> pipewire-0.3.74.tar.gz/src/modules/module-avb/avb.c Changed
9
 
1
@@ -2,6 +2,7 @@
2
 /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */
3
 /* SPDX-License-Identifier: MIT */
4
 
5
+#include "avb.h"
6
 #include "internal.h"
7
 
8
 #include <spa/support/cpu.h>
9
pipewire-0.3.72.tar.gz/src/modules/module-avb/avb.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/avb.h Changed
10
 
1
@@ -5,6 +5,8 @@
2
 #ifndef PIPEWIRE_AVB_H
3
 #define PIPEWIRE_AVB_H
4
 
5
+#include <stddef.h>
6
+
7
 #ifdef __cplusplus
8
 extern "C" {
9
 #endif
10
pipewire-0.3.72.tar.gz/src/modules/module-avb/descriptors.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/descriptors.h Changed
15
 
1
@@ -2,11 +2,12 @@
2
 /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */
3
 /* SPDX-License-Identifier: MIT */
4
 
5
+#include "adp.h"
6
 #include "aecp-aem.h"
7
 #include "aecp-aem-descriptors.h"
8
 #include "internal.h"
9
 
10
-void init_descriptors(struct server *server)
11
+static inline void init_descriptors(struct server *server)
12
 {
13
    server_add_descriptor(server, AVB_AEM_DESC_STRINGS, 0,
14
            sizeof(struct avb_aem_desc_strings),
15
pipewire-0.3.72.tar.gz/src/modules/module-client-device/client-device.h -> pipewire-0.3.74.tar.gz/src/modules/module-client-device/client-device.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
 #define CLIENT_DEVICE_USAGE    ""PW_KEY_DEVICE_NAME"=<string>"
4
 
5
-struct pw_device *
6
+struct pw_impl_device *
7
 pw_client_device_new(struct pw_resource *resource,
8
           struct pw_properties *properties);
9
 
10
pipewire-0.3.72.tar.gz/src/modules/module-client-device/resource-device.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-device/resource-device.c Changed
10
 
1
@@ -17,6 +17,8 @@
2
 
3
 #include <pipewire/impl.h>
4
 
5
+#include "client-device.h"
6
+
7
 struct impl {
8
    struct pw_context *context;
9
    struct pw_impl_device *device;
10
pipewire-0.3.72.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/client-node.c Changed
243
 
1
@@ -86,6 +86,7 @@
2
    struct pw_impl_client_node this;
3
 
4
    struct pw_context *context;
5
+   struct pw_mempool *context_pool;
6
 
7
    struct spa_node node;
8
 
9
@@ -98,6 +99,7 @@
10
 
11
    struct pw_resource *resource;
12
    struct pw_impl_client *client;
13
+   struct pw_mempool *client_pool;
14
 
15
    struct spa_source data_source;
16
 
17
@@ -217,14 +219,12 @@
18
    mix->n_buffers = 0;
19
 }
20
 
21
-static struct mix *ensure_mix(struct impl *impl, struct port *p, uint32_t mix_id)
22
+static struct mix *create_mix(struct impl *impl, struct port *p, uint32_t mix_id)
23
 {
24
    struct mix *mix;
25
 
26
-   if ((mix = find_mix(p, mix_id)) == NULL)
27
+   if ((mix = find_mix(p, mix_id)) == NULL || mix->valid)
28
        return NULL;
29
-   if (mix->valid)
30
-       return mix;
31
    mix_init(mix, p, mix_id);
32
    return mix;
33
 }
34
@@ -238,7 +238,7 @@
35
        struct pw_memblock *m;
36
 
37
        id = SPA_PTR_TO_UINT32(d->data);
38
-       m = pw_mempool_find_id(impl->client->pool, id);
39
+       m = pw_mempool_find_id(impl->client_pool, id);
40
        if (m) {
41
            pw_log_debug("%p: mem %d", impl, m->id);
42
            pw_memblock_unref(m);
43
@@ -356,11 +356,11 @@
44
    if (impl->this.flags & 1)
45
        return 0;
46
 
47
-   old = pw_mempool_find_tag(impl->client->pool, tag, sizeof(tag));
48
+   old = pw_mempool_find_tag(impl->client_pool, tag, sizeof(tag));
49
 
50
    if (data) {
51
-       mm = pw_mempool_import_map(impl->client->pool,
52
-               impl->context->pool, data, size, tag);
53
+       mm = pw_mempool_import_map(impl->client_pool,
54
+               impl->context_pool, data, size, tag);
55
        if (mm == NULL)
56
            return -errno;
57
 
58
@@ -659,11 +659,11 @@
59
    if ((mix = find_mix(port, mix_id)) == NULL || !mix->valid)
60
        return -EINVAL;
61
 
62
-   old = pw_mempool_find_tag(impl->client->pool, tag, sizeof(tag));
63
+   old = pw_mempool_find_tag(impl->client_pool, tag, sizeof(tag));
64
 
65
    if (data) {
66
-       mm = pw_mempool_import_map(impl->client->pool,
67
-               impl->context->pool, data, size, tag);
68
+       mm = pw_mempool_import_map(impl->client_pool,
69
+               impl->context_pool, data, size, tag);
70
        if (mm == NULL)
71
            return -errno;
72
 
73
@@ -726,15 +726,12 @@
74
            direction == SPA_DIRECTION_INPUT ? "input" : "output",
75
            port_id, mix_id, buffers, n_buffers, flags);
76
 
77
+   if (direction == SPA_DIRECTION_OUTPUT)
78
+       mix_id = SPA_ID_INVALID;
79
+
80
    if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid)
81
        return -EINVAL;
82
 
83
-   if (direction == SPA_DIRECTION_OUTPUT) {
84
-       mix_id = SPA_ID_INVALID;
85
-       if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid)
86
-           return -EINVAL;
87
-   }
88
-
89
    clear_buffers(impl, mix);
90
 
91
    if (n_buffers > 0) {
92
@@ -766,7 +763,7 @@
93
        else
94
            return -EINVAL;
95
 
96
-       if ((mem = pw_mempool_find_ptr(impl->context->pool, baseptr)) == NULL)
97
+       if ((mem = pw_mempool_find_ptr(impl->context_pool, baseptr)) == NULL)
98
            return -EINVAL;
99
 
100
        endptr = SPA_PTROFF(baseptr, buffersi->n_datas * sizeof(struct spa_chunk), void);
101
@@ -776,7 +773,7 @@
102
        for (j = 0; j < buffersi->n_datas; j++) {
103
            struct spa_data *d = &buffersi->datasj;
104
            if (d->type == SPA_DATA_MemPtr) {
105
-               if ((m = pw_mempool_find_ptr(impl->context->pool, d->data)) == NULL ||
106
+               if ((m = pw_mempool_find_ptr(impl->context_pool, d->data)) == NULL ||
107
                    m != mem)
108
                    return -EINVAL;
109
                endptr = SPA_MAX(endptr, SPA_PTROFF(d->data, d->maxsize, void));
110
@@ -785,7 +782,7 @@
111
        if (endptr > SPA_PTROFF(baseptr, mem->size, void))
112
            return -EINVAL;
113
 
114
-       m = pw_mempool_import_block(impl->client->pool, mem);
115
+       m = pw_mempool_import_block(impl->client_pool, mem);
116
        if (m == NULL)
117
            return -errno;
118
 
119
@@ -823,7 +820,7 @@
120
                    flags |= PW_MEMBLOCK_FLAG_WRITABLE;
121
 
122
                spa_log_debug(impl->log, "mem %d type:%d fd:%d", j, d->type, (int)d->fd);
123
-               m = pw_mempool_import(impl->client->pool,
124
+               m = pw_mempool_import(impl->client_pool,
125
                    flags, d->type, d->fd);
126
                if (m == NULL)
127
                    return -errno;
128
@@ -1206,14 +1203,14 @@
129
    struct impl *impl = data;
130
    struct pw_memblock *m;
131
 
132
-   m = pw_mempool_import_block(impl->client->pool, peer->activation);
133
+   m = pw_mempool_import_block(impl->client_pool, peer->activation);
134
    if (m == NULL) {
135
        pw_log_warn("%p: can't ensure mem: %m", impl);
136
        return;
137
    }
138
 
139
-   pw_log_debug("%p: peer %p/%p id:%u added mem_id:%u", impl, peer,
140
-           impl->this.node, peer->info.id, m->id);
141
+   pw_log_debug("%p: peer %p/%p id:%u added mem_id:%u %p %d", impl, peer,
142
+           impl->this.node, peer->info.id, m->id, m, m->ref);
143
 
144
    if (impl->resource == NULL)
145
        return;
146
@@ -1231,7 +1228,7 @@
147
    struct impl *impl = data;
148
    struct pw_memblock *m;
149
 
150
-   m = pw_mempool_find_fd(impl->client->pool, peer->activation->fd);
151
+   m = pw_mempool_find_fd(impl->client_pool, peer->activation->fd);
152
    if (m == NULL) {
153
        pw_log_warn("%p: unknown peer %p fd:%d", impl, peer,
154
            peer->source.fd);
155
@@ -1261,7 +1258,7 @@
156
 
157
    pw_log_debug("%p: %d", &impl->node, node_id);
158
 
159
-   impl->activation = pw_mempool_import_block(client->pool, node->activation);
160
+   impl->activation = pw_mempool_import_block(impl->client_pool, node->activation);
161
    if (impl->activation == NULL) {
162
        pw_log_debug("%p: can't import block: %m", &impl->node);
163
        return;
164
@@ -1295,7 +1292,7 @@
165
 
166
    size = sizeof(struct spa_io_buffers) * AREA_SIZE;
167
 
168
-   area = pw_mempool_alloc(impl->context->pool,
169
+   area = pw_mempool_alloc(impl->context_pool,
170
            PW_MEMBLOCK_FLAG_READWRITE |
171
            PW_MEMBLOCK_FLAG_MAP |
172
            PW_MEMBLOCK_FLAG_SEAL,
173
@@ -1348,12 +1345,9 @@
174
 
175
    spa_hook_remove(&impl->node_listener);
176
 
177
-   while ((mm = pw_mempool_find_tag(impl->client->pool, tag, sizeof(uint32_t))) != NULL)
178
+   while ((mm = pw_mempool_find_tag(impl->client_pool, tag, sizeof(uint32_t))) != NULL)
179
        pw_memmap_free(mm);
180
 
181
-   if (impl->resource)
182
-       pw_resource_destroy(impl->resource);
183
-
184
    if (impl->activation)
185
        pw_memblock_free(impl->activation);
186
 
187
@@ -1363,6 +1357,9 @@
188
    }
189
    pw_array_clear(&impl->io_areas);
190
 
191
+   if (impl->resource)
192
+       pw_resource_destroy(impl->resource);
193
+
194
    pw_map_clear(&impl->ports0);
195
    pw_map_clear(&impl->ports1);
196
    pw_map_clear(&impl->io_map);
197
@@ -1380,7 +1377,7 @@
198
    uint32_t idx, pos, len;
199
    struct pw_memblock *area;
200
 
201
-   if ((m = ensure_mix(impl, port, mix->port.port_id)) == NULL)
202
+   if ((m = create_mix(impl, port, mix->port.port_id)) == NULL)
203
        return -ENOMEM;
204
 
205
    mix->id = pw_map_insert_new(&impl->io_map, NULL);
206
@@ -1573,7 +1570,7 @@
207
            SPA_TYPE_INTERFACE_Node,
208
            SPA_VERSION_NODE,
209
            &impl_port_mix, p);
210
-   ensure_mix(impl, p, SPA_ID_INVALID);
211
+   create_mix(impl, p, SPA_ID_INVALID);
212
 
213
    pw_map_insert_at(&impl->portsp->direction, p->id, p);
214
    return;
215
@@ -1675,6 +1672,7 @@
216
    this = &impl->this;
217
 
218
    impl->context = context;
219
+   impl->context_pool = pw_context_get_mempool(context);
220
    impl->data_source.fd = -1;
221
    pw_log_debug("%p: new", &impl->node);
222
 
223
@@ -1682,6 +1680,7 @@
224
    impl_init(impl, NULL, support, n_support);
225
    impl->resource = resource;
226
    impl->client = client;
227
+   impl->client_pool = pw_impl_client_get_mempool(client);
228
    this->flags = do_register ? 0 : 1;
229
 
230
    pw_map_init(&impl->ports0, 64, 64);
231
@@ -1700,6 +1699,11 @@
232
    if (this->node == NULL)
233
        goto error_no_node;
234
 
235
+   if (this->node->data_loop == NULL) {
236
+       errno = EIO;
237
+       goto error_no_node;
238
+   }
239
+
240
    impl->data_loop = this->node->data_loop->loop;
241
    impl->data_system = this->node->data_loop->system;
242
 
243
pipewire-0.3.72.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/remote-node.c Changed
242
 
1
@@ -39,8 +39,6 @@
2
 struct mix {
3
    struct spa_list link;
4
    struct pw_impl_port *port;
5
-   uint32_t mix_id;
6
-   uint32_t peer_id;
7
    struct pw_impl_port_mix mix;
8
    struct pw_array buffers;
9
 };
10
@@ -151,9 +149,10 @@
11
 {
12
    pw_log_debug("port %p: mix init %d.%d", port, port->port_id, mix_id);
13
    mix->port = port;
14
-   mix->mix_id = mix_id;
15
-   mix->peer_id = peer_id;
16
-   pw_impl_port_init_mix(port, &mix->mix);
17
+   mix->mix.id = mix_id;
18
+   mix->mix.peer_id = peer_id;
19
+   if (mix_id != SPA_ID_INVALID)
20
+       pw_impl_port_init_mix(port, &mix->mix);
21
    pw_array_init(&mix->buffers, 32);
22
    pw_array_ensure_size(&mix->buffers, sizeof(struct buffer) * 64);
23
 }
24
@@ -165,7 +164,7 @@
25
 
26
    spa_list_for_each(mix, &data->mixdirection, link) {
27
        if (mix->port->port_id == port_id &&
28
-           mix->mix_id == mix_id) {
29
+           mix->mix.id == mix_id) {
30
            pw_log_debug("port %p: found mix %d:%d.%d", mix->port,
31
                    direction, port_id, mix_id);
32
            return mix;
33
@@ -174,16 +173,10 @@
34
    return NULL;
35
 }
36
 
37
-static struct mix *create_mix(struct node_data *data,
38
-       enum spa_direction direction, uint32_t port_id,
39
+static struct mix *create_mix(struct node_data *data, struct pw_impl_port *port,
40
        uint32_t mix_id, uint32_t peer_id)
41
 {
42
    struct mix *mix;
43
-   struct pw_impl_port *port;
44
-
45
-   port = pw_impl_node_find_port(data->node, direction, port_id);
46
-   if (port == NULL)
47
-       return NULL;
48
 
49
    if (spa_list_is_empty(&data->free_mix)) {
50
        if ((mix = calloc(1, sizeof(*mix))) == NULL)
51
@@ -193,21 +186,11 @@
52
        spa_list_remove(&mix->link);
53
    }
54
    mix_init(mix, port, mix_id, peer_id);
55
-   spa_list_append(&data->mixdirection, &mix->link);
56
+   spa_list_append(&data->mixport->direction, &mix->link);
57
 
58
    return mix;
59
 }
60
 
61
-static struct mix *ensure_mix(struct node_data *data,
62
-       enum spa_direction direction, uint32_t port_id,
63
-       uint32_t mix_id)
64
-{
65
-   struct mix *mix;
66
-   if ((mix = find_mix(data, direction, port_id, mix_id)))
67
-       return mix;
68
-   return create_mix(data, direction, port_id, mix_id, SPA_ID_INVALID);
69
-}
70
-
71
 static int client_node_transport(void *_data,
72
            int readfd, int writefd, uint32_t mem_id, uint32_t offset, uint32_t size)
73
 {
74
@@ -542,7 +525,7 @@
75
 
76
         pw_log_debug("port %p: clear %zd buffers mix:%d", port,
77
            pw_array_get_len(&mix->buffers, struct buffer *),
78
-           mix->mix_id);
79
+           mix->mix.id);
80
 
81
    if ((res = pw_impl_port_use_buffers(port, &mix->mix, 0, NULL, 0)) < 0) {
82
        pw_log_error("port %p: error clear buffers %s", port, spa_strerror(res));
83
@@ -614,7 +597,7 @@
84
    struct mix *mix;
85
    int res, prot;
86
 
87
-   mix = ensure_mix(data, direction, port_id, mix_id);
88
+   mix = find_mix(data, direction, port_id, mix_id);
89
    if (mix == NULL) {
90
        res = -ENOENT;
91
        goto error_exit;
92
@@ -744,8 +727,10 @@
93
 error_exit_cleanup:
94
    clear_buffers(data, mix);
95
 error_exit:
96
-        pw_log_error("port %p: use_buffers: %d %s", mix, res, spa_strerror(res));
97
-   pw_proxy_errorf(proxy, res, "port_use_buffers error: %s", spa_strerror(res));
98
+   pw_log_error("port %p: use_buffers(%u:%u:%d): %d %s", mix,
99
+           direction, port_id, mix_id, res, spa_strerror(res));
100
+   pw_proxy_errorf(proxy, res, "port_use_buffers(%u:%u:%d) error: %s",
101
+           direction, port_id, mix_id, spa_strerror(res));
102
    return res;
103
 }
104
 
105
@@ -767,7 +752,7 @@
106
    int res = 0;
107
    uint32_t tag5 = { data->remote_id, direction, port_id, mix_id, id };
108
 
109
-   mix = ensure_mix(data, direction, port_id, mix_id);
110
+   mix = find_mix(data, direction, port_id, mix_id);
111
    if (mix == NULL) {
112
        res = -ENOENT;
113
        goto exit;
114
@@ -874,18 +859,22 @@
115
        pw_loop_invoke(data->data_loop,
116
                        do_activate_link, SPA_ID_INVALID, NULL, 0, false, link);
117
 
118
-       pw_log_debug("node %p: link %p: fd:%d id:%u state %p required %d, pending %d",
119
-               node, link, signalfd,
120
-               link->target.activation->position.clock.id,
121
+       pw_log_debug("node %p: add link %p: memid:%u fd:%d id:%u state:%p pending:%d/%d",
122
+               node, link, memid, signalfd, node_id,
123
                &link->target.activation->state0,
124
-               link->target.activation->state0.required,
125
-               link->target.activation->state0.pending);
126
+               link->target.activation->state0.pending,
127
+               link->target.activation->state0.required);
128
    } else {
129
        link = find_activation(&data->links, node_id);
130
        if (link == NULL) {
131
            res = -ENOENT;
132
            goto error_exit;
133
        }
134
+       pw_log_debug("node %p: remove link %p: id:%u state:%p pending:%d/%d",
135
+               node, link, node_id,
136
+               &link->target.activation->state0,
137
+               link->target.activation->state0.pending,
138
+               link->target.activation->state0.required);
139
        clear_link(data, link);
140
    }
141
    return res;
142
@@ -898,7 +887,7 @@
143
 
144
 static void clear_mix(struct node_data *data, struct mix *mix)
145
 {
146
-   pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix_id);
147
+   pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix.id);
148
 
149
    spa_node_port_set_io(mix->port->mix, mix->mix.port.direction,
150
            mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0);
151
@@ -909,7 +898,8 @@
152
    pw_array_clear(&mix->buffers);
153
 
154
    spa_list_append(&data->free_mix, &mix->link);
155
-   pw_impl_port_release_mix(mix->port, &mix->mix);
156
+   if (mix->mix.id != SPA_ID_INVALID)
157
+       pw_impl_port_release_mix(mix->port, &mix->mix);
158
 }
159
 
160
 static int client_node_port_set_mix_info(void *_data,
161
@@ -928,9 +918,13 @@
162
            return -EINVAL;
163
        clear_mix(data, mix);
164
    } else {
165
+       struct pw_impl_port *port;
166
        if (mix != NULL)
167
            return -EEXIST;
168
-       mix = create_mix(data, direction, port_id, mix_id, peer_id);
169
+       port = pw_impl_node_find_port(data->node, direction, port_id);
170
+       if (port == NULL)
171
+           return -ENOENT;
172
+       mix = create_mix(data, port, mix_id, peer_id);
173
        if (mix == NULL)
174
            return -errno;
175
    }
176
@@ -956,6 +950,7 @@
177
 static void do_node_init(struct node_data *data)
178
 {
179
    struct pw_impl_port *port;
180
+   struct mix *mix;
181
 
182
    pw_log_debug("%p: node %p init", data, data->node);
183
    add_node_update(data, PW_CLIENT_NODE_UPDATE_PARAMS |
184
@@ -965,11 +960,17 @@
185
                SPA_NODE_CHANGE_MASK_PARAMS);
186
 
187
    spa_list_for_each(port, &data->node->input_ports, link) {
188
+       mix = create_mix(data, port, SPA_ID_INVALID, SPA_ID_INVALID);
189
+       if (mix == NULL)
190
+           pw_log_error("%p: failed to create port mix: %m", data->node);
191
        add_port_update(data, port,
192
                PW_CLIENT_NODE_PORT_UPDATE_PARAMS |
193
                PW_CLIENT_NODE_PORT_UPDATE_INFO);
194
    }
195
    spa_list_for_each(port, &data->node->output_ports, link) {
196
+       mix = create_mix(data, port, SPA_ID_INVALID, SPA_ID_INVALID);
197
+       if (mix == NULL)
198
+           pw_log_error("%p: failed to create port mix: %m", data->node);
199
        add_port_update(data, port,
200
                PW_CLIENT_NODE_PORT_UPDATE_PARAMS |
201
                PW_CLIENT_NODE_PORT_UPDATE_INFO);
202
@@ -1051,6 +1052,21 @@
203
    add_port_update(d, port, change_mask);
204
 }
205
 
206
+static void node_port_added(void *data, struct pw_impl_port *port)
207
+{
208
+   struct node_data *d = data;
209
+   struct mix *mix;
210
+
211
+   pw_log_debug("added %p", d);
212
+
213
+   if (d->client_node == NULL)
214
+       return;
215
+
216
+   mix = create_mix(d, port, SPA_ID_INVALID, SPA_ID_INVALID);
217
+   if (mix == NULL)
218
+       pw_log_error("%p: failed to create port mix: %m", d->node);
219
+}
220
+
221
 static void node_port_removed(void *data, struct pw_impl_port *port)
222
 {
223
    struct node_data *d = data;
224
@@ -1099,6 +1115,7 @@
225
    .free = node_free,
226
    .info_changed = node_info_changed,
227
    .port_info_changed = node_port_info_changed,
228
+   .port_added = node_port_added,
229
    .port_removed = node_port_removed,
230
    .active_changed = node_active_changed,
231
    .event = node_event,
232
@@ -1176,6 +1193,9 @@
233
    struct pw_proxy *client_node;
234
    struct node_data *data;
235
 
236
+   if (node->data_loop == NULL)
237
+       goto error;
238
+
239
    user_data_size = SPA_ROUND_UP_N(user_data_size, __alignof__(struct node_data));
240
 
241
    client_node = pw_core_create_object(core,
242
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/client-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/client-node.c Changed
83
 
1
@@ -15,13 +15,14 @@
2
 #include <spa/node/node.h>
3
 #include <spa/node/utils.h>
4
 #include <spa/node/io.h>
5
+#include <spa/node/type-info.h>
6
 #include <spa/pod/filter.h>
7
 #include <spa/utils/keys.h>
8
+#include <spa/utils/result.h>
9
 
10
 #define PW_ENABLE_DEPRECATED
11
 
12
 #include "pipewire/pipewire.h"
13
-#include "pipewire/private.h"
14
 
15
 #include "pipewire/context.h"
16
 #include "modules/spa/spa-node.h"
17
@@ -130,6 +131,7 @@
18
    bool client_reuse;
19
 
20
    struct pw_context *context;
21
+   struct pw_mempool *context_pool;
22
 
23
    struct node node;
24
 
25
@@ -335,7 +337,7 @@
26
 
27
 static int send_clock_update(struct node *this)
28
 {
29
-   struct pw_impl_client *client = this->resource->client;
30
+   struct pw_impl_client *client = pw_resource_get_client(this->resource);
31
    uint32_t type = pw_protocol_native0_name_to_v2(client, SPA_TYPE_INFO_NODE_COMMAND_BASE "ClockUpdate");
32
    struct timespec ts;
33
    int64_t now;
34
@@ -468,7 +470,7 @@
35
        }
36
        for (i = 0; i < port->n_params; i++) {
37
            port->paramsi = paramsi ?
38
-               pw_protocol_native0_pod_from_v2(this->resource->client, paramsi) : NULL;
39
+               pw_protocol_native0_pod_from_v2(pw_resource_get_client(this->resource), paramsi) : NULL;
40
 
41
            if (port->paramsi && spa_pod_is_object_id(port->paramsi, SPA_PARAM_Format))
42
                port->have_format = true;
43
@@ -661,7 +663,7 @@
44
 
45
 
46
    if (data) {
47
-       if ((mem = pw_mempool_find_ptr(impl->context->pool, data)) == NULL)
48
+       if ((mem = pw_mempool_find_ptr(impl->context_pool, data)) == NULL)
49
            return -EINVAL;
50
 
51
        mem_offset = SPA_PTRDIFF(data, mem->map->ptr);
52
@@ -744,7 +746,7 @@
53
        else
54
            return -EINVAL;
55
 
56
-       if ((mem = pw_mempool_find_ptr(impl->context->pool, baseptr)) == NULL)
57
+       if ((mem = pw_mempool_find_ptr(impl->context_pool, baseptr)) == NULL)
58
            return -EINVAL;
59
 
60
        data_size = 0;
61
@@ -910,8 +912,7 @@
62
    struct node *this = object;
63
    struct impl *impl = this->impl;
64
    struct pw_impl_node *n = impl->this.node;
65
-
66
-   return impl_node_process_input(n->node);
67
+   return impl_node_process_input(pw_impl_node_get_implementation(n));
68
 }
69
 
70
 static int handle_node_message(struct node *this, struct pw_client_node0_message *message)
71
@@ -1363,9 +1364,10 @@
72
    }
73
    convert_properties(properties);
74
 
75
-   pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", client->global->id);
76
+   pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", pw_global_get_id(pw_impl_client_get_global(client)));
77
 
78
    impl->context = context;
79
+   impl->context_pool = pw_context_get_mempool(context);
80
    impl->fds0 = impl->fds1 = -1;
81
    pw_log_debug("client-node %p: new", impl);
82
 
83
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/client-node.h -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/client-node.h Changed
18
 
1
@@ -43,6 +43,16 @@
2
    struct spa_command_node0_clock_update_body body;
3
 };
4
 
5
+enum spa_node0_event {
6
+   SPA_NODE0_EVENT_START   = SPA_TYPE_VENDOR_PipeWire,
7
+   SPA_NODE0_EVENT_RequestClockUpdate,
8
+};
9
+
10
+enum spa_node0_command {
11
+   SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire,
12
+   SPA_NODE0_COMMAND_ClockUpdate,
13
+};
14
+
15
 #define SPA_COMMAND_NODE0_CLOCK_UPDATE_INIT(type,change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency)  \
16
    SPA_COMMAND_INIT_FULL(struct spa_command_node0_clock_update,            \
17
                         sizeof(struct spa_command_node0_clock_update_body), 0, type,   \
18
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/transport.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/transport.c Changed
18
 
1
@@ -10,7 +10,6 @@
2
 #include <spa/node/io.h>
3
 
4
 #include <pipewire/impl.h>
5
-#include <pipewire/private.h>
6
 
7
 #include "ext-client-node.h"
8
 
9
@@ -190,7 +189,7 @@
10
    trans = &impl->trans;
11
    impl->offset = 0;
12
 
13
-   impl->mem = pw_mempool_alloc(context->pool,
14
+   impl->mem = pw_mempool_alloc(pw_context_get_mempool(context),
15
            PW_MEMBLOCK_FLAG_READWRITE |
16
            PW_MEMBLOCK_FLAG_MAP |
17
            PW_MEMBLOCK_FLAG_SEAL,
18
pipewire-0.3.72.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-combine-stream.c Changed
9
 
1
@@ -818,6 +818,7 @@
2
    } else {
3
        direction = PW_DIRECTION_INPUT;
4
        s->stream_events.process = stream_input_process;
5
+       flags |= PW_STREAM_FLAG_ASYNC;
6
    }
7
 
8
    pw_stream_add_listener(s->stream,
9
pipewire-0.3.74.tar.gz/src/modules/module-example-filter.c Added
641
 
1
@@ -0,0 +1,639 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <string.h>
7
+#include <stdio.h>
8
+#include <errno.h>
9
+#include <sys/types.h>
10
+#include <sys/stat.h>
11
+#include <fcntl.h>
12
+#include <unistd.h>
13
+
14
+#include "config.h"
15
+
16
+#include <spa/utils/result.h>
17
+#include <spa/utils/string.h>
18
+#include <spa/utils/json.h>
19
+#include <spa/utils/ringbuffer.h>
20
+#include <spa/param/latency-utils.h>
21
+#include <spa/debug/types.h>
22
+
23
+#include <pipewire/impl.h>
24
+#include <pipewire/extensions/profiler.h>
25
+
26
+/** \page page_module_example_filter PipeWire Module: Example Filter
27
+ *
28
+ * The example filter is a good starting point for writing a custom
29
+ * filter. We refer to the source code for more information.
30
+ *
31
+ * ## Module Options
32
+ *
33
+ * - `node.description`: a human readable name for the filter streams
34
+ * - `capture.props = {}`: properties to be passed to the input stream
35
+ * - `playback.props = {}`: properties to be passed to the output stream
36
+ *
37
+ * ## General options
38
+ *
39
+ * Options with well-known behavior. Most options can be added to the global
40
+ * configuration or the individual streams:
41
+ *
42
+ * - \ref PW_KEY_REMOTE_NAME
43
+ * - \ref PW_KEY_AUDIO_RATE
44
+ * - \ref PW_KEY_AUDIO_CHANNELS
45
+ * - \ref SPA_KEY_AUDIO_POSITION
46
+ * - \ref PW_KEY_MEDIA_NAME
47
+ * - \ref PW_KEY_NODE_LATENCY
48
+ * - \ref PW_KEY_NODE_DESCRIPTION
49
+ * - \ref PW_KEY_NODE_GROUP
50
+ * - \ref PW_KEY_NODE_LINK_GROUP
51
+ * - \ref PW_KEY_NODE_VIRTUAL
52
+ * - \ref PW_KEY_NODE_NAME: See notes below. If not specified, defaults to
53
+ *     'filter-<pid>-<module-id>'.
54
+ *
55
+ * Stream only properties:
56
+ *
57
+ * - \ref PW_KEY_MEDIA_CLASS
58
+ * - \ref PW_KEY_NODE_NAME:  if not given per stream, the global node.name will be
59
+ *         prefixed with 'input.' and 'output.' to generate a capture and playback
60
+ *         stream node.name respectively.
61
+ *
62
+ * ## Example configuration of a virtual source
63
+ *
64
+ *\code{.unparsed}
65
+ * context.modules = 
66
+ * {   name = libpipewire-module-example-filter
67
+ *     args = {
68
+ *       node.description = "Example Filter"
69
+ *       capture.props = {
70
+ *           audio.position =  FL FR 
71
+ *           node.passive = true
72
+ *       }
73
+ *       playback.props = {
74
+ *           node.name = "Example Filter"
75
+ *           media.class = "Audio/Source"
76
+ *           audio.position =  FL FR 
77
+ *       }
78
+ *     }
79
+ * }
80
+ * 
81
+ *\endcode
82
+ *
83
+ *\code{.unparsed}
84
+ * pw-cli -m lm libpipewire-module-example-filter '{ audio.position=FL FR }'
85
+ *\endcode
86
+ *
87
+ */
88
+
89
+#define NAME "example-filter"
90
+
91
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
92
+#define PW_LOG_TOPIC_DEFAULT mod_topic
93
+
94
+static const struct spa_dict_item module_props = {
95
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
96
+   { PW_KEY_MODULE_DESCRIPTION, "Create example filter streams" },
97
+   { PW_KEY_MODULE_USAGE, " ( remote.name=<remote> ) "
98
+               "( node.latency=<latency as fraction> ) "
99
+               "( node.description=<description of the nodes> ) "
100
+               "( audio.rate=<sample rate> ) "
101
+               "( audio.channels=<number of channels> ) "
102
+               "( audio.position=<channel map> ) "
103
+               "( capture.props=<properties> ) "
104
+               "( playback.props=<properties> ) " },
105
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
106
+};
107
+
108
+#include <stdlib.h>
109
+#include <signal.h>
110
+#include <getopt.h>
111
+#include <limits.h>
112
+#include <math.h>
113
+
114
+#include <spa/pod/builder.h>
115
+#include <spa/param/audio/format-utils.h>
116
+#include <spa/param/audio/raw.h>
117
+
118
+#include <pipewire/pipewire.h>
119
+
120
+struct impl {
121
+   struct pw_context *context;
122
+
123
+   struct pw_impl_module *module;
124
+
125
+   struct spa_hook module_listener;
126
+
127
+   struct pw_core *core;
128
+   struct spa_hook core_proxy_listener;
129
+   struct spa_hook core_listener;
130
+
131
+   struct pw_properties *capture_props;
132
+   struct pw_stream *capture;
133
+   struct spa_hook capture_listener;
134
+   struct spa_audio_info_raw capture_info;
135
+   struct spa_latency_info capture_latency;
136
+
137
+   struct pw_properties *playback_props;
138
+   struct pw_stream *playback;
139
+   struct spa_hook playback_listener;
140
+   struct spa_audio_info_raw playback_info;
141
+   struct spa_latency_info playback_latency;
142
+
143
+   unsigned int do_disconnect:1;
144
+};
145
+
146
+static void capture_destroy(void *d)
147
+{
148
+   struct impl *impl = d;
149
+   spa_hook_remove(&impl->capture_listener);
150
+   impl->capture = NULL;
151
+}
152
+
153
+static void capture_process(void *d)
154
+{
155
+   struct impl *impl = d;
156
+   pw_stream_trigger_process(impl->playback);
157
+}
158
+
159
+static void playback_process(void *d)
160
+{
161
+   struct impl *impl = d;
162
+   struct pw_buffer *in, *out;
163
+   uint32_t i;
164
+
165
+   in = NULL;
166
+   while (true) {
167
+       struct pw_buffer *t;
168
+       if ((t = pw_stream_dequeue_buffer(impl->capture)) == NULL)
169
+           break;
170
+       if (in)
171
+           pw_stream_queue_buffer(impl->capture, in);
172
+       in = t;
173
+   }
174
+   if (in == NULL)
175
+       pw_log_debug("%p: out of capture buffers: %m", impl);
176
+
177
+   if ((out = pw_stream_dequeue_buffer(impl->playback)) == NULL)
178
+       pw_log_debug("%p: out of playback buffers: %m", impl);
179
+
180
+   if (in != NULL && out != NULL) {
181
+       uint32_t outsize = UINT32_MAX;
182
+       int32_t stride = 0;
183
+       struct spa_data *d;
184
+       const void *srcin->buffer->n_datas;
185
+       void *dstout->buffer->n_datas;
186
+
187
+       for (i = 0; i < in->buffer->n_datas; i++) {
188
+           uint32_t offs, size;
189
+
190
+           d = &in->buffer->datasi;
191
+           offs = SPA_MIN(d->chunk->offset, d->maxsize);
192
+           size = SPA_MIN(d->chunk->size, d->maxsize - offs);
193
+
194
+           srci = SPA_PTROFF(d->data, offs, void);
195
+           outsize = SPA_MIN(outsize, size);
196
+           stride = SPA_MAX(stride, d->chunk->stride);
197
+       }
198
+       for (i = 0; i < out->buffer->n_datas; i++) {
199
+           d = &out->buffer->datasi;
200
+
201
+           outsize = SPA_MIN(outsize, d->maxsize);
202
+           dsti = d->data;
203
+
204
+           if (i < in->buffer->n_datas) {
205
+               /* do filtering here, samples are a single
206
+                * channel float */
207
+               memcpy(dsti, srci, outsize);
208
+           } else {
209
+               memset(dsti, 0, outsize);
210
+           }
211
+           d->chunk->offset = 0;
212
+           d->chunk->size = outsize;
213
+           d->chunk->stride = stride;
214
+       }
215
+   }
216
+
217
+   if (in != NULL)
218
+       pw_stream_queue_buffer(impl->capture, in);
219
+   if (out != NULL)
220
+       pw_stream_queue_buffer(impl->playback, out);
221
+}
222
+
223
+static void param_latency_changed(struct impl *impl, const struct spa_pod *param,
224
+       struct spa_latency_info *info, struct pw_stream *other)
225
+{
226
+   struct spa_latency_info latency;
227
+   uint8_t buffer1024;
228
+   struct spa_pod_builder b;
229
+   const struct spa_pod *params1;
230
+
231
+   if (spa_latency_parse(param, &latency) < 0)
232
+       return;
233
+
234
+   *info = latency;
235
+
236
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
237
+   params0 = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
238
+   pw_stream_update_params(other, params, 1);
239
+}
240
+
241
+static void stream_state_changed(void *data, enum pw_stream_state old,
242
+       enum pw_stream_state state, const char *error)
243
+{
244
+   struct impl *impl = data;
245
+   switch (state) {
246
+   case PW_STREAM_STATE_PAUSED:
247
+       pw_stream_flush(impl->playback, false);
248
+       pw_stream_flush(impl->capture, false);
249
+       break;
250
+   case PW_STREAM_STATE_UNCONNECTED:
251
+       pw_log_info("module %p: unconnected", impl);
252
+       pw_impl_module_schedule_destroy(impl->module);
253
+       break;
254
+   case PW_STREAM_STATE_ERROR:
255
+       pw_log_info("module %p: error: %s", impl, error);
256
+       break;
257
+   default:
258
+       break;
259
+   }
260
+}
261
+
262
+static void capture_param_changed(void *data, uint32_t id, const struct spa_pod *param)
263
+{
264
+   struct impl *impl = data;
265
+
266
+   switch (id) {
267
+   case SPA_PARAM_Format:
268
+   {
269
+       struct spa_audio_info_raw info;
270
+       if (param == NULL)
271
+           return;
272
+       if (spa_format_audio_raw_parse(param, &info) < 0)
273
+           return;
274
+       if (info.rate == 0 ||
275
+           info.channels == 0 ||
276
+           info.channels > SPA_AUDIO_MAX_CHANNELS)
277
+           return;
278
+       break;
279
+   }
280
+   case SPA_PARAM_Latency:
281
+       param_latency_changed(impl, param, &impl->capture_latency, impl->playback);
282
+       break;
283
+   }
284
+}
285
+
286
+static const struct pw_stream_events in_stream_events = {
287
+   PW_VERSION_STREAM_EVENTS,
288
+   .destroy = capture_destroy,
289
+   .process = capture_process,
290
+   .state_changed = stream_state_changed,
291
+   .param_changed = capture_param_changed,
292
+};
293
+
294
+static void playback_destroy(void *d)
295
+{
296
+   struct impl *impl = d;
297
+   spa_hook_remove(&impl->playback_listener);
298
+   impl->playback = NULL;
299
+}
300
+
301
+static void playback_param_changed(void *data, uint32_t id, const struct spa_pod *param)
302
+{
303
+   struct impl *impl = data;
304
+
305
+   switch (id) {
306
+   case SPA_PARAM_Latency:
307
+       param_latency_changed(impl, param, &impl->playback_latency, impl->capture);
308
+       break;
309
+   }
310
+}
311
+static const struct pw_stream_events out_stream_events = {
312
+   PW_VERSION_STREAM_EVENTS,
313
+   .destroy = playback_destroy,
314
+   .process = playback_process,
315
+   .state_changed = stream_state_changed,
316
+   .param_changed = playback_param_changed,
317
+};
318
+
319
+static int setup_streams(struct impl *impl)
320
+{
321
+   int res;
322
+   uint32_t n_params;
323
+   const struct spa_pod *params1;
324
+   uint8_t buffer1024;
325
+   struct spa_pod_builder b;
326
+
327
+   impl->capture = pw_stream_new(impl->core,
328
+           "filter capture", impl->capture_props);
329
+   impl->capture_props = NULL;
330
+   if (impl->capture == NULL)
331
+       return -errno;
332
+
333
+   pw_stream_add_listener(impl->capture,
334
+           &impl->capture_listener,
335
+           &in_stream_events, impl);
336
+
337
+   impl->playback = pw_stream_new(impl->core,
338
+           "filter playback", impl->playback_props);
339
+   impl->playback_props = NULL;
340
+   if (impl->playback == NULL)
341
+       return -errno;
342
+
343
+   pw_stream_add_listener(impl->playback,
344
+           &impl->playback_listener,
345
+           &out_stream_events, impl);
346
+
347
+   /* connect playback first to activate it before capture triggers it */
348
+   n_params = 0;
349
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
350
+   paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
351
+           &impl->playback_info);
352
+   if ((res = pw_stream_connect(impl->playback,
353
+           PW_DIRECTION_OUTPUT,
354
+           PW_ID_ANY,
355
+           PW_STREAM_FLAG_AUTOCONNECT |
356
+           PW_STREAM_FLAG_MAP_BUFFERS |
357
+           PW_STREAM_FLAG_RT_PROCESS |
358
+           PW_STREAM_FLAG_TRIGGER,
359
+           params, n_params)) < 0)
360
+       return res;
361
+
362
+   n_params = 0;
363
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
364
+   paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
365
+           &impl->capture_info);
366
+   if ((res = pw_stream_connect(impl->capture,
367
+           PW_DIRECTION_INPUT,
368
+           PW_ID_ANY,
369
+           PW_STREAM_FLAG_AUTOCONNECT |
370
+           PW_STREAM_FLAG_MAP_BUFFERS |
371
+           PW_STREAM_FLAG_RT_PROCESS |
372
+           PW_STREAM_FLAG_ASYNC,
373
+           params, n_params)) < 0)
374
+       return res;
375
+
376
+   return 0;
377
+}
378
+
379
+static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
380
+{
381
+   struct impl *impl = data;
382
+
383
+   if (res == -ENOENT) {
384
+       pw_log_info("message id:%u seq:%d res:%d (%s): %s",
385
+               id, seq, res, spa_strerror(res), message);
386
+   } else {
387
+       pw_log_warn("error id:%u seq:%d res:%d (%s): %s",
388
+               id, seq, res, spa_strerror(res), message);
389
+   }
390
+
391
+   if (id == PW_ID_CORE && res == -EPIPE)
392
+       pw_impl_module_schedule_destroy(impl->module);
393
+}
394
+
395
+static const struct pw_core_events core_events = {
396
+   PW_VERSION_CORE_EVENTS,
397
+   .error = core_error,
398
+};
399
+
400
+static void core_destroy(void *d)
401
+{
402
+   struct impl *impl = d;
403
+   spa_hook_remove(&impl->core_listener);
404
+   impl->core = NULL;
405
+   pw_impl_module_schedule_destroy(impl->module);
406
+}
407
+
408
+static const struct pw_proxy_events core_proxy_events = {
409
+   .destroy = core_destroy,
410
+};
411
+
412
+static void impl_destroy(struct impl *impl)
413
+{
414
+   /* deactivate both streams before destroying any of them */
415
+   if (impl->capture)
416
+       pw_stream_set_active(impl->capture, false);
417
+   if (impl->playback)
418
+       pw_stream_set_active(impl->playback, false);
419
+
420
+   if (impl->capture)
421
+       pw_stream_destroy(impl->capture);
422
+   if (impl->playback)
423
+       pw_stream_destroy(impl->playback);
424
+
425
+   if (impl->core && impl->do_disconnect)
426
+       pw_core_disconnect(impl->core);
427
+
428
+   pw_properties_free(impl->capture_props);
429
+   pw_properties_free(impl->playback_props);
430
+   free(impl);
431
+}
432
+
433
+static void module_destroy(void *data)
434
+{
435
+   struct impl *impl = data;
436
+   spa_hook_remove(&impl->module_listener);
437
+   impl_destroy(impl);
438
+}
439
+
440
+static const struct pw_impl_module_events module_events = {
441
+   PW_VERSION_IMPL_MODULE_EVENTS,
442
+   .destroy = module_destroy,
443
+};
444
+
445
+static uint32_t channel_from_name(const char *name)
446
+{
447
+   int i;
448
+   for (i = 0; spa_type_audio_channeli.name; i++) {
449
+       if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name)))
450
+           return spa_type_audio_channeli.type;
451
+   }
452
+   return SPA_AUDIO_CHANNEL_UNKNOWN;
453
+}
454
+
455
+static void parse_position(struct spa_audio_info_raw *info, const char *val, size_t len)
456
+{
457
+   struct spa_json it2;
458
+   char v256;
459
+
460
+   spa_json_init(&it0, val, len);
461
+        if (spa_json_enter_array(&it0, &it1) <= 0)
462
+                spa_json_init(&it1, val, len);
463
+
464
+   info->channels = 0;
465
+   while (spa_json_get_string(&it1, v, sizeof(v)) > 0 &&
466
+       info->channels < SPA_AUDIO_MAX_CHANNELS) {
467
+       info->positioninfo->channels++ = channel_from_name(v);
468
+   }
469
+}
470
+
471
+static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info)
472
+{
473
+   const char *str;
474
+
475
+   *info = SPA_AUDIO_INFO_RAW_INIT(
476
+           .format = SPA_AUDIO_FORMAT_F32P);
477
+   info->rate = pw_properties_get_int32(props, PW_KEY_AUDIO_RATE, 0);
478
+   info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, 0);
479
+   info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS);
480
+   if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL)
481
+       parse_position(info, str, strlen(str));
482
+}
483
+
484
+static void copy_props(struct impl *impl, struct pw_properties *props, const char *key)
485
+{
486
+   const char *str;
487
+   if ((str = pw_properties_get(props, key)) != NULL) {
488
+       if (pw_properties_get(impl->capture_props, key) == NULL)
489
+           pw_properties_set(impl->capture_props, key, str);
490
+       if (pw_properties_get(impl->playback_props, key) == NULL)
491
+           pw_properties_set(impl->playback_props, key, str);
492
+   }
493
+}
494
+
495
+SPA_EXPORT
496
+int pipewire__module_init(struct pw_impl_module *module, const char *args)
497
+{
498
+   struct pw_context *context = pw_impl_module_get_context(module);
499
+   struct pw_properties *props;
500
+   struct impl *impl;
501
+   uint32_t id = pw_global_get_id(pw_impl_module_get_global(module));
502
+   uint32_t pid = getpid();
503
+   const char *str;
504
+   int res;
505
+
506
+   PW_LOG_TOPIC_INIT(mod_topic);
507
+
508
+   impl = calloc(1, sizeof(struct impl));
509
+   if (impl == NULL)
510
+       return -errno;
511
+
512
+   pw_log_debug("module %p: new %s", impl, args);
513
+
514
+   if (args)
515
+       props = pw_properties_new_string(args);
516
+   else
517
+       props = pw_properties_new(NULL, NULL);
518
+   if (props == NULL) {
519
+       res = -errno;
520
+       pw_log_error( "can't create properties: %m");
521
+       goto error;
522
+   }
523
+
524
+   impl->capture_props = pw_properties_new(NULL, NULL);
525
+   impl->playback_props = pw_properties_new(NULL, NULL);
526
+   if (impl->capture_props == NULL || impl->playback_props == NULL) {
527
+       res = -errno;
528
+       pw_log_error( "can't create properties: %m");
529
+       goto error;
530
+   }
531
+
532
+   impl->module = module;
533
+   impl->context = context;
534
+
535
+   if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
536
+       pw_properties_setf(props, PW_KEY_NODE_GROUP, "filter-%u-%u", pid, id);
537
+   if (pw_properties_get(props, PW_KEY_NODE_LINK_GROUP) == NULL)
538
+       pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "filter-%u-%u", pid, id);
539
+   if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
540
+       pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
541
+   if (pw_properties_get(props, "resample.prefill") == NULL)
542
+       pw_properties_set(props, "resample.prefill", "true");
543
+
544
+   if ((str = pw_properties_get(props, "capture.props")) != NULL)
545
+       pw_properties_update_string(impl->capture_props, str, strlen(str));
546
+   if ((str = pw_properties_get(props, "playback.props")) != NULL)
547
+       pw_properties_update_string(impl->playback_props, str, strlen(str));
548
+
549
+   copy_props(impl, props, PW_KEY_AUDIO_RATE);
550
+   copy_props(impl, props, PW_KEY_AUDIO_CHANNELS);
551
+   copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
552
+   copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
553
+   copy_props(impl, props, PW_KEY_NODE_GROUP);
554
+   copy_props(impl, props, PW_KEY_NODE_LINK_GROUP);
555
+   copy_props(impl, props, PW_KEY_NODE_LATENCY);
556
+   copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
557
+   copy_props(impl, props, PW_KEY_MEDIA_NAME);
558
+   copy_props(impl, props, "resample.prefill");
559
+
560
+   if ((str = pw_properties_get(props, PW_KEY_NODE_NAME)) == NULL) {
561
+       pw_properties_setf(props, PW_KEY_NODE_NAME,
562
+               "filter-%u-%u", pid, id);
563
+       str = pw_properties_get(props, PW_KEY_NODE_NAME);
564
+   }
565
+   if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL)
566
+       pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME,
567
+               "input.%s", str);
568
+   if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL)
569
+       pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME,
570
+               "output.%s", str);
571
+   if (pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION) == NULL)
572
+       pw_properties_set(impl->capture_props, PW_KEY_NODE_DESCRIPTION, str);
573
+   if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL)
574
+       pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str);
575
+
576
+   parse_audio_info(impl->capture_props, &impl->capture_info);
577
+   parse_audio_info(impl->playback_props, &impl->playback_info);
578
+
579
+   if (!impl->capture_info.rate && !impl->playback_info.rate) {
580
+       if (pw_properties_get(impl->playback_props, "resample.disable") == NULL)
581
+           pw_properties_set(impl->playback_props, "resample.disable", "true");
582
+       if (pw_properties_get(impl->capture_props, "resample.disable") == NULL)
583
+           pw_properties_set(impl->capture_props, "resample.disable", "true");
584
+   } else if (impl->capture_info.rate && !impl->playback_info.rate)
585
+       impl->playback_info.rate = impl->capture_info.rate;
586
+   else if (impl->playback_info.rate && !impl->capture_info.rate)
587
+       impl->capture_info.rate = !impl->playback_info.rate;
588
+   else if (impl->capture_info.rate != impl->playback_info.rate) {
589
+       pw_log_warn("Both capture and playback rate are set, but"
590
+           " they are different. Using the highest of two. This behaviour"
591
+           " is deprecated, please use equal rates in the module config");
592
+       impl->playback_info.rate = impl->capture_info.rate =
593
+           SPA_MAX(impl->playback_info.rate, impl->capture_info.rate);
594
+   }
595
+
596
+   if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL)
597
+       pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input",
598
+               pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION));
599
+   if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL)
600
+       pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output",
601
+               pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION));
602
+
603
+   impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
604
+   if (impl->core == NULL) {
605
+       str = pw_properties_get(props, PW_KEY_REMOTE_NAME);
606
+       impl->core = pw_context_connect(impl->context,
607
+               pw_properties_new(
608
+                   PW_KEY_REMOTE_NAME, str,
609
+                   NULL),
610
+               0);
611
+       impl->do_disconnect = true;
612
+   }
613
+   if (impl->core == NULL) {
614
+       res = -errno;
615
+       pw_log_error("can't connect: %m");
616
+       goto error;
617
+   }
618
+
619
+   pw_properties_free(props);
620
+
621
+   pw_proxy_add_listener((struct pw_proxy*)impl->core,
622
+           &impl->core_proxy_listener,
623
+           &core_proxy_events, impl);
624
+   pw_core_add_listener(impl->core,
625
+           &impl->core_listener,
626
+           &core_events, impl);
627
+
628
+   setup_streams(impl);
629
+
630
+   pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
631
+
632
+   pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
633
+
634
+   return 0;
635
+
636
+error:
637
+   pw_properties_free(props);
638
+   impl_destroy(impl);
639
+   return res;
640
+}
641
pipewire-0.3.72.tar.gz/src/modules/module-ffado-driver.c -> pipewire-0.3.74.tar.gz/src/modules/module-ffado-driver.c Changed
30
 
1
@@ -27,7 +27,6 @@
2
 
3
 #include <pipewire/impl.h>
4
 #include <pipewire/i18n.h>
5
-#include <pipewire/private.h>
6
 #include <pipewire/thread.h>
7
 
8
 #include <libffado/ffado.h>
9
@@ -745,20 +744,6 @@
10
    return NULL;
11
 }
12
 
13
-static int
14
-do_schedule_destroy(struct spa_loop *loop,
15
-   bool async, uint32_t seq, const void *data, size_t size, void *user_data)
16
-{
17
-   struct impl *impl = user_data;
18
-   pw_impl_module_schedule_destroy(impl->module);
19
-   return 0;
20
-}
21
-
22
-void module_schedule_destroy(struct impl *impl)
23
-{
24
-   pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl);
25
-}
26
-
27
 static int open_ffado_device(struct impl *impl)
28
 {
29
    ffado_streaming_stream_type stream_type;
30
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain.c Changed
452
 
1
@@ -147,7 +147,7 @@
2
  *
3
  * The mixer plugin has up to 8 input ports labeled "In 1" to "In 8" and each with
4
  * a gain control labeled "Gain 1" to "Gain 8". There is an output port labeled
5
- * "Out". Unused input ports will be ignoded and not cause overhead.
6
+ * "Out". Unused input ports will be ignored and not cause overhead.
7
  *
8
  * ### Copy
9
  *
10
@@ -518,9 +518,16 @@
11
 #define MAX_HNDL 64
12
 #define MAX_SAMPLES 8192
13
 
14
+#define DEFAULT_RATE   48000
15
+
16
 static float silence_dataMAX_SAMPLES;
17
 static float discard_dataMAX_SAMPLES;
18
 
19
+struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
20
+       struct dsp_ops *dsp, const char *path, const char *config);
21
+struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
22
+       struct dsp_ops *dsp, const char *path, const char *config);
23
+
24
 struct plugin {
25
    struct spa_list link;
26
    int ref;
27
@@ -531,6 +538,13 @@
28
    struct spa_list descriptor_list;
29
 };
30
 
31
+struct plugin_func {
32
+   struct spa_list link;
33
+   char type256;
34
+   fc_plugin_load_func *func;
35
+   void *hndl;
36
+};
37
+
38
 struct descriptor {
39
    struct spa_list link;
40
    int ref;
41
@@ -627,6 +641,8 @@
42
 
43
    uint32_t n_control;
44
    struct port **control_port;
45
+
46
+   unsigned instantiated:1;
47
 };
48
 
49
 struct impl {
50
@@ -643,6 +659,7 @@
51
    struct dsp_ops dsp;
52
 
53
    struct spa_list plugin_list;
54
+   struct spa_list plugin_func_list;
55
 
56
    struct pw_properties *capture_props;
57
    struct pw_stream *capture;
58
@@ -654,6 +671,10 @@
59
    struct spa_hook playback_listener;
60
    struct spa_audio_info_raw playback_info;
61
 
62
+   struct spa_audio_info_raw info;
63
+
64
+   struct spa_io_position *position;
65
+
66
    unsigned int do_disconnect:1;
67
 
68
    long unsigned rate;
69
@@ -856,7 +877,7 @@
70
    struct fc_port *p = &d->portsport->p;
71
    float def, min, max;
72
    char name512;
73
-   uint32_t rate = impl->rate ? impl->rate : 48000;
74
+   uint32_t rate = impl->rate ? impl->rate : DEFAULT_RATE;
75
 
76
    if (p->hint & FC_HINT_SAMPLE_RATE) {
77
        def = p->def * rate;
78
@@ -1105,6 +1126,7 @@
79
 {
80
    struct impl *impl = data;
81
    struct graph *graph = &impl->graph;
82
+   int res;
83
 
84
    switch (state) {
85
    case PW_STREAM_STATE_PAUSED:
86
@@ -1119,6 +1141,40 @@
87
    case PW_STREAM_STATE_ERROR:
88
        pw_log_info("module %p: error: %s", impl, error);
89
        break;
90
+   case PW_STREAM_STATE_STREAMING:
91
+   {
92
+       uint32_t target = impl->info.rate;
93
+       if (target == 0)
94
+           target = impl->position ?
95
+               impl->position->clock.target_rate.denom : DEFAULT_RATE;
96
+       if (target == 0) {
97
+           res = -EINVAL;
98
+           goto error;
99
+       }
100
+       if (impl->rate != target) {
101
+           impl->rate = target;
102
+           graph_cleanup(graph);
103
+           if ((res = graph_instantiate(graph)) < 0)
104
+               goto error;
105
+       }
106
+       break;
107
+   }
108
+   default:
109
+       break;
110
+   }
111
+   return;
112
+error:
113
+   pw_stream_set_error(impl->capture, res, "can't start graph: %s",
114
+           spa_strerror(res));
115
+}
116
+
117
+static void io_changed(void *data, uint32_t id, void *area, uint32_t size)
118
+{
119
+   struct impl *impl = data;
120
+   switch (id) {
121
+   case SPA_IO_Position:
122
+       impl->position = area;
123
+       break;
124
    default:
125
        break;
126
    }
127
@@ -1132,22 +1188,19 @@
128
 
129
    switch (id) {
130
    case SPA_PARAM_Format:
131
+   {
132
+       struct spa_audio_info_raw info;
133
+       spa_zero(info);
134
        if (param == NULL) {
135
            graph_cleanup(graph);
136
+           impl->rate = 0;
137
        } else {
138
-           struct spa_audio_info_raw info;
139
-           spa_zero(info);
140
            if ((res = spa_format_audio_raw_parse(param, &info)) < 0)
141
                goto error;
142
-           if (info.rate == 0) {
143
-               res = -EINVAL;
144
-               goto error;
145
-           }
146
-           impl->rate = info.rate;
147
-           if ((res = graph_instantiate(graph)) < 0)
148
-               goto error;
149
        }
150
+       impl->info = info;
151
        break;
152
+   }
153
    case SPA_PARAM_Props:
154
        if (param != NULL)
155
            param_props_changed(impl, param);
156
@@ -1167,6 +1220,7 @@
157
    PW_VERSION_STREAM_EVENTS,
158
    .destroy = capture_destroy,
159
    .process = capture_process,
160
+   .io_changed = io_changed,
161
    .state_changed = state_changed,
162
    .param_changed = param_changed
163
 };
164
@@ -1182,8 +1236,9 @@
165
    PW_VERSION_STREAM_EVENTS,
166
    .destroy = playback_destroy,
167
    .process = playback_process,
168
+   .io_changed = io_changed,
169
    .state_changed = state_changed,
170
-   .param_changed = param_changed
171
+   .param_changed = param_changed,
172
 };
173
 
174
 static int setup_streams(struct impl *impl)
175
@@ -1255,7 +1310,8 @@
176
            PW_ID_ANY,
177
            PW_STREAM_FLAG_AUTOCONNECT |
178
            PW_STREAM_FLAG_MAP_BUFFERS |
179
-           PW_STREAM_FLAG_RT_PROCESS,
180
+           PW_STREAM_FLAG_RT_PROCESS |
181
+           PW_STREAM_FLAG_ASYNC,
182
            params, n_params);
183
 
184
    spa_pod_dynamic_builder_clean(&b);
185
@@ -1305,12 +1361,92 @@
186
    free(hndl);
187
 }
188
 
189
+
190
+static struct plugin_func *add_plugin_func(struct impl *impl, const char *type,
191
+       fc_plugin_load_func *func, void *hndl)
192
+{
193
+   struct plugin_func *pl;
194
+
195
+   pl = calloc(1, sizeof(*pl));
196
+   if (pl == NULL)
197
+       return NULL;
198
+
199
+   snprintf(pl->type, sizeof(pl->type), "%s", type);
200
+   pl->func = func;
201
+   pl->hndl = hndl;
202
+   spa_list_append(&impl->plugin_func_list, &pl->link);
203
+   return pl;
204
+}
205
+
206
+static void free_plugin_func(struct plugin_func *pl)
207
+{
208
+   spa_list_remove(&pl->link);
209
+   if (pl->hndl)
210
+       dlclose(pl->hndl);
211
+   free(pl);
212
+}
213
+
214
+static fc_plugin_load_func *find_plugin_func(struct impl *impl, const char *type)
215
+{
216
+   fc_plugin_load_func *func = NULL;
217
+   void *hndl = NULL;
218
+   int res;
219
+   struct plugin_func *pl;
220
+   char modulePATH_MAX;
221
+   const char *module_dir;
222
+   const char *state = NULL, *p;
223
+   size_t len;
224
+
225
+   spa_list_for_each(pl, &impl->plugin_func_list, link) {
226
+       if (spa_streq(pl->type, type))
227
+           return pl->func;
228
+   }
229
+   module_dir = getenv("PIPEWIRE_MODULE_DIR");
230
+   if (module_dir == NULL)
231
+       module_dir = MODULEDIR;
232
+   pw_log_debug("moduledir set to: %s", module_dir);
233
+
234
+   while ((p = pw_split_walk(module_dir, ":", &len, &state))) {
235
+       if ((res = spa_scnprintf(module, sizeof(module),
236
+               "%.*s/libpipewire-module-filter-chain-%s.so",
237
+                       (int)len, p, type)) <= 0)
238
+           continue;
239
+
240
+       hndl = dlopen(module, RTLD_NOW | RTLD_LOCAL);
241
+       if (hndl != NULL)
242
+           break;
243
+
244
+       pw_log_debug("open plugin module %s failed: %s", module, dlerror());
245
+   }
246
+   if (hndl == NULL) {
247
+       errno = ENOENT;
248
+       return NULL;
249
+   }
250
+   func = dlsym(hndl, FC_PLUGIN_LOAD_FUNC);
251
+   if (func != NULL) {
252
+       pw_log_info("opened plugin module %s", module);
253
+       pl = add_plugin_func(impl, type, func, hndl);
254
+       if (pl == NULL)
255
+           goto error_close;
256
+   } else {
257
+       errno = ENOSYS;
258
+       pw_log_error("%s is not a filter chain plugin: %m", module);
259
+       goto error_close;
260
+   }
261
+   return func;
262
+
263
+error_close:
264
+   dlclose(hndl);
265
+   return NULL;
266
+}
267
+
268
 static struct plugin *plugin_load(struct impl *impl, const char *type, const char *path)
269
 {
270
    struct fc_plugin *pl = NULL;
271
    struct plugin *hndl;
272
    const struct spa_support *support;
273
    uint32_t n_support;
274
+   fc_plugin_load_func *plugin_func;
275
 
276
    spa_list_for_each(hndl, &impl->plugin_list, link) {
277
        if (spa_streq(hndl->type, type) &&
278
@@ -1321,27 +1457,12 @@
279
    }
280
    support = pw_context_get_support(impl->context, &n_support);
281
 
282
-   if (spa_streq(type, "builtin")) {
283
-       pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL);
284
-   }
285
-   else if (spa_streq(type, "sofa")) {
286
-       pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL);
287
-   }
288
-   else if (spa_streq(type, "ladspa")) {
289
-       pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL);
290
-   }
291
-   else if (spa_streq(type, "lv2")) {
292
-#ifdef HAVE_LILV
293
-       pl = load_lv2_plugin(support, n_support, &impl->dsp, path, NULL);
294
-#else
295
-       pw_log_error("filter-chain is compiled without lv2 support");
296
+   plugin_func = find_plugin_func(impl, type);
297
+   if (plugin_func == NULL) {
298
+       pw_log_error("can't load plugin type '%s': %m", type);
299
        pl = NULL;
300
-       errno = ENOTSUP;
301
-#endif
302
    } else {
303
-       pw_log_error("invalid plugin type '%s'", type);
304
-       pl = NULL;
305
-       errno = EINVAL;
306
+       pl = plugin_func(support, n_support, &impl->dsp, path, NULL);
307
    }
308
    if (pl == NULL)
309
        goto exit;
310
@@ -1354,7 +1475,7 @@
311
    snprintf(hndl->type, sizeof(hndl->type), "%s", type);
312
    snprintf(hndl->path, sizeof(hndl->path), "%s", path);
313
 
314
-   pw_log_info("successfully opened '%s'", path);
315
+   pw_log_info("successfully opened '%s':'%s'", type, path);
316
 
317
    hndl->plugin = pl;
318
 
319
@@ -1560,7 +1681,7 @@
320
    char output256 = "";
321
    char input256 = "";
322
    const char *val;
323
-   struct node *def_node;
324
+   struct node *def_in_node, *def_out_node;
325
    struct port *in_port, *out_port;
326
    struct link *link;
327
 
328
@@ -1585,16 +1706,25 @@
329
        else if (spa_json_next(json, &val) < 0)
330
            break;
331
    }
332
-   def_node = spa_list_first(&graph->node_list, struct node, link);
333
-   if ((out_port = find_port(def_node, output, FC_PORT_OUTPUT)) == NULL) {
334
-       pw_log_error("unknown output port %s", output);
335
-       return -ENOENT;
336
+   def_out_node = spa_list_first(&graph->node_list, struct node, link);
337
+   def_in_node = spa_list_last(&graph->node_list, struct node, link);
338
+
339
+   out_port = find_port(def_out_node, output, FC_PORT_OUTPUT);
340
+   in_port = find_port(def_in_node, input, FC_PORT_INPUT);
341
+
342
+   if (out_port == NULL && out_port == NULL) {
343
+       /* try control ports */
344
+       out_port = find_port(def_out_node, output, FC_PORT_OUTPUT | FC_PORT_CONTROL);
345
+       in_port = find_port(def_in_node, input, FC_PORT_INPUT | FC_PORT_CONTROL);
346
    }
347
-   def_node = spa_list_last(&graph->node_list, struct node, link);
348
-   if ((in_port = find_port(def_node, input, FC_PORT_INPUT)) == NULL) {
349
-       pw_log_error("unknown input port %s", input);
350
+   if (in_port == NULL || out_port == NULL) {
351
+       if (out_port == NULL)
352
+           pw_log_error("unknown output port %s", output);
353
+       if (in_port == NULL)
354
+           pw_log_error("unknown input port %s", input);
355
        return -ENOENT;
356
    }
357
+
358
    if (in_port->n_links > 0) {
359
        pw_log_info("Can't have more than 1 link to %s, use a mixer", input);
360
        return -ENOTSUP;
361
@@ -1776,6 +1906,7 @@
362
    for (i = 0; i < node->n_hndl; i++) {
363
        if (node->hndli == NULL)
364
            continue;
365
+       pw_log_info("cleanup %s %d", d->name, i);
366
        if (d->deactivate)
367
            d->deactivate(node->hndli);
368
        d->cleanup(node->hndli);
369
@@ -1825,6 +1956,9 @@
370
 static void graph_cleanup(struct graph *graph)
371
 {
372
    struct node *node;
373
+   if (!graph->instantiated)
374
+       return;
375
+   graph->instantiated = false;
376
    spa_list_for_each(node, &graph->node_list, link)
377
        node_cleanup(node);
378
 }
379
@@ -1840,6 +1974,11 @@
380
    uint32_t i, j;
381
    int res;
382
 
383
+   if (graph->instantiated)
384
+       return 0;
385
+
386
+   graph->instantiated = true;
387
+
388
    spa_list_for_each(node, &graph->node_list, link) {
389
        float *sd = silence_data, *dd = discard_data;
390
 
391
@@ -1852,8 +1991,9 @@
392
 
393
        for (i = 0; i < node->n_hndl; i++) {
394
            pw_log_info("instantiate %s %d rate:%lu", d->name, i, impl->rate);
395
+           errno = EINVAL;
396
            if ((node->hndli = d->instantiate(d, impl->rate, i, node->config)) == NULL) {
397
-               pw_log_error("cannot create plugin instance: %m");
398
+               pw_log_error("cannot create plugin instance %d rate:%lu: %m", i, impl->rate);
399
                res = -errno;
400
                goto error;
401
            }
402
@@ -1883,9 +2023,20 @@
403
            for (j = 0; j < desc->n_control; j++) {
404
                port = &node->control_portj;
405
                d->connect_port(node->hndli, port->p, &port->control_data);
406
+
407
+               spa_list_for_each(link, &port->link_list, input_link) {
408
+                   struct port *peer = link->output;
409
+                   pw_log_info("connect control port %s%d:%s %p",
410
+                           node->name, i, d->portsport->p.name,
411
+                           &peer->control_data);
412
+                   d->connect_port(node->hndli, port->p, &peer->control_data);
413
+               }
414
            }
415
            for (j = 0; j < desc->n_notify; j++) {
416
                port = &node->notify_portj;
417
+               pw_log_info("connect notify port %s%d:%s %p",
418
+                       node->name, i, d->portsport->p.name,
419
+                       &port->control_data);
420
                d->connect_port(node->hndli, port->p, &port->control_data);
421
            }
422
            if (d->activate)
423
@@ -2301,6 +2452,8 @@
424
 
425
 static void impl_destroy(struct impl *impl)
426
 {
427
+   struct plugin_func *pl;
428
+
429
    /* disconnect both streams before destroying any of them */
430
    if (impl->capture)
431
        pw_stream_disconnect(impl->capture);
432
@@ -2318,6 +2471,8 @@
433
    pw_properties_free(impl->capture_props);
434
    pw_properties_free(impl->playback_props);
435
    graph_free(&impl->graph);
436
+   spa_list_consume(pl, &impl->plugin_func_list, link)
437
+       free_plugin_func(pl);
438
    free(impl);
439
 }
440
 
441
@@ -2429,6 +2584,10 @@
442
    impl->graph.impl = impl;
443
 
444
    spa_list_init(&impl->plugin_list);
445
+   spa_list_init(&impl->plugin_func_list);
446
+
447
+   add_plugin_func(impl, "builtin", load_builtin_plugin, NULL);
448
+   add_plugin_func(impl, "ladspa", load_ladspa_plugin, NULL);
449
 
450
    support = pw_context_get_support(impl->context, &n_support);
451
 
452
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
9
 
1
@@ -10,6 +10,7 @@
2
 #include <sndfile.h>
3
 #endif
4
 #include <unistd.h>
5
+#include <limits.h>
6
 
7
 #include <spa/utils/json.h>
8
 #include <spa/utils/result.h>
9
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c Changed
40
 
1
@@ -84,33 +84,27 @@
2
 void dsp_biquad_run_c(struct dsp_ops *ops, struct biquad *bq,
3
        float *out, const float *in, uint32_t n_samples)
4
 {
5
-   float x1, x2, y1, y2;
6
+   float x, y, x1, x2;
7
    float b0, b1, b2, a1, a2;
8
    uint32_t i;
9
 
10
    x1 = bq->x1;
11
    x2 = bq->x2;
12
-   y1 = bq->y1;
13
-   y2 = bq->y2;
14
    b0 = bq->b0;
15
    b1 = bq->b1;
16
    b2 = bq->b2;
17
    a1 = bq->a1;
18
    a2 = bq->a2;
19
    for (i = 0; i < n_samples; i++) {
20
-       float x = ini;
21
-       float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
22
+       x  = ini;
23
+       y  = b0 * x          + x1;
24
+       x1 = b1 * x - a1 * y + x2;
25
+       x2 = b2 * x - a2 * y;
26
        outi = y;
27
-       x2 = x1;
28
-       x1 = x;
29
-       y2 = y1;
30
-       y1 = y;
31
    }
32
 #define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
33
    bq->x1 = F(x1);
34
    bq->x2 = F(x2);
35
-   bq->y1 = F(y1);
36
-   bq->y2 = F(y2);
37
 #undef F
38
 }
39
 
40
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c Changed
9
 
1
@@ -6,6 +6,7 @@
2
 
3
 #include <dlfcn.h>
4
 #include <math.h>
5
+#include <limits.h>
6
 
7
 #include <spa/utils/defs.h>
8
 #include <spa/utils/list.h>
9
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/lv2_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/lv2_plugin.c Changed
11
 
1
@@ -451,7 +451,8 @@
2
    free(p);
3
 }
4
 
5
-struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support,
6
+SPA_EXPORT
7
+struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
8
        struct dsp_ops *ops, const char *plugin_uri, const char *config)
9
 {
10
    struct context *c;
11
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/plugin.h -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/plugin.h Changed
34
 
1
@@ -7,14 +7,8 @@
2
 
3
 #include <stdint.h>
4
 #include <stddef.h>
5
-#include <errno.h>
6
-#include <stdio.h>
7
-#include <limits.h>
8
 
9
 #include <spa/support/plugin.h>
10
-#include <spa/utils/defs.h>
11
-#include <spa/utils/list.h>
12
-#include <spa/utils/string.h>
13
 
14
 #include "dsp-ops.h"
15
 
16
@@ -83,13 +77,10 @@
17
        desc->free(desc);
18
 }
19
 
20
-struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
21
-       struct dsp_ops *dsp, const char *path, const char *config);
22
-struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support,
23
-       struct dsp_ops *dsp, const char *path, const char *config);
24
-struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
25
-       struct dsp_ops *dsp, const char *path, const char *config);
26
-struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
27
+#define FC_PLUGIN_LOAD_FUNC "pipewire__filter_chain_plugin_load"
28
+
29
+typedef struct fc_plugin *(fc_plugin_load_func)(const struct spa_support *support, uint32_t n_support,
30
        struct dsp_ops *dsp, const char *path, const char *config);
31
 
32
+
33
 #endif /* PLUGIN_H */
34
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/sofa_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/sofa_plugin.c Changed
114
 
1
@@ -1,19 +1,20 @@
2
 #include "config.h"
3
 
4
+#include <limits.h>
5
+
6
 #include <spa/utils/json.h>
7
 #include <spa/support/loop.h>
8
 
9
 #include <pipewire/log.h>
10
+
11
 #include "plugin.h"
12
 #include "convolver.h"
13
 #include "dsp-ops.h"
14
 #include "pffft.h"
15
 
16
-#ifdef HAVE_LIBMYSOFA
17
 #include <mysofa.h>
18
 
19
 #define MAX_SAMPLES    8192u
20
-#endif
21
 
22
 static struct dsp_ops *dsp_ops;
23
 static struct spa_loop *data_loop;
24
@@ -25,9 +26,7 @@
25
    int n_samples, blocksize, tailsize;
26
    float *tmp2;
27
 
28
-#ifdef HAVE_LIBMYSOFA
29
    struct MYSOFA_EASY *sofa;
30
-#endif
31
    unsigned int interpolate:1;
32
    struct convolver *l_conv3;
33
    struct convolver *r_conv3;
34
@@ -36,7 +35,6 @@
35
 static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
36
        unsigned long SampleRate, int index, const char *config)
37
 {
38
-#ifdef HAVE_LIBMYSOFA
39
    struct spatializer_impl *impl;
40
    struct spa_json it2;
41
    const char *val;
42
@@ -115,14 +113,8 @@
43
        mysofa_close_cached(impl->sofa);
44
    free(impl);
45
    return NULL;
46
-#else
47
-   pw_log_error("libmysofa is required for spatializer, but disabled at compile time");
48
-   errno = EINVAL;
49
-   return NULL;
50
-#endif
51
 }
52
 
53
-#ifdef HAVE_LIBMYSOFA
54
 static int
55
 do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
56
        size_t size, void *user_data)
57
@@ -205,11 +197,9 @@
58
        convolver_free(fd->item1);
59
    return 0;
60
 }
61
-#endif
62
 
63
 static void spatializer_run(void * Instance, unsigned long SampleCount)
64
 {
65
-#ifdef HAVE_LIBMYSOFA
66
    struct spatializer_impl *impl = Instance;
67
 
68
    if (impl->interpolate) {
69
@@ -239,7 +229,6 @@
70
        convolver_run(impl->l_conv0, impl->port2, impl->port0, SampleCount);
71
        convolver_run(impl->r_conv0, impl->port2, impl->port1, SampleCount);
72
    }
73
-#endif
74
 }
75
 
76
 static void spatializer_connect_port(void * Instance, unsigned long Port,
77
@@ -261,10 +250,8 @@
78
        if (impl->r_convi)
79
            convolver_free(impl->r_convi);
80
    }
81
-#ifdef HAVE_LIBMYSOFA
82
    if (impl->sofa)
83
        mysofa_close_cached(impl->sofa);
84
-#endif
85
    free(impl->tmp0);
86
    free(impl->tmp1);
87
 
88
@@ -273,10 +260,8 @@
89
 
90
 static void spatializer_control_changed(void * Instance)
91
 {
92
-#ifdef HAVE_LIBMYSOFA
93
    pw_log_info("control changed");
94
    spatializer_reload(Instance);
95
-#endif
96
 }
97
 
98
 static void spatializer_deactivate(void * Instance)
99
@@ -361,7 +346,8 @@
100
    .make_desc = sofa_make_desc
101
 };
102
 
103
-struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
104
+SPA_EXPORT
105
+struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
106
        struct dsp_ops *dsp, const char *plugin, const char *config)
107
 {
108
    dsp_ops = dsp;
109
@@ -372,4 +358,3 @@
110
 
111
    return &builtin_plugin;
112
 }
113
-
114
pipewire-0.3.72.tar.gz/src/modules/module-jack-tunnel.c -> pipewire-0.3.74.tar.gz/src/modules/module-jack-tunnel.c Changed
18
 
1
@@ -27,7 +27,6 @@
2
 
3
 #include <pipewire/impl.h>
4
 #include <pipewire/i18n.h>
5
-#include <pipewire/private.h>
6
 
7
 #include "module-jack-tunnel/weakjack.h"
8
 
9
@@ -744,7 +743,7 @@
10
    return 0;
11
 }
12
 
13
-void module_schedule_destroy(struct impl *impl)
14
+static void module_schedule_destroy(struct impl *impl)
15
 {
16
    pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl);
17
 }
18
pipewire-0.3.72.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.74.tar.gz/src/modules/module-loopback.c Changed
181
 
1
@@ -142,6 +142,8 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
+#define DEFAULT_RATE   48000
6
+
7
 #include <stdlib.h>
8
 #include <signal.h>
9
 #include <getopt.h>
10
@@ -180,7 +182,9 @@
11
    unsigned int do_disconnect:1;
12
    unsigned int recalc_delay:1;
13
 
14
-   struct spa_audio_info_raw delay_info;
15
+   struct spa_io_position *position;
16
+   struct spa_audio_info_raw info;
17
+   uint32_t rate;
18
    float target_delay;
19
    struct spa_ringbuffer buffer;
20
    uint8_t *buffer_data;
21
@@ -196,7 +200,7 @@
22
 
23
 static void recalculate_delay(struct impl *impl)
24
 {
25
-   uint32_t target = impl->delay_info.rate * impl->target_delay, cdelay, pdelay;
26
+   uint32_t target = impl->rate * impl->target_delay, cdelay, pdelay;
27
    uint32_t delay, w;
28
    struct pw_time pwt;
29
 
30
@@ -332,36 +336,14 @@
31
    impl->recalc_delay = true;
32
 }
33
 
34
-static void stream_state_changed(void *data, enum pw_stream_state old,
35
-       enum pw_stream_state state, const char *error)
36
-{
37
-   struct impl *impl = data;
38
-   switch (state) {
39
-   case PW_STREAM_STATE_PAUSED:
40
-       pw_stream_flush(impl->playback, false);
41
-       pw_stream_flush(impl->capture, false);
42
-       impl->recalc_delay = true;
43
-       break;
44
-   case PW_STREAM_STATE_UNCONNECTED:
45
-       pw_log_info("module %p: unconnected", impl);
46
-       pw_impl_module_schedule_destroy(impl->module);
47
-       break;
48
-   case PW_STREAM_STATE_ERROR:
49
-       pw_log_info("module %p: error: %s", impl, error);
50
-       break;
51
-   default:
52
-       break;
53
-   }
54
-}
55
-
56
 static void recalculate_buffer(struct impl *impl)
57
 {
58
    if (impl->target_delay > 0.0f) {
59
-       uint32_t delay = impl->delay_info.rate * impl->target_delay;
60
+       uint32_t delay = impl->rate * impl->target_delay;
61
        void *data;
62
 
63
        impl->buffer_size = (delay + (1u<<15)) * 4;
64
-       data = realloc(impl->buffer_data, impl->buffer_size * impl->delay_info.channels);
65
+       data = realloc(impl->buffer_data, impl->buffer_size * impl->info.channels);
66
        if (data == NULL) {
67
            pw_log_warn("can't allocate delay buffer, delay disabled: %m");
68
            impl->buffer_size = 0;
69
@@ -378,6 +360,40 @@
70
    impl->recalc_delay = true;
71
 }
72
 
73
+static void stream_state_changed(void *data, enum pw_stream_state old,
74
+       enum pw_stream_state state, const char *error)
75
+{
76
+   struct impl *impl = data;
77
+   switch (state) {
78
+   case PW_STREAM_STATE_PAUSED:
79
+       pw_stream_flush(impl->playback, false);
80
+       pw_stream_flush(impl->capture, false);
81
+       impl->recalc_delay = true;
82
+       break;
83
+   case PW_STREAM_STATE_UNCONNECTED:
84
+       pw_log_info("module %p: unconnected", impl);
85
+       pw_impl_module_schedule_destroy(impl->module);
86
+       break;
87
+   case PW_STREAM_STATE_ERROR:
88
+       pw_log_info("module %p: error: %s", impl, error);
89
+       break;
90
+   case PW_STREAM_STATE_STREAMING:
91
+   {
92
+       uint32_t target = impl->info.rate;
93
+       if (target == 0)
94
+           target = impl->position ?
95
+               impl->position->clock.target_rate.denom : DEFAULT_RATE;
96
+       if (impl->rate != target) {
97
+           impl->rate = target;
98
+           recalculate_buffer(impl);
99
+       }
100
+       break;
101
+   }
102
+   default:
103
+       break;
104
+   }
105
+}
106
+
107
 static void capture_param_changed(void *data, uint32_t id, const struct spa_pod *param)
108
 {
109
    struct impl *impl = data;
110
@@ -386,17 +402,15 @@
111
    case SPA_PARAM_Format:
112
    {
113
        struct spa_audio_info_raw info;
114
-       if (param == NULL)
115
-           return;
116
-       if (spa_format_audio_raw_parse(param, &info) < 0)
117
-           return;
118
-       if (info.rate == 0 ||
119
-           info.channels == 0 ||
120
-           info.channels > SPA_AUDIO_MAX_CHANNELS)
121
-           return;
122
-
123
-       impl->delay_info = info;
124
-       recalculate_buffer(impl);
125
+       spa_zero(info);
126
+       if (param != NULL) {
127
+           if (spa_format_audio_raw_parse(param, &info) < 0 ||
128
+               info.channels == 0 ||
129
+               info.channels > SPA_AUDIO_MAX_CHANNELS)
130
+               return;
131
+       }
132
+       impl->rate = 0;
133
+       impl->info = info;
134
        break;
135
    }
136
    case SPA_PARAM_Latency:
137
@@ -405,12 +419,25 @@
138
    }
139
 }
140
 
141
+static void io_changed(void *data, uint32_t id, void *area, uint32_t size)
142
+{
143
+   struct impl *impl = data;
144
+   switch (id) {
145
+   case SPA_IO_Position:
146
+       impl->position = area;
147
+       break;
148
+   default:
149
+       break;
150
+   }
151
+}
152
+
153
 static const struct pw_stream_events in_stream_events = {
154
    PW_VERSION_STREAM_EVENTS,
155
    .destroy = capture_destroy,
156
    .process = capture_process,
157
    .state_changed = stream_state_changed,
158
    .param_changed = capture_param_changed,
159
+   .io_changed = io_changed,
160
 };
161
 
162
 static void playback_destroy(void *d)
163
@@ -436,6 +463,7 @@
164
    .process = playback_process,
165
    .state_changed = stream_state_changed,
166
    .param_changed = playback_param_changed,
167
+   .io_changed = io_changed,
168
 };
169
 
170
 static int setup_streams(struct impl *impl)
171
@@ -490,7 +518,8 @@
172
            PW_ID_ANY,
173
            PW_STREAM_FLAG_AUTOCONNECT |
174
            PW_STREAM_FLAG_MAP_BUFFERS |
175
-           PW_STREAM_FLAG_RT_PROCESS,
176
+           PW_STREAM_FLAG_RT_PROCESS |
177
+           PW_STREAM_FLAG_ASYNC,
178
            params, n_params)) < 0)
179
        return res;
180
 
181
pipewire-0.3.72.tar.gz/src/modules/module-netjack2-driver.c -> pipewire-0.3.74.tar.gz/src/modules/module-netjack2-driver.c Changed
102
 
1
@@ -31,7 +31,6 @@
2
 
3
 #include <pipewire/impl.h>
4
 #include <pipewire/i18n.h>
5
-#include <pipewire/private.h>
6
 
7
 #include "module-netjack2/packets.h"
8
 #include "module-netjack2/peer.c"
9
@@ -186,7 +185,7 @@
10
 struct impl {
11
    struct pw_context *context;
12
    struct pw_loop *main_loop;
13
-   struct pw_data_loop *data_loop;
14
+   struct pw_loop *data_loop;
15
    struct spa_system *system;
16
 
17
 #define MODE_SINK  (1<<0)
18
@@ -617,7 +616,7 @@
19
 
20
    if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
21
        pw_log_warn("error:%08x", mask);
22
-       pw_loop_update_io(impl->data_loop->loop, impl->socket, 0);
23
+       pw_loop_update_io(impl->data_loop, impl->socket, 0);
24
        return;
25
    }
26
    if (mask & SPA_IO_IN) {
27
@@ -685,20 +684,6 @@
28
    }
29
 }
30
 
31
-static int
32
-do_schedule_destroy(struct spa_loop *loop,
33
-   bool async, uint32_t seq, const void *data, size_t size, void *user_data)
34
-{
35
-   struct impl *impl = user_data;
36
-   pw_impl_module_schedule_destroy(impl->module);
37
-   return 0;
38
-}
39
-
40
-void module_schedule_destroy(struct impl *impl)
41
-{
42
-   pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl);
43
-}
44
-
45
 static int parse_address(const char *address, uint16_t port,
46
        struct sockaddr_storage *addr, socklen_t *len)
47
 {
48
@@ -903,7 +888,7 @@
49
    send(impl->socket->fd, params, sizeof(*params), 0);
50
 
51
    impl->done = true;
52
-   pw_loop_update_io(impl->data_loop->loop, impl->socket, SPA_IO_IN);
53
+   pw_loop_update_io(impl->data_loop, impl->socket, SPA_IO_IN);
54
 
55
    return 0;
56
 connect_error:
57
@@ -1027,7 +1012,7 @@
58
        goto out;
59
    }
60
 
61
-   impl->socket = pw_loop_add_io(impl->data_loop->loop, fd,
62
+   impl->socket = pw_loop_add_io(impl->data_loop, fd,
63
            0, false, on_data_io, impl);
64
    if (impl->socket == NULL) {
65
        res = -errno;
66
@@ -1049,7 +1034,7 @@
67
 
68
    impl->started = false;
69
    if (impl->socket)
70
-       pw_loop_update_io(impl->data_loop->loop, impl->socket, 0);
71
+       pw_loop_update_io(impl->data_loop, impl->socket, 0);
72
 
73
    pw_log_info("sending STOP_DRIVER");
74
    nj2_session_params_hton(&params, &impl->peer.params);
75
@@ -1071,7 +1056,7 @@
76
    update_timer(impl, 0);
77
 
78
    if (impl->socket) {
79
-       pw_loop_destroy_source(impl->data_loop->loop, impl->socket);
80
+       pw_loop_destroy_source(impl->data_loop, impl->socket);
81
        impl->socket = NULL;
82
    }
83
    if (impl->setup_socket) {
84
@@ -1228,6 +1213,7 @@
85
 {
86
    struct pw_context *context = pw_impl_module_get_context(module);
87
    struct pw_properties *props = NULL;
88
+   struct pw_data_loop *data_loop;
89
    struct impl *impl;
90
    const char *str;
91
    int res;
92
@@ -1250,7 +1236,8 @@
93
        goto error;
94
    }
95
    impl->props = props;
96
-   impl->data_loop = pw_context_get_data_loop(context);
97
+   data_loop = pw_context_get_data_loop(context);
98
+   impl->data_loop = pw_data_loop_get_loop(data_loop);
99
 
100
    impl->sink.props = pw_properties_new(NULL, NULL);
101
    impl->source.props = pw_properties_new(NULL, NULL);
102
pipewire-0.3.72.tar.gz/src/modules/module-netjack2-manager.c -> pipewire-0.3.74.tar.gz/src/modules/module-netjack2-manager.c Changed
101
 
1
@@ -32,7 +32,6 @@
2
 
3
 #include <pipewire/impl.h>
4
 #include <pipewire/i18n.h>
5
-#include <pipewire/private.h>
6
 
7
 #include "module-netjack2/packets.h"
8
 
9
@@ -224,7 +223,7 @@
10
 struct impl {
11
    struct pw_context *context;
12
    struct pw_loop *main_loop;
13
-   struct pw_data_loop *data_loop;
14
+   struct pw_loop *data_loop;
15
    struct spa_system *system;
16
 
17
 #define MODE_SINK  (1<<0)
18
@@ -340,7 +339,7 @@
19
    netjack2_send_data(&follower->peer, nframes, midi, n_midi, audio, n_audio);
20
 
21
    if (follower->socket)
22
-       pw_loop_update_io(s->impl->data_loop->loop, follower->socket, SPA_IO_IN);
23
+       pw_loop_update_io(s->impl->data_loop, follower->socket, SPA_IO_IN);
24
 }
25
 
26
 static void source_process(void *d, struct spa_io_position *position)
27
@@ -373,7 +372,7 @@
28
    pw_properties_free(follower->sink.props);
29
 
30
    if (follower->socket)
31
-       pw_loop_destroy_source(impl->data_loop->loop, follower->socket);
32
+       pw_loop_destroy_source(impl->data_loop, follower->socket);
33
    if (follower->setup_socket)
34
        pw_loop_destroy_source(impl->main_loop, follower->setup_socket);
35
 
36
@@ -460,13 +459,13 @@
37
 
38
    if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
39
        pw_log_warn("error:%08x", mask);
40
-       pw_loop_destroy_source(impl->data_loop->loop, follower->socket);
41
+       pw_loop_destroy_source(impl->data_loop, follower->socket);
42
        follower->socket = NULL;
43
        pw_loop_invoke(impl->main_loop, do_stop_follower, 1, NULL, 0, false, follower);
44
        return;
45
    }
46
    if (mask & SPA_IO_IN) {
47
-       pw_loop_update_io(impl->data_loop->loop, follower->socket, 0);
48
+       pw_loop_update_io(impl->data_loop, follower->socket, 0);
49
 
50
        pw_filter_trigger_process(follower->source.filter);
51
    }
52
@@ -730,21 +729,6 @@
53
    return res;
54
 }
55
 
56
-
57
-static int
58
-do_schedule_destroy(struct spa_loop *loop,
59
-   bool async, uint32_t seq, const void *data, size_t size, void *user_data)
60
-{
61
-   struct impl *impl = user_data;
62
-   pw_impl_module_schedule_destroy(impl->module);
63
-   return 0;
64
-}
65
-
66
-void module_schedule_destroy(struct impl *impl)
67
-{
68
-   pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl);
69
-}
70
-
71
 static int parse_address(const char *address, uint16_t port,
72
        struct sockaddr_storage *addr, socklen_t *len)
73
 {
74
@@ -1015,7 +999,7 @@
75
        goto socket_failed;
76
    }
77
 
78
-   follower->socket = pw_loop_add_io(impl->data_loop->loop, fd,
79
+   follower->socket = pw_loop_add_io(impl->data_loop, fd,
80
            0, false, on_data_io, follower);
81
    if (follower->socket == NULL) {
82
        res = -errno;
83
@@ -1269,6 +1253,7 @@
84
 {
85
    struct pw_context *context = pw_impl_module_get_context(module);
86
    struct pw_properties *props = NULL;
87
+   struct pw_data_loop *data_loop;
88
    struct impl *impl;
89
    const char *str;
90
    int res;
91
@@ -1292,7 +1277,8 @@
92
        goto error;
93
    }
94
    impl->props = props;
95
-   impl->data_loop = pw_context_get_data_loop(context);
96
+   data_loop = pw_context_get_data_loop(context);
97
+   impl->data_loop = pw_data_loop_get_loop(data_loop);
98
 
99
    impl->sink_props = pw_properties_new(NULL, NULL);
100
    impl->source_props = pw_properties_new(NULL, NULL);
101
pipewire-0.3.72.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.74.tar.gz/src/modules/module-profiler.c Changed
76
 
1
@@ -12,6 +12,7 @@
2
 
3
 #include "config.h"
4
 
5
+#include <spa/pod/builder.h>
6
 #include <spa/utils/result.h>
7
 #include <spa/utils/ringbuffer.h>
8
 #include <spa/param/profiler.h>
9
@@ -74,6 +75,7 @@
10
    struct pw_context *context;
11
    struct pw_properties *properties;
12
 
13
+   struct pw_loop *main_loop;
14
    struct pw_loop *data_loop;
15
 
16
    struct spa_hook context_listener;
17
@@ -111,7 +113,7 @@
18
         value.tv_nsec = 1;
19
    interval.tv_sec = DEFAULT_INTERVAL;
20
         interval.tv_nsec = 0;
21
-        pw_loop_update_timer(impl->context->main_loop,
22
+        pw_loop_update_timer(impl->main_loop,
23
            impl->flush_timeout, &value, &interval, false);
24
    impl->flushing = true;
25
 }
26
@@ -127,7 +129,7 @@
27
         value.tv_nsec = 0;
28
    interval.tv_sec = 0;
29
         interval.tv_nsec = 0;
30
-        pw_loop_update_timer(impl->context->main_loop,
31
+        pw_loop_update_timer(impl->main_loop,
32
            impl->flush_timeout, &value, &interval, false);
33
    impl->flushing = false;
34
 }
35
@@ -348,7 +350,7 @@
36
 
37
    pw_properties_free(impl->properties);
38
 
39
-   pw_loop_destroy_source(pw_context_get_main_loop(impl->context), impl->flush_timeout);
40
+   pw_loop_destroy_source(impl->main_loop, impl->flush_timeout);
41
 
42
    free(impl);
43
 }
44
@@ -380,7 +382,6 @@
45
    struct pw_context *context = pw_impl_module_get_context(module);
46
    struct pw_properties *props;
47
    struct impl *impl;
48
-   struct pw_loop *main_loop = pw_context_get_main_loop(context);
49
    static const char * const keys = {
50
        PW_KEY_OBJECT_SERIAL,
51
        NULL
52
@@ -403,7 +404,8 @@
53
 
54
    impl->context = context;
55
    impl->properties = props;
56
-   impl->data_loop = pw_context_get_data_loop(impl->context)->loop;
57
+   impl->main_loop = pw_context_get_main_loop(impl->context);
58
+   impl->data_loop = pw_data_loop_get_loop(pw_context_get_data_loop(impl->context));
59
 
60
    spa_ringbuffer_init(&impl->buffer);
61
 
62
@@ -416,11 +418,11 @@
63
        free(impl);
64
        return -errno;
65
    }
66
-   pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", impl->global->id);
67
+   pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", pw_global_get_id(impl->global));
68
    pw_properties_setf(impl->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64,
69
            pw_global_get_serial(impl->global));
70
 
71
-   impl->flush_timeout = pw_loop_add_timer(main_loop, flush_timeout, impl);
72
+   impl->flush_timeout = pw_loop_add_timer(impl->main_loop, flush_timeout, impl);
73
 
74
    pw_global_update_keys(impl->global, &impl->properties->dict, keys);
75
 
76
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native.c Changed
44
 
1
@@ -23,6 +23,8 @@
2
 #endif
3
 
4
 #include <spa/pod/iter.h>
5
+#include <spa/pod/parser.h>
6
+#include <spa/pod/builder.h>
7
 #include <spa/utils/result.h>
8
 #include <spa/utils/string.h>
9
 
10
@@ -1465,6 +1467,7 @@
11
 {
12
    struct pw_context *context = pw_impl_module_get_context(module);
13
    struct pw_protocol *this;
14
+   struct pw_impl_core *core = context->core;
15
    struct protocol_data *d;
16
    const struct pw_properties *props;
17
    int res;
18
@@ -1472,8 +1475,10 @@
19
    PW_LOG_TOPIC_INIT(mod_topic);
20
    PW_LOG_TOPIC_INIT(mod_topic_connection);
21
 
22
-   if (pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native) != NULL)
23
-       return 0;
24
+   if (pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native) != NULL) {
25
+       pw_log_error("protocol %s is already loaded", PW_TYPE_INFO_PROTOCOL_Native);
26
+       return -EEXIST;
27
+   }
28
 
29
    this = pw_protocol_new(context, PW_TYPE_INFO_PROTOCOL_Native, sizeof(struct protocol_data));
30
    if (this == NULL)
31
@@ -1494,10 +1499,10 @@
32
    d->module = module;
33
 
34
    props = pw_context_get_properties(context);
35
-   d->local = create_server(this, context->core, &props->dict);
36
+   d->local = create_server(this, core, &props->dict);
37
 
38
    if (need_server(context, &props->dict)) {
39
-       if (impl_add_server(this, context->core, &props->dict) == NULL) {
40
+       if (impl_add_server(this, core, &props->dict) == NULL) {
41
            res = -errno;
42
            goto error_cleanup;
43
        }
44
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/defs.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/defs.h Changed
11
 
1
@@ -27,3 +27,9 @@
2
        return NULL;
3
    return pod;
4
 }
5
+
6
+struct protocol_compat_v2 {
7
+   /* v2 typemap */
8
+   struct pw_map types;
9
+   unsigned int send_types:1;
10
+};
11
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/protocol-footer.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/protocol-footer.c Changed
19
 
1
@@ -89,7 +89,7 @@
2
    end_footer(&fb);
3
 }
4
 
5
-int demarshal_core_generation(void *object, struct spa_pod_parser *parser)
6
+static int demarshal_core_generation(void *object, struct spa_pod_parser *parser)
7
 {
8
    struct pw_core *core = object;
9
    int64_t generation;
10
@@ -106,7 +106,7 @@
11
    return 0;
12
 }
13
 
14
-int demarshal_client_generation(void *object, struct spa_pod_parser *parser)
15
+static int demarshal_client_generation(void *object, struct spa_pod_parser *parser)
16
 {
17
    struct pw_impl_client *client = object;
18
    int64_t generation;
19
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/v0/protocol-native.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/v0/protocol-native.c Changed
9
 
1
@@ -22,6 +22,7 @@
2
 #include "interfaces.h"
3
 #include "typemap.h"
4
 
5
+#include "../defs.h"
6
 #include "../connection.h"
7
 
8
 PW_LOG_TOPIC_EXTERN(mod_topic);
9
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/v0/typemap.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/v0/typemap.h Changed
15
 
1
@@ -1,3 +1,13 @@
2
+enum spa_node0_event {
3
+   SPA_NODE0_EVENT_START   = SPA_TYPE_VENDOR_PipeWire,
4
+   SPA_NODE0_EVENT_RequestClockUpdate,
5
+};
6
+
7
+enum spa_node0_command {
8
+   SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire,
9
+   SPA_NODE0_COMMAND_ClockUpdate,
10
+};
11
+
12
 static const struct type_info {
13
    const char *type;
14
    const char *name;
15
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse.c Changed
34
 
1
@@ -194,6 +194,32 @@
2
  * VMs usually can't support the low latency settings that are possible on real
3
  * hardware.
4
  *
5
+ * ### Quirk options
6
+ *
7
+ *\code{.unparsed}
8
+ *     pulse.fix.format = "S16LE"
9
+ *\endcode
10
+ *
11
+ * When a stream uses the FIX_FORMAT flag, fixate the format to this value.
12
+ * Normally the format would be fixed to the sink/source that the stream connects
13
+ * to. When an invalid format (null or "") is set, the FIX_FORMAT flag is ignored.
14
+ *
15
+ *\code{.unparsed}
16
+ *     pulse.fix.rate = 48000
17
+ *\endcode
18
+ *
19
+ * When a stream uses the FIX_RATE flag, fixate the sample rate to this value.
20
+ * Normally the rate would be fixed to the sink/source that the stream connects
21
+ * to. When a 0 rate is set, the FIX_RATE flag is ignored.
22
+ *
23
+ *\code{.unparsed}
24
+ *     pulse.fix.position = " FL FR "
25
+ *\endcode
26
+ *
27
+ * When a stream uses the FIX_CHANNELS flag, fixate the channels to this value.
28
+ * Normally the channels would be fixed to the sink/source that the stream connects
29
+ * to. When an invalid position (null or "") is set, the FIX_CHANNELS flag is ignored.
30
+ *
31
  * ## Command execution
32
  *
33
  * As part of the server startup sequence, a set of commands can be executed.
34
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/cmd.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/cmd.c Changed
38
 
1
@@ -4,6 +4,7 @@
2
 
3
 #include <spa/utils/json.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/utils.h>
7
 
8
 #include "module.h"
9
@@ -68,15 +69,14 @@
10
 {
11
    struct impl *impl = user_data;
12
    struct spa_json it3;
13
-   char key512, *s;
14
+   char key512;
15
    int res = 0;
16
 
17
-   s = strndup(str, len);
18
+   spa_autofree char *s = strndup(str, len);
19
    spa_json_init(&it0, s, len);
20
    if (spa_json_enter_array(&it0, &it1) < 0) {
21
        pw_log_error("config file error: pulse.cmd is not an array");
22
-       res = -EINVAL;
23
-       goto exit;
24
+       return -EINVAL;
25
    }
26
 
27
    while (spa_json_enter_object(&it1, &it2) > 0) {
28
@@ -107,8 +107,7 @@
29
        if (res < 0)
30
            break;
31
    }
32
-exit:
33
-   free(s);
34
+
35
    return res;
36
 }
37
 
38
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c Changed
16
 
1
@@ -10,10 +10,14 @@
2
 #include <stdlib.h>
3
 #include <string.h>
4
 
5
+#include <spa/pod/builder.h>
6
 #include <spa/utils/defs.h>
7
 #include <spa/utils/dict.h>
8
 #include <spa/utils/string.h>
9
 #include <spa/utils/json.h>
10
+#include <spa/param/audio/format.h>
11
+#include <spa/param/props.h>
12
+
13
 #include <pipewire/log.h>
14
 #include <pipewire/properties.h>
15
 
16
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/format.c Changed
51
 
1
@@ -243,24 +243,34 @@
2
 {
3
    const char *str;
4
    if (fix_ss->format != 0) {
5
-       if ((str = spa_dict_lookup(props, "pulse.fix.format")) != NULL)
6
-           ss->format = format_name2id(str);
7
+       if ((str = spa_dict_lookup(props, "pulse.fix.format")) != NULL) {
8
+           uint32_t val = format_name2id(str);
9
+           if (val != SPA_AUDIO_FORMAT_UNKNOWN)
10
+               ss->format = val;
11
+       }
12
        else
13
            ss->format = fix_ss->format;
14
        /* convert back and forth to convert potential planar to packed */
15
        ss->format = format_pa2id(format_id2pa(ss->format));
16
    }
17
    if (fix_ss->rate != 0) {
18
-       if ((str = spa_dict_lookup(props, "pulse.fix.rate")) != NULL)
19
-           ss->rate = atoi(str);
20
+       if ((str = spa_dict_lookup(props, "pulse.fix.rate")) != NULL) {
21
+           uint32_t val = atoi(str);
22
+           if (val != 0)
23
+               ss->rate = val;
24
+       }
25
        else
26
            ss->rate = fix_ss->rate;
27
        ss->rate = SPA_CLAMP(ss->rate, 0u, RATE_MAX);
28
    }
29
    if (fix_ss->channels != 0) {
30
        if ((str = spa_dict_lookup(props, "pulse.fix.position")) != NULL) {
31
-           channel_map_parse_position(str, map);
32
-           ss->channels = map->channels;
33
+           struct channel_map val;
34
+           channel_map_parse_position(str, &val);
35
+           if (val.channels > 0) {
36
+               ss->channels = val.channels;
37
+               *map = val;
38
+           }
39
        } else {
40
            ss->channels = fix_ss->channels;
41
            *map = *fix_map;
42
@@ -519,6 +529,8 @@
43
            if (ss != NULL)
44
                *ss = *def_ss;
45
        } else {
46
+           if (info.info.raw.rate == 0)
47
+               info.info.raw.rate = 48000;
48
            if (info.info.raw.format == 0 ||
49
                info.info.raw.rate == 0 ||
50
                info.info.raw.channels == 0 ||
51
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/format.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/format.h Changed
10
 
1
@@ -214,8 +214,6 @@
2
 const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id,
3
        const struct format_info *info, uint32_t *rate);
4
 
5
-int format_info_from_spec(struct format_info *info, const struct sample_spec *ss,
6
-       const struct channel_map *map);
7
 int format_info_to_spec(const struct format_info *info, struct sample_spec *ss,
8
        struct channel_map *map);
9
 
10
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/internal.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/internal.h Changed
24
 
1
@@ -10,10 +10,11 @@
2
 #include <stdbool.h>
3
 #include <stdint.h>
4
 
5
+#include <spa/utils/result.h>
6
 #include <spa/utils/defs.h>
7
+#include <spa/utils/ratelimit.h>
8
 #include <spa/utils/ringbuffer.h>
9
-#include <pipewire/map.h>
10
-#include <pipewire/private.h>
11
+#include <pipewire/impl.h>
12
 
13
 #include "format.h"
14
 #include "server.h"
15
@@ -52,7 +53,7 @@
16
    struct pw_properties *props;
17
    void *dbus_name;
18
 
19
-   struct ratelimit rate_limit;
20
+   struct spa_ratelimit rate_limit;
21
 
22
    struct spa_hook_list hooks;
23
    struct spa_list servers;
24
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/module.c Changed
27
 
1
@@ -11,6 +11,7 @@
2
 #include <spa/utils/list.h>
3
 #include <spa/utils/hook.h>
4
 #include <spa/utils/string.h>
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/log.h>
7
 #include <pipewire/map.h>
8
 #include <pipewire/properties.h>
9
@@ -117,7 +118,8 @@
10
 /** utils */
11
 void module_args_add_props(struct pw_properties *props, const char *str)
12
 {
13
-   char *s = strdup(str), *p = s, *e, f;
14
+   spa_autofree char *s = strdup(str);
15
+   char *p = s, *e, f;
16
    const char *k, *v;
17
    const struct str_map *map;
18
 
19
@@ -160,7 +162,6 @@
20
        }
21
        pw_properties_set(props, k, v);
22
    }
23
-   free(s);
24
 }
25
 
26
 int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props,
27
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c Changed
18
 
1
@@ -56,8 +56,6 @@
2
 
3
    struct spa_source *sinks_timeout;
4
 
5
-   struct spa_audio_info_raw info;
6
-
7
    unsigned int sinks_pending;
8
    unsigned int load_emitted:1;
9
    unsigned int start_error:1;
10
@@ -304,7 +302,6 @@
11
    audioinfo_to_properties(&info, global_props);
12
 
13
    d->module = module;
14
-   d->info = info;
15
    d->sink_names = sink_names;
16
    d->sinks_pending = (sink_names == NULL) ? 0 : num_sinks;
17
    d->stream_props = stream_props;
18
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c Changed
50
 
1
@@ -19,6 +19,8 @@
2
 
3
    struct spa_hook mod_listener;
4
    struct pw_impl_module *mod;
5
+
6
+   uint32_t latency_msec;
7
 };
8
 
9
 static void module_destroy(void *data)
10
@@ -37,10 +39,25 @@
11
 static int module_raop_discover_load(struct module *module)
12
 {
13
    struct module_raop_discover_data *data = module->user_data;
14
+   FILE *f;
15
+   char *args;
16
+   size_t size;
17
+
18
+   if ((f = open_memstream(&args, &size)) == NULL)
19
+       return -errno;
20
+
21
+   fprintf(f, "{");
22
+   if (data->latency_msec > 0)
23
+       fprintf(f, " raop.latency.ms = %u ", data->latency_msec);
24
+   fprintf(f, "}");
25
+   fclose(f);
26
 
27
    data->mod = pw_context_load_module(module->impl->context,
28
            "libpipewire-module-raop-discover",
29
-           NULL, NULL);
30
+           args, NULL);
31
+
32
+   free(args);
33
+
34
    if (data->mod == NULL)
35
        return -errno;
36
 
37
@@ -75,9 +92,12 @@
38
 {
39
    PW_LOG_TOPIC_INIT(mod_topic);
40
 
41
+   struct pw_properties * const props = module->props;
42
    struct module_raop_discover_data * const data = module->user_data;
43
    data->module = module;
44
 
45
+   pw_properties_fetch_uint32(props, "latency_msec", &data->latency_msec);
46
+
47
    return 0;
48
 }
49
 
50
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
417
 
1
@@ -28,6 +28,7 @@
2
 #include <spa/utils/ringbuffer.h>
3
 #include <spa/utils/json.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/pipewire.h>
7
 #include <pipewire/extensions/metadata.h>
8
 
9
@@ -1564,7 +1565,7 @@
10
    int res;
11
    struct sample_spec ss, fix_ss;
12
    struct channel_map map, fix_map;
13
-   uint32_t sink_index, syncid, rate = 0;
14
+   uint32_t sink_index, syncid, ss_rate = 0, rate = 0;
15
    const char *sink_name;
16
    struct buffer_attr attr = { 0 };
17
    bool corked = false,
18
@@ -1712,7 +1713,7 @@
19
                    n_params++;
20
                    n_valid_formats++;
21
                    if (r > rate)
22
-                       rate = r;
23
+                       ss_rate = rate = r;
24
                } else {
25
                    log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
26
                }
27
@@ -1724,9 +1725,9 @@
28
        struct sample_spec sfix = ss;
29
        struct channel_map mfix = map;
30
 
31
-       rate = ss.rate;
32
-
33
+       ss_rate = ss.rate;
34
        sample_spec_fix(&sfix, &mfix, &fix_ss, &fix_map, &props->dict);
35
+       rate = sfix.rate;
36
 
37
        if (n_params < MAX_FORMATS &&
38
            (paramsn_params = format_build_param(&b,
39
@@ -1736,8 +1737,8 @@
40
            n_valid_formats++;
41
        } else {
42
            pw_log_warn("%p: unsupported format:%s rate:%d channels:%u",
43
-                   impl, format_id2name(ss.format), ss.rate,
44
-                   ss.channels);
45
+                   impl, format_id2name(sfix.format), sfix.rate,
46
+                   sfix.channels);
47
        }
48
    }
49
 
50
@@ -1763,7 +1764,7 @@
51
 
52
    if (rate != 0) {
53
        struct spa_fraction lat;
54
-       fix_playback_buffer_attr(stream, &attr, rate, &lat);
55
+       fix_playback_buffer_attr(stream, &attr, ss_rate, &lat);
56
        pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
57
        pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u",
58
                lat.num, lat.denom);
59
@@ -1860,7 +1861,7 @@
60
    struct pw_properties *props = NULL;
61
    uint8_t n_formats = 0;
62
    struct stream *stream = NULL;
63
-   uint32_t n_params = 0, n_valid_formats = 0, flags, id, rate = 0;
64
+   uint32_t n_params = 0, n_valid_formats = 0, flags, id, ss_rate = 0, rate = 0;
65
    const struct spa_pod *paramsMAX_FORMATS;
66
    uint8_t buffer4096;
67
    struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
68
@@ -1966,7 +1967,7 @@
69
                    n_params++;
70
                    n_valid_formats++;
71
                    if (r > rate)
72
-                       rate = r;
73
+                       ss_rate = rate = r;
74
                } else {
75
                    log_format_info(impl, SPA_LOG_LEVEL_WARN, &format);
76
                }
77
@@ -1989,9 +1990,9 @@
78
        struct sample_spec sfix = ss;
79
        struct channel_map mfix = map;
80
 
81
-       rate = ss.rate;
82
-
83
+       ss_rate = ss.rate;
84
        sample_spec_fix(&sfix, &mfix, &fix_ss, &fix_map, &props->dict);
85
+       rate = sfix.rate;
86
 
87
        if (n_params < MAX_FORMATS &&
88
            (paramsn_params = format_build_param(&b,
89
@@ -2001,8 +2002,8 @@
90
            n_valid_formats++;
91
        } else {
92
            pw_log_warn("%p: unsupported format:%s rate:%d channels:%u",
93
-                   impl, format_id2name(ss.format), ss.rate,
94
-                   ss.channels);
95
+                   impl, format_id2name(sfix.format), sfix.rate,
96
+                   sfix.channels);
97
        }
98
    }
99
    if (m->offset != m->length)
100
@@ -2028,7 +2029,7 @@
101
 
102
    if (rate != 0) {
103
        struct spa_fraction lat;
104
-       fix_record_buffer_attr(stream, &attr, rate, &lat);
105
+       fix_record_buffer_attr(stream, &attr, ss_rate, &lat);
106
        pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
107
        pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u",
108
                lat.num, lat.denom);
109
@@ -2516,12 +2517,12 @@
110
    uint32_t sink_index, volume;
111
    struct sample *sample;
112
    const char *sink_name, *name;
113
-   struct pw_properties *props = NULL;
114
+   spa_autoptr(pw_properties) props = NULL;
115
    struct pw_manager_object *o;
116
    int res;
117
 
118
    if ((props = pw_properties_new(NULL, NULL)) == NULL)
119
-       goto error_errno;
120
+       return -errno;
121
 
122
    if ((res = message_get(m,
123
            TAG_U32, &sink_index,
124
@@ -2529,13 +2530,13 @@
125
            TAG_U32, &volume,
126
            TAG_STRING, &name,
127
            TAG_INVALID)) < 0)
128
-       goto error_proto;
129
+       return -EPROTO;
130
 
131
    if (client->version >= 13) {
132
        if ((res = message_get(m,
133
                TAG_PROPLIST, props,
134
                TAG_INVALID)) < 0)
135
-           goto error_proto;
136
+           return -EPROTO;
137
 
138
    }
139
    pw_log_info("%s %s tag:%u sink_index:%u sink_name:%s name:%s",
140
@@ -2545,35 +2546,19 @@
141
    pw_properties_update(props, &client->props->dict);
142
 
143
    if (sink_index != SPA_ID_INVALID && sink_name != NULL)
144
-       goto error_inval;
145
+       return -EINVAL;
146
 
147
    o = find_device(client, sink_index, sink_name, PW_DIRECTION_OUTPUT, NULL);
148
    if (o == NULL)
149
-       goto error_noent;
150
+       return -ENOENT;
151
 
152
    sample = find_sample(impl, SPA_ID_INVALID, name);
153
    if (sample == NULL)
154
-       goto error_noent;
155
+       return -ENOENT;
156
 
157
    pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%"PRIu64, o->serial);
158
 
159
-   return pending_sample_new(client, sample, props, tag);
160
-
161
-error_errno:
162
-   res = -errno;
163
-   goto error;
164
-error_proto:
165
-   res = -EPROTO;
166
-   goto error;
167
-error_inval:
168
-   res = -EINVAL;
169
-   goto error;
170
-error_noent:
171
-   res = -ENOENT;
172
-   goto error;
173
-error:
174
-   pw_properties_free(props);
175
-   return res;
176
+   return pending_sample_new(client, sample, spa_steal_ptr(props), tag);
177
 }
178
 
179
 static int do_remove_sample(struct client *client, uint32_t command, uint32_t tag, struct message *m)
180
@@ -3184,11 +3169,8 @@
181
 static int do_update_proplist(struct client *client, uint32_t command, uint32_t tag, struct message *m)
182
 {
183
    uint32_t channel, mode;
184
-   struct stream *stream;
185
-   struct pw_properties *props;
186
-   int res;
187
 
188
-   props = pw_properties_new(NULL, NULL);
189
+   spa_autoptr(pw_properties) props = pw_properties_new(NULL, NULL);
190
    if (props == NULL)
191
        return -errno;
192
 
193
@@ -3196,7 +3178,7 @@
194
        if (message_get(m,
195
                TAG_U32, &channel,
196
                TAG_INVALID) < 0)
197
-           goto error_protocol;
198
+           return -EPROTO;
199
    } else {
200
        channel = SPA_ID_INVALID;
201
    }
202
@@ -3208,12 +3190,12 @@
203
            TAG_U32, &mode,
204
            TAG_PROPLIST, props,
205
            TAG_INVALID) < 0)
206
-       goto error_protocol;
207
+       return -EPROTO;
208
 
209
    if (command != COMMAND_UPDATE_CLIENT_PROPLIST) {
210
-       stream = pw_map_lookup(&client->streams, channel);
211
+       struct stream *stream = pw_map_lookup(&client->streams, channel);
212
        if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD)
213
-           goto error_noentity;
214
+           return -ENOENT;
215
 
216
        pw_stream_update_properties(stream->stream, &props->dict);
217
    } else {
218
@@ -3223,29 +3205,17 @@
219
            pw_core_update_properties(client->core, &client->props->dict);
220
        }
221
    }
222
-   res = reply_simple_ack(client, tag);
223
-exit:
224
-   pw_properties_free(props);
225
-   return res;
226
 
227
-error_protocol:
228
-   res = -EPROTO;
229
-   goto exit;
230
-error_noentity:
231
-   res = -ENOENT;
232
-   goto exit;
233
+   return reply_simple_ack(client, tag);
234
 }
235
 
236
 static int do_remove_proplist(struct client *client, uint32_t command, uint32_t tag, struct message *m)
237
 {
238
    uint32_t i, channel;
239
-   struct stream *stream;
240
-   struct pw_properties *props;
241
    struct spa_dict dict;
242
    struct spa_dict_item *items;
243
-   int res;
244
 
245
-   props = pw_properties_new(NULL, NULL);
246
+   spa_autoptr(pw_properties) props = pw_properties_new(NULL, NULL);
247
    if (props == NULL)
248
        return -errno;
249
 
250
@@ -3253,7 +3223,7 @@
251
        if (message_get(m,
252
                TAG_U32, &channel,
253
                TAG_INVALID) < 0)
254
-           goto error_protocol;
255
+           return -EPROTO;
256
    } else {
257
        channel = SPA_ID_INVALID;
258
    }
259
@@ -3267,7 +3237,7 @@
260
        if (message_get(m,
261
                TAG_STRING, &key,
262
                TAG_INVALID) < 0)
263
-           goto error_protocol;
264
+           return -EPROTO;
265
        if (key == NULL)
266
            break;
267
        pw_properties_set(props, key, key);
268
@@ -3280,26 +3250,17 @@
269
        itemsi.value = NULL;
270
    }
271
 
272
-   if (command != COMMAND_UPDATE_CLIENT_PROPLIST) {
273
-       stream = pw_map_lookup(&client->streams, channel);
274
+   if (command != COMMAND_REMOVE_CLIENT_PROPLIST) {
275
+       struct stream *stream = pw_map_lookup(&client->streams, channel);
276
        if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD)
277
-           goto error_noentity;
278
+           return -ENOENT;
279
 
280
        pw_stream_update_properties(stream->stream, &dict);
281
    } else {
282
        pw_core_update_properties(client->core, &dict);
283
    }
284
-   res = reply_simple_ack(client, tag);
285
-exit:
286
-   pw_properties_free(props);
287
-   return res;
288
 
289
-error_protocol:
290
-   res = -EPROTO;
291
-   goto exit;
292
-error_noentity:
293
-   res = -ENOENT;
294
-   goto exit;
295
+   return reply_simple_ack(client, tag);
296
 }
297
 
298
 
299
@@ -3529,10 +3490,11 @@
300
 {
301
    struct pw_manager *manager = client->manager;
302
    struct pw_device_info *info = o->info;
303
-   const char *str, *drv_name;
304
+   const char *str, *drv_name, *card_name;
305
    uint32_t module_id = SPA_ID_INVALID, n_profiles, n;
306
    struct card_info card_info = CARD_INFO_INIT;
307
    struct profile_info *profile_info;
308
+   char name128;
309
 
310
    if (!pw_manager_object_is_card(o) || info == NULL || info->props == NULL)
311
        return -ENOENT;
312
@@ -3544,9 +3506,17 @@
313
    if (drv_name && spa_streq("bluez5", drv_name))
314
        drv_name = "module-bluez5-device.c"; /* blueman needs this */
315
 
316
+   card_name = spa_dict_lookup(info->props, PW_KEY_DEVICE_NAME);
317
+   if (card_name == NULL)
318
+       card_name = spa_dict_lookup(info->props, "api.alsa.card.name");
319
+   if (card_name == NULL) {
320
+       snprintf(name, sizeof(name), "card_%u", o->index);
321
+       card_name = name;
322
+   }
323
+
324
    message_put(m,
325
        TAG_U32, o->index,          /* card index */
326
-       TAG_STRING, spa_dict_lookup(info->props, PW_KEY_DEVICE_NAME),
327
+       TAG_STRING, card_name,
328
        TAG_U32, id_to_index(manager, module_id),
329
        TAG_STRING, drv_name,
330
        TAG_INVALID);
331
@@ -3663,7 +3633,7 @@
332
        const struct pw_manager_object *card)
333
 {
334
    struct pw_device_info *card_info = card ? card->info : NULL;
335
-   struct pw_properties *props = NULL;
336
+   spa_autoptr(pw_properties) props = NULL;
337
 
338
    if (card_info && card_info->props) {
339
        props = pw_properties_new_dict(sink_props);
340
@@ -3673,9 +3643,8 @@
341
        pw_properties_add(props, card_info->props);
342
        sink_props = &props->dict;
343
    }
344
-   message_put(m, TAG_PROPLIST, sink_props, TAG_INVALID);
345
 
346
-   pw_properties_free(props);
347
+   message_put(m, TAG_PROPLIST, sink_props, TAG_INVALID);
348
 
349
    return 0;
350
 }
351
@@ -3873,7 +3842,7 @@
352
        const struct pw_manager_object *card, const bool is_monitor)
353
 {
354
    struct pw_device_info *card_info = card ? card->info : NULL;
355
-   struct pw_properties *props = NULL;
356
+   spa_autoptr(pw_properties) props = NULL;
357
 
358
    if ((card_info && card_info->props) || is_monitor) {
359
        props = pw_properties_new_dict(source_props);
360
@@ -3888,9 +3857,8 @@
361
 
362
        source_props = &props->dict;
363
    }
364
-   message_put(m, TAG_PROPLIST, source_props, TAG_INVALID);
365
 
366
-   pw_properties_free(props);
367
+   message_put(m, TAG_PROPLIST, source_props, TAG_INVALID);
368
 
369
    return 0;
370
 }
371
@@ -5131,12 +5099,9 @@
372
    const char *object_path = NULL;
373
    const char *message = NULL;
374
    const char *params = NULL;
375
-   char *response = NULL;
376
-   char *path = NULL;
377
    struct message *reply;
378
    struct pw_manager_object *o;
379
    int len = 0;
380
-   int res;
381
 
382
    if (message_get(m,
383
            TAG_STRING, &object_path,
384
@@ -5155,11 +5120,13 @@
385
    len = strlen(object_path);
386
    if (len > 0 && object_pathlen - 1 == '/')
387
        --len;
388
-   path = strndup(object_path, len);
389
+
390
+   spa_autofree char *path = strndup(object_path, len);
391
    if (path == NULL)
392
        return -ENOMEM;
393
 
394
-   res = -ENOENT;
395
+   spa_autofree char *response = NULL;
396
+   int res = -ENOENT;
397
 
398
    spa_list_for_each(o, &manager->object_list, link) {
399
        if (o->message_object_path && spa_streq(o->message_object_path, path)) {
400
@@ -5171,7 +5138,6 @@
401
        }
402
    }
403
 
404
-   free(path);
405
    if (res < 0)
406
        return res;
407
 
408
@@ -5179,7 +5145,7 @@
409
 
410
    reply = reply_new(client, tag);
411
    message_put(reply, TAG_STRING, response, TAG_INVALID);
412
-   free(response);
413
+
414
    return client_queue_message(client, reply);
415
 }
416
 
417
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/reply.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/reply.c Changed
9
 
1
@@ -12,6 +12,7 @@
2
 #include "commands.h"
3
 #include "message.h"
4
 #include "log.h"
5
+#include "reply.h"
6
 
7
 struct message *reply_new(const struct client *client, uint32_t tag)
8
 {
9
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/server.c Changed
27
 
1
@@ -28,6 +28,7 @@
2
 #include <spa/utils/defs.h>
3
 #include <spa/utils/json.h>
4
 #include <spa/utils/result.h>
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/pipewire.h>
7
 
8
 #include "client.h"
9
@@ -404,7 +405,7 @@
10
        client_access = server->client_access;
11
 
12
    if (server->addr.ss_family == AF_UNIX) {
13
-       char *app_id = NULL, *devices = NULL;
14
+       spa_autofree char *app_id = NULL, *devices = NULL;
15
 
16
 #ifdef SO_PRIORITY
17
        val = 6;
18
@@ -443,8 +444,6 @@
19
            else
20
                pw_properties_set(client->props, PW_KEY_MEDIA_CATEGORY, NULL);
21
        }
22
-       free(devices);
23
-       free(app_id);
24
    }
25
    else if (server->addr.ss_family == AF_INET || server->addr.ss_family == AF_INET6) {
26
 
27
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/stream.c Changed
16
 
1
@@ -216,10 +216,11 @@
2
    struct client *client = stream->client;
3
    struct impl *impl = client->impl;
4
    struct message *reply;
5
+   int missed;
6
 
7
-   if (ratelimit_test(&impl->rate_limit, stream->timestamp, SPA_LOG_LEVEL_INFO)) {
8
-       pw_log_info("%s: UNDERFLOW channel:%u offset:%" PRIi64,
9
-               client->name, stream->channel, offset);
10
+   if ((missed = spa_ratelimit_test(&impl->rate_limit, stream->timestamp)) >= 0) {
11
+       pw_log_info("%s: UNDERFLOW channel:%u offset:%" PRIi64" (%d missed)",
12
+               client->name, stream->channel, offset, missed);
13
    }
14
 
15
    reply = message_alloc(impl, -1, 0);
16
pipewire-0.3.72.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.74.tar.gz/src/modules/module-pulse-tunnel.c Changed
62
 
1
@@ -21,6 +21,7 @@
2
 #include <spa/utils/json.h>
3
 #include <spa/utils/ringbuffer.h>
4
 #include <spa/utils/dll.h>
5
+#include <spa/utils/ratelimit.h>
6
 #include <spa/debug/types.h>
7
 #include <spa/pod/builder.h>
8
 #include <spa/param/audio/format-utils.h>
9
@@ -29,7 +30,6 @@
10
 
11
 #include <pipewire/impl.h>
12
 #include <pipewire/i18n.h>
13
-#include <pipewire/private.h>
14
 
15
 #include <pulse/pulseaudio.h>
16
 #include "module-protocol-pulse/defs.h"
17
@@ -170,7 +170,7 @@
18
    pa_stream *pa_stream;
19
    uint32_t pa_index;
20
 
21
-   struct ratelimit rate_limit;
22
+   struct spa_ratelimit rate_limit;
23
 
24
    uint32_t target_latency;
25
    uint32_t current_latency;
26
@@ -506,7 +506,7 @@
27
    return 0;
28
 }
29
 
30
-void module_schedule_destroy(struct impl *impl)
31
+static void module_schedule_destroy(struct impl *impl)
32
 {
33
    pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl);
34
 }
35
@@ -669,19 +669,22 @@
36
 {
37
    struct impl *impl = userdata;
38
    struct timespec ts;
39
+   int missed;
40
 
41
    clock_gettime(CLOCK_MONOTONIC, &ts);
42
-   if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN))
43
-       pw_log_warn("underflow");
44
+   if ((missed = spa_ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts))) >= 0)
45
+       pw_log_warn("underflow (%d missed)", missed);
46
    impl->resync = true;
47
 }
48
 static void stream_overflow_cb(pa_stream *s, void *userdata)
49
 {
50
    struct impl *impl = userdata;
51
    struct timespec ts;
52
+   int missed;
53
+
54
    clock_gettime(CLOCK_MONOTONIC, &ts);
55
-   if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN))
56
-       pw_log_warn("overflow");
57
+   if ((missed = spa_ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts))) >= 0)
58
+       pw_log_warn("overflow (%d missed)", missed);
59
    impl->resync = true;
60
 }
61
 
62
pipewire-0.3.72.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.74.tar.gz/src/modules/module-raop-discover.c Changed
28
 
1
@@ -41,6 +41,8 @@
2
  *
3
  * Options specific to the behavior of this module
4
  *
5
+ * - `raop.latency.ms` = latency for all streams in microseconds. This
6
+ *    can be overwritten in the stream rules.
7
  * - `stream.rules` = <rules>: match rules, use create-stream actions. See
8
  *   \ref page_module_raop_sink for module properties.
9
  *
10
@@ -50,6 +52,7 @@
11
  * context.modules = 
12
  * {   name = libpipewire-raop-discover
13
  *     args = {
14
+ *         #raop.latency.ms = 1000
15
  *         stream.rules = 
16
  *             {   matches = 
17
  *                     {    raop.ip = "~.*"
18
@@ -410,6 +413,9 @@
19
        avahi_free(value);
20
    }
21
 
22
+   if ((str = pw_properties_get(impl->properties, "raop.latency.ms")) != NULL)
23
+       pw_properties_set(props, "raop.latency.ms", str);
24
+
25
    if ((str = pw_properties_get(impl->properties, "stream.rules")) == NULL)
26
        str = DEFAULT_CREATE_RULES;
27
    if (str != NULL) {
28
pipewire-0.3.72.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.74.tar.gz/src/modules/module-raop-sink.c Changed
154
 
1
@@ -39,6 +39,7 @@
2
 #include <spa/param/audio/raw.h>
3
 #include <spa/param/latency-utils.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/impl.h>
7
 #include <pipewire/i18n.h>
8
 
9
@@ -317,7 +318,7 @@
10
        pkt0 |= htonl(0x10000000);
11
    pkt1 = htonl(rtptime - latency);
12
    transmitted = ntp_now();
13
-   pkt2 = htonl(transmitted >> 32);
14
+   pkt2 = htonl((transmitted >> 32) & 0x0000ffff);
15
    pkt3 = htonl(transmitted & 0xffffffff);
16
    pkt4 = htonl(rtptime);
17
 
18
@@ -972,6 +973,7 @@
19
    size_t len;
20
    uint64_t ntp;
21
    uint16_t control_port, timing_port;
22
+   int res;
23
 
24
    pw_log_info("reply %d", status);
25
 
26
@@ -1003,9 +1005,9 @@
27
        return 0;
28
    }
29
 
30
-   if (pw_getrandom(&impl->seq, sizeof(impl->seq), 0) < 0 ||
31
-       pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0) <  0) {
32
-       pw_log_error("error generating random seq and rtptime: %m");
33
+   if ((res = pw_getrandom(&impl->seq, sizeof(impl->seq), 0)) < 0 ||
34
+       (res = pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0)) <  0) {
35
+       pw_log_error("error generating random seq and rtptime: %s", spa_strerror(res));
36
        return 0;
37
    }
38
 
39
@@ -1210,7 +1212,7 @@
40
    char key512*2;
41
    char iv16*2;
42
    int res, frames, rsa_len, ip_version;
43
-   char *sdp;
44
+   spa_autofree char *sdp = NULL;
45
    char local_ip256;
46
    host = pw_properties_get(impl->props, "raop.ip");
47
 
48
@@ -1258,9 +1260,9 @@
49
        break;
50
 
51
    case CRYPTO_RSA:
52
-       if (pw_getrandom(impl->key, sizeof(impl->key), 0) < 0 ||
53
-           pw_getrandom(impl->iv, sizeof(impl->iv), 0) < 0)
54
-           return -errno;
55
+       if ((res = pw_getrandom(impl->key, sizeof(impl->key), 0)) < 0 ||
56
+           (res = pw_getrandom(impl->iv, sizeof(impl->iv), 0)) < 0)
57
+           return res;
58
 
59
        rsa_len = rsa_encrypt(impl->key, 16, rsakey);
60
        if (rsa_len < 0)
61
@@ -1288,10 +1290,8 @@
62
    default:
63
        return -ENOTSUP;
64
    }
65
-   res = rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply);
66
-   free(sdp);
67
 
68
-   return res;
69
+   return rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply);
70
 }
71
 
72
 static int rtsp_auth_setup_reply(void *data, int status, const struct spa_dict *headers)
73
@@ -1354,7 +1354,6 @@
74
 static int rtsp_do_auth(struct impl *impl, const struct spa_dict *headers)
75
 {
76
    const char *str, *realm, *nonce;
77
-   char **tokens;
78
    int n_tokens;
79
 
80
    if ((str = spa_dict_lookup(headers, "WWW-Authenticate")) == NULL)
81
@@ -1367,9 +1366,9 @@
82
 
83
    pw_log_info("Auth: %s", str);
84
 
85
-   tokens = pw_split_strv(str, " ", INT_MAX, &n_tokens);
86
+   spa_auto(pw_strv) tokens = pw_split_strv(str, " ", INT_MAX, &n_tokens);
87
    if (tokens == NULL || tokens0 == NULL)
88
-       goto error;
89
+       return -EINVAL;
90
 
91
    impl->auth_method = strdup(tokens0);
92
 
93
@@ -1377,20 +1376,13 @@
94
        realm = find_attr(tokens, "realm");
95
        nonce = find_attr(tokens, "nonce");
96
        if (realm == NULL || nonce == NULL)
97
-           goto error;
98
+           return -EINVAL;
99
 
100
        impl->realm = strdup(realm);
101
        impl->nonce = strdup(nonce);
102
    }
103
 
104
-   pw_free_strv(tokens);
105
-
106
-   rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply);
107
-   return 0;
108
-
109
-error:
110
-   pw_free_strv(tokens);
111
-   return -EINVAL;
112
+   return rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply);
113
 }
114
 
115
 static int rtsp_options_reply(void *data, int status, const struct spa_dict *headers)
116
@@ -1420,14 +1412,15 @@
117
    uint32_t sci2;
118
    uint8_t rac16;
119
    char sac16*4;
120
+   int res;
121
 
122
    pw_log_info("connected");
123
 
124
    impl->connected = true;
125
 
126
-   if (pw_getrandom(sci, sizeof(sci), 0) < 0 ||
127
-       pw_getrandom(rac, sizeof(rac), 0) < 0) {
128
-       pw_log_error("error generating random data: %m");
129
+   if ((res = pw_getrandom(sci, sizeof(sci), 0)) < 0 ||
130
+       (res = pw_getrandom(rac, sizeof(rac), 0)) < 0) {
131
+       pw_log_error("error generating random data: %s", spa_strerror(res));
132
        return;
133
    }
134
 
135
@@ -1533,6 +1526,7 @@
136
 {
137
    const char *hostname, *port;
138
    uint32_t session_id;
139
+   int res;
140
 
141
    if (impl->connected) {
142
        if (!impl->ready)
143
@@ -1545,8 +1539,8 @@
144
    if (hostname == NULL || port == NULL)
145
        return -EINVAL;
146
 
147
-   if (pw_getrandom(&session_id, sizeof(session_id), 0) < 0)
148
-       return -errno;
149
+   if ((res = pw_getrandom(&session_id, sizeof(session_id), 0)) < 0)
150
+       return res;
151
 
152
    spa_scnprintf(impl->session_id, sizeof(impl->session_id), "%u", session_id);
153
 
154
pipewire-0.3.72.tar.gz/src/modules/module-rt.c -> pipewire-0.3.74.tar.gz/src/modules/module-rt.c Changed
212
 
1
@@ -63,7 +63,8 @@
2
  * This requires `RLIMIT_RTPRIO` to be set to a value that's equal to this
3
  * module's `rt.prio` parameter or higher. Most distros will come with some
4
  * package that configures this for certain groups or users. If this is not set
5
- * up and DBus is available, then this module will fall back to using RTKit.
6
+ * up and DBus is available, then this module will fall back to using the Portal
7
+ * Realtime DBus API or RTKit.
8
  *
9
  * ## Module Options
10
  *
11
@@ -75,6 +76,9 @@
12
  *              consume without doing any blocking calls before the kernel kills
13
  *              the thread. This is a safety measure to avoid lockups of the complete
14
  *              system when some thread consumes 100%.
15
+ * - `rlimits.enabled`: enable the use of rtlimits, default true.
16
+ * - `rtportal.enabled`: enable the use of realtime portal, default true
17
+ * - `rtkit.enabled`: enable the use of rtkit, default true
18
 
19
  * The nice level is by default set to an invalid value so that clients don't
20
  * automatically have the nice level raised.
21
@@ -91,6 +95,9 @@
22
  *         #rt.prio      = 88
23
  *         #rt.time.soft = -1
24
  *         #rt.time.hard = -1
25
+ *         #rlimits.enabled = true
26
+ *         #rtportal.enabled = true
27
+ *         #rtkit.enabled = true
28
  *     }
29
  *     flags =  ifexists nofail 
30
  * }
31
@@ -115,7 +122,7 @@
32
 #define MAX_NICE_LEVEL     19
33
 #define IS_VALID_NICE_LEVEL(l) ((l)>=MIN_NICE_LEVEL && (l)<=MAX_NICE_LEVEL)
34
 
35
-#define DEFAULT_NICE_LEVEL 20
36
+#define DEFAULT_NICE_LEVEL 20  /* invalid value by default, see above */
37
 #define DEFAULT_RT_PRIO_MIN    11
38
 #define DEFAULT_RT_PRIO        88
39
 #define DEFAULT_RT_TIME_SOFT   -1
40
@@ -123,8 +130,11 @@
41
 
42
 #define MODULE_USAGE   "( nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL)"(don't change)> ) " \
43
            "( rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO)"> ) "     \
44
-           "( rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)" ) " \
45
-           "( rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)" ) "
46
+           "( rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"> ) "    \
47
+           "( rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"> ) "    \
48
+           "( rlimits.enabled=<default true> ) " \
49
+           "( rtportal.enabled=<default true> ) " \
50
+           "( rtkit.enabled=<default true> ) "
51
 
52
 static const struct spa_dict_item module_props = {
53
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
54
@@ -170,6 +180,10 @@
55
 
56
    struct spa_hook module_listener;
57
 
58
+   unsigned rlimits_enabled:1;
59
+   unsigned rtportal_enabled:1;
60
+   unsigned rtkit_enabled:1;
61
+
62
 #ifdef HAVE_DBUS
63
    bool use_rtkit;
64
    /* For D-Bus. These are const static. */
65
@@ -207,7 +221,7 @@
66
 }
67
 
68
 #ifdef HAVE_DBUS
69
-struct pw_rtkit_bus *pw_rtkit_bus_get(DBusBusType bus_type)
70
+static struct pw_rtkit_bus *pw_rtkit_bus_get(DBusBusType bus_type)
71
 {
72
    struct pw_rtkit_bus *bus;
73
    DBusError error;
74
@@ -240,17 +254,17 @@
75
    return NULL;
76
 }
77
 
78
-struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
79
+static struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
80
 {
81
    return pw_rtkit_bus_get(DBUS_BUS_SYSTEM);
82
 }
83
 
84
-struct pw_rtkit_bus *pw_rtkit_bus_get_session(void)
85
+static struct pw_rtkit_bus *pw_rtkit_bus_get_session(void)
86
 {
87
    return pw_rtkit_bus_get(DBUS_BUS_SESSION);
88
 }
89
 
90
-bool pw_rtkit_check_xdg_portal(struct pw_rtkit_bus *system_bus)
91
+static bool pw_rtkit_check_xdg_portal(struct pw_rtkit_bus *system_bus)
92
 {
93
    if (!dbus_bus_name_has_owner(system_bus->bus, XDG_PORTAL_SERVICE_NAME, NULL)) {
94
        pw_log_info("Can't find %s. Is xdg-desktop-portal running?", XDG_PORTAL_SERVICE_NAME);
95
@@ -260,7 +274,7 @@
96
    return true;
97
 }
98
 
99
-void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
100
+static void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
101
 {
102
    dbus_connection_close(system_bus->bus);
103
    dbus_connection_unref(system_bus->bus);
104
@@ -369,7 +383,7 @@
105
    return ret;
106
 }
107
 
108
-int pw_rtkit_get_max_realtime_priority(struct impl *impl)
109
+static int pw_rtkit_get_max_realtime_priority(struct impl *impl)
110
 {
111
    long long retval;
112
    int err;
113
@@ -378,7 +392,7 @@
114
    return err < 0 ? err : retval;
115
 }
116
 
117
-int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level)
118
+static int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level)
119
 {
120
    long long retval;
121
    int err;
122
@@ -389,7 +403,7 @@
123
    return err;
124
 }
125
 
126
-long long pw_rtkit_get_rttime_usec_max(struct impl *impl)
127
+static long long pw_rtkit_get_rttime_usec_max(struct impl *impl)
128
 {
129
    long long retval;
130
    int err;
131
@@ -398,7 +412,7 @@
132
    return err < 0 ? err : retval;
133
 }
134
 
135
-int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority)
136
+static int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority)
137
 {
138
    DBusMessage *m = NULL, *r = NULL;
139
    dbus_uint64_t pid;
140
@@ -458,7 +472,7 @@
141
    return ret;
142
 }
143
 
144
-int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level)
145
+static int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level)
146
 {
147
    DBusMessage *m = NULL, *r = NULL;
148
    dbus_uint64_t pid;
149
@@ -568,6 +582,9 @@
150
    struct sched_param new_sched_params;
151
    int try = 0;
152
 
153
+   if (!impl->rlimits_enabled)
154
+       return false;
155
+
156
    while (try++ < 2) {
157
        /* We could check `RLIMIT_RTPRIO`, but the BSDs generally don't have
158
         * that available, and there are also other ways to use realtime
159
@@ -643,10 +660,15 @@
160
        }
161
        res = pw_rtkit_make_high_priority(impl, 0, nice_level);
162
    }
163
-   else
164
+   else if (impl->rlimits_enabled)
165
        res = sched_set_nice(nice_level);
166
+   else
167
+       res = -ENOTSUP;
168
 #else
169
-   res = sched_set_nice(nice_level);
170
+   if (impl->rlimits_enabled)
171
+       res = sched_set_nice(nice_level);
172
+   else
173
+       res = -ENOTSUP;
174
 #endif
175
 
176
    if (res < 0) {
177
@@ -993,6 +1015,9 @@
178
    impl->rt_prio = pw_properties_get_int32(props, "rt.prio", DEFAULT_RT_PRIO);
179
    impl->rt_time_soft = pw_properties_get_int32(props, "rt.time.soft", DEFAULT_RT_TIME_SOFT);
180
    impl->rt_time_hard = pw_properties_get_int32(props, "rt.time.hard", DEFAULT_RT_TIME_HARD);
181
+   impl->rlimits_enabled = pw_properties_get_bool(props, "rlimits.enabled", true);
182
+   impl->rtportal_enabled = pw_properties_get_bool(props, "rtportal.enabled", true);
183
+   impl->rtkit_enabled = pw_properties_get_bool(props, "rtkit.enabled", true);
184
 
185
    bool can_use_rtkit = false, use_rtkit = false;
186
 
187
@@ -1031,7 +1056,10 @@
188
    impl->use_rtkit = use_rtkit;
189
    if (impl->use_rtkit) {
190
        /* Checking xdg-desktop-portal. It works fine in all situations. */
191
-       impl->rtkit_bus = pw_rtkit_bus_get_session();
192
+       if (impl->rtportal_enabled)
193
+           impl->rtkit_bus = pw_rtkit_bus_get_session();
194
+       else
195
+           pw_log_info("Portal Realtime disabled");
196
        if (impl->rtkit_bus != NULL) {
197
            if (pw_rtkit_check_xdg_portal(impl->rtkit_bus)) {
198
                impl->service_name = XDG_PORTAL_SERVICE_NAME;
199
@@ -1045,7 +1073,11 @@
200
        }
201
        /* Failed to get xdg-desktop-portal, try to use rtkit. */
202
        if (impl->rtkit_bus == NULL) {
203
-           impl->rtkit_bus = pw_rtkit_bus_get_system();
204
+           if (impl->rtkit_enabled)
205
+               impl->rtkit_bus = pw_rtkit_bus_get_system();
206
+           else
207
+               pw_log_info("RTkit disabled");
208
+
209
            if (impl->rtkit_bus != NULL) {
210
                impl->service_name = RTKIT_SERVICE_NAME;
211
                impl->object_path = RTKIT_OBJECT_PATH;
212
pipewire-0.3.72.tar.gz/src/modules/module-rtp-sap.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp-sap.c Changed
19
 
1
@@ -28,7 +28,7 @@
2
 #define ifr_ifindex ifr_index
3
 #endif
4
 
5
-/** \page page_module_rtp_sap PipeWire Module: Announce and create RTP streams
6
+/** \page page_module_rtp_sap PipeWire Module: SAP Announce and create RTP streams
7
  *
8
  * The `rtp-sap` module announces RTP streams that match the rules with the
9
  * announce-stream action.
10
@@ -1489,7 +1489,7 @@
11
            }
12
        }
13
    }
14
-   if ((res = parse_address(str, port, &impl->src_addr, &impl->src_len)) < 0) {
15
+   if ((res = parse_address(str, 0, &impl->src_addr, &impl->src_len)) < 0) {
16
        pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res));
17
        goto out;
18
    }
19
pipewire-0.3.72.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp-source.c Changed
48
 
1
@@ -40,13 +40,19 @@
2
  * The `rtp-source` module creates a PipeWire source that receives audio
3
  * and midi RTP packets.
4
  *
5
+ * This module is usually loaded from the \page page_module_rtp_sap so that the
6
+ * source.ip and source.port and format parameters matches that of the sender.
7
+ *
8
  * ## Module Options
9
  *
10
  * Options specific to the behavior of this module
11
  *
12
  * - `local.ifname = <str>`: interface name to use
13
+ * - `source.ip = <str>`: the source ip address, default 224.0.0.56
14
+ * - `source.port = <int>`: the source port
15
  * - `node.always-process = <bool>`: true to receive even when not running
16
  * - `sess.latency.msec = <str>`: target network latency in milliseconds, default 100
17
+ * - `sess.ignore-ssrc = <bool>`: ignore SSRC, default false
18
  * - `sess.media = <string>`: the media type audio|midi|opus, default audio
19
  * - `stream.props = {}`: properties to be passed to the stream
20
  *
21
@@ -73,7 +79,10 @@
22
  * {   name = libpipewire-module-rtp-source
23
  *     args = {
24
  *         #local.ifname = eth0
25
+ *         #source.ip = 224.0.0.56
26
+ *         #source.port = 0
27
  *         sess.latency.msec = 100
28
+ *         #sess.ignore-ssrc = false
29
  *         #node.always-process = false
30
  *         #sess.media = "audio"
31
  *         #audio.format = "S16BE"
32
@@ -106,6 +115,7 @@
33
        "( source.ip=<source IP address, default:"DEFAULT_SOURCE_IP"> ) "               \
34
        "source.port=<int, source port> "                               \
35
        "( sess.latency.msec=<target network latency, default "SPA_STRINGIFY(DEFAULT_SESS_LATENCY)"> ) "\
36
+       "( sess.ignore-ssrc=<to ignore SSRC, default false> ) "\
37
        "( sess.media=<string, the media type audio|midi|opus, default audio> ) "           \
38
        "( audio.format=<format, default:"DEFAULT_FORMAT"> ) "                      \
39
        "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) "              \
40
@@ -490,6 +500,7 @@
41
    copy_props(impl, props, "sess.max-ptime");
42
    copy_props(impl, props, "sess.latency.msec");
43
    copy_props(impl, props, "sess.ts-direct");
44
+   copy_props(impl, props, "sess.ignore-ssrc");
45
 
46
    str = pw_properties_get(props, "local.ifname");
47
    impl->ifname = str ? strdup(str) : NULL;
48
pipewire-0.3.72.tar.gz/src/modules/module-rtp/audio.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/audio.c Changed
10
 
1
@@ -117,7 +117,7 @@
2
    if (impl->have_ssrc && impl->ssrc != hdr->ssrc)
3
        goto unexpected_ssrc;
4
    impl->ssrc = hdr->ssrc;
5
-   impl->have_ssrc = true;
6
+   impl->have_ssrc = !impl->ignore_ssrc;
7
 
8
    seq = ntohs(hdr->sequence_number);
9
    if (impl->have_seq && impl->seq != seq) {
10
pipewire-0.3.72.tar.gz/src/modules/module-rtp/midi.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/midi.c Changed
10
 
1
@@ -293,7 +293,7 @@
2
    if (impl->have_ssrc && impl->ssrc != hdr->ssrc)
3
        goto unexpected_ssrc;
4
    impl->ssrc = hdr->ssrc;
5
-   impl->have_ssrc = true;
6
+   impl->have_ssrc = !impl->ignore_ssrc;
7
 
8
    seq = ntohs(hdr->sequence_number);
9
    if (impl->have_seq && impl->seq != seq) {
10
pipewire-0.3.72.tar.gz/src/modules/module-rtp/opus.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/opus.c Changed
10
 
1
@@ -124,7 +124,7 @@
2
    if (impl->have_ssrc && impl->ssrc != hdr->ssrc)
3
        goto unexpected_ssrc;
4
    impl->ssrc = hdr->ssrc;
5
-   impl->have_ssrc = true;
6
+   impl->have_ssrc = !impl->ignore_ssrc;
7
 
8
    seq = ntohs(hdr->sequence_number);
9
    if (impl->have_seq && impl->seq != seq) {
10
pipewire-0.3.72.tar.gz/src/modules/module-rtp/stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/stream.c Changed
17
 
1
@@ -56,6 +56,7 @@
2
    uint32_t ssrc;
3
    uint16_t seq;
4
    unsigned have_ssrc:1;
5
+   unsigned ignore_ssrc:1;
6
    unsigned have_seq:1;
7
    uint32_t ts_offset;
8
    uint32_t psamples;
9
@@ -363,6 +364,7 @@
10
    if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL)
11
        pw_properties_set(props, PW_KEY_NODE_NETWORK, "true");
12
 
13
+   impl->ignore_ssrc = pw_properties_get_bool(props, "sess.ignore-ssrc", false);
14
    impl->direct_timestamp = pw_properties_get_bool(props, "sess.ts-direct", false);
15
 
16
    if (direction == PW_DIRECTION_INPUT) {
17
pipewire-0.3.72.tar.gz/src/modules/spa/module-device.c -> pipewire-0.3.74.tar.gz/src/modules/spa/module-device.c Changed
63
 
1
@@ -8,6 +8,7 @@
2
 #include <getopt.h>
3
 #include <limits.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/impl.h>
7
 
8
 #include "spa-device.h"
9
@@ -51,12 +52,11 @@
10
 int pipewire__module_init(struct pw_impl_module *module, const char *args)
11
 {
12
    struct pw_properties *props = NULL;
13
-   char **argv = NULL;
14
+   spa_auto(pw_strv) argv = NULL;
15
    int n_tokens;
16
    struct pw_context *context = pw_impl_module_get_context(module);
17
    struct pw_impl_device *device;
18
         struct device_data *data;
19
-   int res;
20
 
21
    PW_LOG_TOPIC_INIT(mod_topic);
22
 
23
@@ -69,10 +69,8 @@
24
 
25
    if (n_tokens == 2) {
26
        props = pw_properties_new_string(argv1);
27
-       if (props == NULL) {
28
-           res = -errno;
29
-           goto error_exit_cleanup;
30
-       }
31
+       if (props == NULL)
32
+           return -errno;
33
    }
34
 
35
    device = pw_spa_device_load(context,
36
@@ -80,12 +78,8 @@
37
                0,
38
                props,
39
                sizeof(struct device_data));
40
-   if (device == NULL) {
41
-       res = -errno;
42
-       goto error_exit_cleanup;
43
-   }
44
-
45
-   pw_free_strv(argv);
46
+   if (device == NULL)
47
+       return -errno;
48
 
49
    data = pw_spa_device_get_user_data(device);
50
    data->this = device;
51
@@ -99,10 +93,6 @@
52
    return 0;
53
 
54
 error_arguments:
55
-   res = -EINVAL;
56
    pw_log_error("usage: module-spa-device " MODULE_USAGE);
57
-   goto error_exit_cleanup;
58
-error_exit_cleanup:
59
-   pw_free_strv(argv);
60
-   return res;
61
+   return -EINVAL;
62
 }
63
pipewire-0.3.72.tar.gz/src/modules/spa/module-node.c -> pipewire-0.3.74.tar.gz/src/modules/spa/module-node.c Changed
60
 
1
@@ -10,6 +10,7 @@
2
 #include <getopt.h>
3
 #include <limits.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/impl.h>
7
 
8
 #include "spa-node.h"
9
@@ -52,8 +53,8 @@
10
 int pipewire__module_init(struct pw_impl_module *module, const char *args)
11
 {
12
    struct pw_properties *props = NULL;
13
-   char **argv = NULL;
14
-   int n_tokens, res;
15
+   spa_auto(pw_strv) argv = NULL;
16
+   int n_tokens;
17
    struct pw_context *context = pw_impl_module_get_context(module);
18
    struct pw_impl_node *node;
19
         struct node_data *data;
20
@@ -69,10 +70,8 @@
21
 
22
    if (n_tokens == 2) {
23
        props = pw_properties_new_string(argv1);
24
-       if (props == NULL) {
25
-           res = -errno;
26
-           goto error_exit_cleanup;
27
-       }
28
+       if (props == NULL)
29
+           return -errno;
30
    }
31
 
32
    node = pw_spa_node_load(context,
33
@@ -81,12 +80,8 @@
34
                props,
35
                sizeof(struct node_data));
36
 
37
-   if (node == NULL) {
38
-       res = -errno;
39
-       goto error_exit_cleanup;
40
-   }
41
-
42
-   pw_free_strv(argv);
43
+   if (node == NULL)
44
+       return -errno;
45
 
46
    data = pw_spa_node_get_user_data(node);
47
    data->this = node;
48
@@ -101,10 +96,6 @@
49
    return 0;
50
 
51
 error_arguments:
52
-   res = -EINVAL;
53
    pw_log_error("usage: module-spa-node " MODULE_USAGE);
54
-   goto error_exit_cleanup;
55
-error_exit_cleanup:
56
-   pw_free_strv(argv);
57
-   return res;
58
+   return -EINVAL;
59
 }
60
pipewire-0.3.74.tar.gz/src/pipewire/cleanup.h Added
23
 
1
@@ -0,0 +1,21 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#ifndef PIPEWIRE_CLEANUP_H
7
+#define PIPEWIRE_CLEANUP_H
8
+
9
+#include <spa/utils/cleanup.h>
10
+
11
+#include <pipewire/properties.h>
12
+#include <pipewire/utils.h>
13
+
14
+SPA_DEFINE_AUTOPTR_CLEANUP(pw_properties, struct pw_properties, {
15
+   spa_clear_ptr(*thing, pw_properties_free);
16
+})
17
+
18
+SPA_DEFINE_AUTO_CLEANUP(pw_strv, char **, {
19
+   spa_clear_ptr(*thing, pw_free_strv);
20
+})
21
+
22
+#endif /* PIPEWIRE_CLEANUP_H */
23
pipewire-0.3.72.tar.gz/src/pipewire/conf.c -> pipewire-0.3.74.tar.gz/src/pipewire/conf.c Changed
193
 
1
@@ -28,6 +28,7 @@
2
 #include <spa/utils/string.h>
3
 #include <spa/utils/json.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/impl.h>
7
 #include <pipewire/private.h>
8
 
9
@@ -345,7 +346,8 @@
10
 {
11
    char pathPATH_MAX;
12
    char *tmp_name;
13
-   int res, sfd, fd, count = 0;
14
+   spa_autoclose int sfd = -1;
15
+   int res, fd, count = 0;
16
    FILE *f;
17
 
18
    if ((sfd = open_write_dir(path, sizeof(path), prefix)) < 0)
19
@@ -354,9 +356,9 @@
20
    tmp_name = alloca(strlen(name)+5);
21
    sprintf(tmp_name, "%s.tmp", name);
22
    if ((fd = openat(sfd, tmp_name,  O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0600)) < 0) {
23
-       pw_log_error("can't open file '%s': %m", tmp_name);
24
        res = -errno;
25
-       goto error;
26
+       pw_log_error("can't open file '%s': %m", tmp_name);
27
+       return res;
28
    }
29
 
30
    f = fdopen(fd, "w");
31
@@ -366,46 +368,43 @@
32
    fclose(f);
33
 
34
    if (renameat(sfd, tmp_name, sfd, name) < 0) {
35
-       pw_log_error("can't rename temp file '%s': %m", tmp_name);
36
        res = -errno;
37
-       goto error;
38
+       pw_log_error("can't rename temp file '%s': %m", tmp_name);
39
+       return res;
40
    }
41
-   res = 0;
42
+
43
    pw_log_info("%p: saved state '%s%s'", conf, path, name);
44
-error:
45
-   close(sfd);
46
-   return res;
47
+
48
+   return 0;
49
 }
50
 
51
 static int conf_load(const char *path, struct pw_properties *conf)
52
 {
53
    char *data;
54
    struct stat sbuf;
55
-   int fd, count;
56
+   int count;
57
 
58
-   if ((fd = open(path,  O_CLOEXEC | O_RDONLY)) < 0)
59
+   spa_autoclose int fd = open(path,  O_CLOEXEC | O_RDONLY);
60
+   if (fd < 0)
61
        goto error;
62
 
63
    if (fstat(fd, &sbuf) < 0)
64
-       goto error_close;
65
+       goto error;
66
 
67
    if (sbuf.st_size > 0) {
68
        if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
69
-           goto error_close;
70
+           goto error;
71
 
72
        count = pw_properties_update_string(conf, data, sbuf.st_size);
73
        munmap(data, sbuf.st_size);
74
    } else {
75
        count = 0;
76
    }
77
-   close(fd);
78
 
79
    pw_log_info("%p: loaded config '%s' with %d items", conf, path, count);
80
 
81
    return 0;
82
 
83
-error_close:
84
-   close(fd);
85
 error:
86
    pw_log_warn("%p: error loading config '%s': %m", conf, path);
87
    return -errno;
88
@@ -455,7 +454,7 @@
89
    char pathPATH_MAX;
90
    char fnamePATH_MAX + 256;
91
    int i, res, level = 0;
92
-   struct pw_properties *override = NULL;
93
+   spa_autoptr(pw_properties) override = NULL;
94
    const char *dname;
95
 
96
    if (name == NULL) {
97
@@ -510,7 +509,7 @@
98
        }
99
        free(entries);
100
    }
101
-   pw_properties_free(override);
102
+
103
    return 0;
104
 }
105
 
106
@@ -660,15 +659,14 @@
107
    struct data *d = user_data;
108
    struct pw_context *context = d->context;
109
    struct spa_json it4;
110
-   char key512, *s;
111
+   char key512;
112
    int res = 0;
113
 
114
-   s = strndup(str, len);
115
+   spa_autofree char *s = strndup(str, len);
116
    spa_json_init(&it0, s, len);
117
    if (spa_json_enter_array(&it0, &it1) < 0) {
118
        pw_log_error("config file error: context.modules is not an array");
119
-       res = -EINVAL;
120
-       goto exit;
121
+       return -EINVAL;
122
    }
123
 
124
    while (spa_json_enter_object(&it1, &it2) > 0) {
125
@@ -714,8 +712,7 @@
126
 
127
        d->count++;
128
    }
129
-exit:
130
-   free(s);
131
+
132
    return res;
133
 }
134
 
135
@@ -761,15 +758,14 @@
136
    struct data *d = user_data;
137
    struct pw_context *context = d->context;
138
    struct spa_json it4;
139
-   char key512, *s;
140
+   char key512;
141
    int res = 0;
142
 
143
-   s = strndup(str, len);
144
+   spa_autofree char *s = strndup(str, len);
145
    spa_json_init(&it0, s, len);
146
    if (spa_json_enter_array(&it0, &it1) < 0) {
147
        pw_log_error("config file error: context.objects is not an array");
148
-       res = -EINVAL;
149
-       goto exit;
150
+       return -EINVAL;
151
    }
152
 
153
    while (spa_json_enter_object(&it1, &it2) > 0) {
154
@@ -815,8 +811,7 @@
155
            break;
156
        d->count++;
157
    }
158
-exit:
159
-   free(s);
160
+
161
    return res;
162
 }
163
 
164
@@ -880,15 +875,14 @@
165
    struct data *d = user_data;
166
    struct pw_context *context = d->context;
167
    struct spa_json it4;
168
-   char key512, *s;
169
+   char key512;
170
    int res = 0;
171
 
172
-   s = strndup(str, len);
173
+   spa_autofree char *s = strndup(str, len);
174
    spa_json_init(&it0, s, len);
175
    if (spa_json_enter_array(&it0, &it1) < 0) {
176
        pw_log_error("config file error: context.exec is not an array");
177
-       res = -EINVAL;
178
-       goto exit;
179
+       return -EINVAL;
180
    }
181
 
182
    while (spa_json_enter_object(&it1, &it2) > 0) {
183
@@ -926,8 +920,7 @@
184
 
185
        d->count++;
186
    }
187
-exit:
188
-   free(s);
189
+
190
    return res;
191
 }
192
 
193
pipewire-0.3.72.tar.gz/src/pipewire/conf.h -> pipewire-0.3.74.tar.gz/src/pipewire/conf.h Changed
17
 
1
@@ -2,6 +2,9 @@
2
 /* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */
3
 /* SPDX-License-Identifier: MIT */
4
 
5
+#ifndef PIPEWIRE_CONF_H
6
+#define PIPEWIRE_CONF_H
7
+
8
 #include <pipewire/context.h>
9
 
10
 /** \defgroup pw_conf Configuration
11
@@ -40,3 +43,5 @@
12
 /**
13
  * \}
14
  */
15
+
16
+#endif /* PIPEWIRE_CONF_H */
17
pipewire-0.3.72.tar.gz/src/pipewire/context.c -> pipewire-0.3.74.tar.gz/src/pipewire/context.c Changed
44
 
1
@@ -560,6 +560,12 @@
2
 }
3
 
4
 SPA_EXPORT
5
+struct pw_mempool *pw_context_get_mempool(struct pw_context *context)
6
+{
7
+   return context->pool;
8
+}
9
+
10
+SPA_EXPORT
11
 const struct pw_properties *pw_context_get_properties(struct pw_context *context)
12
 {
13
    return context->properties;
14
@@ -1155,12 +1161,14 @@
15
     * 8000 and  44100 192000  -> 44100
16
     * 11025 and  44100 48000  -> 44100
17
     * 44100 and  48000 176400  -> 48000
18
+    * 144 and  44100 48000 88200 96000 -> 48000
19
     */
20
    spa_zero(best);
21
    /* Don't try to do excessive upsampling by limiting the max rate
22
     * for desired < default to default*2. For other rates allow
23
-    * a x3 upsample rate max */
24
-   limit = rate < def ? def*2 : rate*3;
25
+    * a x3 upsample rate max. For values lower than half of the default,
26
+    * limit to the default.  */
27
+   limit = rate < def/2 ? def : rate < def ? def*2 : rate*3;
28
    for (i = 0; i < n_rates; i++) {
29
        if (infoi.rate >= rate && infoi.rate <= limit)
30
            update_nearest_gcd(&best, &infoi);
31
@@ -1327,11 +1335,11 @@
32
            if ((t->want_driver && t->active && t->runnable) ||
33
                t->always_process) {
34
                driver = target;
35
-               driver->runnable = true;
36
                break;
37
            }
38
        }
39
        if (driver != NULL) {
40
+           driver->runnable = true;
41
            /* driver needed for this group */
42
            move_to_driver(context, &collect, driver);
43
        } else {
44
pipewire-0.3.72.tar.gz/src/pipewire/context.h -> pipewire-0.3.74.tar.gz/src/pipewire/context.h Changed
11
 
1
@@ -122,6 +122,9 @@
2
 /** Get the work queue from the context: Since 0.3.26 */
3
 struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context);
4
 
5
+/** Get the memmory pool from the context: Since 0.3.74 */
6
+struct pw_mempool *pw_context_get_mempool(struct pw_context *context);
7
+
8
 /** Iterate the globals of the context. The callback should return
9
  * 0 to fetch the next item, any other value stops the iteration and returns
10
  * the value. When all callbacks return 0, this function returns 0 when all
11
pipewire-0.3.72.tar.gz/src/pipewire/core.c -> pipewire-0.3.74.tar.gz/src/pipewire/core.c Changed
44
 
1
@@ -24,7 +24,7 @@
2
 {
3
    struct pw_core *this = data;
4
    pw_log_debug("%p: object %u ping %u", this, id, seq);
5
-   pw_core_pong(this->core, id, seq);
6
+   pw_core_pong(this, id, seq);
7
 }
8
 
9
 static void core_event_done(void *data, uint32_t id, int seq)
10
@@ -317,11 +317,9 @@
11
 
12
    pw_properties_add(properties, &context->properties->dict);
13
 
14
-   p->proxy.core = p;
15
    p->context = context;
16
    p->properties = properties;
17
    p->pool = pw_mempool_new(NULL);
18
-   p->core = p;
19
    if (user_data_size > 0)
20
        p->user_data = SPA_PTROFF(p, sizeof(struct pw_core), void);
21
    p->proxy.user_data = p->user_data;
22
@@ -344,7 +342,7 @@
23
    if (p->conn == NULL)
24
        goto error_connection;
25
 
26
-   if ((res = pw_proxy_init(&p->proxy, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE)) < 0)
27
+   if ((res = pw_proxy_init(&p->proxy, p, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE)) < 0)
28
        goto error_proxy;
29
 
30
    p->client = (struct pw_client*)pw_proxy_new(&p->proxy,
31
@@ -478,6 +476,12 @@
32
 SPA_EXPORT
33
 int pw_core_disconnect(struct pw_core *core)
34
 {
35
+   /*
36
+    * the `proxy` member must be the first because the whole pw_core object is
37
+    * freed via the free() call in pw_proxy_destroy() -> pw_proxy_unref()
38
+    */
39
+   SPA_STATIC_ASSERT(offsetof(struct pw_core, proxy) == 0, "`proxy` member must be first");
40
+
41
    pw_log_debug("%p: disconnect", core);
42
    if (!core->removed)
43
        pw_proxy_remove(&core->proxy);
44
pipewire-0.3.72.tar.gz/src/pipewire/filter.c -> pipewire-0.3.74.tar.gz/src/pipewire/filter.c Changed
39
 
1
@@ -18,6 +18,7 @@
2
 #include <spa/pod/dynamic.h>
3
 #include <spa/debug/types.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include "pipewire/pipewire.h"
7
 #include "pipewire/filter.h"
8
 #include "pipewire/private.h"
9
@@ -1632,7 +1633,9 @@
10
    impl->info = SPA_NODE_INFO_INIT();
11
    impl->info.max_input_ports = UINT32_MAX;
12
    impl->info.max_output_ports = UINT32_MAX;
13
-   impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0;
14
+   impl->info.flags = SPA_NODE_FLAG_RT;
15
+   if (!impl->process_rt || SPA_FLAG_IS_SET(flags, PW_FILTER_FLAG_ASYNC))
16
+       impl->info.flags |= SPA_NODE_FLAG_ASYNC;
17
    impl->info.props = &filter->properties->dict;
18
    impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
19
    impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
20
@@ -1896,8 +1899,8 @@
21
    ensure_loop(impl->main_loop, return -EIO);
22
 
23
    if (res < 0) {
24
+       spa_autofree char *value = NULL;
25
        va_list args;
26
-       char *value;
27
        int r;
28
 
29
        va_start(args, error);
30
@@ -1909,8 +1912,6 @@
31
        if (filter->proxy)
32
            pw_proxy_error(filter->proxy, res, value);
33
        filter_set_state(filter, PW_FILTER_STATE_ERROR, res, value);
34
-
35
-       free(value);
36
    }
37
    return res;
38
 }
39
pipewire-0.3.72.tar.gz/src/pipewire/filter.h -> pipewire-0.3.74.tar.gz/src/pipewire/filter.h Changed
15
 
1
@@ -109,6 +109,13 @@
2
                              *  needs to be called. This can be used
3
                              *  when the filter depends on processing
4
                              *  of other filters. */
5
+   PW_FILTER_FLAG_ASYNC        = (1 << 5), /**< Buffers will not be dequeued/queued from
6
+                             *  the realtime process() function. This is
7
+                             *  assumed when RT_PROCESS is unset but can
8
+                             *  also be the case when the process() function
9
+                             *  does a trigger_process() that will then
10
+                             *  dequeue/queue a buffer from another process()
11
+                             *  function. since 0.3.73 */
12
 };
13
 
14
 enum pw_filter_port_flags {
15
pipewire-0.3.72.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-client.c Changed
14
 
1
@@ -572,6 +572,12 @@
2
 }
3
 
4
 SPA_EXPORT
5
+struct pw_mempool *pw_impl_client_get_mempool(struct pw_impl_client *client)
6
+{
7
+   return client->pool;
8
+}
9
+
10
+SPA_EXPORT
11
 const struct pw_properties *pw_impl_client_get_properties(struct pw_impl_client *client)
12
 {
13
    return client->properties;
14
pipewire-0.3.72.tar.gz/src/pipewire/impl-client.h -> pipewire-0.3.74.tar.gz/src/pipewire/impl-client.h Changed
11
 
1
@@ -143,6 +143,9 @@
2
 /** Get the global associated with this client */
3
 struct pw_global *pw_impl_client_get_global(struct pw_impl_client *client);
4
 
5
+/** Get the mempool associated with this client, Since 0.3.74 */
6
+struct pw_mempool *pw_impl_client_get_mempool(struct pw_impl_client *client);
7
+
8
 /** listen to events from this client */
9
 void pw_impl_client_add_listener(struct pw_impl_client *client,
10
                struct spa_hook *listener,
11
pipewire-0.3.72.tar.gz/src/pipewire/impl-metadata.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-metadata.c Changed
47
 
1
@@ -7,6 +7,7 @@
2
 #include <spa/debug/types.h>
3
 #include <spa/utils/string.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include "pipewire/impl.h"
7
 #include "pipewire/private.h"
8
 
9
@@ -576,32 +577,15 @@
10
            uint32_t subject, const char *key, const char *type,
11
            const char *fmt, ...)
12
 {
13
+   spa_autofree char *value = NULL;
14
    va_list args;
15
-   int n = 0, res;
16
-   size_t size = 0;
17
-   char *p = NULL;
18
-
19
-   va_start(args, fmt);
20
-   n = vsnprintf(p, size, fmt, args);
21
-   va_end(args);
22
-   if (n < 0)
23
-       return -errno;
24
-
25
-   size = (size_t) n + 1;
26
-   p = malloc(size);
27
-   if (p == NULL)
28
-       return -errno;
29
+   int res;
30
 
31
    va_start(args, fmt);
32
-   n = vsnprintf(p, size, fmt, args);
33
+   res = vasprintf(&value, fmt, args);
34
    va_end(args);
35
-
36
-   if (n < 0) {
37
-       free(p);
38
+   if (res < 0)
39
        return -errno;
40
-   }
41
-   res = pw_impl_metadata_set_property(metadata, subject, key, type, p);
42
-   free(p);
43
 
44
-   return res;
45
+   return pw_impl_metadata_set_property(metadata, subject, key, type, value);
46
 }
47
pipewire-0.3.72.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-module.c Changed
61
 
1
@@ -15,6 +15,7 @@
2
 
3
 #include <spa/utils/string.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include "pipewire/impl.h"
7
 #include "pipewire/private.h"
8
 
9
@@ -38,7 +39,6 @@
10
    char *filename;
11
    struct dirent *entry;
12
    struct stat s;
13
-   DIR *dir;
14
    int res;
15
 
16
    filename = spa_aprintf("%s/%s.so", path, name);
17
@@ -57,7 +57,7 @@
18
    if (level <= 0)
19
        return NULL;
20
 
21
-   dir = opendir(path);
22
+   spa_autoptr(DIR) dir = opendir(path);
23
    if (dir == NULL) {
24
        res = -errno;
25
        pw_log_warn("could not open %s: %m", path);
26
@@ -66,27 +66,22 @@
27
    }
28
 
29
    while ((entry = readdir(dir))) {
30
-       char *newpath;
31
-
32
        if (spa_streq(entry->d_name, ".") || spa_streq(entry->d_name, ".."))
33
            continue;
34
 
35
-       newpath = spa_aprintf("%s/%s", path, entry->d_name);
36
+       spa_autofree char *newpath = spa_aprintf("%s/%s", path, entry->d_name);
37
        if (newpath == NULL)
38
            break;
39
 
40
-       if (stat(newpath, &s) == 0 && S_ISDIR(s.st_mode))
41
+       if (entry->d_type == DT_DIR ||
42
+           (entry->d_type == DT_UNKNOWN && stat(newpath, &s) == 0 && S_ISDIR(s.st_mode))) {
43
            filename = find_module(newpath, name, level - 1);
44
-
45
-       free(newpath);
46
-
47
-       if (filename != NULL)
48
-           break;
49
+           if (filename)
50
+               return filename;
51
+       }
52
    }
53
 
54
-   closedir(dir);
55
-
56
-   return filename;
57
+   return NULL;
58
 }
59
 
60
 static int
61
pipewire-0.3.72.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-node.c Changed
77
 
1
@@ -901,8 +901,8 @@
2
 
3
    pw_impl_node_emit_driver_changed(node, old, driver);
4
 
5
-   pw_impl_node_emit_peer_added(driver, node);
6
    pw_impl_node_emit_peer_removed(old, node);
7
+   pw_impl_node_emit_peer_added(driver, node);
8
 
9
    return 0;
10
 }
11
@@ -1095,22 +1095,27 @@
12
    struct pw_node_activation *na = driver->rt.target.activation;
13
    struct spa_io_clock *cl = &na->position.clock;
14
    enum spa_log_level level = SPA_LOG_LEVEL_DEBUG;
15
+   int missed;
16
 
17
-   if (ratelimit_test(&driver->rt.rate_limit, nsec, SPA_LOG_LEVEL_DEBUG))
18
+   if ((missed = spa_ratelimit_test(&driver->rt.rate_limit, nsec)) >= 0)
19
        level = SPA_LOG_LEVEL_INFO;
20
 
21
    spa_list_for_each(t, &driver->rt.target_list, link) {
22
        struct pw_node_activation *a = t->activation;
23
        struct pw_node_activation_state *state = &a->state0;
24
 
25
+       if (t->id == driver->info.id)
26
+           continue;
27
+
28
        if (a->status == PW_NODE_ACTIVATION_TRIGGERED ||
29
            a->status == PW_NODE_ACTIVATION_AWAKE) {
30
            update_xrun_stats(a, nsec / 1000, 0);
31
 
32
-           pw_log(level, "(%s-%u) client too slow! rate:%u/%u pos:%"PRIu64" status:%s",
33
+           pw_log(level, "(%s-%u) client too slow! rate:%u/%u pos:%"PRIu64" status:%s (%u missed)",
34
                t->name, t->id,
35
                (uint32_t)(cl->rate.num * cl->duration), cl->rate.denom,
36
-               cl->position, str_status(a->status));
37
+               cl->position, str_status(a->status),
38
+               missed);
39
        }
40
        pw_log_debug("(%s-%u) state:%p pending:%d/%d s:%"PRIu64" a:%"PRIu64" f:%"PRIu64
41
                " waiting:%"PRIu64" process:%"PRIu64" status:%s sync:%d",
42
@@ -1878,10 +1883,11 @@
43
    struct pw_node_activation *da = this->rt.driver_target.activation;
44
    struct spa_system *data_system = this->data_system;
45
    uint64_t nsec = get_time_ns(data_system);
46
+   int missed;
47
 
48
    update_xrun_stats(a, trigger, delay);
49
 
50
-   if (ratelimit_test(&this->rt.rate_limit, nsec, SPA_LOG_LEVEL_INFO)) {
51
+   if ((missed = spa_ratelimit_test(&this->rt.rate_limit, nsec)) >= 0) {
52
        struct spa_fraction rate;
53
        if (da) {
54
            struct spa_io_clock *cl = &da->position.clock;
55
@@ -1891,10 +1897,11 @@
56
            rate = SPA_FRACTION(0,0);
57
        }
58
        pw_log_info("(%s-%d) XRun! rate:%u/%u count:%u time:%"PRIu64
59
-               " delay:%"PRIu64" max:%"PRIu64,
60
+               " delay:%"PRIu64" max:%"PRIu64" (%d missed)",
61
                this->name, this->info.id,
62
                rate.num, rate.denom, a->xrun_count,
63
-               trigger, delay, a->max_delay);
64
+               trigger, delay, a->max_delay,
65
+               missed);
66
    }
67
 
68
    pw_context_driver_emit_xrun(this->context, this);
69
@@ -1980,6 +1987,7 @@
70
 
71
    /* remove ourself as a follower from the driver node */
72
    spa_list_remove(&node->follower_link);
73
+   pw_impl_node_emit_peer_removed(node->driver_node, node);
74
    remove_segment_owner(node->driver_node, node->info.id);
75
 
76
    spa_list_consume(follower, &node->follower_list, follower_link) {
77
pipewire-0.3.72.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-port.c Changed
33
 
1
@@ -298,9 +298,9 @@
2
    spa_list_append(&port->mix_list, &mix->link);
3
    port->n_mix++;
4
 
5
-   pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port,
6
+   pw_log_debug("%p: init mix n_mix:%d %d.%d id:%d peer:%d io:%p: (%s)", port,
7
            port->n_mix, port->port_id, mix->port.port_id,
8
-           mix->io, spa_strerror(res));
9
+           mix->id, mix->peer_id, mix->io, spa_strerror(res));
10
 
11
    if (port->n_mix == 1) {
12
        pw_log_debug("%p: setting port io", port);
13
@@ -329,6 +329,9 @@
14
    spa_list_remove(&mix->link);
15
    port->n_mix--;
16
 
17
+   pw_log_debug("%p: release mix %d %d.%d", port,
18
+           port->n_mix, port->port_id, mix->port.port_id);
19
+
20
    res = pw_impl_port_call_release_mix(port, mix);
21
 
22
    if (port->destroying)
23
@@ -338,9 +341,6 @@
24
        res != -ENOTSUP)
25
        pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res));
26
 
27
-   pw_log_debug("%p: release mix %d %d.%d", port,
28
-           port->n_mix, port->port_id, mix->port.port_id);
29
-
30
    if (port->n_mix == 0) {
31
        pw_log_debug("%p: clearing port io", port);
32
        spa_node_port_set_io(node->node,
33
pipewire-0.3.72.tar.gz/src/pipewire/log.h -> pipewire-0.3.74.tar.gz/src/pipewire/log.h Changed
19
 
1
@@ -96,7 +96,7 @@
2
  */
3
 #define PW_LOG_TOPIC_STATIC(var, topic) \
4
   static struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \
5
-  static struct spa_log_topic *(var) = &(var##__LINE__)
6
+  static struct spa_log_topic *var = &(var##__LINE__)
7
 
8
 /**
9
  * Declare a static log topic named \a var.
10
@@ -111,7 +111,7 @@
11
  */
12
 #define PW_LOG_TOPIC(var, topic) \
13
   struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \
14
-  struct spa_log_topic *(var) = &(var##__LINE__)
15
+  struct spa_log_topic *var = &(var##__LINE__)
16
 
17
 #define PW_LOG_TOPIC_INIT(var) \
18
    spa_log_topic_init(pw_log_get(), var);
19
pipewire-0.3.72.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.74.tar.gz/src/pipewire/pipewire.c Changed
66
 
1
@@ -25,8 +25,10 @@
2
 #include <spa/support/cpu.h>
3
 #include <spa/support/i18n.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include "pipewire.h"
7
 #include "private.h"
8
+#include "i18n.h"
9
 
10
 #define MAX_SUPPORT    32
11
 
12
@@ -497,9 +499,7 @@
13
 parse_pw_debug_env(void)
14
 {
15
    const char *str;
16
-   char **tokens;
17
    int n_tokens;
18
-   size_t slen;
19
    char json1024 = {0};
20
    char *pos = json;
21
    char *end = pos + sizeof(json) - 1;
22
@@ -507,7 +507,7 @@
23
 
24
    str = getenv("PIPEWIRE_DEBUG");
25
 
26
-   if (!str || (slen = strlen(str)) == 0)
27
+   if (!str || !*str)
28
        return NULL;
29
 
30
    /* String format is PIPEWIRE_DEBUG=<glob>:<level>,...,
31
@@ -516,17 +516,16 @@
32
     */
33
    pos += spa_scnprintf(pos, end - pos, " { conn.* = %d },", SPA_LOG_LEVEL_NONE);
34
 
35
-   tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens);
36
+   spa_auto(pw_strv) tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens);
37
    if (n_tokens > 0) {
38
        int i;
39
        for (i = 0; i < n_tokens; i++) {
40
            int n_tok;
41
-           char **tok;
42
-           char *pattern;
43
+           char *tok2;
44
 
45
-           tok = pw_split_strv(tokensi, ":", 2, &n_tok);
46
+           n_tok = pw_split_ip(tokensi, ":", SPA_N_ELEMENTS(tok), tok);
47
            if (n_tok == 2 && parse_log_level(tok1, &lvl)) {
48
-               pattern = tok0;
49
+               char *pattern = tok0;
50
                pos += spa_scnprintf(pos, end - pos, "{ %s = %d },",
51
                             pattern, lvl);
52
            } else if (n_tok == 1 && parse_log_level(tok0, &lvl)) {
53
@@ -535,11 +534,9 @@
54
                pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'",
55
                        tokensi);
56
            }
57
-
58
-           pw_free_strv(tok);
59
        }
60
    }
61
-   pw_free_strv(tokens);
62
+
63
    pos += spa_scnprintf(pos, end - pos, "");
64
    return strdup(json);
65
 }
66
pipewire-0.3.72.tar.gz/src/pipewire/private.h -> pipewire-0.3.74.tar.gz/src/pipewire/private.h Changed
99
 
1
@@ -17,6 +17,7 @@
2
 #include <spa/support/plugin.h>
3
 #include <spa/pod/builder.h>
4
 #include <spa/param/latency-utils.h>
5
+#include <spa/utils/ratelimit.h>
6
 #include <spa/utils/result.h>
7
 #include <spa/utils/type-info.h>
8
 
9
@@ -53,29 +54,6 @@
10
    uint32_t clock_force_quantum;       /* force a quantum */
11
 };
12
 
13
-struct ratelimit {
14
-   uint64_t interval;
15
-   uint64_t begin;
16
-   unsigned burst;
17
-   unsigned n_printed, n_missed;
18
-};
19
-
20
-static inline bool ratelimit_test(struct ratelimit *r, uint64_t now, enum spa_log_level level)
21
-{
22
-   if (r->begin + r->interval < now) {
23
-       if (r->n_missed)
24
-           pw_log(level, "%u events suppressed", r->n_missed);
25
-       r->begin = now;
26
-       r->n_printed = 0;
27
-       r->n_missed = 0;
28
-   } else if (r->n_printed >= r->burst) {
29
-       r->n_missed++;
30
-       return false;
31
-   }
32
-   r->n_printed++;
33
-   return true;
34
-}
35
-
36
 #define MAX_PARAMS 32
37
 
38
 struct pw_param {
39
@@ -203,22 +181,6 @@
40
 #define pw_impl_client_emit_resource_removed(o,r)  pw_impl_client_emit(o, resource_removed, 0, r)
41
 #define pw_impl_client_emit_busy_changed(o,b)      pw_impl_client_emit(o, busy_changed, 0, b)
42
 
43
-enum spa_node0_event {
44
-   SPA_NODE0_EVENT_START   = SPA_TYPE_VENDOR_PipeWire,
45
-   SPA_NODE0_EVENT_RequestClockUpdate,
46
-};
47
-
48
-enum spa_node0_command {
49
-   SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire,
50
-   SPA_NODE0_COMMAND_ClockUpdate,
51
-};
52
-
53
-struct protocol_compat_v2 {
54
-   /* v2 typemap */
55
-   struct pw_map types;
56
-   unsigned int send_types:1;
57
-};
58
-
59
 #define pw_impl_core_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct pw_impl_core_events, m, v, ##__VA_ARGS__)
60
 
61
 #define pw_impl_core_emit_destroy(s)       pw_impl_core_emit(s, destroy, 0)
62
@@ -801,7 +763,7 @@
63
                               driver */
64
        struct spa_list driver_link;        /* our link in driver */
65
 
66
-       struct ratelimit rate_limit;
67
+       struct spa_ratelimit rate_limit;
68
    } rt;
69
    struct spa_fraction target_rate;
70
    uint64_t target_quantum;
71
@@ -1066,7 +1028,6 @@
72
    struct pw_properties *properties;   /**< extra properties */
73
 
74
    struct pw_mempool *pool;        /**< memory pool */
75
-   struct pw_core *core;           /**< proxy for the core object */
76
    struct spa_hook core_listener;
77
    struct spa_hook proxy_core_listener;
78
 
79
@@ -1229,9 +1190,7 @@
80
        struct spa_node *node, enum spa_direction direction,
81
        uint32_t port_id, uint32_t id, int err, const char *debug, ...);
82
 
83
-const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type);
84
-
85
-int pw_proxy_init(struct pw_proxy *proxy, const char *type, uint32_t version);
86
+int pw_proxy_init(struct pw_proxy *proxy, struct pw_core *core, const char *type, uint32_t version);
87
 
88
 void pw_proxy_remove(struct pw_proxy *proxy);
89
 
90
@@ -1356,7 +1315,7 @@
91
 void pw_log_init(void);
92
 void pw_log_deinit(void);
93
 
94
-void pw_random_init();
95
+void pw_random_init(void);
96
 
97
 void pw_settings_init(struct pw_context *context);
98
 int pw_settings_expose(struct pw_context *context);
99
pipewire-0.3.72.tar.gz/src/pipewire/proxy.c -> pipewire-0.3.74.tar.gz/src/pipewire/proxy.c Changed
38
 
1
@@ -21,10 +21,11 @@
2
 };
3
 /** \endcond */
4
 
5
-int pw_proxy_init(struct pw_proxy *proxy, const char *type, uint32_t version)
6
+int pw_proxy_init(struct pw_proxy *proxy, struct pw_core *core, const char *type, uint32_t version)
7
 {
8
    int res;
9
 
10
+   proxy->core = core;
11
    proxy->refcount = 1;
12
    proxy->type = type;
13
    proxy->version = version;
14
@@ -81,9 +82,8 @@
15
        return NULL;
16
 
17
    this = &impl->this;
18
-   this->core = factory->core;
19
 
20
-   if ((res = pw_proxy_init(this, type, version)) < 0)
21
+   if ((res = pw_proxy_init(this, factory->core, type, version)) < 0)
22
        goto error_init;
23
 
24
    if (user_data_size > 0)
25
@@ -160,12 +160,6 @@
26
 }
27
 
28
 SPA_EXPORT
29
-struct pw_core *pw_proxy_get_core(struct pw_proxy *proxy)
30
-{
31
-   return proxy->core;
32
-}
33
-
34
-SPA_EXPORT
35
 struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy)
36
 {
37
    if (proxy->core == NULL || proxy->core->conn == NULL)
38
pipewire-0.3.72.tar.gz/src/pipewire/stream.c -> pipewire-0.3.74.tar.gz/src/pipewire/stream.c Changed
47
 
1
@@ -21,6 +21,7 @@
2
 
3
 #define PW_ENABLE_DEPRECATED
4
 
5
+#include <pipewire/cleanup.h>
6
 #include "pipewire/pipewire.h"
7
 #include "pipewire/stream.h"
8
 #include "pipewire/private.h"
9
@@ -446,7 +447,8 @@
10
    struct stream *impl = user_data;
11
    struct pw_stream *stream = &impl->this;
12
    pw_log_trace_fp("%p: do process", stream);
13
-   pw_stream_emit_process(stream);
14
+   if (!impl->disconnecting)
15
+       pw_stream_emit_process(stream);
16
    return 0;
17
 }
18
 
19
@@ -1957,7 +1959,7 @@
20
    impl->info.flags = SPA_NODE_FLAG_RT;
21
    /* if the callback was not marked RT_PROCESS, we will offload
22
     * the process callback in the main thread and we are ASYNC */
23
-   if (!impl->process_rt)
24
+   if (!impl->process_rt || SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_ASYNC))
25
        impl->info.flags |= SPA_NODE_FLAG_ASYNC;
26
    impl->info.props = &stream->properties->dict;
27
    impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
28
@@ -2164,8 +2166,8 @@
29
    ensure_loop(impl->main_loop, return -EIO);
30
 
31
    if (res < 0) {
32
+       spa_autofree char *value = NULL;
33
        va_list args;
34
-       char *value;
35
        int r;
36
 
37
        va_start(args, error);
38
@@ -2177,8 +2179,6 @@
39
        if (stream->proxy)
40
            pw_proxy_error(stream->proxy, res, value);
41
        stream_set_state(stream, PW_STREAM_STATE_ERROR, res, value);
42
-
43
-       free(value);
44
    }
45
    return res;
46
 }
47
pipewire-0.3.72.tar.gz/src/pipewire/stream.h -> pipewire-0.3.74.tar.gz/src/pipewire/stream.h Changed
15
 
1
@@ -378,6 +378,13 @@
2
                              *  needs to be called. This can be used
3
                              *  when the output of the stream depends
4
                              *  on input from other streams. */
5
+   PW_STREAM_FLAG_ASYNC        = (1 << 10),    /**< Buffers will not be dequeued/queued from
6
+                             *  the realtime process() function. This is
7
+                             *  assumed when RT_PROCESS is unset but can
8
+                             *  also be the case when the process() function
9
+                             *  does a trigger_process() that will then
10
+                             *  dequeue/queue a buffer from another process()
11
+                             *  function. since 0.3.73 */
12
 };
13
 
14
 /** Create a new unconneced \ref pw_stream
15
pipewire-0.3.72.tar.gz/src/pipewire/thread.c -> pipewire-0.3.74.tar.gz/src/pipewire/thread.c Changed
12
 
1
@@ -12,8 +12,8 @@
2
 #include <spa/utils/list.h>
3
 
4
 #include <pipewire/log.h>
5
-
6
-#include "thread.h"
7
+#include <pipewire/private.h>
8
+#include <pipewire/thread.h>
9
 
10
 #define CHECK(expression,label)                        \
11
 do {                                   \
12
pipewire-0.3.72.tar.gz/src/pipewire/utils.c -> pipewire-0.3.74.tar.gz/src/pipewire/utils.c Changed
62
 
1
@@ -16,6 +16,7 @@
2
 #include <pipewire/array.h>
3
 #include <pipewire/log.h>
4
 #include <pipewire/utils.h>
5
+#include <pipewire/private.h>
6
 
7
 /** Split a string based on delimiters
8
  * \param str a string to split
9
@@ -157,21 +158,25 @@
10
 static inline ssize_t make_random(void *buf, size_t buflen, unsigned int flags)
11
 {
12
    ssize_t bytes;
13
-   int read_errno;
14
 
15
 #ifdef HAVE_GETRANDOM
16
    bytes = getrandom(buf, buflen, flags);
17
-   if (!(bytes == -1 && errno == ENOSYS))
18
+   if (bytes < 0)
19
+       bytes = -errno;
20
+   if (bytes != -ENOSYS)
21
        return bytes;
22
 #endif
23
 
24
    int fd = open("/dev/urandom", O_CLOEXEC);
25
    if (fd < 0)
26
-       return -1;
27
+       return -errno;
28
+
29
    bytes = read(fd, buf, buflen);
30
-   read_errno = errno;
31
+   if (bytes < 0)
32
+       bytes = -errno;
33
+
34
    close(fd);
35
-   errno = read_errno;
36
+
37
    return bytes;
38
 }
39
 
40
@@ -189,9 +194,9 @@
41
    ssize_t res;
42
    do {
43
        res = make_random(buf, buflen, flags);
44
-   } while ((res == -1) && (errno == EINTR));
45
-   if (res == -1)
46
-       return -errno;
47
+   } while (res == -EINTR);
48
+   if (res < 0)
49
+       return res;
50
    if ((size_t)res != buflen)
51
        return -ENODATA;
52
    return res;
53
@@ -227,7 +232,7 @@
54
    }
55
 }
56
 
57
-void pw_random_init()
58
+void pw_random_init(void)
59
 {
60
    unsigned int seed;
61
    if (pw_getrandom(&seed, sizeof(seed), 0) < 0) {
62
pipewire-0.3.72.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.74.tar.gz/src/tools/pw-cat.c Changed
111
 
1
@@ -26,6 +26,7 @@
2
 #include <spa/utils/json.h>
3
 #include <spa/debug/types.h>
4
 
5
+#include <pipewire/cleanup.h>
6
 #include <pipewire/pipewire.h>
7
 #include <pipewire/i18n.h>
8
 #include <pipewire/extensions/metadata.h>
9
@@ -603,7 +604,6 @@
10
 static int parse_channelmap(const char *channel_map, struct channelmap *map)
11
 {
12
    int i, nch;
13
-   char **ch;
14
 
15
    SPA_FOR_EACH_ELEMENT_VAR(maps, m) {
16
        if (spa_streq(m->name, channel_map)) {
17
@@ -614,7 +614,7 @@
18
        }
19
    }
20
 
21
-   ch = pw_split_strv(channel_map, ",", SPA_AUDIO_MAX_CHANNELS, &nch);
22
+   spa_auto(pw_strv) ch = pw_split_strv(channel_map, ",", SPA_AUDIO_MAX_CHANNELS, &nch);
23
    if (ch == NULL)
24
        return -1;
25
 
26
@@ -623,7 +623,7 @@
27
        int c = find_channel(chi);
28
        map->channelsi = c;
29
    }
30
-   pw_free_strv(ch);
31
+
32
    return 0;
33
 }
34
 
35
@@ -1245,7 +1245,8 @@
36
            *s == '\0')
37
            continue;
38
 
39
-       pw_properties_set(data->props, tablec, s);
40
+       if (pw_properties_get(data->props, tablec) == NULL)
41
+           pw_properties_set(data->props, tablec, s);
42
    }
43
 
44
    spa_zero(sfi);
45
@@ -1257,13 +1258,15 @@
46
    spa_zero(fi);
47
    fi.format = sfi.format;
48
    if (sf_command(data->file, SFC_GET_FORMAT_INFO, &fi, sizeof(fi)) == 0 && fi.name)
49
-       pw_properties_set(data->props, PW_KEY_MEDIA_FORMAT, fi.name);
50
+       if (pw_properties_get(data->props, PW_KEY_MEDIA_FORMAT) == NULL)
51
+           pw_properties_set(data->props, PW_KEY_MEDIA_FORMAT, fi.name);
52
 
53
    s = pw_properties_get(data->props, PW_KEY_MEDIA_TITLE);
54
    t = pw_properties_get(data->props, PW_KEY_MEDIA_ARTIST);
55
    if (s && t)
56
-       pw_properties_setf(data->props, PW_KEY_MEDIA_NAME,
57
-               "'%s' / '%s'", s, t);
58
+       if (pw_properties_get(data->props, PW_KEY_MEDIA_NAME) == NULL)
59
+           pw_properties_setf(data->props, PW_KEY_MEDIA_NAME,
60
+                   "'%s' / '%s'", s, t);
61
 
62
    return 0;
63
 }
64
@@ -1494,10 +1497,10 @@
65
    const char *s;
66
    unsigned int nom = 0;
67
 
68
-   if (data->quality >= 0)
69
+   if (data->quality >= 0 && pw_properties_get(data->props, "resample.quality") == NULL)
70
        pw_properties_setf(data->props, "resample.quality", "%d", data->quality);
71
 
72
-   if (data->rate)
73
+   if (data->rate && pw_properties_get(data->props, PW_KEY_NODE_RATE) == NULL)
74
        pw_properties_setf(data->props, PW_KEY_NODE_RATE, "1/%u", data->rate);
75
 
76
    data->latency_unit = unit_none;
77
@@ -1551,7 +1554,7 @@
78
    if (data->verbose)
79
        printf("rate:%d latency:%u (%.3fs)\n",
80
                data->rate, nom, data->rate ? (double)nom/data->rate : 0.0f);
81
-   if (nom)
82
+   if (nom && pw_properties_get(data->props, PW_KEY_NODE_LATENCY) == NULL)
83
        pw_properties_setf(data->props, PW_KEY_NODE_LATENCY, "%u/%u", nom, data->rate);
84
 
85
    return 0;
86
@@ -1785,12 +1788,18 @@
87
    }
88
    data.filename = argvoptind++;
89
 
90
-   pw_properties_set(data.props, PW_KEY_MEDIA_TYPE, data.media_type);
91
-   pw_properties_set(data.props, PW_KEY_MEDIA_CATEGORY, data.media_category);
92
-   pw_properties_set(data.props, PW_KEY_MEDIA_ROLE, data.media_role);
93
-   pw_properties_set(data.props, PW_KEY_MEDIA_FILENAME, data.filename);
94
-   pw_properties_set(data.props, PW_KEY_MEDIA_NAME, data.filename);
95
-   pw_properties_set(data.props, PW_KEY_TARGET_OBJECT, data.target);
96
+   if (pw_properties_get(data.props, PW_KEY_MEDIA_TYPE) == NULL)
97
+       pw_properties_set(data.props, PW_KEY_MEDIA_TYPE, data.media_type);
98
+   if (pw_properties_get(data.props, PW_KEY_MEDIA_CATEGORY) == NULL)
99
+       pw_properties_set(data.props, PW_KEY_MEDIA_CATEGORY, data.media_category);
100
+   if (pw_properties_get(data.props, PW_KEY_MEDIA_ROLE) == NULL)
101
+       pw_properties_set(data.props, PW_KEY_MEDIA_ROLE, data.media_role);
102
+   if (pw_properties_get(data.props, PW_KEY_MEDIA_FILENAME) == NULL)
103
+       pw_properties_set(data.props, PW_KEY_MEDIA_FILENAME, data.filename);
104
+   if (pw_properties_get(data.props, PW_KEY_MEDIA_NAME) == NULL)
105
+       pw_properties_set(data.props, PW_KEY_MEDIA_NAME, data.filename);
106
+   if (pw_properties_get(data.props, PW_KEY_TARGET_OBJECT) == NULL)
107
+       pw_properties_set(data.props, PW_KEY_TARGET_OBJECT, data.target);
108
 
109
    /* make a main loop. If you already have another main loop, you can add
110
     * the fd of this pipewire mainloop to it. */
111
Refresh

No build results available

Refresh

No rpmlint results available

Request History
Bjørn Lie's avatar

zaitor created request almost 2 years ago

New upstream release


Bjørn Lie's avatar

zaitor accepted request almost 2 years ago

Xin