Changes of Revision 23

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Mon Mar 13 12:30:13 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.66
6
+
7
+-------------------------------------------------------------------
8
 Thu Jan 26 20:45:06 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.65
11
pipewire-aptx.spec Changed
10
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        0.3.65
6
+Version:        0.3.66
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/libcamera-client.c Deleted
201
 
1
@@ -1,247 +0,0 @@
2
-/* Spa libcamera client
3
- *
4
- * Copyright (C) 2020, Collabora Ltd.
5
- *     Author: Raghavendra Rao Sidlagatta <raghavendra.rao@collabora.com>
6
- *
7
- * libcamera-client.c
8
- *
9
- * Permission is hereby granted, free of charge, to any person obtaining a
10
- * copy of this software and associated documentation files (the "Software"),
11
- * to deal in the Software without restriction, including without limitation
12
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
- * and/or sell copies of the Software, and to permit persons to whom the
14
- * Software is furnished to do so, subject to the following conditions:
15
- *
16
- * The above copyright notice and this permission notice (including the next
17
- * paragraph) shall be included in all copies or substantial portions of the
18
- * Software.
19
- *
20
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
- * DEALINGS IN THE SOFTWARE.
27
- */
28
-
29
-#include <errno.h>
30
-#include <stddef.h>
31
-#include <stdio.h>
32
-#include <sys/types.h>
33
-#include <sys/stat.h>
34
-#include <fcntl.h>
35
-
36
-#include <spa/support/log.h>
37
-#include <spa/support/loop.h>
38
-#include <spa/support/plugin.h>
39
-#include <spa/utils/type.h>
40
-#include <spa/utils/keys.h>
41
-#include <spa/utils/names.h>
42
-#include <spa/utils/string.h>
43
-#include <spa/monitor/device.h>
44
-#include <spa/monitor/utils.h>
45
-
46
-#include "libcamera.h"
47
-
48
-struct impl {
49
-   struct spa_handle handle;
50
-   struct spa_device device;
51
-
52
-   struct spa_log *log;
53
-   struct spa_loop *main_loop;
54
-
55
-   struct spa_hook_list hooks;
56
-
57
-   uint64_t info_all;
58
-   struct spa_device_info info;
59
-
60
-   struct spa_source source;
61
-};
62
-
63
-static int emit_object_info(struct impl *this, uint32_t id)
64
-{
65
-   struct spa_device_object_info info;
66
-   struct spa_dict_item items20;
67
-   uint32_t n_items = 0;
68
-
69
-   info = SPA_DEVICE_OBJECT_INFO_INIT();
70
-
71
-   info.type = SPA_TYPE_INTERFACE_Device;
72
-   info.factory_name = SPA_NAME_API_LIBCAMERA_DEVICE;
73
-   info.change_mask = (SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS |
74
-       SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS);
75
-   info.flags = 0;
76
-
77
-   itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_ENUM_API,"libcamera-client");
78
-   itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "libcamera");
79
-   itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Video/Device");
80
-
81
-   info.props = &SPA_DICT_INIT(items, n_items);
82
-   spa_device_emit_object_info(&this->hooks, id, &info);
83
-
84
-   return 1;
85
-}
86
-
87
-static const struct spa_dict_item device_info_items = {
88
-   { SPA_KEY_DEVICE_API, "libcamera" },
89
-   { SPA_KEY_DEVICE_NICK, "libcamera-client" },
90
-   { SPA_KEY_API_UDEV_MATCH, "libcamera" },
91
-};
92
-
93
-
94
-static void emit_device_info(struct impl *this, bool full)
95
-{
96
-   uint64_t old = full ? this->info.change_mask : 0;
97
-   if (full)
98
-       this->info.change_mask = this->info_all;
99
-   if (this->info.change_mask) {
100
-       this->info.props = &SPA_DICT_INIT_ARRAY(device_info_items);
101
-       spa_device_emit_info(&this->hooks, &this->info);
102
-       this->info.change_mask = old;
103
-   }
104
-}
105
-
106
-static void impl_hook_removed(struct spa_hook *hook)
107
-{
108
-   return;
109
-}
110
-
111
-static int
112
-impl_device_add_listener(void *object, struct spa_hook *listener,
113
-       const struct spa_device_events *events, void *data)
114
-{
115
-   struct impl *this = object;
116
-   struct spa_hook_list save;
117
-
118
-   spa_return_val_if_fail(this != NULL, -EINVAL);
119
-   spa_return_val_if_fail(events != NULL, -EINVAL);
120
-
121
-   spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
122
-
123
-   emit_device_info(this, true);
124
-
125
-   emit_object_info(this, 0);
126
-
127
-   spa_hook_list_join(&this->hooks, &save);
128
-
129
-   listener->removed = impl_hook_removed;
130
-   listener->priv = this;
131
-
132
-   return 0;
133
-}
134
-
135
-static const struct spa_device_methods impl_device = {
136
-   SPA_VERSION_DEVICE_METHODS,
137
-   .add_listener = impl_device_add_listener,
138
-};
139
-
140
-static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface)
141
-{
142
-   struct impl *this;
143
-
144
-   spa_return_val_if_fail(handle != NULL, -EINVAL);
145
-   spa_return_val_if_fail(interface != NULL, -EINVAL);
146
-
147
-   this = (struct impl *) handle;
148
-
149
-   if (spa_streq(type, SPA_TYPE_INTERFACE_Device))
150
-       *interface = &this->device;
151
-   else
152
-       return -ENOENT;
153
-
154
-   return 0;
155
-}
156
-
157
-static int impl_clear(struct spa_handle *handle)
158
-{
159
-   struct impl *this = (struct impl *) handle;
160
-
161
-   if(this->dev.camera) {
162
-       deleteLibCamera(this->dev.camera);
163
-       this->dev.camera = NULL;
164
-   }
165
-   return 0;
166
-}
167
-
168
-static size_t
169
-impl_get_size(const struct spa_handle_factory *factory,
170
-         const struct spa_dict *params)
171
-{
172
-   return sizeof(struct impl);
173
-}
174
-
175
-static int
176
-impl_init(const struct spa_handle_factory *factory,
177
-     struct spa_handle *handle,
178
-     const struct spa_dict *info,
179
-     const struct spa_support *support,
180
-     uint32_t n_support)
181
-{
182
-   struct impl *this;
183
-
184
-   spa_return_val_if_fail(factory != NULL, -EINVAL);
185
-   spa_return_val_if_fail(handle != NULL, -EINVAL);
186
-
187
-   handle->get_interface = impl_get_interface;
188
-   handle->clear = impl_clear;
189
-
190
-   this = (struct impl *) handle;
191
-
192
-   this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
193
-   libcamera_log_topic_init(this->log);
194
-
195
-   this->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
196
-
197
-   if (this->main_loop == NULL) {
198
-       spa_log_error(this->log, "a main-loop is needed");
199
-       return -EINVAL;
200
-   }
201
pipewire-0.3.65.tar.gz/.gitignore -> pipewire-0.3.66.tar.gz/.gitignore Changed
13
 
1
@@ -15,6 +15,11 @@
2
 subprojects/wireplumber
3
 subprojects/media-session
4
 subprojects/packagecache
5
+subprojects/googletest*
6
+subprojects/gtest.wrap
7
+subprojects/libyaml.wrap
8
+subprojects/libyaml
9
+subprojects/libcamera
10
 
11
 # Created by https://www.gitignore.io/api/vim
12
 
13
pipewire-0.3.65.tar.gz/.gitlab-ci.yml -> pipewire-0.3.66.tar.gz/.gitlab-ci.yml Changed
18
 
1
@@ -25,7 +25,7 @@
2
 .fedora:
3
   variables:
4
     # Update this tag when you want to trigger a rebuild
5
-    FDO_DISTRIBUTION_TAG: '2022-11-07.0'
6
+    FDO_DISTRIBUTION_TAG: '2023-01-18.0'
7
     FDO_DISTRIBUTION_VERSION: '35'
8
     FDO_DISTRIBUTION_PACKAGES: >-
9
       alsa-lib-devel
10
@@ -46,6 +46,7 @@
11
       jack-audio-connection-kit-devel
12
       libcanberra-devel
13
       libldac-devel
14
+      libmysofa-devel
15
       libsndfile-devel
16
       libusb-devel
17
       lilv-devel
18
pipewire-0.3.65.tar.gz/NEWS -> pipewire-0.3.66.tar.gz/NEWS Changed
93
 
1
@@ -1,3 +1,81 @@
2
+# PipeWire 0.3.66 (2023-02-16)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - Fix a regression in the pulseaudio module-combine-stream because the new
9
+    module-combine-stream was not installed.
10
+  - PipeWire can now generate a limits.d config file with our recommended
11
+    settings for priorities and memlock.
12
+
13
+
14
+## PipeWire
15
+  - Avoid rate switches when the graph is idle.
16
+  - The rate selection algorithm was improved. This ensures minimal performance
17
+    and quality loss when resampling.
18
+  - The default min.quantum was set to 32 again after it got erronously changed
19
+    to (the too low) 16 in version 0.3.45.
20
+  - Fix compilation issues with rust bindings because of macros in defines.
21
+    Work around it for now. (#2952)
22
+  - Invalid file mappings are now refused (#2617 #2914 #3007)
23
+  - Modules, exec and objects can now be loaded depending on conditions. One
24
+    example is the X11-bell module that can now be disabled with a custom
25
+    property override.
26
+  - Filter now also supports _trigger_process() to drive the graph.
27
+  - TID is now added to the journald log.
28
+  - PipeWire generates and installs */etc/security/limits.d/25-pw-rlimits.conf*
29
+    that by default contains project's recommended settings. Creation of the
30
+    pipewire group is left to the distro or user ( `groupadd -r pipewire` ).
31
+    See the rlimits-* Meson options for controlling this behavior.
32
+  - Additionally there is now by default disabled Meson option that will
33
+    install */etc/security/limits.d/20-pw-defaults.conf* with the current Linux
34
+    default memlock value. Distros with only kernels >=5.16 or always using
35
+    systemd v251 or newer do not need this. But all other builds should set the
36
+    `-Dpam-defaults-install=true` Meson option to ensure that the memlock value
37
+    is always large enough. Thanks to Rickie Schroeder for pointing out that
38
+    the default Linux memlock value has been somewhat recently increased.
39
+
40
+## modules
41
+  - Install module-combine-stream.
42
+  - RTP source now has support for custom channel names.
43
+  - RTP source will now stop when inactive.
44
+  - There is now
45
+  - Filter-chain has a new mysofa based spacializer plugin.
46
+  - The RTP modules can now use direct clock timestamps to send and receive
47
+    packets. This makes it possible to synchronize sender and receiver with
48
+    a PTP clock, for example.
49
+  - Filter-chain now has an invert plugin to invert the polarity of a
50
+    signal. (#3008)
51
+
52
+## SPA
53
+  - There is now an option to set the channels used for probing Pro Audio
54
+    devices. This could unlock more samplerates for some devices when they are
55
+    probed with fewer channels. (#2990)
56
+  - Support was added for other clocks than the MONOTONIC clock in the
57
+    driver nodes. This can be used to synchronize the graph to a PTP clock,
58
+    for example.
59
+  - The ALSA source has some more headroom when rate matching to avoid
60
+    stuttering when following another driver.
61
+  - libcamera controls are now mapped to standard PipeWire property values.
62
+  - The channelmixer has seen some improvements. MONO and undefined channel
63
+    layouts are now upmixed and downmixed more correctly. (#3010)
64
+
65
+## Bluetooth
66
+  - Many BAP support fixes.
67
+
68
+## GStreamer
69
+  - The gstreamer elements now support buffer video metadata so that strides
70
+    are correctly handled.
71
+  - pipewiresrc will now error out correctly in more cases. (#2935)
72
+
73
+## JACK
74
+  - The frame to/from time functions are improved to also work with negative
75
+    time and frame offsets.
76
+
77
+Older versions:
78
+
79
+
80
 # PipeWire 0.3.65 (2023-01-26)
81
 
82
 This is a bugfix release that is API and ABI compatible with previous
83
@@ -109,9 +187,6 @@
84
     this.
85
   - pipewiresrc will now always be a live source unless told otherwise.
86
 
87
-Older versions:
88
-
89
-
90
 # PipeWire 0.3.64 (2023-01-12)
91
 
92
 This is a bugfix release that is API and ABI compatible with previous
93
pipewire-0.3.65.tar.gz/meson.build -> pipewire-0.3.66.tar.gz/meson.build Changed
18
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.65',
4
+  version : '0.3.66',
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
@@ -285,6 +285,9 @@
9
 sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile'))
10
 summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')
11
 cdata.set('HAVE_SNDFILE', sndfile_dep.found())
12
+libmysofa_dep = dependency('libmysofa', required : get_option('libmysofa'))
13
+summary({'libmysofa': libmysofa_dep.found()}, bool_yn: true, section: 'filter-chain')
14
+cdata.set('HAVE_LIBMYSOFA', libmysofa_dep.found())
15
 pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
16
 summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
17
 avahi_dep = dependency('avahi-client', required : get_option('avahi'))
18
pipewire-0.3.65.tar.gz/meson_options.txt -> pipewire-0.3.66.tar.gz/meson_options.txt Changed
49
 
1
@@ -213,6 +213,10 @@
2
        description: 'Enable code that depends on libsndfile',
3
        type: 'feature',
4
        value: 'auto')
5
+option('libmysofa',
6
+       description: 'Enable code that depends on libmysofa',
7
+       type: 'feature',
8
+       value: 'auto')
9
 option('libpulse',
10
        description: 'Enable code that depends on libpulse',
11
        type: 'feature',
12
@@ -281,3 +285,36 @@
13
        description: 'Enable ALSA Compress-Offload support',
14
        type: 'feature',
15
        value: 'disabled')
16
+option('pam-defaults-install',
17
+       description: 'Install limits.d file modifying defaults for all PAM users. Only for old kernels/systemd!',
18
+       type: 'boolean',
19
+       value: 'false')
20
+option('pam-memlock-default',
21
+       description : 'The default memlock value for any PAM user in kilobytes. Multiples of 64 recommended.',
22
+       type : 'integer',
23
+       min: 640,
24
+       value: 8192)
25
+option('rlimits-install',
26
+       description: 'Install PAM limits.d file. Voids all following rlimits-* options, if false',
27
+       type: 'boolean',
28
+       value: 'true')
29
+option('rlimits-match',
30
+       description : 'PAM match rule for the generated limits.d file. @<name> denotes matching a group.',
31
+       type : 'string',
32
+       value: '@pipewire')
33
+option('rlimits-rtprio',
34
+       description : 'RR and FIFO scheduler priority permitted for realtime threads of the matching user(s)',
35
+       type : 'integer',
36
+       min: 11,
37
+       max: 99,
38
+       value: 95)
39
+option('rlimits-memlock',
40
+       description : 'kB of memory each process of the user matched by the rule can lock. Can be unlimited .',
41
+       type : 'string',
42
+       value: '4194304')
43
+option('rlimits-nice',
44
+       description : 'Not niceness permitted for non-realtime threads of the matching user(s)',
45
+       type : 'integer',
46
+       min: -20,
47
+       max: -1,
48
+       value: -19)
49
pipewire-0.3.65.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.66.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
46
 
1
@@ -5784,15 +5784,18 @@
2
 {
3
    struct client *c = (struct client *) client;
4
    struct spa_io_position *pos;
5
-   double df;
6
 
7
    spa_return_val_if_fail(c != NULL, -EINVAL);
8
 
9
-   if (SPA_UNLIKELY((pos = c->rt.position) == NULL))
10
+   if (SPA_UNLIKELY((pos = c->rt.position) == NULL) || c->buffer_frames == 0)
11
        return 0;
12
 
13
-   df = (frames - pos->clock.position) * (double)SPA_NSEC_PER_SEC / c->sample_rate;
14
-   return (pos->clock.nsec + (int64_t)rint(df)) / SPA_NSEC_PER_USEC;
15
+   uint32_t nf = (uint32_t)pos->clock.position;
16
+   uint64_t w = pos->clock.nsec/SPA_NSEC_PER_USEC;
17
+   uint64_t nw = pos->clock.next_nsec/SPA_NSEC_PER_USEC;
18
+   int32_t df = frames - nf;
19
+   int64_t dp = nw - w;
20
+   return w + (int64_t)rint((double) df * (double) dp / c->buffer_frames);
21
 }
22
 
23
 SPA_EXPORT
24
@@ -5800,15 +5803,18 @@
25
 {
26
    struct client *c = (struct client *) client;
27
    struct spa_io_position *pos;
28
-   double du;
29
 
30
    spa_return_val_if_fail(c != NULL, -EINVAL);
31
 
32
    if (SPA_UNLIKELY((pos = c->rt.position) == NULL))
33
        return 0;
34
 
35
-   du = (usecs - pos->clock.nsec/SPA_NSEC_PER_USEC) * (double)c->sample_rate / SPA_USEC_PER_SEC;
36
-   return pos->clock.position + (int32_t)rint(du);
37
+   uint32_t nf = (uint32_t)pos->clock.position;
38
+   uint64_t w = pos->clock.nsec/SPA_NSEC_PER_USEC;
39
+   uint64_t nw = pos->clock.next_nsec/SPA_NSEC_PER_USEC;
40
+   int64_t du = usecs - w;
41
+   int64_t dp = nw - w;
42
+   return nf + (int32_t)rint((double)du / (double)dp * c->buffer_frames);
43
 }
44
 
45
 SPA_EXPORT
46
pipewire-0.3.65.tar.gz/po/oc.po -> pipewire-0.3.66.tar.gz/po/oc.po Changed
201
 
1
@@ -1,4 +1,4 @@
2
-# French translation of pipewire.
3
+# Occitan translation of pipewire.
4
 # Copyright (C) 2006-2008 Lennart Poettering
5
 # This file is distributed under the same license as the pipewire package.
6
 # Robert-André Mauchin <zebob.m@pengzone.org>, 2008.
7
@@ -8,24 +8,25 @@
8
 # Thomas Canniot <mrtom@fedoraproject.org>, 2009, 2012.
9
 # Cédric Valmary (Tot en Òc) <cvalmary@yahoo.fr>, 2015.
10
 # Cédric Valmary (totenoc.eu) <cvalmary@yahoo.fr>, 2016.
11
+# Quentin PAGÈS, 2023.
12
 msgid ""
13
 msgstr ""
14
 "Project-Id-Version: pipewire trunk\n"
15
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
16
 "issues/new\n"
17
-"POT-Creation-Date: 2021-04-18 16:54+0800\n"
18
-"PO-Revision-Date: 2016-10-12 22:20+0200\n"
19
-"Last-Translator: Cédric Valmary (totenoc.eu) <cvalmary@yahoo.fr>\n"
20
+"POT-Creation-Date: 2022-06-30 12:50+0200\n"
21
+"PO-Revision-Date: 2023-02-11 00:11+0100\n"
22
+"Last-Translator: Quentin PAGÈS\n"
23
 "Language-Team: Tot En Òc\n"
24
 "Language: oc\n"
25
 "MIME-Version: 1.0\n"
26
 "Content-Type: text/plain; charset=UTF-8\n"
27
 "Content-Transfer-Encoding: 8bit\n"
28
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
29
-"X-Generator: Virtaal 0.7.1\n"
30
+"X-Generator: Poedit 3.2.2\n"
31
 "X-Launchpad-Export-Date: 2016-10-12 20:12+0000\n"
32
 
33
-#: src/daemon/pipewire.c:43
34
+#: src/daemon/pipewire.c:46
35
 #, c-format
36
 msgid ""
37
 "%s options\n"
38
@@ -33,40 +34,56 @@
39
 "      --version                         Show version\n"
40
 "  -c, --config                          Load config (Default %s)\n"
41
 msgstr ""
42
+"%s opcions\n"
43
+"  -h, --help                            Afichar aquesta ajuda\n"
44
+"      --version                         Afichar la version\n"
45
+"  -c, --config                          Cargar la conf. (Defaut %s)\n"
46
 
47
-#: src/daemon/pipewire.desktop.in:4
48
-msgid "PipeWire Media System"
49
-msgstr ""
50
-
51
-#: src/daemon/pipewire.desktop.in:5
52
-msgid "Start the PipeWire Media System"
53
-msgstr ""
54
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
55
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
56
+#, c-format
57
+msgid "Tunnel to %s/%s"
58
+msgstr "Tunèl cap a %s/%s"
59
 
60
-#: src/examples/media-session/alsa-monitor.c:526
61
-#: spa/plugins/alsa/acp/compat.c:187
62
-msgid "Built-in Audio"
63
-msgstr "Àudio integrat"
64
+#: src/modules/module-fallback-sink.c:51
65
+msgid "Dummy Output"
66
+msgstr "Sortida factícia"
67
 
68
-#: src/examples/media-session/alsa-monitor.c:530
69
-#: spa/plugins/alsa/acp/compat.c:192
70
-msgid "Modem"
71
-msgstr "Modèm"
72
+#: src/modules/module-pulse-tunnel.c:662
73
+#, c-format
74
+msgid "Tunnel for %s@%s"
75
+msgstr "Tunèl per %s@%s"
76
 
77
-#: src/examples/media-session/alsa-monitor.c:539
78
+#: src/modules/module-zeroconf-discover.c:332
79
 msgid "Unknown device"
80
-msgstr ""
81
+msgstr "Periferic desconegut"
82
+
83
+#: src/modules/module-zeroconf-discover.c:344
84
+#, c-format
85
+msgid "%s on %s@%s"
86
+msgstr "%s sus %s@%s"
87
 
88
-#: src/tools/pw-cat.c:991
89
+#: src/modules/module-zeroconf-discover.c:348
90
+#, c-format
91
+msgid "%s on %s"
92
+msgstr "%s sus %s"
93
+
94
+#: src/tools/pw-cat.c:784
95
 #, c-format
96
 msgid ""
97
-"%s options <file>\n"
98
+"%s options <file>|-\n"
99
 "  -h, --help                            Show this help\n"
100
 "      --version                         Show version\n"
101
 "  -v, --verbose                         Enable verbose operations\n"
102
 "\n"
103
 msgstr ""
104
+"%s opcions <file>|-\n"
105
+"  -h, --help                            Afichar aquesta ajuda\n"
106
+"      --version                         Afichar la version\n"
107
+"  -v, --verbose                         Activar las operacions verbosas\n"
108
+"\n"
109
 
110
-#: src/tools/pw-cat.c:998
111
+#: src/tools/pw-cat.c:791
112
 #, c-format
113
 msgid ""
114
 "  -R, --remote                          Remote daemon name\n"
115
@@ -80,11 +97,11 @@
116
 "                                          or direct samples (256)\n"
117
 "                                          the rate is the one of the source "
118
 "file\n"
119
-"      --list-targets                    List available targets for --target\n"
120
+"  -P  --properties                      Set node properties\n"
121
 "\n"
122
 msgstr ""
123
 
124
-#: src/tools/pw-cat.c:1016
125
+#: src/tools/pw-cat.c:809
126
 #, c-format
127
 msgid ""
128
 "      --rate                            Sample rate (req. for rec) (default "
129
@@ -104,15 +121,21 @@
130
 "\n"
131
 msgstr ""
132
 
133
-#: src/tools/pw-cat.c:1033
134
+#: src/tools/pw-cat.c:826
135
 msgid ""
136
 "  -p, --playback                        Playback mode\n"
137
 "  -r, --record                          Recording mode\n"
138
 "  -m, --midi                            Midi mode\n"
139
+"  -d, --dsd                             DSD mode\n"
140
 "\n"
141
 msgstr ""
142
+"  -p, --playback                        Mòde lectura\n"
143
+"  -r, --record                          Mòde enregistrament\n"
144
+"  -m, --midi                            Mòde Midi\n"
145
+"  -d, --dsd                             Mòde DSD\n"
146
+"\n"
147
 
148
-#: src/tools/pw-cli.c:2932
149
+#: src/tools/pw-cli.c:2250
150
 #, c-format
151
 msgid ""
152
 "%s options command\n"
153
@@ -122,360 +145,353 @@
154
 "  -r, --remote                          Remote daemon name\n"
155
 "\n"
156
 msgstr ""
157
+"%s opcions comanda\n"
158
+"  -h, --help                           Afichar aquesta ajuda\n"
159
+"      --version                         Afichar la version\n"
160
+"  -d, --daemon                          Aviar coma demòni (Per defaut "
161
+"false)\n"
162
+"  -r, --remote                          Remote daemon name\n"
163
+"\n"
164
 
165
-#: spa/plugins/alsa/acp/acp.c:290
166
+#: spa/plugins/alsa/acp/acp.c:321
167
 msgid "Pro Audio"
168
 msgstr ""
169
 
170
-#: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704
171
-#: spa/plugins/bluez5/bluez5-device.c:1000
172
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
173
+#: spa/plugins/bluez5/bluez5-device.c:1236
174
 msgid "Off"
175
 msgstr "Atudat"
176
 
177
-#: spa/plugins/alsa/acp/channelmap.h:466
178
-msgid "(invalid)"
179
-msgstr "(invalid)"
180
-
181
-#: spa/plugins/alsa/acp/alsa-mixer.c:2709
182
+#: spa/plugins/alsa/acp/alsa-mixer.c:2652
183
 msgid "Input"
184
 msgstr "Entrada"
185
 
186
-#: spa/plugins/alsa/acp/alsa-mixer.c:2710
187
+#: spa/plugins/alsa/acp/alsa-mixer.c:2653
188
 msgid "Docking Station Input"
189
 msgstr "Entrada de l'estacion d'acuèlh"
190
 
191
-#: spa/plugins/alsa/acp/alsa-mixer.c:2711
192
+#: spa/plugins/alsa/acp/alsa-mixer.c:2654
193
 msgid "Docking Station Microphone"
194
 msgstr "Microfòn de l'estacion d'acuèlh"
195
 
196
-#: spa/plugins/alsa/acp/alsa-mixer.c:2712
197
+#: spa/plugins/alsa/acp/alsa-mixer.c:2655
198
 msgid "Docking Station Line In"
199
 msgstr "Entrada linha de l'estacion d'acuèlh"
200
 
201
pipewire-0.3.65.tar.gz/po/uk.po -> pipewire-0.3.66.tar.gz/po/uk.po Changed
201
 
1
@@ -1,14 +1,14 @@
2
 # Copyright (C) 2009 Free Software Foundation, Inc.
3
 # This file is distributed under the same license as the pipewire package.
4
 #
5
-# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021, 2022.
6
+# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021, 2022, 2023.
7
 msgid ""
8
 msgstr ""
9
 "Project-Id-Version: pipewire\n"
10
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issue"
11
-"s\n"
12
-"POT-Creation-Date: 2022-05-20 15:26+0000\n"
13
-"PO-Revision-Date: 2022-06-18 13:07+0300\n"
14
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issu"
15
+"es\n"
16
+"POT-Creation-Date: 2023-02-06 15:27+0000\n"
17
+"PO-Revision-Date: 2023-02-11 17:42+0200\n"
18
 "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
19
 "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
20
 "Language: uk\n"
21
@@ -41,8 +41,8 @@
22
 msgid "Start the PipeWire Media System"
23
 msgstr "Запустити мультимедійну систему 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:179
28
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:179
29
 #, c-format
30
 msgid "Tunnel to %s/%s"
31
 msgstr "Тунель до %s/%s"
32
@@ -51,33 +51,27 @@
33
 msgid "Dummy Output"
34
 msgstr "Фіктивний вихід"
35
 
36
-#: src/modules/module-pulse-tunnel.c:639
37
+#: src/modules/module-pulse-tunnel.c:695
38
 #, c-format
39
 msgid "Tunnel for %s@%s"
40
 msgstr "Тунель для %s@%s"
41
 
42
-#: src/modules/module-zeroconf-discover.c:332
43
+#: src/modules/module-zeroconf-discover.c:335
44
 msgid "Unknown device"
45
 msgstr "Невідомий пристрій"
46
 
47
-#: src/modules/module-zeroconf-discover.c:344
48
+#: src/modules/module-zeroconf-discover.c:347
49
 #, c-format
50
 msgid "%s on %s@%s"
51
 msgstr "%s на %s@%s"
52
 
53
-#: src/modules/module-zeroconf-discover.c:348
54
+#: src/modules/module-zeroconf-discover.c:351
55
 #, c-format
56
 msgid "%s on %s"
57
 msgstr "%s на %s"
58
 
59
-#: src/tools/pw-cat.c:872
60
+#: src/tools/pw-cat.c:940
61
 #, c-format
62
-#| msgid ""
63
-#| "%s options <file>\n"
64
-#| "  -h, --help                            Show this help\n"
65
-#| "      --version                         Show version\n"
66
-#| "  -v, --verbose                         Enable verbose operations\n"
67
-#| "\n"
68
 msgid ""
69
 "%s options <file>|-\n"
70
 "  -h, --help                            Show this help\n"
71
@@ -92,7 +86,7 @@
72
 "інформації\n"
73
 "\n"
74
 
75
-#: src/tools/pw-cat.c:879
76
+#: src/tools/pw-cat.c:947
77
 #, c-format
78
 #| msgid ""
79
 #| "  -R, --remote                          Remote daemon name\n"
80
@@ -106,13 +100,15 @@
81
 #| "                                          or direct samples (256)\n"
82
 #| "                                          the rate is the one of the "
83
 #| "source file\n"
84
+#| "  -P  --properties                      Set node properties\n"
85
 #| "\n"
86
 msgid ""
87
 "  -R, --remote                          Remote daemon name\n"
88
 "      --media-type                      Set media type (default %s)\n"
89
 "      --media-category                  Set media category (default %s)\n"
90
 "      --media-role                      Set media role (default %s)\n"
91
-"      --target                          Set node target (default %s)\n"
92
+"      --target                          Set node target serial or name "
93
+"(default %s)\n"
94
 "                                          0 means don't link\n"
95
 "      --latency                         Set node latency (default %s)\n"
96
 "                                          Xunit (unit = s, ms, us, ns)\n"
97
@@ -129,7 +125,8 @@
98
 "(типово, %s)\n"
99
 "      --media-role                      встановити роль мультимедіа (типово, "
100
 "%s)\n"
101
-"      --target                          встановити ціль вузла (типово, %s)\n"
102
+"      --target                          встановити назву або серійний номер"
103
+" цілі вузла (типово, %s)\n"
104
 "                                          0 — не пов'язувати\n"
105
 "      --latency                         встановити затримку вузла (типово, "
106
 "%s)\n"
107
@@ -140,7 +137,7 @@
108
 "  -P  --properties                      встановити властивості вузла\n"
109
 "\n"
110
 
111
-#: src/tools/pw-cat.c:897
112
+#: src/tools/pw-cat.c:965
113
 #, c-format
114
 msgid ""
115
 "      --rate                            Sample rate (req. for rec) (default "
116
@@ -176,28 +173,44 @@
117
 "(типово, %d)\n"
118
 "\n"
119
 
120
-#: src/tools/pw-cat.c:914
121
+#: src/tools/pw-cat.c:982
122
+#| msgid ""
123
+#| "  -p, --playback                        Playback mode\n"
124
+#| "  -r, --record                          Recording mode\n"
125
+#| "  -m, --midi                            Midi mode\n"
126
+#| "  -d, --dsd                             DSD mode\n"
127
+#| "\n"
128
 msgid ""
129
 "  -p, --playback                        Playback mode\n"
130
 "  -r, --record                          Recording mode\n"
131
 "  -m, --midi                            Midi mode\n"
132
 "  -d, --dsd                             DSD mode\n"
133
+"  -o, --encoded\t\t\t      Encoded mode\n"
134
 "\n"
135
 msgstr ""
136
 "  -p, --playback                        режим відтворення\n"
137
 "  -r, --record                          режим запису\n"
138
 "  -m, --midi                            режим MIDI\n"
139
 "  -d, --dsd                             режим DSD\n"
140
+"  -o, --encoded\t\t\t      закодований режим\n"
141
 "\n"
142
 
143
-#: src/tools/pw-cli.c:3139
144
+#: src/tools/pw-cli.c:2236
145
 #, c-format
146
+#| msgid ""
147
+#| "%s options command\n"
148
+#| "  -h, --help                            Show this help\n"
149
+#| "      --version                         Show version\n"
150
+#| "  -d, --daemon                          Start as daemon (Default false)\n"
151
+#| "  -r, --remote                          Remote daemon name\n"
152
+#| "\n"
153
 msgid ""
154
 "%s options command\n"
155
 "  -h, --help                            Show this help\n"
156
 "      --version                         Show version\n"
157
 "  -d, --daemon                          Start as daemon (Default false)\n"
158
 "  -r, --remote                          Remote daemon name\n"
159
+"  -m, --monitor                         Monitor activity\n"
160
 "\n"
161
 msgstr ""
162
 "%s параметри команда\n"
163
@@ -206,14 +219,15 @@
164
 "  -d, --daemon                          запустити як фонову службу (типово, "
165
 "false)\n"
166
 "  -r, --remote                          назва віддаленої фонової служби\n"
167
+"  -m, --monitor                         спостерігати за діями\n"
168
 "\n"
169
 
170
-#: spa/plugins/alsa/acp/acp.c:321
171
+#: spa/plugins/alsa/acp/acp.c:323
172
 msgid "Pro Audio"
173
 msgstr "Професійний звук"
174
 
175
-#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
176
-#: spa/plugins/bluez5/bluez5-device.c:1161
177
+#: spa/plugins/alsa/acp/acp.c:447 spa/plugins/alsa/acp/alsa-mixer.c:4648
178
+#: spa/plugins/bluez5/bluez5-device.c:1303
179
 msgid "Off"
180
 msgstr "Вимкнено"
181
 
182
@@ -240,7 +254,7 @@
183
 
184
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
185
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
186
-#: spa/plugins/bluez5/bluez5-device.c:1330
187
+#: spa/plugins/bluez5/bluez5-device.c:1536
188
 msgid "Microphone"
189
 msgstr "Мікрофон"
190
 
191
@@ -306,7 +320,7 @@
192
 msgstr "Без підсилення"
193
 
194
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
195
-#: spa/plugins/bluez5/bluez5-device.c:1335
196
+#: spa/plugins/bluez5/bluez5-device.c:1542
197
 msgid "Speaker"
198
 msgstr "Динамік"
199
 
200
@@ -421,7 +435,7 @@
201
pipewire-0.3.65.tar.gz/spa/include/spa/param/port-config.h -> pipewire-0.3.66.tar.gz/spa/include/spa/param/port-config.h Changed
10
 
1
@@ -48,7 +48,7 @@
2
 /** properties for SPA_TYPE_OBJECT_ParamPortConfig */
3
 enum spa_param_port_config {
4
    SPA_PARAM_PORT_CONFIG_START,
5
-   SPA_PARAM_PORT_CONFIG_direction,    /**< direction, input/output (Id enum spa_direction) */
6
+   SPA_PARAM_PORT_CONFIG_direction,    /**< (Id enum spa_direction) direction */
7
    SPA_PARAM_PORT_CONFIG_mode,     /**< (Id enum spa_param_port_config_mode) mode */
8
    SPA_PARAM_PORT_CONFIG_monitor,      /**< (Bool) enable monitor output ports on input ports */
9
    SPA_PARAM_PORT_CONFIG_control,      /**< (Bool) enable control ports */
10
pipewire-0.3.65.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.66.tar.gz/spa/include/spa/utils/defs.h Changed
10
 
1
@@ -142,7 +142,7 @@
2
    for ((ptr) = arr; (void*)(ptr) < SPA_PTROFF(arr, sizeof(arr), void); (ptr)++)
3
 
4
 #define SPA_FOR_EACH_ELEMENT_VAR(arr, var) \
5
-   for (__typeof__((arr)0)* (var) = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++)
6
+   for (__typeof__((arr)0)* var = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++)
7
 
8
 #define SPA_ABS(a)         \
9
 ({                 \
10
pipewire-0.3.65.tar.gz/spa/meson.build -> pipewire-0.3.66.tar.gz/spa/meson.build Changed
28
 
1
@@ -41,14 +41,23 @@
2
   # plugin-specific dependencies
3
   alsa_dep = dependency('alsa', required: get_option('alsa'))
4
   summary({'ALSA': alsa_dep.found()}, bool_yn: true, section: 'Backend')
5
+
6
   bluez_dep = dependency('bluez', version : '>= 4.101', required: get_option('bluez5'))
7
   gio_dep = dependency('gio-2.0', required : get_option('bluez5'))
8
   gio_unix_dep = dependency('gio-unix-2.0', required : get_option('bluez5'))
9
-  bluez_deps_found = bluez_dep.found() and gio_dep.found() and gio_unix_dep.found()
10
+  bluez_glib2_dep = dependency('glib-2.0', required : get_option('bluez5'))
11
+  sbc_dep = dependency('sbc', required: get_option('bluez5'))
12
+  summary({'SBC': sbc_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
13
+  bluez5_deps =  mathlib, dbus_dep, sbc_dep, bluez_dep, bluez_glib2_dep, gio_dep, gio_unix_dep 
14
+  bluez_deps_found = get_option('bluez5').allowed()
15
+  foreach dep: bluez5_deps
16
+      if get_option('bluez5').enabled() and not dep.found()
17
+        error('bluez5 enabled, but dependency not found: ' + dep.name())
18
+      endif
19
+      bluez_deps_found = bluez_deps_found and dep.found()
20
+  endforeach
21
   summary({'Bluetooth audio': bluez_deps_found}, bool_yn: true, section: 'Backend')
22
   if bluez_deps_found
23
-    sbc_dep = dependency('sbc', required: get_option('bluez5'))
24
-    summary({'SBC': sbc_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
25
     ldac_dep = dependency('ldacBT-enc', required : get_option('bluez5-codec-ldac'))
26
     summary({'LDAC': ldac_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
27
     ldac_abr_dep = dependency('ldacBT-abr', required : get_option('bluez5-codec-ldac'))
28
pipewire-0.3.65.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/acp/acp.c Changed
27
 
1
@@ -315,7 +315,7 @@
2
 
3
    ss.format = PA_SAMPLE_S32LE;
4
    ss.rate = impl->rate;
5
-   ss.channels = 64;
6
+   ss.channels = impl->pro_channels;
7
 
8
    ap = pa_xnew0(pa_alsa_profile, 1);
9
    ap->profile_set = ps;
10
@@ -1564,6 +1564,7 @@
11
    impl->auto_port = true;
12
    impl->ignore_dB = false;
13
    impl->rate = DEFAULT_RATE;
14
+   impl->pro_channels = 64;
15
 
16
    if (props) {
17
        if ((s = acp_dict_lookup(props, "api.alsa.use-ucm")) != NULL)
18
@@ -1582,6 +1583,8 @@
19
            impl->auto_port = spa_atob(s);
20
        if ((s = acp_dict_lookup(props, "api.acp.probe-rate")) != NULL)
21
            impl->rate = atoi(s);
22
+       if ((s = acp_dict_lookup(props, "api.acp.pro-channels")) != NULL)
23
+           impl->pro_channels = atoi(s);
24
    }
25
 
26
    impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE;
27
pipewire-0.3.65.tar.gz/spa/plugins/alsa/acp/card.h -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/acp/card.h Changed
9
 
1
@@ -48,6 +48,7 @@
2
    bool auto_port;
3
    bool ignore_dB;
4
    uint32_t rate;
5
+   uint32_t pro_channels;
6
 
7
    pa_alsa_ucm_config ucm;
8
    pa_alsa_profile_set *profile_set;
9
pipewire-0.3.65.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
10
 
1
@@ -1879,6 +1879,8 @@
2
    } else {
3
        *delay = avail;
4
        *target = SPA_MAX(*target, state->read_size);
5
+       if (state->matching)
6
+           *target += 32;
7
    }
8
    *target = SPA_CLAMP(*target, state->min_delay, state->buffer_frames);
9
    return 0;
10
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/channelmix-ops.c Changed
201
 
1
@@ -142,18 +142,67 @@
2
 #define MATRIX_DOLBY   1
3
 #define MATRIX_DPLII   2
4
 
5
-#define _CH(ch)        ((SPA_AUDIO_CHANNEL_ ## ch)-3)
6
+#define _SH        2
7
+#define _CH(ch)        ((SPA_AUDIO_CHANNEL_ ## ch)-_SH)
8
 #define _MASK(ch)  (1ULL << _CH(ch))
9
 #define FRONT      (_MASK(FC))
10
 #define STEREO     (_MASK(FL)|_MASK(FR))
11
 #define REAR       (_MASK(RL)|_MASK(RR))
12
 #define SIDE       (_MASK(SL)|_MASK(SR))
13
 
14
+static uint32_t mask_to_ch(struct channelmix *mix, uint64_t mask)
15
+{
16
+   uint32_t ch = 0;
17
+   while (mask > 1) {
18
+       ch++;
19
+       mask >>= 1;
20
+   }
21
+   return ch;
22
+}
23
+
24
+static void distribute_mix(struct channelmix *mix,
25
+       float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS,
26
+       uint64_t mask)
27
+{
28
+   uint32_t i, ch = mask_to_ch(mix, mask);
29
+   for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
30
+       matrixich= 1.0f;
31
+}
32
+static void average_mix(struct channelmix *mix,
33
+       float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS,
34
+       uint64_t mask)
35
+{
36
+   uint32_t i, ch = mask_to_ch(mix, mask);
37
+   for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
38
+       matrixchi= 1.0f;
39
+}
40
+static void pair_mix(float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS)
41
+{
42
+   uint32_t i;
43
+   for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
44
+       matrixii= 1.0f;
45
+}
46
+static bool match_mix(struct channelmix *mix,
47
+       float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS,
48
+       uint64_t src_mask, uint64_t dst_mask)
49
+{
50
+   bool matched = false;
51
+   uint32_t i;
52
+   for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
53
+       if ((src_mask & dst_mask & (1ULL << i))) {
54
+           spa_log_info(mix->log, "matched channel %u (%f)", i, 1.0f);
55
+           matrixii = 1.0f;
56
+           matched = true;
57
+       }
58
+   }
59
+   return matched;
60
+}
61
+
62
 static int make_matrix(struct channelmix *mix)
63
 {
64
    float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS = {{ 0.0f }};
65
-   uint64_t src_mask = mix->src_mask;
66
-   uint64_t dst_mask = mix->dst_mask;
67
+   uint64_t src_mask = mix->src_mask, src_paired;
68
+   uint64_t dst_mask = mix->dst_mask, dst_paired;
69
    uint32_t src_chan = mix->src_chan;
70
    uint32_t dst_chan = mix->dst_chan;
71
    uint64_t unassigned, keep;
72
@@ -162,89 +211,110 @@
73
    float slev = SQRT1_2;
74
    float llev = 0.5f;
75
    float maxsum = 0.0f;
76
-   bool filter_fc = false, filter_lfe = false;
77
+   bool filter_fc = false, filter_lfe = false, matched = false, normalize;
78
 #define _MATRIX(s,d)   matrix_CH(s)_CH(d)
79
 
80
+   normalize =  SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE);
81
+
82
    spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64
83
            " options:%08x", src_mask, dst_mask, mix->options);
84
 
85
-   /* move the MONO mask to FRONT so that the lower bits can be shifted
86
-    * away. */
87
-   if ((src_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0) {
88
-       if (src_chan == 1)
89
-           src_mask = 0;
90
-       else
91
-           src_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC);
92
-   }
93
-   if ((dst_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0)
94
-       dst_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC);
95
+   /* shift so that bit 0 is MONO */
96
+   src_mask >>= _SH;
97
+   dst_mask >>= _SH;
98
 
99
-   /* shift so that bit 0 is FL */
100
-   src_mask >>= 3;
101
-   dst_mask >>= 3;
102
+   if (src_chan > 1 && (src_mask & _MASK(MONO)))
103
+       src_mask = 0;
104
+   if (dst_chan > 1 && (dst_mask & _MASK(MONO)))
105
+       dst_mask = 0;
106
 
107
-   /* unknown channels or just 1 channel */
108
+   src_paired = src_mask;
109
+   dst_paired = dst_mask;
110
+
111
+   /* unknown channels */
112
    if (src_mask == 0 || dst_mask == 0) {
113
        if (src_chan == 1) {
114
-           /* one FC/MONO src goes everywhere */
115
-           spa_log_debug(mix->log, "distribute FC/MONO (%f)", 1.0f);
116
-           for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
117
-               matrixi0= 1.0f;
118
+           /* one src channel goes everywhere */
119
+           spa_log_info(mix->log, "distribute UNK (%f) %"PRIu64, 1.0f, src_mask);
120
+           distribute_mix(mix, matrix, src_mask);
121
        } else if (dst_chan == 1) {
122
-           /* one FC/MONO dst get average of everything */
123
-           spa_log_debug(mix->log, "average FC/MONO (%f)", 1.0f / src_chan);
124
-           for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
125
-               matrix0i= 1.0f / src_chan;
126
+           /* one dst channel get average of everything */
127
+           spa_log_info(mix->log, "average UNK (%f) %"PRIu64, 1.0f / src_chan, dst_mask);
128
+           average_mix(mix, matrix, dst_mask);
129
+           normalize = true;
130
        } else {
131
            /* just pair channels */
132
-           spa_log_debug(mix->log, "pairing channels (%f)", 1.0f);
133
-           for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
134
-               matrixii= 1.0f;
135
+           spa_log_info(mix->log, "pairing UNK channels (%f)", 1.0f);
136
+           if (src_mask == 0)
137
+               src_paired = dst_mask;
138
+           else if (dst_mask == 0)
139
+               dst_paired = src_mask;
140
+           pair_mix(matrix);
141
        }
142
-       if (dst_mask & FRONT)
143
-           filter_fc = true;
144
-       if (dst_mask & _MASK(LFE))
145
-           filter_lfe = true;
146
-       src_mask = dst_mask = ~0LU;
147
        goto done;
148
    } else {
149
        spa_log_debug(mix->log, "matching channels");
150
-       for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
151
-           if ((src_mask & dst_mask & (1ULL << i))) {
152
-               spa_log_debug(mix->log, "matched channel %u (%f)", i, 1.0f);
153
-               matrixii= 1.0f;
154
-           }
155
-       }
156
+       matched = match_mix(mix, matrix, src_mask, dst_mask);
157
    }
158
 
159
    unassigned = src_mask & ~dst_mask;
160
    keep = dst_mask & ~src_mask;
161
 
162
    if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX)) {
163
+       /* upmix completely disabled */
164
        keep = 0;
165
    } else {
166
+       /* some upmixing (FC and LFE) enabled. */
167
        if (mix->upmix == CHANNELMIX_UPMIX_NONE)
168
            keep = 0;
169
-       keep |= FRONT;
170
+       if (mix->fc_cutoff > 0.0f)
171
+           keep |= FRONT;
172
+       else
173
+           keep &= ~FRONT;
174
        if (mix->lfe_cutoff > 0.0f)
175
            keep |= _MASK(LFE);
176
        else
177
            keep &= ~_MASK(LFE);
178
    }
179
+   /* if we have no channel matched, try to upmix or keep the stereo
180
+    * pair or else we might end up with silence. */
181
+   if (dst_mask & STEREO && !matched)
182
+       keep |= STEREO;
183
+
184
+   spa_log_info(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep);
185
+
186
+   if (unassigned & _MASK(MONO)) {
187
+       if ((dst_mask & STEREO) == STEREO) {
188
+           spa_log_info(mix->log, "assign MONO to STEREO (%f)", 1.0f);
189
+           _MATRIX(FL,MONO) += 1.0f;
190
+           _MATRIX(FR,MONO) += 1.0f;
191
+           keep &= ~STEREO;
192
+       } else if ((dst_mask & FRONT) == FRONT) {
193
+           spa_log_info(mix->log, "assign MONO to FRONT (%f)", 1.0f);
194
+           _MATRIX(FC,MONO) += 1.0f;
195
+           normalize = true;
196
+       } else {
197
+           spa_log_warn(mix->log, "can't assign MONO");
198
+       }
199
+   }
200
 
201
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/test-audioconvert.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/test-audioconvert.c Changed
22
 
1
@@ -38,6 +38,7 @@
2
 #include <spa/node/node.h>
3
 #include <spa/node/io.h>
4
 #include <spa/debug/mem.h>
5
+#include <spa/debug/log.h>
6
 #include <spa/support/log-impl.h>
7
 
8
 SPA_LOG_IMPL(logger);
9
@@ -682,8 +683,10 @@
10
            res = memcmp(b->datasj.data, out_data->datak, out_data->size);
11
            if (res != 0) {
12
                fprintf(stderr, "error port %d plane %d\n", i, j);
13
-               spa_debug_mem(0, b->datasj.data, out_data->size);
14
-               spa_debug_mem(0, out_data->datak, out_data->size);
15
+               spa_debug_log_mem(&logger.log, SPA_LOG_LEVEL_WARN,
16
+                       0, b->datasj.data, out_data->size);
17
+               spa_debug_log_mem(&logger.log, SPA_LOG_LEVEL_WARN,
18
+                       2, out_data->datak, out_data->size);
19
            }
20
            spa_assert_se(res == 0);
21
 
22
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/test-channelmix.c Changed
135
 
1
@@ -72,6 +72,8 @@
2
    mix.src_mask = src_mask;
3
    mix.dst_mask = dst_mask;
4
    mix.log = &logger.log;
5
+   mix.fc_cutoff = 120.0f;
6
+   mix.lfe_cutoff = 12000.0f;
7
 
8
    spa_assert_se(channelmix_init(&mix) == 0);
9
    channelmix_set_volume(&mix, 1.0f, false, 0, NULL);
10
@@ -83,11 +85,17 @@
11
    test_mix(1, _M(MONO), 2, _M(FL)|_M(FR), 0,
12
            MATRIX(1.0, 1.0));
13
    test_mix(1, _M(MONO), 3, _M(FL)|_M(FR)|_M(LFE), 0,
14
+           MATRIX(1.0, 1.0, 0.0));
15
+   test_mix(1, _M(MONO), 3, _M(FL)|_M(FR)|_M(LFE), CHANNELMIX_OPTION_UPMIX,
16
            MATRIX(1.0, 1.0, 1.0));
17
    test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 0,
18
+           MATRIX(1.0, 1.0, 0.0, 0.0));
19
+   test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), CHANNELMIX_OPTION_UPMIX,
20
            MATRIX(1.0, 1.0, 1.0, 1.0));
21
    test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 0,
22
-           MATRIX(1.0, 1.0, 1.0, 1.0));
23
+           MATRIX(1.0, 1.0, 0.0, 0.0));
24
+   test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(RL)|_M(RR), CHANNELMIX_OPTION_UPMIX,
25
+           MATRIX(1.0, 1.0, 0.0, 0.0));
26
    test_mix(1, _M(MONO), 12, 0, 0,
27
            MATRIX(1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
28
                   1.0, 1.0, 1.0, 1.0, 1.0, 1.0));
29
@@ -119,16 +127,49 @@
30
    test_mix(1, _M(FC), 1, _M(FC), 0,
31
            MATRIX(1.0));
32
    test_mix(2, _M(FL)|_M(FR), 1, _M(MONO), 0,
33
-           MATRIX(0.707107, 0.707107));
34
+           MATRIX(0.5, 0.5));
35
    test_mix(12, 0, 1, _M(MONO), 0,
36
            MATRIX(0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333,
37
                   0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.0833333));
38
 }
39
 
40
+static void test_2_N(void)
41
+{
42
+   test_mix(2, _M(FL)|_M(FR), 1, _M(MONO), 0, MATRIX(0.5, 0.5));
43
+   test_mix(2, _M(FL)|_M(FR), 1, 0, 0, MATRIX(0.5, 0.5));
44
+   test_mix(2, _M(FL)|_M(FR), 2, 0, 0, MATRIX(1.0, 0.0, 0.0, 1.0));
45
+   test_mix(2, _M(FL)|_M(FR), 2, _M(MONO), 0, MATRIX(1.0, 0.0, 0.0, 1.0));
46
+   test_mix(2, _M(FL)|_M(FR), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.0, 1.0));
47
+   test_mix(2, _M(FL)|_M(FR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 0,
48
+           MATRIX(1.0, 0.0,
49
+                  0.0, 1.0,
50
+                  0.0, 0.0,
51
+                  0.0, 0.0));
52
+   test_mix(2, _M(FL)|_M(FR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), CHANNELMIX_OPTION_UPMIX,
53
+           MATRIX(1.0, 0.0,
54
+                  0.0, 1.0,
55
+                  0.707107, 0.707107,
56
+                  0.5, 0.5));
57
+   test_mix(2, _M(FL)|_M(FR), 6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 0,
58
+           MATRIX(1.0, 0.0,
59
+                  0.0, 1.0,
60
+                  0.0, 0.0,
61
+                  0.0, 0.0,
62
+                  0.0, 0.0,
63
+                  0.0, 0.0));
64
+   test_mix(2, _M(FL)|_M(FR), 6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), CHANNELMIX_OPTION_UPMIX,
65
+           MATRIX(1.0, 0.0,
66
+                  0.0, 1.0,
67
+                  0.707107, 0.707107,
68
+                  0.5, 0.5,
69
+                  0.0, 0.0,
70
+                  0.0, 0.0));
71
+}
72
+
73
 static void test_3p1_N(void)
