Changes of Revision 14

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Wed Sep  7 13:36:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.57
6
+
7
+-------------------------------------------------------------------
8
 Thu Jul 21 12:08:38 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.56
11
pipewire-aptx.spec Changed
18
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        0.3.56
6
+Version:        0.3.57
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
@@ -20,6 +20,7 @@
11
 BuildRequires:  pkgconfig
12
 BuildRequires:  pkgconfig(bluez)
13
 BuildRequires:  pkgconfig(dbus-1)
14
+BuildRequires:  pkgconfig(glib-2.0)
15
 BuildRequires:  pkgconfig(libfreeaptx)
16
 BuildRequires:  pkgconfig(sbc)
17
 
18
pipewire-0.3.56.tar.gz/.cirrus.yml -> pipewire-0.3.57.tar.gz/.cirrus.yml Changed
10
 
1
@@ -1,7 +1,7 @@
2
 task:
3
   freebsd_instance:
4
     matrix:
5
-      - image_family: freebsd-13-0-snap
6
+      - image_family: freebsd-13-1-snap
7
   env:
8
     # /usr/ports/Mk/Uses/localbase.mk localbase:ldflags
9
     LOCALBASE: /usr/local
10
pipewire-0.3.56.tar.gz/NEWS -> pipewire-0.3.57.tar.gz/NEWS Changed
104
 