74
 {
75
    test_mix(4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 1, _M(MONO), 0,
76
-           MATRIX(0.707107, 0.707107, 1.0, 0.0));
77
+           MATRIX(0.333333, 0.333333, 0.333333, 0.0));
78
    test_mix(4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 2, _M(FL)|_M(FR), 0,
79
            MATRIX(1.0, 0.0, 0.707107, 0.0,
80
                   0.0, 1.0, 0.707107, 0.0 ));
81
@@ -151,9 +192,9 @@
82
 static void test_4_N(void)
83
 {
84
    test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 1, _M(MONO), 0,
85
-           MATRIX(0.707107, 0.707107, 0.5, 0.5));
86
+           MATRIX(0.25, 0.25, 0.25, 0.25));
87
    test_mix(4, _M(FL)|_M(FR)|_M(SL)|_M(SR), 1, _M(MONO), 0,
88
-           MATRIX(0.707107, 0.707107, 0.5, 0.5));
89
+           MATRIX(0.25, 0.25, 0.25, 0.25));
90
    test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 2, _M(FL)|_M(FR), 0,
91
            MATRIX(1.0, 0.0, 0.707107, 0.0,
92
                   0.0, 1.0, 0.0, 0.707107));
93
@@ -178,13 +219,13 @@
94
            MATRIX(1.0, 0.0, 0.707107, 0.0,
95
                   0.0, 1.0, 0.0, 0.707107,
96
                   0.707107, 0.707107, 0.0, 0.0,
97
-                  0.0, 0.0, 0.0, 0.0));
98
+                  0.5, 0.5, 0.0, 0.0));
99
 }