1
@@ -1,3 +1,93 @@
2
+# PipeWire 0.3.57 (2022-09-02)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+
9
+## PipeWire
10
+  - Support masking of conf.d/ files. (#2629)
11
+  - Add some more debug info to memfd.
12
+  - Improve data-loop invoke method. Also flush pending items. (#2631)
13
+  - Add a filter-chain systemd service file than can be used to start
14
+    custom filters placed in ~/.conf/pipewire/filter-chain.d/ (#2553)
15
+  - Improve triggered timestamps for remote nodes.
16
+  - Fix some potential cross compilation problems due to wrong
17
+    host_machine.
18
+  - Check return values of pw_getrandom().
19
+
20
+
21
+## Tools
22
+  - Updates to pw-cli manpages. (#2552)
23
+  - Remove the pw-cli dump command. It is mostly implemented as part of
24
+    wpctl status, pw-dump, pw-link, pw-top and others.
25
+  - Clean up resource in pw-cat correctly on errors. (#2651)
26
+
27
+## Modules
28
+  - Fix compilation of AVB on big-endian. Enable AVB only on Linux.
29
+  - Use org.freedesktop.portal.Realtime when available. This does the
30
+    correct PID/TID mappings to make realtime also work from flatpaks.
31
+  - Fix compilation of ROC module when headers are missing. (#2513)
32
+  - Improve some error cleanup paths in protocol-native. Improve connect
33
+    and disconnect.
34
+  - Fix a potential crash in FFT unload in filter-chain.
35
+  - Implement PIPEWIRE_NOTIFICATION_FD for notification when the socket
36
+    is ready.
37
+  - Try to use rtkit if set_nice() fails.
38
+  - Fix rate adjustement logic in pulse-tunnel. This would cause
39
+    increasing delays and hickups when using tunnels. (#2548)
40
+  - Handle disconnect in pulse-tunnel.
41
+
42
+## Bluetooth
43
+  - Add OPUS as a new vendor codec. Add OPUS-A2DP spec. PipeWire can now
44
+    send and reveive OPUS data over bluetooth.
45
+  - An AAC decoder was added so that PipeWire can now also function as
46
+    an A2DP AAC receiver.
47
+
48
+## SPA
49
+  - Tweak the resampler window function some more. (#2574)
50
+  - Improve format convert performance in some fallback cases.
51
+  - Fix rounding in format conversion on ARM NEON.
52
+  - Fix libcamera build error. (#2575)
53
+  - Fix some issues where the wrong samplerate was used. (#2614)
54
+  - Don't wait for more samples that can fit in the ringbuffer in ALSA.
55
+  - Improve buffer size handling in audioconvert, scale the buffers based
56
+    on the rate conversion and make things work with really large rate
57
+    conversions as well.
58
+  - Add more and better debug for ALSA devices.
59
+  - Improve channel mix: Filter FC and LFE when copying from a different
60
+    layout. Implement STEREO from FC. Avoid generating REAR from FC in PSD
61
+    mode.
62
+  - Fix rate match for sources. This fixes an error where follower sources
63
+    would generate many resync warnings.
64
+  - Improve ALSA format negotiation. If the ALSA node is not running and
65
+    there was a previously configured format, close and reopen the device
66
+    to enumerate and accept all possible formats again. (#2625).
67
+
68
+## ALSA
69
+  - The alsa plugin will now also save the volumes set with the control
70
+    API. This saves the volumes set with alsa-mixer, for example.
71
+
72
+## Pulse-server
73
+  - Flatpak apps with devices=all (Zoom) will now be granted Manager
74
+    permissions.
75
+  - Small tweaks to the amount of data sent to clients to work around an
76
+    issue in freerdp.
77
+
78
+## JACK
79
+  - Clean up the transport correctly when closing a client. (#2569)
80
+  - Match context properties in addition to node properties for the jack
81
+    client rules. (#2580)
82
+  - Make sure to return an error when disconnected from the server. (#2606)
83
+  - Fix thread cast problem in jack_client_thread_id().
84
+  - Increase jack_client_name_size() length and make sure we have space for
85
+    the \0 byte.
86
+  - JACK clients from the same application will be added to the same group
87
+    so that they share the quantum and rate.
88
+
89
+
90
+Older versions:
91
+
92
 # PipeWire 0.3.56 (2022-07-19)
93
 
94
 This is a quick bugfix release that is API and ABI compatible with previous
95
@@ -52,8 +142,6 @@
96
   - Add the resampler delay to delay reporting as well.
97
 
98
 
99
-Older versions:
100
-
101
 # PipeWire 0.3.55 (2022-07-12)
102
 
103
 This is a quick bugfix release that is API and ABI compatible with previous
104
pipewire-0.3.56.tar.gz/doc/tutorial3.c -> pipewire-0.3.57.tar.gz/doc/tutorial3.c Changed
124
 
1
@@ -7,32 +7,36 @@
2
 #include <pipewire/pipewire.h>
3
 
4
 /* roundtrip */
5
-static int roundtrip(struct pw_core *core, struct pw_main_loop *loop)
6
+struct roundtrip_data {
7
+   int pending;
8
+   struct pw_main_loop *loop;
9
+};
10
+
11
+static void on_core_done(void *data, uint32_t id, int seq)
12
+{
13
+   struct roundtrip_data *d = data;
14
+
15
+   if (id == PW_ID_CORE && seq == d->pending)
16
+       pw_main_loop_quit(d->loop);
17
+}
18
+
19
+static void roundtrip(struct pw_core *core, struct pw_main_loop *loop)
20
 {
21
-        struct spa_hook core_listener;
22
-        int pending, done = 0;
23
-        void core_event_done(void *object, uint32_t id, int seq) {
24
-                if (id == PW_ID_CORE && seq == pending) {
25
-                        done = 1;
26
-                        pw_main_loop_quit(loop);
27
-                }
28
-        }
29
-        const struct pw_core_events core_events = {
30
-                PW_VERSION_CORE_EVENTS,
31
-                .done = core_event_done,
32
-        };
33
-
34
-        spa_zero(core_listener);
35
-        pw_core_add_listener(core, &core_listener,
36
-                                 &core_events, NULL);
37
-
38
-        pending = pw_core_sync(core, PW_ID_CORE, 0);
39
-
40
-        while (!done) {
41
-                pw_main_loop_run(loop);
42
-        }
43
-        spa_hook_remove(&core_listener);
44
-        return 0;
45
+   static const struct pw_core_events core_events = {
46
+       PW_VERSION_CORE_EVENTS,
47
+       .done = on_core_done,
48
+   };
49
+
50
+   struct roundtrip_data d = { .loop = loop };
51
+   struct spa_hook core_listener;
52
+
53
+   pw_core_add_listener(core, &core_listener, &core_events, &d);
54
+
55
+   d.pending = pw_core_sync(core, PW_ID_CORE, 0);
56
+
57
+   pw_main_loop_run(loop);
58
+
59
+   spa_hook_remove(&core_listener);
60
 }
61
 /* roundtrip */
62
 
63
@@ -50,37 +54,36 @@
64
 
65
 int main(int argc, char *argv)
66
 {
67
-        struct pw_main_loop *loop;
68
-        struct pw_context *context;
69
-        struct pw_core *core;
70
-        struct pw_registry *registry;
71
-        struct spa_hook registry_listener;
72
+   struct pw_main_loop *loop;
73
+   struct pw_context *context;
74
+   struct pw_core *core;
75
+   struct pw_registry *registry;
76
+   struct spa_hook registry_listener;
77
 
78
-        pw_init(&argc, &argv);
79
+   pw_init(&argc, &argv);
80
 
81
-        loop = pw_main_loop_new(NULL /* properties */);
82
-        context = pw_context_new(pw_main_loop_get_loop(loop),
83
-                        NULL /* properties */,
84
-                        0 /* user_data size */);
85
+   loop = pw_main_loop_new(NULL /* properties */);
86
+   context = pw_context_new(pw_main_loop_get_loop(loop),
87
+           NULL /* properties */,
88
+           0 /* user_data size */);
89
 
90
-        core = pw_context_connect(context,
91
-                        NULL /* properties */,
92
-                        0 /* user_data size */);
93
+   core = pw_context_connect(context,
94
+           NULL /* properties */,
95
+           0 /* user_data size */);
96
 
97
-        registry = pw_core_get_registry(core, PW_VERSION_REGISTRY,
98
-                        0 /* user_data size */);
99
+   registry = pw_core_get_registry(core, PW_VERSION_REGISTRY,
100
+           0 /* user_data size */);
101
 
102
-        spa_zero(registry_listener);
103
-        pw_registry_add_listener(registry, &registry_listener,
104
-                                       &registry_events, NULL);
105
+   pw_registry_add_listener(registry, &registry_listener,
106
+                      &registry_events, NULL);
107
 
108
-        roundtrip(core, loop);
109
+   roundtrip(core, loop);
110
 
111
-        pw_proxy_destroy((struct pw_proxy*)registry);
112
-        pw_core_disconnect(core);
113
-        pw_context_destroy(context);
114
-        pw_main_loop_destroy(loop);
115
+   pw_proxy_destroy((struct pw_proxy*)registry);
116
+   pw_core_disconnect(core);
117
+   pw_context_destroy(context);
118
+   pw_main_loop_destroy(loop);
119
 
120
-        return 0;
121
+   return 0;
122
 }
123
 /* code */
124
pipewire-0.3.56.tar.gz/doc/tutorial3.dox -> pipewire-0.3.57.tar.gz/doc/tutorial3.dox Changed
114
 
1
@@ -15,10 +15,9 @@
2
 Let's take a look at what this method does.
3
 
4
 \code{.c}
5
-        struct spa_hook core_listener;
6
-        spa_zero(core_listener);
7
-        pw_core_add_listener(core, &core_listener,
8
-           &core_events, NULL);
9
+   struct spa_hook core_listener;
10
+
11
+   pw_core_add_listener(core, &core_listener, &core_events, &d);
12
 \endcode
13
 
14
 First of all we add a listener for the events of the core
15
@@ -26,37 +25,31 @@
16
 tutorial. This is the event handler:
17
 
18
 \code{.c}
19
-        int pending, done = 0;
20
-
21
-        void core_event_done(void *data, uint32_t id, int seq) {
22
-                if (id == PW_ID_CORE && seq == pending) {
23
-                        done = 1;
24
-                        pw_main_loop_quit(loop);
25
-                }
26
-        }
27
-        const struct pw_core_events core_events = {
28
-                PW_VERSION_CORE_EVENTS,
29
-                .done = core_event_done,
30
-        };
31
+static void on_core_done(void *data, uint32_t id, int seq)
32
+{
33
+   struct roundtrip_data *d = data;
34
+
35
+   if (id == PW_ID_CORE && seq == d->pending)
36
+       pw_main_loop_quit(d->loop);
37
+}
38
 \endcode
39
 
40
-When the done event is received for an object with id `PW_ID_CORE`
41
-and a certain sequence number `seq`, this function will set the done
42
-variable to 1 and call `pw_main_loop_quit()`.
43
+When the done event is received for an object with id `PW_ID_CORE` and
44
+a certain sequence number `seq`, this function will call `pw_main_loop_quit()`.
45
 
46
 Next we do:
47
 
48
 \code{.c}
49
-        pending = pw_core_sync(core, PW_ID_CORE, 0);
50
+   d.pending = pw_core_sync(core, PW_ID_CORE, 0);
51
 \endcode
52
 
53
 This triggers the `sync` method on the core object with id
54
 `PW_ID_CORE` and sequence number 0.
55
 
56
 Because this is a method on a proxy object, it will be executed
57
-asynchronously and the returns value will reflect this. PipeWire
58
+asynchronously and the return value will reflect this. PipeWire
59
 uses the return values of the underlying SPA (Simple Plugin API)
60
-helper objects (See also error codes(spa-design.md#error-codes)).
61
+helper objects (See also \ref page_spa_design ).
62
 
63
 Because all messages on the PipeWire server are handled sequentially,
64
 the sync method will be executed after all previous methods are
65
@@ -68,9 +61,7 @@
66
 receive the events:
67
 
68
 \code{.c}
69
-        while (!done) {
70
-                pw_main_loop_run(loop);
71
-        }
72
+   pw_main_loop_run(loop);
73
 \endcode
74
 
75
 When we get the done event, we can compare it to the sync method
76
@@ -79,7 +70,7 @@
77
 remove the listener:
78
 
79
 \code{.c}
80
-        spa_hook_remove(&core_listener);
81
+   spa_hook_remove(&core_listener);
82
 \endcode
83
 
84
 If we add this roundtrip method to our code and call it instead of the
85
@@ -100,7 +91,7 @@
86
 created them:
87
 
88
 \code{.c}
89
-        pw_proxy_destroy((struct pw_proxy*)registry);
90
+   pw_proxy_destroy((struct pw_proxy*)registry);
91
 \endcode
92
 
93
 The registry is a proxy and can be destroyed with the generic proxy destroy
94
@@ -110,7 +101,7 @@
95
 We can disconnect from the server with:
96
 
97
 \code{.c}
98
-        pw_core_disconnect(core);
99
+   pw_core_disconnect(core);
100
 \endcode
101
 
102
 This will also destroy the core proxy object and will remove the proxies
103
@@ -119,8 +110,8 @@
104
 We can finally destroy our context and mainloop to conclude this tutorial:
105
 
106
 \code{.c}
107
-        pw_context_destroy(context);
108
-        pw_main_loop_destroy(loop);
109
+   pw_context_destroy(context);
110
+   pw_main_loop_destroy(loop);
111
 \endcode
112
 
113
 \ref page_tutorial2 | \ref page_tutorial "Index" | \ref page_tutorial4
114
pipewire-0.3.56.tar.gz/man/pw-cli.1.rst.in -> pipewire-0.3.57.tar.gz/man/pw-cli.1.rst.in Changed
100
 
1
@@ -34,17 +34,20 @@
2
 GENERAL COMMANDS
3
 ================
4
 
5
-help
6
-  Show a quick help on the commands available.
7
+help | h
8
+  Show a quick help on the commands available. It also lists the aliases
9
+  for many commands.
10
 
11
-quit
12
+quit | q
13
   Exit from **pw-cli**
14
 
15
 MODULE MANAGEMENT
16
 =================
17
 
18
-| Modules are loaded and unloaded in the local instance and can add
19
-| functionality or objects to the local instance.
20
+| Modules are loaded and unloaded in the local instance, thus the pw-cli
21
+| binary itself and can add functionality or objects to the local
22
+| instance. It is not possible in PipeWire to load modules in another
23
+| instance.
24
 
25
 load-module *name* *arguments...*
26
   Load a module specified by its name and arguments. For most
27
@@ -105,14 +108,22 @@
28
 
29
   This command returns a *node variable*.
30
 
31
-destroy-node *node-var*
32
-  Destroy a node.
33
-
34
 export-node *node-id* *remote-var*
35
   Export a node from the local instance to the specified instance.
36
   When no instance is specified, the node will be exported to the current
37
   instance.
38
 
39
+DEVICE MANAGEMENT
40
+=================
41
+
42
+create-device *factory-name* *properties...*
43
+  Create a device from a factory in the current instance.
44
+
45
+  Properties are key=value pairs separated by whitespace.
46
+
47
+  This command returns a *device variable*.
48
+
49
+
50
 LINK MANAGEMENT
51
 ===============
52
 
53
@@ -125,8 +136,44 @@
54
 
55
   This command returns a *link variable*.
56
 
57
-destroy-link *link-var*
58
-  Destroy a link.
59
+GLOBALS MANAGEMENT
60
+==================
61
+
62
+destroy *object-id*
63
+  Destroy a global object.
64
+
65
+
66
+PARAMETER MANAGEMENT
67
+====================
68
+
69
+enum-params *object-id* *param-id*
70
+  Enumerate params of an object.
71
+
72
+  *param-id* can also be given as the param short name.
73
+
74
+set-param *object-id* *param-id* *param-json*
75
+  Set param of an object.
76
+
77
+  *param-id* can also be given as the param short name.
78
+
79
+PERMISSION MANAGEMENT
80
+=====================
81
+
82
+permissions *client-id* *object-id* *permission*
83
+  Set permissions for a client.
84
+
85
+  *object-id* can be *-1* to set the default permissions.
86
+
87
+get-permissions *client-id*
88
+  Get permissions of a client.
89
+
90
+
91
+COMMAND MANAGEMENT
92
+==================
93
+
94
+send-command *object-id*
95
+  Send a command to an object.
96
+
97
 
98
 EXAMPLES
99
 ========
100
pipewire-0.3.56.tar.gz/meson.build -> pipewire-0.3.57.tar.gz/meson.build Changed
43
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.56',
4
+  version : '0.3.57',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.59.0',
7
   default_options :  'warning_level=3',
8
@@ -295,6 +295,11 @@
9
 cap_lib = dependency('libcap', required : false)
10
 cdata.set('HAVE_LIBCAP', cap_lib.found())
11
 
12
+glib2_dep = dependency('glib-2.0', required : get_option('flatpak'))
13
+summary({'GLib-2.0 (Flatpak support)': glib2_dep.found()}, bool_yn: true, section: 'Misc dependencies')
14
+flatpak_support = glib2_dep.found()
15
+cdata.set('HAVE_GLIB2', flatpak_support)
16
+
17
 gst_option = get_option('gstreamer')
18
 gst_deps_def = {
19
   'glib-2.0': {'version': '>=2.32.0'},
20
@@ -337,11 +342,11 @@
21
 cdata.set('HAVE_WEBRTC', webrtc_dep.found())
22
 
23
 # On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd()
24
-epoll_shim_dep = (build_machine.system() == 'freebsd' or build_machine.system() == 'midnightbsd'
25
+epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
26
     ? dependency('epoll-shim', required: true)
27
     : dependency('', required: false))
28
 
29
-libinotify_dep = (build_machine.system() == 'freebsd' or build_machine.system() == 'midnightbsd'
30
+libinotify_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
31
     ? dependency('libinotify', required: true)
32
     : dependency('', required: false))
33
 
34
@@ -356,7 +361,7 @@
35
 alsa_dep = dependency('alsa', version : '>=1.1.7', required: need_alsa)
36
 summary({'pipewire-alsa': alsa_dep.found()}, bool_yn: true)
37
 
38
-if build_machine.system() == 'freebsd' or build_machine.system() == 'midnightbsd'
39
+if host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
40
 # On FreeBSD and MidnightBSD the OpenSSL library may come from base or a package.
41
 # Check for a package first and fallback to the base library if we can't find it via pkgconfig
42
     openssl_lib = dependency('openssl', required: false)
43
pipewire-0.3.56.tar.gz/meson_options.txt -> pipewire-0.3.57.tar.gz/meson_options.txt Changed
20
 
1
@@ -116,6 +116,10 @@
2
         description: 'Enable LC3plus open source codec implementation',
3
         type: 'feature',
4
         value: 'auto')
5
+option('bluez5-codec-opus',
6
+        description: 'Enable Opus open source codec implementation',
7
+        type: 'feature',
8
+        value: 'auto')
9
 option('control',
10
        description: 'Enable control spa plugin integration',
11
        type: 'feature',
12
@@ -249,3 +253,7 @@
13
        description: 'Enable AVB code',
14
        type: 'feature',
15
        value: 'auto')
16
+option('flatpak',
17
+       description: 'Enable Flatpak support',
18
+       type: 'feature',
19
+       value: 'enabled')
20
pipewire-0.3.56.tar.gz/pipewire-alsa/alsa-plugins/ctl_pipewire.c -> pipewire-0.3.57.tar.gz/pipewire-alsa/alsa-plugins/ctl_pipewire.c Changed
9
 
1
@@ -532,6 +532,7 @@
2
        spa_pod_builder_add(&b,
3
            SPA_PARAM_ROUTE_index, SPA_POD_Int(id),
4
            SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id),
5
+           SPA_PARAM_ROUTE_save, SPA_POD_Bool(true),
6
            0);
7
 
8
        spa_pod_builder_prop(&b, SPA_PARAM_ROUTE_props, 0);
9
pipewire-0.3.56.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.57.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
92
 
1
@@ -62,7 +62,7 @@
2
 
3
 #define DEFAULT_RT_MAX 88
4
 
5
-#define JACK_CLIENT_NAME_SIZE      128
6
+#define JACK_CLIENT_NAME_SIZE      256
7
 #define JACK_PORT_NAME_SIZE        256
8
 #define JACK_PORT_TYPE_SIZE             32
9
 #define MONITOR_EXT            " Monitor"
10
@@ -800,7 +800,7 @@
11
    } else {                        \
12
        if (c->active)                  \
13
            (expr);                 \
14
-       pw_log_debug("skip " #callback          \
15
+       pw_log_debug("skip " #callback          \
16
            " cb:%p active:%d", c->callback,    \
17
            c->active);             \
18
    }                           \
19
@@ -817,6 +817,9 @@
20
            res = c->callback(__VA_ARGS__);     \
21
            c->rt_locked = false;           \
22
            pthread_mutex_unlock(&c->rt_lock);  \
23
+       } else {                    \
24
+           pw_log_debug("skip " #callback      \
25
+               " cb:%p", c->callback);     \
26
        }                       \
27
    }                           \
28
    res;                            \
29
@@ -871,6 +874,8 @@
30
        pw_log_warn("sync requested from callback");
31
        return 0;
32
    }
33
+   if (client->last_res == -EPIPE)
34
+       return -EPIPE;
35
 
36
    client->last_res = 0;
37
    client->pending_sync = pw_proxy_sync((struct pw_proxy*)client->core, client->pending_sync);
38
@@ -3279,7 +3284,7 @@
39
            "jack.properties", client->props);
40
 
41
    pw_context_conf_section_match_rules(client->context.context, "jack.rules",
42
-           &client->props->dict, execute_match, client);
43
+           &client->context.context->properties->dict, execute_match, client);
44
 
45
    support = pw_context_get_support(client->context.context, &n_support);
46
 
47
@@ -3356,6 +3361,8 @@
48
    }
49
    if (pw_properties_get(client->props, PW_KEY_NODE_NAME) == NULL)
50
        pw_properties_set(client->props, PW_KEY_NODE_NAME, client_name);
51
+   if (pw_properties_get(client->props, PW_KEY_NODE_GROUP) == NULL)
52
+       pw_properties_setf(client->props, PW_KEY_NODE_GROUP, "jack-%d", getpid());
53
    if (pw_properties_get(client->props, PW_KEY_NODE_DESCRIPTION) == NULL)
54
        pw_properties_set(client->props, PW_KEY_NODE_DESCRIPTION, client_name);
55
    if (pw_properties_get(client->props, PW_KEY_MEDIA_TYPE) == NULL)
56
@@ -3492,6 +3499,8 @@
57
 
58
    res = jack_deactivate(client);
59
 
60
+   clean_transport(c);
61
+
62
    if (c->context.loop)
63
        pw_thread_loop_stop(c->context.loop);
64
 
65
@@ -3577,8 +3586,9 @@
66
 SPA_EXPORT
67
 int jack_client_name_size (void)
68
 {
69
-   pw_log_trace("%d", JACK_CLIENT_NAME_SIZE);
70
-   return JACK_CLIENT_NAME_SIZE;
71
+   /* The JACK API specifies that this value includes the final NULL character. */
72
+   pw_log_trace("%d", JACK_CLIENT_NAME_SIZE+1);
73
+   return JACK_CLIENT_NAME_SIZE+1;
74
 }
75
 
76
 SPA_EXPORT
77
@@ -3765,12 +3775,12 @@
78
    struct client *c = (struct client *) client;
79
    void *thr;
80
 
81
-   spa_return_val_if_fail(c != NULL, -EINVAL);
82
+   spa_return_val_if_fail(c != NULL, (pthread_t){0});
83
 
84
    thr = pw_data_loop_get_thread(c->loop);
85
    if (thr == NULL)
86
        return pthread_self();
87
-   return *(pthread_t*)thr;
88
+   return (pthread_t) thr;
89
 }
90
 
91
 SPA_EXPORT
92
pipewire-0.3.56.tar.gz/po/LINGUAS -> pipewire-0.3.57.tar.gz/po/LINGUAS Changed
9
 
1
@@ -21,6 +21,7 @@
2
 id
3
 it
4
 ja
5
+ka
6
 kk
7
 kn
8
 ko
9
pipewire-0.3.56.tar.gz/po/ca.po -> pipewire-0.3.57.tar.gz/po/ca.po Changed
201
 
1
@@ -5,6 +5,7 @@
2
 # Xavier Conde Rueda <xavi.conde@gmail.com>, 2008.
3
 # Agustí Grau <fletxa@gmail.com>, 2009.
4
 # Judith Pintó Subirada <judithp@gmail.com>
5
+# Jordi Mas i Herǹandez, <jmas@softcatala.org>, 2022
6
 #
7
 # This file is translated according to the glossary and style guide of
8
 # Softcatalà. If you plan to modify this file, please read first the page
9
@@ -26,11 +27,10 @@
10
 msgid ""
11
 msgstr ""
12
 "Project-Id-Version: pipewire\n"
13
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
14
-"issues/new\n"
15
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/issues/new\n"
16
 "POT-Creation-Date: 2021-04-18 16:54+0800\n"
17
-"PO-Revision-Date: 2012-01-30 09:52+0000\n"
18
-"Last-Translator: Josep Torné Llavall <josep.torne@gmail.com>\n"
19
+"PO-Revision-Date: 2022-09-01 19:24+0000\n"
20
+"Last-Translator: Jordi Mas i Herǹandez, <jmas@softcatala.org>,\n"
21
 "Language-Team: Catalan <fedora@softcatala.net>\n"
22
 "Language: ca\n"
23
 "MIME-Version: 1.0\n"
24
@@ -45,14 +45,18 @@
25
 "      --version                         Show version\n"
26
 "  -c, --config                          Load config (Default %s)\n"
27
 msgstr ""
28
+"%s opcions\n"
29
+"  -h, --help                            Mostra aquesta ajuda\n"
30
+"      --version                         Mostra la versió\n"
31
+"  -c, --config                          Carrega la configuració (predeterminada %s)\n"
32
 
33
 #: src/daemon/pipewire.desktop.in:4
34
 msgid "PipeWire Media System"
35
-msgstr ""
36
+msgstr "Sistema multimèdia PipeWire"
37
 
38
 #: src/daemon/pipewire.desktop.in:5
39
 msgid "Start the PipeWire Media System"
40
-msgstr ""
41
+msgstr "Inicia el sistema multimèdia PipeWire"
42
 
43
 #: src/examples/media-session/alsa-monitor.c:526
44
 #: spa/plugins/alsa/acp/compat.c:187
45
@@ -66,7 +70,7 @@
46
 
47
 #: src/examples/media-session/alsa-monitor.c:539
48
 msgid "Unknown device"
49
-msgstr ""
50
+msgstr "Dispositiu desconegut"
51
 
52
 #: src/tools/pw-cat.c:991
53
 #, c-format
54
@@ -77,9 +81,13 @@
55
 "  -v, --verbose                         Enable verbose operations\n"
56
 "\n"
57
 msgstr ""
58
+"%s opcions <fitxer>\n"
59
+"  -h, --help                            Mostra aquesta ajuda\n"
60
+"      --version                         Mostra la versió\n"
61
+"  -v, --verbose                         Habilita les operacions detallades\n"
62
 
63
 #: src/tools/pw-cat.c:998
64
-#, c-format
65
+#, c-format, fuzzy
66
 msgid ""
67
 "  -R, --remote                          Remote daemon name\n"
68
 "      --media-type                      Set media type (default %s)\n"
69
@@ -90,42 +98,58 @@
70
 "      --latency                         Set node latency (default %s)\n"
71
 "                                          Xunit (unit = s, ms, us, ns)\n"
72
 "                                          or direct samples (256)\n"
73
-"                                          the rate is the one of the source "
74
-"file\n"
75
+"                                          the rate is the one of the source file\n"
76
 "      --list-targets                    List available targets for --target\n"
77
 "\n"
78
 msgstr ""
79
+"-R, --remote Nom del dimoni remot\n"
80
+"      --media-type Estableix el tipus de mitjà (per defecte %s)\n"
81
+"      --media-category Estableix la categoria dels mitjans (per defecte %s)\n"
82
+"      --media-role Estableix el rol del mitjà (per defecte %s)\n"
83
+"      --target Estableix l'objectiu del node (per defecte %s)\n"
84
+"                                          0 vol dir que no enllaça\n"
85
+"      --latency Estableix latència del node (per defecte %s)\n"
86
+"                                          Xunit (unitat = s, ms, us, ns)\n"
87
+"                                          o mostres directes (256)\n"
88
+"                                          la taxa és la del fitxer d'origen\n"
89
+"      --list-targets Llista d'objectius disponibles per a --target"
90
 
91
 #: src/tools/pw-cat.c:1016
92
-#, c-format
93
+#, c-format, fuzzy
94
 msgid ""
95
-"      --rate                            Sample rate (req. for rec) (default "
96
-"%u)\n"
97
-"      --channels                        Number of channels (req. for rec) "
98
-"(default %u)\n"
99
+"      --rate                            Sample rate (req. for rec) (default %u)\n"
100
+"      --channels                        Number of channels (req. for rec) (default %u)\n"
101
 "      --channel-map                     Channel map\n"
102
-"                                            one of: \"stereo\", "
103
-"\"surround-51\",... or\n"
104
-"                                            comma separated list of channel "
105
-"names: eg. \"FL,FR\"\n"
106
-"      --format                          Sample format %s (req. for rec) "
107
-"(default %s)\n"
108
+"                                            one of: \"stereo\", \"surround-51\",... or\n"
109
+"                                            comma separated list of channel names: eg. \"FL,FR\"\n"
110
+"      --format                          Sample format %s (req. for rec) (default %s)\n"
111
 "      --volume                          Stream volume 0-1.0 (default %.3f)\n"
112
-"  -q  --quality                         Resampler quality (0 - 15) (default "
113
-"%d)\n"
114
+"  -q  --quality                         Resampler quality (0 - 15) (default %d)\n"
115
 "\n"
116
 msgstr ""
117
+"--rate Freqüència de mostreig (req. per rec) (predeterminat %u)\n"
118
+"      --channels Nombre de canals (req. per rec) (predeterminat %u)\n"
119
+"      --channel-map Mapa de canals\n"
120
+"                                            un dels següents: \"estèreo\", \"surround-51\",... o\n"
121
+"                                            Llista separada per comes dels noms dels canals: per exemple. \"FL,FR\"\n"
122
+"      --format Format de mostra %s (req. per a rec) (predeterminat %s)\n"
123
+"      --volume Volum de flux 0-1.0 (predeterminat %.3f)\n"
124
+"  -q --qualitat Remostrador de qualitat (0 - 15) (per defecte %d)"
125
 
126
 #: src/tools/pw-cat.c:1033
127
+#, fuzzy
128
 msgid ""
129
 "  -p, --playback                        Playback mode\n"
130
 "  -r, --record                          Recording mode\n"
131
 "  -m, --midi                            Midi mode\n"
132
 "\n"
133
 msgstr ""
134
+"-p, --playback Mode de reproducció\n"
135
+"  -r, --record mode d'enregistrament\n"
136
+"  -m, --midi Mode MIDI"
137
 
138
 #: src/tools/pw-cli.c:2932
139
-#, c-format
140
+#, c-format, fuzzy
141
 msgid ""
142
 "%s options command\n"
143
 "  -h, --help                            Show this help\n"
144
@@ -134,10 +158,15 @@
145
 "  -r, --remote                          Remote daemon name\n"
146
 "\n"
147
 msgstr ""
148
+"%s opcions ordre\n"
149
+"  -h, --help Mostra aquesta ajuda\n"
150
+"      --version Mostra la versió\n"
151
+"  -d, --daemon Inicia com a dimoni (fals predeterminat)\n"
152
+"  -r, --remote Nom del dimoni remot"
153
 
154
 #: spa/plugins/alsa/acp/acp.c:290
155
 msgid "Pro Audio"
156
-msgstr ""
157
+msgstr "Pro Audio"
158
 
159
 #: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704
160
 #: spa/plugins/bluez5/bluez5-device.c:1000
161
@@ -252,25 +281,23 @@
162
 
163
 #: spa/plugins/alsa/acp/alsa-mixer.c:2801
164
 msgid "Dock Microphone"
165
-msgstr ""
166
+msgstr "Micròfon de l'acoblador"
167
 
168
 #: spa/plugins/alsa/acp/alsa-mixer.c:2803
169
 msgid "Headset Microphone"
170
-msgstr ""
171
+msgstr "Micròfon d'auriculars"
172
 
173
 #: spa/plugins/alsa/acp/alsa-mixer.c:2807
174
 msgid "Analog Output"
175
 msgstr "Sortida analògica"
176
 
177
 #: spa/plugins/alsa/acp/alsa-mixer.c:2809
178
-#, fuzzy
179
 msgid "Headphones 2"
180
-msgstr "Auriculars"
181
+msgstr "Auriculars 2"
182
 
183
 #: spa/plugins/alsa/acp/alsa-mixer.c:2810
184
-#, fuzzy
185
 msgid "Headphones Mono Output"
186
-msgstr "Sortida mono analògica"
187
+msgstr "Sortida mono dels auriculars"
188
 
189
 #: spa/plugins/alsa/acp/alsa-mixer.c:2811
190
 msgid "Line Out"
191
@@ -297,49 +324,41 @@
192
 msgstr "Entrada digital (S/PDIF)"
193
 
194
 #: spa/plugins/alsa/acp/alsa-mixer.c:2817
195
-#, fuzzy
196
 msgid "Multichannel Input"
197
-msgstr "Multicanal"
198
+msgstr "Entrada multicanal"
199
 
200
 #: spa/plugins/alsa/acp/alsa-mixer.c:2818
201
pipewire-0.3.56.tar.gz/po/gl.po -> pipewire-0.3.57.tar.gz/po/gl.po Changed
201
 
1
@@ -4,25 +4,31 @@
2
 # Translators:
3
 # bassball93 <bassball93@gmail.com>, 2011.
4
 # mbouzada <mbouzada@gmail.com>, 2011.
5
-# Fran Dieguez <frandieguez@gnome.org>, 2012, 2019.
6
 # Marcos Lans <marcoslansgarza@gmail.com>, 2018.
7
+# Fran Dieguez <frandieguez@gnome.org>, 2012-2022.
8
+#
9
 msgid ""
10
 msgstr ""
11
 "Project-Id-Version: PipeWire\n"
12
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
13
-"issues/new\n"
14
-"POT-Creation-Date: 2021-04-18 16:54+0800\n"
15
-"PO-Revision-Date: 2019-02-20 01:36+0200\n"
16
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
17
+"issues\n"
18
+"POT-Creation-Date: 2022-07-10 03:27+0000\n"
19
+"PO-Revision-Date: 2022-08-23 09:47+0200\n"
20
 "Last-Translator: Fran Dieguez <frandieguez@gnome.org>\n"
21
-"Language-Team: Galician\n"
22
+"Language-Team: Galician <Proxecto Trasno <proxecto@trasno.gal>>\n"
23
 "Language: gl\n"
24
 "MIME-Version: 1.0\n"
25
 "Content-Type: text/plain; charset=UTF-8\n"
26
 "Content-Transfer-Encoding: 8bit\n"
27
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
28
-"X-Generator: Virtaal 0.7.1\n"
29
-
30
-#: src/daemon/pipewire.c:43
31
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
32
+"X-Generator: Gtranslator 40.0\n"
33
+"X-DL-Team: gl\n"
34
+"X-DL-Module: PipeWire\n"
35
+"X-DL-Branch: master\n"
36
+"X-DL-Domain: po\n"
37
+"X-DL-State: Translating\n"
38
+
39
+#: src/daemon/pipewire.c:46
40
 #, c-format
41
 msgid ""
42
 "%s options\n"
43
@@ -30,6 +36,11 @@
44
 "      --version                         Show version\n"
45
 "  -c, --config                          Load config (Default %s)\n"
46
 msgstr ""
47
+"%s opcións\n"
48
+"  -h, --help                            Mostra esta axuda\n"
49
+"      --version                         Mostrar versión\n"
50
+"  -c, --config                          Cargar configuración (Predeterminado "
51
+"%s)\n"
52
 
53
 #: src/daemon/pipewire.desktop.in:4
54
 msgid "PipeWire Media System"
55
@@ -39,31 +50,52 @@
56
 msgid "Start the PipeWire Media System"
57
 msgstr "Iniciar o Sistema multimedia PipeWire"
58
 
59
-#: src/examples/media-session/alsa-monitor.c:526
60
-#: spa/plugins/alsa/acp/compat.c:187
61
-msgid "Built-in Audio"
62
-msgstr "Audio interno"
63
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
64
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
65
+#, c-format
66
+msgid "Tunnel to %s/%s"
67
+msgstr "Túnel a %s/%s"
68
 
69
-#: src/examples/media-session/alsa-monitor.c:530
70
-#: spa/plugins/alsa/acp/compat.c:192
71
-msgid "Modem"
72
-msgstr "Módem"
73
+#: src/modules/module-fallback-sink.c:51
74
+#| msgid "Game Output"
75
+msgid "Dummy Output"
76
+msgstr "Saída de proba"
77
 
78
-#: src/examples/media-session/alsa-monitor.c:539
79
+#: src/modules/module-pulse-tunnel.c:648
80
+#, c-format
81
+msgid "Tunnel for %s@%s"
82
+msgstr "Túnel para %s@%s"
83
+
84
+#: src/modules/module-zeroconf-discover.c:332
85
 msgid "Unknown device"
86
-msgstr ""
87
+msgstr "Dispositivo descoñecido"
88
+
89
+#: src/modules/module-zeroconf-discover.c:344
90
+#, c-format
91
+msgid "%s on %s@%s"
92
+msgstr "%s en %s@%s"
93
+
94
+#: src/modules/module-zeroconf-discover.c:348
95
+#, c-format
96
+msgid "%s on %s"
97
+msgstr "%s en %s"
98
 
99
-#: src/tools/pw-cat.c:991
100
+#: src/tools/pw-cat.c:784
101
 #, c-format
102
 msgid ""
103
-"%s options <file>\n"
104
+"%s options <file>|-\n"
105
 "  -h, --help                            Show this help\n"
106
 "      --version                         Show version\n"
107
 "  -v, --verbose                         Enable verbose operations\n"
108
 "\n"
109
 msgstr ""
110
+"%s opcións <ficheiro>|-\n"
111
+"  -h, --help                            Mostrar esta axuda\n"
112
+"      --version                         Mostrar versión\n"
113
+"  -v, --verbose                         Activar operacións verbosas\n"
114
+"\n"
115
 
116
-#: src/tools/pw-cat.c:998
117
+#: src/tools/pw-cat.c:791
118
 #, c-format
119
 msgid ""
120
 "  -R, --remote                          Remote daemon name\n"
121
@@ -77,11 +109,29 @@
122
 "                                          or direct samples (256)\n"
123
 "                                          the rate is the one of the source "
124
 "file\n"
125
-"      --list-targets                    List available targets for --target\n"
126
+"  -P  --properties                      Set node properties\n"
127
 "\n"
128
 msgstr ""
129
+"  -R, --remote                          Nome do daemon remoto\n"
130
+"      --media-type                      Estabelecer o tipo de medio (por "
131
+"omisión %s)\n"
132
+"      --media-category                  Estabelecer a categoría multimedia "
133
+"(por omisión %s)\n"
134
+"      --media-role                      Estabelecer o rol multimedia (por "
135
+"omisión %s)\n"
136
+"      --target                          Estabelecer o nodo obxectivo (por "
137
+"omisión %s)\n"
138
+"                                          0 significa non ligar\n"
139
+"      --latency                         Estabelecer a latencia do nodo (por "
140
+"omisión %s)\n"
141
+"                                          Xunit (unidade = s, ms, us, ns)\n"
142
+"                                          ou mostras directas samples (256)\n"
143
+"                                          a taxa é un dos ficheiros de "
144
+"orixe\n"
145
+"  -P  --properties                      Estabelecer as propiedades do nodo\n"
146
+"\n"
147
 
148
-#: src/tools/pw-cat.c:1016
149
+#: src/tools/pw-cat.c:809
150
 #, c-format
151
 msgid ""
152
 "      --rate                            Sample rate (req. for rec) (default "
153
@@ -100,16 +150,38 @@
154
 "%d)\n"
155
 "\n"
156
 msgstr ""
157
+"      --rate                            Taxa de mostreo (solicitudes por "
158
+"segundo) (por omisión %u)\n"
159
+"      --channels                        Número de canles (solicitudes por "
160
+"segundo) (por omisión %u)\n"
161
+"      --channel-map                     Mapa de canles\n"
162
+"                                            un de: \"stereo\", "
163
+"\"surround-51\",... or\n"
164
+"                                            lista separada por comas dos "
165
+"nomes das canles: p.ex. \"FL,FR\"\n"
166
+"      --format                          Formato de mostras %s (solicitudes "
167
+"por segundo) (por omisión %s)\n"
168
+"      --volume                          Volume do fluxo 0-1.0 (por omisión "
169
+"%.3f)\n"
170
+"  -q  --quality                         Calidade do remostreador (0 - 15) "
171
+"(por omisión %d)\n"
172
+"\n"
173
 
174
-#: src/tools/pw-cat.c:1033
175
+#: src/tools/pw-cat.c:826
176
 msgid ""
177
 "  -p, --playback                        Playback mode\n"
178
 "  -r, --record                          Recording mode\n"
179
 "  -m, --midi                            Midi mode\n"
180
+"  -d, --dsd                             DSD mode\n"
181
 "\n"
182
 msgstr ""
183
+"  -p, --playback                        Modo de reprodución\n"
184
+"  -r, --record                          Modo de grabación\n"
185
+"  -m, --midi                            Modo MIDI\n"
186
+"  -d, --dsd                             Modo DSD\n"
187
+"\n"
188
 
189
-#: src/tools/pw-cli.c:2932
190
+#: src/tools/pw-cli.c:3165
191
 #, c-format
192
 msgid ""
193
 "%s options command\n"
194
@@ -119,355 +191,352 @@
195
 "  -r, --remote                          Remote daemon name\n"
196
 "\n"
197
 msgstr ""
198
+"%s opcións orde\n"
199
+"  -h, --help                            Mostrar esta axuda\n"
200
+"      --version                         Mostrar versión\n"
201
pipewire-0.3.57.tar.gz/po/ka.po Added
201
 
1
@@ -0,0 +1,661 @@
2
+# SOME DESCRIPTIVE TITLE.
3
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
4
+# This file is distributed under the same license as the pipewire package.
5
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
6
+#
7
+msgid ""
8
+msgstr ""
9
+"Project-Id-Version: pipewire\n"
10
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
11
+"issues/new\n"
12
+"POT-Creation-Date: 2022-06-30 12:50+0200\n"
13
+"PO-Revision-Date: 2022-07-25 13:11+0200\n"
14
+"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
15
+"Language-Team: Georgian <(nothing)>\n"
16
+"Language: ka\n"
17
+"MIME-Version: 1.0\n"
18
+"Content-Type: text/plain; charset=UTF-8\n"
19
+"Content-Transfer-Encoding: 8bit\n"
20
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
21
+"X-Generator: Poedit 3.1.1\n"
22
+
23
+#: src/daemon/pipewire.c:46
24
+#, c-format
25
+msgid ""
26
+"%s options\n"
27
+"  -h, --help                            Show this help\n"
28
+"      --version                         Show version\n"
29
+"  -c, --config                          Load config (Default %s)\n"
30
+msgstr ""
31
+"%s პარამეტრები\n"
32
+"   -h, --help ამ დახმარების ჩვენება\n"
33
+"       --version ვერსიის ჩვენება\n"
34
+"   -c, --config ჩატვირთვის კონფიგურაცია (ნაგულისხმები %s)\n"
35
+
36
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
37
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
38
+#, c-format
39
+msgid "Tunnel to %s/%s"
40
+msgstr "გვირაბი %s/%s -მდე"
41
+
42
+#: src/modules/module-fallback-sink.c:51
43
+msgid "Dummy Output"
44
+msgstr "ნულოვანი გამოყვანა"
45
+
46
+#: src/modules/module-pulse-tunnel.c:648
47
+#, c-format
48
+msgid "Tunnel for %s@%s"
49
+msgstr "გვირაბი %s@%s-სთვის"
50
+
51
+#: src/modules/module-zeroconf-discover.c:332
52
+msgid "Unknown device"
53
+msgstr "უცნობი მოწყობილობა"
54
+
55
+#: src/modules/module-zeroconf-discover.c:344
56
+#, c-format
57
+msgid "%s on %s@%s"
58
+msgstr "%s %s@%s -ზე"
59
+
60
+#: src/modules/module-zeroconf-discover.c:348
61
+#, c-format
62
+msgid "%s on %s"
63
+msgstr "%s %s-ზე"
64
+
65
+#: src/tools/pw-cat.c:784
66
+#, c-format
67
+msgid ""
68
+"%s options <file>|-\n"
69
+"  -h, --help                            Show this help\n"
70
+"      --version                         Show version\n"
71
+"  -v, --verbose                         Enable verbose operations\n"
72
+"\n"
73
+msgstr ""
74
+"%s პარამეტრები <ფაილი>|-\n"
75
+"   -h, --help ამ დახმარების ჩვენება\n"
76
+"       --version ვერსიის ჩვენება\n"
77
+"   -v, --verbose დამატებითი შეტყობინებების გამოტანა\n"
78
+"\n"
79
+
80
+#: src/tools/pw-cat.c:791
81
+#, c-format
82
+msgid ""
83
+"  -R, --remote                          Remote daemon name\n"
84
+"      --media-type                      Set media type (default %s)\n"
85
+"      --media-category                  Set media category (default %s)\n"
86
+"      --media-role                      Set media role (default %s)\n"
87
+"      --target                          Set node target (default %s)\n"
88
+"                                          0 means don't link\n"
89
+"      --latency                         Set node latency (default %s)\n"
90
+"                                          Xunit (unit = s, ms, us, ns)\n"
91
+"                                          or direct samples (256)\n"
92
+"                                          the rate is the one of the source "
93
+"file\n"
94
+"  -P  --properties                      Set node properties\n"
95
+"\n"
96
+msgstr ""
97
+"  -R, --remote დაშორებული დემონის სახელი\n"
98
+"       --media-type მედიის ტიპის დაყენება (ნაგულისხმები %s)\n"
99
+"       --media-category მედია კატეგორიის დაყენება (ნაგულისხმები %s)\n"
100
+"       --media-role მედიის როლის დაყენება (ნაგულისხმები %s)\n"
101
+"       --target კვანძის სამიზნის დაყენება (ნაგულისხმები %s)\n"
102
+"                                           0 ნიშნავს არ მიბმა\n"
103
+"       --latency კვანძის შეყოვნების დაყენება (ნაგულისხმები %s)\n"
104
+"                                           Xunit (ერთეული = s, ms, us, ns)\n"
105
+"                                           ან პირდაპირი ნიმუშები (256)\n"
106
+"                                           მაჩვენებელი არის ერთ-ერთი წყაროს "
107
+"ფაილი\n"
108
+"   -P --properties კვანძის თვისებების დაყენება\n"
109
+
110
+#: src/tools/pw-cat.c:809
111
+#, c-format
112
+msgid ""
113
+"      --rate                            Sample rate (req. for rec) (default "
114
+"%u)\n"
115
+"      --channels                        Number of channels (req. for rec) "
116
+"(default %u)\n"
117
+"      --channel-map                     Channel map\n"
118
+"                                            one of: \"stereo\", "
119
+"\"surround-51\",... or\n"
120
+"                                            comma separated list of channel "
121
+"names: eg. \"FL,FR\"\n"
122
+"      --format                          Sample format %s (req. for rec) "
123
+"(default %s)\n"
124
+"      --volume                          Stream volume 0-1.0 (default %.3f)\n"
125
+"  -q  --quality                         Resampler quality (0 - 15) (default "
126
+"%d)\n"
127
+"\n"
128
+msgstr ""
129
+"    --rate სემპლის_სიჩქარე (მოთხოვნილება rec.) (ნაგულისხმები %u)\n"
130
+"       --channels არხების რაოდენობა (მოთხოვნილი ჩანაწერისთვის) (ნაგულისხმები "
131
+"%u)\n"
132
+"       --channel-map არხის რუკა\n"
133
+"                                             ერთ-ერთი: \"stereo\", "
134
+"\"surround-51\",... ან\n"
135
+"                                             მძიმით გამოყოფილი არხის "
136
+"სახელების სია: მაგ. \"FL, FR\"\n"
137
+"       --format                     ნიმუშის ფორმატი %s (მოთხოვნილება rec.) "
138
+"(ნაგულისხმები %s)\n"
139
+"       --volume               ნაკადის მოცულობა 0-1.0 (ნაგულისხმები %.3f)\n"
140
+"   -q --quality                         Resampler ხარისხი (0 - 15) "
141
+"(ნაგულისხმები %d)\n"
142
+
143
+#: src/tools/pw-cat.c:826
144
+msgid ""
145
+"  -p, --playback                        Playback mode\n"
146
+"  -r, --record                          Recording mode\n"
147
+"  -m, --midi                            Midi mode\n"
148
+"  -d, --dsd                             DSD mode\n"
149
+"\n"
150
+msgstr ""
151
+"   -p, --playback                        დაკვრის რეჟიმი\n"
152
+"   -r, -- record                          ჩაწერის რეჟიმი\n"
153
+"   -m, --midi                            Midi რეჟიმი\n"
154
+"   -d, --dsd                             DSD რეჟიმი\n"
155
+"\n"
156
+
157
+#: src/tools/pw-cli.c:3165
158
+#, c-format
159
+msgid ""
160
+"%s options command\n"
161
+"  -h, --help                            Show this help\n"
162
+"      --version                         Show version\n"
163
+"  -d, --daemon                          Start as daemon (Default false)\n"
164
+"  -r, --remote                          Remote daemon name\n"
165
+"\n"
166
+msgstr ""
167
+"%s პარამეტრები ბრძანება\n"
168
+"   -h, --help                            ამ დახმარების ჩვენება\n"
169
+"       --version                         ვერსიის ჩვენება\n"
170
+"   -d, --daemon                          დაწყება როგორც დემონი (ნაგულისხმები "
171
+"false)\n"
172
+"   -r, --remote                          დაშორებული დემონის სახელი\n"
173
+
174
+#: spa/plugins/alsa/acp/acp.c:321
175
+msgid "Pro Audio"
176
+msgstr "Pro Audio"
177
+
178
+#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
179
+#: spa/plugins/bluez5/bluez5-device.c:1161
180
+msgid "Off"
181
+msgstr "გამორთული"
182
+
183
+#: spa/plugins/alsa/acp/alsa-mixer.c:2652
184
+msgid "Input"
185
+msgstr "შეყვანა"
186
+
187
+#: spa/plugins/alsa/acp/alsa-mixer.c:2653
188
+msgid "Docking Station Input"
189
+msgstr "Docking Station-ის შეყვანა"
190
+
191
+#: spa/plugins/alsa/acp/alsa-mixer.c:2654
192
+msgid "Docking Station Microphone"
193
+msgstr "Docking Station-ის მიკროფონი"
194
+
195
+#: spa/plugins/alsa/acp/alsa-mixer.c:2655
196
+msgid "Docking Station Line In"
197
+msgstr "Docking Station Line In"
198
+
199
+#: spa/plugins/alsa/acp/alsa-mixer.c:2656
200
+#: spa/plugins/alsa/acp/alsa-mixer.c:2747
201
pipewire-0.3.56.tar.gz/po/pl.po -> pipewire-0.3.57.tar.gz/po/pl.po Changed
201
 
1
@@ -8,8 +8,8 @@
2
 "Project-Id-Version: pipewire\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
4
 "issues\n"
5
-"POT-Creation-Date: 2022-05-20 15:26+0000\n"
6
-"PO-Revision-Date: 2022-05-21 12:49+0200\n"
7
+"POT-Creation-Date: 2022-08-27 13:57+0000\n"
8
+"PO-Revision-Date: 2022-08-27 16:00+0200\n"
9
 "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
10
 "Language-Team: Polish <community-poland@mozilla.org>\n"
11
 "Language: pl\n"
12
@@ -41,8 +41,8 @@
13
 msgid "Start the PipeWire Media System"
14
 msgstr "Uruchomienie systemu multimediów PipeWire"
15
 
16
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:183
17
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:183
18
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
19
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
20
 #, c-format
21
 msgid "Tunnel to %s/%s"
22
 msgstr "Tunel do %s/%s"
23
@@ -51,7 +51,7 @@
24
 msgid "Dummy Output"
25
 msgstr "Głuche wyjście"
26
 
27
-#: src/modules/module-pulse-tunnel.c:639
28
+#: src/modules/module-pulse-tunnel.c:648
29
 #, c-format
30
 msgid "Tunnel for %s@%s"
31
 msgstr "Tunel dla %s@%s"
32
@@ -70,7 +70,7 @@
33
 msgid "%s on %s"
34
 msgstr "%s na %s"
35
 
36
-#: src/tools/pw-cat.c:872
37
+#: src/tools/pw-cat.c:784
38
 #, c-format
39
 msgid ""
40
 "%s options <file>|-\n"
41
@@ -85,7 +85,7 @@
42
 "  -v, --verbose                         Wyświetla więcej komunikatów\n"
43
 "\n"
44
 
45
-#: src/tools/pw-cat.c:879
46
+#: src/tools/pw-cat.c:791
47
 #, c-format
48
 msgid ""
49
 "  -R, --remote                          Remote daemon name\n"
50
@@ -122,7 +122,7 @@
51
 "  -P  --properties                      Ustawia właściwości węzła\n"
52
 "\n"
53
 
54
-#: src/tools/pw-cat.c:897
55
+#: src/tools/pw-cat.c:809
56
 #, c-format
57
 msgid ""
58
 "      --rate                            Sample rate (req. for rec) (default "
59
@@ -158,7 +158,7 @@
60
 "(domyślnie %d)\n"
61
 "\n"
62
 
63
-#: src/tools/pw-cat.c:914
64
+#: src/tools/pw-cat.c:826
65
 msgid ""
66
 "  -p, --playback                        Playback mode\n"
67
 "  -r, --record                          Recording mode\n"
68
@@ -172,7 +172,7 @@
69
 "  -d, --dsd                             Tryb DSD\n"
70
 "\n"
71
 
72
-#: src/tools/pw-cli.c:3139
73
+#: src/tools/pw-cli.c:2255
74
 #, c-format
75
 msgid ""
76
 "%s options command\n"
77
@@ -195,7 +195,7 @@
78
 msgstr "Dźwięk w zastosowaniach profesjonalnych"
79
 
80
 #: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
81
-#: spa/plugins/bluez5/bluez5-device.c:1161
82
+#: spa/plugins/bluez5/bluez5-device.c:1188
83
 msgid "Off"
84
 msgstr "Wyłączone"
85
 
86
@@ -222,7 +222,7 @@
87
 
88
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
89
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
90
-#: spa/plugins/bluez5/bluez5-device.c:1330
91
+#: spa/plugins/bluez5/bluez5-device.c:1360
92
 msgid "Microphone"
93
 msgstr "Mikrofon"
94
 
95
@@ -288,7 +288,7 @@
96
 msgstr "Brak podbicia basów"
97
 
98
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
99
-#: spa/plugins/bluez5/bluez5-device.c:1335
100
+#: spa/plugins/bluez5/bluez5-device.c:1366
101
 msgid "Speaker"
102
 msgstr "Głośnik"
103
 
104
@@ -403,7 +403,7 @@
105
 
106
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
107
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
108
-#: spa/plugins/bluez5/bluez5-device.c:1320
109
+#: spa/plugins/bluez5/bluez5-device.c:1348
110
 msgid "Headset"
111
 msgstr "Słuchawki z mikrofonem"
112
 
113
@@ -527,7 +527,7 @@
114
 msgid "%s Input"
115
 msgstr "Wejście %s"
116
 
117
-#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
118
+#: spa/plugins/alsa/acp/alsa-util.c:1187 spa/plugins/alsa/acp/alsa-util.c:1281
119
 #, c-format
120
 msgid ""
121
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
122
@@ -552,7 +552,7 @@
123
 "Prawdopodobnie jest to błąd sterownika ALSA „%s”. Proszę zgłosić ten problem "
124
 "programistom usługi ALSA."
125
 
126
-#: spa/plugins/alsa/acp/alsa-util.c:1239
127
+#: spa/plugins/alsa/acp/alsa-util.c:1253
128
 #, c-format
129
 msgid ""
130
 "snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
131
@@ -577,7 +577,7 @@
132
 "Prawdopodobnie jest to błąd sterownika ALSA „%s”. Proszę zgłosić ten problem "
133
 "programistom usługi ALSA."
134
 
135
-#: spa/plugins/alsa/acp/alsa-util.c:1286
136
+#: spa/plugins/alsa/acp/alsa-util.c:1300
137
 #, c-format
138
 msgid ""
139
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
140
@@ -590,7 +590,7 @@
141
 "Prawdopodobnie jest to błąd sterownika ALSA „%s”. Proszę zgłosić ten problem "
142
 "programistom usługi ALSA."
143
 
144
-#: spa/plugins/alsa/acp/alsa-util.c:1329
145
+#: spa/plugins/alsa/acp/alsa-util.c:1343
146
 #, c-format
147
 msgid ""
148
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
149
@@ -615,7 +615,7 @@
150
 "Prawdopodobnie jest to błąd sterownika ALSA „%s”. Proszę zgłosić ten problem "
151
 "programistom usługi ALSA."
152
 
153
-#: spa/plugins/alsa/acp/channelmap.h:464
154
+#: spa/plugins/alsa/acp/channelmap.h:457
155
 msgid "(invalid)"
156
 msgstr "(nieprawidłowe)"
157
 
158
@@ -627,61 +627,77 @@
159
 msgid "Modem"
160
 msgstr "Modem"
161
 
162
-#: spa/plugins/bluez5/bluez5-device.c:1172
163
+#: spa/plugins/bluez5/bluez5-device.c:1199
164
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
165
 msgstr "Bramka dźwięku (źródło A2DP i AG HSP/HFP)"
166
 
167
-#: spa/plugins/bluez5/bluez5-device.c:1197
168
+#: spa/plugins/bluez5/bluez5-device.c:1224
169
 #, c-format
170
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
171
 msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP, kodek %s)"
172
 
173
-#: spa/plugins/bluez5/bluez5-device.c:1200
174
+#: spa/plugins/bluez5/bluez5-device.c:1227
175
 #, c-format
176
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
177
 msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP, kodek %s)"
178
 
179
-#: spa/plugins/bluez5/bluez5-device.c:1208
180
+#: spa/plugins/bluez5/bluez5-device.c:1235
181
 msgid "High Fidelity Playback (A2DP Sink)"
182
 msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP)"
183
 
184
-#: spa/plugins/bluez5/bluez5-device.c:1210
185
+#: spa/plugins/bluez5/bluez5-device.c:1237
186
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
187
 msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP)"
188
 
189
-#: spa/plugins/bluez5/bluez5-device.c:1238
190
+#: spa/plugins/bluez5/bluez5-device.c:1265
191
 #, c-format
192
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
193
 msgstr "Jednostka główna słuchawek z mikrofonem (HSP/HFP, kodek %s)"
194
 
195
-#: spa/plugins/bluez5/bluez5-device.c:1243
196
+#: spa/plugins/bluez5/bluez5-device.c:1270
197
 msgid "Headset Head Unit (HSP/HFP)"
198
 msgstr "Jednostka główna słuchawek z mikrofonem (HSP/HFP)"
199
 
200
-#: spa/plugins/bluez5/bluez5-device.c:1325
201
pipewire-0.3.56.tar.gz/po/sv.po -> pipewire-0.3.57.tar.gz/po/sv.po Changed
201
 
1
@@ -19,8 +19,8 @@
2
 "Project-Id-Version: pipewire\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
4
 "issues\n"
5
-"POT-Creation-Date: 2022-05-20 15:26+0000\n"
6
-"PO-Revision-Date: 2022-05-23 11:01+0200\n"
7
+"POT-Creation-Date: 2022-07-19 15:27+0000\n"
8
+"PO-Revision-Date: 2022-07-10 10:22+0200\n"
9
 "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
10
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
11
 "Language: sv\n"
12
@@ -28,7 +28,7 @@
13
 "Content-Type: text/plain; charset=UTF-8\n"
14
 "Content-Transfer-Encoding: 8bit\n"
15
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
16
-"X-Generator: Poedit 3.0.1\n"
17
+"X-Generator: Poedit 3.1\n"
18
 
19
 #: src/daemon/pipewire.c:46
20
 #, c-format
21
@@ -51,8 +51,8 @@
22
 msgid "Start the PipeWire Media System"
23
 msgstr "Starta mediasystemet PipeWire"
24
 
25
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:183
26
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:183
27
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
28
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
29
 #, c-format
30
 msgid "Tunnel to %s/%s"
31
 msgstr "Tunnel till %s/%s"
32
@@ -61,7 +61,7 @@
33
 msgid "Dummy Output"
34
 msgstr "Attrapputgång"
35
 
36
-#: src/modules/module-pulse-tunnel.c:639
37
+#: src/modules/module-pulse-tunnel.c:648
38
 #, c-format
39
 msgid "Tunnel for %s@%s"
40
 msgstr "Tunnel för %s@%s"
41
@@ -80,7 +80,7 @@
42
 msgid "%s on %s"
43
 msgstr "%s på %s"
44
 
45
-#: src/tools/pw-cat.c:872
46
+#: src/tools/pw-cat.c:784
47
 #, c-format
48
 msgid ""
49
 "%s options <file>|-\n"
50
@@ -95,7 +95,7 @@
51
 "  -v, --verbose                         Aktivera utförliga operationer\n"
52
 "\n"
53
 
54
-#: src/tools/pw-cat.c:879
55
+#: src/tools/pw-cat.c:791
56
 #, c-format
57
 msgid ""
58
 "  -R, --remote                          Remote daemon name\n"
59
@@ -125,7 +125,7 @@
60
 "  -P  --properties                      Sätt nodegenskaper\n"
61
 "\n"
62
 
63
-#: src/tools/pw-cat.c:897
64
+#: src/tools/pw-cat.c:809
65
 #, c-format
66
 msgid ""
67
 "      --rate                            Sample rate (req. for rec) (default "
68
@@ -160,7 +160,7 @@
69
 "%d)\n"
70
 "\n"
71
 
72
-#: src/tools/pw-cat.c:914
73
+#: src/tools/pw-cat.c:826
74
 msgid ""
75
 "  -p, --playback                        Playback mode\n"
76
 "  -r, --record                          Recording mode\n"
77
@@ -174,7 +174,7 @@
78
 "  -d, --dsd                             DSD-läge\n"
79
 "\n"
80
 
81
-#: src/tools/pw-cli.c:3139
82
+#: src/tools/pw-cli.c:3165
83
 #, c-format
84
 msgid ""
85
 "%s options command\n"
86
@@ -195,8 +195,8 @@
87
 msgid "Pro Audio"
88
 msgstr "Professionellt ljud"
89
 
90
-#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
91
-#: spa/plugins/bluez5/bluez5-device.c:1161
92
+#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
93
+#: spa/plugins/bluez5/bluez5-device.c:1188
94
 msgid "Off"
95
 msgstr "Av"
96
 
97
@@ -223,7 +223,7 @@
98
 
99
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
100
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
101
-#: spa/plugins/bluez5/bluez5-device.c:1330
102
+#: spa/plugins/bluez5/bluez5-device.c:1360
103
 msgid "Microphone"
104
 msgstr "Mikrofon"
105
 
106
@@ -289,7 +289,7 @@
107
 msgstr "Ingen basökning"
108
 
109
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
110
-#: spa/plugins/bluez5/bluez5-device.c:1335
111
+#: spa/plugins/bluez5/bluez5-device.c:1366
112
 msgid "Speaker"
113
 msgstr "Högtalare"
114
 
115
@@ -404,7 +404,7 @@
116
 
117
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
118
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
119
-#: spa/plugins/bluez5/bluez5-device.c:1320
120
+#: spa/plugins/bluez5/bluez5-device.c:1348
121
 msgid "Headset"
122
 msgstr "Headset"
123
 
124
@@ -554,13 +554,13 @@
125
 #: spa/plugins/alsa/acp/alsa-util.c:1239
126
 #, c-format
127
 msgid ""
128
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
129
-"(%s%lu ms).\n"
130
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
131
+"%lu ms).\n"
132
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
133
 "to the ALSA developers."
134
 msgid_plural ""
135
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
136
-"(%s%lu ms).\n"
137
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
138
+"%lu ms).\n"
139
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
140
 "to the ALSA developers."
141
 msgstr0 ""
142
@@ -610,7 +610,7 @@
143
 "Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
144
 "problemet till ALSA-utvecklarna."
145
 
146
-#: spa/plugins/alsa/acp/channelmap.h:464
147
+#: spa/plugins/alsa/acp/channelmap.h:457
148
 msgid "(invalid)"
149
 msgstr "(ogiltig)"
150
 
151
@@ -622,61 +622,77 @@
152
 msgid "Modem"
153
 msgstr "Modem"
154
 
155
-#: spa/plugins/bluez5/bluez5-device.c:1172
156
+#: spa/plugins/bluez5/bluez5-device.c:1199
157
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
158
 msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
159
 
160
-#: spa/plugins/bluez5/bluez5-device.c:1197
161
+#: spa/plugins/bluez5/bluez5-device.c:1224
162
 #, c-format
163
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
164
 msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
165
 
166
-#: spa/plugins/bluez5/bluez5-device.c:1200
167
+#: spa/plugins/bluez5/bluez5-device.c:1227
168
 #, c-format
169
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
170
 msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
171
 
172
-#: spa/plugins/bluez5/bluez5-device.c:1208
173
+#: spa/plugins/bluez5/bluez5-device.c:1235
174
 msgid "High Fidelity Playback (A2DP Sink)"
175
 msgstr "High fidelity-uppspelning (A2DP-utgång)"
176
 
177
-#: spa/plugins/bluez5/bluez5-device.c:1210
178
+#: spa/plugins/bluez5/bluez5-device.c:1237
179
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
180
 msgstr "High fidelity duplex (A2DP-källa/utgång)"
181
 
182
-#: spa/plugins/bluez5/bluez5-device.c:1238
183
+#: spa/plugins/bluez5/bluez5-device.c:1265
184
 #, c-format
185
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
186
 msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
187
 
188
-#: spa/plugins/bluez5/bluez5-device.c:1243
189
+#: spa/plugins/bluez5/bluez5-device.c:1270
190
 msgid "Headset Head Unit (HSP/HFP)"
191
 msgstr "Headset-huvudenhet (HSP/HFP)"
192
 
193
-#: spa/plugins/bluez5/bluez5-device.c:1325
194
+#: spa/plugins/bluez5/bluez5-device.c:1349
195
+#: spa/plugins/bluez5/bluez5-device.c:1354
196
+#: spa/plugins/bluez5/bluez5-device.c:1361
197
+#: spa/plugins/bluez5/bluez5-device.c:1367
198
+#: spa/plugins/bluez5/bluez5-device.c:1373
199
+#: spa/plugins/bluez5/bluez5-device.c:1379
200
+#: spa/plugins/bluez5/bluez5-device.c:1385
201
pipewire-0.3.56.tar.gz/spa/include/spa/interfaces/audio/aec.h -> pipewire-0.3.57.tar.gz/spa/include/spa/interfaces/audio/aec.h Changed
14
 
1
@@ -68,9 +68,9 @@
2
            const struct spa_audio_aec_events *events,
3
            void *data);
4
 
5
-   int (*init) (void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info);
6
-   int (*run) (void *data, const float *rec, const float *play, float *out, uint32_t n_samples);
7
-   int (*set_props) (void *data, const struct spa_dict *args);
8
+   int (*init) (void *object, const struct spa_dict *args, const struct spa_audio_info_raw *info);
9
+   int (*run) (void *object, const float *rec, const float *play, float *out, uint32_t n_samples);
10
+   int (*set_props) (void *object, const struct spa_dict *args);
11
 };
12
 
13
 #define spa_audio_aec_method(o,method,version,...)         \
14
pipewire-0.3.56.tar.gz/spa/include/spa/param/bluetooth/audio.h -> pipewire-0.3.57.tar.gz/spa/include/spa/param/bluetooth/audio.h Changed
13
 
1
@@ -49,6 +49,11 @@
2
    SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM,
3
    SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX,
4
    SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR,
5
+   SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05,
6
+   SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_51,
7
+   SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71,
8
+   SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_DUPLEX,
9
+   SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_PRO,
10
 
11
    /* HFP */
12
    SPA_BLUETOOTH_AUDIO_CODEC_CVSD = 0x100,
13
pipewire-0.3.56.tar.gz/spa/include/spa/param/bluetooth/type-info.h -> pipewire-0.3.57.tar.gz/spa/include/spa/param/bluetooth/type-info.h Changed
13
 
1
@@ -53,6 +53,11 @@
2
    { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "faststream", NULL },
3
    { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "faststream_duplex", NULL },
4
    { SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "lc3plus_hr", NULL },
5
+   { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05", NULL },
6
+   { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_51, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_51", NULL },
7
+   { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_71", NULL },
8
+   { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_DUPLEX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_duplex", NULL },
9
+   { SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_PRO, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "opus_05_pro", NULL },
10
 
11
    { SPA_BLUETOOTH_AUDIO_CODEC_CVSD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "cvsd", NULL },
12
    { SPA_BLUETOOTH_AUDIO_CODEC_MSBC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "msbc", NULL },
13
pipewire-0.3.56.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.57.tar.gz/spa/include/spa/utils/defs.h Changed
30
 
1
@@ -147,6 +147,12 @@
2
    SPA_MIN(SPA_MAX(_v, _low), _high);      \
3
 })
4
 
5
+#define SPA_CLAMPF(v,low,high)             \
6
+({                         \
7
+   fminf(fmaxf(v, low), high);         \
8
+})
9
+
10
+
11
 #define SPA_SWAP(a,b)                  \
12
 ({                         \
13
    __typeof__(a) _t = (a);             \
14
@@ -209,6 +215,7 @@
15
 #define SPA_SENTINEL __attribute__((__sentinel__))
16
 #define SPA_UNUSED __attribute__ ((unused))
17
 #define SPA_NORETURN __attribute__ ((noreturn))
18
+#define SPA_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
19
 #else
20
 #define SPA_PRINTF_FUNC(fmt, arg1)
21
 #define SPA_FORMAT_ARG_FUNC(arg1)
22
@@ -218,6 +225,7 @@
23
 #define SPA_SENTINEL
24
 #define SPA_UNUSED
25
 #define SPA_NORETURN
26
+#define SPA_WARN_UNUSED_RESULT
27
 #endif
28
 
29
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
30
pipewire-0.3.56.tar.gz/spa/include/spa/utils/hook.h -> pipewire-0.3.57.tar.gz/spa/include/spa/utils/hook.h Changed
11
 
1
@@ -382,7 +382,8 @@
2
 /** Remove a hook */
3
 static inline void spa_hook_remove(struct spa_hook *hook)
4
 {
5
-   spa_list_remove(&hook->link);
6
+   if (spa_list_is_initialized(&hook->link))
7
+       spa_list_remove(&hook->link);
8
    if (hook->removed)
9
        hook->removed(hook);
10
 }
11
pipewire-0.3.56.tar.gz/spa/include/spa/utils/list.h -> pipewire-0.3.57.tar.gz/spa/include/spa/utils/list.h Changed
13
 
1
@@ -51,6 +51,11 @@
2
    *list = SPA_LIST_INIT(list);
3
 }
4
 
5
+static inline int spa_list_is_initialized(struct spa_list *list)
6
+{
7
+   return !!list->prev;
8
+}
9
+
10
 #define spa_list_is_empty(l)  ((l)->next == (l))
11
 
12
 static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem)
13
pipewire-0.3.56.tar.gz/spa/meson.build -> pipewire-0.3.57.tar.gz/spa/meson.build Changed
10
 
1
@@ -62,6 +62,8 @@
2
       endif
3
     endif
4
     summary({'LC3plus': lc3plus_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
5
+    opus_dep = dependency('opus', required : get_option('bluez5-codec-opus'))
6
+    summary({'Opus': opus_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
7
   endif
8
   avcodec_dep = dependency('libavcodec', required: get_option('ffmpeg'))
9
   jack_dep = dependency('jack', version : '>= 1.9.10', required: get_option('jack'))
10
pipewire-0.3.56.tar.gz/spa/plugins/aec/aec-null.c -> pipewire-0.3.57.tar.gz/spa/plugins/aec/aec-null.c Changed
67
 
1
@@ -58,19 +58,18 @@
2
    return 0;
3
 }
4
 
5
-static struct spa_audio_aec_methods impl_aec = {
6
+static const struct spa_audio_aec_methods impl_aec = {
7
+   SPA_VERSION_AUDIO_AEC,
8
    .init = null_init,
9
    .run = null_run,
10
 };
11
 
12
 static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface)
13
 {
14
-   struct impl *impl;
15
-
16
    spa_return_val_if_fail(handle != NULL, -EINVAL);
17
    spa_return_val_if_fail(interface != NULL, -EINVAL);
18
 
19
-   impl = (struct impl *) handle;
20
+   struct impl *impl = (struct impl *) handle;
21
 
22
    if (spa_streq(type, SPA_TYPE_INTERFACE_AUDIO_AEC))
23
        *interface = &impl->aec;
24
@@ -101,15 +100,13 @@
25
      const struct spa_support *support,
26
      uint32_t n_support)
27
 {
28
-   struct impl *impl;
29
-
30
    spa_return_val_if_fail(factory != NULL, -EINVAL);
31
    spa_return_val_if_fail(handle != NULL, -EINVAL);
32
 
33
    handle->get_interface = impl_get_interface;
34
    handle->clear = impl_clear;
35
 
36
-   impl = (struct impl *) handle;
37
+   struct impl *impl = (struct impl *) handle;
38
 
39
    impl->aec.iface = SPA_INTERFACE_INIT(
40
        SPA_TYPE_INTERFACE_AUDIO_AEC,
41
@@ -119,7 +116,7 @@
42
    impl->aec.info = NULL;
43
    impl->aec.latency = NULL;
44
 
45
-   impl->log = (struct spa_log*)spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
46
+   impl->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
47
    spa_log_topic_init(impl->log, &log_topic);
48
 
49
    spa_hook_list_init(&impl->hooks_list);
50
@@ -151,7 +148,7 @@
51
    return 1;
52
 }
53
 
54
-const struct spa_handle_factory spa_aec_null_factory = {
55
+static const struct spa_handle_factory spa_aec_null_factory = {
56
    SPA_VERSION_HANDLE_FACTORY,
57
    SPA_NAME_AEC,
58
    NULL,
59
@@ -160,7 +157,6 @@
60
    impl_enum_interface_info,
61
 };
62
 
63
-
64
 SPA_EXPORT
65
 int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
66
 {
67
pipewire-0.3.56.tar.gz/spa/plugins/aec/aec-webrtc.cpp -> pipewire-0.3.57.tar.gz/spa/plugins/aec/aec-webrtc.cpp Changed
76
 
1
@@ -50,19 +50,17 @@
2
 #undef SPA_LOG_TOPIC_DEFAULT
3
 #define SPA_LOG_TOPIC_DEFAULT &log_topic
4
 
5
-static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bool default_value) {
6
-   const char *str_val;
7
-   bool value = default_value;
8
-   str_val = spa_dict_lookup(args, key);
9
-   if (str_val != NULL)
10
-       value =spa_atob(str_val);
11
-
12
-   return value;
13
+static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bool default_value)
14
+{
15
+   if (auto str = spa_dict_lookup(args, key))
16
+       return spa_atob(str);
17
+
18
+   return default_value;
19
 }
20
 
21
-static int webrtc_init(void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info)
22
+static int webrtc_init(void *object, const struct spa_dict *args, const struct spa_audio_info_raw *info)
23
 {
24
-   auto impl = reinterpret_cast<struct impl_data*>(data);
25
+   auto impl = static_cast<struct impl_data*>(object);
26
 
27
    bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true);
28
    bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true);
29
@@ -122,9 +120,9 @@
30
    return 0;
31
 }
32
 
33
-static int webrtc_run(void *data, const float *rec, const float *play, float *out, uint32_t n_samples)
34
+static int webrtc_run(void *object, const float *rec, const float *play, float *out, uint32_t n_samples)
35
 {
36
-   auto impl = reinterpret_cast<struct impl_data*>(data);
37
+   auto impl = static_cast<struct impl_data*>(object);
38
    webrtc::StreamConfig config =
39
        webrtc::StreamConfig(impl->info.rate, impl->info.channels, false);
40
    unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10;
41
@@ -160,7 +158,7 @@
42
    return 0;
43
 }
44
 
45
-static struct spa_audio_aec_methods impl_aec = {
46
+static const struct spa_audio_aec_methods impl_aec = {
47
    SPA_VERSION_AUDIO_AEC_METHODS,
48
    .add_listener = NULL,
49
    .init = webrtc_init,
50
@@ -220,7 +218,7 @@
51
    impl->aec.info = NULL;
52
    impl->aec.latency = "480/48000",
53
 
54
-   impl->log = (struct spa_log*)spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
55
+   impl->log = static_cast<struct spa_log *>(spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log));
56
    spa_log_topic_init(impl->log, &log_topic);
57
 
58
    return 0;
59
@@ -250,7 +248,7 @@
60
    return 1;
61
 }
62
 
63
-const struct spa_handle_factory spa_aec_webrtc_factory = {
64
+static const struct spa_handle_factory spa_aec_webrtc_factory = {
65
    SPA_VERSION_HANDLE_FACTORY,
66
    SPA_NAME_AEC,
67
    NULL,
68
@@ -259,7 +257,6 @@
69
    impl_enum_interface_info,
70
 };
71
 
72
-
73
 SPA_EXPORT
74
 int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
75
 {
76
pipewire-0.3.56.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/acp.c Changed
72
 
1
@@ -382,8 +382,7 @@
2
                            0, NULL, NULL, false))) {
3
                pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
4
                pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
5
-               snd_pcm_close(m->output_pcm);
6
-               m->output_pcm = NULL;
7
+               pa_alsa_close(&m->output_pcm);
8
                m->supported = true;
9
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
10
            }
11
@@ -413,8 +412,7 @@
12
                            0, NULL, NULL, false))) {
13
                pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
14
                pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
15
-               snd_pcm_close(m->input_pcm);
16
-               m->input_pcm = NULL;
17
+               pa_alsa_close(&m->input_pcm);
18
                m->supported = true;
19
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
20
            }
21
@@ -1058,6 +1056,9 @@
22
    uint32_t i;
23
    int res;
24
 
25
+   if (!dev->mixer_handle)
26
+       return 0;
27
+
28
    if ((res = pa_alsa_path_get_volume(dev->mixer_path, dev->mixer_handle, &dev->mapping->channel_map, &r)) < 0)
29
        return res;
30
 
31
@@ -1089,6 +1090,9 @@
32
 
33
    dev->real_volume = *v;
34
 
35
+   if (!dev->mixer_handle)
36
+       return;
37
+
38
    /* Shift up by the base volume */
39
    pa_sw_cvolume_divide_scalar(&r, &dev->real_volume, dev->base_volume);
40
 
41
@@ -1139,6 +1143,9 @@
42
    bool mute;
43
    int res;
44
 
45
+   if (!dev->mixer_handle)
46
+       return 0;
47
+
48
    if ((res = pa_alsa_path_get_mute(dev->mixer_path, dev->mixer_handle, &mute)) < 0)
49
        return res;
50
 
51
@@ -1157,6 +1164,10 @@
52
 static void set_mute(pa_alsa_device *dev, bool mute)
53
 {
54
    dev->muted = mute;
55
+
56
+   if (!dev->mixer_handle)
57
+       return;
58
+
59
    pa_alsa_path_set_mute(dev->mixer_path, dev->mixer_handle, mute);
60
 }
61
 
62
@@ -1735,7 +1746,8 @@
63
        setting = data->setting;
64
    }
65
 
66
-   pa_alsa_path_select(d->mixer_path, setting, d->mixer_handle, d->muted);
67
+   if (d->mixer_handle)
68
+       pa_alsa_path_select(d->mixer_path, setting, d->mixer_handle, d->muted);
69
 
70
    if (d->set_mute)
71
        d->set_mute(d, d->muted);
72
pipewire-0.3.56.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c Changed
21
 
1
@@ -4966,8 +4966,7 @@
2
                 continue;
3
 
4
             pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
5
-            snd_pcm_close(m->output_pcm);
6
-            m->output_pcm = NULL;
7
+            pa_alsa_close(&m->output_pcm);
8
         }
9
 
10
     if (to_be_finalized->input_mappings)
11
@@ -4986,8 +4985,7 @@
12
                 continue;
13
 
14
             pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
15
-            snd_pcm_close(m->input_pcm);
16
-            m->input_pcm = NULL;
17
+            pa_alsa_close(&m->input_pcm);
18
         }