100
 
101
 static void test_5p1_N(void)
102
 {
103
    test_mix(6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 1, _M(MONO), 0,
104
-           MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5));
105
+           MATRIX(0.20, 0.20, 0.20, 0.0, 0.20, 0.20));
106
    test_mix(6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 2, _M(FL)|_M(FR), 0,
107
            MATRIX(1.0, 0.0, 0.707107, 0.0, 0.707107, 0.0,
108
                   0.0, 1.0, 0.707107, 0.0, 0.0, 0.707107));
109
@@ -223,7 +264,7 @@
110
 static void test_6p1_N(void)
111
 {
112
    test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RC)|_M(SL)|_M(SR), 1, _M(MONO), 0,
113
-           MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5, 0.5));
114
+           MATRIX(0.166667, 0.166667, 0.166667, 0.0, 0.166667, 0.166667, 0.166667));
115
    test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RC),
116
         6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 0,
117
            MATRIX(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
118
@@ -263,7 +304,7 @@
119
 static void test_7p1_N(void)
120
 {
121
    test_mix(8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 1, _M(MONO), 0,
122
-           MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5, 0.5, 0.5));
123
+           MATRIX(0.142857, 0.142857, 0.142857, 0.0, 0.142857, 0.142857, 0.142857, 0.142857));
124
    test_mix(8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 2, _M(FL)|_M(FR), 0,
125
            MATRIX(1.0, 0.0, 0.707107, 0.0, 0.707107, 0.0, 0.707107, 0.0,
126
                   0.0, 1.0, 0.707107, 0.0, 0.0, 0.707107, 0.0, 0.707107));
127
@@ -362,6 +403,7 @@
128
    test_1_N_MONO();
129
    test_1_N_FC();
130
    test_N_1();
131
+   test_2_N();
132
    test_3p1_N();
133
    test_4_N();
134
    test_5p1_N();
135
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
201
 
1
@@ -134,8 +134,6 @@
2
 
3
    /* A reference audio info for A2DP codec configuration. */
4
    struct media_codec_audio_info default_audio_info;
5
-
6
-   bool le_audio_supported;
7
 };
8
 
9
 /* Stream endpoints owned by BlueZ for each device */
10
@@ -1008,6 +1006,52 @@
11
    return 0;
12
 }
13
 
14
+static int adapter_media_update_props(struct spa_bt_adapter *adapter,
15
+               DBusMessageIter *props_iter,
16
+               DBusMessageIter *invalidated_iter)
17
+{
18
+   /* Handle org.bluez.Media1 interface properties of .Adapter1 objects */
19
+   struct spa_bt_monitor *monitor = adapter->monitor;
20
+
21
+   while (dbus_message_iter_get_arg_type(props_iter) != DBUS_TYPE_INVALID) {
22
+       DBusMessageIter it2;
23
+       const char *key;
24
+
25
+       dbus_message_iter_recurse(props_iter, &it0);
26
+       dbus_message_iter_get_basic(&it0, &key);
27
+       dbus_message_iter_next(&it0);
28
+       dbus_message_iter_recurse(&it0, &it1);
29
+
30
+       if (spa_streq(key, "SupportedUUIDs")) {
31
+           DBusMessageIter iter;
32
+
33
+           if (!check_iter_signature(&it1, "as"))
34
+               goto next;
35
+
36
+           dbus_message_iter_recurse(&it1, &iter);
37
+
38
+           while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
39
+               const char *uuid;
40
+
41
+               dbus_message_iter_get_basic(&iter, &uuid);
42
+
43
+               if (spa_streq(uuid, SPA_BT_UUID_BAP_SINK)) {
44
+                   adapter->le_audio_supported = true;
45
+                   spa_log_info(monitor->log, "Adapter %s: LE Audio supported",
46
+                           adapter->path);
47
+               }
48
+               dbus_message_iter_next(&iter);
49
+           }
50
+       }
51
+       else
52
+           spa_log_debug(monitor->log, "media: unhandled key %s", key);
53
+
54
+next:
55
+       dbus_message_iter_next(props_iter);
56
+   }
57
+   return 0;
58
+}
59
+
60
 static void adapter_update_devices(struct spa_bt_adapter *adapter)
61
 {
62
    struct spa_bt_monitor *monitor = adapter->monitor;
63
@@ -1875,6 +1919,8 @@
64
 {
65
    struct spa_bt_monitor *monitor = device->monitor;
66
    struct spa_bt_remote_endpoint *ep;
67
+   enum spa_bt_profile codec_profile;
68
+   struct spa_bt_transport *t;
69
    const struct { enum spa_bluetooth_audio_codec codec; uint32_t mask; } quirks = {
70
        { SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ, SPA_BT_FEATURE_SBC_XQ },
71
        { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM, SPA_BT_FEATURE_FASTSTREAM },
72
@@ -1887,10 +1933,13 @@
73
    if (!is_media_codec_enabled(device->monitor, codec))
74
        return false;
75
 
76
-   if (!device->adapter->application_registered) {
77
+   if (!device->adapter->a2dp_application_registered && !codec->bap) {
78
        /* Codec switching not supported: only plain SBC allowed */
79
-       return (codec->codec_id == A2DP_CODEC_SBC && spa_streq(codec->name, "sbc"));
80
+       return (codec->codec_id == A2DP_CODEC_SBC && spa_streq(codec->name, "sbc") &&
81
+               device->adapter->legacy_endpoints_registered);
82
    }
83
+   if (!device->adapter->bap_application_registered && codec->bap)
84
+       return false;
85
 
86
    /* Check codec quirks */
87
    for (i = 0; i < SPA_N_ELEMENTS(quirks); ++i) {
88
@@ -1906,16 +1955,15 @@
89
            return false;
90
    }
91
 
92
+   if (codec->bap)
93
+       codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE;
94
+   else
95
+       codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
96
+
97
    spa_list_for_each(ep, &device->remote_endpoint_list, device_link) {
98
        const enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid);
99
-       enum spa_bt_profile expected;
100
 
101
-       if (codec->bap)
102
-           expected = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE;
103
-       else
104
-           expected = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
105
-
106
-       if (profile != expected)
107
+       if (profile != codec_profile)
108
            continue;
109
 
110
        if (media_codec_check_caps(codec, ep->codec, ep->capabilities, ep->capabilities_len,
111
@@ -1923,6 +1971,21 @@
112
            return true;
113
    }
114
 
115
+   /* Codecs on configured transports are always supported.
116
+    *
117
+    * Remote BAP endpoints correspond to capabilities of the remote
118
+    * BAP Server, not to remote BAP Client, and need not be the same.
119
+    * BAP Clients may not have any remote endpoints. In this case we
120
+    * can only know that the currently configured codec is supported.
121
+    */
122
+   spa_list_for_each(t, &device->transport_list, device_link) {
123
+       if (t->profile != codec_profile)
124
+           continue;
125
+
126
+       if (codec == t->media_codec)
127
+           return true;
128
+   }
129
+
130
    return false;
131
 }
132
 
133
@@ -3355,7 +3418,8 @@
134
    const struct media_codec *preferred_codec = NULL;
135
    size_t i, j, num_codecs, num_eps;
136
 
137
-   if (!device->adapter->application_registered) {
138
+   if (!device->adapter->a2dp_application_registered &&
139
+           !device->adapter->bap_application_registered) {
140
        /* Codec switching not supported */
141
        return -ENOTSUP;
142
    }
143
@@ -3690,9 +3754,10 @@
144
    return res;
145
 }
146
 
147
-static void bluez_register_endpoint_reply(DBusPendingCall *pending, void *user_data)
148
+static void bluez_register_endpoint_legacy_reply(DBusPendingCall *pending, void *user_data)
149
 {
150
-   struct spa_bt_monitor *monitor = user_data;
151
+   struct spa_bt_adapter *adapter = user_data;
152
+   struct spa_bt_monitor *monitor = adapter->monitor;
153
    DBusMessage *r;
154
 
155
    r = dbus_pending_call_steal_reply(pending);
156
@@ -3711,6 +3776,8 @@
157
        goto finish;
158
    }
159
 
160
+   adapter->legacy_endpoints_registered = true;
161
+
162
 finish:
163
    dbus_message_unref(r);
164
 }
165
@@ -3739,10 +3806,12 @@
166
    dbus_message_iter_close_container(dict, &dict_entry_it);
167
 }
168
 
169
-static int bluez_register_endpoint(struct spa_bt_monitor *monitor,
170
-                  const char *path, enum spa_bt_media_direction direction,
171
+static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter,
172
+                  enum spa_bt_media_direction direction,
173
                   const char *uuid, const struct media_codec *codec)
174
 {
175
+   struct spa_bt_monitor *monitor = adapter->monitor;
176
+   const char *path = adapter->path;
177
    char  *object_path = NULL;
178
    DBusMessage *m;
179
    DBusMessageIter object_it, dict_it;
180
@@ -3783,7 +3852,7 @@
181
    dbus_message_iter_close_container(&object_it, &dict_it);
182
 
183
    dbus_connection_send_with_reply(monitor->conn, m, &call, -1);
184
-   dbus_pending_call_set_notify(call, bluez_register_endpoint_reply, monitor, NULL);
185
+   dbus_pending_call_set_notify(call, bluez_register_endpoint_legacy_reply, adapter, NULL);
186
    dbus_message_unref(m);
187
 
188
    free(object_path);
189
@@ -3795,14 +3864,15 @@
190
    return ret;
191
 }
192
 
193
-static int adapter_register_endpoints(struct spa_bt_adapter *a)
194
+static int adapter_register_endpoints_legacy(struct spa_bt_adapter *a)
195
 {
196
    struct spa_bt_monitor *monitor = a->monitor;
197
    const struct media_codec * const * const media_codecs = monitor->media_codecs;
198
    int i;
199
    int err = 0;
200
+   bool registered = false;
201
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
136
 
1
@@ -204,6 +204,33 @@
2
    return media_codec;
3
 }
4
 
5
+static bool is_bap_client(struct impl *this)
6
+{
7
+   struct spa_bt_device *device = this->bt_dev;
8
+   struct spa_bt_transport *t;
9
+
10
+   spa_list_for_each(t, &device->transport_list, device_link) {
11
+       if (t->bap_initiator)
12
+           return true;
13
+   }
14
+
15
+   return false;
16
+}
17
+
18
+static bool can_bap_codec_switch(struct impl *this)
19
+{
20
+   if (!is_bap_client(this))
21
+       return false;
22
+
23
+   /* XXX: codec switching for source/duplex is not currently
24
+    * XXX: implemented properly. TODO: fix this
25
+    */
26
+   if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE)
27
+       return false;
28
+
29
+   return true;
30
+}
31
+
32
 static unsigned int get_hfp_codec(enum spa_bluetooth_audio_codec id)
33
 {
34
    switch (id) {
35
@@ -873,9 +900,15 @@
36
     * A2DP/BAP: ensure there's a transport with the selected codec (0 means any).
37
     * Don't try to switch codecs when the device is in the A2DP source role, since
38
     * devices do not appear to like that.
39
+    *
40
+    * For BAP, only BAP client can configure the codec.
41
+    *
42
+    * XXX: codec switching also currently does not work in the duplex or
43
+    * XXX: source-only case, as it will only switch the sink, and we only
44
+    * XXX: list the sink codecs here. TODO: fix this
45
     */
46
-   if ((profile == DEVICE_PROFILE_A2DP || profile == DEVICE_PROFILE_BAP)
47
-       && !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) {
48
+   if ((profile == DEVICE_PROFILE_A2DP || (profile == DEVICE_PROFILE_BAP && can_bap_codec_switch(this)))
49
+           && !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) {
50
        int ret;
51
        const struct media_codec *codecs64;
52
 
53
@@ -1332,11 +1365,6 @@
54
        if (profile == 0)
55
            return NULL;
56
 
57
-       if (!codec) {
58
-           errno = EINVAL;
59
-           return NULL;
60
-       }
61
-
62
        if (profile & (SPA_BT_PROFILE_BAP_SINK))
63
            n_sink++;
64
        if (profile & (SPA_BT_PROFILE_BAP_SOURCE))
65
@@ -1344,28 +1372,51 @@
66
 
67
        name = spa_bt_profile_name(profile);
68
 
69
-       media_codec = get_supported_media_codec(this, codec, &idx);
70
-       if (media_codec == NULL) {
71
-           errno = EINVAL;
72
+       /* If we can't codec switch, emit codecless profile */
73
+       if (current && !can_bap_codec_switch(this)) {
74
+           codec = 0;
75
+           index = get_index_from_profile(this, profile_index, codec);
76
+       } else if ((codec != 0) != can_bap_codec_switch(this)) {
77
+           errno = -EINVAL;
78
            return NULL;
79
        }
80
-       name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
81
-       name = name_and_codec;
82
-       switch (profile) {
83
-       case SPA_BT_PROFILE_BAP_SINK:
84
-           desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"),
85
-                            media_codec->description);
86
-           break;
87
-       case SPA_BT_PROFILE_BAP_SOURCE:
88
-           desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"),
89
-                            media_codec->description);
90
-           break;
91
-       default:
92
-           desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"),
93
-                            media_codec->description);
94
+
95
+       if (codec) {
96
+           media_codec = get_supported_media_codec(this, codec, &idx);
97
+           if (media_codec == NULL) {
98
+               errno = EINVAL;
99
+               return NULL;
100
+           }
101
+           name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
102
+           name = name_and_codec;
103
+           switch (profile) {
104
+           case SPA_BT_PROFILE_BAP_SINK:
105
+               desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"),
106
+                       media_codec->description);
107
+               break;
108
+           case SPA_BT_PROFILE_BAP_SOURCE:
109
+               desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"),
110
+                       media_codec->description);
111
+               break;
112
+           default:
113
+               desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"),
114
+                       media_codec->description);
115
+           }
116
+           desc = desc_and_codec;
117
+           priority = 128 + this->supported_codec_count - idx;  /* order as in codec list */
118
+       } else {
119
+           switch (profile) {
120
+           case SPA_BT_PROFILE_BAP_SINK:
121
+               desc = _("High Fidelity Playback (BAP Sink)");
122
+               break;
123
+           case SPA_BT_PROFILE_BAP_SOURCE:
124
+               desc = _("High Fidelity Input (BAP Source)");
125
+               break;
126
+           default:
127
+               desc = _("High Fidelity Duplex (BAP Source/Sink)");
128
+           }
129
+           priority = 128;
130
        }
131
-       desc = desc_and_codec;
132
-       priority = 128 + this->supported_codec_count - idx;  /* order as in codec list */
133
        break;
134
    }
135
    case DEVICE_PROFILE_HSP_HFP:
136
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/defs.h Changed
38
 
1
@@ -161,12 +161,13 @@
2
 #define HFP_AUDIO_CODEC_CVSD    0x01
3
 #define HFP_AUDIO_CODEC_MSBC    0x02