19
 }
20
 
21
pipewire-0.3.56.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c Changed
21
 
1
@@ -1941,8 +1941,7 @@
2
             continue;
3
 
4
         pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
5
-        snd_pcm_close(m->output_pcm);
6
-        m->output_pcm = NULL;
7
+        pa_alsa_close(&m->output_pcm);
8
     }
9
 
10
     PA_IDXSET_FOREACH(m, p->input_mappings, idx) {
11
@@ -1953,8 +1952,7 @@
12
             continue;
13
 
14
         pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
15
-        snd_pcm_close(m->input_pcm);
16
-        m->input_pcm = NULL;
17
+        pa_alsa_close(&m->input_pcm);
18
     }
19
 }
20
 
21
pipewire-0.3.56.tar.gz/spa/plugins/alsa/acp/alsa-util.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/alsa-util.c Changed
66
 
1
@@ -656,6 +656,20 @@
2
     return pcm_handle;
3
 }
4
 
5
+int pa_alsa_close(snd_pcm_t **pcm)
6
+{
7
+    int err;
8
+    pa_assert(pcm);
9
+    pa_log_info("ALSA device close %p", *pcm);
10
+    if (*pcm == NULL)
11
+       return 0;
12
+    if ((err = snd_pcm_close(*pcm)) < 0) {
13
+        pa_log_warn("ALSA close failed: %s", snd_strerror(err));
14
+    }
15
+    *pcm = NULL;
16
+    return err;
17
+}
18
+
19
 snd_pcm_t *pa_alsa_open_by_device_string(
20
         const char *device,
21
         char **dev,
22
@@ -691,8 +705,8 @@
23
             pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
24
             goto fail;
25
         }
26
-
27
-        pa_log_debug("Managed to open %s", d);
28
+        pa_log_info("ALSA device open '%s' %s: %p", d,
29
+           mode == SND_PCM_STREAM_CAPTURE ? "capture" : "playback", pcm_handle);
30
 
31
         if ((err = pa_alsa_set_hw_params(
32
                      pcm_handle,
33
@@ -707,7 +721,7 @@
34
             if (!reformat) {
35
                 reformat = true;
36
 
37
-                snd_pcm_close(pcm_handle);
38
+                pa_alsa_close(&pcm_handle);
39
                 continue;
40
             }
41
 
42
@@ -721,12 +735,12 @@
43
 
44
                 reformat = false;
45
 
46
-                snd_pcm_close(pcm_handle);
47
+                pa_alsa_close(&pcm_handle);
48
                 continue;
49
             }
50
 
51
             pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
52
-            snd_pcm_close(pcm_handle);
53
+            pa_alsa_close(&pcm_handle);
54
 
55
             goto fail;
56
         }
57
@@ -734,7 +748,7 @@
58
         if (ss->channels > PA_CHANNELS_MAX) {
59
             pa_log("Device %s has %u channels, but PulseAudio supports only %u channels. Unable to use the device.",
60
                    d, ss->channels, PA_CHANNELS_MAX);
61
-            snd_pcm_close(pcm_handle);
62
+            pa_alsa_close(&pcm_handle);
63
             goto fail;
64
         }
65
 
66
pipewire-0.3.56.tar.gz/spa/plugins/alsa/acp/alsa-util.h -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/alsa-util.h Changed
9
 
1
@@ -115,6 +115,7 @@
2
 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
3
 void pa_alsa_dump_status(snd_pcm_t *pcm);
4
 #endif
5
+int pa_alsa_close(snd_pcm_t **pcm);
6
 
7
 void pa_alsa_refcnt_inc(void);
8
 void pa_alsa_refcnt_dec(void);
9
pipewire-0.3.56.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c Changed
54
 
1
@@ -798,38 +798,38 @@
2
 static int impl_node_process(void *object)
3
 {
4
    struct state *this = object;
5
-   struct spa_io_buffers *input;
6
+   struct spa_io_buffers *io;
7
 
8
    spa_return_val_if_fail(this != NULL, -EINVAL);
9
 
10
-   input = this->io;
11
-   spa_return_val_if_fail(input != NULL, -EIO);
12
+   if ((io = this->io) == NULL)
13
+       return -EIO;
14
 
15
-   spa_log_trace_fp(this->log, "%p: process %d %d/%d", this, input->status,
16
-           input->buffer_id, this->n_buffers);
17
+   spa_log_trace_fp(this->log, "%p: process %d %d/%d", this, io->status,
18
+           io->buffer_id, this->n_buffers);
19
 
20
    if (this->position && this->position->clock.flags & SPA_IO_CLOCK_FLAG_FREEWHEEL) {
21
-       input->status = SPA_STATUS_NEED_DATA;
22
+       io->status = SPA_STATUS_NEED_DATA;
23
        return SPA_STATUS_HAVE_DATA;
24
    }
25
-   if (input->status == SPA_STATUS_HAVE_DATA &&
26
-       input->buffer_id < this->n_buffers) {
27
-       struct buffer *b = &this->buffersinput->buffer_id;
28
+   if (io->status == SPA_STATUS_HAVE_DATA &&
29
+       io->buffer_id < this->n_buffers) {
30
+       struct buffer *b = &this->buffersio->buffer_id;
31
 
32
        if (!SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) {
33
            spa_log_warn(this->log, "%p: buffer %u in use",
34
-                   this, input->buffer_id);
35
-           input->status = -EINVAL;
36
+                   this, io->buffer_id);
37
+           io->status = -EINVAL;
38
            return -EINVAL;
39
        }
40
-       spa_log_trace_fp(this->log, "%p: queue buffer %u", this, input->buffer_id);
41
+       spa_log_trace_fp(this->log, "%p: queue buffer %u", this, io->buffer_id);
42
        spa_list_append(&this->ready, &b->link);
43
        SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT);
44
-       input->buffer_id = SPA_ID_INVALID;
45
+       io->buffer_id = SPA_ID_INVALID;
46
 
47
        spa_alsa_write(this);
48
 
49
-       input->status = SPA_STATUS_OK;
50
+       io->status = SPA_STATUS_OK;
51
    }
52
    return SPA_STATUS_HAVE_DATA;
53
 }
54
pipewire-0.3.56.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-source.c Changed
12
 
1
@@ -753,8 +753,8 @@
2
 
3
    spa_return_val_if_fail(this != NULL, -EINVAL);
4
 
5
-   io = this->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = this->io) == NULL)
8
+       return -EIO;
9
 
10
    spa_log_trace_fp(this->log, "%p; status %d", this, io->status);
11
 
12
pipewire-0.3.56.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
201
 
1
@@ -10,6 +10,7 @@
2
 
3
 #include <spa/pod/filter.h>
4
 #include <spa/utils/string.h>
5
+#include <spa/utils/result.h>
6
 #include <spa/support/system.h>
7
 #include <spa/utils/keys.h>
8
 
9
@@ -442,9 +443,31 @@
10
    return changed;
11
 }
12
 
13
+#define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; }
14
+
15
+static ssize_t log_write(void *cookie, const char *buf, size_t size)
16
+{
17
+   struct state *state = cookie;
18
+   int len;
19
+
20
+   while (size > 0) {
21
+       len = strcspn(buf, "\n");
22
+       if (len > 0)
23
+           spa_log_debug(state->log, "%.*s", (int)len, buf);
24
+       buf += len + 1;
25
+       size -= len + 1;
26
+   }
27
+   return size;
28
+}
29
+
30
+static cookie_io_functions_t io_funcs = {
31
+   .write = log_write,
32
+};
33
+
34
 int spa_alsa_init(struct state *state, const struct spa_dict *info)
35
 {
36
    uint32_t i;
37
+   int err;
38
 
39
    snd_config_update_free_global();
40
 
41
@@ -481,20 +504,31 @@
42
        spa_log_error(state->log, "can't create card %u", state->card_index);
43
        return -errno;
44
    }
45
+   state->log_file = fopencookie(state, "w", io_funcs);
46
+   if (state->log_file == NULL) {
47
+       spa_log_error(state->log, "can't create log file");
48
+       return -errno;
49
+   }
50
+   CHECK(snd_output_stdio_attach(&state->output, state->log_file, 0), "attach failed");
51
+
52
    return 0;
53
 }
54
 
55
 int spa_alsa_clear(struct state *state)
56
 {
57
+   int err;
58
+
59
    release_card(state->card);
60
 
61
    state->card = NULL;
62
    state->card_index = SPA_ID_INVALID;
63
 
64
-   return 0;
65
-}
66
+   if ((err = snd_output_close(state->output)) < 0)
67
+       spa_log_warn(state->log, "output close failed: %s", snd_strerror(err));
68
+   fclose(state->log_file);
69
 
70
-#define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; }
71
+   return err;
72
+}
73
 
74
 int spa_alsa_open(struct state *state, const char *params)
75
 {
76
@@ -505,8 +539,6 @@
77
    if (state->opened)
78
        return 0;
79
 
80
-   CHECK(snd_output_stdio_attach(&state->output, stderr, 0), "attach failed");
81
-
82
    spa_scnprintf(device_name, sizeof(device_name), "%s%s%s",
83
            state->card->ucm_prefix ? state->card->ucm_prefix : "",
84
            props->device, params ? params : "");
85
@@ -538,6 +570,8 @@
86
    return 0;
87
 
88
 error_exit_close:
89
+   spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->props.device,
90
+           spa_strerror(err));
91
    snd_pcm_close(state->hndl);
92
    return err;
93
 }
94
@@ -556,9 +590,6 @@
95
        spa_log_warn(state->log, "%s: close failed: %s", state->props.device,
96
                snd_strerror(err));
97
 
98
-   if ((err = snd_output_close(state->output)) < 0)
99
-       spa_log_warn(state->log, "output close failed: %s", snd_strerror(err));
100
-
101
    spa_system_close(state->data_system, state->timerfd);
102
 
103
    if (state->have_format)
104
@@ -763,6 +794,9 @@
105
    CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
106
    CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max");
107
 
108
+   spa_log_debug(state->log, "min:%u max:%u min-allowed:%u scale:%u all:%d",
109
+           min, max, min_allowed_rate, scale, all);
110
+
111
    min_allowed_rate /= scale;
112
    min = SPA_MAX(min_allowed_rate, min);
113
 
114
@@ -782,6 +816,9 @@
115
 
116
    rate = SPA_CLAMP(rate, min, max);
117
 
118
+   spa_log_debug(state->log, "rate:%u multi:%d card:%d def:%d",
119
+           rate, state->multi_rate, state->card->rate, state->default_rate);
120
+
121
    spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0);
122
 
123
    spa_pod_builder_push_choice(b, &f0, SPA_CHOICE_None, 0);
124
@@ -833,7 +870,8 @@
125
 
126
    CHECK(snd_pcm_hw_params_get_channels_min(params, &min), "get_channels_min");
127
    CHECK(snd_pcm_hw_params_get_channels_max(params, &max), "get_channels_max");
128
-   spa_log_debug(state->log, "channels (%d %d)", min, max);
129
+   spa_log_debug(state->log, "channels (%d %d) default:%d all:%d",
130
+           min, max, state->default_channels, all);
131
 
132
    if (state->default_channels != 0 && !all) {
133
        if (min < state->default_channels)
134
@@ -914,6 +952,14 @@
135
    return 1;
136
 }
137
 
138
+static void debug_hw_params(struct state *state, const char *prefix, snd_pcm_hw_params_t *params)
139
+{
140
+   if (SPA_UNLIKELY(spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_DEBUG))) {
141
+       spa_log_debug(state->log, "%s:", prefix);
142
+       snd_pcm_hw_params_dump(params, state->output);
143
+       fflush(state->log_file);
144
+   }
145
+}
146
 static int enum_pcm_formats(struct state *state, uint32_t index, uint32_t *next,
147
        struct spa_pod **result, struct spa_pod_builder *b)
148
 {
149
@@ -931,6 +977,8 @@
150
    snd_pcm_hw_params_alloca(&params);
151
    CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
152
 
153
+   debug_hw_params(state, __func__, params);
154
+
155
    CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample");
156
 
157
    if (state->default_channels != 0) {
158
@@ -1077,6 +1125,8 @@
159
    snd_pcm_hw_params_alloca(&params);
160
    CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
161
 
162
+   debug_hw_params(state, __func__, params);
163
+
164
    CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample");
165
 
166
    spa_pod_builder_push_object(b, &f0, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
167
@@ -1138,6 +1188,8 @@
168
    snd_pcm_hw_params_alloca(&params);
169
    CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
170
 
171
+   debug_hw_params(state, __func__, params);
172
+
173
    snd_pcm_format_mask_alloca(&fmask);
174
    snd_pcm_hw_params_get_format_mask(params, fmask);
175
 
176
@@ -1197,7 +1249,12 @@
177
    struct spa_result_node_params result;
178
    uint32_t count = 0;
179
 
180
+   spa_log_debug(state->log, "opened:%d format:%d started:%d", state->opened,
181
+           state->have_format, state->started);
182
+
183
    opened = state->opened;
184
+   if (!state->started && state->have_format)
185
+       spa_alsa_close(state);
186
    if ((err = spa_alsa_open(state, NULL)) < 0)
187
        return err;
188
 
189
@@ -1258,6 +1315,9 @@
190
    bool match = true, planar = false, is_batch;
191
    char spdif_params128 = "";
192
 
193
+   spa_log_debug(state->log, "opened:%d format:%d started:%d", state->opened,
194
+           state->have_format, state->started);
195
+
196
    state->use_mmap = !state->disable_mmap;
197
 
198
    switch (fmt->media_subtype) {
199
@@ -1370,6 +1430,8 @@
200
        return -EINVAL;
201
pipewire-0.3.56.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
10
 
1
@@ -106,6 +106,8 @@
2
    struct spa_system *data_system;
3
    struct spa_loop *data_loop;
4
 
5
+   FILE *log_file;
6
+
7
    uint32_t card_index;
8
    struct card *card;
9
    snd_pcm_stream_t stream;
10
pipewire-0.3.56.tar.gz/spa/plugins/alsa/alsa-seq.c -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-seq.c Changed
10
 
1
@@ -186,7 +186,7 @@
2
 
3
 static void debug_event(struct seq_state *state, snd_seq_event_t *ev)
4
 {
5
-   if (SPA_LIKELY(!spa_log_level_enabled(state->log, SPA_LOG_LEVEL_TRACE)))
6
+   if (SPA_LIKELY(!spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_TRACE)))
7
        return;
8
 
9
    spa_log_trace(state->log, "event type:%d flags:0x%x", ev->type, ev->flags);
10
pipewire-0.3.56.tar.gz/spa/plugins/alsa/meson.build -> pipewire-0.3.57.tar.gz/spa/plugins/alsa/meson.build Changed
21
 
1
@@ -34,13 +34,18 @@
2
   install : true,
3
 )
4
 
5
-
6
 executable('test-timer',
7
    'test-timer.c' ,
8
   dependencies :  spa_dep, alsa_dep, mathlib, epoll_shim_dep ,
9
   install : false,
10
 )
11
 
12
+executable('test-hw-params',
13
+   'test-hw-params.c' ,
14
+  dependencies :  spa_dep, alsa_dep, mathlib ,
15
+  install : false,
16
+)
17
+
18
 if libudev_dep.found()
19
   install_data(alsa_udevrules,
20
     install_dir : udevrulesdir,
21
pipewire-0.3.57.tar.gz/spa/plugins/alsa/test-hw-params.c Added
175
 
1
@@ -0,0 +1,173 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <stdio.h>
27
+#include <stdbool.h>
28
+#include <limits.h>
29
+#include <getopt.h>
30
+#include <math.h>
31
+
32
+#include <alsa/asoundlib.h>
33
+
34
+#include <spa/utils/defs.h>
35
+
36
+#define DEFAULT_DEVICE "default"
37
+
38
+
39
+struct state {
40
+   const char *device;
41
+   snd_output_t *output;
42
+   snd_pcm_t *hndl;
43
+};
44
+
45
+#define CHECK(s,msg,...) {     \
46
+   int __err;          \
47
+   if ((__err = (s)) < 0) {    \
48
+       fprintf(stderr, msg ": %s\n", ##__VA_ARGS__, snd_strerror(__err));  \
49
+       return __err;       \
50
+   }               \
51
+}
52
+
53
+static const char *get_class(snd_pcm_class_t c)
54
+{
55
+   switch (c) {
56
+   case SND_PCM_CLASS_GENERIC:
57
+       return "generic";
58
+   case SND_PCM_CLASS_MULTI:
59
+       return "multichannel";
60
+   case SND_PCM_CLASS_MODEM:
61
+       return "modem";
62
+   case SND_PCM_CLASS_DIGITIZER:
63
+       return "digitizer";
64
+   default:
65
+       return "unknown";
66
+   }
67
+}
68
+
69
+static const char *get_subclass(snd_pcm_subclass_t c)
70
+{
71
+   switch (c) {
72
+   case SND_PCM_SUBCLASS_GENERIC_MIX:
73
+       return "generic-mix";
74
+   case SND_PCM_SUBCLASS_MULTI_MIX:
75
+       return "multichannel-mix";
76
+   default:
77
+       return "unknown";
78
+   }
79
+}
80
+
81
+static void show_help(const char *name, bool error)
82
+{
83
+        fprintf(error ? stderr : stdout, "%s options\n"
84
+       "  -h, --help                            Show this help\n"
85
+       "  -D, --device                          device name (default '%s')\n"
86
+       "  -C, --capture                         capture mode (default playback)\n",
87
+       name, DEFAULT_DEVICE);
88
+}
89
+
90
+int main(int argc, char *argv)
91
+{
92
+   struct state state = { 0, };
93
+   snd_pcm_hw_params_t *hparams;
94
+   snd_pcm_info_t *info;
95
+   snd_pcm_sync_id_t sync;
96
+   snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
97
+   snd_pcm_chmap_query_t **maps;
98
+   int c, i;
99
+   static const struct option long_options = {
100
+       { "help",   no_argument,        NULL, 'h' },
101
+       { "device", required_argument,  NULL, 'D' },
102
+       { "capture",    no_argument,        NULL, 'C' },
103
+       { NULL, 0, NULL, 0}
104
+   };
105
+   state.device = DEFAULT_DEVICE;
106
+
107
+   while ((c = getopt_long(argc, argv, "hD:C", long_options, NULL)) != -1) {
108
+       switch (c) {
109
+       case 'h':
110
+           show_help(argv0, false);
111
+           return 0;
112
+       case 'D':
113
+           state.device = optarg;
114
+           break;
115
+       case 'C':
116
+           stream = SND_PCM_STREAM_CAPTURE;
117
+           break;
118
+       default:
119
+           show_help(argv0, true);
120
+           return -1;
121
+       }
122
+   }
123
+
124
+   CHECK(snd_output_stdio_attach(&state.output, stdout, 0), "attach failed");
125
+
126
+   fprintf(stdout, "opening device: '%s'\n", state.device);
127
+
128
+   CHECK(snd_pcm_open(&state.hndl, state.device, stream, 0),
129
+           "open %s failed", state.device);
130
+
131
+   snd_pcm_info_alloca(&info);
132
+   snd_pcm_info(state.hndl, info);
133
+
134
+   fprintf(stdout, "info:\n");
135
+   fprintf(stdout, "  device: %u\n", snd_pcm_info_get_device(info));
136
+   fprintf(stdout, "  subdevice: %u\n", snd_pcm_info_get_subdevice(info));
137
+   fprintf(stdout, "  stream: %s\n", snd_pcm_stream_name(snd_pcm_info_get_stream(info)));
138
+   fprintf(stdout, "  card: %d\n", snd_pcm_info_get_card(info));
139
+   fprintf(stdout, "  id: '%s'\n", snd_pcm_info_get_id(info));
140
+   fprintf(stdout, "  name: '%s'\n", snd_pcm_info_get_name(info));
141
+   fprintf(stdout, "  subdevice name: '%s'\n", snd_pcm_info_get_subdevice_name(info));
142
+   fprintf(stdout, "  class: %s\n", get_class(snd_pcm_info_get_class(info)));
143
+   fprintf(stdout, "  subclass: %s\n", get_subclass(snd_pcm_info_get_subclass(info)));
144
+   fprintf(stdout, "  subdevice count: %u\n", snd_pcm_info_get_subdevices_count(info));
145
+   fprintf(stdout, "  subdevice avail: %u\n", snd_pcm_info_get_subdevices_avail(info));
146
+   sync = snd_pcm_info_get_sync(info);
147
+   fprintf(stdout, "  sync: %08x:%08x:%08x:%08x\n",
148
+           sync.id320, sync.id321, sync.id322,sync.id323);
149
+
150
+   /* channel maps */
151
+   if ((maps = snd_pcm_query_chmaps(state.hndl)) != NULL) {
152
+       fprintf(stdout, "channels:\n");
153
+
154
+       for (i = 0; mapsi; i++) {
155
+           snd_pcm_chmap_t* map = &mapsi->map;
156
+           char buf2048;
157
+
158
+           snd_pcm_chmap_print(map, sizeof(buf), buf);
159
+
160
+           fprintf(stdout, "  %d: %s\n", map->channels, buf);
161
+       }
162
+       snd_pcm_free_chmaps(maps);
163
+   }
164
+
165
+   /* hw params */
166
+   snd_pcm_hw_params_alloca(&hparams);
167
+   snd_pcm_hw_params_any(state.hndl, hparams);
168
+
169
+   snd_pcm_hw_params_dump(hparams, state.output);
170
+
171
+   snd_pcm_close(state.hndl);
172
+
173
+   return EXIT_SUCCESS;
174
+}
175
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
147
 
1
@@ -909,8 +909,7 @@
2
            }
3
            break;
4
        case SPA_PROP_rate:
5
-           if (spa_pod_get_double(&prop->value, &p->rate) == 0)
6
-               changed++;
7
+           spa_pod_get_double(&prop->value, &p->rate);
8
            break;
9
        case SPA_PROP_params:
10
            changed += parse_prop_params(this, &prop->value);
11
@@ -1471,26 +1470,29 @@
12
 
13
    rate = this->io_position ?  this->io_position->clock.rate.denom : DEFAULT_RATE;
14
 
15
-   if (in->format.info.raw.rate == 0 && in->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp)
16
+   /* in DSP mode we always convert to the DSP rate */
17
+   if (in->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp)
18
        in->format.info.raw.rate = rate;
19
-   if (out->format.info.raw.rate == 0 && out->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp)
20
+   if (out->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp)
21
        out->format.info.raw.rate = rate;
22
 
23
+   /* try to passthrough the rates */
24
    if (in->format.info.raw.rate == 0)
25
        in->format.info.raw.rate = out->format.info.raw.rate;
26
    else if (out->format.info.raw.rate == 0)
27
        out->format.info.raw.rate = in->format.info.raw.rate;
28
 
29
-   if (in->format.info.raw.rate == 0 && out->format.info.raw.rate == 0)
30
-       return -EINVAL;
31
-   if (in->format.info.raw.channels == 0 && out->format.info.raw.channels == 0)
32
-       return -EINVAL;
33
-
34
+   /* try to passthrough the channels */
35
    if (in->format.info.raw.channels == 0)
36
        in->format.info.raw.channels = out->format.info.raw.channels;
37
    else if (out->format.info.raw.channels == 0)
38
        out->format.info.raw.channels = in->format.info.raw.channels;
39
 
40
+   if (in->format.info.raw.rate == 0 || out->format.info.raw.rate == 0)
41
+       return -EINVAL;
42
+   if (in->format.info.raw.channels == 0 || out->format.info.raw.channels == 0)
43
+       return -EINVAL;
44
+
45
    if ((res = setup_in_convert(this)) < 0)
46
        return res;
47
    if ((res = setup_channelmix(this)) < 0)
48
@@ -1722,21 +1724,51 @@
49
            param = spa_format_audio_raw_build(&b, id, &port->format.info.raw);
50
        break;
51
    case SPA_PARAM_Buffers:
52
+   {
53
+       uint32_t size;
54
+       struct dir *dir;
55
+
56
        if (!port->have_format)
57
            return -EIO;
58
        if (result.index > 0)
59
            return 0;
60
 
61
+       dir = &this->dirdirection;
62
+       if (dir->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp) {
63
+           /* DSP ports always use the quantum_limit as the buffer
64
+            * size. */
65
+           size = this->quantum_limit;
66
+       } else {
67
+           uint32_t irate, orate;
68
+           /* Convert ports are scaled so that they can always
69
+            * provide one quantum of data */
70
+           irate = dir->format.info.raw.rate;
71
+
72
+           /* collect the other port rate */
73
+           dir = &this->dirSPA_DIRECTION_REVERSE(direction);
74
+           if (dir->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp)
75
+               orate = this->io_position ?  this->io_position->clock.rate.denom : DEFAULT_RATE;
76
+           else
77
+               orate = dir->format.info.raw.rate;
78
+
79
+           /* always keep some extra room for adaptive resampling */
80
+           size = this->quantum_limit * 2;
81
+           /*  scale the buffer size when we can. */
82
+           if (irate != 0 && orate != 0)
83
+               size = size * (irate + orate - 1) / orate;
84
+       }
85
+
86
        param = spa_pod_builder_add_object(&b,
87
            SPA_TYPE_OBJECT_ParamBuffers, id,
88
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
89
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
90
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
91
-                               this->quantum_limit * port->stride,
92
+                               size * port->stride,
93
                                16 * port->stride,
94
                                INT32_MAX),
95
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->stride));
96
        break;
97
+   }
98
    case SPA_PARAM_Meta:
99
        switch (result.index) {
100
        case 0:
101
@@ -2193,15 +2225,22 @@
102
    return end ? 1 : 0;
103
 }
104
 
105
+static uint32_t resample_get_in_size(struct impl *this, bool passthrough, uint32_t out_size)
106
+{
107
+   uint32_t match_size = passthrough ? out_size : resample_in_len(&this->resample, out_size);
108
+   spa_log_trace_fp(this->log, "%p: current match %u", this, match_size);
109
+   return match_size;
110
+}
111
+
112
 static uint32_t resample_update_rate_match(struct impl *this, bool passthrough, uint32_t out_size, uint32_t in_queued)
113
 {
114
-   double rate = this->rate_scale / this->props.rate;
115
    uint32_t delay, match_size;
116
 
117
    if (passthrough) {
118
        delay = 0;
119
        match_size = out_size;
120
    } else {
121
+       double rate = this->rate_scale / this->props.rate;
122
        if (this->io_rate_match &&
123
            SPA_FLAG_IS_SET(this->io_rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE))
124
            rate *= this->io_rate_match->rate;
125
@@ -2470,16 +2509,16 @@
126
 
127
    /* calculate how many samples we are going to consume. */
128
    if (this->direction == SPA_DIRECTION_INPUT) {
129
-       uint32_t n_in;
130
-       /* then figure out how much input samples we need to consume */
131
-       n_in = resample_update_rate_match(this, resample_passthrough, n_out, 0);
132
        if (!in_avail || this->drained) {
133
+           /* no input, ask for more, update rate-match first */
134
+           resample_update_rate_match(this, resample_passthrough, n_out, 0);
135
            spa_log_trace_fp(this->log, "%p: no input drained:%d", this, this->drained);
136
-           /* no input, ask for more */
137
            res |= this->drained ? SPA_STATUS_DRAINED : SPA_STATUS_NEED_DATA;
138
            return res;
139
        }
140
-       n_samples = SPA_MIN(n_samples, n_in);
141
+       /* else figure out how much input samples we need to consume */
142
+       n_samples = SPA_MIN(n_samples,
143
+               resample_get_in_size(this, resample_passthrough, n_out));
144
    } else {
145
        /* in merge mode we consume one duration of samples */
146
        n_samples = SPA_MIN(n_samples, quant_samples);
147
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/channelmix-ops.c Changed
55
 
1
@@ -200,6 +200,7 @@
2
                matrixii= 1.0f;
3
        }
4
        src_mask = dst_mask = ~0LU;
5
+       filter_fc = filter_lfe = true;
6
        goto done;
7
    } else {
8
        spa_log_debug(mix->log, "matching channels");
9
@@ -398,6 +399,15 @@
10
    spa_log_debug(mix->log, "unassigned upmix %08"PRIx64" lfe:%f",
11
            unassigned, mix->lfe_cutoff);
12
 
13
+   if (unassigned & STEREO) {
14
+       if ((src_mask & FRONT) == FRONT) {
15
+           spa_log_debug(mix->log, "produce STEREO from FC");
16
+           _MATRIX(FL,FC) += clev;
17
+           _MATRIX(FR,FC) += clev;
18
+       } else {
19
+           spa_log_warn(mix->log, "can't produce STEREO");
20
+       }
21
+   }
22
    if (unassigned & FRONT) {
23
        if ((src_mask & STEREO) == STEREO) {
24
            spa_log_debug(mix->log, "produce FC from STEREO");
25
@@ -431,10 +441,13 @@
26
            spa_log_debug(mix->log, "produce SIDE from STEREO");
27
            _MATRIX(SL,FL) += slev;
28
            _MATRIX(SR,FR) += slev;
29
-       } else if ((src_mask & FRONT) == FRONT) {
30
+       } else if ((src_mask & FRONT) == FRONT &&
31
+           mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
32
            spa_log_debug(mix->log, "produce SIDE from FC");
33
            _MATRIX(SL,FC) += clev;
34
            _MATRIX(SR,FC) += clev;
35
+       } else {
36
+           spa_log_debug(mix->log, "won't produce SIDE");
37
        }
38
    }
39
    if (unassigned & REAR) {
40
@@ -446,10 +459,13 @@
41
            spa_log_debug(mix->log, "produce REAR from STEREO");
42
            _MATRIX(RL,FL) += slev;
43
            _MATRIX(RR,FR) += slev;
44
-       } else if ((src_mask & FRONT) == FRONT) {
45
+       } else if ((src_mask & FRONT) == FRONT &&
46
+           mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
47
            spa_log_debug(mix->log, "produce REAR from FC");
48
            _MATRIX(RL,FC) += clev;
49
            _MATRIX(RR,FC) += clev;
50
+       } else {
51
+           spa_log_debug(mix->log, "won't produce SIDE");
52
        }
53
    }
54
 
55
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c Changed
101
 
1
@@ -362,7 +362,7 @@
2
    float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3;
3
    uint32_t n, unrolled;
4
    __m256i in4, t4;
5
-   __m256 out4, factor = _mm256_set1_ps(1.0f / S32_SCALE);
6
+   __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
7
    __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 0*n_channels+2, 4*n_channels, 4*n_channels+2);
8
    __m256i mask2 = _mm256_setr_epi64x(1*n_channels, 1*n_channels+2, 5*n_channels, 5*n_channels+2);
9
    __m256i mask3 = _mm256_setr_epi64x(2*n_channels, 2*n_channels+2, 6*n_channels, 6*n_channels+2);
10
@@ -391,6 +391,11 @@
11
        in2 = _mm256_unpacklo_epi64(t1, t3);     /* c0 c1 c2 c3 c4 c5 c6 c7 */
12
        in3 = _mm256_unpackhi_epi64(t1, t3);     /* d0 d1 d2 d3 d4 d5 d6 d7 */
13
 
14
+       in0 = _mm256_srai_epi32(in0, 8);
15
+       in1 = _mm256_srai_epi32(in1, 8);
16
+       in2 = _mm256_srai_epi32(in2, 8);
17
+       in3 = _mm256_srai_epi32(in3, 8);
18
+
19
        out0 = _mm256_cvtepi32_ps(in0);
20
        out1 = _mm256_cvtepi32_ps(in1);
21
        out2 = _mm256_cvtepi32_ps(in2);
22
@@ -409,11 +414,11 @@
23
        s += 8*n_channels;
24
    }
25
    for(; n < n_samples; n++) {
26
-       __m128 out4, factor = _mm_set1_ps(1.0f / S32_SCALE);
27
-       out0 = _mm_cvtsi32_ss(factor, s0);
28
-       out1 = _mm_cvtsi32_ss(factor, s1);
29
-       out2 = _mm_cvtsi32_ss(factor, s2);
30
-       out3 = _mm_cvtsi32_ss(factor, s3);
31
+       __m128 out4, factor = _mm_set1_ps(1.0f / S24_SCALE);
32
+       out0 = _mm_cvtsi32_ss(factor, s0 >> 8);
33
+       out1 = _mm_cvtsi32_ss(factor, s1 >> 8);
34
+       out2 = _mm_cvtsi32_ss(factor, s2 >> 8);
35
+       out3 = _mm_cvtsi32_ss(factor, s3 >> 8);
36
        out0 = _mm_mul_ss(out0, factor);
37
        out1 = _mm_mul_ss(out1, factor);
38
        out2 = _mm_mul_ss(out2, factor);
39
@@ -434,7 +439,7 @@
40
    float *d0 = dst0, *d1 = dst1;
41
    uint32_t n, unrolled;
42
    __m256i in4, t4;
43
-   __m256 out4, factor = _mm256_set1_ps(1.0f / S32_SCALE);
44
+   __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
45
    __m256i perm = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7);
46
    __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels);
47
    __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
48
@@ -455,6 +460,9 @@
49
        in0 = _mm256_permute2x128_si256(t0, t1, 0 | (2 << 4));
50
        in1 = _mm256_permute2x128_si256(t0, t1, 1 | (3 << 4));
51
 
52
+       in0 = _mm256_srai_epi32(in0, 8);
53
+       in1 = _mm256_srai_epi32(in1, 8);
54
+
55
        out0 = _mm256_cvtepi32_ps(in0);
56
        out1 = _mm256_cvtepi32_ps(in1);
57
 
58
@@ -467,9 +475,9 @@
59
        s += 8*n_channels;
60
    }
61
    for(; n < n_samples; n++) {
62
-       __m128 out2, factor = _mm_set1_ps(1.0f / S32_SCALE);
63
-       out0 = _mm_cvtsi32_ss(factor, s0);
64
-       out1 = _mm_cvtsi32_ss(factor, s1);
65
+       __m128 out2, factor = _mm_set1_ps(1.0f / S24_SCALE);
66
+       out0 = _mm_cvtsi32_ss(factor, s0 >> 8);
67
+       out1 = _mm_cvtsi32_ss(factor, s1 >> 8);
68
        out0 = _mm_mul_ss(out0, factor);
69
        out1 = _mm_mul_ss(out1, factor);
70
        _mm_store_ss(&d0n, out0);
71
@@ -486,7 +494,7 @@
72
    float *d0 = dst0;
73
    uint32_t n, unrolled;
74
    __m256i in2;
75
-   __m256 out2, factor = _mm256_set1_ps(1.0f / S32_SCALE);
76
+   __m256 out2, factor = _mm256_set1_ps(1.0f / S24_SCALE);
77
    __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels);
78
    __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
79
 
80
@@ -503,6 +511,9 @@
81
                _mm256_i64gather_epi32(&s 8*n_channels, mask1, 4),
82
                _mm256_i64gather_epi32(&s 8*n_channels, mask2, 4));
83
 
84
+       in0 = _mm256_srai_epi32(in0, 8);
85
+       in1 = _mm256_srai_epi32(in1, 8);
86
+
87
        out0 = _mm256_cvtepi32_ps(in0);
88
        out1 = _mm256_cvtepi32_ps(in1);
89
 
90
@@ -515,8 +526,8 @@
91
        s += 16*n_channels;
92
    }
93
    for(; n < n_samples; n++) {
94
-       __m128 out, factor = _mm_set1_ps(1.0f / S32_SCALE);
95
-       out = _mm_cvtsi32_ss(factor, s0);
96
+       __m128 out, factor = _mm_set1_ps(1.0f / S24_SCALE);
97
+       out = _mm_cvtsi32_ss(factor, s0 >> 8);
98
        out = _mm_mul_ss(out, factor);
99
        _mm_store_ss(&d0n, out);
100
        s += n_channels;
101
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c Changed
200
 
1
@@ -26,6 +26,8 @@
2
 #include <stdio.h>
3
 #include <math.h>
4
 
5
+#include <arm_neon.h>
6
+
7
 #include "fmt-ops.h"
8
 
9
 void
10
@@ -289,16 +291,19 @@
11
 
12
 #ifdef __aarch64__
13
    asm volatile(
14
+       "      dup v2.4s, %wscale\n"
15
        "      cmp %n_samples, #0\n"
16
        "      beq 2f\n"
17
        "1:"
18
        "      ld1 { v0.4s }, %s0, #16\n"
19
        "      ld1 { v1.4s }, %s1, #16\n"
20
        "      subs %n_samples, %n_samples, #4\n"
21
-       "      fcvtzs v0.4s, v0.4s, #31\n"
22
-       "      fcvtzs v1.4s, v1.4s, #31\n"
23
-       "      sqrshrn v0.4h, v0.4s, #16\n"
24
-       "      sqrshrn v1.4h, v1.4s, #16\n"
25
+       "      sqadd  v0.4s, v0.4s, v2.4s\n"
26
+       "      sqadd  v1.4s, v1.4s, v2.4s\n"
27
+       "      fcvtns v0.4s, v0.4s\n"
28
+       "      fcvtns v1.4s, v1.4s\n"
29
+       "      sqxtn  v0.4h, v0.4s\n"
30
+       "      sqxtn  v1.4h, v1.4s\n"
31
        "      st2 { v0.h, v1.h }0, %d, %stride\n"
32
        "      st2 { v0.h, v1.h }1, %d, %stride\n"
33
        "      st2 { v0.h, v1.h }2, %d, %stride\n"
34
@@ -311,29 +316,42 @@
35
        "      ld1 { v0.s }0, %s0, #4\n"
36
        "      ld1 { v2.s }0, %s1, #4\n"
37
        "      subs %remainder, %remainder, #1\n"
38
-       "      fcvtzs v0.4s, v0.4s, #31\n"
39
-       "      fcvtzs v1.4s, v1.4s, #31\n"
40
-       "      sqrshrn v0.4h, v0.4s, #16\n"
41
-       "      sqrshrn v1.4h, v1.4s, #16\n"
42
+       "      sqadd  v0.4s, v0.4s, v2.4s\n"
43
+       "      sqadd  v1.4s, v1.4s, v2.4s\n"
44
+       "      fcvtns v0.4s, v0.4s\n"
45
+       "      fcvtns v1.4s, v1.4s\n"
46
+       "      sqxtn  v0.4h, v0.4s\n"
47
+       "      sqxtn  v1.4h, v1.4s\n"
48
        "      st2 { v0.h, v1.h }0, %d, %stride\n"
49
        "      bne 3b\n"
50
        "4:"
51
        : d "+r" (d), s0 "+r" (s0), s1 "+r" (s1), n_samples "+r" (n_samples),
52
          remainder "+r" (remainder)
53
-       : stride "r" (stride)
54
+       : stride "r" (stride),
55
+         scale "r" (15 << 23)
56
        : "cc", "v0", "v1");
57
 #else
58
+   float32x4_t pos = vdupq_n_f32(0.4999999f / S16_SCALE);
59
+   float32x4_t neg = vdupq_n_f32(-0.4999999f / S16_SCALE);
60
+
61
    asm volatile(
62
+       "      veor q2, q2, q2\n"
63
        "      cmp %n_samples, #0\n"
64
        "      beq 2f\n"
65
        "1:"
66
        "      vld1.32 { q0 }, %s0!\n"
67
        "      vld1.32 { q1 }, %s1!\n"
68
        "      subs %n_samples, %n_samples, #4\n"
69
-       "      vcvt.s32.f32 q0, q0, #31\n"
70
-       "      vcvt.s32.f32 q1, q1, #31\n"
71
-       "      vqrshrn.s32 d0, q0, #16\n"
72
-       "      vqrshrn.s32 d1, q1, #16\n"
73
+       "      vcgt.f32 q3, q0, q2\n"
74
+       "      vcgt.f32 q4, q0, q2\n"
75
+       "      vbsl q3, %qpos, %qneg\n"
76
+       "      vbsl q4, %qpos, %qneg\n"
77
+       "      vadd.f32 q0, q0, q3\n"
78
+       "      vadd.f32 q1, q1, q4\n"
79
+       "      vcvt.s32.f32 q0, q0, #15\n"
80
+       "      vcvt.s32.f32 q1, q1, #15\n"
81
+       "      vqmovn.s32 d0, q0\n"
82
+       "      vqmovn.s32 d1, q1\n"
83
        "      vst2.16 { d00, d10 }, %d, %stride\n"
84
        "      vst2.16 { d01, d11 }, %d, %stride\n"
85
        "      vst2.16 { d02, d12 }, %d, %stride\n"
86
@@ -346,17 +364,25 @@
87
        "      vld1.32 { d00 }, %s0!\n"
88
        "      vld1.32 { d20 }, %s1!\n"
89
        "      subs %remainder, %remainder, #1\n"
90
-       "      vcvt.s32.f32 q0, q0, #31\n"
91
-       "      vcvt.s32.f32 q1, q1, #31\n"
92
-       "      vqrshrn.s32 d0, q0, #16\n"
93
-       "      vqrshrn.s32 d1, q1, #16\n"
94
+       "      vcgt.f32 q3, q0, q2\n"
95
+       "      vcgt.f32 q4, q0, q2\n"
96
+       "      vbsl q3, %qpos, %qneg\n"
97
+       "      vbsl q4, %qpos, %qneg\n"
98
+       "      vadd.f32 q0, q0, q3\n"
99
+       "      vadd.f32 q1, q1, q4\n"
100
+       "      vcvt.s32.f32 q0, q0, #15\n"
101
+       "      vcvt.s32.f32 q1, q1, #15\n"
102
+       "      vqmovn.s32 d0, q0\n"
103
+       "      vqmovn.s32 d1, q1\n"
104
        "      vst2.16 { d00, d10 }, %d, %stride\n"
105
        "      bne 3b\n"
106
        "4:"
107
        : d "+r" (d), s0 "+r" (s0), s1 "+r" (s1), n_samples "+r" (n_samples),
108
          remainder "+r" (remainder)
109
-       : stride "r" (stride)
110
-       : "cc", "q0", "q1");
111
+       : stride "r" (stride),
112
+         pos"w"(pos),
113
+         neg"w"(neg)
114
+       : "cc", "q0", "q1", "q2", "q3", "q4");
115
 #endif
116
 }
117
 
118
@@ -372,13 +398,15 @@
119
 
120
 #ifdef __aarch64__
121
    asm volatile(
122
+       "      dup v2.4s, %wscale\n"
123
        "      cmp %n_samples, #0\n"
124
        "      beq 2f\n"
125
        "1:"
126
        "      ld1 { v0.4s }, %s, #16\n"
127
        "      subs %n_samples, %n_samples, #4\n"
128
-       "      fcvtzs v0.4s, v0.4s, #31\n"
129
-       "      sqrshrn v0.4h, v0.4s, #16\n"
130
+       "      sqadd  v0.4s, v0.4s, v2.4s\n"
131
+       "      fcvtns v0.4s, v0.4s\n"
132
+       "      sqxtn  v0.4h, v0.4s\n"
133
        "      st1 { v0.h }0, %d, %stride\n"
134
        "      st1 { v0.h }1, %d, %stride\n"
135
        "      st1 { v0.h }2, %d, %stride\n"
136
@@ -390,24 +418,33 @@
137
        "3:"
138
        "      ld1 { v0.s }0, %s, #4\n"
139
        "      subs %remainder, %remainder, #1\n"
140
-       "      fcvtzs v0.4s, v0.4s, #31\n"
141
-       "      sqrshrn v0.4h, v0.4s, #16\n"
142
+       "      sqadd  v0.4s, v0.4s, v2.4s\n"
143
+       "      fcvtns v0.4s, v0.4s\n"
144
+       "      sqxtn  v0.4h, v0.4s\n"
145
        "      st1 { v0.h }0, %d, %stride\n"
146
        "      bne 3b\n"
147
        "4:"
148
        : d "+r" (d), s "+r" (s), n_samples "+r" (n_samples),
149
          remainder "+r" (remainder)
150
-       : stride "r" (stride)
151
+       : stride "r" (stride),
152
+         scale "r" (15 << 23)
153
        : "cc", "v0");
154
 #else
155
+   float32x4_t pos = vdupq_n_f32(0.4999999f / S16_SCALE);
156
+   float32x4_t neg = vdupq_n_f32(-0.4999999f / S16_SCALE);
157
+
158
    asm volatile(
159
+       "      veor q1, q1, q1\n"
160
        "      cmp %n_samples, #0\n"
161
        "      beq 2f\n"
162
        "1:"
163
        "      vld1.32 { q0 }, %s!\n"
164
        "      subs %n_samples, %n_samples, #4\n"
165
-       "      vcvt.s32.f32 q0, q0, #31\n"
166
-       "      vqrshrn.s32 d0, q0, #16\n"
167
+       "      vcgt.f32 q2, q0, q1\n"
168
+       "      vbsl q2, %qpos, %qneg\n"
169
+       "      vadd.f32 q0, q0, q2\n"
170
+       "      vcvt.s32.f32 q0, q0, #15\n"
171
+       "      vqmovn.s32 d0, q0\n"
172
        "      vst1.16 { d00 }, %d, %stride\n"
173
        "      vst1.16 { d01 }, %d, %stride\n"
174
        "      vst1.16 { d02 }, %d, %stride\n"
175
@@ -419,15 +456,20 @@
176
        "3:"
177
        "      vld1.32 { d00 }, %s!\n"
178
        "      subs %remainder, %remainder, #1\n"
179
-       "      vcvt.s32.f32 q0, q0, #31\n"
180
-       "      vqrshrn.s32 d0, q0, #16\n"
181
+       "      vcgt.f32 q2, q0, q1\n"
182
+       "      vbsl q2, %qpos, %qneg\n"
183
+       "      vadd.f32 q0, q0, q2\n"
184
+       "      vcvt.s32.f32 q0, q0, #15\n"
185
+       "      vqmovn.s32 d0, q0\n"
186
        "      vst1.16 { d00 }, %d, %stride\n"
187
        "      bne 3b\n"
188
        "4:"
189
        : d "+r" (d), s "+r" (s), n_samples "+r" (n_samples),
190
          remainder "+r" (remainder)
191
-       : stride "r" (stride)
192
-       : "cc", "q0");
193
+       : stride "r" (stride),
194
+         pos"w"(pos),
195
+         neg"w"(neg)
196
+       : "cc", "q0", "q1", "q2");
197
 #endif
198
 }
199
 
200
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/fmt-ops.h Changed
22
 
1
@@ -40,7 +40,7 @@
2
 #define ITOF(type,v,scale,offs) \
3
    (((type)(v)) * (1.0f / (scale)) - (offs))
4
 #define FTOI(type,v,scale,offs,noise,min,max) \
5
-   (type)f32_round(SPA_CLAMP((v) * (scale) + (offs) + (noise), min, max))
6
+   (type)f32_round(SPA_CLAMPF((v) * (scale) + (offs) + (noise), min, max))
7
 
8
 #define FMT_OPS_MAX_ALIGN  32
9
 
10
@@ -119,9 +119,8 @@
11
 #define F32_TO_S24_32S(v)  bswap_32(F32_TO_S24_32(v))
12
 #define F32_TO_S24_32S_D(v,d)  bswap_32(F32_TO_S24_32_D(v,d))
13
 
14
-#define S32_MIN            -2147483648
15
-#define S32_MAX            2147483647
16
-#define S32_SCALE      2147483648.f
17
+#define S32_MIN            (S24_MIN * 256)
18
+#define S32_MAX            (S24_MAX * 256)
19
 #define S32_TO_F32(v)      ITOF(int32_t, (v) >> 8, S24_SCALE, 0.0f)
20
 #define S32S_TO_F32(v)     S32_TO_F32(bswap_32(v))
21
 #define F32_TO_S32(v)      (F32_TO_S24_32(v) << 8)
22
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/resample-native.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native.c Changed
20
 
1
@@ -68,14 +68,15 @@
2
 }
3
 static inline double window_cosh(double x, double n_taps)
4
 {
5
-   double R = 190.0, r;
6
-   double A = (-325.1E-6 * R + 0.1677) * R - 3.149;
7
+   double r;
8
+   double A = 16.97789;
9
    double x2;
10
    x =  2.0 * x / n_taps;
11
    x2 = x * x;
12
    if (x2 >= 1.0)
13
        return 0.0;
14
-   r = cosh(A * sqrt(1 - x2)) / cosh(A);
15
+   /* doi:10.1109/RME.2008.4595727 with tweak */
16
+   r = (exp(A * sqrt(1 - x2)) - 1) / (exp(A) - 1);
17
    return r;
18
 }
19
 
20
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c Changed
27
 
1
@@ -242,6 +242,12 @@
2
            false, true, conv_f32d_to_s16_avx2);
3
    }
4
 #endif
5
+#if defined(HAVE_NEON)
6
+   if (cpu_flags & SPA_CPU_FLAG_NEON) {
7
+       run_test("test_f32d_s16_neon", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out),
8
+           false, true, conv_f32d_to_s16_neon);
9
+   }
10
+#endif
11
 }
12
 
13
 static void test_s16_f32(void)
14
@@ -269,6 +275,12 @@
15
            true, false, conv_s16_to_f32d_avx2);
16
    }
17
 #endif
18
+#if defined(HAVE_NEON)
19
+   if (cpu_flags & SPA_CPU_FLAG_NEON) {
20
+       run_test("test_s16_f32d_neon", in, sizeof(in0), out, sizeof(out0), SPA_N_ELEMENTS(out),
21
+           true, false, conv_s16_to_f32d_neon);
22
+   }
23
+#endif
24
 }
25
 
26
 static void test_f32_u32(void)
27
pipewire-0.3.56.tar.gz/spa/plugins/audioconvert/test-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/test-source.c Changed
13
 
1
@@ -749,9 +749,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = GET_OUT_PORT(this, 0);
5
-
6
-   io = port->io;
7
-   spa_return_val_if_fail(io != NULL, -EIO);
8
+   if ((io = port->io) == NULL)
9
+       return -EIO;
10
 
11
    spa_log_trace_fp(this->log, NAME " %p: status %d", this, io->status);
12
 
13
pipewire-0.3.56.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.57.tar.gz/spa/plugins/audiomixer/audiomixer.c Changed
12
 
1
@@ -730,8 +730,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    outport = GET_OUT_PORT(this, 0);
5
-   outio = outport->io;
6
-   spa_return_val_if_fail(outio != NULL, -EIO);
7
+   if ((outio = outport->io) == NULL)
8
+       return -EIO;
9
 
10
    spa_log_trace_fp(this->log, "%p: status %p %d %d",
11
            this, outio, outio->status, outio->buffer_id);
12
pipewire-0.3.56.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.57.tar.gz/spa/plugins/audiomixer/mixer-dsp.c Changed
12
 
1
@@ -675,8 +675,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    outport = GET_OUT_PORT(this, 0);
5
-   outio = outport->io;
6
-   spa_return_val_if_fail(outio != NULL, -EIO);
7
+   if ((outio = outport->io) == NULL)
8
+       return -EIO;
9
 
10
    spa_log_trace_fp(this->log, "%p: status %p %d %d",
11
            this, outio, outio->status, outio->buffer_id);
12
pipewire-0.3.56.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.57.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c Changed
11
 
1
@@ -931,7 +931,8 @@
2
    port = &this->port;
3
 
4
    io = port->io;
5
-   spa_return_val_if_fail(io != NULL, -EIO);
6
+   if ((io = port->io) == NULL)
7
+       return -EIO;
8
 
9
    if (port->io_control)
10
        process_control(this, &port->io_control->sequence);
11
pipewire-0.3.56.tar.gz/spa/plugins/avb/avb-pcm-sink.c -> pipewire-0.3.57.tar.gz/spa/plugins/avb/avb-pcm-sink.c Changed
56
 
1
@@ -699,40 +699,39 @@
2
 {
3
    struct state *this = object;
4
    struct port *port;
5
-   struct spa_io_buffers *input;
6
+   struct spa_io_buffers *io;
7
 
8
    spa_return_val_if_fail(this != NULL, -EINVAL);
9
 
10
    port = GET_PORT(this, SPA_DIRECTION_INPUT, 0);
11
+   if ((io = port->io) == NULL)
12
+       return -EIO;
13
 
14
-   input = port->io;
15
-   spa_return_val_if_fail(input != NULL, -EIO);
16
-
17
-   spa_log_trace_fp(this->log, "%p: process %d %d/%d", this, input->status,
18
-           input->buffer_id, port->n_buffers);
19
+   spa_log_trace_fp(this->log, "%p: process %d %d/%d", this, io->status,
20
+           io->buffer_id, port->n_buffers);
21
 
22
    if (this->position && this->position->clock.flags & SPA_IO_CLOCK_FLAG_FREEWHEEL) {
23
-       input->status = SPA_STATUS_NEED_DATA;
24
+       io->status = SPA_STATUS_NEED_DATA;
25
        return SPA_STATUS_HAVE_DATA;
26
    }
27
-   if (input->status == SPA_STATUS_HAVE_DATA &&
28
-       input->buffer_id < port->n_buffers) {
29
-       struct buffer *b = &port->buffersinput->buffer_id;
30
+   if (io->status == SPA_STATUS_HAVE_DATA &&
31
+       io->buffer_id < port->n_buffers) {
32
+       struct buffer *b = &port->buffersio->buffer_id;
33
 
34
        if (!SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) {
35
            spa_log_warn(this->log, "%p: buffer %u in use",
36
-                   this, input->buffer_id);
37
-           input->status = -EINVAL;
38
+                   this, io->buffer_id);
39
+           io->status = -EINVAL;
40
            return -EINVAL;
41
        }
42
-       spa_log_trace_fp(this->log, "%p: queue buffer %u", this, input->buffer_id);
43
+       spa_log_trace_fp(this->log, "%p: queue buffer %u", this, io->buffer_id);
44
        spa_list_append(&port->ready, &b->link);
45
        SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT);
46
-       input->buffer_id = SPA_ID_INVALID;
47
+       io->buffer_id = SPA_ID_INVALID;
48
 
49
        spa_avb_write(this);
50
 
51
-       input->status = SPA_STATUS_OK;
52
+       io->status = SPA_STATUS_OK;
53
    }
54
    return SPA_STATUS_HAVE_DATA;
55
 }
56
pipewire-0.3.56.tar.gz/spa/plugins/avb/avb-pcm-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/avb/avb-pcm-source.c Changed
13
 
1
@@ -705,9 +705,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = GET_PORT(this, SPA_DIRECTION_OUTPUT, 0);
5
-
6
-   io = port->io;
7
-   spa_return_val_if_fail(io != NULL, -EIO);
8
+   if ((io = port->io) == NULL)
9
+       return -EIO;
10
 
11
    spa_log_trace_fp(this->log, "%p: process %d %d/%d %d", this, io->status,
12
            io->buffer_id, port->n_buffers, this->following);
13
pipewire-0.3.56.tar.gz/spa/plugins/avb/avbtp/packets.h -> pipewire-0.3.57.tar.gz/spa/plugins/avb/avbtp/packets.h Changed
10
 
1
@@ -116,7 +116,7 @@
2
    unsigned gv:1;
3
    unsigned tv:1;
4
 
5
-   uint8_t seq_number;
6
+   uint8_t seq_num;
7
 
8
    unsigned _r2:7;
9
    unsigned tu:1;
10
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/README-OPUS-A2DP.md Added
201
 
1
@@ -0,0 +1,321 @@
2
+---
3
+title: OPUS-A2DP-0.5 specification
4
+author: Pauli Virtanen <pav@iki.fi>
5
+date: Jun 4, 2022
6
+---
7
+
8
+# OPUS-A2DP-0.5 specification
9
+
10
+DRAFT
11
+
12
+In this file, we specify how to use Opus as an A2DP vendor codec. We
13
+will call this "OPUS-A2DP-0.5". There is no previous public
14
+specification for using Opus as an A2DP vendor codec (to my
15
+knowledge), which is why we need this one.
16
+
17
+_TOC_
18
+
19
+# A2DP Codec Capabilities
20
+
21
+The A2DP capability structure is as follows.
22
+
23
+Integer fields and multi-byte bitfields are laid out in **little
24
+endian** order.  All integer fields are unsigned.
25
+
26
+Each entry may have different meaning when present as a capability.
27
+Below, we indicate this by abbreviations CAP/SNK for sink capability,
28
+CAP/SRC for source capability, CAP for capability as either, and SEL
29
+for the selected value by SRC.
30
+
31
+Bits in fields marked RFA (Reserved For Additions) shall be set to
32
+zero.
33
+
34
+The capability and configuration structure is as follows:
35
+
36
+| Octet | Bits | Meaning                                       |
37
+|-------|------|-----------------------------------------------|
38
+| 0-5   | 0-7  | Vendor ID Part                                |
39
+| 6-7   | 0-7  | Channel Configuration                         |
40
+| 8-11  | 0-7  | Audio Location Configuration                  |
41
+| 12-14 | 0-7  | Limits Configuration                          |
42
+| 15-16 | 0-7  | Return Direction Channel Configuration        |
43
+| 17-20 | 0-7  | Return Direction Audio Location Configuration |
44
+| 21-23 | 0-7  | Return Direction Limits Configuration         |
45
+
46
+See `a2dp-codec-caps.h` for definition as C structs.
47
+
48
+## Vendor ID Part
49
+
50
+The fixed value
51
+
52
+| Octet | Bits | Meaning                       |
53
+|-------|------|-------------------------------|
54
+| 0-3   | 0-7  | A2DP Vendor ID (0x05F1)       |
55
+| 4-5   | 0-7  | A2DP Vendor Codec ID (0x1005) |
56
+
57
+The Vendor ID is that of the Linux Foundation, and we are using it
58
+here unofficially.
59
+
60
+## Channel Configuration
61
+
62
+The channel configuration consists of the channel count and a bitfield
63
+indicating which of them are encoded in coupled streams.
64
+
65
+| Octet | Bits | Meaning                                                    |
66
+|-------|------|------------------------------------------------------------|
67
+| 6     | 0-7  | Channel Count. CAP: maximum number supported. SEL: actual. |
68
+| 7     | 0-7  | Coupled Stream Count. CAP: 0. SEL: actual.                 |
69
+
70
+The Channel Count indicates the number of logical channels encoded in
71
+the data stream.
72
+
73
+The Coupled Stream Count indicates the number of streams that encode a
74
+coupled (left & right) channel pair.  The count shall satisfy
75
+`(Channel Count) >= 2*(Coupled Stream Count)`.
76
+The Stream Count is `(Channel Count) - (Coupled Stream Count)`.
77
+
78
+Streams and Coupled Streams have the same meaning as in Sec. 5.1.1 of
79
+Opus Multistream RFC7845.
80
+
81
+The logical Channels are identified by a Channel Index *j* such that `0 <= j
82
+< (Channel Count)`. The channels `0 <= j < 2*(Coupled Stream Count)`
83
+are encoded in the *k*-th stream of the payload, where `k = floor(j/2)` and
84
+`j mod 2` determines which of the two channels of the stream the logical
85
+channel is. The channels `2*(Coupled Stream Count) <= j < (Channel Count)`
86
+are encoded in the *k*-th stream of the payload, where `k = j - (Coupled Stream Count)`.
87
+The prescription here is identical to RFC7845 with channel mapping
88
+`mappingj = j`.
89
+
90
+The semantic meaning for each channel is determined by their Audio
91
+Location.
92
+
93
+## Audio Location Configuration
94
+
95
+The channel audio location specification is similar to the location
96
+bitfield of the `Audio_Channel_Allocation` LTV structure in Bluetooth
97
+SIG Assigned Numbers, Generic Audio used in the LE Audio.
98
+
99
+| Octet | Bits | Meaning                                              |
100
+|-------|------|------------------------------------------------------|
101
+| 8-11  | 0-7  | Audio Location bitfield. CAP: available. SEL: actual |
102
+
103
+The values specified in CAP are informative, and SEL may contain bits
104
+that were not set in CAP. SNK shall handle unsupported audio
105
+locations. It may do this for example by ignoring unsupported channels
106
+or via suitable up/downmixing.  Hence, SRC may transmit channels with
107
+audio locations that are not marked supported by SNK. The maximum
108
+Channel Count however shall not be exceeded.
109
+
110
+The audio location bitfield values defined in Assigned Numbers,
111
+Generic Audio are:
112
+
113
+| Channel Order | Bitmask    | Audio Location          |
114
+|---------------|------------|-------------------------|
115
+| 0             | 0x00000001 | Front Left              |
116
+| 1             | 0x00000002 | Front Right             |
117
+| 2             | 0x00000400 | Side Left               |
118
+| 3             | 0x00000800 | Side Right              |
119
+| 4             | 0x00000010 | Back Left               |
120
+| 5             | 0x00000020 | Back Right              |
121
+| 6             | 0x00000040 | Front Left of Center    |
122
+| 7             | 0x00000080 | Front Right of Center   |
123
+| 8             | 0x00001000 | Top Front Left          |
124
+| 9             | 0x00002000 | Top Front Right         |
125
+| 10            | 0x00040000 | Top Side Left           |
126
+| 11            | 0x00080000 | Top Side Right          |
127
+| 12            | 0x00010000 | Top Back Left           |
128
+| 13            | 0x00020000 | Top Back Right          |
129
+| 14            | 0x00400000 | Bottom Front Left       |
130
+| 15            | 0x00800000 | Bottom Front Right      |
131
+| 16            | 0x01000000 | Front Left Wide         |
132
+| 17            | 0x02000000 | Front Right Wide        |
133
+| 18            | 0x04000000 | Left Surround           |
134
+| 19            | 0x08000000 | Right Surround          |
135
+| 20            | 0x00000004 | Front Center            |
136
+| 21            | 0x00000100 | Back Center             |
137
+| 22            | 0x00004000 | Top Front Center        |
138
+| 23            | 0x00008000 | Top Center              |
139
+| 24            | 0x00100000 | Top Back Center         |
140
+| 25            | 0x00200000 | Bottom Front Center     |
141
+| 26            | 0x00000008 | Low Frequency Effects 1 |
142
+| 27            | 0x00000200 | Low Frequency Effects 2 |
143
+| 28            | 0x10000000 | RFA                     |
144
+| 29            | 0x20000000 | RFA                     |
145
+| 30            | 0x40000000 | RFA                     |
146
+| 31            | 0x80000000 | RFA                     |
147
+
148
+In addition, we define a specific Channel Order for each.  The bits
149
+set in the bitfield define audio locations for the streams present in the
150
+payload. The set bit with the smallest Channel Order value defines the
151
+audio location for the Channel Index *j=0*, the bit with the next
152
+lowest Channel Order value defines the audio location for the Channel
153
+Index *j=1*, and so forth.
154
+
155
+When the Channel Count is larger than the number of bits set in the
156
+Audio Location bitfield, the audio locations of the remaining channels
157
+are unspecified. Implementations may handle them as appropriate for
158
+their use case, considering them as AUX0-AUXN, or in the case of
159
+Channel Count = 1, as the single mono audio channel.
160
+
161
+When the Channel Count is smaller than the number of bits set in the
162
+Audio Location bitfield, the audio locations for the channels are
163
+assigned as above, and remaining excess bits shall be ignored.
164
+
165
+The channel ordering defined here is compatible with the internal
166
+stream ordering in the reference Opus Multistream surround encoder
167
+Mapping Family 0 and 1 output. This allows making use of its surround
168
+masking and LFE handling capabilities.  The stream ordering of the
169
+reference Opus surround encoder, although being unchanged since its
170
+addition in 2013, is an internal detail of the
171
+encoder. Implementations using the surround encoder shall check that
172
+the mapping table used by the encoder corresponds to the above channel
173
+ordering.
174
+
175
+For reference, we list the Audio Location bitfield values
176
+corresponding to the different channel counts in Opus Mapping Family 0
177
+and 1 surround encoder output, and the expected mapping table:
178
+
179
+| Mapping Family | Channel Count | Audio Location Value | Stream Ordering                 | Mapping Table            |
180
+|----------------|---------------|----------------------|---------------------------------|--------------------------|
181
+| 0              | 1             | 0x00000000           | mono                            | {0}                      |
182
+| 0              | 2             | 0x00000003           | FL, FR                          | {0, 1}                   |
183
+| 1              | 1             | 0x00000000           | mono                            | {0}                      |
184
+| 1              | 2             | 0x00000003           | FL, FR                          | {0, 1}                   |
185
+| 1              | 3             | 0x00000007           | FL, FR, FC                      | {0, 2, 1}                |
186
+| 1              | 4             | 0x00000033           | FL, FR, BL, BR                  | {0, 1, 2, 3}             |
187
+| 1              | 5             | 0x00000037           | FL, FR, BL, BR, FC              | {0, 4, 1, 2, 3}          |
188
+| 1              | 6             | 0x0000003f           | FL, FR, BL, BR, FC, LFE         | {0, 4, 1, 2, 3, 5}       |
189
+| 1              | 7             | 0x00000d0f           | FL, FR, SL, SR, FC, BC, LFE     | {0, 4, 1, 2, 3, 5, 6}    |
190
+| 1              | 8             | 0x00000c3f           | FL, FR, SL, SR, BL, BR, FC, LFE | {0, 6, 1, 2, 3, 4, 5, 7} |
191
+
192
+The Mapping Table in the table indicates the mapping table selected by
193
+`opus_multistream_surround_encoder_create` (Opus 1.3.1). If the
194
+encoder outputs a different mapping table in a future Opus encoder
195
+release, the channel ordering will be incorrect, and the surround
196
+encoder can not be used. We expect that the probability of the Opus
197
+encoder authors making such changes is negligible.
198
+
199
+## Limits Configuration
200
+
201
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c Changed
175
 