4
 
5
-#define MEDIA_OBJECT_MANAGER_PATH "/MediaEndpoint"
6
-#define A2DP_SINK_ENDPOINT MEDIA_OBJECT_MANAGER_PATH "/A2DPSink"
7
-#define A2DP_SOURCE_ENDPOINT   MEDIA_OBJECT_MANAGER_PATH "/A2DPSource"
8
+#define A2DP_OBJECT_MANAGER_PATH "/MediaEndpoint"
9
+#define A2DP_SINK_ENDPOINT A2DP_OBJECT_MANAGER_PATH "/A2DPSink"
10
+#define A2DP_SOURCE_ENDPOINT   A2DP_OBJECT_MANAGER_PATH "/A2DPSource"
11
 
12
-#define BAP_SINK_ENDPOINT  MEDIA_OBJECT_MANAGER_PATH "/BAPSink"
13
-#define BAP_SOURCE_ENDPOINT    MEDIA_OBJECT_MANAGER_PATH "/BAPSource"
14
+#define BAP_OBJECT_MANAGER_PATH "/MediaEndpointLE"
15
+#define BAP_SINK_ENDPOINT  BAP_OBJECT_MANAGER_PATH "/BAPSink"
16
+#define BAP_SOURCE_ENDPOINT    BAP_OBJECT_MANAGER_PATH "/BAPSource"
17
 
18
 #define SPA_BT_UNKNOWN_DELAY           0
19
 
20
@@ -358,11 +359,15 @@
21
    int powered;
22
    unsigned int has_msbc:1;
23
    unsigned int msbc_probed:1;
24
-   unsigned int endpoints_registered:1;
25
-   unsigned int application_registered:1;
26
+   unsigned int legacy_endpoints_registered:1;
27
+   unsigned int a2dp_application_registered:1;
28
+   unsigned int bap_application_registered:1;
29
    unsigned int player_registered:1;
30
    unsigned int has_battery_provider:1;
31
    unsigned int battery_provider_unavailable:1;
32
+   unsigned int le_audio_supported:1;
33
+   unsigned int has_adapter1_interface:1;
34
+   unsigned int has_media1_interface:1;
35
 };
36
 
37
 enum spa_bt_form_factor {
38
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/meson.build Changed
14
 
1
@@ -1,12 +1,5 @@
2
 gnome = import('gnome')
3
 
4
-bluez5_deps =  mathlib, dbus_dep, glib2_dep, sbc_dep, bluez_dep, gio_dep, gio_unix_dep 
5
-foreach dep: bluez5_deps
6
-  if not dep.found()
7
-    subdir_done()
8
-  endif
9
-endforeach
10
-
11
 cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE',
12
           get_option('bluez5-backend-hsp-native').allowed() or
13
           get_option('bluez5-backend-hfp-native').allowed())
14
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.66.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp Changed
86
 
1
@@ -35,6 +35,7 @@
2
 #include <limits.h>
3
 
4
 #include <linux/media.h>
5
+#include <libcamera/control_ids.h>
6
 
7
 int spa_libcamera_open(struct impl *impl)
8
 {
9
@@ -458,6 +459,38 @@
10
 
11
 }
12
 
13
+static struct {
14
+   uint32_t id;
15
+   uint32_t spa_id;
16
+} control_map = {
17
+   { libcamera::controls::BRIGHTNESS, SPA_PROP_brightness },
18
+   { libcamera::controls::CONTRAST, SPA_PROP_contrast },
19
+   { libcamera::controls::SATURATION, SPA_PROP_saturation },
20
+   { libcamera::controls::EXPOSURE_TIME, SPA_PROP_exposure },
21
+   { libcamera::controls::ANALOGUE_GAIN, SPA_PROP_gain },
22
+   { libcamera::controls::SHARPNESS, SPA_PROP_sharpness },
23
+};
24
+
25
+static uint32_t control_to_prop_id(struct impl *impl, uint32_t control_id)
26
+{
27
+   SPA_FOR_EACH_ELEMENT_VAR(control_map, c) {
28
+       if (c->id == control_id)
29
+           return c->spa_id;
30
+   }
31
+   return SPA_PROP_START_CUSTOM + control_id;
32
+}
33
+
34
+static uint32_t prop_id_to_control(struct impl *impl, uint32_t prop_id)
35
+{
36
+   SPA_FOR_EACH_ELEMENT_VAR(control_map, c) {
37
+       if (c->spa_id == prop_id)
38
+           return c->id;
39
+   }
40
+   if (prop_id >= SPA_PROP_START_CUSTOM)
41
+       return prop_id - SPA_PROP_START_CUSTOM;
42
+   return SPA_ID_INVALID;
43
+}
44
+
45
 static int
46
 spa_libcamera_enum_controls(struct impl *impl, struct port *port, int seq,
47
               uint32_t start, uint32_t num,
48
@@ -469,7 +502,7 @@
49
    struct spa_pod_frame f2;
50
    struct spa_result_node_params result;
51
    struct spa_pod *ctrl;
52
-   uint32_t count = 0, skip;
53
+   uint32_t count = 0, skip, id;
54
    int res;
55
    const ControlId *ctrl_id;
56
    ControlInfo ctrl_info;
57
@@ -492,10 +525,12 @@
58
    ctrl_id = it->first;
59
    ctrl_info = it->second;
60
 
61
+   id = control_to_prop_id(impl, ctrl_id->id());
62
+
63
    spa_pod_builder_init(&b, buffer, sizeof(buffer));
64
    spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
65
    spa_pod_builder_add(&b,
66
-           SPA_PROP_INFO_id,   SPA_POD_Id(ctrl_id->id()),
67
+           SPA_PROP_INFO_id,   SPA_POD_Id(id),
68
            SPA_PROP_INFO_description, SPA_POD_String(ctrl_id->name().c_str()),
69
            0);
70
 
71
@@ -601,8 +636,13 @@
72
    const ControlId *ctrl_id;
73
    int res;
74
    struct val d;
75
+   uint32_t control_id;
76
+
77
+   control_id = prop_id_to_control(impl, prop->key);
78
+   if (control_id == SPA_ID_INVALID)
79
+       return -ENOENT;
80
 
81
-   auto v = info.idmap().find(prop->key);
82
+   auto v = info.idmap().find(control_id);
83
    if (v == info.idmap().end())
84
        return -ENOENT;
85
 
86
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/libcamera/meson.build Changed
20
 
1
@@ -5,13 +5,8 @@
2
   'libcamera-source.cpp'
3
 
4
 
5
-libdrm_dep = dependency('libdrm', version : '>= 2.4.98',
6
-                        required : get_option('libcamera'))
7
-summary({'libdrm': libdrm_dep.found()}, bool_yn: true, section: 'Backend')
8
-if libdrm_dep.found()
9
-  libcameralib = shared_library('spa-libcamera',
10
-    libcamera_sources,
11
-    dependencies :  spa_dep, libudev_dep, libcamera_dep, pthread_lib, libdrm_dep  ,
12
-    install : true,
13
-    install_dir : spa_plugindir / 'libcamera')
14
-endif
15
+libcameralib = shared_library('spa-libcamera',
16
+  libcamera_sources,
17
+  dependencies :  spa_dep, libudev_dep, libcamera_dep, pthread_lib  ,
18
+  install : true,
19
+  install_dir : spa_plugindir / 'libcamera')
20
pipewire-0.3.65.tar.gz/spa/plugins/support/journal.c -> pipewire-0.3.66.tar.gz/spa/plugins/support/journal.c Changed
20
 
1
@@ -22,6 +22,8 @@
2
  * DEALINGS IN THE SOFTWARE.
3
  */
4
 
5
+#include "config.h"
6
+
7
 #include <stddef.h>
8
 #include <unistd.h>
9
 #include <string.h>
10
@@ -114,6 +116,9 @@
11
    sd_journal_send_with_location(file_buffer, line_buffer, func,
12
                      "MESSAGE=%s", message_buffer,
13
                      "PRIORITY=%i", priority,
14
+#ifdef HAVE_GETTID
15
+                     "TID=%jd", (intmax_t) gettid(),
16
+#endif
17
                      NULL);
18
 }
19
 
20
pipewire-0.3.65.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/support/meson.build Changed
18
 
1
@@ -18,7 +18,7 @@
2
 spa_support_lib = shared_library('spa-support',
3
   spa_support_sources,
4
   c_args :  simd_cargs ,
5
-  dependencies :  spa_dep, pthread_lib, epoll_shim_dep ,
6
+  dependencies :  spa_dep, pthread_lib, epoll_shim_dep, mathlib ,
7
   install : true,
8
   install_dir : spa_plugindir / 'support')
9
 spa_support_dep = declare_dependency(link_with: spa_support_lib)
10
@@ -61,6 +61,7 @@
11
 
12
   spa_journal_lib = shared_library('spa-journal',
13
     spa_journal_sources,
14
+    include_directories :  configinc ,
15
     dependencies :  spa_dep, systemd_dep ,
16
     install : true,
17
     install_dir : spa_plugindir / 'support')
18
pipewire-0.3.65.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.66.tar.gz/spa/plugins/support/node-driver.c Changed
201
 
1
@@ -27,6 +27,7 @@
2
 #include <unistd.h>
3
 #include <string.h>
4
 #include <stdio.h>
5
+#include <fcntl.h>
6
 
7
 #include <spa/support/plugin.h>
8
 #include <spa/support/log.h>
9
@@ -34,6 +35,7 @@
10
 #include <spa/utils/names.h>
11
 #include <spa/utils/result.h>
12
 #include <spa/utils/string.h>
13
+#include <spa/utils/dll.h>
14
 #include <spa/node/node.h>
15
 #include <spa/node/keys.h>
16
 #include <spa/node/io.h>
17
@@ -43,11 +45,20 @@
18
 #define NAME "driver"
19
 
20
 #define DEFAULT_FREEWHEEL  false
21
-#define DEFAULT_CLOCK_NAME "clock.system.monotonic"
22
+#define DEFAULT_CLOCK_PREFIX   "clock.system"
23
+#define DEFAULT_CLOCK_ID   CLOCK_MONOTONIC
24
+
25
+#define CLOCKFD 3
26
+#define FD_TO_CLOCKID(fd)  ((~(clockid_t) (fd) << 3) | CLOCKFD)
27
+#define CLOCKID_TO_FD(clk) ((unsigned int) ~((clk) >> 3))
28
+
29
+#define BW_PERIOD  (3 * SPA_NSEC_PER_SEC)
30
+#define MAX_ERROR_MS   1
31
 
32
 struct props {
33
    bool freewheel;
34
    char clock_name64;
35
+   clockid_t clock_id;
36
 };
37
 
38
 struct impl {
39
@@ -72,19 +83,62 @@
40
 
41
    struct spa_source timer_source;
42
    struct itimerspec timerspec;
43
+   int clock_fd;
44
 
45
    bool started;
46
    bool following;
47
+   bool tracking;
48
+   clockid_t timer_clockid;
49
    uint64_t next_time;
50
+   uint64_t last_time;
51
+   uint64_t base_time;
52
+   struct spa_dll dll;
53
+   double max_error;
54
 };
55
 
56
 static void reset_props(struct props *props)
57
 {
58
    props->freewheel = DEFAULT_FREEWHEEL;
59
-   spa_scnprintf(props->clock_name, sizeof(props->clock_name),
60
-           "%s", DEFAULT_CLOCK_NAME);
61
+   spa_zero(props->clock_name);
62
+   props->clock_id = CLOCK_MONOTONIC;
63
 }
64
 
65
+static const struct clock_info {
66
+   const char *name;
67
+   clockid_t id;
68
+} clock_info = {
69
+   { "realtime", CLOCK_REALTIME },
70
+   { "tai", CLOCK_TAI },
71
+   { "monotonic", CLOCK_MONOTONIC },
72
+   { "monotonic-raw", CLOCK_MONOTONIC_RAW },
73
+   { "boottime", CLOCK_BOOTTIME },
74
+};
75
+
76
+static bool clock_for_timerfd(clockid_t id)
77
+{
78
+   return id == CLOCK_REALTIME ||
79
+       id == CLOCK_MONOTONIC ||
80
+       id == CLOCK_BOOTTIME;
81
+}
82
+
83
+static clockid_t clock_name_to_id(const char *name)
84
+{
85
+   SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) {
86
+       if (spa_streq(i->name, name))
87
+           return i->id;
88
+   }
89
+   return -1;
90
+}
91
+static const char *clock_id_to_name(clockid_t id)
92
+{
93
+   SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) {
94
+       if (i->id == id)
95
+           return i->name;
96
+   }
97
+   return "custom";
98
+}
99
+
100
+
101
 static void set_timeout(struct impl *this, uint64_t next_time)
102
 {
103
    spa_log_trace(this->log, "set timeout %"PRIu64, next_time);
104
@@ -94,14 +148,22 @@
105
            this->timer_source.fd, SPA_FD_TIMER_ABSTIME, &this->timerspec, NULL);
106
 }
107
 
108
+static inline uint64_t gettime_nsec(struct impl *this, clockid_t clock_id)
109
+{
110
+   struct timespec now = { 0 };
111
+   uint64_t nsec;
112
+   if (spa_system_clock_gettime(this->data_system, clock_id, &now) < 0)
113
+       return 0;
114
+   nsec = SPA_TIMESPEC_TO_NSEC(&now);
115
+   spa_log_trace(this->log, "%p now:%"PRIu64, this, nsec);
116
+   return nsec;
117
+}
118
+
119
 static int set_timers(struct impl *this)
120
 {
121
-   struct timespec now;
122
-   int res;
123
+   this->next_time = gettime_nsec(this, this->timer_clockid);
124
 
125
-   if ((res = spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now)) < 0)
126
-       return res;
127
-   this->next_time = SPA_TIMESPEC_TO_NSEC(&now);
128
+   spa_log_debug(this->log, "%p now:%"PRIu64, this, this->next_time);
129
 
130
    if (this->following) {
131
        set_timeout(this, 0);
132
@@ -176,15 +238,23 @@
133
    return 0;
134
 }
135
 
136
+static inline uint64_t scale_u64(uint64_t val, uint32_t num, uint32_t denom)
137
+{
138
+#if 0
139
+   return ((__uint128_t)val * num) / denom;
140
+#else
141
+   return (double)val / denom * num;
142
+#endif
143
+}
144
+
145
 static void on_timeout(struct spa_source *source)
146
 {
147
    struct impl *this = source->data;
148
-   uint64_t expirations, nsec, duration;
149
+   uint64_t expirations, nsec, duration, current_time, current_position, position;
150
    uint32_t rate;
151
+   double corr = 1.0, err = 0.0;
152
    int res;
153
 
154
-   spa_log_trace(this->log, "timeout");
155
-
156
    if ((res = spa_system_timerfd_read(this->data_system,
157
                this->timer_source.fd, &expirations)) < 0) {
158
        if (res != EAGAIN)
159
@@ -192,9 +262,6 @@
160
                    this, spa_strerror(res));
161
        return;
162
    }
163
-
164
-   nsec = this->next_time;
165
-
166
    if (SPA_LIKELY(this->position)) {
167
        duration = this->position->clock.duration;
168
        rate = this->position->clock.rate.denom;
169
@@ -202,15 +269,61 @@
170
        duration = 1024;
171
        rate = 48000;
172
    }
173
+   nsec = this->next_time;
174
+
175
+   if (this->tracking)
176
+       /* we are actually following another clock */
177
+       current_time = gettime_nsec(this, this->props.clock_id);
178
+   else
179
+       current_time = nsec;
180
+
181
+   current_position = scale_u64(current_time, rate, SPA_NSEC_PER_SEC);
182
+
183
+   if (SPA_LIKELY(this->clock))
184
+       position = this->clock->position;
185
+   else
186
+       position = current_position;
187
+
188
+   if (this->last_time == 0) {
189
+       spa_dll_set_bw(&this->dll, SPA_DLL_BW_MIN, duration, rate);
190
+       this->max_error = rate * MAX_ERROR_MS / 1000;
191
+       position = current_position;
192
+   }
193
 
194
-   this->next_time = nsec + duration * SPA_NSEC_PER_SEC / rate;
195
+   /* check the elapsed time of the other clock against
196
+    * the graph clock elapsed time, feed this error into the
197
+    * dll and adjust the timeout of our MONOTONIC clock. */
198
+   err = (double)position - (double)current_position;
199
+   if (err > this->max_error)
200
+       err = this->max_error;
201
pipewire-0.3.65.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/client-rt.conf.in Changed
13
 
1
@@ -31,8 +31,9 @@
2
 
3
 context.modules = 
4
     #{ name = <module-name>
5
-    #     args  = { <key> = <value> ... } 
6
-    #     flags =   ifexists   nofail  
7
+    #    ( args  = { <key> = <value> ... } )
8
+    #    ( flags =  ( ifexists ) ( nofail )  )
9
+    #    ( condition =  { <key> = <value> ... } ...  )
10
     #}
11
     #
12
     # Loads a module with the given parameters.
13
pipewire-0.3.65.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/client.conf.in Changed
13
 
1
@@ -31,8 +31,9 @@
2
 
3
 context.modules = 
4
     #{ name = <module-name>
5
-    #     args  = { <key> = <value> ... } 
6
-    #     flags =   ifexists   nofail  
7
+    #    ( args  = { <key> = <value> ... } )
8
+    #    ( flags =  ( ifexists ) ( nofail )  )
9
+    #    ( condition =  { <key> = <value> ... } ...  )
10
     #}
11
     #
12
     # Loads a module with the given parameters.
13
pipewire-0.3.65.tar.gz/src/daemon/filter-chain.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/filter-chain.conf.in Changed
13
 
1
@@ -30,8 +30,9 @@
2
 
3
 context.modules = 
4
     #{ name = <module-name>
5
-    #     args  = { <key> = <value> ... } 
6
-    #     flags =   ifexists   nofail  
7
+    #    ( args  = { <key> = <value> ... } )
8
+    #    ( flags =  ( ifexists ) ( nofail )  )
9
+    #    ( condition =  { <key> = <value> ... } ...  )
10
     #}
11
     #
12
     # Loads a module with the given parameters.
13
pipewire-0.3.66.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf Added
159
 
1
@@ -0,0 +1,157 @@
2
+# Headphone surround sink
3
+#
4
+# Copy this file into a conf.d/ directory such as
5
+# ~/.config/pipewire/filter-chain.conf.d/
6
+#
7
+context.modules = 
8
+    { name = libpipewire-module-filter-chain
9
+        args = {
10
+            node.description = "Spatial Sink"
11
+            media.name       = "Spatial Sink"
12
+            filter.graph = {
13
+                nodes = 
14
+                    {
15
+                        type = sofa
16
+                        label = spatializer
17
+                        name = spFL
18
+                        config = {
19
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
20
+                        }
21
+                        control = {
22
+                            "Azimuth"    = 30.0
23
+                            "Elevation"  = 0.0
24
+                            "Radius"     = 3.0
25
+                        }
26
+                    }
27
+                    {
28
+                        type = sofa
29
+                        label = spatializer
30
+                        name = spFR
31
+                        config = {
32
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
33
+                        }
34
+                        control = {
35
+                            "Azimuth"    = 330.0
36
+                            "Elevation"  = 0.0
37
+                            "Radius"     = 3.0
38
+                        }
39
+                    }
40
+                    {
41
+                        type = sofa
42
+                        label = spatializer
43
+                        name = spFC
44
+                        config = {
45
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
46
+                        }
47
+                        control = {
48
+                            "Azimuth"    = 0.0
49
+                            "Elevation"  = 0.0
50
+                            "Radius"     = 3.0
51
+                        }
52
+                    }
53
+                    {
54
+                        type = sofa
55
+                        label = spatializer
56
+                        name = spRL
57
+                        config = {
58
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
59
+                        }
60
+                        control = {
61
+                            "Azimuth"    = 150.0
62
+                            "Elevation"  = 0.0
63
+                            "Radius"     = 3.0
64
+                        }
65
+                    }
66
+                    {
67
+                        type = sofa
68
+                        label = spatializer
69
+                        name = spRR
70
+                        config = {
71
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
72
+                        }
73
+                        control = {
74
+                            "Azimuth"    = 210.0
75
+                            "Elevation"  = 0.0
76
+                            "Radius"     = 3.0
77
+                        }
78
+                    }
79
+                    {
80
+                        type = sofa
81
+                        label = spatializer
82
+                        name = spSL
83
+                        config = {
84
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
85
+                        }
86
+                        control = {
87
+                            "Azimuth"    = 90.0
88
+                            "Elevation"  = 0.0
89
+                            "Radius"     = 3.0
90
+                        }
91
+                    }
92
+                    {
93
+                        type = sofa
94
+                        label = spatializer
95
+                        name = spSR
96
+                        config = {
97
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
98
+                        }
99
+                        control = {
100
+                            "Azimuth"    = 270.0
101
+                            "Elevation"  = 0.0
102
+                            "Radius"     = 3.0
103
+                        }
104
+                    }
105
+                    {
106
+                        type = sofa
107
+                        label = spatializer
108
+                        name = spLFE
109
+                        config = {
110
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
111
+                        }
112
+                        control = {
113
+                            "Azimuth"    = 0.0
114
+                            "Elevation"  = -60.0
115
+                            "Radius"     = 3.0
116
+                        }
117
+                    }
118
+
119
+                    { type = builtin label = mixer name = mixL }
120
+                    { type = builtin label = mixer name = mixR }
121
+                
122
+                links = 
123
+                    # output
124
+                    { output = "spFL:Out L"  input="mixL:In 1" }
125
+                    { output = "spFL:Out R"  input="mixR:In 1" }
126
+                    { output = "spFR:Out L"  input="mixL:In 2" }
127
+                    { output = "spFR:Out R"  input="mixR:In 2" }
128
+                    { output = "spFC:Out L"  input="mixL:In 3" }
129
+                    { output = "spFC:Out R"  input="mixR:In 3" }
130
+                    { output = "spRL:Out L"  input="mixL:In 4" }
131
+                    { output = "spRL:Out R"  input="mixR:In 4" }
132
+                    { output = "spRR:Out L"  input="mixL:In 5" }
133
+                    { output = "spRR:Out R"  input="mixR:In 5" }
134
+                    { output = "spSL:Out L"  input="mixL:In 6" }
135
+                    { output = "spSL:Out R"  input="mixR:In 6" }
136
+                    { output = "spSR:Out L"  input="mixL:In 7" }
137
+                    { output = "spSR:Out R"  input="mixR:In 7" }
138
+                    { output = "spLFE:Out L" input="mixL:In 8" }
139
+                    { output = "spLFE:Out R" input="mixR:In 8" }
140
+                
141
+                inputs  =  "spFL:In" "spFR:In" "spFC:In" "spLFE:In" "spRL:In" "spRR:In", "spSL:In", "spSR:In" 
142
+                outputs =  "mixL:Out" "mixR:Out" 
143
+            }
144
+            capture.props = {
145
+                node.name      = "effect_input.spatializer"
146
+                media.class    = Audio/Sink
147
+                audio.channels = 8
148
+                audio.position =  FL FR FC LFE RL RR SL SR 
149
+            }
150
+            playback.props = {
151
+                node.name      = "effect_output.spatializer"
152
+                node.passive   = true
153
+                audio.channels = 2
154
+                audio.position =  FL FR 
155
+            }
156
+        }
157
+    }
158
+
159
pipewire-0.3.66.tar.gz/src/daemon/filter-chain/spatializer-single.conf Added
47
 