1
@@ -31,10 +31,16 @@
2
 #include <spa/utils/dict.h>
3
 
4
 #include <fdk-aac/aacenc_lib.h>
5
+#include <fdk-aac/aacdecoder_lib.h>
6
 
7
 #include "rtp.h"
8
 #include "a2dp-codecs.h"
9
 
10
+static struct spa_log *log;
11
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.codecs.aac");
12
+#undef SPA_LOG_TOPIC_DEFAULT
13
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
14
+
15
 #define DEFAULT_AAC_BITRATE    320000
16
 #define MIN_AAC_BITRATE        64000
17
 
18
@@ -44,6 +50,7 @@
19
 
20
 struct impl {
21
    HANDLE_AACENCODER aacenc;
22
+   HANDLE_AACDECODER aacdec;
23
 
24
    struct rtp_header *header;
25
 
26
@@ -170,7 +177,7 @@
27
    return sizeof(conf);
28
 }
29
 
30
-static int codec_enum_config(const struct a2dp_codec *codec,
31
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
32
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
33
        struct spa_pod_builder *b, struct spa_pod **param)
34
 {
35
@@ -289,7 +296,7 @@
36
    return 0;
37
 }
38
 
39
-static void *codec_init_props(const struct a2dp_codec *codec, const struct spa_dict *settings)
40
+static void *codec_init_props(const struct a2dp_codec *codec, uint32_t flags, const struct spa_dict *settings)
41
 {
42
    struct props *p = calloc(1, sizeof(struct props));
43
    const char *str;
44
@@ -412,11 +419,39 @@
45
 
46
    this->codesize = enc_info.frameLength * this->channels * this->samplesize;
47
 
48
+   this->aacdec = aacDecoder_Open(TT_MP4_LATM_MCP1, 1);
49
+   if (!this->aacdec) {
50
+       res = -EINVAL;
51
+       goto error;
52
+   }
53
+
54
+#ifdef AACDECODER_LIB_VL0
55
+   res = aacDecoder_SetParam(this->aacdec, AAC_PCM_MIN_OUTPUT_CHANNELS, this->channels);
56
+   if (res != AAC_DEC_OK) {
57
+       spa_log_debug(log, "Couldn't set min output channels: 0x%04X", res);
58
+       goto error;
59
+   }
60
+
61
+   res = aacDecoder_SetParam(this->aacdec, AAC_PCM_MAX_OUTPUT_CHANNELS, this->channels);
62
+   if (res != AAC_DEC_OK) {
63
+       spa_log_debug(log, "Couldn't set max output channels: 0x%04X", res);
64
+       goto error;
65
+   }
66
+#else
67
+   res = aacDecoder_SetParam(this->aacdec, AAC_PCM_OUTPUT_CHANNELS, this->channels);
68
+   if (res != AAC_DEC_OK) {
69
+       spa_log_debug(log, "Couldn't set output channels: 0x%04X", res);
70
+       goto error;
71
+   }
72
+#endif
73
+
74
    return this;
75
 
76
 error:
77
    if (this && this->aacenc)
78
        aacEncClose(&this->aacenc);
79
+   if (this && this->aacdec)
80
+       aacDecoder_Close(this->aacdec);
81
    free(this);
82
    errno = -res;
83
    return NULL;
84
@@ -427,6 +462,8 @@
85
    struct impl *this = data;
86
    if (this->aacenc)
87
        aacEncClose(&this->aacenc);
88
+   if (this->aacdec)
89
+       aacDecoder_Close(this->aacdec);
90
    free(this);
91
 }
92
 
93
@@ -502,6 +539,55 @@
94
    return out_args.numInSamples * this->samplesize;
95
 }
96
 
97
+static int codec_start_decode (void *data,
98
+       const void *src, size_t src_size, uint16_t *seqnum, uint32_t *timestamp)
99
+{
100
+   const struct rtp_header *header = src;
101
+   size_t header_size = sizeof(struct rtp_header);
102
+
103
+   spa_return_val_if_fail (src_size > header_size, -EINVAL);
104
+
105
+   if (seqnum)
106
+       *seqnum = ntohs(header->sequence_number);
107
+   if (timestamp)
108
+       *timestamp = ntohl(header->timestamp);
109
+
110
+   return header_size;
111
+}
112
+
113
+static int codec_decode(void *data,
114
+       const void *src, size_t src_size,
115
+       void *dst, size_t dst_size,
116
+       size_t *dst_out)
117
+{
118
+   struct impl *this = data;
119
+   uint data_size = (uint)src_size;
120
+   uint bytes_valid = data_size;
121
+   CStreamInfo *aacinf;
122
+   int res;
123
+
124
+   res = aacDecoder_Fill(this->aacdec, (UCHAR **)&src, &data_size, &bytes_valid);
125
+   if (res != AAC_DEC_OK) {
126
+       spa_log_debug(log, "AAC buffer fill error: 0x%04X", res);
127
+       return -EINVAL;
128
+   }
129
+
130
+   res = aacDecoder_DecodeFrame(this->aacdec, dst, dst_size, 0);
131
+   if (res != AAC_DEC_OK) {
132
+       spa_log_debug(log, "AAC decode frame error: 0x%04X", res);
133
+       return -EINVAL;
134
+   }
135
+
136
+   aacinf = aacDecoder_GetStreamInfo(this->aacdec);
137
+   if (!aacinf) {
138
+       spa_log_debug(log, "AAC get stream info failed");
139
+       return -EINVAL;
140
+   }
141
+   *dst_out = aacinf->frameSize * aacinf->numChannels * this->samplesize;
142
+
143
+   return src_size - bytes_valid;
144
+}
145
+
146
 static int codec_abr_process (void *data, size_t unsent)
147
 {
148
    return -ENOTSUP;
149
@@ -538,6 +624,12 @@
150
    return codec_change_bitrate(this, (this->cur_bitrate * 4) / 3);
151
 }
152
 
153
+static void codec_set_log(struct spa_log *global_log)
154
+{
155
+   log = global_log;
156
+   spa_log_topic_init(log, &log_topic);
157
+}
158
+
159
 const struct a2dp_codec a2dp_codec_aac = {
160
    .id = SPA_BLUETOOTH_AUDIO_CODEC_AAC,
161
    .codec_id = A2DP_CODEC_MPEG24,
162
@@ -554,9 +646,12 @@
163
    .get_block_size = codec_get_block_size,
164
    .start_encode = codec_start_encode,
165
    .encode = codec_encode,
166
+   .start_decode = codec_start_decode,
167
+   .decode = codec_decode,
168
    .abr_process = codec_abr_process,
169
    .reduce_bitpool = codec_reduce_bitpool,
170
    .increase_bitpool = codec_increase_bitpool,
171
+   .set_log = codec_set_log,
172
 };
173
 
174
 A2DP_CODEC_EXPORT_DEF(
175
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-aptx.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-aptx.c Changed
47
 
1
@@ -218,7 +218,7 @@
2
    return actual_conf_size;
3
 }
4
 
5
-static int codec_enum_config(const struct a2dp_codec *codec,
6
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
7
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
8
        struct spa_pod_builder *b, struct spa_pod **param)