1
@@ -0,0 +1,45 @@
2
+# A virtual sound source sink
3
+# Useful for testing spatial effects by moving it around with controls
4
+#
5
+# Copy this file into a conf.d/ directory such as
6
+# ~/.config/pipewire/filter-chain.conf.d/
7
+#
8
+context.modules = 
9
+    { name = libpipewire-module-filter-chain
10
+        args = {
11
+            node.description = "3D Sink"
12
+            media.name       = "3D Sink"
13
+            filter.graph = {
14
+                nodes = 
15
+                    {
16
+                        type = sofa
17
+                        label = spatializer
18
+                        name = sp
19
+                        config = {
20
+                            filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa"
21
+                        }
22
+                        control = {
23
+                            "Azimuth"    = 220.0
24
+                            "Elevation"  = 0.0
25
+                            "Radius"     = 3.0
26
+                        }
27
+                    }
28
+                
29
+                inputs  =  "sp:In" 
30
+                outputs =  "sp:Out L" "sp:Out R" 
31
+            }
32
+            capture.props = {
33
+                node.name      = "effect_input.3d"
34
+                media.class    = Audio/Sink
35
+                audio.channels = 1
36
+                audio.position =  FC 
37
+            }
38
+            playback.props = {
39
+                node.name      = "effect_output.3d"
40
+                node.passive   = true
41
+                audio.channels = 2
42
+                audio.position =  FL FR 
43
+            }
44
+        }
45
+    }
46
+
47
pipewire-0.3.65.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/jack.conf.in Changed
13
 
1
@@ -30,8 +30,9 @@
2
 
3
 context.modules = 
4
     #{ name = <module-name>
5
-    #     args  = { <key> = <value> ... } 
6
-    #     flags =   ifexists   nofail  
7
+    #    ( args  = { <key> = <value> ... } )
8
+    #    ( flags =  ( ifexists ) ( nofail )  )
9
+    #    ( condition =  { <key> = <value> ... } ...  )
10
     #}
11
     #
12
     # Loads a module with the given parameters.
13
pipewire-0.3.65.tar.gz/src/daemon/meson.build -> pipewire-0.3.66.tar.gz/src/daemon/meson.build Changed
24
 
1
@@ -72,6 +72,7 @@
2
  'minimal.conf',
3
  'pipewire-pulse.conf',
4
  'pipewire-avb.conf',
5
+ 'pipewire-aes67.conf',
6
 
7
 
8
 foreach c : conf_files
9
@@ -109,6 +110,14 @@
10
   dependencies :  spa_dep, pipewire_dep, ,
11
 )
12
 
13
+executable('pipewire-aes67',
14
+  pipewire_daemon_sources,
15
+  install: true,
16
+  c_args : pipewire_c_args,
17
+  include_directories :  configinc ,
18
+  dependencies :  spa_dep, pipewire_dep, ,
19
+)
20
+
21
 ln = find_program('ln')
22
 
23
 custom_target('pipewire-uninstalled',
24
pipewire-0.3.65.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/minimal.conf.in Changed
37
 
1
@@ -60,8 +60,9 @@
2
 
3
 context.modules = 
4
     #{ name = <module-name>
5
-    #     args  = { <key> = <value> ... } 
6
-    #     flags =   ifexists   nofail  
7
+    #    ( args  = { <key> = <value> ... } )
8
+    #    ( flags =  ( ifexists ) ( nofail )  )
9
+    #    ( condition =  { <key> = <value> ... } ...  )
10
     #}
11
     #
12
     # Loads a module with the given parameters.
13
@@ -135,8 +136,9 @@
14
 
15
 context.objects = 
16
     #{ factory = <factory-name>
17
-    #     args  = { <key> = <value> ... } 
18
-    #     flags =   nofail  
19
+    #    ( args  = { <key> = <value> ... } )
20
+    #    ( flags =  ( nofail )  )
21
+    #    ( condition =  { <key> = <value> ... } ...  )
22
     #}
23
     #
24
     # Creates an object from a PipeWire factory with the given parameters.
25
@@ -339,7 +341,10 @@
26
 
27
 
28
 context.exec = 
29
-    #{ path = <program-name>  args = "<arguments>"  }
30
+    #{   path = <program-name>
31
+    #    ( args = "<arguments>" )
32
+    #    ( condition =  { <key> = <value> ... } ...  )
33
+    #}
34
     #
35
     # Execute the given program with arguments.
36
     #
37
pipewire-0.3.66.tar.gz/src/daemon/pipewire-aes67.conf.in Added
54
 
1
@@ -0,0 +1,52 @@
2
+# AES67 config file for PipeWire version @VERSION@ #
3
+#
4
+# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
5
+# or in ~/.config/pipewire for local changes.
6
+#
7
+# It is also possible to place a file with an updated section in
8
+# @PIPEWIRE_CONFIG_DIR@/pipewire-aes67.conf.d/ for system-wide changes or in
9
+# ~/.config/pipewire/pipewire-aes67.conf.d/ for local changes.
10
+#
11
+
12
+context.properties = {
13
+    ## Configure properties in the system.
14
+    #mem.warn-mlock  = false
15
+    #mem.allow-mlock = true
16
+    #mem.mlock-all   = false
17
+    #log.level       = 2
18
+
19
+    #default.clock.quantum-limit = 8192
20
+}
21
+
22
+#context.spa-libs = {
23
+#    audio.convert.* = audioconvert/libspa-audioconvert
24
+#    support.*       = support/libspa-support
25
+#}
26
+
27
+context.modules = 
28
+    { name = libpipewire-module-rt
29
+        args = {
30
+            nice.level   = -11
31
+            #rt.prio      = 88
32
+            #rt.time.soft = -1
33
+            #rt.time.hard = -1
34
+        }
35
+        flags =  ifexists nofail 
36
+    }
37
+    { name = libpipewire-module-protocol-native }
38
+    { name = libpipewire-module-client-node }
39
+    { name = libpipewire-module-adapter }
40
+    { name = libpipewire-module-rtp-source
41
+        args = {
42
+            sap.ip = 239.255.255.255
43
+            sap.port = 9875
44
+            sess.latency.msec = 10
45
+            local.ifname = eth0
46
+            stream.props = {
47
+               media.class = "Audio/Source"
48
+               node.virtual = false
49
+               device.api = aes67
50
+            }
51
+        }
52
+    }
53
+
54
pipewire-0.3.65.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
15
 
1
@@ -57,11 +57,11 @@
2
 # Extra commands can be executed here.
3
 #   load-module : loads a module with args and flags
4
 #      args = "<module-name> <module-args>"
5
-#      flags =  "no-fail" 
6
+#      ( flags =  nofail  )
7
 pulse.cmd = 
8
     { cmd = "load-module" args = "module-always-sink" flags =   }
9
     #{ cmd = "load-module" args = "module-switch-on-connect" }
10
-    #{ cmd = "load-module" args = "module-gsettings" flags =  "nofail"  }
11
+    #{ cmd = "load-module" args = "module-gsettings" flags =  nofail  }
12
 
13
 
14
 stream.properties = {
15
pipewire-0.3.65.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/pipewire.conf.in Changed
109
 
1
@@ -29,7 +29,7 @@
2
     #default.clock.rate          = 48000
3
     #default.clock.allowed-rates =  48000 
4
     #default.clock.quantum       = 1024
5
-    default.clock.min-quantum   = 16
6
+    #default.clock.min-quantum   = 32
7
     #default.clock.max-quantum   = 2048
8
     #default.clock.quantum-limit = 8192
9
     #default.video.width         = 640
10
@@ -44,6 +44,9 @@
11
     vm.overrides = {
12
         default.clock.min-quantum = 1024
13
     }
14
+
15
+    # keys checked below to disable module loading
16
+    module.x11.bell = true
17
 }
18
 
19
 context.spa-libs = {
20
@@ -68,13 +71,16 @@
21
 
22
 context.modules = 
23
     #{ name = <module-name>
24
-    #     args  = { <key> = <value> ... } 
25
-    #     flags =   ifexists   nofail  
26
+    #    ( args  = { <key> = <value> ... } )
27
+    #    ( flags =  ( ifexists ) ( nofail )  )
28
+    #    ( condition =  { <key> = <value> ... } ...  )
29
     #}
30
     #
31
     # Loads a module with the given parameters.
32
     # If ifexists is given, the module is ignored when it is not found.
33
     # If nofail is given, module initialization failures are ignored.
34
+    # If condition is given, the module is loaded only when the context
35
+    # properties all match the match rules.
36
     #
37
 
38
     # Uses realtime scheduling to boost the audio thread priorities. This uses
39
@@ -167,17 +173,21 @@
40
             #x11.xauthority = null
41
         }
42
         flags =  ifexists nofail 
43
+        condition =  { module.x11.bell = true } 
44
     }
45
 
46
 
47
 context.objects = 
48
     #{ factory = <factory-name>
49
-    #     args  = { <key> = <value> ... } 
50
-    #     flags =   nofail  
51
+    #    ( args  = { <key> = <value> ... } )
52
+    #    ( flags =  ( nofail )  )
53
+    #    ( condition =  { <key> = <value> ... } ...  )
54
     #}
55
     #
56
     # Creates an object from a PipeWire factory with the given parameters.
57
     # If nofail is given, errors are ignored (and no object is created).
58
+    # If condition is given, the object is created only when the context properties
59
+    # all match the match rules.
60
     #
61
     #{ factory = spa-node-factory   args = { factory.name = videotestsrc node.name = videotestsrc Spa:Pod:Object:Param:Props:patternType = 1 } }
62
     #{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags =  nofail  }
63
@@ -194,6 +204,8 @@
64
             node.name       = Dummy-Driver
65
             node.group      = pipewire.dummy
66
             priority.driver = 20000
67
+            #clock.id       = monotonic # realtime | tai | monotonic-raw | boottime
68
+            #clock.name     = "clock.system.monotonic"
69
         }
70
     }
71
     { factory = spa-node-factory
72
@@ -205,6 +217,20 @@
73
             node.freewheel  = true
74
         }
75
     }
76
+    # An example clock reading from /dev/ptp0. Another option is to sync the
77
+    # ptp clock to CLOCK_TAI and then set clock.id = tai.
78
+    #{ factory = spa-node-factory
79
+    #    args = {
80
+    #        factory.name    = support.node.driver
81
+    #        node.name       = PTP0-Driver
82
+    #        node.group      = pipewire.ptp0
83
+    #        priority.driver = 30000
84
+    #        clock.name      = "clock.system.ptp0"
85
+    #        #clock.id       = tai
86
+    #        clock.device    = "/dev/ptp0"
87
+    #    }
88
+    #}
89
+
90
     # This creates a new Source node. It will have input ports
91
     # that you can link, to provide audio for this source.
92
     #{ factory = adapter
93
@@ -240,9 +266,14 @@
94
 
95
 
96
 context.exec = 
97
-    #{ path = <program-name>  args = "<arguments>"  }
98
+    #{   path = <program-name>
99
+    #    ( args = "<arguments>" )
100
+    #    ( condition =  { <key> = <value> ... } ...  )
101
+    #}
102
     #
103
     # Execute the given program with arguments.
104
+    # If condition is given, the program is executed only when the context
105
+    # properties all match the match rules.
106
     #
107
     # You can optionally start the session manager here,
108
     # but it is better to start it as a systemd service.
109
pipewire-0.3.65.tar.gz/src/gst/gstpipewirepool.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewirepool.c Changed
69
 
1
@@ -109,6 +109,16 @@
2
       gst_buffer_insert_memory (buf, i, gmem);
3
   }
4
 
5
+  if (pool->add_metavideo) {
6
+    gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
7
+        GST_VIDEO_INFO_FORMAT (&pool->video_info),
8
+        GST_VIDEO_INFO_WIDTH (&pool->video_info),
9
+        GST_VIDEO_INFO_HEIGHT (&pool->video_info),
10
+        GST_VIDEO_INFO_N_PLANES (&pool->video_info),
11
+        pool->video_info.offset,
12
+        pool->video_info.stride);
13
+  }
14
+
15
   data->pool = gst_object_ref (pool);
16
   data->owner = NULL;
17
   data->header = spa_buffer_find_meta_data (b->buffer, SPA_META_Header, sizeof(*data->header));
18
@@ -208,6 +218,41 @@
19
   }
20
 }
21
 
22
+static const gchar **
23
+get_options (GstBufferPool * pool)
24
+{
25
+  static const gchar *options = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
26
+  return options;
27
+}
28
+
29
+static gboolean
30
+set_config (GstBufferPool * pool, GstStructure * config)
31
+{
32
+  GstPipeWirePool *p = GST_PIPEWIRE_POOL (pool);
33
+  GstCaps *caps;
34
+  guint size, min_buffers, max_buffers;
35
+  gboolean has_video;
36
+
37
+  if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) {
38
+    GST_WARNING_OBJECT (pool, "invalid config");
39
+    return FALSE;
40
+  }
41
+
42
+  if (caps == NULL) {
43
+    GST_WARNING_OBJECT (pool, "no caps in config");
44
+    return FALSE;
45
+  }
46
+
47
+  has_video = gst_video_info_from_caps (&p->video_info, caps);
48
+
49
+  p->add_metavideo = has_video && gst_buffer_pool_config_has_option (config,
50
+      GST_BUFFER_POOL_OPTION_VIDEO_META);
51
+
52
+  gst_buffer_pool_config_set_params (config, caps, p->video_info.size, min_buffers, max_buffers);
53
+
54
+  return GST_BUFFER_POOL_CLASS (gst_pipewire_pool_parent_class)->set_config (pool, config);
55
+}
56
+
57
 static void
58
 flush_start (GstBufferPool * pool)
59
 {
60
@@ -252,6 +297,8 @@
61
 
62
   gobject_class->finalize = gst_pipewire_pool_finalize;
63
 
64
+  bufferpool_class->get_options = get_options;
65
+  bufferpool_class->set_config = set_config;
66
   bufferpool_class->start = do_start;
67
   bufferpool_class->flush_start = flush_start;
68
   bufferpool_class->acquire_buffer = acquire_buffer;
69
pipewire-0.3.65.tar.gz/src/gst/gstpipewirepool.h -> pipewire-0.3.66.tar.gz/src/gst/gstpipewirepool.h Changed
20
 
1
@@ -27,6 +27,8 @@
2
 
3
 #include <gst/gst.h>
4
 
5
+#include <gst/video/video.h>
6
+
7
 #include <pipewire/pipewire.h>
8
 
9
 G_BEGIN_DECLS
10
@@ -66,6 +68,9 @@
11
   struct pw_stream *stream;
12
   struct pw_type *t;
13
 
14
+  gboolean add_metavideo;
15
+  GstVideoInfo video_info;
16
+
17
   GstAllocator *fd_allocator;
18
   GstAllocator *dmabuf_allocator;
19
 
20
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresink.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresink.c Changed
32
 
1
@@ -142,6 +142,7 @@
2
   GstPipeWireSink *pwsink = GST_PIPEWIRE_SINK (bsink);
3
 
4
   gst_query_add_allocation_pool (query, GST_BUFFER_POOL_CAST (pwsink->pool), 0, 0, 0);
5
+  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
6
   return TRUE;
7
 }
8
 
9
@@ -504,6 +505,22 @@
10
     d->chunk->stride = 0;
11
   }
12
 
13
+  GstVideoMeta *meta = gst_buffer_get_video_meta (buffer);
14
+  if (meta) {
15
+    if (meta->n_planes == b->n_datas) {
16
+      gsize video_size = 0;
17
+      for (i = 0; i < meta->n_planes; i++) {
18
+        struct spa_data *d = &b->datasi;
19
+        d->chunk->offset += meta->offseti - video_size;
20
+        d->chunk->stride = meta->stridei;
21
+
22
+        video_size += d->chunk->size;
23
+      }
24
+    } else {
25
+      GST_ERROR ("plane num not matching, meta:%u buffer:%u", meta->n_planes, b->n_datas);
26
+    }
27
+  }
28
+
29
   if ((res = pw_stream_queue_buffer (pwsink->stream, data->b)) < 0) {
30
     g_warning ("can't send buffer %s", spa_strerror(res));
31
   }
32
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresrc.c Changed
48
 
1
@@ -615,6 +615,27 @@
2
     }
3
   }
4
 
5
+  if (pwsrc->is_video) {
6
+    gsize video_size = 0;
7
+    GstVideoInfo *info = &pwsrc->video_info;
8
+    GstVideoMeta *meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
9
+                             GST_VIDEO_INFO_FORMAT (info),
10
+                             GST_VIDEO_INFO_WIDTH (info),
11
+                             GST_VIDEO_INFO_HEIGHT (info),
12
+                             GST_VIDEO_INFO_N_PLANES (info),
13
+                             info->offset,
14
+                             info->stride);
15
+
16
+    meta->n_planes = MIN(meta->n_planes, b->buffer->n_datas);
17
+    for (i = 0; i < meta->n_planes; i++) {
18
+      struct spa_data *d = &b->buffer->datasi;
19
+      meta->offseti = video_size;
20
+      meta->stridei = d->chunk->stride;
21
+
22
+      video_size += d->chunk->size;
23
+    }
24
+  }
25
+
26
   for (i = 0; i < b->buffer->n_datas; i++) {
27
     struct spa_data *d = &b->buffer->datasi;
28
     GstMemory *pmem = gst_buffer_peek_memory (data->buf, i);
29
@@ -658,6 +679,7 @@
30
     case PW_STREAM_STATE_STREAMING:
31
       break;
32
     case PW_STREAM_STATE_ERROR:
33
+      pw_stream_set_error (pwsrc->stream, -EPIPE, "%s", error);
34
       GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED,
35
           ("stream error: %s", error), (NULL));
36
       break;
37
@@ -958,6 +980,10 @@
38
           gst_caps_unref(pwsrc->caps);
39
   pwsrc->caps = gst_caps_from_format (param);
40
 
41
+  pwsrc->is_video = pwsrc->caps != NULL
42
+                      ? gst_video_info_from_caps (&pwsrc->video_info, pwsrc->caps)
43
+                      : FALSE;
44
+
45
   pwsrc->negotiated = pwsrc->caps != NULL;
46
 
47
   if (pwsrc->negotiated) {
48
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresrc.h -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresrc.h Changed
20
 
1
@@ -28,6 +28,8 @@
2
 #include <gst/gst.h>
3
 #include <gst/base/gstpushsrc.h>
4
 
5
+#include <gst/video/video.h>
6
+
7
 #include <pipewire/pipewire.h>
8
 #include <gst/gstpipewirepool.h>
9
 #include <gst/gstpipewirecore.h>
10
@@ -71,6 +73,9 @@
11
 
12
   GstCaps *caps;
13
 
14
+  gboolean is_video;
15
+  GstVideoInfo video_info;
16
+
17
   gboolean negotiated;
18
   gboolean flushing;
19
   gboolean started;
20
pipewire-0.3.65.tar.gz/src/modules/meson.build -> pipewire-0.3.66.tar.gz/src/modules/meson.build Changed
201
 
1
@@ -1,3 +1,4 @@
2
+subdir('module-rt')
3
 subdir('spa')
4
 
5
 # The list of "main" source files for modules, the ones that have the
6
@@ -108,10 +109,11 @@
7
   'module-filter-chain/biquad.c',
8
   'module-filter-chain/ladspa_plugin.c',
9
   'module-filter-chain/builtin_plugin.c',
10
+  'module-filter-chain/sofa_plugin.c',
11
   'module-filter-chain/convolver.c'
12
 
13
 filter_chain_dependencies = 
14
-  mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep
15
+  mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep, libmysofa_dep
16
 
17
 
18
 if lilv_lib.found()
19
@@ -139,7 +141,7 @@
20
 pipewire_module_combine_stream = shared_library('pipewire-module-combine-stream',
21
    'module-combine-stream.c' ,
22
   include_directories : configinc,
23
-  install : false,
24
+  install : true,
25
   install_dir : modules_install_dir,
26
   install_rpath: modules_install_dir,
27
   dependencies : spa_dep, dl_lib, pipewire_dep,
28
@@ -174,27 +176,25 @@
29
 
30
 build_module_rtkit = dbus_dep.found() and (get_option('legacy-rtkit') == true)
31
 if build_module_rtkit
32
-# TODO: This serves as a temporary alias to prevent breaking existing setups
33
-#       while `module-rtkit` is being migrated to `module-rt`
34
-pipewire_module_rtkit = shared_library('pipewire-module-rtkit',  'module-rt.c' ,
35
-  include_directories : configinc,
36
-  install : true,
37
-  install_dir : modules_install_dir,
38
-  install_rpath: modules_install_dir,
39
-  dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep,
40
-)
41
+  pipewire_module_rtkit = shared_library('pipewire-module-rtkit',  'module-rt.c' ,
42
+    include_directories : configinc,
43
+    install : true,
44
+    install_dir : modules_install_dir,
45
+    install_rpath: modules_install_dir,
46
+    dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep,
47
+  )
48
 endif
49
 summary({'rt': '@0@ RTKit'.format(build_module_rtkit ? 'with' : 'without')}, section: 'Optional Modules')
50
 
51
 build_module_portal = dbus_dep.found()
52
 if build_module_portal
53
-pipewire_module_portal = shared_library('pipewire-module-portal',  'module-portal.c' ,
54
-  include_directories : configinc,
55
-  install : true,
56
-  install_dir : modules_install_dir,
57
-  install_rpath: modules_install_dir,
58
-  dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep,
59
-)
60
+  pipewire_module_portal = shared_library('pipewire-module-portal',  'module-portal.c' ,
61
+    include_directories : configinc,
62
+    install : true,
63
+    install_dir : modules_install_dir,
64
+    install_rpath: modules_install_dir,
65
+    dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep,
66
+  )
67
 endif
68
 summary({'portal': build_module_portal}, bool_yn: true, section: 'Optional Modules')
69
 
70
@@ -332,16 +332,16 @@
71
 )
72
 
73
 build_module_pulse_tunnel = pulseaudio_dep.found()
74
-if build_module_pulse_tunnel
75
-  pipewire_module_pulse_tunnel = shared_library('pipewire-module-pulse-tunnel',
76
-   'module-pulse-tunnel.c',
77
-    'module-protocol-pulse/format.c' ,
78
-  include_directories : configinc,
79
-  install : true,
80
-  install_dir : modules_install_dir,
81
-  install_rpath: modules_install_dir,
82
-  dependencies : mathlib, dl_lib, pipewire_dep, pulseaudio_dep,
83
-)
84
+  if build_module_pulse_tunnel
85
+    pipewire_module_pulse_tunnel = shared_library('pipewire-module-pulse-tunnel',
86
+     'module-pulse-tunnel.c',
87
+      'module-protocol-pulse/format.c' ,
88
+    include_directories : configinc,
89
+    install : true,
90
+    install_dir : modules_install_dir,
91
+    install_rpath: modules_install_dir,
92
+    dependencies : mathlib, dl_lib, pipewire_dep, pulseaudio_dep,
93
+  )
94
 endif
95
 summary({'pulse-tunnel': build_module_pulse_tunnel}, bool_yn: true, section: 'Optional Modules')
96
 
97
@@ -474,44 +474,44 @@
98
 
99
 build_module_zeroconf_discover = avahi_dep.found()
100
 if build_module_zeroconf_discover
101
-pipewire_module_zeroconf_discover = shared_library('pipewire-module-zeroconf-discover',
102
-   'module-zeroconf-discover.c',
103
-    'module-protocol-pulse/format.c',
104
-    'module-zeroconf-discover/avahi-poll.c' ,
105
-  include_directories : configinc,
106
-  install : true,
107
-  install_dir : modules_install_dir,
108
-  install_rpath: modules_install_dir,
109
-  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep,
110
-)
111
+  pipewire_module_zeroconf_discover = shared_library('pipewire-module-zeroconf-discover',
112
+     'module-zeroconf-discover.c',
113
+      'module-protocol-pulse/format.c',
114
+      'module-zeroconf-discover/avahi-poll.c' ,
115
+    include_directories : configinc,
116
+    install : true,
117
+    install_dir : modules_install_dir,
118
+    install_rpath: modules_install_dir,
119
+    dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep,
120
+  )
121
 endif
122
 summary({'zeroconf-discover': build_module_zeroconf_discover}, bool_yn: true, section: 'Optional Modules')
123
 
124
 build_module_raop_discover = avahi_dep.found()
125
 if build_module_raop_discover
126
-pipewire_module_raop_discover = shared_library('pipewire-module-raop-discover',
127
-   'module-raop-discover.c',
128
-    'module-zeroconf-discover/avahi-poll.c' ,
129
-  include_directories : configinc,
130
-  install : true,
131
-  install_dir : modules_install_dir,
132
-  install_rpath: modules_install_dir,
133
-  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep,
134
-)
135
+  pipewire_module_raop_discover = shared_library('pipewire-module-raop-discover',
136
+     'module-raop-discover.c',
137
+      'module-zeroconf-discover/avahi-poll.c' ,
138
+    include_directories : configinc,
139
+    install : true,
140
+    install_dir : modules_install_dir,
141
+    install_rpath: modules_install_dir,
142
+    dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep,
143
+  )
144
 endif
145
 summary({'raop-discover (needs Avahi)': build_module_raop_discover}, bool_yn: true, section: 'Optional Modules')
146
 
147
 build_module_raop = openssl_lib.found()
148
 if build_module_raop
149
-pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink',
150
-   'module-raop-sink.c',
151
-    'module-raop/rtsp-client.c' ,
152
-  include_directories : configinc,
153
-  install : true,
154
-  install_dir : modules_install_dir,
155
-  install_rpath: modules_install_dir,
156
-  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, openssl_lib,
157
-)
158
+  pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink',
159
+     'module-raop-sink.c',
160
+      'module-raop/rtsp-client.c' ,
161
+    include_directories : configinc,
162
+    install : true,
163
+    install_dir : modules_install_dir,
164
+    install_rpath: modules_install_dir,
165
+    dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, openssl_lib,
166
+  )
167
 endif