9
 {
10
@@ -458,7 +458,7 @@
11
  * When connected as SRC to SNK, aptX-LL sink may send back mSBC data.
12
  */
13
 
14
-static int msbc_enum_config(const struct a2dp_codec *codec,
15
+static int msbc_enum_config(const struct a2dp_codec *codec, uint32_t flags,
16
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
17
        struct spa_pod_builder *b, struct spa_pod **param)
18
 {
19
@@ -710,6 +710,11 @@
20
    .increase_bitpool = msbc_increase_bitpool,
21
 };
22
 
23
+static const struct spa_dict_item duplex_info_items = {
24
+   { "duplex.boost", "true" },
25
+};
26
+static const struct spa_dict duplex_info = SPA_DICT_INIT_ARRAY(duplex_info_items);
27
+
28
 const struct a2dp_codec a2dp_codec_aptx_ll_duplex_0 = {
29
    APTX_LL_COMMON_DEFS,
30
    .id = SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX,
31
@@ -718,6 +723,7 @@
32
    .name = "aptx_ll_duplex",
33
    .endpoint_name = "aptx_ll_duplex_0",
34
    .duplex_codec = &aptx_ll_msbc,
35
+   .info = &duplex_info,
36
 };
37
 
38
 const struct a2dp_codec a2dp_codec_aptx_ll_duplex_1 = {
39
@@ -728,6 +734,7 @@
40
    .name = "aptx_ll_duplex",
41
    .endpoint_name = "aptx_ll_duplex_1",
42
    .duplex_codec = &aptx_ll_msbc,
43
+   .info = &duplex_info,
44
 };
45
 
46
 A2DP_CODEC_EXPORT_DEF(
47
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-caps.h -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-caps.h Changed
79
 
1
@@ -233,6 +233,54 @@
2
 #define LC3PLUS_HR_SAMPLING_FREQ_48000 (1 << 8)
3
 #define LC3PLUS_HR_SAMPLING_FREQ_96000 (1 << 7)
4
 
5
+#define OPUS_05_VENDOR_ID      0x000005f1
6
+#define OPUS_05_CODEC_ID       0x1005
7
+
8
+#define OPUS_05_MAPPING_FAMILY_0   (1 << 0)
9
+#define OPUS_05_MAPPING_FAMILY_1   (1 << 1)
10
+#define OPUS_05_MAPPING_FAMILY_255 (1 << 2)
11
+
12
+#define OPUS_05_FRAME_DURATION_25  (1 << 0)
13
+#define OPUS_05_FRAME_DURATION_50  (1 << 1)
14
+#define OPUS_05_FRAME_DURATION_100 (1 << 2)
15
+#define OPUS_05_FRAME_DURATION_200 (1 << 3)
16
+#define OPUS_05_FRAME_DURATION_400 (1 << 4)
17
+
18
+#define OPUS_05_GET_UINT16(a, field)           \
19
+   (((a).field ## 2 << 8) | (a).field ## 1)
20
+#define OPUS_05_INIT_UINT16(field, v)          \
21
+   .field ## 1 = ((v) & 0xff),         \
22
+   .field ## 2 = (((v) >> 8) & 0xff),
23
+#define OPUS_05_SET_UINT16(a, field, v)            \
24
+   do {                        \
25
+       (a).field ## 1 = ((v) & 0xff);      \
26
+       (a).field ## 2 = (((v) >> 8) & 0xff);   \
27
+   } while (0)
28
+#define OPUS_05_GET_UINT32(a, field)               \
29
+   (((a).field ## 4 << 24) | ((a).field ## 3 << 16) |  \
30
+   ((a).field ## 2 << 8) | (a).field ## 1)
31
+#define OPUS_05_INIT_UINT32(field, v)          \
32
+   .field ## 1 = ((v) & 0xff),         \
33
+   .field ## 2 = (((v) >> 8) & 0xff),      \
34
+   .field ## 3 = (((v) >> 16) & 0xff),     \
35
+   .field ## 4 = (((v) >> 24) & 0xff),
36
+#define OPUS_05_SET_UINT32(a, field, v)            \
37
+   do {                        \
38
+       (a).field ## 1 = ((v) & 0xff);      \
39
+       (a).field ## 2 = (((v) >> 8) & 0xff);   \
40
+       (a).field ## 3 = (((v) >> 16) & 0xff);  \
41
+       (a).field ## 4 = (((v) >> 24) & 0xff);  \
42
+   } while (0)
43
+
44
+#define OPUS_05_GET_LOCATION(a) OPUS_05_GET_UINT32(a, location)
45
+#define OPUS_05_INIT_LOCATION(v) OPUS_05_INIT_UINT32(location, v)
46
+#define OPUS_05_SET_LOCATION(a, v) OPUS_05_SET_UINT32(a, location, v)
47
+
48
+#define OPUS_05_GET_BITRATE(a) OPUS_05_GET_UINT16(a, bitrate)
49
+#define OPUS_05_INIT_BITRATE(v) OPUS_05_INIT_UINT16(bitrate, v)
50
+#define OPUS_05_SET_BITRATE(a, v) OPUS_05_SET_UINT16(a, bitrate, v)
51
+
52
+
53
 typedef struct {
54
    uint32_t vendor_id;
55
    uint16_t codec_id;
56
@@ -391,4 +439,22 @@
57
    uint8_t frequency2;
58
 } __attribute__ ((packed)) a2dp_lc3plus_hr_t;
59
 
60
+typedef struct {
61
+   uint8_t channels;
62
+   uint8_t coupled_streams;
63
+   uint8_t location1;
64
+   uint8_t location2;
65
+   uint8_t location3;
66
+   uint8_t location4;
67
+   uint8_t frame_duration;
68
+   uint8_t bitrate1;
69
+   uint8_t bitrate2;
70
+} __attribute__ ((packed)) a2dp_opus_05_direction_t;
71
+
72
+typedef struct {
73
+   a2dp_vendor_codec_t info;
74
+   a2dp_opus_05_direction_t main;
75
+   a2dp_opus_05_direction_t bidi;
76
+} __attribute__ ((packed)) a2dp_opus_05_t;
77
+
78
 #endif
79
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-faststream.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-faststream.c Changed
44
 
1
@@ -129,7 +129,7 @@
2
    return sizeof(conf);
3
 }
4
 
5
-static int codec_enum_config(const struct a2dp_codec *codec,
6
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
7
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
8
        struct spa_pod_builder *b, struct spa_pod **param)
9
 {
10
@@ -372,7 +372,7 @@
11
  * When connected as SRC to SNK, FastStream sink may send back SBC data.
12
  */
13
 
14
-static int duplex_enum_config(const struct a2dp_codec *codec,
15
+static int duplex_enum_config(const struct a2dp_codec *codec, uint32_t flags,
16
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
17
        struct spa_pod_builder *b, struct spa_pod **param)
18
 {
19
@@ -614,17 +614,23 @@
20
    .reduce_bitpool = codec_reduce_bitpool,     \
21
    .increase_bitpool = codec_increase_bitpool
22
 
23
-const struct a2dp_codec a2dp_codec_faststream = {
24
+static const struct a2dp_codec a2dp_codec_faststream = {
25
    FASTSTREAM_COMMON_DEFS,
26
    .id = SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM,
27
    .name = "faststream",
28
 };
29
 
30
+static const struct spa_dict_item duplex_info_items = {
31
+   { "duplex.boost", "true" },
32
+};
33
+static const struct spa_dict duplex_info = SPA_DICT_INIT_ARRAY(duplex_info_items);
34
+
35
 const struct a2dp_codec a2dp_codec_faststream_duplex = {
36
    FASTSTREAM_COMMON_DEFS,
37
    .id = SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX,
38
    .name = "faststream_duplex",
39
    .duplex_codec = &duplex_codec,
40
+   .info = &duplex_info,
41
 };
42
 
43
 A2DP_CODEC_EXPORT_DEF(
44
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-lc3plus.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-lc3plus.c Changed
30
 
1
@@ -150,8 +150,8 @@
2
    return sizeof(conf);
3
 }
4
 
5
-static int codec_caps_preference_cmp(const struct a2dp_codec *codec, const void *caps1, size_t caps1_size,
6
-       const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info)
7
+static int codec_caps_preference_cmp(const struct a2dp_codec *codec, uint32_t flags, const void *caps1, size_t caps1_size,
8
+       const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info, const struct spa_dict *global_settings)
9
 {
10
    a2dp_lc3plus_hr_t conf1, conf2;
11
    a2dp_lc3plus_hr_t *conf;
12
@@ -160,7 +160,7 @@
13
 
14
    /* Order selected configurations by preference */
15
    res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1);
16
-   res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2);
17
+   res2 = codec->select_config(codec, 0, caps2, caps2_size, info, NULL, (uint8_t *)&conf2);
18
 
19
 #define PREFER_EXPR(expr)          \
20
        do {                \
21
@@ -190,7 +190,7 @@
22
 #undef PREFER_BOOL
23
 }
24
 
25
-static int codec_enum_config(const struct a2dp_codec *codec,
26
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
27
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
28
        struct spa_pod_builder *b, struct spa_pod **param)
29
 {
30
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-ldac.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-ldac.c Changed
32
 
1
@@ -150,7 +150,7 @@
2
         return sizeof(conf);
3
 }
4
 
5
-static int codec_enum_config(const struct a2dp_codec *codec,
6
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
7
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
8
        struct spa_pod_builder *b, struct spa_pod **param)
9
 {
10
@@ -284,7 +284,7 @@
11
        return LDACBT_EQMID_AUTO;
12
 }
13
 
14
-static void *codec_init_props(const struct a2dp_codec *codec, const struct spa_dict *settings)
15
+static void *codec_init_props(const struct a2dp_codec *codec, uint32_t flags, const struct spa_dict *settings)
16
 {
17
    struct props *p = calloc(1, sizeof(struct props));
18
    const char *str;
19
@@ -469,10 +469,10 @@
20
 error_errno:
21
    res = -errno;
22
 error:
23
-   if (this->ldac)
24
+   if (this && this->ldac)
25
        ldacBT_free_handle(this->ldac);
26
 #ifdef ENABLE_LDAC_ABR
27
-   if (this->ldac_abr)
28
+   if (this && this->ldac_abr)
29
        ldac_ABR_free_handle(this->ldac_abr);
30
 #endif
31
    free(this);
32
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c Added
201
 
1
@@ -0,0 +1,1437 @@
2
+/* Spa A2DP Opus Codec
3
+ *
4
+ * Copyright © 2020 Wim Taymans
5
+ * Copyright © 2022 Pauli Virtanen
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice (including the next
15
+ * paragraph) shall be included in all copies or substantial portions of the
16
+ * Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ */
26
+
27
+#include <unistd.h>
28
+#include <string.h>
29
+#include <stddef.h>
30
+#include <errno.h>
31
+#include <arpa/inet.h>
32
+#if __BYTE_ORDER != __LITTLE_ENDIAN
33
+#include <byteswap.h>
34
+#endif
35
+
36
+#include <spa/debug/types.h>
37
+#include <spa/param/audio/type-info.h>
38
+#include <spa/param/audio/raw.h>
39
+#include <spa/utils/string.h>
40
+#include <spa/utils/dict.h>
41
+#include <spa/param/audio/format.h>
42
+#include <spa/param/audio/format-utils.h>
43
+
44
+#include <opus.h>
45
+#include <opus_multistream.h>
46
+
47
+#include "rtp.h"
48
+#include "a2dp-codecs.h"
49
+
50
+static struct spa_log *log;
51
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.codecs.opus");
52
+#undef SPA_LOG_TOPIC_DEFAULT
53
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
54
+
55
+#define BUFSIZE_FROM_BITRATE(frame_dms,bitrate)    ((bitrate)/8 * (frame_dms) / 10000 * 5/4)  /* estimate */
56
+
57
+/*
58
+ * Opus CVBR target bitrate. When connecting, it is set to the INITIAL
59
+ * value, and after that adjusted according to link quality between the MIN and
60
+ * MAX values. The bitrate adjusts up to either MAX or the value at
61
+ * which the socket buffer starts filling up, whichever is lower.
62
+ *
63
+ * With perfect connection quality, the target bitrate converges to the MAX
64
+ * value. Under realistic conditions, the upper limit may often be as low as
65
+ * 300-500kbit/s, so the INITIAL values are not higher than this.
66
+ *
67
+ * The MAX is here set to 2-2.5x and INITIAL to 1.5x the upper Opus recommended
68
+ * values 1, to be safer quality-wise for CVBR, and MIN to the lower
69
+ * recommended value.
70
+ *
71
+ * 1 https://wiki.xiph.org/Opus_Recommended_Settings
72
+ */
73
+#define BITRATE_INITIAL            192000
74
+#define BITRATE_MAX            320000
75
+#define BITRATE_MIN            96000
76
+
77
+#define BITRATE_INITIAL_51     384000
78
+#define BITRATE_MAX_51         600000
79
+#define BITRATE_MIN_51         128000
80
+
81
+#define BITRATE_INITIAL_71     450000
82
+#define BITRATE_MAX_71         900000
83
+#define BITRATE_MIN_71         256000
84
+
85
+#define BITRATE_DUPLEX_BIDI        160000
86
+
87
+#define OPUS_05_MAX_BYTES  (15 * 1024)
88
+
89
+struct props {
90
+   uint32_t channels;
91
+   uint32_t coupled_streams;
92
+   uint32_t location;
93
+   uint32_t max_bitrate;
94
+   uint8_t frame_duration;
95
+   int application;
96
+
97
+   uint32_t bidi_channels;
98
+   uint32_t bidi_coupled_streams;
99
+   uint32_t bidi_location;
100
+   uint32_t bidi_max_bitrate;
101
+   uint32_t bidi_frame_duration;
102
+   int bidi_application;
103
+};
104
+
105
+struct dec_data {
106
+   int fragment_size;
107
+   int fragment_count;
108
+   uint8_t fragmentOPUS_05_MAX_BYTES;
109
+};
110
+
111
+struct abr {
112
+   uint64_t now;
113
+   uint64_t last_update;
114
+
115
+   uint32_t buffer_level;
116
+   uint32_t packet_size;
117
+   uint32_t total_size;
118
+   bool bad;
119
+
120
+   uint64_t last_change;
121
+   uint64_t retry_interval;
122
+
123
+   bool prev_bad;
124
+};
125
+
126
+struct enc_data {
127
+   struct rtp_header *header;
128
+   struct rtp_payload *payload;
129
+
130
+   struct abr abr;
131
+
132
+   int samples;
133
+   int codesize;
134
+
135
+   int packet_size;
136
+   int fragment_size;
137
+   int fragment_count;
138
+   void *fragment;
139
+
140
+   int bitrate_min;
141
+   int bitrate_max;
142
+
143
+   int bitrate;
144
+   int next_bitrate;
145
+
146
+   int frame_dms;
147
+   int application;
148
+};
149
+
150
+struct impl {
151
+   OpusMSEncoder *enc;
152
+   OpusMSDecoder *dec;
153
+
154
+   int mtu;
155
+   int samplerate;
156
+   int application;
157
+
158
+   uint8_t channels;
159
+   uint8_t streams;
160
+   uint8_t coupled_streams;
161
+
162
+   bool is_bidi;
163
+
164
+   struct dec_data d;
165
+   struct enc_data e;
166
+};
167
+
168
+struct audio_location {
169
+   uint32_t mask;
170
+   enum spa_audio_channel position;
171
+};
172
+
173
+struct surround_encoder_mapping {
174
+   uint8_t channels;
175
+   uint8_t coupled_streams;
176
+   uint32_t location;
177
+   uint8_t mapping8;       /**< permutation streams -> vorbis order */
178
+   uint8_t inv_mapping8;       /**< permutation vorbis order -> streams */
179
+};
180
+
181
+/* Bluetooth SIG, Assigned Numbers, Generic Audio, Audio Location Definitions */
182
+#define BT_AUDIO_LOCATION_FL   0x00000001  /* Front Left */
183
+#define BT_AUDIO_LOCATION_FR   0x00000002  /* Front Right */
184
+#define BT_AUDIO_LOCATION_FC   0x00000004  /* Front Center */
185
+#define BT_AUDIO_LOCATION_LFE  0x00000008  /* Low Frequency Effects 1 */
186
+#define BT_AUDIO_LOCATION_RL   0x00000010  /* Back Left */
187
+#define BT_AUDIO_LOCATION_RR   0x00000020  /* Back Right */
188
+#define BT_AUDIO_LOCATION_FLC  0x00000040  /* Front Left of Center */
189
+#define BT_AUDIO_LOCATION_FRC  0x00000080  /* Front Right of Center */
190
+#define BT_AUDIO_LOCATION_RC   0x00000100  /* Back Center */
191
+#define BT_AUDIO_LOCATION_LFE2 0x00000200  /* Low Frequency Effects 2 */
192
+#define BT_AUDIO_LOCATION_SL   0x00000400  /* Side Left */
193
+#define BT_AUDIO_LOCATION_SR   0x00000800  /* Side Right */
194
+#define BT_AUDIO_LOCATION_TFL  0x00001000  /* Top Front Left */
195
+#define BT_AUDIO_LOCATION_TFR  0x00002000  /* Top Front Right */
196
+#define BT_AUDIO_LOCATION_TFC  0x00004000  /* Top Front Center */
197
+#define BT_AUDIO_LOCATION_TC   0x00008000  /* Top Center */
198
+#define BT_AUDIO_LOCATION_TRL  0x00010000  /* Top Back Left */
199
+#define BT_AUDIO_LOCATION_TRR  0x00020000  /* Top Back Right */
200
+#define BT_AUDIO_LOCATION_TSL  0x00040000  /* Top Side Left */
201
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codec-sbc.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codec-sbc.c Changed
21
 
1
@@ -229,8 +229,8 @@
2
    return sizeof(conf);
3
 }
4
 
5
-static int codec_caps_preference_cmp(const struct a2dp_codec *codec, const void *caps1, size_t caps1_size,
6
-       const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info)
7
+static int codec_caps_preference_cmp(const struct a2dp_codec *codec, uint32_t flags, const void *caps1, size_t caps1_size,
8
+       const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info, const struct spa_dict *global_settings)
9
 {
10
    a2dp_sbc_t conf1, conf2;
11
    a2dp_sbc_t *conf;
12
@@ -356,7 +356,7 @@
13
    return this->sbc.bitpool;
14
 }
15
 
16
-static int codec_enum_config(const struct a2dp_codec *codec,
17
+static int codec_enum_config(const struct a2dp_codec *codec, uint32_t flags,
18
        const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
19
        struct spa_pod_builder *b, struct spa_pod **param)
20
 {
21
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codecs.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codecs.c Changed
20
 
1
@@ -62,7 +62,8 @@
2
 
3
 bool a2dp_codec_check_caps(const struct a2dp_codec *codec, unsigned int codec_id,
4
               const void *caps, size_t caps_size,
5
-              const struct a2dp_codec_audio_info *info)
6
+              const struct a2dp_codec_audio_info *info,
7
+              const struct spa_dict *global_settings)
8
 {
9
    uint8_t configA2DP_MAX_CAPS_SIZE;
10
    int res;
11
@@ -73,7 +74,7 @@
12
    if (caps == NULL)
13
        return false;
14
 
15
-   res = codec->select_config(codec, 0, caps, caps_size, info, NULL, config);
16
+   res = codec->select_config(codec, 0, caps, caps_size, info, global_settings, config);
17
    if (res < 0)
18
        return false;
19
 
20
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-codecs.h -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-codecs.h Changed
70
 
1
@@ -33,6 +33,7 @@
2
 #include <spa/support/plugin.h>
3
 #include <spa/pod/pod.h>
4
 #include <spa/pod/builder.h>
5
+#include <spa/support/log.h>
6
 
7
 #include "a2dp-codec-caps.h"
8
 
9
@@ -43,7 +44,7 @@
10
 
11
 #define SPA_TYPE_INTERFACE_Bluez5CodecA2DP SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:A2DP:Private"
12
 
13
-#define SPA_VERSION_BLUEZ5_CODEC_A2DP      1
14
+#define SPA_VERSION_BLUEZ5_CODEC_A2DP      5
15
 
16
 struct spa_bluez5_codec_a2dp {
17
    struct spa_interface iface;
18
@@ -62,6 +63,7 @@
19
 extern const char *codec_plugin_factory_name;
20
 #endif
21
 
22
+#define A2DP_CODEC_FLAG_SINK       (1 << 0)
23
 
24
 #define A2DP_CODEC_DEFAULT_RATE        48000
25
 #define A2DP_CODEC_DEFAULT_CHANNELS    2
26
@@ -96,8 +98,8 @@
27
    int (*select_config) (const struct a2dp_codec *codec, uint32_t flags,
28
            const void *caps, size_t caps_size,
29
            const struct a2dp_codec_audio_info *info,
30
-           const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE);
31
-   int (*enum_config) (const struct a2dp_codec *codec,
32
+           const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE);
33
+   int (*enum_config) (const struct a2dp_codec *codec, uint32_t flags,
34
            const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
35
            struct spa_pod_builder *builder, struct spa_pod **param);
36
    int (*validate_config) (const struct a2dp_codec *codec, uint32_t flags,
37
@@ -109,10 +111,11 @@
38
     * The caps handed in correspond to this codec_id, but are
39
     * otherwise not checked beforehand.
40
     */
41
-   int (*caps_preference_cmp) (const struct a2dp_codec *codec, const void *caps1, size_t caps1_size,
42
-           const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info);
43
+   int (*caps_preference_cmp) (const struct a2dp_codec *codec, uint32_t flags, const void *caps1, size_t caps1_size,
44
+           const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info,
45
+           const struct spa_dict *global_settings);
46
 
47
-   void *(*init_props) (const struct a2dp_codec *codec, const struct spa_dict *settings);
48
+   void *(*init_props) (const struct a2dp_codec *codec, uint32_t flags, const struct spa_dict *settings);
49
    void (*clear_props) (void *);
50
    int (*enum_props) (void *props, const struct spa_dict *settings, uint32_t id, uint32_t idx,
51
            struct spa_pod_builder *builder, struct spa_pod **param);
52
@@ -144,6 +147,8 @@
53
 
54
    int (*reduce_bitpool) (void *data);
55
    int (*increase_bitpool) (void *data);
56
+
57
+   void (*set_log) (struct spa_log *global_log);
58
 };
59
 
60
 struct a2dp_codec_config {
61
@@ -156,6 +161,7 @@
62
    uint32_t cap, int preferred_value);
63
 
64
 bool a2dp_codec_check_caps(const struct a2dp_codec *codec, unsigned int codec_id,
65
-   const void *caps, size_t caps_size, const struct a2dp_codec_audio_info *info);
66
+   const void *caps, size_t caps_size, const struct a2dp_codec_audio_info *info,
67
+   const struct spa_dict *global_settings);
68
 
69
 #endif
70
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-sink.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-sink.c Changed
70
 
1
@@ -137,6 +137,8 @@
2
    unsigned int started:1;
3
    unsigned int following:1;
4
 
5
+   unsigned int is_duplex:1;
6
+
7
    struct spa_source source;
8
    int timerfd;
9
    struct spa_source flush_source;
10
@@ -908,7 +910,8 @@
11
    for (i = 0; i < size; i++)
12
        spa_log_debug(this->log, "  %d: %02x", i, confi);
13
 
14
-   this->codec_data = this->codec->init(this->codec, 0,
15
+   this->codec_data = this->codec->init(this->codec,
16
+           this->is_duplex ? A2DP_CODEC_FLAG_SINK : 0,
17
            this->transport->configuration,
18
            this->transport->configuration_len,
19
            &port->current_format,
20
@@ -1195,6 +1198,7 @@
21
            return -EIO;
22
 
23
        if ((res = this->codec->enum_config(this->codec,
24
+                   this->is_duplex ? A2DP_CODEC_FLAG_SINK : 0,
25
                    this->transport->configuration,
26
                    this->transport->configuration_len,
27
                    id, result.index, &b, &param)) != 1)
28
@@ -1457,8 +1461,8 @@
29
    spa_return_val_if_fail(this != NULL, -EINVAL);
30
 
31
    port = &this->port;
32
-   io = port->io;
33
-   spa_return_val_if_fail(io != NULL, -EIO);
34
+   if ((io = port->io) == NULL)
35
+       return -EIO;
36
 
37
    if (this->position && this->position->clock.flags & SPA_IO_CLOCK_FLAG_FREEWHEEL) {
38
        io->status = SPA_STATUS_NEED_DATA;
39
@@ -1697,6 +1701,9 @@
40
 
41
    spa_list_init(&port->ready);
42
 
43
+   if (info && (str = spa_dict_lookup(info, "api.bluez5.a2dp-duplex")) != NULL)
44
+       this->is_duplex = spa_atob(str);
45
+
46
    if (info && (str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_TRANSPORT)))
47
        sscanf(str, "pointer:%p", &this->transport);
48
 
49
@@ -1708,9 +1715,20 @@
50
        spa_log_error(this->log, "a transport codec is needed");
51
        return -EINVAL;
52
    }
53
+
54
    this->codec = this->transport->a2dp_codec;
55
+
56
+   if (this->is_duplex) {
57
+       if (!this->codec->duplex_codec) {
58
+           spa_log_error(this->log, "transport codec doesn't support duplex");
59
+           return -EINVAL;
60
+       }
61
+       this->codec = this->codec->duplex_codec;
62
+   }
63
+
64
    if (this->codec->init_props != NULL)
65
        this->codec_props = this->codec->init_props(this->codec,
66
+                   this->is_duplex ? A2DP_CODEC_FLAG_SINK : 0,
67
                    this->transport->device->settings);
68
 
69
    reset_props(this, &this->props);
70
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/a2dp-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-source.c Changed
103
 
1
@@ -142,6 +142,7 @@
2
 
3
    unsigned int is_input:1;
4
    unsigned int is_duplex:1;
5
+   unsigned int use_duplex_source:1;
6
 
7
    int fd;
8
    struct spa_source source;
9
@@ -629,7 +630,8 @@
10
 
11
    this->transport_acquired = true;
12
 
13
-   this->codec_data = this->codec->init(this->codec, 0,
14
+   this->codec_data = this->codec->init(this->codec,
15
+           this->is_duplex ? 0 : A2DP_CODEC_FLAG_SINK,
16
            this->transport->configuration,
17
            this->transport->configuration_len,
18
            &port->current_format,
19
@@ -668,7 +670,7 @@
20
 
21
    this->source.data = this;
22
 
23
-   if (!this->is_duplex) {
24
+   if (!this->use_duplex_source) {
25
        this->source.fd = this->transport->fd;
26
        this->source.func = a2dp_on_ready_read;
27
        this->source.mask = SPA_IO_IN;
28
@@ -683,7 +685,8 @@
29
         * XXX: The reason for this should be found and fixed.
30
         * XXX: To work around this, for now we just do the stupid thing and poll
31
         * XXX: on a timer, chosen so that it's fast enough for the aptX-LL codec
32
-        * XXX: we currently support (which sends mSBC data).
33
+        * XXX: we currently support (which sends mSBC data), and also for Opus
34
+        * XXX: forward stream.
35
         */
36
        this->source.fd = this->duplex_timerfd;
37
        this->source.func = a2dp_on_duplex_timeout;
38
@@ -691,7 +694,7 @@
39
        this->source.rmask = 0;
40
        spa_loop_add_source(this->data_loop, &this->source);
41
 
42
-       this->duplex_timeout = SPA_NSEC_PER_MSEC * 75/10;
43
+       this->duplex_timeout = SPA_NSEC_PER_MSEC * 25/10;
44
        set_duplex_timeout(this, this->duplex_timeout);
45
    }
46
 
47
@@ -718,13 +721,13 @@
48
    if (this->started)
49
        return 0;
50
 
51
+   spa_return_val_if_fail(this->transport != NULL, -EIO);
52
+
53
    this->following = is_following(this);
54
 
55
    spa_log_debug(this->log, "%p: start state:%d following:%d",
56
            this, this->transport->state, this->following);
57
 
58
-   spa_return_val_if_fail(this->transport != NULL, -EIO);
59
-
60
    if (this->transport->state >= SPA_BT_TRANSPORT_STATE_PENDING ||
61
            this->is_duplex)
62
        res = transport_start(this);
63
@@ -965,6 +968,7 @@
64
            return -EIO;
65
 
66
        if ((res = this->codec->enum_config(this->codec,
67
+                   this->is_duplex ? 0 : A2DP_CODEC_FLAG_SINK,
68
                    this->transport->configuration,
69
                    this->transport->configuration_len,
70
                    id, result.index, &b, &param)) != 1)
71
@@ -1341,8 +1345,8 @@
72
    spa_return_val_if_fail(this != NULL, -EINVAL);
73
 
74
    port = &this->port;
75
-   io = port->io;
76
-   spa_return_val_if_fail(io != NULL, -EIO);
77
+   if ((io = port->io) == NULL)
78
+       return -EIO;
79
 
80
    spa_log_trace(this->log, "%p status:%d", this, io->status);
81
 
82
@@ -1575,9 +1579,11 @@
83
        this->codec = this->codec->duplex_codec;
84
        this->is_input = true;
85
    }
86
+   this->use_duplex_source = this->is_duplex || (this->codec->duplex_codec != NULL);
87
 
88
    if (this->codec->init_props != NULL)
89
        this->codec_props = this->codec->init_props(this->codec,
90
+                   this->is_duplex ? 0 : A2DP_CODEC_FLAG_SINK,
91
                    this->transport->device->settings);
92
 
93
    spa_bt_transport_add_listener(this->transport,
94
@@ -1586,7 +1592,7 @@
95
    this->timerfd = spa_system_timerfd_create(this->data_system,
96
            CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);
97
 
98
-   if (this->is_duplex) {
99
+   if (this->use_duplex_source) {
100
        this->duplex_timerfd = spa_system_timerfd_create(this->data_system,
101
                CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);
102
    } else {
103
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/bluez-hardware.conf -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/bluez-hardware.conf Changed
9
 
1
@@ -39,6 +39,7 @@
2
     { name = "Motorola DC800", no-features =  sbc-xq  },  # #pipewire-1590
3
     { name = "Motorola S305", no-features =  sbc-xq  },  # #pipewire-1590
4
     { name = "Soundcore Life P2-L", no-features =  msbc-alt1, msbc-alt1-rtl  },
5
+    { name = "Soundcore Motion B", no-features =  hw-volume  },
6
     { name = "SoundCore mini", no-features =  hw-volume  },  # #pipewire-1686
7
     { name = "SoundCore 2", no-features =  sbc-xq  },  # #pipewire-2291
8
     { name = "Tribit MAXSound Plus", no-features =  hw-volume  },  # #pipewire-1592
9
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
201
 
1
@@ -125,6 +125,10 @@
2
 
3
    struct spa_bt_quirks *quirks;
4
 
5
+#define MAX_SETTINGS 128
6
+   struct spa_dict_item global_setting_itemsMAX_SETTINGS;
7
+   struct spa_dict global_settings;
8
+
9
    /* A reference audio info for A2DP codec configuration. */
10
    struct a2dp_codec_audio_info default_audio_info;
11
 };
12
@@ -437,18 +441,21 @@
13
    return 0;
14
 }
15
 
16
-static const struct a2dp_codec *a2dp_endpoint_to_codec(struct spa_bt_monitor *monitor, const char *endpoint)
17
+static const struct a2dp_codec *a2dp_endpoint_to_codec(struct spa_bt_monitor *monitor, const char *endpoint, bool *sink)
18
 {
19
    const char *ep_name;
20
    const struct a2dp_codec * const * const a2dp_codecs = monitor->a2dp_codecs;
21
    int i;
22
 
23
-   if (spa_strstartswith(endpoint, A2DP_SINK_ENDPOINT "/"))
24
+   if (spa_strstartswith(endpoint, A2DP_SINK_ENDPOINT "/")) {
25
        ep_name = endpoint + strlen(A2DP_SINK_ENDPOINT "/");
26
-   else if (spa_strstartswith(endpoint, A2DP_SOURCE_ENDPOINT "/"))
27
+       *sink = true;
28
+   } else if (spa_strstartswith(endpoint, A2DP_SOURCE_ENDPOINT "/")) {
29
        ep_name = endpoint + strlen(A2DP_SOURCE_ENDPOINT "/");
30
-   else
31
+       *sink = false;
32
+   } else {
33
        return NULL;
34
+   }
35
 
36
    for (i = 0; a2dp_codecsi; i++) {
37
        const struct a2dp_codec *codec = a2dp_codecsi;
38
@@ -486,6 +493,7 @@
39
    DBusError err;
40
    int i, size, res;
41
    const struct a2dp_codec *codec;
42
+   bool sink;
43
 
44
    dbus_error_init(&err);
45
 
46
@@ -501,14 +509,15 @@
47
    for (i = 0; i < size; i++)
48
        spa_log_debug(monitor->log, "  %d: %02x", i, capi);
49
 
50
-   codec = a2dp_endpoint_to_codec(monitor, path);
51
+   codec = a2dp_endpoint_to_codec(monitor, path, &sink);
52
    if (codec != NULL)
53
        /* FIXME: We can't determine which device the SelectConfiguration()
54
         * call is associated with, therefore device settings are not passed.
55
         * This causes inconsistency with SelectConfiguration() triggered
56
         * by codec switching.
57
          */
58
-       res = codec->select_config(codec, 0, cap, size, &monitor->default_audio_info, NULL, config);
59
+       res = codec->select_config(codec, sink ? A2DP_CODEC_FLAG_SINK : 0, cap, size, &monitor->default_audio_info,
60
+               &monitor->global_settings, config);
61
    else
62
        res = -ENOTSUP;
63
 
64
@@ -1543,7 +1552,7 @@
65
    return device->adapter && device->address;
66
 }
67
 
68
-bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec)
69
+bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec, bool sink)
70
 {
71
    struct spa_bt_monitor *monitor = device->monitor;
72
    struct spa_bt_remote_endpoint *ep;
73
@@ -1579,15 +1588,22 @@
74
    }
75
 
76
    spa_list_for_each(ep, &device->remote_endpoint_list, device_link) {
77
+       const enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid);
78
+       const enum spa_bt_profile expected = sink ?
79
+           SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
80
+
81
+       if (profile != expected)
82
+           continue;
83
+
84
        if (a2dp_codec_check_caps(codec, ep->codec, ep->capabilities, ep->capabilities_len,
85
-                     &ep->monitor->default_audio_info))
86
+                       &ep->monitor->default_audio_info, &monitor->global_settings))
87
            return true;
88
    }
89
 
90
    return false;
91
 }
92
 
93
-const struct a2dp_codec **spa_bt_device_get_supported_a2dp_codecs(struct spa_bt_device *device, size_t *count)
94
+const struct a2dp_codec **spa_bt_device_get_supported_a2dp_codecs(struct spa_bt_device *device, size_t *count, bool sink)
95
 {
96
    struct spa_bt_monitor *monitor = device->monitor;
97
    const struct a2dp_codec * const * const a2dp_codecs = monitor->a2dp_codecs;
98
@@ -1603,7 +1619,7 @@
99
 
100
    j = 0;
101
    for (i = 0; a2dp_codecsi != NULL; ++i) {
102
-       if (spa_bt_device_supports_a2dp_codec(device, a2dp_codecsi)) {
103
+       if (spa_bt_device_supports_a2dp_codec(device, a2dp_codecsi, sink)) {
104
            supported_codecsj = a2dp_codecsi;
105
            ++j;
106
        }
107
@@ -2511,7 +2527,7 @@
108
    .set_volume = transport_set_volume,
109
 };
110
 
111
-static void append_basic_array_variant_dict_entry(DBusMessageIter *dict, int key_type_int, void* key, const char* variant_type_str, const char* array_type_str, int array_type_int, void* data, int data_size);
112
+static void append_basic_array_variant_dict_entry(DBusMessageIter *dict, const char* key, const char* variant_type_str, const char* array_type_str, int array_type_int, void* data, int data_size);
113
 
114
 static void a2dp_codec_switch_reply(DBusPendingCall *pending, void *userdata);
115
 
116
@@ -2569,10 +2585,10 @@
117
    char *local_endpoint = NULL;
118
    int res, config_size;
119
    dbus_bool_t dbus_ret;
120
-   const char *str;
121
    DBusMessage *m;
122
    DBusMessageIter iter, d;
123
    int i;
124
+   bool sink;
125
 
126
    /* Try setting configuration for current codec on current endpoint in list */
127
 
128
@@ -2603,8 +2619,10 @@
129
 
130
    if (sw->profile & SPA_BT_PROFILE_A2DP_SINK) {
131
        local_endpoint_base = A2DP_SOURCE_ENDPOINT;
132
+       sink = false;
133
    } else if (sw->profile & SPA_BT_PROFILE_A2DP_SOURCE) {
134
        local_endpoint_base = A2DP_SINK_ENDPOINT;
135
+       sink = true;
136
    } else {
137
        spa_log_debug(sw->device->monitor->log, "a2dp codec switch %p: bad profile (%d), try next",
138
                      sw, sw->profile);
139
@@ -2630,9 +2648,9 @@
140
        }
141
    }
142
 
143
-   res = codec->select_config(codec, 0, ep->capabilities, ep->capabilities_len,
144
+   res = codec->select_config(codec, sink ? A2DP_CODEC_FLAG_SINK : 0, ep->capabilities, ep->capabilities_len,
145
                   &sw->device->monitor->default_audio_info,
146
-                  sw->device->settings, config);
147
+                  &sw->device->monitor->global_settings, config);
148
    if (res < 0) {
149
        spa_log_debug(sw->device->monitor->log, "a2dp codec switch %p: incompatible capabilities (%d), try next",
150
                      sw, res);
151
@@ -2659,8 +2677,7 @@
152
    dbus_message_iter_init_append(m, &iter);
153
    dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &local_endpoint);
154
    dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &d);
155
-   str = "Capabilities";
156
-   append_basic_array_variant_dict_entry(&d, DBUS_TYPE_STRING, &str, "ay", "y", DBUS_TYPE_BYTE, config, config_size);
157
+   append_basic_array_variant_dict_entry(&d, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, config, config_size);
158
    dbus_message_iter_close_container(&iter, &d);
159
 
160
    spa_assert(sw->pending == NULL);
161
@@ -2878,6 +2895,7 @@
162
    const struct a2dp_codec *codec = *sw->codec_iter;
163
    const char *path1 = *(char **)a, *path2 = *(char **)b;
164
    struct spa_bt_remote_endpoint *ep1, *ep2;
165
+   uint32_t flags;
166
 
167
    ep1 = device_remote_endpoint_find(sw->device, path1);
168
    ep2 = device_remote_endpoint_find(sw->device, path2);
169
@@ -2886,6 +2904,10 @@
170
        ep1 = NULL;
171
    if (ep2 != NULL && (ep2->uuid == NULL || ep2->codec != codec->codec_id || ep2->capabilities == NULL))
172
        ep2 = NULL;
173
+   if (ep1 && ep2 && !spa_streq(ep1->uuid, ep2->uuid)) {
174
+       ep1 = NULL;
175
+       ep2 = NULL;
176
+   }
177
 
178
    if (ep1 == NULL && ep2 == NULL)
179
        return 0;
180
@@ -2894,8 +2916,11 @@
181
    else if (ep2 == NULL)
182
        return -1;
183
 
184
-   return codec->caps_preference_cmp(codec, ep1->capabilities, ep1->capabilities_len,
185
-           ep2->capabilities, ep2->capabilities_len, &sw->device->monitor->default_audio_info);
186
+   flags = spa_streq(ep1->uuid, SPA_BT_UUID_A2DP_SOURCE) ? A2DP_CODEC_FLAG_SINK : 0;
187
+
188
+   return codec->caps_preference_cmp(codec, flags, ep1->capabilities, ep1->capabilities_len,
189
+           ep2->capabilities, ep2->capabilities_len, &sw->device->monitor->default_audio_info,
190
+           &sw->device->monitor->global_settings);
191
 }
192
 
193
 /* Ensure there's a transport for at least one of the listed codecs */
194
@@ -2913,7 +2938,7 @@
195
    }
196
 
197
    for (i = 0; codecsi != NULL; ++i) {
198
-       if (spa_bt_device_supports_a2dp_codec(device, codecsi)) {
199
+       if (spa_bt_device_supports_a2dp_codec(device, codecsi, true)) {
200
            preferred_codec = codecsi;
201
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
38
 
1
@@ -301,6 +301,8 @@
2
 
3
 static float get_soft_volume_boost(struct node *node)
4
 {
5
+   const struct a2dp_codec *codec = node->transport ? node->transport->a2dp_codec : NULL;
6
+
7
    /*
8
     * For A2DP duplex, the duplex microphone channel sometimes does not appear
9
     * to have hardware gain, and input volume is very low.
10
@@ -310,7 +312,8 @@
11
     * If this causes clipping, the user can just reduce the mic volume to
12
     * bring SW gain below 1.
13
     */
14
-   if (node->a2dp_duplex && node->transport &&
15
+   if (node->a2dp_duplex && node->transport && codec && codec->info &&
16
+           spa_atob(spa_dict_lookup(codec->info, "duplex.boost")) &&
17
            node->id == DEVICE_ID_SOURCE &&
18
            !node->transport->volumesSPA_BT_VOLUME_ID_RX.active)
19
        return 10.0f;   /* 20 dB boost */
20
@@ -912,7 +915,7 @@
21
    if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) {
22
        free(this->supported_codecs);
23
        this->supported_codecs = spa_bt_device_get_supported_a2dp_codecs(
24
-           this->bt_dev, &this->supported_codec_count);
25
+           this->bt_dev, &this->supported_codec_count, true);
26
    }
27
 
28
    switch (this->profile) {
29
@@ -1127,7 +1130,7 @@
30
    if (this->supported_codecs)
31
        free(this->supported_codecs);
32
    this->supported_codecs = spa_bt_device_get_supported_a2dp_codecs(
33
-                   this->bt_dev, &this->supported_codec_count);
34
+       this->bt_dev, &this->supported_codec_count, true);
35
 
36
    /* Prefer A2DP, then HFP, then null, but select AG if the device
37
       appears not to have A2DP_SINK or any HEAD_UNIT profile */
38
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/codec-loader.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/codec-loader.c Changed
33
 
1
@@ -63,6 +63,11 @@
2
        SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX,
3
        SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM,
4
        SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX,
5
+       SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05,
6
+       SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_51,
7
+       SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71,
8
+       SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_DUPLEX,
9
+       SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_PRO,
10
    };
11
    size_t i;
12
    for (i = 0; i < SPA_N_ELEMENTS(order); ++i)
13
@@ -138,6 +143,9 @@
14
 
15
        spa_log_debug(impl->log, "loaded A2DP codec %s from %s", c->name, factory_name);
16
 
17
+       if (c->set_log)
18
+           c->set_log(impl->log);
19
+
20
        impl->codecsimpl->n_codecs++ = c;
21
        ++n_codecs;
22
 
23
@@ -171,7 +179,8 @@
24
        A2DP_CODEC_FACTORY_LIB("faststream"),
25
        A2DP_CODEC_FACTORY_LIB("ldac"),
26
        A2DP_CODEC_FACTORY_LIB("sbc"),
27
-       A2DP_CODEC_FACTORY_LIB("lc3plus")
28
+       A2DP_CODEC_FACTORY_LIB("lc3plus"),
29
+       A2DP_CODEC_FACTORY_LIB("opus")
30
 #undef A2DP_CODEC_FACTORY_LIB
31
    };
32
 
33
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/decode-buffer.h -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/decode-buffer.h Changed
31
 
1
@@ -389,7 +389,8 @@
2
 static void spa_bt_decode_buffer_process(struct spa_bt_decode_buffer *this, uint32_t samples, uint32_t duration)
3
 {
4
    const uint32_t data_size = samples * this->frame_size;
5
-   const int32_t max_level = SPA_MAX(8 * this->packet_size.max, (int32_t)duration);
6
+   const int32_t packet_size = SPA_CLAMP(this->packet_size.max, 0, INT32_MAX/8);
7
+   const int32_t max_level = SPA_MAX(8 * packet_size, (int32_t)duration);
8
    uint32_t avail;
9
 
10
    if (SPA_UNLIKELY(duration != this->prev_duration)) {
11
@@ -405,8 +406,8 @@
12
        spa_log_trace(this->log, "%p buffering size:%d", this, (int)size);
13
 
14
        if (this->received &&
15
-               this->packet_size.max > 0 &&
16
-               size >= SPA_MAX(3*this->packet_size.max, (int32_t)duration))
17
+               packet_size > 0 &&
18
+               size >= SPA_MAX(3*packet_size, (int32_t)duration))
19
            this->buffering = false;
20
        else
21
            return;
22
@@ -428,7 +429,7 @@
23
        spa_bt_ptp_update(&this->spike, this->ctl.avg - level, this->prev_consumed);
24
 
25
        /* Update target level */
26
-       target = BUFFERING_TARGET(this->spike.max, this->packet_size.max);
27
+       target = BUFFERING_TARGET(this->spike.max, packet_size);
28
 
29
        if (level > SPA_MAX(4 * target, 2*(int32_t)duration) &&
30
                avail > data_size) {
31
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/defs.h Changed
33
 
1
@@ -134,13 +134,13 @@
2
 
3
 #define BLUEZ_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported"
4
 
5
-#define SPA_BT_UUID_A2DP_SOURCE "0000110A-0000-1000-8000-00805F9B34FB"
6
-#define SPA_BT_UUID_A2DP_SINK   "0000110B-0000-1000-8000-00805F9B34FB"
7
-#define SPA_BT_UUID_HSP_HS      "00001108-0000-1000-8000-00805F9B34FB"
8
-#define SPA_BT_UUID_HSP_HS_ALT  "00001131-0000-1000-8000-00805F9B34FB"
9
-#define SPA_BT_UUID_HSP_AG      "00001112-0000-1000-8000-00805F9B34FB"
10
-#define SPA_BT_UUID_HFP_HF      "0000111E-0000-1000-8000-00805F9B34FB"
11
-#define SPA_BT_UUID_HFP_AG      "0000111F-0000-1000-8000-00805F9B34FB"
12
+#define SPA_BT_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb"
13
+#define SPA_BT_UUID_A2DP_SINK   "0000110b-0000-1000-8000-00805f9b34fb"
14
+#define SPA_BT_UUID_HSP_HS      "00001108-0000-1000-8000-00805f9b34fb"
15
+#define SPA_BT_UUID_HSP_HS_ALT  "00001131-0000-1000-8000-00805f9b34fb"
16
+#define SPA_BT_UUID_HSP_AG      "00001112-0000-1000-8000-00805f9b34fb"
17
+#define SPA_BT_UUID_HFP_HF      "0000111e-0000-1000-8000-00805f9b34fb"
18
+#define SPA_BT_UUID_HFP_AG      "0000111f-0000-1000-8000-00805f9b34fb"
19
 
20
 #define PROFILE_HSP_AG "/Profile/HSPAG"
21
 #define PROFILE_HSP_HS "/Profile/HSPHS"
22
@@ -490,8 +490,8 @@
23
 int spa_bt_device_connect_profile(struct spa_bt_device *device, enum spa_bt_profile profile);
24
 int spa_bt_device_check_profiles(struct spa_bt_device *device, bool force);
25
 int spa_bt_device_ensure_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec * const *codecs);
26
-bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec);
27
-const struct a2dp_codec **spa_bt_device_get_supported_a2dp_codecs(struct spa_bt_device *device, size_t *count);
28
+bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec, bool sink);
29
+const struct a2dp_codec **spa_bt_device_get_supported_a2dp_codecs(struct spa_bt_device *device, size_t *count, bool sink);
30
 int spa_bt_device_ensure_hfp_codec(struct spa_bt_device *device, unsigned int codec);
31
 int spa_bt_device_supports_hfp_codec(struct spa_bt_device *device, unsigned int codec);
32
 int spa_bt_device_release_transports(struct spa_bt_device *device);
33
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/meson.build Changed
26
 
1
@@ -111,8 +111,6 @@
2
 endif
3
 
4
 if get_option('bluez5-codec-lc3plus').allowed() and lc3plus_dep.found()
5
-  lc3plus_args = codec_args
6
-  lc3plus_dep =  lc3plus_dep 
7
   bluez_codec_lc3plus = shared_library('spa-codec-bluez5-lc3plus',
8
      'a2dp-codec-lc3plus.c', 'a2dp-codecs.c' ,
9
     include_directories :  configinc ,
10
@@ -121,3 +119,15 @@
11
     install : true,
12
     install_dir : spa_plugindir / 'bluez5')
13
 endif
14
+
15
+if get_option('bluez5-codec-opus').allowed() and opus_dep.found()
16
+  opus_args = codec_args
17
+  opus_dep =  opus_dep 
18
+  bluez_codec_opus = shared_library('spa-codec-bluez5-opus',
19
+     'a2dp-codec-opus.c', 'a2dp-codecs.c' ,
20
+    include_directories :  configinc ,
21
+    c_args : opus_args,
22
+    dependencies :  spa_dep, opus_dep, mathlib ,
23
+    install : true,
24
+    install_dir : spa_plugindir / 'bluez5')
25
+endif
26
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/sco-sink.c Changed
12
 
1
@@ -1147,8 +1147,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (io->status == SPA_STATUS_HAVE_DATA && io->buffer_id < port->n_buffers) {
11
        struct buffer *b = &port->buffersio->buffer_id;
12
pipewire-0.3.56.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/bluez5/sco-source.c Changed
28
 
1
@@ -542,6 +542,15 @@
2
            return 0;
3
        }
4
 
5
+       if (size_read % port->frame_size != 0) {
6
+           /* Unaligned data: reception or adapter problem.
7
+            * Consider the whole packet lost and report.
8
+            */
9
+           spa_log_debug(this->log,
10
+                   "received bad Bluetooth SCO CVSD packet");
11
+           return 0;
12
+       }
13
+
14
        packet = spa_bt_decode_buffer_get_write(&port->buffer, &avail);
15
        avail = SPA_MIN(avail, (uint32_t)size_read);
16
        spa_memmove(packet, read_data, avail);
17
@@ -1286,8 +1295,8 @@
18
    spa_return_val_if_fail(this != NULL, -EINVAL);
19
 
20
    port = &this->port;
21
-   io = port->io;
22
-   spa_return_val_if_fail(io != NULL, -EIO);
23
+   if ((io = port->io) == NULL)
24
+       return -EIO;
25
 
26
    /* Return if we already have a buffer */
27
    if (io->status == SPA_STATUS_HAVE_DATA)
28
pipewire-0.3.56.tar.gz/spa/plugins/control/mixer.c -> pipewire-0.3.57.tar.gz/spa/plugins/control/mixer.c Changed
12
 
1
@@ -587,8 +587,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    outport = GET_OUT_PORT(this, 0);
5
-   outio = outport->io;
6
-   spa_return_val_if_fail(outio != NULL, -EIO);
7
+   if ((outio = outport->io) == NULL)
8
+       return -EIO;
9
 
10
    spa_log_trace_fp(this->log, NAME " %p: status %p %d %d",
11
            this, outio, outio->status, outio->buffer_id);
12
pipewire-0.3.56.tar.gz/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-0.3.57.tar.gz/spa/plugins/libcamera/libcamera-device.cpp Changed
76
 
1
@@ -78,35 +78,32 @@
2
    std::shared_ptr<Camera> camera;
3
 };
4
 
5
-std::string cameraModel(const Camera *camera)
6
+static std::string cameraModel(const Camera *camera)
7
 {
8
    const ControlList &props = camera->properties();
9
-   std::string name;
10
-   if (props.contains(properties::Model))
11
-       name = props.get(properties::Model);
12
-   else
13
-       name = camera->id();
14
-        return name;
15
+
16
+   if (auto model = props.get(properties::Model))
17
+       return std::move(model.value());
18
+
19
+   return camera->id();
20
 }
21
 
22
-std::string cameraLoc(const Camera *camera)
23
+static const char *cameraLoc(const Camera *camera)
24
 {
25
    const ControlList &props = camera->properties();
26
-   std::string location;
27
-   if (props.contains(properties::Location)) {
28
-       switch (props.get(properties::Location)) {
29
+
30
+   if (auto location = props.get(properties::Location)) {
31
+       switch (location.value()) {
32
        case properties::CameraLocationFront:
33
-           location = "front";
34
-           break;
35
+           return "front";
36
        case properties::CameraLocationBack:
37
-           location = "back";
38
-           break;
39
+           return "back";
40
        case properties::CameraLocationExternal:
41
-           location = "external";
42
-           break;
43
+           return "external";
44
        }
45
    }
46
-   return location;
47
+
48
+   return nullptr;
49
 }
50
 
51
 static int emit_info(struct impl *impl, bool full)
52
@@ -116,7 +113,7 @@
53
    uint32_t n_items = 0;
54
    struct spa_device_info info;
55
    struct spa_param_info params2;
56
-   char path256, location10, model256, name256;
57
+   char path256, model256, name256;
58
 
59
    info = SPA_DEVICE_INFO_INIT();
60
 
61
@@ -127,9 +124,11 @@
62
    ADD_ITEM(SPA_KEY_OBJECT_PATH, path);
63
    ADD_ITEM(SPA_KEY_DEVICE_API, "libcamera");
64
    ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Video/Device");
65
-   ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, (char *)impl->props.device);
66
-   snprintf(location, sizeof(location), "%s", cameraLoc(impl->camera.get()).c_str());
67
-   ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location);
68
+   ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, impl->props.device);
69
+
70
+   if (auto location = cameraLoc(impl->camera.get()))
71
+       ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location);
72
+
73
    snprintf(model, sizeof(model), "%s", cameraModel(impl->camera.get()).c_str());
74
    ADD_ITEM(SPA_KEY_DEVICE_PRODUCT_NAME, model);
75
    ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, model);
76
pipewire-0.3.56.tar.gz/spa/plugins/libcamera/libcamera-source.cpp -> pipewire-0.3.57.tar.gz/spa/plugins/libcamera/libcamera-source.cpp Changed
12
 
1
@@ -823,8 +823,8 @@
2
    spa_return_val_if_fail(impl != NULL, -EINVAL);
3
 
4
    port = GET_OUT_PORT(impl, 0);
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (port->control)
11
        process_control(impl, &port->control->sequence);
12
pipewire-0.3.56.tar.gz/spa/plugins/meson.build -> pipewire-0.3.57.tar.gz/spa/plugins/meson.build Changed
17
 
1
@@ -1,7 +1,7 @@
2
 if alsa_dep.found()
3
   subdir('alsa')
4
 endif
5
-if get_option('avb').allowed()
6
+if get_option('avb').require(host_machine.system() == 'linux', error_message: 'AVB support is only available on Linux').allowed()
7
   subdir('avb')
8
 endif
9
 if get_option('audioconvert').allowed()
10
@@ -55,4 +55,4 @@
11
   subdir('libcamera')
12
 endif
13
 
14
-subdir('aec')
15
\ No newline at end of file
16
+subdir('aec')
17
pipewire-0.3.56.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.57.tar.gz/spa/plugins/support/loop.c Changed
9
 
1
@@ -350,6 +350,7 @@
2
 
3
    if (--impl->enter_count == 0) {
4
        impl->thread = 0;
5
+       flush_items(impl);
6
        impl->polling = false;
7
    }
8
 }
9
pipewire-0.3.56.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.57.tar.gz/spa/plugins/support/null-audio-sink.c Changed
13
 
1
@@ -737,9 +737,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-
6
-   io = port->io;
7
-   spa_return_val_if_fail(io != NULL, -EIO);
8
+   if ((io = port->io) == NULL)
9
+       return -EIO;
10
 
11
    if (io->status != SPA_STATUS_HAVE_DATA)
12
        return io->status;
13
pipewire-0.3.56.tar.gz/spa/plugins/test/fakesink.c -> pipewire-0.3.57.tar.gz/spa/plugins/test/fakesink.c Changed
13
 
1
@@ -639,9 +639,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-
6
-   io = port->io;
7
-   spa_return_val_if_fail(io != NULL, -EIO);
8
+   if ((io = port->io) == NULL)
9
+       return -EIO;
10
 
11
    if (io->status == SPA_STATUS_HAVE_DATA && io->buffer_id < port->n_buffers) {
12
        struct buffer *b = &port->buffersio->buffer_id;
13
pipewire-0.3.56.tar.gz/spa/plugins/test/fakesrc.c -> pipewire-0.3.57.tar.gz/spa/plugins/test/fakesrc.c Changed
12
 
1
@@ -680,8 +680,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (io->status == SPA_STATUS_HAVE_DATA)
11
        return SPA_STATUS_HAVE_DATA;
12
pipewire-0.3.56.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/v4l2/v4l2-source.c Changed
12
 
1
@@ -879,8 +879,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = GET_OUT_PORT(this, 0);
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (port->control)
11
        process_control(this, &port->control->sequence);
12
pipewire-0.3.56.tar.gz/spa/plugins/videotestsrc/videotestsrc.c -> pipewire-0.3.57.tar.gz/spa/plugins/videotestsrc/videotestsrc.c Changed
12
 
1
@@ -787,8 +787,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (io->status == SPA_STATUS_HAVE_DATA)
11
        return SPA_STATUS_HAVE_DATA;
12
pipewire-0.3.56.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.57.tar.gz/spa/plugins/volume/volume.c Changed
23
 
1
@@ -679,8 +679,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    out_port = GET_OUT_PORT(this, 0);
5
-   output = out_port->io;
6
-   spa_return_val_if_fail(output != NULL, -EIO);
7
+   if ((output = out_port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (output->status == SPA_STATUS_HAVE_DATA)
11
        return SPA_STATUS_HAVE_DATA;
12
@@ -692,8 +692,8 @@
13
    }
14
 
15
    in_port = GET_IN_PORT(this, 0);
16
-   input = in_port->io;
17
-   spa_return_val_if_fail(input != NULL, -EIO);
18
+   if ((input = in_port->io) == NULL)
19
+       return -EIO;
20
 
21
    if (input->status != SPA_STATUS_HAVE_DATA)
22
        return SPA_STATUS_NEED_DATA;
23
pipewire-0.3.56.tar.gz/spa/plugins/vulkan/vulkan-compute-filter.c -> pipewire-0.3.57.tar.gz/spa/plugins/vulkan/vulkan-compute-filter.c Changed
23
 
1
@@ -578,8 +578,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    inport = &this->portSPA_DIRECTION_INPUT;
5
-   inio = inport->io;
6
-   spa_return_val_if_fail(inio != NULL, -EIO);
7
+   if ((inio = inport->io) == NULL)
8
+       return -EIO;
9
 
10
    if (inio->status != SPA_STATUS_HAVE_DATA)
11
        return inio->status;
12
@@ -590,8 +590,8 @@
13
    }
14
 
15
    outport = &this->portSPA_DIRECTION_OUTPUT;
16
-   outio = outport->io;
17
-   spa_return_val_if_fail(outio != NULL, -EIO);
18
+   if ((outio = outport->io) == NULL)
19
+       return -EIO;
20
 
21
    if (outio->status == SPA_STATUS_HAVE_DATA)
22
        return SPA_STATUS_HAVE_DATA;
23
pipewire-0.3.56.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c -> pipewire-0.3.57.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c Changed
12
 
1
@@ -802,8 +802,8 @@
2
    spa_return_val_if_fail(this != NULL, -EINVAL);
3
 
4
    port = &this->port;
5
-   io = port->io;
6
-   spa_return_val_if_fail(io != NULL, -EIO);
7
+   if ((io = port->io) == NULL)
8
+       return -EIO;
9
 
10
    if (io->status == SPA_STATUS_HAVE_DATA)
11
        return SPA_STATUS_HAVE_DATA;
12
pipewire-0.3.57.tar.gz/src/daemon/systemd/user/filter-chain.service.in Added
23
 
1
@@ -0,0 +1,21 @@
2
+Unit
3
+Description=PipeWire filter chain daemon
4
+
5
+After=pipewire.service pipewire-session-manager.service
6
+BindsTo=pipewire.service
7
+
8
+Service
9
+LockPersonality=yes
10
+MemoryDenyWriteExecute=yes
11
+NoNewPrivileges=yes
12
+RestrictNamespaces=yes
13
+SystemCallArchitectures=native
14
+SystemCallFilter=@system-service
15
+Type=simple
16
+ExecStart=@PW_BINARY@ -c filter-chain.conf
17
+Restart=on-failure
18
+Slice=session.slice
19
+
20
+Install
21
+Also=pipewire.socket
22
+WantedBy=default.target
23
pipewire-0.3.56.tar.gz/src/daemon/systemd/user/meson.build -> pipewire-0.3.57.tar.gz/src/daemon/systemd/user/meson.build Changed
10
 
1
@@ -20,3 +20,8 @@
2
                output : 'pipewire-pulse.service',
3
                configuration : systemd_config,
4
                install_dir : systemd_user_services_dir)
5
+
6
+configure_file(input : 'filter-chain.service.in',
7
+               output : 'filter-chain.service',
8
+               configuration : systemd_config,
9
+               install_dir : systemd_user_services_dir)
10
pipewire-0.3.56.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.57.tar.gz/src/gst/gstpipewiresrc.c Changed
43
 
1
@@ -568,19 +568,23 @@
2
       meta->height = crop->region.size.height;
3
     }
4
   }
5
-  gst_buffer_add_parent_buffer_meta (buf, data->buf);
6
-  gst_buffer_unref (data->buf);
7
   for (i = 0; i < b->buffer->n_datas; i++) {
8
     struct spa_data *d = &b->buffer->datasi;
9
     GstMemory *pmem = gst_buffer_peek_memory (data->buf, i);
10
     if (pmem) {
11
-      GstMemory *mem = gst_memory_share (pmem, d->chunk->offset, d->chunk->size);
12
+      GstMemory *mem;
13
+      if (!pwsrc->always_copy)
14
+        mem = gst_memory_share (pmem, d->chunk->offset, d->chunk->size);
15
+      else
16
+        mem = gst_memory_copy (pmem, d->chunk->offset, d->chunk->size);
17
       gst_buffer_insert_memory (buf, i, mem);
18
-      spa_assert_se(mem->size <= mem->maxsize);
19
     }
20
     if (d->chunk->flags & SPA_CHUNK_FLAG_CORRUPTED)
21
       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_CORRUPTED);
22
   }
23
+  if (!pwsrc->always_copy)
24
+    gst_buffer_add_parent_buffer_meta (buf, data->buf);
25
+  gst_buffer_unref (data->buf);
26
   return buf;
27
 }
28
 
29
@@ -1091,12 +1095,7 @@
30
   }
31
   pw_thread_loop_unlock (pwsrc->core->loop);
32
 
33
-  if (pwsrc->always_copy) {
34
-    *buffer = gst_buffer_copy_deep (buf);
35
-    gst_buffer_unref (buf);
36
-  }
37
-  else
38
-    *buffer = buf;
39
+  *buffer = buf;
40
 
41
   if (pwsrc->is_live)
42
     base_time = GST_ELEMENT_CAST (psrc)->base_time;
43
pipewire-0.3.57.tar.gz/src/modules/flatpak-utils.h Added
158
 
1
@@ -0,0 +1,156 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2018 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef FLATPAK_UTILS_H
27
+#define FLATPAK_UTILS_H
28
+
29
+#include <stdio.h>
30
+#include <string.h>
31
+#include <fcntl.h>
32
+#include <sys/mman.h>
33
+#include <sys/stat.h>
34
+#ifdef HAVE_SYS_VFS_H
35
+#include <sys/vfs.h>
36
+#endif
37
+
38
+#include "config.h"
39
+
40
+#ifdef HAVE_GLIB2
41
+#include <glib.h>
42
+#endif
43
+
44
+#include <spa/utils/result.h>
45
+#include <pipewire/log.h>
46
+
47
+static int pw_check_flatpak_parse_metadata(const char *buf, size_t size, char **app_id, char **devices)
48
+{
49
+#ifdef HAVE_GLIB2
50
+   /*
51
+    * See flatpak-metadata(5)
52
+    *
53
+    * The .flatpak-info file is in GLib key_file .ini format.
54
+    */
55
+   g_autoptr(GKeyFile) metadata = NULL;
56
+   char *s;
57
+
58
+   metadata = g_key_file_new();
59
+   if (!g_key_file_load_from_data(metadata, buf, size, G_KEY_FILE_NONE, NULL))
60
+       return -EINVAL;
61
+
62
+   if (app_id) {
63
+       s = g_key_file_get_value(metadata, "Application", "name", NULL);
64
+       *app_id = s ? strdup(s) : NULL;
65
+       g_free(s);
66
+   }
67
+
68
+   if (devices) {
69
+       s = g_key_file_get_value(metadata, "Context", "devices", NULL);
70
+       *devices = s ? strdup(s) : NULL;
71
+       g_free(s);
72
+   }
73
+
74
+   return 0;
75
+#else
76
+   return -ENOTSUP;
77
+#endif
78
+}
79
+
80
+static int pw_check_flatpak(pid_t pid, char **app_id, char **devices)
81
+{
82
+#if defined(__linux__)
83
+   char root_path2048;
84
+   int root_fd, info_fd, res;
85
+   struct stat stat_buf;
86
+
87
+   if (app_id)
88
+       *app_id = NULL;
89
+   if (devices)
90
+       *devices = NULL;
91
+
92
+   snprintf(root_path, sizeof(root_path), "/proc/%d/root", (int)pid);
93
+   root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
94
+   if (root_fd == -1) {
95
+       res = -errno;
96
+       if (res == -EACCES) {
97
+           struct statfs buf;
98
+           /* Access to the root dir isn't allowed. This can happen if the root is on a fuse
99
+            * filesystem, such as in a toolbox container. We will never have a fuse rootfs
100
+            * in the flatpak case, so in that case its safe to ignore this and
101
+            * continue to detect other types of apps. */
102
+           if (statfs(root_path, &buf) == 0 &&
103
+               buf.f_type == 0x65735546) /* FUSE_SUPER_MAGIC */
104
+               return 0;
105
+       }
106
+       /* Not able to open the root dir shouldn't happen. Probably the app died and
107
+        * we're failing due to /proc/$pid not existing. In that case fail instead
108
+        * of treating this as privileged. */
109
+       pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res));
110
+       return res;
111
+   }
112
+   info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
113
+   close (root_fd);
114
+   if (info_fd == -1) {
115
+       if (errno == ENOENT) {
116
+           pw_log_debug("no .flatpak-info, client on the host");
117
+           /* No file => on the host */
118
+           return 0;
119
+       }
120
+       res = -errno;
121
+       pw_log_error("error opening .flatpak-info: %m");
122
+       return res;
123
+        }
124
+   if (fstat (info_fd, &stat_buf) != 0 || !S_ISREG (stat_buf.st_mode)) {
125
+       /* Some weird fd => failure, assume sandboxed */
126
+       pw_log_error("error fstat .flatpak-info: %m");
127
+   } else if (app_id || devices) {
128
+       /* Parse the application ID if needed */
129
+       const size_t size = stat_buf.st_size;
130
+
131
+       if (size > 0) {
132
+           void *buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, info_fd, 0);
133
+           if (buf != MAP_FAILED) {
134
+               res = pw_check_flatpak_parse_metadata(buf, size, app_id, devices);
135
+               munmap(buf, size);
136
+           } else {
137
+               res = -errno;
138
+           }
139
+       } else {
140
+           res = -EINVAL;
141
+       }
142
+
143
+       if (res == -EINVAL)
144
+           pw_log_error("PID %d .flatpak-info file is malformed",
145
+                   (int)pid);
146
+       else if (res < 0)
147
+           pw_log_error("PID %d .flatpak-info parsing failed: %s",
148
+                   (int)pid, spa_strerror(res));
149
+   }
150
+   close(info_fd);
151
+   return 1;
152
+#else
153
+   return 0;
154
+#endif
155
+}
156
+
157
+#endif /* FLATPAK_UTILS_H */
158
pipewire-0.3.56.tar.gz/src/modules/meson.build -> pipewire-0.3.57.tar.gz/src/modules/meson.build Changed
49
 
1
@@ -33,12 +33,17 @@
2
   'module-x11-bell.c',
3
 
4
 
5
+pipewire_module_access_deps = spa_dep, mathlib, dl_lib, pipewire_dep
6
+if flatpak_support
7
+  pipewire_module_access_deps += glib2_dep
8
+endif
9
+
10
 pipewire_module_access = shared_library('pipewire-module-access',  'module-access.c' ,
11
   include_directories : configinc,
12
   install : true,
13
   install_dir : modules_install_dir,
14
   install_rpath: modules_install_dir,
15
-  dependencies : spa_dep, mathlib, dl_lib, pipewire_dep,
16
+  dependencies : pipewire_module_access_deps
17
 )
18
 
19
 pipewire_module_loopback = shared_library('pipewire-module-loopback',
20
@@ -277,6 +282,10 @@
21
   cdata.set('HAVE_AVAHI', true)
22
 endif
23
 
24
+if flatpak_support
25
+  pipewire_module_protocol_pulse_deps += glib2_dep
26
+endif
27
+
28
 pipewire_module_protocol_pulse = shared_library('pipewire-module-protocol-pulse',
29
   pipewire_module_protocol_pulse_sources,
30
   include_directories : configinc,
31
@@ -470,7 +479,7 @@
32
 endif
33
 summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules')
34
 
35
-roc_lib = cc.find_library('roc', required: get_option('roc'))
36
+roc_lib = cc.find_library('roc', has_headers: 'roc/config.h' , required: get_option('roc'))
37
 summary({'ROC': roc_lib.found()}, bool_yn: true, section: 'Streaming between daemons')
38
 
39
 build_module_roc = roc_lib.found()
40
@@ -518,7 +527,7 @@
41
   dependencies : mathlib, dl_lib, rt_lib, pipewire_dep,
42
 )
43
 
44
-build_module_avb = get_option('avb').allowed()
45
+build_module_avb = get_option('avb').require(host_machine.system() == 'linux', error_message: 'AVB support is only available on Linux').allowed()
46
 if build_module_avb
47
 pipewire_module_avb = shared_library('pipewire-module-avb',
48
    'module-avb.c',
49
pipewire-0.3.56.tar.gz/src/modules/module-access.c -> pipewire-0.3.57.tar.gz/src/modules/module-access.c Changed
144
 
1
@@ -46,6 +46,8 @@
2
 #include <pipewire/impl.h>
3
 #include <pipewire/private.h>
4
 
5
+#include "flatpak-utils.h"
6
+
7
 /** \page page_module_access PipeWire Module: Access
8
  *
9
  *
10
@@ -75,6 +77,9 @@
11
  *       on an external actor to update that property once permission is
12
  *       granted or rejected.
13
  *
14
+ * For connections from applications running inside Flatpak not mediated
15
+ * by a portal, the `access` module itself sets the `pipewire.access.portal.app_id`
16
+ * property to the Flatpak application ID.
17
  *
18
  * ## Module Options
19
  *
20
@@ -184,54 +189,6 @@
21
    return res;
22
 }
23
 
24
-#if defined(__linux__)
25
-static int check_flatpak(struct pw_impl_client *client, int pid)
26
-{
27
-   char root_path2048;
28
-   int root_fd, info_fd, res;
29
-   struct stat stat_buf;
30
-
31
-   sprintf(root_path, "/proc/%u/root", 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
-       res = -errno;
35
-       if (res == -EACCES) {
36
-           struct statfs buf;
37
-           /* Access to the root dir isn't allowed. This can happen if the root is on a fuse
38
-            * filesystem, such as in a toolbox container. We will never have a fuse rootfs
39
-            * in the flatpak case, so in that case its safe to ignore this and
40
-            * continue to detect other types of apps. */
41
-           if (statfs(root_path, &buf) == 0 &&
42
-               buf.f_type == 0x65735546) /* FUSE_SUPER_MAGIC */
43
-               return 0;
44
-       }
45
-       /* Not able to open the root dir shouldn't happen. Probably the app died and
46
-        * we're failing due to /proc/$pid not existing. In that case fail instead
47
-        * of treating this as privileged. */
48
-       pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res));
49
-       return res;
50
-   }
51
-   info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY);
52
-   close (root_fd);
53
-   if (info_fd == -1) {
54
-       if (errno == ENOENT) {
55
-           pw_log_debug("no .flatpak-info, client on the host");
56
-           /* No file => on the host */
57
-           return 0;
58
-       }
59
-       res = -errno;
60
-       pw_log_error("error opening .flatpak-info: %m");
61
-       return res;
62
-        }
63
-   if (fstat (info_fd, &stat_buf) != 0 || !S_ISREG (stat_buf.st_mode)) {
64
-       /* Some weird fd => failure, assume sandboxed */
65
-       pw_log_error("error fstat .flatpak-info: %m");
66
-   }
67
-   close(info_fd);
68
-   return 1;
69
-}
70
-#endif
71
-
72
 static void
73
 context_check_access(void *data, struct pw_impl_client *client)
74
 {
75
@@ -240,6 +197,8 @@
76
    struct spa_dict_item items2;
77
    const struct pw_properties *props;
78
    const char *str, *access;
79
+   char *flatpak_app_id = NULL;
80
+   int nitems = 0;
81
    int pid, res;
82
 
83
    pid = -EINVAL;
84
@@ -298,8 +257,7 @@
85
        (access = pw_properties_get(impl->properties, "access.force")) != NULL)
86
        goto wait_permissions;
87
 
88
-#if defined(__linux__)
89
-   res = check_flatpak(client, pid);
90
+   res = pw_check_flatpak(pid, &flatpak_app_id, NULL);
91
    if (res != 0) {
92
        if (res < 0) {
93
            if (res == -EACCES) {
94
@@ -313,9 +271,11 @@
95
            pw_log_debug(" %p: flatpak client %p added", impl, client);
96
        }
97
        access = "flatpak";
98
+       itemsnitems++ = SPA_DICT_ITEM_INIT("pipewire.access.portal.app_id",
99
+               flatpak_app_id);
100
        goto wait_permissions;
101
    }
102
-#endif
103
+
104
    if ((access = pw_properties_get(props, PW_KEY_CLIENT_ACCESS)) == NULL)
105
        access = "unrestricted";
106
 
107
@@ -326,24 +286,28 @@
108
 
109
 granted:
110
    pw_log_info("%p: client %p '%s' access granted", impl, client, access);
111
-   items0 = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
112
-   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, 1));
113
+   itemsnitems++ = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
114
+   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, nitems));
115
 
116
    permissions0 = PW_PERMISSION_INIT(PW_ID_ANY, PW_PERM_ALL);
117
    pw_impl_client_update_permissions(client, 1, permissions);
118
-   return;
119
+   goto done;
120
 
121
 wait_permissions:
122
    pw_log_info("%p: client %p wait for '%s' permissions",
123
            impl, client, access);
124
-   items0 = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
125
-   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, 1));
126
-   return;
127
+   itemsnitems++ = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
128
+   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, nitems));
129
+   goto done;
130
 
131
 rejected:
132
    pw_resource_error(pw_impl_client_get_core_resource(client), res, access);
133
-   items0 = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
134
-   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, 1));
135
+   itemsnitems++ = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, access);
136
+   pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, nitems));
137
+   goto done;
138
+
139
+done:
140
+   free(flatpak_app_id);
141
    return;
142
 }
143
 
144
pipewire-0.3.56.tar.gz/src/modules/module-avb/aaf.h -> pipewire-0.3.57.tar.gz/src/modules/module-avb/aaf.h Changed
10
 
1
@@ -35,7 +35,7 @@
2
    unsigned gv:1;
3
    unsigned tv:1;
4
 
5
-   uint8_t seq_number;
6
+   uint8_t seq_num;
7
 
8
    unsigned _r2:7;
9
    unsigned tu:1;
10
pipewire-0.3.56.tar.gz/src/modules/module-avb/iec61883.h -> pipewire-0.3.57.tar.gz/src/modules/module-avb/iec61883.h Changed
10
 
1
@@ -37,7 +37,7 @@
2
    unsigned gv:1;
3
    unsigned tv:1;
4
 
5
-   uint8_t seq_number;
6
+   uint8_t seq_num;
7
 
8
    unsigned _r2:7;
9
    unsigned tu:1;
10
pipewire-0.3.56.tar.gz/src/modules/module-avb/maap.c -> pipewire-0.3.57.tar.gz/src/modules/module-avb/maap.c Changed
13
 
1
@@ -421,7 +421,10 @@
2
    maap->server = server;
3
    pw_log_info("0x%"PRIx64" %d", server->entity_id, server->ifindex);
4
 
5
-   pw_getrandom(maap->xsubi, sizeof(maap->xsubi), 0);
6
+   if (pw_getrandom(maap->xsubi, sizeof(maap->xsubi), 0) != sizeof(maap->xsubi)) {
7
+       res = -errno;
8
+       goto error_free;
9
+   }
10
    load_state(maap);
11
 
12
    maap->source = pw_loop_add_io(server->impl->loop, fd, SPA_IO_IN, true, on_socket_data, maap);
13
pipewire-0.3.56.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.57.tar.gz/src/modules/module-client-node/remote-node.c Changed
26
 
1
@@ -857,14 +857,8 @@
2
 {
3
    struct link *link = user_data;
4
    struct spa_system *data_system = link->data->context->data_system;
5
-   struct timespec ts = { 0, 0 };
6
-
7
-   pw_log_trace_fp("link %p: signal", link);
8
-
9
-   spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts);
10
-   link->target.activation->status = PW_NODE_ACTIVATION_TRIGGERED;
11
-   link->target.activation->signal_time = SPA_TIMESPEC_TO_NSEC(&ts);
12
 
13
+   pw_log_trace_fp("link %p: signal %p", link, link->target.activation);
14
    if (SPA_UNLIKELY(spa_system_eventfd_write(data_system, link->signalfd, 1) < 0))
15
        pw_log_warn("link %p: write failed %m", link);
16
 
17
@@ -930,7 +924,7 @@
18
        link->map = mm;
19
        link->target.activation = ptr;
20
        link->signalfd = signalfd;
21
-       link->target.signal = link_signal_func;
22
+       link->target.signal_func = link_signal_func;
23
        link->target.data = link;
24
        link->target.node = NULL;
25
        spa_list_append(&data->links, &link->link);
26
pipewire-0.3.56.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.57.tar.gz/src/modules/module-echo-cancel.c Changed
10
 
1
@@ -993,8 +993,6 @@
2
        goto error;
3
    }
4
 
5
-   (void)SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_AUDIO_AEC, (struct spa_audio_aec *)impl->aec);
6
-
7
    pw_log_info("Using plugin AEC %s", impl->aec->name);
8
 
9
    if ((str = pw_properties_get(props, "aec.args")) != NULL)
10
pipewire-0.3.56.tar.gz/src/modules/module-filter-chain/convolver.c -> pipewire-0.3.57.tar.gz/src/modules/module-filter-chain/convolver.c Changed
17
 
1
@@ -232,9 +232,12 @@
2
        fft_cpx_free(&conv->segmentsi);
3
        fft_cpx_free(&conv->segmentsIri);
4
    }
5
-   fft_destroy(conv->fft);
6
-   fft_destroy(conv->ifft);
7
-   fft_free(conv->fft_buffer);
8
+   if (conv->fft)
9
+       fft_destroy(conv->fft);
10
+   if (conv->ifft)
11
+       fft_destroy(conv->ifft);
12
+   if (conv->fft_buffer)
13
+       fft_free(conv->fft_buffer);
14
    free(conv->segments);
15
    free(conv->segmentsIr);
16
    fft_cpx_free(&conv->pre_mult);
17
pipewire-0.3.56.tar.gz/src/modules/module-filter-chain/lv2_plugin.c -> pipewire-0.3.57.tar.gz/src/modules/module-filter-chain/lv2_plugin.c Changed
14
 
1
@@ -37,9 +37,9 @@
2
 #include <lilv/lilv.h>
3
 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
4
 #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
5
-#include "lv2/lv2plug.in/ns/ext/worker/worker.h"
6
-#include "lv2/lv2plug.in/ns/ext/options/options.h"
7
-#include "lv2/lv2plug.in/ns/ext/parameters/parameters.h"
8
+#include <lv2/lv2plug.in/ns/ext/worker/worker.h>
9
+#include <lv2/lv2plug.in/ns/ext/options/options.h>
10
+#include <lv2/lv2plug.in/ns/ext/parameters/parameters.h>
11
 
12
 #include "plugin.h"
13
 
14
pipewire-0.3.56.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.57.tar.gz/src/modules/module-protocol-native.c Changed
201
 
1
@@ -103,6 +103,11 @@
2
  * - XDG_RUNTIME_DIR
3
  * - USERPROFILE
4
  *
5
+ * The socket address will be written into the notification file descriptor
6
+ * if the following environment variable is set:
7
+ *
8
+ * - PIPEWIRE_NOTIFICATION_FD
9
+ *
10
  * When a client connect, the connection will be made to:
11
  *
12
  * - PIPEWIRE_REMOTE : the environment with the remote name
13
@@ -605,12 +610,15 @@
14
    if (client == NULL)
15
        goto exit;
16
 
17
-
18
    this = pw_impl_client_get_user_data(client);
19
    spa_list_append(&s->this.client_list, &this->protocol_link);
20
 
21
    this->server = s;
22
    this->client = client;
23
+   pw_map_init(&this->compat_v2.types, 0, 32);
24
+
25
+   pw_impl_client_add_listener(client, &this->client_listener, &client_events, this);
26
+
27
    this->source = pw_loop_add_io(pw_context_get_main_loop(context),
28
                      fd, SPA_IO_ERR | SPA_IO_HUP, true,
29
                      connection_data, this);
30
@@ -625,15 +633,11 @@
31
        goto cleanup_client;
32
    }
33
 
34
-   pw_map_init(&this->compat_v2.types, 0, 32);
35
-
36
    pw_protocol_native_connection_add_listener(this->connection,
37
                           &this->conn_listener,
38
                           &server_conn_events,
39
                           this);
40
 
41
-   pw_impl_client_add_listener(client, &this->client_listener, &client_events, this);
42
-
43
    if ((res = pw_impl_client_register(client, NULL)) < 0)
44
        goto cleanup_client;
45
 
46
@@ -761,6 +765,44 @@
47
    }
48
 }
49
 
50
+static int write_socket_address(struct server *s)
51
+{
52
+   long v;
53
+   int fd, res = 0;
54
+   char *endptr;
55
+   const char *env = getenv("PIPEWIRE_NOTIFICATION_FD");
56
+
57
+   if (env == NULL || env0 == '\0')
58
+       return 0;
59
+
60
+   errno = 0;
61
+   v = strtol(env, &endptr, 10);
62
+   if (endptr0 != '\0')
63
+       errno = EINVAL;
64
+   if (errno != 0) {
65
+       res = -errno;
66
+       pw_log_error("server %p: strtol() failed with error: %m", s);
67
+       goto error;
68
+   }
69
+   fd = (int)v;
70
+   if (v != fd) {
71
+       res = -ERANGE;
72
+       pw_log_error("server %p: invalid fd %ld: %s", s, v, spa_strerror(res));
73
+       goto error;
74
+   }
75
+   if (dprintf(fd, "%s\n", s->addr.sun_path) < 0) {
76
+       res = -errno;
77
+       pw_log_error("server %p: dprintf() failed with error: %m", s);
78
+       goto error;
79
+   }
80
+   close(fd);
81
+   unsetenv("PIPEWIRE_NOTIFICATION_FD");
82
+   return 0;
83
+
84
+error:
85
+   return res;
86
+}
87
+
88
 static int add_socket(struct pw_protocol *protocol, struct server *s)
89
 {
90
    socklen_t size;
91
@@ -815,6 +857,12 @@
92
        }
93
    }
94
 
95
+   res = write_socket_address(s);
96
+   if (res < 0) {
97
+       pw_log_error("server %p: failed to write socket address: %s", s,
98
+               spa_strerror(res));
99
+       goto error_close;
100
+   }
101
    s->activated = activated;
102
    s->loop = pw_context_get_main_loop(protocol->context);
103
    if (s->loop == NULL) {
104
@@ -990,35 +1038,9 @@
105
    goto done;
106
 }
107
 
108
-static void on_client_connection_destroy(void *data)
109
-{
110
-   struct client *impl = data;
111
-   spa_hook_remove(&impl->conn_listener);
112
-}
113
-
114
-static void on_client_need_flush(void *data)
115
-{
116
-        struct client *impl = data;
117
-
118
-   pw_log_trace("need flush");
119
-   impl->need_flush = true;
120
-
121
-   if (impl->source && !(impl->source->mask & SPA_IO_OUT)) {
122
-       pw_loop_update_io(impl->context->main_loop,
123
-               impl->source, impl->source->mask | SPA_IO_OUT);
124
-   }
125
-}
126
-
127
-static const struct pw_protocol_native_connection_events client_conn_events = {
128
-   PW_VERSION_PROTOCOL_NATIVE_CONNECTION_EVENTS,
129
-   .destroy = on_client_connection_destroy,
130
-   .need_flush = on_client_need_flush,
131
-};
132
-
133
 static int impl_connect_fd(struct pw_protocol_client *client, int fd, bool do_close)
134
 {
135
    struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
136
-   int res;
137
 
138
    impl->connected = false;
139
    impl->disconnecting = false;
140
@@ -1028,23 +1050,10 @@
141
                    fd,
142
                    SPA_IO_IN | SPA_IO_OUT | SPA_IO_HUP | SPA_IO_ERR,
143
                    do_close, on_remote_data, impl);
144
-   if (impl->source == NULL) {
145
-       res = -errno;
146
-       goto error_cleanup;
147
-   }
148
+   if (impl->source == NULL)
149
+       return -errno;
150
 
151
-   pw_protocol_native_connection_add_listener(impl->connection,
152
-                          &impl->conn_listener,
153
-                          &client_conn_events,
154
-                          impl);
155
    return 0;
156
-
157
-error_cleanup:
158
-   if (impl->connection) {
159
-       pw_protocol_native_connection_destroy(impl->connection);
160
-       impl->connection = NULL;
161
-   }
162
-   return res;
163
 }
164
 
165
 static void impl_disconnect(struct pw_protocol_client *client)
166
@@ -1057,9 +1066,7 @@
167
                 pw_loop_destroy_source(impl->context->main_loop, impl->source);
168
    impl->source = NULL;
169
 
170
-   if (impl->connection)
171
-                pw_protocol_native_connection_destroy(impl->connection);
172
-   impl->connection = NULL;
173
+   pw_protocol_native_connection_set_fd(impl->connection, -1);
174
 }
175
 
176
 static void impl_destroy(struct pw_protocol_client *client)
177
@@ -1068,6 +1075,10 @@
178
 
179
    impl_disconnect(client);
180
 
181
+   if (impl->connection)
182
+                pw_protocol_native_connection_destroy(impl->connection);
183
+   impl->connection = NULL;
184
+
185
    spa_list_remove(&client->link);
186
    client_unref(impl);
187
 }
188
@@ -1134,6 +1145,31 @@
189
    goto done;
190
 }
191
 