168
 summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules')
169
 
170
@@ -538,37 +538,37 @@
171
 
172
 build_module_roc = roc_dep.found()
173
 if build_module_roc
174
-pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink',
175
-   'module-roc-sink.c' ,
176
-  include_directories : configinc,
177
-  install : true,
178
-  install_dir : modules_install_dir,
179
-  install_rpath: modules_install_dir,
180
-  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep,
181
-)
182
+  pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink',
183
+     'module-roc-sink.c' ,
184
+    include_directories : configinc,
185
+    install : true,
186
+    install_dir : modules_install_dir,
187
+    install_rpath: modules_install_dir,
188
+    dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep,
189
+  )
190
 
191
-pipewire_module_roc_source = shared_library('pipewire-module-roc-source',
192
-   'module-roc-source.c' ,
193
-  include_directories : configinc,
194
-  install : true,
195
-  install_dir : modules_install_dir,
196
-  install_rpath: modules_install_dir,
197
-  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep,
198
-)
199
+  pipewire_module_roc_source = shared_library('pipewire-module-roc-source',
200
+     'module-roc-source.c' ,
201
pipewire-0.3.65.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.66.tar.gz/src/modules/module-combine-stream.c Changed
9
 
1
@@ -847,6 +847,7 @@
2
 }
3
 
4
 static const struct pw_proxy_events core_proxy_events = {
5
+   PW_VERSION_PROXY_EVENTS,
6
    .removed = core_removed,
7
 };
8
 
9
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain.c Changed
130
 
1
@@ -273,6 +273,12 @@
2
  * - `max-delay` the maximum delay in seconds. The "Delay (s)" parameter will
3
  *              be clamped to this value.
4
  *
5
+ * ### Invert
6
+ *
7
+ * The invert plugin can be used to invert the phase of the signal.
8
+ *
9
+ * It has an input port "In" and an output port "Out".
10
+ *
11
  * ## General options
12
  *
13
  * Options with well-known behavior. Most options can be added to the global
14
@@ -445,7 +451,7 @@
15
 struct plugin {
16
    struct spa_list link;
17
    int ref;
18
-   char type64;
19
+   char type256;
20
    char pathPATH_MAX;
21
 
22
    struct fc_plugin *plugin;
23
@@ -506,6 +512,7 @@
24
    unsigned int n_deps;
25
    unsigned int visited:1;
26
    unsigned int disabled:1;
27
+   unsigned int control_changed:1;
28
 };
29
 
30
 struct link {
31
@@ -878,7 +885,8 @@
32
    old = port->control_data;
33
    port->control_data = value ? *value : desc->default_controlport->idx;
34
    pw_log_info("control %d ('%s') from %f to %f", port->idx, name, old, port->control_data);
35
-   return old == port->control_data ? 0 : 1;
36
+   node->control_changed = old != port->control_data;
37
+   return node->control_changed ? 1 : 0;
38
 }
39
 
40
 static int parse_params(struct graph *graph, const struct spa_pod *pod)
41
@@ -938,6 +946,24 @@
42
            d->activate(*hndl->hndl);
43
    }
44
 }
45
+
46
+static void node_control_changed(struct node *node)
47
+{
48
+   const struct fc_descriptor *d = node->desc->desc;
49
+   uint32_t i;
50
+
51
+   if (!node->control_changed)
52
+       return;
53
+
54
+   for (i = 0; i < node->n_hndl; i++) {
55
+       if (node->hndli == NULL)
56
+           continue;
57
+       if (d->control_changed)
58
+           d->control_changed(node->hndli);
59
+   }
60
+   node->control_changed = false;
61
+}
62
+
63
 static void param_props_changed(struct impl *impl, const struct spa_pod *param)
64
 {
65
    struct spa_pod_object *obj = (struct spa_pod_object *) param;
66
@@ -953,6 +979,10 @@
67
        uint8_t buffer1024;
68
        struct spa_pod_dynamic_builder b;
69
        const struct spa_pod *params1;
70
+       struct node *node;
71
+
72
+       spa_list_for_each(node, &graph->node_list, link)
73
+           node_control_changed(node);
74
 
75
        spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
76
        params0 = get_props_param(graph, &b.b);
77
@@ -1205,6 +1235,9 @@
78
    if (spa_streq(type, "builtin")) {
79
        pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL);
80
    }
81
+   else if (spa_streq(type, "sofa")) {
82
+       pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL);
83
+   }
84
    else if (spa_streq(type, "ladspa")) {
85
        pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL);
86
    }
87
@@ -1696,6 +1729,7 @@
88
    free(node->output_port);
89
    free(node->control_port);
90
    free(node->notify_port);
91
+   free(node->config);
92
    free(node);
93
 }
94
 
95
@@ -1767,6 +1801,8 @@
96
            }
97
            if (d->activate)
98
                d->activate(node->hndli);
99
+           if (node->control_changed && d->control_changed)
100
+               d->control_changed(node->hndli);
101
        }
102
    }
103
    return 0;
104
@@ -1902,6 +1938,8 @@
105
                    pw_log_error("input port %s not found", v);
106
                    goto error;
107
                } else {
108
+                   bool disabled = false;
109
+
110
                    desc = port->node->desc;
111
                    d = desc->desc;
112
                    if (i == 0 && port->external != SPA_ID_INVALID) {
113
@@ -1936,12 +1974,14 @@
114
                                gp->hndl = &peer->node->hndli;
115
                                gp->port = peer->p;
116
                                gp->next = true;
117
+                               disabled = true;
118
                            }
119
                            if (gp != NULL)
120
                                gp->next = false;
121
                        }
122
-                       port->node->disabled = true;
123
-                   } else {
124
+                       port->node->disabled = disabled;
125
+                   }
126
+                   if (!disabled) {
127
                        pw_log_info("input port %s%d:%s",
128
                            port->node->name, i, d->portsport->p.name);
129
                        port->external = graph->n_input;
130
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
49
 
1
@@ -978,6 +978,38 @@
2
    .cleanup = delay_cleanup,
3
 };
4
 
5
+static void invert_run(void * Instance, unsigned long SampleCount)
6
+{
7
+   struct builtin *impl = Instance;
8
+   float *in = impl->port1, *out = impl->port0;
9
+   unsigned long n;
10
+   for (n = 0; n < SampleCount; n++)
11
+       outn = -inn;
12
+}
13
+
14
+static struct fc_port invert_ports = {
15
+   { .index = 0,
16
+     .name = "Out",
17
+     .flags = FC_PORT_OUTPUT | FC_PORT_AUDIO,
18
+   },
19
+   { .index = 1,
20
+     .name = "In",
21
+     .flags = FC_PORT_INPUT | FC_PORT_AUDIO,
22
+   },
23
+};
24
+
25
+static const struct fc_descriptor invert_desc = {
26
+   .name = "invert",
27
+
28
+   .n_ports = 2,
29
+   .ports = invert_ports,
30
+
31
+   .instantiate = builtin_instantiate,
32
+   .connect_port = builtin_connect_port,
33
+   .run = invert_run,
34
+   .cleanup = builtin_cleanup,
35
+};
36
+
37
 static const struct fc_descriptor * builtin_descriptor(unsigned long Index)
38
 {
39
    switch(Index) {
40
@@ -1005,6 +1037,8 @@
41
        return &convolve_desc;
42
    case 11:
43
        return &delay_desc;
44
+   case 12:
45
+       return &invert_desc;
46
    }
47
    return NULL;
48
 }
49
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain/plugin.h -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/plugin.h Changed
17
 
1
@@ -83,6 +83,7 @@
2
    void (*cleanup) (void *instance);
3
 
4
    void (*connect_port) (void *instance, unsigned long port, float *data);
5
+   void (*control_changed) (void *instance);
6
 
7
    void (*activate) (void *instance);
8
    void (*deactivate) (void *instance);
9
@@ -108,5 +109,7 @@
10
        struct dsp_ops *dsp, const char *path, const char *config);
11
 struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
12
        struct dsp_ops *dsp, const char *path, const char *config);
13
+struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
14
+       struct dsp_ops *dsp, const char *path, const char *config);
15
 
16
 #endif /* PLUGIN_H */
17
pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/sofa_plugin.c Added
201
 
1
@@ -0,0 +1,375 @@
2
+#include "config.h"
3
+
4
+#include <spa/utils/json.h>
5
+#include <spa/support/loop.h>
6
+
7
+#include <pipewire/log.h>
8
+#include "plugin.h"
9
+#include "convolver.h"
10
+#include "dsp-ops.h"
11
+#include "pffft.h"
12
+
13
+#ifdef HAVE_LIBMYSOFA
14
+#include <mysofa.h>
15
+
16
+#define MAX_SAMPLES    8192u
17
+#endif
18
+
19
+static struct dsp_ops *dsp_ops;
20
+static struct spa_loop *data_loop;
21
+static struct spa_loop *main_loop;
22
+
23
+struct spatializer_impl {
24
+   unsigned long rate;
25
+   float *port6;
26
+   int n_samples, blocksize, tailsize;
27
+   float *tmp2;
28
+
29
+#ifdef HAVE_LIBMYSOFA
30
+   struct MYSOFA_EASY *sofa;
31
+#endif
32
+   unsigned int interpolate:1;
33
+   struct convolver *l_conv3;
34
+   struct convolver *r_conv3;
35
+};
36
+
37
+static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
38
+       unsigned long SampleRate, int index, const char *config)
39
+{
40
+#ifdef HAVE_LIBMYSOFA
41
+   struct spatializer_impl *impl;
42
+   struct spa_json it2;
43
+   const char *val;
44
+   char key256;
45
+   char filenamePATH_MAX = "";
46
+
47
+   errno = EINVAL;
48
+   if (config == NULL)
49
+       return NULL;
50
+
51
+   spa_json_init(&it0, config, strlen(config));
52
+   if (spa_json_enter_object(&it0, &it1) <= 0)
53
+       return NULL;
54
+
55
+   impl = calloc(1, sizeof(*impl));
56
+   if (impl == NULL) {
57
+       errno = ENOMEM;
58
+       return NULL;
59
+   }
60
+
61
+   while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
62
+       if (spa_streq(key, "blocksize")) {
63
+           if (spa_json_get_int(&it1, &impl->blocksize) <= 0) {
64
+               pw_log_error("spatializer:blocksize requires a number");
65
+               errno = EINVAL;
66
+               goto error;
67
+           }
68
+       }
69
+       else if (spa_streq(key, "tailsize")) {
70
+           if (spa_json_get_int(&it1, &impl->tailsize) <= 0) {
71
+               pw_log_error("spatializer:tailsize requires a number");
72
+               errno = EINVAL;
73
+               goto error;
74
+           }
75
+       }
76
+       else if (spa_streq(key, "filename")) {
77
+           if (spa_json_get_string(&it1, filename, sizeof(filename)) <= 0) {
78
+               pw_log_error("spatializer:filename requires a string");
79
+               errno = EINVAL;
80
+               goto error;
81
+           }
82
+       }
83
+       else if (spa_json_next(&it1, &val) < 0)
84
+           break;
85
+   }
86
+   if (!filename0) {
87
+       pw_log_error("spatializer:filename was not given");
88
+       errno = EINVAL;
89
+       goto error;
90
+   }
91
+
92
+   int ret = MYSOFA_OK;
93
+
94
+   impl->sofa = mysofa_open_cached(filename, SampleRate, &impl->n_samples, &ret);
95
+
96
+   if (ret != MYSOFA_OK) {
97
+       pw_log_error("Unable to load HRTF from %s: %d", filename, ret);
98
+       errno = ENOENT;
99
+       goto error;
100
+   }
101
+
102
+   if (impl->blocksize <= 0)
103
+       impl->blocksize = SPA_CLAMP(impl->n_samples, 64, 256);
104
+   if (impl->tailsize <= 0)
105
+       impl->tailsize = SPA_CLAMP(4096, impl->blocksize, 32768);
106
+
107
+   pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples,
108
+       impl->blocksize, impl->tailsize, filename);
109
+
110
+   impl->tmp0 = calloc(MAX_SAMPLES, sizeof(float));
111
+   impl->tmp1 = calloc(MAX_SAMPLES, sizeof(float));
112
+   impl->rate = SampleRate;
113
+   return impl;
114
+error:
115
+   if (impl->sofa)
116
+       mysofa_close_cached(impl->sofa);
117
+   free(impl);
118
+   return NULL;
119
+#else
120
+   pw_log_error("libmysofa is required for spatializer, but disabled at compile time");
121
+   errno = EINVAL;
122
+   return NULL;
123
+#endif
124
+}
125
+
126
+#ifdef HAVE_LIBMYSOFA
127
+static int
128
+do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
129
+       size_t size, void *user_data)
130
+{
131
+   struct spatializer_impl *impl = user_data;
132
+
133
+   if (impl->l_conv0 == NULL) {
134
+       SPA_SWAP(impl->l_conv0, impl->l_conv2);
135
+       SPA_SWAP(impl->r_conv0, impl->r_conv2);
136
+   } else {
137
+       SPA_SWAP(impl->l_conv1, impl->l_conv2);
138
+       SPA_SWAP(impl->r_conv1, impl->r_conv2);
139
+   }
140
+   impl->interpolate = impl->l_conv0 && impl->l_conv1;
141
+
142
+   return 0;
143
+}
144
+
145
+static void spatializer_reload(void * Instance)
146
+{
147
+   struct spatializer_impl *impl = Instance;
148
+   float *left_ir = calloc(impl->n_samples, sizeof(float));
149
+   float *right_ir = calloc(impl->n_samples, sizeof(float));
150
+   float left_delay;
151
+   float right_delay;
152
+   float coords3;
153
+
154
+   for (uint8_t i = 0; i < 3; i++)
155
+       coordsi = impl->port3 + i0;
156
+
157
+   mysofa_s2c(coords);
158
+   mysofa_getfilter_float(
159
+       impl->sofa,
160
+       coords0,
161
+       coords1,
162
+       coords2,
163
+       left_ir,
164
+       right_ir,
165
+       &left_delay,
166
+       &right_delay
167
+   );
168
+
169
+   // TODO: make use of delay
170
+   if ((left_delay || right_delay) && (!isnan(left_delay) || !isnan(right_delay))) {
171
+       pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay);
172
+   }
173
+
174
+   if (impl->l_conv2)
175
+       convolver_free(impl->l_conv2);
176
+   if (impl->r_conv2)
177
+       convolver_free(impl->r_conv2);
178
+
179
+   impl->l_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
180
+           left_ir, impl->n_samples);
181
+   impl->r_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
182
+           right_ir, impl->n_samples);
183
+
184
+   free(left_ir);
185
+   free(right_ir);
186
+
187
+   if (impl->l_conv2 == NULL || impl->r_conv2 == NULL) {
188
+       pw_log_error("reloading left or right convolver failed");
189
+       return;
190
+   }
191
+   spa_loop_invoke(data_loop, do_switch, 1, NULL, 0, true, impl);
192
+}
193
+
194
+struct free_data {
195
+   void *item2;
196
+};
197
+
198
+static int
199
+do_free(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
200
+       size_t size, void *user_data)
201
pipewire-0.3.65.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.66.tar.gz/src/modules/module-loopback.c Changed
34
 
1
@@ -111,6 +111,32 @@
2
  * 
3
  *\endcode
4
  *
5
+ * ## Example configuration of a virtual source
6
+ *
7
+ * This Virtual source routes the front-left channel of a multi-channel input to a mono channel.
8
+ * This is useful for splitting up multi-channel inputs from USB audio interfaces that are not yet fully supported by alsa.
9
+ *
10
+ *\code{.unparsed}
11
+ * context.modules = 
12
+ * {   name = libpipewire-module-loopback
13
+ *     args = {
14
+ *       node.description = "Scarlett Focusrite Line 1"
15
+ *       capture.props = {
16
+ *           audio.position =  FL 
17
+ *           stream.dont-remix = true
18
+ *           node.target = "alsa_input.usb-Focusrite_Scarlett_Solo_USB_Y7ZD17C24495BC-00.analog-stereo"
19
+ *           node.passive = true
20
+ *       }
21
+ *       playback.props = {
22
+ *           node.name = "SF_mono_in_1"
23
+ *           media.class = "Audio/Source"
24
+ *           audio.position =  MONO 
25
+ *       }
26
+ *     }
27
+ * }
28
+ * 
29
+ *\endcode
30
+ *
31
  * ## See also
32
  *
33
  * `pw-loopback` : a tool that loads the loopback module with given parameters.
34
pipewire-0.3.65.tar.gz/src/modules/module-protocol-pulse/cmd.c -> pipewire-0.3.66.tar.gz/src/modules/module-protocol-pulse/cmd.c Changed
13
 
1
@@ -76,7 +76,10 @@
2
 
3
 /*
4
  * pulse.cmd = 
5
- *   { cmd = <command>  args = "<arguments>"  }
6
+ *   {   cmd = <command>
7
+ *       ( args = "<arguments>" )
8
+ *       ( flags =  ( nofail )  )
9
+ *   }
10
  *   ...
11
  * 
12
  */
13
pipewire-0.3.66.tar.gz/src/modules/module-rt Added
2
 
1
+(directory)
2
pipewire-0.3.66.tar.gz/src/modules/module-rt/20-pw-defaults.conf.in Added
22
 
1
@@ -0,0 +1,20 @@
2
+# This file was installed by PipeWire project for buffer locking to always work
3
+
4
+# Required to memlock audio buffers for all client types
5
+#
6
+# This will match all PAM users i.e. those going through the login procedure but
7
+# it should not get applied to system daemons, since they are run bypassing PAM.
8
+#
9
+# While at first glance this might appear very relevant, in fact abusing this
10
+# can at most allow for either more rapid OOM or enhance malicious system memory
11
+# thrashing while evading systemd-oomd limits that are based on the requirement
12
+# that swap utilization must be high before issues arise. As such it's perfectly
13
+# reasonable to just set a limit where each client can lock a few megabytes with
14
+# nearly no impact on regular systems. Meanwhile malicious attackers can OOM
15
+# just as they could. And instead tooling for OOM and resource abuse should be
16
+# improved, if such denial of service attacks are a serious consideration at all.
17
+#
18
+# Starting with Linux 5.16 or systemd v253 the default is 8192 which is plenty
19
+# good enough and this file should not be installed on such systems.
20
+#
21
+*         - memlock @PAM_MEMLOCK@
22
pipewire-0.3.66.tar.gz/src/modules/module-rt/25-pw-rlimits.conf.in Added
10
 
1
@@ -0,0 +1,8 @@
2
+# This file was installed by PipeWire project for its libpipewire-module-rt.so
3
+
4
+# It's believed to be acceptable to have match rules that will never be true
5
+# i.e. a group that does not exist.
6
+#
7
+@MATCH@   - rtprio  @RTPRIO@
8
+@MATCH@   - nice    @NICE@
9
+@MATCH@   - memlock @MEMLOCK@
10
pipewire-0.3.66.tar.gz/src/modules/module-rt/meson.build Added
25
 
1
@@ -0,0 +1,23 @@
2
+rlimits_install = get_option('rlimits-install')
3
+rlimits_data = configuration_data()
4
+rlimits_data.set('MATCH', get_option('rlimits-match'))
5
+rlimits_data.set('RTPRIO', get_option('rlimits-rtprio'))
6
+rlimits_data.set('NICE', get_option('rlimits-nice'))
7
+rlimits_data.set('MEMLOCK', get_option('rlimits-memlock'))
8
+configure_file(input: '25-pw-rlimits.conf.in',
9
+  output: '25-pw-rlimits.conf',
10
+  install: rlimits_install,
11
+  install_dir: get_option('sysconfdir') / 'security' / 'limits.d',
12
+  configuration: rlimits_data)
13
+summary({'RLIMITs': '@0@ limits.d file affecting matching PAM users'.format(rlimits_install ? 'with' : 'without')})
14
+
15
+# The pam-defaults-install related code can be removed once all Linux <5.16 kernels are EOL (projected Dec, 2026)
16
+pam_defaults_install = get_option('pam-defaults-install')
17
+pam_defaults_data = configuration_data()
18
+pam_defaults_data.set('PAM_MEMLOCK', get_option('pam-memlock-default'))
19
+configure_file(input: '20-pw-defaults.conf.in',
20
+  output: '20-pw-defaults.conf',
21
+  install: pam_defaults_install,
22
+  install_dir: get_option('sysconfdir') / 'security' / 'limits.d',
23
+  configuration: pam_defaults_data)
24
+summary({'PAM defaults': '@0@ limits.d file affecting all PAM users (not needed with modern systemd or kernel)'.format(pam_defaults_install ? 'with' : 'without')})
25
pipewire-0.3.65.tar.gz/src/modules/module-rtp-sink.c -> pipewire-0.3.66.tar.gz/src/modules/module-rtp-sink.c Changed
201
 