192
+static void on_client_connection_destroy(void *data)
193
+{
194
+   struct client *impl = data;
195
+   spa_hook_remove(&impl->conn_listener);
196
+}
197
+
198
+static void on_client_need_flush(void *data)
199
+{
200
+        struct client *impl = data;
201
pipewire-0.3.56.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
26
 
1
@@ -668,15 +668,16 @@
2
    attr->fragsize = SPA_ROUND_UP(attr->fragsize, frame_size);
3
    attr->fragsize = SPA_MAX(attr->fragsize, minfrag);
4
 
5
-   attr->tlength = attr->minreq = attr->prebuf = 0;
6
+   /* pulseaudio configures the source to half of the fragsize. It also
7
+    * immediately sends chunks to clients. Configure a 2/3 of the fragsize
8
+    * as the latency. */
9
+   latency = attr->fragsize * 2 / 3;
10
+
11
+   if (s->adjust_latency)
12
+       attr->fragsize = SPA_ROUND_UP(latency, frame_size);
13
+
14
+   attr->tlength = attr->prebuf = 0;
15
 
16
-   if (s->early_requests) {
17
-       latency = attr->fragsize;
18
-   } else if (s->adjust_latency) {
19
-       latency = attr->fragsize;
20
-   } else {
21
-       latency = attr->fragsize;
22
-   }
23
    /* make sure can queue at least to fragsize without overruns */
24
    if (attr->maxlength < attr->fragsize * 4)
25
        attr->maxlength = attr->fragsize * 4;
26
pipewire-0.3.56.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/server.c Changed
58
 
1
@@ -60,6 +60,7 @@
2
 #include "server.h"
3
 #include "stream.h"
4
 #include "utils.h"
5
+#include "flatpak-utils.h"
6
 
7
 #define LISTEN_BACKLOG 32
8
 #define MAX_CLIENTS 64
9
@@ -417,14 +418,47 @@
10
        client_access = server->client_access;
11
 
12
    if (server->addr.ss_family == AF_UNIX) {
13
+       char *app_id = NULL, *devices = NULL;
14
+
15
 #ifdef SO_PRIORITY
16
        val = 6;
17
        if (setsockopt(client_fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
18
            pw_log_warn("setsockopt(SO_PRIORITY) failed: %m");
19
 #endif
20
        pid = get_client_pid(client, client_fd);
21
-       if (pid != 0 && check_flatpak(client, pid) == 1)
22
+       if (pid != 0 && pw_check_flatpak(pid, &app_id, &devices) == 1) {
23
+           /*
24
+            * XXX: we should really use Portal client access here
25
+            *
26
+            * However, session managers currently support only camera
27
+            * permissions, and the XDG Portal doesn't have a "Sound Manager"
28
+            * permission defined. So for now, use access=flatpak, and determine
29
+            * extra permissions here.
30
+            *
31
+            * The application has access to the Pulseaudio socket,
32
+            * and with real PA it would always then have full sound access.
33
+            * We'll restrict the full access here behind devices=all;
34
+            * if the application can access all devices it can then
35
+            * also sound and camera devices directly, so granting also the
36
+            * Manager permissions here is reasonable.
37
+            *
38
+            * The "Manager" permission in any case is also currently not safe
39
+            * as the session manager does not check any permission store
40
+            * for it.
41
+            */
42
            client_access = "flatpak";
43
+           pw_properties_set(client->props, "pipewire.access.portal.app_id",
44
+                   app_id);
45
+
46
+           if (devices && (spa_streq(devices, "all") ||
47
+                           spa_strstartswith(devices, "all;") ||
48
+                           strstr(devices, ";all;")))
49
+               pw_properties_set(client->props, PW_KEY_MEDIA_CATEGORY, "Manager");
50
+           else
51
+               pw_properties_set(client->props, PW_KEY_MEDIA_CATEGORY, NULL);
52
+       }
53
+       free(devices);
54
+       free(app_id);
55
    }
56
    else if (server->addr.ss_family == AF_INET || server->addr.ss_family == AF_INET6) {
57
 
58
pipewire-0.3.56.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.57.tar.gz/src/modules/module-pulse-tunnel.c Changed
60
 
1
@@ -278,7 +278,7 @@
2
    } else {
3
        float error, corr;
4
 
5
-       error = (float)(impl->current_latency) - (float)impl->target_latency;
6
+       error = (float)impl->target_latency - (float)impl->current_latency;
7
        error = SPA_CLAMP(error, -impl->max_error, impl->max_error);
8
 
9
        corr = spa_dll_update(&impl->dll, error);
10
@@ -422,33 +422,47 @@
11
 static void context_state_cb(pa_context *c, void *userdata)
12
 {
13
    struct impl *impl = userdata;
14
+   bool do_destroy = false;
15
    switch (pa_context_get_state(c)) {
16
-   case PA_CONTEXT_READY:
17
    case PA_CONTEXT_TERMINATED:
18
    case PA_CONTEXT_FAILED:
19
+       do_destroy = true;
20
+       SPA_FALLTHROUGH;
21
+   case PA_CONTEXT_READY:
22
        pa_threaded_mainloop_signal(impl->pa_mainloop, 0);
23
        break;
24
    case PA_CONTEXT_UNCONNECTED:
25
+       do_destroy = true;
26
+       break;
27
    case PA_CONTEXT_CONNECTING:
28
    case PA_CONTEXT_AUTHORIZING:
29
    case PA_CONTEXT_SETTING_NAME:
30
        break;
31
    }
32
+   if (do_destroy)
33
+       pw_impl_module_schedule_destroy(impl->module);
34
 }
35
 
36
 static void stream_state_cb(pa_stream *s, void * userdata)
37
 {
38
    struct impl *impl = userdata;
39
+   bool do_destroy = false;
40
    switch (pa_stream_get_state(s)) {
41
-   case PA_STREAM_READY:
42
    case PA_STREAM_FAILED:
43
    case PA_STREAM_TERMINATED:
44
+       do_destroy = true;
45
+       SPA_FALLTHROUGH;
46
+   case PA_STREAM_READY:
47
        pa_threaded_mainloop_signal(impl->pa_mainloop, 0);
48
        break;
49
    case PA_STREAM_UNCONNECTED:
50
+       do_destroy = true;
51
+       break;
52
    case PA_STREAM_CREATING:
53
        break;
54
    }
55
+   if (do_destroy)
56
+       pw_impl_module_schedule_destroy(impl->module);
57
 }
58
 
59
 static void stream_read_request_cb(pa_stream *s, size_t length, void *userdata)
60
pipewire-0.3.56.tar.gz/src/modules/module-rt.c -> pipewire-0.3.57.tar.gz/src/modules/module-rt.c Changed
201
 
1
@@ -153,6 +153,11 @@
2
 #ifdef HAVE_DBUS
3
 #define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
4
 #define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
5
+#define RTKIT_INTERFACE "org.freedesktop.RealtimeKit1"
6
+
7
+#define XDG_PORTAL_SERVICE_NAME "org.freedesktop.portal.Desktop"
8
+#define XDG_PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
9
+#define XDG_PORTAL_INTERFACE "org.freedesktop.portal.Realtime"
10
 
11
 /** \cond */
12
 struct pw_rtkit_bus {
13
@@ -184,7 +189,11 @@
14
 
15
 #ifdef HAVE_DBUS
16
    bool use_rtkit;
17
-   struct pw_rtkit_bus *system_bus;
18
+   /* For D-Bus. These are const static. */
19
+   const char* service_name;
20
+   const char* object_path;
21
+   const char* interface;
22
+   struct pw_rtkit_bus *rtkit_bus;
23
 
24
    /* These are only for the RTKit implementation to fill in the `thread`
25
     * struct. Since there's barely any overhead here we'll do this
26
@@ -215,7 +224,7 @@
27
 }
28
 
29
 #ifdef HAVE_DBUS
30
-struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
31
+struct pw_rtkit_bus *pw_rtkit_bus_get(DBusBusType bus_type)
32
 {
33
    struct pw_rtkit_bus *bus;
34
    DBusError error;
35
@@ -231,7 +240,7 @@
36
    if (bus == NULL)
37
        return NULL;
38
 
39
-   bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
40
+   bus->bus = dbus_bus_get_private(bus_type, &error);
41
    if (bus->bus == NULL)
42
        goto error;
43
 
44
@@ -241,12 +250,41 @@
45
 
46
 error:
47
    free(bus);
48
-   pw_log_error("Failed to connect to system bus: %s", error.message);
49
+   pw_log_error("Failed to connect to %s bus: %s",
50
+            bus_type == DBUS_BUS_SYSTEM ? "system" : "session", error.message);
51
    dbus_error_free(&error);
52
    errno = ECONNREFUSED;
53
    return NULL;
54
 }
55
 
56
+struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
57
+{
58
+   return pw_rtkit_bus_get(DBUS_BUS_SYSTEM);
59
+}
60
+
61
+struct pw_rtkit_bus *pw_rtkit_bus_get_session(void)
62
+{
63
+   return pw_rtkit_bus_get(DBUS_BUS_SESSION);
64
+}
65
+
66
+bool pw_rtkit_check_xdg_portal(struct pw_rtkit_bus *system_bus)
67
+{
68
+   DBusError error;
69
+        bool ret = true;
70
+
71
+   dbus_error_init(&error);
72
+
73
+   if (!dbus_bus_name_has_owner(system_bus->bus, XDG_PORTAL_SERVICE_NAME, &error)) {
74
+       pw_log_warn("Can't find xdg-portal: %s", error.name);
75
+       ret = false;
76
+       goto finish;
77
+   }
78
+finish:
79
+   dbus_error_free(&error);
80
+
81
+   return ret;
82
+}
83
+
84
 void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
85
 {
86
    dbus_connection_close(system_bus->bus);
87
@@ -270,7 +308,7 @@
88
    return -EIO;
89
 }
90
 
91
-static long long rtkit_get_int_property(struct pw_rtkit_bus *connection, const char *propname,
92
+static long long rtkit_get_int_property(struct impl *impl, const char *propname,
93
                    long long *propval)
94
 {
95
    DBusMessage *m = NULL, *r = NULL;
96
@@ -280,19 +318,19 @@
97
    DBusError error;
98
    int current_type;
99
    long long ret;
100
-   const char *interfacestr = "org.freedesktop.RealtimeKit1";
101
+   struct pw_rtkit_bus *connection = impl->rtkit_bus;
102
 
103
    dbus_error_init(&error);
104
 
105
-   if (!(m = dbus_message_new_method_call(RTKIT_SERVICE_NAME,
106
-                          RTKIT_OBJECT_PATH,
107
+   if (!(m = dbus_message_new_method_call(impl->service_name,
108
+                          impl->object_path,
109
                           "org.freedesktop.DBus.Properties", "Get"))) {
110
        ret = -ENOMEM;
111
        goto finish;
112
    }
113
 
114
    if (!dbus_message_append_args(m,
115
-                     DBUS_TYPE_STRING, &interfacestr,
116
+                     DBUS_TYPE_STRING, &impl->interface,
117
                      DBUS_TYPE_STRING, &propname, DBUS_TYPE_INVALID)) {
118
        ret = -ENOMEM;
119
        goto finish;
120
@@ -349,60 +387,63 @@
121
    return ret;
122
 }
123
 
124
-int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection)
125
+int pw_rtkit_get_max_realtime_priority(struct impl *impl)
126
 {
127
    long long retval;
128
    int err;
129
 
130
-   err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
131
+   err = rtkit_get_int_property(impl, "MaxRealtimePriority", &retval);
132
    return err < 0 ? err : retval;
133
 }
134
 
135
-int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int *min_nice_level)
136
+int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level)
137
 {
138
    long long retval;
139
    int err;
140
 
141
-   err = rtkit_get_int_property(connection, "MinNiceLevel", &retval);
142
+   err = rtkit_get_int_property(impl, "MinNiceLevel", &retval);
143
    if (err >= 0)
144
        *min_nice_level = retval;
145
    return err;
146
 }
147
 
148
-long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection)
149
+long long pw_rtkit_get_rttime_usec_max(struct impl *impl)
150
 {
151
    long long retval;
152
    int err;
153
 
154
-   err = rtkit_get_int_property(connection, "RTTimeUSecMax", &retval);
155
+   err = rtkit_get_int_property(impl, "RTTimeUSecMax", &retval);
156
    return err < 0 ? err : retval;
157
 }
158
 
159
-int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority)
160
+int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority)
161
 {
162
    DBusMessage *m = NULL, *r = NULL;
163
+   dbus_uint64_t pid;
164
    dbus_uint64_t u64;
165
    dbus_uint32_t u32;
166
    DBusError error;
167
    int ret;
168
+   struct pw_rtkit_bus *connection = impl->rtkit_bus;
169
 
170
    dbus_error_init(&error);
171
 
172
    if (thread == 0)
173
        thread = _gettid();
174
 
175
-   if (!(m = dbus_message_new_method_call(RTKIT_SERVICE_NAME,
176
-                          RTKIT_OBJECT_PATH,
177
-                          "org.freedesktop.RealtimeKit1",
178
-                          "MakeThreadRealtime"))) {
179
+   if (!(m = dbus_message_new_method_call(impl->service_name,
180
+                          impl->object_path, impl->interface,
181
+                          "MakeThreadRealtimeWithPID"))) {
182
        ret = -ENOMEM;
183
        goto finish;
184
    }
185
 
186
+   pid = (dbus_uint64_t) getpid();
187
    u64 = (dbus_uint64_t) thread;
188
    u32 = (dbus_uint32_t) priority;
189
 
190
    if (!dbus_message_append_args(m,
191
+                     DBUS_TYPE_UINT64, &pid,
192
                      DBUS_TYPE_UINT64, &u64,
193
                      DBUS_TYPE_UINT32, &u32, DBUS_TYPE_INVALID)) {
194
        ret = -ENOMEM;
195
@@ -435,31 +476,34 @@
196
    return ret;
197
 }
198
 
199
-int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, int nice_level)
200
+int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level)
201
pipewire-0.3.56.tar.gz/src/pipewire/conf.c -> pipewire-0.3.57.tar.gz/src/pipewire/conf.c Changed
201
 
1
@@ -39,8 +39,10 @@
2
 #include <pwd.h>
3
 #endif
4
 #if defined(__FreeBSD__) || defined(__MidnightBSD__)
5
+#ifndef O_PATH
6
 #define O_PATH 0
7
 #endif
8
+#endif
9
 
10
 #include <spa/utils/result.h>
11
 #include <spa/utils/string.h>
12
@@ -190,6 +192,9 @@
13
        return -ENOENT;
14
    }
15
 
16
+   if (pw_check_option("no-config", "true"))
17
+       goto no_config;
18
+
19
    if ((res = get_envconf_path(path, size, prefix, name)) != 0) {
20
        if ((*level)++ == 0)
21
            return res;
22
@@ -198,20 +203,18 @@
23
 
24
    if (*level == 0) {
25
        (*level)++;
26
-       if ((res = get_confdata_path(path, size, prefix, name)) != 0)
27
+       if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
28
            return res;
29
    }
30
-   if (pw_check_option("no-config", "true"))
31
-       return 0;
32
-
33
    if (*level == 1) {
34
        (*level)++;
35
        if ((res = get_configdir_path(path, size, prefix, name)) != 0)
36
            return res;
37
    }
38
    if (*level == 2) {
39
+no_config:
40
        (*level)++;
41
-       if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
42
+       if ((res = get_confdata_path(path, size, prefix, name)) != 0)
43
            return res;
44
    }
45
    return 0;
46
@@ -405,12 +408,17 @@
47
 
48
    if (fstat(fd, &sbuf) < 0)
49
        goto error_close;
50
-   if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
51
-       goto error_close;
52
-   close(fd);
53
 
54
-   count = pw_properties_update_string(conf, data, sbuf.st_size);
55
-   munmap(data, sbuf.st_size);
56
+   if (sbuf.st_size > 0) {
57
+       if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
58
+           goto error_close;
59
+
60
+       count = pw_properties_update_string(conf, data, sbuf.st_size);
61
+       munmap(data, sbuf.st_size);
62
+   } else {
63
+       count = 0;
64
+   }
65
+   close(fd);
66
 
67
    pw_log_info("%p: loaded config '%s' with %d items", conf, path, count);
68
 
69
@@ -423,13 +431,33 @@
70
    return -errno;
71
 }
72
 
73
+static bool check_override(struct pw_properties *conf, const char *name, int level)
74
+{
75
+   const struct spa_dict_item *it;
76
+
77
+   spa_dict_for_each(it, &conf->dict) {
78
+       int lev, idx;
79
+
80
+       if (!spa_streq(name, it->value))
81
+           continue;
82
+       if (sscanf(it->key, "override.%d.%d.config.name", &lev, &idx) != 2)
83
+           continue;
84
+       if (lev < level)
85
+           return false;
86
+   }
87
+   return true;
88
+}
89
+
90
 static void add_override(struct pw_properties *conf, struct pw_properties *override,
91
-       const char *path, int level, int index)
92
+       const char *path, const char *name, int level, int index)
93
 {
94
    const struct spa_dict_item *it;
95
    char key1024;
96
+
97
    snprintf(key, sizeof(key), "override.%d.%d.config.path", level, index);
98
    pw_properties_set(conf, key, path);
99
+   snprintf(key, sizeof(key), "override.%d.%d.config.name", level, index);
100
+   pw_properties_set(conf, key, name);
101
    spa_dict_for_each(it, &override->dict) {
102
        snprintf(key, sizeof(key), "override.%d.%d.%s", level, index, it->key);
103
        pw_properties_set(conf, key, it->value);
104
@@ -488,10 +516,16 @@
105
            return -errno;
106
 
107
        for (i = 0; i < n; i++) {
108
-           snprintf(fname, sizeof(fname), "%s/%s", path, entriesi->d_name);
109
-           if (conf_load(fname, override) >= 0)
110
-               add_override(conf, override, fname, level, i);
111
-           pw_properties_clear(override);
112
+           const char *name = entriesi->d_name;
113
+
114
+           snprintf(fname, sizeof(fname), "%s/%s", path, name);
115
+           if (check_override(conf, name, level)) {
116
+               if (conf_load(fname, override) >= 0)
117
+                   add_override(conf, override, fname, name, level, i);
118
+               pw_properties_clear(override);
119
+           } else {
120
+               pw_log_info("skip override %s with lower priority", fname);
121
+           }
122
            free(entriesi);
123
        }
124
        free(entries);
125
@@ -891,6 +925,75 @@
126
    return 0;
127
 }
128
 
129
+static int try_load_conf(const char *conf_prefix, const char *conf_name,
130
+            struct pw_properties *conf)
131
+{
132
+   int res;
133
+
134
+   if (conf_name == NULL)
135
+       return -EINVAL;
136
+   if (spa_streq(conf_name, "null"))
137
+       return 0;
138
+   if ((res = pw_conf_load_conf(conf_prefix, conf_name, conf)) < 0) {
139
+       bool skip_prefix = conf_prefix == NULL || conf_name0 == '/';
140
+       pw_log_warn("can't load config %s%s%s: %s",
141
+               skip_prefix ? "" : conf_prefix,
142
+               skip_prefix ? "" : "/",
143
+               conf_name, spa_strerror(res));
144
+   }
145
+   return res;
146
+}
147
+
148
+SPA_EXPORT
149
+int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_properties *conf)
150
+{
151
+   const char *conf_prefix, *conf_name;
152
+   int res;
153
+
154
+   conf_prefix = getenv("PIPEWIRE_CONFIG_PREFIX");
155
+   if (conf_prefix == NULL)
156
+       conf_prefix = pw_properties_get(props, PW_KEY_CONFIG_PREFIX);
157
+
158
+   conf_name = getenv("PIPEWIRE_CONFIG_NAME");
159
+   if ((res = try_load_conf(conf_prefix, conf_name, conf)) < 0) {
160
+       conf_name = pw_properties_get(props, PW_KEY_CONFIG_NAME);
161
+       if ((res = try_load_conf(conf_prefix, conf_name, conf)) < 0) {
162
+           conf_name = "client.conf";
163
+           if ((res = try_load_conf(conf_prefix, conf_name, conf)) < 0) {
164
+               pw_log_error("can't load default config %s: %s",
165
+                   conf_name, spa_strerror(res));
166
+               return res;
167
+           }
168
+       }
169
+   }
170
+
171
+   conf_name = pw_properties_get(props, PW_KEY_CONFIG_OVERRIDE_NAME);
172
+   if (conf_name != NULL) {
173
+       struct pw_properties *override;
174
+       const char *path, *name;
175
+
176
+       override = pw_properties_new(NULL, NULL);
177
+       if (override == NULL) {
178
+           res = -errno;
179
+           return res;
180
+       }
181
+
182
+       conf_prefix = pw_properties_get(props, PW_KEY_CONFIG_OVERRIDE_PREFIX);
183
+       if ((res = try_load_conf(conf_prefix, conf_name, override)) < 0) {
184
+           pw_log_error("can't load default override config %s: %s",
185
+               conf_name, spa_strerror(res));
186
+           pw_properties_free (override);
187
+           return res;
188
+       }
189
+       path = pw_properties_get(override, "config.path");
190
+       name = pw_properties_get(override, "config.name");
191
+       add_override(conf, override, path, name, 0, 1);
192
+       pw_properties_free(override);
193
+   }
194
+
195
+   return res;
196
+}
197
+
198
 SPA_EXPORT
199
 int pw_context_conf_update_props(struct pw_context *context,
200
        const char *section, struct pw_properties *props)
201
pipewire-0.3.56.tar.gz/src/pipewire/conf.h -> pipewire-0.3.57.tar.gz/src/pipewire/conf.h Changed
9
 
1
@@ -33,6 +33,7 @@
2
  * \{
3
  */
4
 
5
+int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_properties *conf);
6
 int pw_conf_load_conf(const char *prefix, const char *name, struct pw_properties *conf);
7
 int pw_conf_load_state(const char *prefix, const char *name, struct pw_properties *conf);
8
 int pw_conf_save_state(const char *prefix, const char *name, const struct pw_properties *conf);
9
pipewire-0.3.56.tar.gz/src/pipewire/context.c -> pipewire-0.3.57.tar.gz/src/pipewire/context.c Changed
172
 
1
@@ -101,26 +101,6 @@
2
    pw_properties_set(properties, PW_KEY_CORE_NAME, context->core->info.name);
3
 }
4
 
5
-static int try_load_conf(struct pw_context *this, const char *conf_prefix,
6
-       const char *conf_name, struct pw_properties *conf)
7
-{
8
-   int res;
9
-
10
-   if (conf_name == NULL)
11
-       return -EINVAL;
12
-   if (spa_streq(conf_name, "null"))
13
-       return 0;
14
-   if ((res = pw_conf_load_conf(conf_prefix, conf_name, conf)) < 0) {
15
-       bool skip_prefix = conf_prefix == NULL || conf_name0 == '/';
16
-       pw_log_warn("%p: can't load config %s%s%s: %s",
17
-               this,
18
-               skip_prefix ? "" : conf_prefix,
19
-               skip_prefix ? "" : "/",
20
-               conf_name, spa_strerror(res));
21
-   }
22
-   return res;
23
-}
24
-
25
 static int context_set_freewheel(struct pw_context *context, bool freewheel)
26
 {
27
    struct spa_thread *thr;
28
@@ -211,7 +191,7 @@
29
 {
30
    struct impl *impl;
31
    struct pw_context *this;
32
-   const char *lib, *str, *conf_prefix, *conf_name;
33
+   const char *lib, *str;
34
    void *dbus_iface = NULL;
35
    uint32_t n_support;
36
    struct pw_properties *pr, *conf;
37
@@ -270,23 +250,8 @@
38
        goto error_free;
39
    }
40
    this->conf = conf;
41
-
42
-   conf_prefix = getenv("PIPEWIRE_CONFIG_PREFIX");
43
-   if (conf_prefix == NULL)
44
-       conf_prefix = pw_properties_get(properties, PW_KEY_CONFIG_PREFIX);
45
-
46
-   conf_name = getenv("PIPEWIRE_CONFIG_NAME");
47
-   if (try_load_conf(this, conf_prefix, conf_name, conf) < 0) {
48
-       conf_name = pw_properties_get(properties, PW_KEY_CONFIG_NAME);
49
-       if (try_load_conf(this, conf_prefix, conf_name, conf) < 0) {
50
-           conf_name = "client.conf";
51
-           if ((res = try_load_conf(this, conf_prefix, conf_name, conf)) < 0) {
52
-               pw_log_error("%p: can't load config %s: %s",
53
-                   this, conf_name, spa_strerror(res));
54
-               goto error_free;
55
-           }
56
-       }
57
-   }
58
+   if ((res = pw_conf_load_conf_for_context (properties, conf)) < 0)
59
+       goto error_free;
60
 
61
    n_support = pw_get_support(this->support, SPA_N_ELEMENTS(this->support) - 6);
62
    cpu = spa_support_find(this->support, n_support, SPA_TYPE_INTERFACE_CPU);
63
@@ -627,98 +592,6 @@
64
    return global;
65
 }
66
 
67
-/** Find a port to link with
68
- *
69
- * \param context a context
70
- * \param other_port a port to find a link with
71
- * \param id the id of a port or PW_ID_ANY
72
- * \param props extra properties
73
- * \param n_format_filters number of filters
74
- * \param format_filters array of format filters
75
- * \paramout error an error when something is wrong
76
- * \return a port that can be used to link to \a otherport or NULL on error
77
- */
78
-struct pw_impl_port *pw_context_find_port(struct pw_context *context,
79
-                 struct pw_impl_port *other_port,
80
-                 uint32_t id,
81
-                 struct pw_properties *props,
82
-                 uint32_t n_format_filters,
83
-                 struct spa_pod **format_filters,
84
-                 char **error)
85
-{
86
-   struct pw_impl_port *best = NULL;
87
-   bool have_id;
88
-   struct pw_impl_node *n;
89
-
90
-   have_id = id != PW_ID_ANY;
91
-
92
-   pw_log_debug("%p: id:%u", context, id);
93
-
94
-   spa_list_for_each(n, &context->node_list, link) {
95
-       if (n->global == NULL)
96
-           continue;
97
-
98
-       if (other_port->node == n)
99
-           continue;
100
-
101
-       if (!global_can_read(context, n->global))
102
-           continue;
103
-
104
-       pw_log_debug("%p: node id:%d", context, n->global->id);
105
-
106
-       if (have_id) {
107
-           if (n->global->id == id) {
108
-               pw_log_debug("%p: id:%u matches node %p", context, id, n);
109
-
110
-               best =
111
-                   pw_impl_node_find_port(n,
112
-                       pw_direction_reverse(other_port->direction),
113
-                       PW_ID_ANY);
114
-               if (best)
115
-                   break;
116
-           }
117
-       } else {
118
-           struct pw_impl_port *p, *pin, *pout;
119
-           uint8_t buf4096;
120
-           struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
121
-           struct spa_pod *dummy;
122
-
123
-           p = pw_impl_node_find_port(n,
124
-                   pw_direction_reverse(other_port->direction),
125
-                   PW_ID_ANY);
126
-           if (p == NULL)
127
-               continue;
128
-
129
-           if (p->direction == PW_DIRECTION_OUTPUT) {
130
-               pin = other_port;
131
-               pout = p;
132
-           } else {
133
-               pin = p;
134
-               pout = other_port;
135
-           }
136
-
137
-           if (pw_context_find_format(context,
138
-                       pout,
139
-                       pin,
140
-                       props,
141
-                       n_format_filters,
142
-                       format_filters,
143
-                       &dummy,
144
-                       &b,
145
-                       error) < 0) {
146
-               free(*error);
147
-               continue;
148
-           }
149
-           best = p;
150
-           break;
151
-       }
152
-   }
153
-   if (best == NULL) {
154
-       *error = spa_aprintf("No matching Node found");
155
-   }
156
-   return best;
157
-}
158
-
159
 SPA_PRINTF_FUNC(7, 8) int pw_context_debug_port_params(struct pw_context *this,
160
        struct spa_node *node, enum spa_direction direction,
161
        uint32_t port_id, uint32_t id, int err, const char *debug, ...)
162
@@ -1382,6 +1255,9 @@
163
             * panding change. Apply the change to the position now so
164
             * that we have the right values when we change the node
165
             * states of the driver and followers to RUNNING below */
166
+           pw_log_debug("%p: apply duration:%"PRIu64" rate:%u/%u", context,
167
+                   n->current_quantum, n->current_rate.num,
168
+                   n->current_rate.denom);
169
            n->rt.position->clock.duration = n->current_quantum;
170
            n->rt.position->clock.rate = n->current_rate;
171
            n->current_pending = false;
172
pipewire-0.3.56.tar.gz/src/pipewire/data-loop.c -> pipewire-0.3.57.tar.gz/src/pipewire/data-loop.c Changed
15
 
1
@@ -274,12 +274,7 @@
2
        spa_invoke_func_t func, uint32_t seq, const void *data, size_t size,
3
        bool block, void *user_data)
4
 {
5
-   int res;
6
-   if (loop->running)
7
-       res = pw_loop_invoke(loop->loop, func, seq, data, size, block, user_data);
8
-   else
9
-       res = func(loop->loop->loop, false, seq, data, size, user_data);
10
-   return res;
11
+   return pw_loop_invoke(loop->loop, func, seq, data, size, block, user_data);
12
 }
13
 
14
 /** Set a thread utils implementation.
15
pipewire-0.3.56.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.57.tar.gz/src/pipewire/impl-link.c Changed
22
 
1
@@ -281,8 +281,10 @@
2
    /* find a common format for the ports */
3
    if ((res = pw_context_find_format(context,
4
                    output, input, NULL, 0, NULL,
5
-                   &format, &b, &error)) < 0)
6
+                   &format, &b, &error)) < 0) {
7
+       format = NULL;
8
        goto error;
9
+   }
10
 
11
    format = spa_pod_copy(format);
12
    spa_pod_fixate(format);
13
@@ -1262,7 +1264,7 @@
14
        impl->inode = input_node;
15
    }
16
 
17
-   this->rt.target.signal = impl->inode->rt.target.signal;
18
+   this->rt.target.signal_func = impl->inode->rt.target.signal_func;
19
    this->rt.target.data = impl->inode->rt.target.data;
20
 
21
    pw_log_debug("%p: constructed out:%p:%d.%d -> in:%p:%d.%d", impl,
22
pipewire-0.3.56.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.57.tar.gz/src/pipewire/impl-node.c Changed
40
 
1
@@ -1047,7 +1047,7 @@
2
        if (pw_node_activation_state_dec(state, 1)) {
3
            a->status = PW_NODE_ACTIVATION_TRIGGERED;
4
            a->signal_time = nsec;
5
-           t->signal(t->data);
6
+           t->signal_func(t->data);
7
        }
8
    }
9
    return 0;
10
@@ -1145,7 +1145,7 @@
11
                this->name, this->info.id, cmd - 1);
12
 
13
        pw_log_trace_fp("%p: got process", this);
14
-       this->rt.target.signal(this->rt.target.data);
15
+       this->rt.target.signal_func(this->rt.target.data);
16
    }
17
 }
18
 
19
@@ -1262,9 +1262,9 @@
20
    this->rt.activation = this->activation->map->ptr;
21
    this->rt.target.activation = this->rt.activation;
22
    this->rt.target.node = this;
23
-   this->rt.target.signal = process_node;
24
+   this->rt.target.signal_func = process_node;
25
    this->rt.target.data = this;
26
-   this->rt.driver_target.signal = process_node;
27
+   this->rt.driver_target.signal_func = process_node;
28
 
29
    reset_position(this, &this->rt.activation->position);
30
    this->rt.activation->sync_timeout = DEFAULT_SYNC_TIMEOUT;
31
@@ -1613,7 +1613,7 @@
32
                        state->pending, state->required);
33
                dump_states(node);
34
            }
35
-           node->rt.target.signal(node->rt.target.data);
36
+           node->rt.target.signal_func(node->rt.target.data);
37
        }
38
 
39
        if (node->current_pending) {
40
pipewire-0.3.56.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.57.tar.gz/src/pipewire/impl-port.c Changed
59
 
1
@@ -209,6 +209,7 @@
2
 int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mix)
3
 {
4
    uint32_t port_id;
5
+   struct pw_impl_node *node = port->node;
6
    int res = 0;
7
 
8
    port_id = pw_map_insert_new(&port->mix_port_map, mix);
9
@@ -252,6 +253,13 @@
10
            port->n_mix, port->port_id, mix->port.port_id,
11
            mix->io, spa_strerror(res));
12
 
13
+   if (port->n_mix == 1) {
14
+       pw_log_debug("%p: setting port io", port);
15
+       spa_node_port_set_io(node->node,
16
+                    port->direction, port->port_id,
17
+                    SPA_IO_Buffers,
18
+                    &port->rt.io, sizeof(port->rt.io));
19
+   }
20
    return res;
21
 
22
 error_remove_port:
23
@@ -266,6 +274,7 @@
24
 {
25
    int res = 0;
26
    uint32_t port_id = mix->port.port_id;
27
+   struct pw_impl_node *node = port->node;
28
 
29
    pw_map_remove(&port->mix_port_map, port_id);
30
    spa_list_remove(&mix->link);
31
@@ -280,6 +289,13 @@
32
    pw_log_debug("%p: release mix %d %d.%d", port,
33
            port->n_mix, port->port_id, mix->port.port_id);
34
 
35
+   if (port->n_mix == 0) {
36
+       pw_log_debug("%p: clearing port io", port);
37
+       spa_node_port_set_io(node->node,
38
+                    port->direction, port->port_id,
39
+                    SPA_IO_Buffers,
40
+                    NULL, sizeof(port->rt.io));
41
+   }
42
    return res;
43
 }
44
 
45
@@ -1025,12 +1041,7 @@
46
    if (control) {
47
        pw_log_debug("%p: setting node control", port);
48
    } else {
49
-       pw_log_debug("%p: setting node io", port);
50
-       spa_node_port_set_io(node->node,
51
-                    port->direction, port->port_id,
52
-                    SPA_IO_Buffers,
53
-                    &port->rt.io, sizeof(port->rt.io));
54
-
55
+       pw_log_debug("%p: setting mixer io", port);
56
        spa_node_port_set_io(port->mix,
57
                 pw_direction_reverse(port->direction), 0,
58
                 SPA_IO_Buffers,
59
pipewire-0.3.56.tar.gz/src/pipewire/keys.h -> pipewire-0.3.57.tar.gz/src/pipewire/keys.h Changed
22
 
1
@@ -76,6 +76,8 @@
2
 /* config */
3
 #define PW_KEY_CONFIG_PREFIX       "config.prefix"     /**< a config prefix directory */
4
 #define PW_KEY_CONFIG_NAME     "config.name"       /**< a config file name */
5
+#define PW_KEY_CONFIG_OVERRIDE_PREFIX  "config.override.prefix"    /**< a config override prefix directory */
6
+#define PW_KEY_CONFIG_OVERRIDE_NAME    "config.override.name"  /**< a config override file name */
7
 
8
 /* context */
9
 #define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules"   /**< a context profile for modules, deprecated */
10
@@ -170,7 +172,10 @@
11
 #define PW_KEY_NODE_FORCE_RATE     "node.force-rate"   /**< force a rate while the node is
12
                                  *  active */
13
 
14
-#define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect"   /**< don't reconnect this node */
15
+#define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect"   /**< don't reconnect this node. The node is
16
+                                 *  initially linked to node.target or
17
+                                 *  target.object or the default node. If the
18
+                                 *  targets is removed, the node is destroyed */
19
 #define PW_KEY_NODE_ALWAYS_PROCESS "node.always-process"   /**< process even when unlinked */
20
 #define PW_KEY_NODE_WANT_DRIVER        "node.want-driver"  /**< the node wants to be grouped with a driver
21
                                  *  node in order to schedule the graph. */
22
pipewire-0.3.56.tar.gz/src/pipewire/mem.c -> pipewire-0.3.57.tar.gz/src/pipewire/mem.c Changed
28
 
1
@@ -485,7 +485,12 @@
2
    spa_list_init(&b->memmaps);
3
 
4
 #ifdef HAVE_MEMFD_CREATE
5
-   b->this.fd = memfd_create("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
6
+   char name128;
7
+   snprintf(name, sizeof(name),
8
+        "pipewire-memfd:flags=0x%08x,type=%" PRIu32 ",size=%zu",
9
+        (unsigned int) flags, type, size);
10
+
11
+   b->this.fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
12
    if (b->this.fd == -1) {
13
        res = -errno;
14
        pw_log_error("%p: Failed to create memfd: %m", pool);
15
@@ -499,7 +504,11 @@
16
        goto error_free;
17
    }
18
 #else
19
-   char filename = "/dev/shm/pipewire-tmpfile.XXXXXX";
20
+   char filename128;
21
+   snprintf(filename, sizeof(filename),
22
+        "/dev/shm/pipewire-tmpfile:flags=0x%08x,type=%" PRIu32 ",size=%zu:XXXXXX",
23
+        (unsigned int) flags, type, size);
24
+
25
    b->this.fd = mkostemp(filename, O_CLOEXEC);
26
    if (b->this.fd == -1) {
27
        res = -errno;
28
pipewire-0.3.56.tar.gz/src/pipewire/meson.build -> pipewire-0.3.57.tar.gz/src/pipewire/meson.build Changed
10
 
1
@@ -94,7 +94,7 @@
2
   '-DOLD_MEDIA_SESSION_WORKAROUND=1'
3
 
4
 
5
-if build_machine.system() != 'freebsd' and build_machine.system() != 'midnightbsd'
6
+if host_machine.system() != 'freebsd' and host_machine.system() != 'midnightbsd'
7
   libpipewire_c_args += 
8
     '-D_POSIX_C_SOURCE'
9
   
10
pipewire-0.3.56.tar.gz/src/pipewire/private.h -> pipewire-0.3.57.tar.gz/src/pipewire/private.h Changed
27
 
1
@@ -573,7 +573,7 @@
2
    struct spa_list link;
3
    struct pw_impl_node *node;
4
    struct pw_node_activation *activation;
5
-   int (*signal) (void *data);
6
+   int (*signal_func) (void *data);
7
    void *data;
8
    unsigned int active:1;
9
 };
10
@@ -1153,16 +1153,6 @@
11
            struct spa_pod_builder *builder,
12
            char **error);
13
 
14
-/** Find a ports compatible with \a other_port and the format filters */
15
-struct pw_impl_port *
16
-pw_context_find_port(struct pw_context *context,
17
-         struct pw_impl_port *other_port,
18
-         uint32_t id,
19
-         struct pw_properties *props,
20
-         uint32_t n_format_filters,
21
-         struct spa_pod **format_filters,
22
-         char **error);
23
-
24
 int pw_context_debug_port_params(struct pw_context *context,
25
        struct spa_node *node, enum spa_direction direction,
26
        uint32_t port_id, uint32_t id, int err, const char *debug, ...);
27
pipewire-0.3.56.tar.gz/src/pipewire/stream.c -> pipewire-0.3.57.tar.gz/src/pipewire/stream.c Changed
49
 
1
@@ -1261,11 +1261,9 @@
2
    {
3
        struct spa_pod_prop *prop;
4
        struct spa_pod_object *obj = (struct spa_pod_object *) param;
5
-       union {
6
-           float f;
7
-           double d;
8
-           bool b;
9
-       } value;
10
+       float value_f;
11
+       double value_d;
12
+       bool value_b;
13
        float *values;
14
        uint32_t i, n_values;
15
 
16
@@ -1278,24 +1276,24 @@
17
 
18
            switch (c->container) {
19
            case SPA_TYPE_Float:
20
-               if (spa_pod_get_float(&prop->value, &value.f) < 0)
21
+               if (spa_pod_get_float(&prop->value, &value_f) < 0)
22
                    continue;
23
                n_values = 1;
24
-               values = &value.f;
25
+               values = &value_f;
26
                break;
27
            case SPA_TYPE_Double:
28
-               if (spa_pod_get_double(&prop->value, &value.d) < 0)
29
+               if (spa_pod_get_double(&prop->value, &value_d) < 0)
30
                    continue;
31
                n_values = 1;
32
-               value.f = value.d;
33
-               values = &value.f;
34
+               value_f = value_d;
35
+               values = &value_f;
36
                break;
37
            case SPA_TYPE_Bool:
38
-               if (spa_pod_get_bool(&prop->value, &value.b) < 0)
39
+               if (spa_pod_get_bool(&prop->value, &value_b) < 0)
40
                    continue;
41
-               value.f = value.b ? 1.0f : 0.0f;
42
+               value_f = value_b ? 1.0f : 0.0f;
43
                n_values = 1;
44
-               values = &value.f;
45
+               values = &value_f;
46
                break;
47
            case SPA_TYPE_Array:
48
                if ((values = spa_pod_get_array(&prop->value, &n_values)) == NULL ||
49
pipewire-0.3.56.tar.gz/src/pipewire/utils.c -> pipewire-0.3.57.tar.gz/src/pipewire/utils.c Changed
19
 
1
@@ -154,6 +154,7 @@
2
 ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags)
3
 {
4
    ssize_t bytes;
5
+   int read_errno;
6
 
7
 #ifdef HAVE_GETRANDOM
8
    bytes = getrandom(buf, buflen, flags);
9
@@ -165,7 +166,9 @@
10
    if (fd < 0)
11
        return -1;
12
    bytes = read(fd, buf, buflen);
13
+   read_errno = errno;
14
    close(fd);
15
+   errno = read_errno;
16
    return bytes;
17
 }
18
 
19
pipewire-0.3.56.tar.gz/src/pipewire/utils.h -> pipewire-0.3.57.tar.gz/src/pipewire/utils.h Changed
9
 
1
@@ -86,6 +86,7 @@
2
    })
3
 #endif
4
 
5
+SPA_WARN_UNUSED_RESULT
6
 ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags);
7
 
8
 void* pw_reallocarray(void *ptr, size_t nmemb, size_t size);
9
pipewire-0.3.56.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.57.tar.gz/src/tools/pw-cat.c Changed
17
 
1
@@ -1663,6 +1663,7 @@
2
        pw_stream_destroy(data.stream);
3
    }
4
 error_no_stream:
5
+error_bad_file:
6
    spa_hook_remove(&data.core_listener);
7
    pw_core_disconnect(data.core);
8
 error_ctx_connect_failed:
9
@@ -1671,7 +1672,6 @@
10
    pw_main_loop_destroy(data.loop);
11
 error_no_props:
12
 error_no_main_loop:
13
-error_bad_file:
14
    pw_properties_free(data.props);
15
    if (data.file)
16
        sf_close(data.file);
17
pipewire-0.3.56.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.57.tar.gz/src/tools/pw-cli.c Changed
201
 
1
@@ -226,7 +226,6 @@
2
 static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
3
 static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
4
 static bool do_send_command(struct data *data, const char *cmd, char *args, char **error);
5
-static bool do_dump(struct data *data, const char *cmd, char *args, char **error);
6
 static bool do_quit(struct data *data, const char *cmd, char *args, char **error);
7
 
8
 #define DUMP_NAMES "Core|Module|Device|Node|Port|Factory|Client|Link|Session|Endpoint|EndpointStream"
9
@@ -251,8 +250,6 @@
10
    { "permissions", "sp", "Set permissions for a client <client-id> <object> <permission>", do_permissions },
11
    { "get-permissions", "gp", "Get permissions of a client <client-id>", do_get_permissions },
12
    { "send-command", "c", "Send a command <object-id>", do_send_command },
13
-   { "dump", "D", "Dump objects in ways that are cleaner for humans to understand "
14
-        "short|deep|resolve|notype -sdrt all|"DUMP_NAMES"|<id>", do_dump },
15
    { "quit", "q", "Quit", do_quit },
16
 };
17
 
18
@@ -269,7 +266,10 @@
19
 
20
    printf("Available commands:\n");
21
    for (i = 0; i < SPA_N_ELEMENTS(command_list); i++) {
22
-       printf("\t%-20.20s\t%s\n", command_listi.name, command_listi.description);
23
+       char cmd256;
24
+       snprintf(cmd, sizeof(cmd), "%s | %s",
25
+               command_listi.name, command_listi.alias);
26
+       printf("\t%-20.20s\t%s\n", cmd, command_listi.description);
27
    }
28
    return true;
29
 }
30
@@ -1929,20 +1929,6 @@
31
    return true;
32
 }
33
 
34
-static const char *
35
-pw_interface_short(const char *type)
36
-{
37
-   size_t ilen;
38
-
39
-   ilen = strlen(PW_TYPE_INFO_INTERFACE_BASE);
40
-
41
-   if (!type || strlen(type) <= ilen ||
42
-       memcmp(type, PW_TYPE_INFO_INTERFACE_BASE, ilen))
43
-       return NULL;
44
-
45
-   return type + ilen;
46
-}
47
-
48
 static struct global *
49
 obj_global(struct remote_data *rd, uint32_t id)
50
 {
51
@@ -2001,20 +1987,6 @@
52
    return NULL;
53
 }
54
 
55
-static struct spa_dict *
56
-obj_props(struct remote_data *rd, uint32_t id)
57
-{
58
-   struct global *global;
59
-
60
-   if (!rd)
61
-       return NULL;
62
-
63
-   global = obj_global(rd, id);
64
-   if (!global)
65
-       return NULL;
66
-   return global_props(global);
67
-}
68
-
69
 static const char *
70
 global_lookup(struct global *global, const char *key)
71
 {
72
@@ -2026,16 +1998,6 @@
73
    return spa_dict_lookup(dict, key);
74
 }
75
 
76
-static const char *
77
-obj_lookup(struct remote_data *rd, uint32_t id, const char *key)
78
-{
79
-   struct spa_dict *dict;
80
-
81
-   dict = obj_props(rd, id);
82
-   if (!dict)
83
-       return NULL;
84
-   return spa_dict_lookup(dict, key);
85
-}
86
 
87
 static int
88
 children_of(struct remote_data *rd, uint32_t parent_id,
89
@@ -2135,67 +2097,6 @@
90
    return count;
91
 }
92
 
93
-#ifndef BIT
94
-#define BIT(x) (1U << (x))
95
-#endif
96
-
97
-enum dump_flags {
98
-   is_default = 0,
99
-   is_short = BIT(0),
100
-   is_deep = BIT(1),
101
-   is_resolve = BIT(2),
102
-   is_notype = BIT(3)
103
-};
104
-
105
-static const char * const dump_types = {
106
-   PW_TYPE_INTERFACE_Core,
107
-   PW_TYPE_INTERFACE_Module,
108
-   PW_TYPE_INTERFACE_Device,
109
-   PW_TYPE_INTERFACE_Node,
110
-   PW_TYPE_INTERFACE_Port,
111
-   PW_TYPE_INTERFACE_Factory,
112
-   PW_TYPE_INTERFACE_Client,
113
-   PW_TYPE_INTERFACE_Link,
114
-   PW_TYPE_INTERFACE_Session,
115
-   PW_TYPE_INTERFACE_Endpoint,
116
-   PW_TYPE_INTERFACE_EndpointStream,
117
-};
118
-
119
-int dump_type_index(const char *type)
120
-{
121
-   unsigned int i;
122
-
123
-   if (!type)
124
-       return -1;
125
-
126
-   for (i = 0; i < SPA_N_ELEMENTS(dump_types); i++) {
127
-       if (spa_streq(dump_typesi, type))
128
-           return (int)i;
129
-   }
130
-
131
-   return -1;
132
-}
133
-
134
-static inline unsigned int dump_type_count(void)
135
-{
136
-   return SPA_N_ELEMENTS(dump_types);
137
-}
138
-
139
-static const char *name_to_dump_type(const char *name)
140
-{
141
-   unsigned int i;
142
-
143
-   if (!name)
144
-       return NULL;
145
-
146
-   for (i = 0; i < SPA_N_ELEMENTS(dump_types); i++) {
147
-       if (!strcasecmp(name, pw_interface_short(dump_typesi)))
148
-           return dump_typesi;
149
-   }
150
-
151
-   return NULL;
152
-}
153
-
154
 #define INDENT(_level) \
155
    ({ \
156
        int __level = (_level); \
157
@@ -2205,817 +2106,6 @@
158
        (const char *)_indent; \
159
    })
160
 
161
-static void
162
-dump(struct data *data, struct global *global,
163
-     enum dump_flags flags, int level);
164
-
165
-static void
166
-dump_properties(struct data *data, struct global *global,
167
-       enum dump_flags flags, int level)
168
-{
169
-   struct remote_data *rd = data->current;
170
-   struct spa_dict *props;
171
-   const struct spa_dict_item *item;
172
-   const char *ind;
173
-   int id;
174
-   const char *extra;
175
-
176
-   if (!global)
177
-       return;
178
-
179
-   props = global_props(global);
180
-   if (!props || !props->n_items)
181
-       return;
182
-
183
-   ind = INDENT(level + 2);
184
-   spa_dict_for_each(item, props) {
185
-       printf("%s%s = \"%s\"",
186
-               ind, item->key, item->value);
187
-
188
-       extra = NULL;
189
-       if (spa_streq(global->type, PW_TYPE_INTERFACE_Port) && spa_streq(item->key, PW_KEY_NODE_ID)) {
190
-           id = atoi(item->value);
191
-           if (id >= 0)
192
-               extra = obj_lookup(rd, id, PW_KEY_NODE_NAME);
193
-       } else if (spa_streq(global->type, PW_TYPE_INTERFACE_Factory) && spa_streq(item->key, PW_KEY_MODULE_ID)) {
194
-           id = atoi(item->value);
195
-           if (id >= 0)
196
-               extra = obj_lookup(rd, id, PW_KEY_MODULE_NAME);
197
-       } else if (spa_streq(global->type, PW_TYPE_INTERFACE_Device) && spa_streq(item->key, PW_KEY_FACTORY_ID)) {
198
-           id = atoi(item->value);
199
-           if (id >= 0)
200
-               extra = obj_lookup(rd, id, PW_KEY_FACTORY_NAME);
201
pipewire-0.3.56.tar.gz/test/test-spa-utils.c -> pipewire-0.3.57.tar.gz/test/test-spa-utils.c Changed
14
 
1
@@ -419,6 +419,12 @@
2
    }
3
    pwtest_int_eq(count, 4);
4
    pwtest_int_eq(hook_free_count, 4);
5
+
6
+   /* remove a zeroed hook */
7
+   struct spa_hook hook;
8
+   spa_zero(hook);
9
+   spa_hook_remove(&hook);
10
+
11
    return PWTEST_PASS;
12
 }
13
 
14