1
@@ -70,6 +70,8 @@
2
  * - `sess.min-ptime = <int>`: minimum packet time in milliseconds, default 2
3
  * - `sess.max-ptime = <int>`: maximum packet time in milliseconds, default 20
4
  * - `sess.name = <str>`: a session name
5
+ * - `sess.ts-offset = <int>`: an offset to apply to the timestamp, default -1 = random offset
6
+ * - `sess.ts-refclk = <string>`: the name of a reference clock
7
  * - `stream.props = {}`: properties to be passed to the stream
8
  *
9
  * ## General options
10
@@ -149,6 +151,7 @@
11
 
12
 #define DEFAULT_MIN_PTIME  2
13
 #define DEFAULT_MAX_PTIME  20
14
+#define DEFAULT_TS_OFFSET  -1
15
 
16
 #define USAGE  "sap.ip=<SAP IP address to send announce, default:"DEFAULT_SAP_IP"> "       \
17
        "sap.port=<SAP port to send on, default:"SPA_STRINGIFY(DEFAULT_SAP_PORT)"> "    \
18
@@ -212,6 +215,8 @@
19
    struct pw_stream *stream;
20
    struct spa_hook stream_listener;
21
 
22
+   struct spa_io_position *io_position;
23
+
24
    unsigned int do_disconnect:1;
25
 
26
    char *ifname;
27
@@ -220,9 +225,9 @@
28
    int mtu;
29
    bool ttl;
30
    bool mcast_loop;
31
-   uint32_t min_ptime;
32
-   uint32_t max_ptime;
33
-   uint32_t pbytes;
34
+   float min_ptime;
35
+   float max_ptime;
36
+   uint32_t psamples;
37
 
38
    struct sockaddr_storage src_addr;
39
    socklen_t src_len;
40
@@ -240,17 +245,20 @@
41
 
42
    struct spa_audio_info_raw info;
43
    const struct format_info *format_info;
44
-   uint32_t frame_size;
45
+   uint32_t stride;
46
    int payload;
47
    uint16_t seq;
48
-   uint32_t timestamp;
49
    uint32_t ssrc;
50
+   uint32_t ts_offset;
51
+   char ts_refclk64;
52
 
53
    struct spa_ringbuffer ring;
54
    uint8_t bufferBUFFER_SIZE;
55
 
56
    int rtp_fd;
57
    int sap_fd;
58
+
59
+   unsigned sync:1;
60
 };
61
 
62
 
63
@@ -274,20 +282,21 @@
64
 static void flush_packets(struct impl *impl)
65
 {
66
    int32_t avail;
67
-   uint32_t index;
68
+   uint32_t stride, timestamp;
69
    struct iovec iov3;
70
    struct msghdr msg;
71
    ssize_t n;
72
    struct rtp_header header;
73
    int32_t tosend;
74
 
75
-   avail = spa_ringbuffer_get_read_index(&impl->ring, &index);
76
-
77
-   tosend = impl->pbytes;
78
+   avail = spa_ringbuffer_get_read_index(&impl->ring, &timestamp);
79
+   tosend = impl->psamples;
80
 
81
    if (avail < tosend)
82
        return;
83
 
84
+   stride = impl->stride;
85
+
86
    spa_zero(header);
87
    header.v = 2;
88
    header.pt = impl->payload;
89
@@ -306,13 +315,14 @@
90
 
91
    while (avail >= tosend) {
92
        header.sequence_number = htons(impl->seq);
93
-       header.timestamp = htonl(impl->timestamp);
94
+       header.timestamp = htonl(impl->ts_offset + timestamp);
95
 
96
        set_iovec(&impl->ring,
97
            impl->buffer, BUFFER_SIZE,
98
-           index & BUFFER_MASK,
99
-           &iov1, tosend);
100
+           (timestamp * stride) & BUFFER_MASK,
101
+           &iov1, tosend * stride);
102
 
103
+       pw_log_trace("sending %d timestamp:%d", tosend, timestamp);
104
        n = sendmsg(impl->rtp_fd, &msg, MSG_NOSIGNAL);
105
        if (n < 0) {
106
            switch (errno) {
107
@@ -321,18 +331,18 @@
108
                pw_log_debug("remote end not listening");
109
                break;
110
            default:
111
-               pw_log_warn("sendmsg() failed: %m");
112
+               pw_log_warn("sendmsg() failed, seq:%u dropped: %m",
113
+                       impl->seq);
114
                break;
115
            }
116
        }
117
 
118
        impl->seq++;
119
-       impl->timestamp += tosend / impl->frame_size;
120
 
121
-       index += tosend;
122
+       timestamp += tosend;
123
        avail -= tosend;
124
    }
125
-   spa_ringbuffer_read_update(&impl->ring, index);
126
+   spa_ringbuffer_read_update(&impl->ring, timestamp);
127
 }
128
 
129
 static void stream_process(void *data)
130
@@ -340,8 +350,8 @@
131
    struct impl *impl = data;
132
    struct pw_buffer *buf;
133
    struct spa_data *d;
134
-   uint32_t index;
135
-        int32_t filled, wanted;
136
+   uint32_t offs, size, timestamp, expected_timestamp, stride;
137
+   int32_t filled, wanted;
138
 
139
    if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
140
        pw_log_debug("Out of stream buffers: %m");
141
@@ -349,27 +359,56 @@
142
    }
143
    d = buf->buffer->datas;
144
 
145
-   wanted = d0.chunk->size;
146
+   offs = SPA_MIN(d0.chunk->offset, d0.maxsize);
147
+   size = SPA_MIN(d0.chunk->size, d0.maxsize - offs);
148
+   stride = impl->stride;
149
+   wanted = size / stride;
150
+
151
+   filled = spa_ringbuffer_get_write_index(&impl->ring, &expected_timestamp);
152
+   if (SPA_LIKELY(impl->io_position))
153
+       timestamp = impl->io_position->clock.position;
154
+   else
155
+       timestamp = expected_timestamp;
156
+
157
+   if (impl->sync) {
158
+       if (expected_timestamp != timestamp) {
159
+           pw_log_warn("expected %u != timestamp %u", expected_timestamp, timestamp);
160
+           impl->sync = false;
161
+       } else if (filled + wanted > (int32_t)(BUFFER_SIZE / stride)) {
162
+           pw_log_warn("overrun %u + %u > %u", filled, wanted, BUFFER_SIZE / stride);
163
+           impl->sync = false;
164
+       }
165
+   }
166
+   if (!impl->sync) {
167
+       pw_log_info("sync to timestamp %u", timestamp);
168
+       impl->ring.readindex = impl->ring.writeindex = timestamp;
169
+       memset(impl->buffer, 0, BUFFER_SIZE);
170
+       impl->sync = true;
171
+   }
172
 
173
-   filled = spa_ringbuffer_get_write_index(&impl->ring, &index);
174
+   spa_ringbuffer_write_data(&impl->ring,
175
+           impl->buffer,
176
+           BUFFER_SIZE,
177
+           (timestamp * stride) & BUFFER_MASK,
178
+           SPA_PTROFF(d0.data, offs, void), wanted * stride);
179
+   timestamp += wanted;
180
+   spa_ringbuffer_write_update(&impl->ring, timestamp);
181
 
182
-   if (filled + wanted > (int32_t)BUFFER_SIZE) {
183
-       pw_log_warn("overrun %u + %u > %u", filled, wanted, BUFFER_SIZE);
184
-   } else {
185
-       spa_ringbuffer_write_data(&impl->ring,
186
-               impl->buffer,
187
-               BUFFER_SIZE,
188
-                                index & BUFFER_MASK,
189
-                                d0.data, wanted);
190
-
191
-                index += wanted;
192
-                spa_ringbuffer_write_update(&impl->ring, index);
193
-        }
194
    pw_stream_queue_buffer(impl->stream, buf);
195
 
196
    flush_packets(impl);
197
 }
198
 
199
+static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size)
200
+{
201
pipewire-0.3.65.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.66.tar.gz/src/modules/module-rtp-source.c Changed
201
 
1
@@ -25,6 +25,7 @@
2
 #include "config.h"
3
 
4
 #include <limits.h>
5
+#include <string.h>
6
 #include <unistd.h>
7
 #include <sys/stat.h>
8
 #include <sys/socket.h>
9
@@ -84,6 +85,7 @@
10
  *         #sap.port = 9875
11
  *         #local.ifname = eth0
12
  *         sess.latency.msec = 100
13
+ *         #node.always-process = false # true to receive even when not running
14
  *         stream.props = {
15
  *            #media.class = "Audio/Source"
16
  *            #node.name = "rtp-source"
17
@@ -97,11 +99,14 @@
18
  *                         #rtp.payload = "127"
19
  *                         #rtp.fmt = "L16/48000/2"
20
  *                         #rtp.session = "PipeWire RTP Stream on fedora"
21
+ *                         #rtp.ts-offset = 0
22
+ *                         #rtp.ts-refclk = "private"
23
  *                     }
24
  *                 
25
  *                 actions = {
26
  *                     create-stream = {
27
  *                         #sess.latency.msec = 100
28
+ *                         #sess.ts-direct = false
29
  *                         #target.object = ""
30
  *                     }
31
  *                 }
32
@@ -169,6 +174,7 @@
33
 
34
    char *ifname;
35
    char *sap_ip;
36
+   bool always_process;
37
    int sap_port;
38
    int sess_latency_msec;
39
    uint32_t cleanup_interval;
40
@@ -202,6 +208,7 @@
41
 
42
    char origin128;
43
    char session256;
44
+   char channelmap512;
45
 
46
    struct sockaddr_storage sa;
47
    socklen_t salen;
48
@@ -212,6 +219,9 @@
49
    const struct format_info *format_info;
50
    struct spa_audio_info_raw info;
51
    uint32_t stride;
52
+
53
+   uint32_t ts_offset;
54
+   char refclk64;
55
 };
56
 
57
 struct session {
58
@@ -237,12 +247,13 @@
59
    uint8_t bufferBUFFER_SIZE;
60
 
61
    struct spa_io_rate_match *rate_match;
62
+   struct spa_io_position *position;
63
    struct spa_dll dll;
64
    uint32_t target_buffer;
65
-   uint32_t last_packet_size;
66
    float max_error;
67
-   unsigned buffering:1;
68
    unsigned first:1;
69
+   unsigned receiving:1;
70
+   unsigned direct_timestamp:1;
71
 };
72
 
73
 static void stream_destroy(void *d)
74
@@ -257,8 +268,8 @@
75
    struct session *sess = data;
76
    struct pw_buffer *buf;
77
    struct spa_data *d;
78
-   uint32_t index, target_buffer;
79
-   int32_t avail, wanted;
80
+   uint32_t wanted, timestamp, target_buffer, stride, maxsize;
81
+   int32_t avail;
82
 
83
    if ((buf = pw_stream_dequeue_buffer(sess->stream)) == NULL) {
84
        pw_log_debug("Out of stream buffers: %m");
85
@@ -266,38 +277,53 @@
86
    }
87
    d = buf->buffer->datas;
88
 
89
-   wanted = buf->requested ?
90
-       SPA_MIN(buf->requested * sess->info.stride, d0.maxsize)
91
-       : d0.maxsize;
92
+   stride = sess->info.stride;
93
 
94
-   avail = spa_ringbuffer_get_read_index(&sess->ring, &index);
95
+   maxsize = d0.maxsize / stride;
96
+   wanted = buf->requested ? SPA_MIN(buf->requested, maxsize) : maxsize;
97
 
98
-   target_buffer = sess->target_buffer + sess->last_packet_size / 2;
99
+   if (sess->position && sess->direct_timestamp) {
100
+       /* in direct mode, read directly from the timestamp index,
101
+        * because sender and receiver are in sync, this would keep
102
+        * target_buffer of bytes available. */
103
+       spa_ringbuffer_read_update(&sess->ring,
104
+               sess->position->clock.position);
105
+   }
106
+   avail = spa_ringbuffer_get_read_index(&sess->ring, &timestamp);
107
 
108
-   if (avail < wanted || sess->buffering) {
109
-       memset(d0.data, 0, wanted);
110
-       if (!sess->buffering && sess->have_sync) {
111
-           pw_log_debug("underrun %u/%u < %u, buffering...",
112
-                   avail, target_buffer, wanted);
113
-           sess->buffering = true;
114
+   target_buffer = sess->target_buffer;
115
+
116
+   if (avail < (int32_t)wanted) {
117
+       enum spa_log_level level;
118
+       memset(d0.data, 0, wanted * stride);
119
+       if (sess->have_sync) {
120
+           sess->have_sync = false;
121
+           level = SPA_LOG_LEVEL_WARN;
122
+       } else {
123
+           level = SPA_LOG_LEVEL_DEBUG;
124
        }
125
+       pw_log(level, "underrun %d/%u < %u",
126
+                   avail, target_buffer, wanted);
127
    } else {
128
        float error, corr;
129
-       if (avail > (int32_t)SPA_MIN(target_buffer * 8, BUFFER_SIZE)) {
130
+       if (avail > (int32_t)SPA_MIN(target_buffer * 8, BUFFER_SIZE / stride)) {
131
            pw_log_warn("overrun %u > %u", avail, target_buffer * 8);
132
-           index += avail - target_buffer;
133
+           timestamp += avail - target_buffer;
134
            avail = target_buffer;
135
-       } else {
136
-           if (sess->first) {
137
-               if ((uint32_t)avail > target_buffer) {
138
-                   uint32_t skip = avail - target_buffer;
139
-                   pw_log_debug("first: avail:%d skip:%u target:%u",
140
+       } else if (sess->first) {
141
+           if ((uint32_t)avail > target_buffer) {
142
+               uint32_t skip = avail - target_buffer;
143
+               pw_log_debug("first: avail:%d skip:%u target:%u",
144
                            avail, skip, target_buffer);
145
-                   index += skip;
146
-                   avail = target_buffer;
147
-               }
148
-               sess->first = false;
149
+               timestamp += skip;
150
+               avail = target_buffer;
151
            }
152
+           sess->first = false;
153
+       }
154
+       if (!sess->direct_timestamp) {
155
+           /* when not using direct timestamp and clocks are not
156
+            * in sync, try to adjust our playback rate to keep the
157
+            * requested target_buffer bytes in the ringbuffer */
158
            error = (float)target_buffer - (float)avail;
159
            error = SPA_CLAMP(error, -sess->max_error, sess->max_error);
160
 
161
@@ -307,46 +333,28 @@
162
                    target_buffer, error, corr);
163
 
164
            if (sess->rate_match) {
165
-               SPA_FLAG_SET(sess->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE);
166
+               SPA_FLAG_SET(sess->rate_match->flags,
167
+                       SPA_IO_RATE_MATCH_FLAG_ACTIVE);
168
                sess->rate_match->rate = 1.0f / corr;
169
            }
170
        }
171
        spa_ringbuffer_read_data(&sess->ring,
172
                sess->buffer,
173
                BUFFER_SIZE,
174
-               index & BUFFER_MASK,
175
-               d0.data, wanted);
176
+               (timestamp * stride) & BUFFER_MASK,
177
+               d0.data, wanted * stride);
178
 
179
-       index += wanted;
180
-       spa_ringbuffer_read_update(&sess->ring, index);
181
+       timestamp += wanted;
182
+       spa_ringbuffer_read_update(&sess->ring, timestamp);
183
    }
184
-   d0.chunk->size = wanted;
185
-   d0.chunk->stride = sess->info.stride;
186
+   d0.chunk->size = wanted * stride;
187
+   d0.chunk->stride = stride;
188
    d0.chunk->offset = 0;
189
-   buf->size = wanted / sess->info.stride;
190
+   buf->size = wanted;
191
 
192
    pw_stream_queue_buffer(sess->stream, buf);
193
 }
194
 
195
-static void on_stream_state_changed(void *d, enum pw_stream_state old,
196
-       enum pw_stream_state state, const char *error)
197
-{
198
-   struct session *sess = d;
199
-   struct impl *impl = sess->impl;
200
-
201
pipewire-0.3.65.tar.gz/src/pipewire/conf.c -> pipewire-0.3.66.tar.gz/src/pipewire/conf.c Changed
201
 
1
@@ -605,10 +605,70 @@
2
 }
3
 
4
 /*
5
+ * {
6
+ *     # all keys must match the value. ~ in value starts regex.
7
+ *     <key> = <value>
8
+ *     ...
9
+ * }
10
+ */
11
+static bool find_match(struct spa_json *arr, const struct spa_dict *props)
12
+{
13
+   struct spa_json it1;
14
+
15
+   while (spa_json_enter_object(arr, &it0) > 0) {
16
+       char key256, val1024;
17
+       const char *str, *value;
18
+       int match = 0, fail = 0;
19
+       int len;
20
+
21
+       while (spa_json_get_string(&it0, key, sizeof(key)) > 0) {
22
+           bool success = false;
23
+
24
+           if ((len = spa_json_next(&it0, &value)) <= 0)
25
+               break;
26
+
27
+           str = spa_dict_lookup(props, key);
28
+
29
+           if (spa_json_is_null(value, len)) {
30
+               success = str == NULL;
31
+           } else {
32
+               if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0)
33
+                   continue;
34
+               value = val;
35
+               len = strlen(val);
36
+           }
37
+           if (str != NULL) {
38
+               if (value0 == '~') {
39
+                   regex_t preg;
40
+                   if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
41
+                       if (regexec(&preg, str, 0, NULL, 0) == 0)
42
+                           success = true;
43
+                       regfree(&preg);
44
+                   }
45
+               } else if (strncmp(str, value, len) == 0 &&
46
+                   strlen(str) == (size_t)len) {
47
+                   success = true;
48
+               }
49
+           }
50
+           if (success) {
51
+               match++;
52
+               pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
53
+           }
54
+           else
55
+               fail++;
56
+       }
57
+       if (match > 0 && fail == 0)
58
+           return true;
59
+   }
60
+   return false;
61
+}
62
+
63
+/*
64
  * context.modules = 
65
  *   {   name = <module-name>
66
- *        args = { <key> = <value> ... } 
67
- *        flags =   ifexists   nofail  
68
+ *       ( args = { <key> = <value> ... } )
69
+ *       ( flags =  ( ifexists ) ( nofail ) 
70
+ *       ( condition =  { key = value, .. } ..  )
71
  *   }
72
  * 
73
  */
74
@@ -617,7 +677,7 @@
75
 {
76
    struct data *d = user_data;
77
    struct pw_context *context = d->context;
78
-   struct spa_json it3;
79
+   struct spa_json it4;
80
    char key512, *s;
81
    int res = 0;
82
 
83
@@ -631,6 +691,7 @@
84
 
85
    while (spa_json_enter_object(&it1, &it2) > 0) {
86
        char *name = NULL, *args = NULL, *flags = NULL;
87
+       bool have_match = true;
88
 
89
        while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
90
            const char *val;
91
@@ -653,8 +714,16 @@
92
                    len = spa_json_container_len(&it2, val, len);
93
                flags = (char*)val;
94
                spa_json_parse_stringn(val, len, flags, len+1);
95
+           } else if (spa_streq(key, "condition")) {
96
+               if (!spa_json_is_array(val, len))
97
+                   break;
98
+               spa_json_enter(&it2, &it3);
99
+               have_match = find_match(&it3, &context->properties->dict);
100
            }
101
        }
102
+       if (!have_match)
103
+           continue;
104
+
105
        if (name != NULL)
106
            res = load_module(context, name, args, flags);
107
 
108
@@ -698,8 +767,9 @@
109
 /*
110
  * context.objects = 
111
  *   {   factory = <factory-name>
112
- *        args  = { <key> = <value> ... } 
113
- *        flags =   nofail   
114
+ *       ( args  = { <key> = <value> ... } )
115
+ *       ( flags =  ( nofail )  )
116
+ *       ( condition =  { key = value, .. } ..  )
117
  *   }
118
  * 
119
  */
120
@@ -708,7 +778,7 @@
121
 {
122
    struct data *d = user_data;
123
    struct pw_context *context = d->context;
124
-   struct spa_json it3;
125
+   struct spa_json it4;
126
    char key512, *s;
127
    int res = 0;
128
 
129
@@ -722,6 +792,7 @@
130
 
131
    while (spa_json_enter_object(&it1, &it2) > 0) {
132
        char *factory = NULL, *args = NULL, *flags = NULL;
133
+       bool have_match = true;
134
 
135
        while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
136
            const char *val;
137
@@ -745,8 +816,16 @@
138
 
139
                flags = (char*)val;
140
                spa_json_parse_stringn(val, len, flags, len+1);
141
+           } else if (spa_streq(key, "condition")) {
142
+               if (!spa_json_is_array(val, len))
143
+                   break;
144
+               spa_json_enter(&it2, &it3);
145
+               have_match = find_match(&it3, &context->properties->dict);
146
            }
147
        }
148
+       if (!have_match)
149
+           continue;
150
+
151
        if (factory != NULL)
152
            res = create_object(context, factory, args, flags);
153
 
154
@@ -807,8 +886,9 @@
155
 
156
 /*
157
  * context.exec = 
158
- *   { path = <program-name>
159
- *      args = "<arguments>" 
160
+ *   {   path = <program-name>
161
+ *       ( args = "<arguments>" )
162
+ *       ( condition =  { key = value, .. } ..  )
163
  *   }
164
  * 
165
  */
166
@@ -817,7 +897,7 @@
167
 {
168
    struct data *d = user_data;
169
    struct pw_context *context = d->context;
170
-   struct spa_json it3;
171
+   struct spa_json it4;
172
    char key512, *s;
173
    int res = 0;
174
 
175
@@ -831,6 +911,7 @@
176
 
177
    while (spa_json_enter_object(&it1, &it2) > 0) {
178
        char *path = NULL, *args = NULL;
179
+       bool have_match = true;
180
 
181
        while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
182
            const char *val;
183
@@ -845,8 +926,16 @@
184
            } else if (spa_streq(key, "args")) {
185
                args = (char*)val;
186
                spa_json_parse_stringn(val, len, args, len+1);
187
+           } else if (spa_streq(key, "condition")) {
188
+               if (!spa_json_is_array(val, len))
189
+                   break;
190
+               spa_json_enter(&it2, &it3);
191
+               have_match = find_match(&it3, &context->properties->dict);
192
            }
193
        }
194
+       if (!have_match)
195
+           continue;
196
+
197
        if (path != NULL)
198
            res = do_exec(context, path, args);
199
 
200
@@ -1014,65 +1103,6 @@
201
pipewire-0.3.65.tar.gz/src/pipewire/context.c -> pipewire-0.3.66.tar.gz/src/pipewire/context.c Changed
136
 
1
@@ -970,15 +970,114 @@
2
    return fa < fb ? -1 : (fa > fb ? 1 : 0);
3
 }
4
 
5
-static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t best)
6
+static inline uint32_t calc_gcd(uint32_t a, uint32_t b)
7
 {
8
-   uint32_t i;
9
+   while (b != 0) {
10
+       uint32_t temp = a;
11
+       a = b;
12
+       b = temp % b;
13
+   }
14
+   return a;
15
+}
16
+
17
+struct rate_info {
18
+   uint32_t rate;
19
+   uint32_t gcd;
20
+   uint32_t diff;
21
+};
22
+
23
+static inline void update_highest_rate(struct rate_info *best, struct rate_info *current)
24
+{
25
+   /* find highest rate */
26
+   if (best->rate == 0 || best->rate < current->rate)
27
+       *best = *current;
28
+}
29
+
30
+static inline void update_nearest_gcd(struct rate_info *best, struct rate_info *current)
31
+{
32
+   /* find nearest GCD */
33
+   if (best->rate == 0 ||
34
+       (best->gcd < current->gcd) ||
35
+       (best->gcd == current->gcd && best->diff > current->diff))
36
+       *best = *current;
37
+}
38
+static inline void update_nearest_rate(struct rate_info *best, struct rate_info *current)
39
+{
40
+   /* find nearest rate */
41
+   if (best->rate == 0 || best->diff > current->diff)
42
+       *best = *current;
43
+}
44
+
45
+static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t def)
46
+{
47
+   uint32_t i, limit;
48
+   struct rate_info best;
49
+   struct rate_info infon_rates;
50
+
51
+   for (i = 0; i < n_rates; i++) {
52
+       infoi.rate = ratesi;
53
+       infoi.gcd = calc_gcd(rate, ratesi);
54
+       infoi.diff = SPA_ABS((int32_t)rate - (int32_t)ratesi);
55
+   }
56
+
57
+   /* first find higher nearest GCD. This tries to find next bigest rate that
58
+    * requires the least amount of resample filter banks. Usually these are
59
+    * rates that are multiples of eachother or multiples of a common rate.
60
+    *
61
+    * 44100 and  32000 56000 88200 96000   -> 88200
62
+    * 48000 and  32000 56000 88200 96000   -> 96000
63
+    * 88200 and  44100 48000 96000 192000   -> 96000
64
+    * 32000 and  44100 192000  -> 44100
65
+    * 8000 and  44100 48000  -> 48000
66
+    * 8000 and  44100 192000  -> 44100
67
+    * 11025 and  44100 48000  -> 44100
68
+    * 44100 and  48000 176400  -> 48000
69
+    */
70
+   spa_zero(best);
71
+   /* Don't try to do excessive upsampling by limiting the max rate
72
+    * for desired < default to default*2. For other rates allow
73
+    * a x3 upsample rate max */
74
+   limit = rate < def ? def*2 : rate*3;
75
+   for (i = 0; i < n_rates; i++) {
76
+       if (infoi.rate >= rate && infoi.rate <= limit)
77
+           update_nearest_gcd(&best, &infoi);
78
+   }
79
+   if (best.rate != 0)
80
+       return best.rate;
81
+
82
+   /* we would need excessive upsampling, pick a nearest higher rate */
83
+   spa_zero(best);
84
+   for (i = 0; i < n_rates; i++) {
85
+       if (infoi.rate >= rate)
86
+           update_nearest_rate(&best, &infoi);
87
+   }
88
+   if (best.rate != 0)
89
+       return best.rate;
90
+
91
+   /* There is nothing above the rate, we need to downsample. Try to downsample
92
+    * but only to something that is from a common rate family. Also don't
93
+    * try to downsample to something that will sound worse (< 44100).
94
+    *
95
+    * 88200 and  22050 44100 48000  -> 44100
96
+    * 88200 and  22050 48000  -> 48000
97
+    */
98
+   spa_zero(best);
99
    for (i = 0; i < n_rates; i++) {
100
-       if (SPA_ABS((int32_t)rate - (int32_t)ratesi) <
101
-           SPA_ABS((int32_t)rate - (int32_t)best))
102
-           best = ratesi;
103
+       if (infoi.rate >= 44100)
104
+           update_nearest_gcd(&best, &infoi);
105
    }
106
-   return best;
107
+   if (best.rate != 0)
108
+       return best.rate;
109
+
110
+   /* There is nothing to downsample above our threshold. Downsample to whatever
111
+    * is the highest rate then. */
112
+   spa_zero(best);
113
+   for (i = 0; i < n_rates; i++)
114
+       update_highest_rate(&best, &infoi);
115
+   if (best.rate != 0)
116
+       return best.rate;
117
+
118
+   return def;
119
 }
120
 
121
 /* here we evaluate the complete state of the graph.
122
@@ -1201,10 +1300,12 @@
123
            running = true;
124
 
125
        current_rate = n->current_rate.denom;
126
-       if (lock_rate || n->reconfigure ||
127
+       if (lock_rate || n->reconfigure || !running ||
128
            (!force_rate &&
129
            (n->info.state > PW_NODE_STATE_IDLE)))
130
            /* when someone wants us to lock the rate of this driver or
131
+            * when we are in the process of reconfiguring the driver or
132
+            * when we are not running any followers or
133
             * when the driver is busy and we don't need to force a rate,
134
             * keep the current rate */
135
            target_rate = current_rate;
136
pipewire-0.3.65.tar.gz/src/pipewire/filter.c -> pipewire-0.3.66.tar.gz/src/pipewire/filter.c Changed
201
 
1
@@ -95,15 +95,15 @@
2
 
3
    struct pw_properties *props;
4
 
5
-   uint32_t change_mask_all;
6
+   uint64_t change_mask_all;
7
    struct spa_port_info info;
8
    struct spa_list param_list;
9
-#define IDX_EnumFormat 0
10
-#define IDX_Meta   1
11
-#define IDX_IO     2
12
-#define IDX_Format 3
13
-#define IDX_Buffers    4
14
-#define IDX_Latency    5
15
+#define PORT_EnumFormat    0
16
+#define PORT_Meta  1
17
+#define PORT_IO        2
18
+#define PORT_Format    3
19
+#define PORT_Buffers   4
20
+#define PORT_Latency   5
21
 #define N_PORT_PARAMS  6
22
    struct spa_param_info paramsN_PORT_PARAMS;
23
 
24
@@ -133,6 +133,7 @@
25
    struct spa_node impl_node;
26
    struct spa_hook_list hooks;
27
    struct spa_callbacks callbacks;
28
+   struct spa_io_clock *clock;
29
    struct spa_io_position *position;
30
 
31
    struct {
32
@@ -142,12 +143,12 @@
33
    struct spa_list port_list;
34
    struct pw_map ports2;
35
 
36
-   uint32_t change_mask_all;
37
+   uint64_t change_mask_all;
38
    struct spa_node_info info;
39
    struct spa_list param_list;
40
-#define IDX_PropInfo       0
41
-#define IDX_Props      1
42
-#define IDX_ProcessLatency 2
43
+#define NODE_PropInfo      0
44
+#define NODE_Props     1
45
+#define NODE_ProcessLatency    2
46
 #define N_NODE_PARAMS      3
47
    struct spa_param_info paramsN_NODE_PARAMS;
48
 
49
@@ -168,17 +169,18 @@
50
    unsigned int allow_mlock:1;
51
    unsigned int warn_mlock:1;
52
    unsigned int process_rt:1;
53
+   unsigned int driving:1;
54
 };
55
 
56
 static int get_param_index(uint32_t id)
57
 {
58
    switch (id) {
59
    case SPA_PARAM_PropInfo:
60
-       return IDX_PropInfo;
61
+       return NODE_PropInfo;
62
    case SPA_PARAM_Props:
63
-       return IDX_Props;
64
+       return NODE_Props;
65
    case SPA_PARAM_ProcessLatency:
66
-       return IDX_ProcessLatency;
67
+       return NODE_ProcessLatency;
68
    default:
69
        return -1;
70
    }
71
@@ -188,17 +190,17 @@
72
 {
73
    switch (id) {
74
    case SPA_PARAM_EnumFormat:
75
-       return IDX_EnumFormat;
76
+       return PORT_EnumFormat;
77
    case SPA_PARAM_Meta:
78
-       return IDX_Meta;
79
+       return PORT_Meta;
80
    case SPA_PARAM_IO:
81
-       return IDX_IO;
82
+       return PORT_IO;
83
    case SPA_PARAM_Format:
84
-       return IDX_Format;
85
+       return PORT_Format;
86
    case SPA_PARAM_Buffers:
87
-       return IDX_Buffers;
88
+       return PORT_Buffers;
89
    case SPA_PARAM_Latency:
90
-       return IDX_Latency;
91
+       return PORT_Latency;
92
    default:
93
        return -1;
94
    }
95
@@ -475,6 +477,12 @@
96
    pw_log_debug("%p: io %d %p/%zd", impl, id, data, size);
97
 
98
    switch(id) {
99
+   case SPA_IO_Clock:
100
+       if (data && size >= sizeof(struct spa_io_clock))
101
+           impl->clock = data;
102
+       else
103
+           impl->clock = NULL;
104
+       break;
105
    case SPA_IO_Position:
106
        if (data && size >= sizeof(struct spa_io_position))
107
            impl->position = data;
108
@@ -484,6 +492,7 @@
109
            do_set_position, 1, NULL, 0, true, impl);
110
        break;
111
    }
112
+   impl->driving = impl->clock && impl->position && impl->position->clock.id == impl->clock->id;
113
    pw_filter_emit_io_changed(&impl->this, NULL, id, data, size);
114
 
115
    return 0;
116
@@ -1530,9 +1539,9 @@
117
    impl->info.max_output_ports = UINT32_MAX;
118
    impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0;
119
    impl->info.props = &filter->properties->dict;
120
-   impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
121
-   impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
122
-   impl->paramsIDX_ProcessLatency = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0);
123
+   impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
124
+   impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
125
+   impl->paramsNODE_ProcessLatency = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0);
126
    impl->info.params = impl->params;
127
    impl->info.n_params = N_NODE_PARAMS;
128
    impl->info.change_mask = impl->change_mask_all;
129
@@ -1712,12 +1721,12 @@
130
        p->info.flags |= SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
131
    p->info.props = &p->props->dict;
132
    p->change_mask_all |= SPA_PORT_CHANGE_MASK_PARAMS;
133
-   p->paramsIDX_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0);
134
-   p->paramsIDX_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0);
135
-   p->paramsIDX_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0);
136
-   p->paramsIDX_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
137
-   p->paramsIDX_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
138
-   p->paramsIDX_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE);
139
+   p->paramsPORT_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0);
140
+   p->paramsPORT_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0);
141
+   p->paramsPORT_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0);
142
+   p->paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
143
+   p->paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
144
+   p->paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE);
145
    p->info.params = p->params;
146
    p->info.n_params = N_PORT_PARAMS;
147
 
148
@@ -1749,22 +1758,23 @@
149
    return NULL;
150
 }
151
 
152
-SPA_EXPORT
153
-int pw_filter_remove_port(void *port_data)
154
+static inline void free_port(struct filter *impl, struct port *port)
155
 {
156
-   struct port *port = SPA_CONTAINER_OF(port_data, struct port, user_data);
157
-   struct filter *impl = port->filter;
158
-
159
-   spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL);
160
-
161
    spa_list_remove(&port->link);
162
+   spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL);
163
    pw_map_remove(&impl->portsport->direction, port->id);
164
-
165
    clear_buffers(port);
166
    clear_params(impl, port, SPA_ID_INVALID);
167
    pw_properties_free(port->props);
168
    free(port);
169
+}
170
 
171
+SPA_EXPORT
172
+int pw_filter_remove_port(void *port_data)
173
+{
174
+   struct port *port = SPA_CONTAINER_OF(port_data, struct port, user_data);
175
+   struct filter *impl = port->filter;
176
+   free_port(impl, port);
177
    return 0;
178
 }
179
 
180
@@ -1844,25 +1854,6 @@
181
    return 0;
182
 }
183
 
184
-static int
185
-do_process(struct spa_loop *loop,
186
-                 bool async, uint32_t seq, const void *data, size_t size, void *user_data)
187
-{
188
-   struct filter *impl = user_data;
189
-   int res = impl_node_process(impl);
190
-   return spa_node_call_ready(&impl->callbacks, res);
191
-}
192
-
193
-static inline int call_trigger(struct filter *impl)
194
-{
195
-   int res = 0;
196
-   if (SPA_FLAG_IS_SET(impl->flags, PW_FILTER_FLAG_DRIVER)) {
197
-       res = pw_loop_invoke(impl->context->data_loop,
198
-           do_process, 1, NULL, 0, false, impl);
199
-   }
200
-   return res;
201
pipewire-0.3.65.tar.gz/src/pipewire/filter.h -> pipewire-0.3.66.tar.gz/src/pipewire/filter.h Changed
18
 
1
@@ -239,6 +239,16 @@
2
  * be called when all data is played or recorded */
3
 int pw_filter_flush(struct pw_filter *filter, bool drain);
4
 
5
+/** Check if the filter is driving. The filter needs to have the
6
+ * PW_FILTER_FLAG_DRIVER set. When the filter is driving,
7
+ * pw_filter_trigger_process() needs to be called when data is
8
+ * available (output) or needed (input). Since 0.3.66 */
9
+bool pw_filter_is_driving(struct pw_filter *filter);
10
+
11
+/** Trigger a push/pull on the filter. One iteration of the graph will
12
+ * be scheduled and process() will be called. Since 0.3.66 */
13
+int pw_filter_trigger_process(struct pw_filter *filter);
14
+
15
 /**
16
  * \}
17
  */
18
pipewire-0.3.65.tar.gz/src/pipewire/impl-core.c -> pipewire-0.3.66.tar.gz/src/pipewire/impl-core.c Changed
10
 
1
@@ -351,7 +351,7 @@
2
    if (obj == NULL)
3
        goto error_create_failed;
4
 
5
-   return 0;
6
+   return obj;
7
 
8
 error_no_factory:
9
    res = -ENOENT;
10
pipewire-0.3.65.tar.gz/src/pipewire/keys.h -> pipewire-0.3.66.tar.gz/src/pipewire/keys.h Changed
17
 
1
@@ -342,8 +342,13 @@
2
                                  * and object name or object.serial */
3
 
4
 #ifndef PW_REMOVE_DEPRECATED
5
-#define PW_KEY_PRIORITY_MASTER     PW_DEPRECATED("priority.master")    /**< deprecated, use priority.driver */
6
-#define PW_KEY_NODE_TARGET     PW_DEPRECATED("node.target")        /**< deprecated since 0.3.64, use target.object. */
7
+# ifdef PW_ENABLE_DEPRECATED
8
+#  define PW_KEY_PRIORITY_MASTER   "priority.master"   /**< deprecated, use priority.driver */
9
+#  define PW_KEY_NODE_TARGET       "node.target"       /**< deprecated since 0.3.64, use target.object. */
10
+# else
11
+#  define PW_KEY_PRIORITY_MASTER   PW_DEPRECATED("priority.master")
12
+#  define PW_KEY_NODE_TARGET       PW_DEPRECATED("node.target")
13
+# endif /* PW_ENABLE_DEPRECATED */
14
 #endif /* PW_REMOVE_DEPRECATED */
15
 
16
 /** \}
17
pipewire-0.3.65.tar.gz/src/pipewire/log.c -> pipewire-0.3.66.tar.gz/src/pipewire/log.c Changed
29
 
1
@@ -29,6 +29,7 @@
2
 
3
 #include <spa/pod/pod.h>
4
 #include <spa/debug/types.h>
5
+#include <spa/debug/format.h>
6
 #include <spa/pod/iter.h>
7
 #include <spa/utils/list.h>
8
 
9
@@ -241,13 +242,14 @@
10
 {
11
    struct spa_debug_log_ctx ctx = SPA_LOGF_DEBUG_INIT(global_log, level,
12
            topic, file, line, func );
13
-   if (flags & PW_LOG_OBJECT_POD) {
14
+   if (object == NULL) {
15
+       pw_log_logt(level, topic, file, line, func, "NULL");
16
+   } else {
17
        const struct spa_pod *pod = object;
18
-       if (pod == NULL) {
19
-           pw_log_logt(level, topic, file, line, func, "NULL");
20
-       } else {
21
+       if (flags & PW_LOG_OBJECT_POD)
22
            spa_debugc_pod(&ctx.ctx, 0, SPA_TYPE_ROOT, pod);
23
-       }
24
+       else if (flags & PW_LOG_OBJECT_FORMAT)
25
+           spa_debugc_format(&ctx.ctx, 0, NULL, pod);
26
    }
27
 }
28
 
29
pipewire-0.3.65.tar.gz/src/pipewire/mem.c -> pipewire-0.3.66.tar.gz/src/pipewire/mem.c Changed
33
 
1
@@ -33,6 +33,7 @@
2
 #include <unistd.h>
3
 #include <stdlib.h>
4
 #include <sys/syscall.h>
5
+#include <sys/stat.h>
6
 
7
 #include <spa/utils/list.h>
8
 #include <spa/buffer/buffer.h>
9
@@ -363,6 +364,23 @@
10
    struct mapping *m;
11
    struct memmap *mm;
12
    struct pw_map_range range;
13
+   struct stat sb;
14
+
15
+   if (fstat(b->this.fd, &sb) != 0)
16
+       return NULL;
17
+
18
+   const bool valid = (int64_t) offset + size <= (int64_t) sb.st_size;
19
+   pw_log(valid ? SPA_LOG_LEVEL_DEBUG : SPA_LOG_LEVEL_ERROR,
20
+       "%p: block %p%u mapping %" PRIu32 "+%" PRIu32 " of file=%d/%" PRIu64 ":%" PRIu64 " with size=%" PRId64,
21
+       block->pool, block, block->id,
22
+       offset, size,
23
+       block->fd, (uint64_t) sb.st_dev, (uint64_t) sb.st_ino,
24
+       (int64_t) sb.st_size);
25
+
26
+   if (!valid) {
27
+       errno = -EINVAL;
28
+       return NULL;
29
+   }
30
 
31
    pw_map_range_init(&range, offset, size, p->pagesize);
32
 
33
pipewire-0.3.65.tar.gz/src/pipewire/private.h -> pipewire-0.3.66.tar.gz/src/pipewire/private.h Changed
18
 
1
@@ -1276,6 +1276,7 @@
2
 void pw_impl_client_unref(struct pw_impl_client *client);
3
 
4
 #define PW_LOG_OBJECT_POD  (1<<0)
5
+#define PW_LOG_OBJECT_FORMAT   (1<<1)
6
 void pw_log_log_object(enum spa_log_level level, const struct spa_log_topic *topic,
7
        const char *file, int line, const char *func, uint32_t flags,
8
        const void *object);
9
@@ -1288,7 +1289,7 @@
10
 })
11
 
12
 #define pw_log_pod(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_POD,pod)
13
-#define pw_log_format(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_POD,pod)
14
+#define pw_log_format(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_FORMAT,pod)
15
 
16
 bool pw_log_is_default(void);
17
 
18
pipewire-0.3.65.tar.gz/src/pipewire/stream.c -> pipewire-0.3.66.tar.gz/src/pipewire/stream.c Changed
19
 
1
@@ -123,7 +123,7 @@
2
        struct spa_io_position *position;
3
    } rt;
4
 
5
-   uint32_t port_change_mask_all;
6
+   uint64_t port_change_mask_all;
7
    struct spa_port_info port_info;
8
    struct pw_properties *port_props;
9
 #define PORT_EnumFormat    0
10
@@ -137,7 +137,7 @@
11
 
12
    struct spa_list param_list;
13
 
14
-   uint32_t change_mask_all;
15
+   uint64_t change_mask_all;
16
    struct spa_node_info info;
17
 #define NODE_PropInfo  0
18
 #define NODE_Props 1
19
pipewire-0.3.65.tar.gz/src/pipewire/thread-loop.c -> pipewire-0.3.66.tar.gz/src/pipewire/thread-loop.c Changed
10
 
1
@@ -435,7 +435,7 @@
2
  *
3
  */
4
 SPA_EXPORT
5
-int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime)
6
+int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, const struct timespec *abstime)
7
 {
8
    int ret;
9
    loop->n_waiting++;
10
pipewire-0.3.65.tar.gz/src/pipewire/thread-loop.h -> pipewire-0.3.66.tar.gz/src/pipewire/thread-loop.h Changed
10
 
1
@@ -153,7 +153,7 @@
2
 /** Release the lock and wait up to \a abstime until some thread calls
3
  * \ref pw_thread_loop_signal. Use \ref pw_thread_loop_get_time to make a timeout.
4
  * Since: 0.3.7 */
5
-int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime);
6
+int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, const struct timespec *abstime);
7
 
8
 /** Signal all threads waiting with \ref pw_thread_loop_wait */
9
 void pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept);
10
pipewire-0.3.65.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.66.tar.gz/src/tools/pw-cat.c Changed
58
 
1
@@ -255,14 +255,13 @@
2
 static int encoded_playback_fill(struct data *d, void *dest, unsigned int n_frames)
3
 {
4
    int ret, size = 0;
5
-   uint8_t buffer16384 = { 0 };
6
+   uint8_t buffer16384;
7
 
8
-   ret = fread(buffer, 1, 16384, d->encoded_file);
9
+   ret = fread(buffer, 1, SPA_MIN(n_frames, sizeof(buffer)), d->encoded_file);
10
    if (ret > 0) {
11
        memcpy(dest, buffer, ret);
12
        size = ret;
13
    }
14
-
15
    return (int)size;
16
 }
17
 
18
@@ -786,31 +785,6 @@
19
        n_frames = d->maxsize / data->stride;
20
        n_frames = SPA_MIN(n_frames, (int)b->requested);
21
 
22
-#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
23
-       n_fill_frames = data->fill(data, p, n_frames);
24
-
25
-       if (n_fill_frames > 0 || n_frames == 0) {
26
-           d->chunk->offset = 0;
27
-           if (data->data_type == TYPE_ENCODED) {
28
-               d->chunk->stride = 0;
29
-               // encoded_playback_fill returns number of bytes
30
-               // read and not number of frames like other
31
-               // functions for raw audio.
32
-               d->chunk->size = n_fill_frames;
33
-               b->size = n_fill_frames;
34
-           } else {
35
-               d->chunk->stride = data->stride;
36
-               d->chunk->size = n_fill_frames * data->stride;
37
-               b->size = n_frames;
38
-           }
39
-           have_data = true;
40
-       } else if (n_fill_frames < 0) {
41
-           fprintf(stderr, "fill error %d\n", n_fill_frames);
42
-       } else {
43
-           if (data->verbose)
44
-               printf("drain start\n");
45
-       }
46
-#else
47
        n_fill_frames = data->fill(data, p, n_frames);
48
 
49
        if (n_fill_frames > 0 || n_frames == 0) {
50
@@ -825,7 +799,6 @@
51
            if (data->verbose)
52
                printf("drain start\n");
53
        }
54
-#endif
55
    } else {
56
        offset = SPA_MIN(d->chunk->offset, d->maxsize);
57
        size = SPA_MIN(d->chunk->size, d->maxsize - offset);
58
pipewire-0.3.66.tar.gz/subprojects/libcamera.wrap Added
5
 
1
@@ -0,0 +1,3 @@
2
+wrap-git
3
+url = https://git.libcamera.org/libcamera/libcamera.git
4
+revision = head
5