Changes of Revision 2

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Sun Jan 30 16:36:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.44
6
+
7
+-------------------------------------------------------------------
8
 Wed Jan  5 16:20:56 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.43
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.43
6
+Version:        0.3.44
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.43.tar.gz/doc/pipewire-tools.dox Deleted
6
 
1
@@ -1,4 +0,0 @@
2
-/** \page page_tools PipeWire Tools
3
-
4
-*/
5
-
6
pipewire-0.3.43.tar.gz/spa/plugins/alsa/mixer/profile-sets/behringer-umc22.conf Deleted
70
 
1
@@ -1,68 +0,0 @@
2
-# This file is part of PulseAudio.
3
-#
4
-# PulseAudio is free software; you can redistribute it and/or modify
5
-# it under the terms of the GNU Lesser General Public License as
6
-# published by the Free Software Foundation; either version 2.1 of the
7
-# License, or (at your option) any later version.
8
-#
9
-# PulseAudio is distributed in the hope that it will be useful, but
10
-# WITHOUT ANY WARRANTY; without even the implied warranty of
11
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
-# General Public License for more details.
13
-#
14
-# You should have received a copy of the GNU Lesser General Public License
15
-# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
16
-
17
-; Behringer U-Phoria UMC22
18
-;
19
-; Default mapping only allows to use stereo input and sound card has two
20
-; physical input channels.
21
-;
22
-; However in case of only using a single input channel (like condenser
23
-; microphone) only one channel will have any sound, which is often
24
-; inconvenient for casual use.
25
-;
26
-; This config includes mono input options which makes it much more
27
-; friendly in single input configuration.
28
-;
29
-; This config also removes default digital input/output mappings that do
30
-; not physically exist on this card.
31
-;
32
-; Added by Nazar Mokrynskyi <nazar@mokrynskyi.com>
33
-
34
-[General]
35
-auto-profiles = yes
36
-
37
-[Mapping analog-stereo-input]
38
-device-strings = hw:%f
39
-channel-map = left,right
40
-paths-input = analog-input-mic
41
-direction = input
42
-priority = 4
43
-
44
-[Mapping analog-mono]
45
-device-strings = hw:%f
46
-channel-map = mono,mono
47
-paths-input = analog-input-mic
48
-direction = input
49
-priority = 3
50
-
51
-[Mapping analog-mono-left]
52
-device-strings = hw:%f
53
-channel-map = mono,aux1
54
-paths-input = analog-input-mic
55
-direction = input
56
-priority = 2
57
-
58
-[Mapping analog-mono-right]
59
-device-strings = hw:%f
60
-channel-map = aux1,mono
61
-paths-input = analog-input-mic
62
-direction = input
63
-priority = 1
64
-
65
-[Mapping analog-stereo-output]
66
-device-strings = front:%f
67
-channel-map = left,right
68
-paths-output = analog-output
69
-direction = output
70
pipewire-0.3.43.tar.gz/src/modules/module-rtkit.c Deleted
201
 
1
@@ -1,730 +0,0 @@
2
-/* PipeWire
3
- *
4
- * Copyright © 2018 Wim Taymans
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a
7
- * copy of this software and associated documentation files (the "Software"),
8
- * to deal in the Software without restriction, including without limitation
9
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
- * and/or sell copies of the Software, and to permit persons to whom the
11
- * Software is furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice (including the next
14
- * paragraph) shall be included in all copies or substantial portions of the
15
- * Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
- * DEALINGS IN THE SOFTWARE.
24
- */
25
-
26
-#include <stdlib.h>
27
-#include <stdbool.h>
28
-#include <string.h>
29
-#include <stdio.h>
30
-#include <errno.h>
31
-#include <sys/stat.h>
32
-#ifdef __FreeBSD__
33
-#include <sys/thr.h>
34
-#endif
35
-#include <fcntl.h>
36
-#include <unistd.h>
37
-#include <pthread.h>
38
-#include <sys/resource.h>
39
-
40
-#include "config.h"
41
-
42
-#include <spa/support/dbus.h>
43
-#include <spa/utils/result.h>
44
-#include <spa/utils/string.h>
45
-
46
-#include <pipewire/impl.h>
47
-#include <pipewire/thread.h>
48
-
49
-/** \page page_module_rtkit PipeWire Module: RTKit
50
- */
51
-
52
-#define NAME "rtkit"
53
-
54
-PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
55
-#define PW_LOG_TOPIC_DEFAULT mod_topic
56
-
57
-#define DEFAULT_NICE_LEVEL -11
58
-#define DEFAULT_RT_PRIO        88
59
-#define DEFAULT_RT_TIME_SOFT   2000000
60
-#define DEFAULT_RT_TIME_HARD   2000000
61
-
62
-#define MODULE_USAGE   "[nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL) ">] "    \
63
-           "[rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO) ">] "      \
64
-           "[rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] "   \
65
-           "[rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] "
66
-
67
-static const struct spa_dict_item module_props[] = {
68
-   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
69
-   { PW_KEY_MODULE_DESCRIPTION, "Use RTKit to raise thread priorities" },
70
-   { PW_KEY_MODULE_USAGE, MODULE_USAGE },
71
-   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
72
-};
73
-
74
-struct pw_rtkit_bus;
75
-
76
-struct thread {
77
-   struct impl *impl;
78
-   struct spa_list link;
79
-   pthread_t thread;
80
-   pid_t pid;
81
-   void *(*start)(void*);
82
-   void *arg;
83
-};
84
-
85
-struct impl {
86
-   struct pw_context *context;
87
-
88
-   struct pw_properties *props;
89
-
90
-   struct pw_rtkit_bus *system_bus;
91
-
92
-   pthread_mutex_t lock;
93
-   pthread_cond_t cond;
94
-
95
-   struct spa_list threads_list;
96
-   struct spa_thread_utils thread_utils;
97
-
98
-   int nice_level;
99
-   int rt_prio;
100
-   rlim_t rt_time_soft;
101
-   rlim_t rt_time_hard;
102
-
103
-   struct spa_hook module_listener;
104
-};
105
-
106
-/***
107
-  Copyright 2009 Lennart Poettering
108
-  Copyright 2010 David Henningsson <diwic@ubuntu.com>
109
-
110
-  Permission is hereby granted, free of charge, to any person
111
-  obtaining a copy of this software and associated documentation files
112
-  (the "Software"), to deal in the Software without restriction,
113
-  including without limitation the rights to use, copy, modify, merge,
114
-  publish, distribute, sublicense, and/or sell copies of the Software,
115
-  and to permit persons to whom the Software is furnished to do so,
116
-  subject to the following conditions:
117
-
118
-  The above copyright notice and this permission notice shall be
119
-  included in all copies or substantial portions of the Software.
120
-
121
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
122
-  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
123
-  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
124
-  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
125
-  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
126
-  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
127
-  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
128
-  SOFTWARE.
129
-***/
130
-
131
-#include <dbus/dbus.h>
132
-
133
-#include "config.h"
134
-
135
-#include <sys/syscall.h>
136
-
137
-#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
138
-#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
139
-
140
-#ifndef RLIMIT_RTTIME
141
-#define RLIMIT_RTTIME 15
142
-#endif
143
-
144
-/** \cond */
145
-struct pw_rtkit_bus {
146
-   DBusConnection *bus;
147
-};
148
-/** \endcond */
149
-
150
-struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
151
-{
152
-   struct pw_rtkit_bus *bus;
153
-   DBusError error;
154
-
155
-   if (getenv("DISABLE_RTKIT")) {
156
-       errno = ENOTSUP;
157
-       return NULL;
158
-   }
159
-
160
-   dbus_error_init(&error);
161
-
162
-   bus = calloc(1, sizeof(struct pw_rtkit_bus));
163
-   if (bus == NULL)
164
-       return NULL;
165
-
166
-   bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
167
-   if (bus->bus == NULL)
168
-       goto error;
169
-
170
-   dbus_connection_set_exit_on_disconnect(bus->bus, false);
171
-
172
-   return bus;
173
-
174
-error:
175
-   free(bus);
176
-   pw_log_error("Failed to connect to system bus: %s", error.message);
177
-   dbus_error_free(&error);
178
-   errno = ECONNREFUSED;
179
-   return NULL;
180
-}
181
-
182
-void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
183
-{
184
-   dbus_connection_close(system_bus->bus);
185
-   dbus_connection_unref(system_bus->bus);
186
-   free(system_bus);
187
-}
188
-
189
-static pid_t _gettid(void)
190
-{
191
-#if defined(HAVE_GETTID)
192
-   return (pid_t) gettid();
193
-#elif defined(__linux__)
194
-   return syscall(SYS_gettid);
195
-#elif defined(__FreeBSD__)
196
-   long pid;
197
-   thr_self(&pid);
198
-   return (pid_t)pid;
199
-#else
200
-#error "No gettid impl"
201
pipewire-0.3.43.tar.gz/.cirrus.yml -> pipewire-0.3.44.tar.gz/.cirrus.yml Changed
10
 
1
@@ -17,7 +17,7 @@
2
   build_script:
3
     - mkdir build
4
     - cd build
5
-    - meson setup -Dalsa=enabled -Draop=enabled -Dv4l2=enabled -Dpipewire-alsa=enabled -Dbluez5=disabled -Djack=disabled -Dpipewire-jack=disabled -Dpw-cat=enabled -Dpipewire-v4l2=disabled -Dsdl2=enabled -Dsystemd=disabled -Dsession-managers=media-session ..
6
+    - meson setup -Dalsa=enabled -Draop=enabled -Dv4l2=enabled -Dpipewire-alsa=enabled -Dbluez5=disabled -Djack=disabled -Dpipewire-jack=enabled -Dpw-cat=enabled -Dpipewire-v4l2=disabled -Dsdl2=enabled -Dsystemd=disabled -Dsession-managers=media-session ..
7
     - ninja
8
   test_script:
9
     - cd build
10
pipewire-0.3.43.tar.gz/.gitlab-ci.yml -> pipewire-0.3.44.tar.gz/.gitlab-ci.yml Changed
32
 
1
@@ -8,8 +8,8 @@
2
 variables:
3
   FDO_UPSTREAM_REPO: 'pipewire/pipewire'
4
 
5
-# ci-templates as of March 19th 2021
6
-.templates_sha: &templates_sha 290b79e0e78eab67a83766f4e9691be554fc4afd
7
+# ci-templates as of Jan 27th 2022
8
+.templates_sha: &templates_sha 0c312d9c7255f46e741d43bcd1930f09cd12efe7
9
 
10
 include:
11
   - project: 'freedesktop/ci-templates'
12
@@ -22,8 +22,8 @@
13
 .fedora:
14
   variables:
15
     # Update this tag when you want to trigger a rebuild
16
-    FDO_DISTRIBUTION_TAG: '2021-10-12.1'
17
-    FDO_DISTRIBUTION_VERSION: '34'
18
+    FDO_DISTRIBUTION_TAG: '2022-01-27.1'
19
+    FDO_DISTRIBUTION_VERSION: '35'
20
     FDO_DISTRIBUTION_PACKAGES: >-
21
       alsa-lib-devel
22
       bluez-libs-devel
23
@@ -62,7 +62,7 @@
24
 .ubuntu:
25
   variables:
26
     # Update this tag when you want to trigger a rebuild
27
-    FDO_DISTRIBUTION_TAG: '2021-10-15.0'
28
+    FDO_DISTRIBUTION_TAG: '2022-01-27.0'
29
     FDO_DISTRIBUTION_VERSION: '20.04'
30
     FDO_DISTRIBUTION_PACKAGES: >-
31
       debhelper-compat
32
pipewire-0.3.43.tar.gz/NEWS -> pipewire-0.3.44.tar.gz/NEWS Changed
156
 
1
@@ -1,4 +1,142 @@
2
-# PipeWire 0.3.43 (2021-01-05)
3
+# PipeWire 0.3.44 (2022-01-27)
4
+
5
+This is a bugfix release that is API and ABI compatible with previous
6
+0.3.x releases.
7
+
8
+## Highlights
9
+  - It is now possible to run a minimal PipeWire server without a session
10
+    manager, enough to run JACK clients.
11
+  - The maximum buffer size is now configurable and can be larger than
12
+    the previously hardcoded limit of 8192 samples. When using high sample
13
+    rates, the larger buffer size can avoid xruns.
14
+  - The default maximum latency was reduced from 170ms to 42ms. This should
15
+    improve overall latency for application that ask for a large latency,
16
+    such as notifications.
17
+  - Better JACK compatibility. Patchbays should now get less confused about
18
+    ports appearing and disappearing.
19
+  - Fix some bluetooth crashes.
20
+  - Fix some races in ALSA device detection.
21
+  - Many bug fixes and improvements all over the place.
22
+
23
+## PipeWire
24
+  - Bump the meson requirement to 0.59.0.
25
+  - pw-top now reports correct times for filter-chain and loopback.
26
+  - max-quantum is now also scaled with the rate. A new quantum-limit
27
+    property was added as a hard limit for the quantum. This makes it
28
+    possible to configure for larger than 8192 buffer sizes. Note
29
+    than many JACK applications have a hardcoded 8192 limit. (#1931)
30
+  - The max-quantum was reduced to 2048, This gives a 42ms default
31
+    latency. (#1908)
32
+  - pw-filter can now return a NULL buffer from _get_dsp_buffer().
33
+  - Add a PIPEWIRE_RATE and PIPEWIRE_QUANTUM env variable to set the
34
+    graph rate and the graph quantum and rate respectively.
35
+  - Fix a potential file descriptor leak in the connection.
36
+  - A new minimal.conf file was added to demonstrate a static setup
37
+    of a daemon that doesn't require a session manager and is able to
38
+    run JACK applicaions.
39
+  - Nice levels are now only changed on the servers, not the clients.
40
+  - Add an option to suspend nodes when idle.
41
+  - Make it possible to avoid quantum and rate changes with
42
+    pw-metadata. This is essential in a locked down system.
43
+  - Handle mixer port errors better and fail to create the link instead
44
+    of silently not working.
45
+  - Nodes that are moved to a driver now have all the linked nodes moved
46
+    as well. This makes it possible to run some graphs without a
47
+    driver, such as paplay -> zita-j2n.
48
+  - pw-cli and pw-dump can now also list objects by name, serial and
49
+    object.path using glob style pattern matching.
50
+
51
+
52
+## modules
53
+  - filter-chain can now also configure parameters by index.
54
+  - Fix the client name of module-protocol-simple. (#2017)
55
+  - module-rtkit was merged into module-rt. This makes it easier to
56
+    ship a default config that works on more systems by default.
57
+  - module-adapter can now configure the adapter node from the config.
58
+    Previously, this was a task only performed by the session manager.
59
+  - module-metadata can now also create metadata object from the
60
+    config file.
61
+  - The ROC module should now work again. (#2045)
62
+  - An X11-bell module was added to handle X11 bell events. (#1668)
63
+  - filter-chain and loopback modules now have better unique default
64
+    names for the streams, which makes it possible to save and restore
65
+    their volumes independently. (#1983)
66
+  - module-echo-cancel now has properties to control the delay and
67
+    buffer size.
68
+
69
+## ALSA
70
+  - The monitor names are now correctly parsed.
71
+  - The default period size for batch devices is limited now to avoid
72
+    large latency.
73
+  - The unused min/max-latency properties were removed.
74
+  - Internal latency is now also configurable with params at runtime.
75
+  - The udev rule for TI2902 was removed because it causes problems.
76
+  - Fix a race where some devices would sometimes be missing. (#2046)
77
+  - Add some more timeouts to work around a race in udev device
78
+    permission changes when switching VTs.
79
+
80
+## SPA
81
+  - Fix potential infinite loop in audioconvert.
82
+  - The spa-resample tools can now also use optimized implementations.
83
+  - Fix a potential crash in resampler. (#1994)
84
+  - audioconvert can now also handle F64 formats. (#1990)
85
+  - The channelmixer now does normalization by default to avoid clipping
86
+    when downmixing is active.
87
+  - The channelmixer will now generate LFE channels when the lfe_cutoff
88
+    frequency is set, even when upmix is disabled.
89
+  - The channelmixer will now always generate FC when the target has it.
90
+  - Adapter now reports latency correctly, even after linking the monitor
91
+    ports.
92
+  - Reduce memory usage and preallocated memory in some of the
93
+    audioconvert nodes.
94
+  - Many properties are now exposed in adapter, such as the resample
95
+    quality.
96
+  - The resampler and channelmixer can now be disabled.
97
+
98
+## V4L2
99
+  - pw-v4l2 now also works for ffplay. (#2029)
100
+  - Take product names from udev now that the kernel returns a generic
101
+    name.
102
+
103
+## JACK
104
+  - The jack pkgconfig file now has the `jack_implementation=pipewire`
105
+    variable to be able to distinguish jack implementations. (#1666)
106
+  - jconvolver now starts correctly again. (#1989)
107
+  - The object.serial is now used for the port_id. This makes it easier
108
+    to track old objects in the cache.
109
+  - Add a dummy jacknet implementation. (#2043)
110
+  - A bug in the port allocation was fixed that would make it impossible
111
+    to allocate ports at some point. (#1714)
112
+
113
+## Bluetooth
114
+  - Bluetooth profiles are now saved properly by the session manager.
115
+  - Improved profile detections, increased timeouts for slow devices.
116
+  - Implement HFP call indicator for improved compatibility.
117
+  - Handle the case where bluez does not set the adapter or address
118
+    properties on the device instead of crashing.
119
+  - Improved support for setting the profile from the session manager.
120
+
121
+## pulse-server
122
+  - Monitor sources now have the device.class=monitor for better
123
+    compatibility.
124
+  - Behaviour after seeking is improved. The algorithm for requesting
125
+    bytes from the client was simplified and improved. (#1981)
126
+  - module-ladspa-sink implements the control argument now. (#1987)
127
+  - A potential memory leak in the message queue was fixed. (#1840)
128
+  - Use the object.serial for the pulseaudio object index. The index is
129
+    not supposed to be reused and this would cause problems with some
130
+    clients.
131
+  - Servers should now again be able to listen in IPv4. (#2047)
132
+  - module-x11-bell was added. (#1668)
133
+  - There is now support for per-application quirks and properties in
134
+    the pipewire-pulse.conf file. Per-application latency and buffering
135
+    properties can also be configured.
136
+  - Fix a regression in telegram sounds not playing.
137
+
138
+
139
+Older versions:
140
+
141
+# PipeWire 0.3.43 (2022-01-05)
142
 
143
 This is a bugfix release that is API and ABI compatible with previous
144
 0.3.x releases.
145
@@ -81,10 +219,6 @@
146
   - Add command access control. This avoids execution of commands without
147
     proper authentication.
148
 
149
-
150
-Older versions:
151
-
152
-
153
 # PipeWire 0.3.42 (2021-12-16)
154
 
155
 This is a bugfix release that is API and ABI compatible with previous
156
pipewire-0.3.43.tar.gz/README.md -> pipewire-0.3.44.tar.gz/README.md Changed
15
 
1
@@ -48,6 +48,13 @@
2
                   expressed as a fraction of the samplerate,
3
                   like 256/48000, which uses 256 samples at a
4
                   samplerate of 48KHz for a latency of 5.33ms.
5
+                  This function does not attempt to configure
6
+                  the samplerate.
7
+* `PIPEWIRE_RATE=<num/denom>`      to configure a rate for the graph.
8
+* `PIPEWIRE_QUANTUM=<num/denom>`   to configure latency as a fraction and a
9
+                  samplerate. This function will attempt to change
10
+                  the graph samplerate to `denom` and use the
11
+                  specified `num` as the buffer size.
12
 * `PIPEWIRE_NODE=<id>`             to request a link to the specified node
13
 
14
 ### Using tools
15
pipewire-0.3.44.tar.gz/doc/manpage.dox.in Added
7
 
1
@@ -0,0 +1,5 @@
2
+/** \page @pagename@ @title@
3
+
4
+\verbinclude @filename@
5
+
6
+*/
7
pipewire-0.3.43.tar.gz/doc/meson.build -> pipewire-0.3.44.tar.gz/doc/meson.build Changed
49
 
1
@@ -26,7 +26,6 @@
2
   'pipewire-daemon.dox',
3
   'pipewire-library.dox',
4
   'pipewire-modules.dox',
5
-  'pipewire-tools.dox',
6
   'pipewire-session-manager.dox',
7
   'pipewire-objects-design.dox',
8
   'pipewire-audio.dox',
9
@@ -115,6 +114,30 @@
10
 
11
 input_dirs += [ 'doc/examples.dox' ]
12
 
13
+man_doxygen = []
14
+man_subpages = []
15
+foreach m : manpages
16
+  manconf = configuration_data()
17
+  pagename = 'page_man_' + m.split('.rst.in').get(0).replace('.', '_').replace('-', '_')
18
+  filename = m.split('.rst.in').get(0) + '.dox'
19
+  manconf.set('pagename', pagename)
20
+  manconf.set('title', m.split('.rst.in').get(0).replace('.1','').replace('.5',''))
21
+  manconf.set('filename', meson.project_source_root() / 'man' / m)
22
+  manfile = configure_file(input: 'manpage.dox.in',
23
+                           output: filename,
24
+                           configuration: manconf)
25
+  man_doxygen += [manfile]
26
+  man_subpages += ['- \subpage ' + pagename]
27
+  input_dirs += [ 'doc/' + filename ]
28
+endforeach
29
+
30
+pw_tools_dox_conf = configuration_data()
31
+pw_tools_dox_conf.set('man_subpages', '\n'.join(man_subpages))
32
+pw_tools_dox = configure_file(input: 'pipewire-tools.dox.in',
33
+                          output: 'pipewire-tools.dox',
34
+                          configuration: pw_tools_dox_conf)
35
+input_dirs += [ 'doc/pipewire-tools.dox' ]
36
+
37
 doxyfile_conf.set('inputs', ' '.join(inputs + input_dirs))
38
 doxyfile_conf.set('cssfiles', ' '.join(cssfiles))
39
 doxyfile_conf.set('path_prefixes', ' '.join(path_prefixes))
40
@@ -131,7 +154,7 @@
41
 endif
42
 
43
 html_target = custom_target('pipewire-docs',
44
-                            input: [ doxyfile, examples_dox ] + inputs + cssfiles,
45
+                            input: [ doxyfile, examples_dox, pw_tools_dox ] + inputs + cssfiles + man_doxygen,
46
                             output: [ 'html' ],
47
                             command: [ doxygen, doxyfile ],
48
                             install: true,
49
pipewire-0.3.43.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.44.tar.gz/doc/pipewire-modules.dox Changed
11
 
1
@@ -74,8 +74,8 @@
2
 - \subpage page_module_roc_sink
3
 - \subpage page_module_roc_source
4
 - \subpage page_module_rt
5
-- \subpage page_module_rtkit
6
 - \subpage page_module_session_manager
7
+- \subpage page_module_x11_bell
8
 - \subpage page_module_zeroconf_discover
9
 
10
 
11
pipewire-0.3.44.tar.gz/doc/pipewire-tools.dox.in Added
9
 
1
@@ -0,0 +1,7 @@
2
+/** \page page_tools PipeWire Tools
3
+
4
+Manual pages:
5
+
6
+@man_subpages@
7
+
8
+*/
9
pipewire-0.3.43.tar.gz/man/meson.build -> pipewire-0.3.44.tar.gz/man/meson.build Changed
12
 
1
@@ -23,6 +23,10 @@
2
   manpages += 'pw-jack.1.rst.in'
3
 endif
4
 
5
+if not generate_manpages
6
+  subdir_done()
7
+endif
8
+
9
 foreach m : manpages
10
   file = m.split('.rst.in').get(0)
11
   rst = configure_file(input : m,
12
pipewire-0.3.43.tar.gz/man/pipewire-pulse.1.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire-pulse.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pipewire-pulse
5
 ##############
6
 
7
pipewire-0.3.43.tar.gz/man/pipewire.1.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pipewire
5
 ########
6
 
7
pipewire-0.3.43.tar.gz/man/pipewire.conf.5.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire.conf.5.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pipewire.conf
5
 #############
6
 
7
pipewire-0.3.43.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-cat.1.rst.in Changed
27
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-cat
5
 ######
6
 
7
@@ -44,13 +42,16 @@
8
   a connection is made to the default PipeWire instance.
9
 
10
 -p | --playback
11
-  Playback mode. Read data from the specified file, and play it back. If the tool is called under the name **pw-play** or **pw-midiplay** this is the default.
12
+  Playback mode. Read data from the specified file, and play it back. If the tool
13
+  is called under the name **pw-play** or **pw-midiplay** this is the default.
14
 
15
 -r | --record
16
-  Recording mode. Capture data and write it to the specified file. If the tool is called under the name **pw-record** or **pw-midirecord** this is the default.
17
+  Recording mode. Capture data and write it to the specified file. If the tool is
18
+  called under the name **pw-record** or **pw-midirecord** this is the default.
19
 
20
 -m | --midi
21
-  MIDI mode. *FILE* is a MIDI file. If the tool is called under the name **pw-midiplay** or **pw-midirecord** this is the default.
22
+  MIDI mode. *FILE* is a MIDI file. If the tool is called under the name
23
+  **pw-midiplay** or **pw-midirecord** this is the default.
24
 
25
 --media-type=VALUE
26
   Set the media type property (default Audio/Midi depending on mode).
27
pipewire-0.3.43.tar.gz/man/pw-cli.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-cli.1.rst.in Changed
17
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-cli
5
 ######
6
 
7
@@ -45,7 +43,8 @@
8
 MODULE MANAGEMENT
9
 =================
10
 
11
-| Modules are loaded and unloaded in the local instance and can add functionality or objects to the local instance.
12
+| Modules are loaded and unloaded in the local instance and can add
13
+| functionality or objects to the local instance.
14
 
15
 load-module *name* [*arguments...*]
16
   Load a module specified by its name and arguments. For most
17
pipewire-0.3.43.tar.gz/man/pw-dot.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-dot.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-dot
5
 ######
6
 
7
pipewire-0.3.43.tar.gz/man/pw-jack.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-jack.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-jack
5
 #######
6
 
7
pipewire-0.3.43.tar.gz/man/pw-metadata.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-metadata.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-metadata
5
 ###########
6
 
7
pipewire-0.3.43.tar.gz/man/pw-mididump.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-mididump.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-mididump
5
 ###########
6
 
7
pipewire-0.3.43.tar.gz/man/pw-mon.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-mon.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-mon
5
 ######
6
 
7
pipewire-0.3.43.tar.gz/man/pw-profiler.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-profiler.1.rst.in Changed
7
 
1
@@ -1,5 +1,3 @@
2
-.. This file is part of PipeWire.
3
-
4
 pw-profiler
5
 ###########
6
 
7
pipewire-0.3.43.tar.gz/meson.build -> pipewire-0.3.44.tar.gz/meson.build Changed
116
 
1
@@ -1,7 +1,7 @@
2
 project('pipewire', ['c' ],
3
-  version : '0.3.43',
4
+  version : '0.3.44',
5
   license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
6
-  meson_version : '>= 0.56.0',
7
+  meson_version : '>= 0.59.0',
8
   default_options : [ 'warning_level=3',
9
                       'c_std=gnu99',
10
                       'cpp_std=c++17',
11
@@ -323,12 +323,12 @@
12
 dl_lib = cc.find_library('dl', required : false)
13
 pthread_lib = dependency('threads')
14
 dbus_dep = dependency('dbus-1', required : get_option('dbus'))
15
-summary({'dbus (Bluetooth, rtkit, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies')
16
+summary({'dbus (Bluetooth, rt, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies')
17
 if dbus_dep.found()
18
   cdata.set('HAVE_DBUS', 1)
19
 endif
20
 sdl_dep = dependency('sdl2', required : get_option('sdl2'))
21
-summary({'SDL 2': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
22
+summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
23
 drm_dep = dependency('libdrm', required : false)
24
 readline_dep = dependency('readline', required : false)
25
 
26
@@ -349,6 +349,14 @@
27
 summary({'Avahi DNS-SD (Zeroconf)': avahi_dep.found()}, bool_yn: true,
28
   section: 'Streaming between daemons')
29
 
30
+x11_dep = dependency('x11-xcb', required : get_option('x11'))
31
+summary({'X11 (x11-bell)': x11_dep.found()}, bool_yn: true,
32
+  section: 'Misc dependencies')
33
+
34
+canberra_dep = dependency('libcanberra', required : get_option('libcanberra'))
35
+summary({'libcanberra (x11-bell)': canberra_dep.found()}, bool_yn: true,
36
+  section: 'Misc dependencies')
37
+
38
 libusb_dep = dependency('libusb-1.0', required : get_option('libusb'))
39
 summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend')
40
 if libusb_dep.found()
41
@@ -479,22 +487,25 @@
42
   subdir('pipewire-alsa/tests')
43
 endif
44
 
45
-doxygen = find_program('doxygen', required : get_option('docs'))
46
-if doxygen.found()
47
-  subdir('doc')
48
-endif
49
-
50
+generate_manpages = false
51
 if not get_option('man').disabled()
52
   rst2man = find_program('rst2man', required: false)
53
   if not rst2man.found()
54
     rst2man = find_program('rst2man.py', required: get_option('man'))
55
   endif
56
-  summary({'Manpage generation': rst2man.found()}, bool_yn: true)
57
   if rst2man.found()
58
-    subdir('man')
59
+    generate_manpages = true
60
   endif
61
 endif
62
 
63
+summary({'Manpage generation': generate_manpages}, bool_yn: true)
64
+subdir('man')
65
+
66
+doxygen = find_program('doxygen', required : get_option('docs'))
67
+if doxygen.found()
68
+  subdir('doc')
69
+endif
70
+
71
 setenv = find_program('pw-uninstalled.sh')
72
 run_target('pw-uninstalled',
73
   command : [setenv,
74
@@ -502,27 +513,25 @@
75
              '-v@0@'.format(pipewire_version)]
76
 )
77
 
78
-if meson.version().version_compare('>=0.58.0')
79
-  devenv = environment()
80
+devenv = environment()
81
 
82
-  builddir = meson.project_build_root()
83
-  srcdir = meson.project_source_root()
84
+builddir = meson.project_build_root()
85
+srcdir = meson.project_source_root()
86
 
87
-  devenv.set('PIPEWIRE_CONFIG_DIR', pipewire_dep.get_variable(internal: 'confdatadir'))
88
-  devenv.set('PIPEWIRE_MODULE_DIR', pipewire_dep.get_variable(internal: 'moduledir'))
89
+devenv.set('PIPEWIRE_CONFIG_DIR', pipewire_dep.get_variable('confdatadir'))
90
+devenv.set('PIPEWIRE_MODULE_DIR', pipewire_dep.get_variable('moduledir'))
91
 
92
-  devenv.set('SPA_PLUGIN_DIR', spa_dep.get_variable(internal: 'plugindir'))
93
-  devenv.set('SPA_DATA_DIR', spa_dep.get_variable(internal: 'datadir'))
94
+devenv.set('SPA_PLUGIN_DIR', spa_dep.get_variable('plugindir'))
95
+devenv.set('SPA_DATA_DIR', spa_dep.get_variable('datadir'))
96
 
97
-  devenv.set('GST_PLUGIN_PATH', builddir / 'src'/ 'gst')
98
+devenv.set('GST_PLUGIN_PATH', builddir / 'src'/ 'gst')
99
 
100
-  devenv.set('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins')
101
-  devenv.set('ACP_PATHS_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'paths')
102
-  devenv.set('ACP_PROFILES_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'profile-sets')
103
+devenv.set('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins')
104
+devenv.set('ACP_PATHS_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'paths')
105
+devenv.set('ACP_PROFILES_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'profile-sets')
106
 
107
-  devenv.set('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src')
108
+devenv.set('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src')
109
 
110
-  devenv.set('PW_UNINSTALLED', '1')
111
+devenv.set('PW_UNINSTALLED', '1')
112
 
113
-  meson.add_devenv(devenv)
114
-endif
115
+meson.add_devenv(devenv)
116
pipewire-0.3.43.tar.gz/meson_options.txt -> pipewire-0.3.44.tar.gz/meson_options.txt Changed
23
 
1
@@ -179,6 +179,9 @@
2
 option('udevrulesdir',
3
        type : 'string',
4
        description : 'Directory for udev rules (defaults to /lib/udev/rules.d)')
5
+option('systemd-system-unit-dir',
6
+       type : 'string',
7
+       description : 'Directory for system systemd units (defaults to /usr/lib/systemd/system)')
8
 option('systemd-user-unit-dir',
9
        type : 'string',
10
        description : 'Directory for user systemd units (defaults to /usr/lib/systemd/user)')
11
@@ -222,3 +225,11 @@
12
        description: 'Enable loading of LV2 plugins',
13
        type: 'feature',
14
        value: 'auto')
15
+option('x11',
16
+       description: 'Enable code that depends on X11',
17
+       type: 'feature',
18
+       value: 'auto')
19
+option('libcanberra',
20
+       description: 'Enable code that depends on libcanberra',
21
+       type: 'feature',
22
+       value: 'auto')
23
pipewire-0.3.43.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.44.tar.gz/pipewire-jack/src/meson.build Changed
34
 
1
@@ -11,10 +11,9 @@
2
   'control.c',
3
 ]
4
 
5
-pipewire_dummy_sources = [
6
-  'dummy.c',
7
+pipewire_net_sources = [
8
+  'net.c',
9
 ]
10
-
11
 pipewire_jack_c_args = [
12
   '-DPIC',
13
 ]
14
@@ -57,8 +56,8 @@
15
     install_dir : libjack_path,
16
 )
17
 
18
-pipewire_jackserver = shared_library('jacknet',
19
-    pipewire_dummy_sources,
20
+pipewire_jacknet = shared_library('jacknet',
21
+    pipewire_net_sources,
22
     soversion : soversion,
23
     version : libversion,
24
     c_args : pipewire_jack_c_args,
25
@@ -85,7 +84,7 @@
26
   description : 'PipeWire JACK API',
27
   version : '1.9.17',
28
   extra_cflags : '-D_REENTRANT',
29
-  unescaped_variables: ['server_libs=-L${libdir} -ljackserver'])
30
+  unescaped_variables: ['server_libs=-L${libdir} -ljackserver', 'jack_implementation=pipewire'])
31
 endif
32
 
33
 if sdl_dep.found()
34
pipewire-0.3.43.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.44.tar.gz/pipewire-jack/src/metadata.c Changed
31
 
1
@@ -213,7 +213,8 @@
2
              const char* type)
3
 {
4
    struct client *c = (struct client *) client;
5
-   uint32_t id;
6
+   struct object *o;
7
+   uint32_t serial;
8
    int res = -1;
9
 
10
    spa_return_val_if_fail(c != NULL, -EINVAL);
11
@@ -227,14 +228,16 @@
12
    if (subject & (1<<30))
13
        goto done;
14
 
15
-   id = jack_uuid_to_index(subject);
16
+   serial = jack_uuid_to_index(subject);
17
+   if ((o = find_by_serial(c, serial)) == NULL)
18
+       goto done;
19
 
20
    if (type == NULL)
21
        type = "";
22
 
23
-   pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", id, subject, key, value, type);
24
+   pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", o->id, subject, key, value, type);
25
    if (update_property(c, subject, key, type, value))
26
-       pw_metadata_set_property(c->metadata->proxy, id, key, type, value);
27
+       pw_metadata_set_property(c->metadata->proxy, o->id, key, type, value);
28
    res = 0;
29
 done:
30
    pw_thread_loop_unlock(c->context.loop);
31
pipewire-0.3.44.tar.gz/pipewire-jack/src/net.c Added
171
 
1
@@ -0,0 +1,169 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include "config.h"
27
+
28
+#include <stdio.h>
29
+#include <unistd.h>
30
+#include <errno.h>
31
+
32
+#include <jack/net.h>
33
+
34
+#include <pipewire/pipewire.h>
35
+
36
+SPA_EXPORT
37
+jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name,
38
+       jack_slave_t* request, jack_master_t* result)
39
+{
40
+   return NULL;
41
+}
42
+
43
+SPA_EXPORT
44
+int jack_net_slave_close(jack_net_slave_t* net)
45
+{
46
+   return ENOTSUP;
47
+}
48
+
49
+SPA_EXPORT
50
+int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg)
51
+{
52
+   return ENOTSUP;
53
+}
54
+
55
+SPA_EXPORT
56
+int jack_net_slave_activate(jack_net_slave_t* net)
57
+{
58
+   return ENOTSUP;
59
+}
60
+
61
+SPA_EXPORT
62
+int jack_net_slave_deactivate(jack_net_slave_t* net)
63
+{
64
+   return ENOTSUP;
65
+}
66
+
67
+SPA_EXPORT
68
+int jack_net_slave_is_active(jack_net_slave_t* net)
69
+{
70
+   return false;
71
+}
72
+
73
+SPA_EXPORT
74
+int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
75
+{
76
+   return ENOTSUP;
77
+}
78
+
79
+SPA_EXPORT
80
+int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
81
+{
82
+   return ENOTSUP;
83
+}
84
+
85
+SPA_EXPORT
86
+int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
87
+{
88
+   return ENOTSUP;
89
+}
90
+
91
+SPA_EXPORT
92
+int jack_set_net_slave_restart_callback(jack_net_slave_t *net, JackNetSlaveRestartCallback restart_callback, void *arg)
93
+{
94
+   return ENOTSUP;
95
+}
96
+
97
+SPA_EXPORT
98
+int jack_set_net_slave_error_callback(jack_net_slave_t *net, JackNetSlaveErrorCallback error_callback, void *arg)
99
+{
100
+   return ENOTSUP;
101
+}
102
+
103
+SPA_EXPORT
104
+jack_net_master_t* jack_net_master_open(const char* ip, int port, jack_master_t* request, jack_slave_t* result)
105
+{
106
+   return NULL;
107
+}
108
+
109
+SPA_EXPORT
110
+int jack_net_master_close(jack_net_master_t* net)
111
+{
112
+   return ENOTSUP;
113
+}
114
+
115
+SPA_EXPORT
116
+int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
117
+{
118
+   return ENOTSUP;
119
+}
120
+
121
+SPA_EXPORT
122
+int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames)
123
+{
124
+   return ENOTSUP;
125
+}
126
+
127
+SPA_EXPORT
128
+int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
129
+{
130
+   return ENOTSUP;
131
+}
132
+
133
+SPA_EXPORT
134
+int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames)
135
+{
136
+   return ENOTSUP;
137
+}
138
+
139
+SPA_EXPORT
140
+jack_adapter_t* jack_create_adapter(int input, int output,
141
+                                    jack_nframes_t host_buffer_size,
142
+                                    jack_nframes_t host_sample_rate,
143
+                                    jack_nframes_t adapted_buffer_size,
144
+                                    jack_nframes_t adapted_sample_rate)
145
+{
146
+   return NULL;
147
+}
148
+
149
+SPA_EXPORT
150
+int jack_destroy_adapter(jack_adapter_t* adapter)
151
+{
152
+   return ENOTSUP;
153
+}
154
+
155
+SPA_EXPORT
156
+void jack_flush_adapter(jack_adapter_t* adapter)
157
+{
158
+}
159
+
160
+SPA_EXPORT
161
+int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
162
+{
163
+   return ENOTSUP;
164
+}
165
+
166
+SPA_EXPORT
167
+int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
168
+{
169
+   return ENOTSUP;
170
+}
171
pipewire-0.3.43.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.44.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
201
 
1
@@ -99,14 +99,14 @@
2
    jack_thread_creator_t creator;
3
    pthread_mutex_t lock;
4
    struct pw_array descriptions;
5
-   struct spa_list free_objects[3];
6
-   struct pw_map cache;
7
+   struct spa_list free_objects;
8
 };
9
 
10
 static struct globals globals;
11
 static bool mlock_warned = false;
12
 
13
-#define OBJECT_CHUNK   8
14
+#define OBJECT_CHUNK       8
15
+#define RECYCLE_THRESHOLD  128
16
 
17
 typedef void (*mix2_func) (float *dst, float *src1, float *src2, int n_samples);
18
 
19
@@ -122,7 +122,7 @@
20
 #define INTERFACE_Link     2
21
    uint32_t type;
22
    uint32_t id;
23
-   uint32_t idx;
24
+   uint32_t serial;
25
 
26
    union {
27
        struct {
28
@@ -134,11 +134,11 @@
29
        struct {
30
            uint32_t src;
31
            uint32_t dst;
32
+           uint32_t src_serial;
33
+           uint32_t dst_serial;
34
            bool src_ours;
35
            bool dst_ours;
36
            bool is_complete;
37
-           uint32_t src_idx;
38
-           uint32_t dst_idx;
39
            struct port *our_input;
40
            struct port *our_output;
41
        } port_link;
42
@@ -151,7 +151,6 @@
43
            uint32_t system_id;
44
            uint32_t type_id;
45
            uint32_t node_id;
46
-           uint32_t port_id;
47
            uint32_t monitor_requests;
48
            int32_t priority;
49
            struct port *port;
50
@@ -164,6 +163,7 @@
51
    struct spa_hook proxy_listener;
52
    struct spa_hook object_listener;
53
    unsigned int removing:1;
54
+   unsigned int removed:1;
55
 };
56
 
57
 struct midi_buffer {
58
@@ -223,7 +223,7 @@
59
    struct client *client;
60
 
61
    enum spa_direction direction;
62
-   uint32_t id;
63
+   uint32_t port_id;
64
    struct object *object;
65
    struct pw_properties *props;
66
    struct spa_port_info info;
67
@@ -264,15 +264,13 @@
68
    struct pw_context *context;
69
 
70
    pthread_mutex_t lock;       /* protects map and lists below, in addition to thread_lock */
71
-   struct pw_map globals;
72
-   struct spa_list ports;
73
-   struct spa_list nodes;
74
-   struct spa_list links;
75
+   struct spa_list objects;
76
+   uint32_t free_count;
77
 };
78
 
79
 #define GET_DIRECTION(f)   ((f) & JackPortIsInput ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT)
80
 
81
-#define GET_PORT(c,d,p)        ((d >= 0 && d <=1 && p < c->n_port_pool[d]) ? c->port_pool[d][p] : NULL)
82
+#define GET_PORT(c,d,p)        (pw_map_lookup(&c->ports[d], p))
83
 
84
 struct metadata {
85
    struct pw_metadata *proxy;
86
@@ -315,6 +313,7 @@
87
    struct metadata *metadata;
88
 
89
    uint32_t node_id;
90
+   uint32_t serial;
91
    struct spa_source *socket_source;
92
 
93
    JackThreadCallback thread_callback;
94
@@ -362,10 +361,8 @@
95
    struct spa_list mix;
96
    struct spa_list free_mix;
97
 
98
-   uint32_t n_port_pool[2];
99
-   struct port *port_pool[2][MAX_PORTS];
100
-   struct spa_list ports[2];
101
-   struct spa_list free_ports[2];
102
+   struct spa_list free_ports;
103
+   struct pw_map ports[2];
104
 
105
    struct spa_list links;
106
    uint32_t driver_id;
107
@@ -406,6 +403,7 @@
108
 };
109
 
110
 static int do_sync(struct client *client);
111
+static struct object *find_by_serial(struct client *c, uint32_t serial);
112
 
113
 #include "metadata.c"
114
 
115
@@ -413,64 +411,66 @@
116
        int (*matched) (void *data, const char *action, const char *val, int len),
117
        void *data);
118
 
119
-static void init_port_pool(struct client *c, enum spa_direction direction)
120
-{
121
-   spa_list_init(&c->ports[direction]);
122
-   spa_list_init(&c->free_ports[direction]);
123
-   c->n_port_pool[direction] = 0;
124
-}
125
-
126
-static struct object * find_cache(uint32_t type, uint32_t idx)
127
-{
128
-   struct object *o;
129
-   pthread_mutex_lock(&globals.lock);
130
-   o = pw_map_lookup(&globals.cache, idx);
131
-   if (o != NULL && o->type != type)
132
-       o = NULL;
133
-   pthread_mutex_unlock(&globals.lock);
134
-   return o;
135
-}
136
-
137
 static struct object * alloc_object(struct client *c, int type)
138
 {
139
    struct object *o;
140
    int i;
141
 
142
    pthread_mutex_lock(&globals.lock);
143
-   if (spa_list_is_empty(&globals.free_objects[type])) {
144
+   if (spa_list_is_empty(&globals.free_objects)) {
145
        o = calloc(OBJECT_CHUNK, sizeof(struct object));
146
        if (o == NULL) {
147
            pthread_mutex_unlock(&globals.lock);
148
            return NULL;
149
        }
150
-       for (i = 0; i < OBJECT_CHUNK; i++) {
151
-           o[i].idx = pw_map_insert_new(&globals.cache, &o[i]);
152
-           spa_list_append(&globals.free_objects[type], &o[i].link);
153
-       }
154
+       for (i = 0; i < OBJECT_CHUNK; i++)
155
+           spa_list_append(&globals.free_objects, &o[i].link);
156
    }
157
-   o = spa_list_first(&globals.free_objects[type], struct object, link);
158
+   o = spa_list_first(&globals.free_objects, struct object, link);
159
    spa_list_remove(&o->link);
160
    pthread_mutex_unlock(&globals.lock);
161
 
162
    o->client = c;
163
+   o->removed = false;
164
    o->type = type;
165
    pw_log_debug("%p: object:%p type:%d", c, o, type);
166
 
167
    return o;
168
 }
169
 
170
+static void recycle_objects(struct client *c, uint32_t remain)
171
+{
172
+   struct object *o, *t;
173
+   pthread_mutex_lock(&globals.lock);
174
+   spa_list_for_each_safe(o, t, &c->context.objects, link) {
175
+       if (o->removed) {
176
+           pw_log_info("%p: recycle object:%p type:%d id:%u/%u",
177
+                   c, o, o->type, o->id, o->serial);
178
+           spa_list_remove(&o->link);
179
+           memset(o, 0, sizeof(struct object));
180
+           spa_list_append(&globals.free_objects, &o->link);
181
+           if (--c->context.free_count == remain)
182
+               break;
183
+       }
184
+   }
185
+   pthread_mutex_unlock(&globals.lock);
186
+}
187
+
188
+/* JACK clients expect the objects to hang around after
189
+ * they are unregistered and freed. We mark the object removed and
190
+ * move it to the end of the queue. */
191
 static void free_object(struct client *c, struct object *o)
192
 {
193
+   pw_log_debug("%p: object:%p type:%d", c, o, o->type);
194
    pthread_mutex_lock(&c->context.lock);
195
    spa_list_remove(&o->link);
196
+   o->removed = true;
197
+   o->id = SPA_ID_INVALID;
198
+   spa_list_append(&c->context.objects, &o->link);
199
+   if (++c->context.free_count > RECYCLE_THRESHOLD)
200
+       recycle_objects(c, RECYCLE_THRESHOLD / 2);
201
pipewire-0.3.43.tar.gz/pipewire-jack/src/pw-jack.in -> pipewire-0.3.44.tar.gz/pipewire-jack/src/pw-jack.in Changed
34
 
1
@@ -24,7 +24,7 @@
2
 # DEALINGS IN THE SOFTWARE.
3
 #
4
 
5
-SAMPLERATE=48000
6
+DEFAULT_SAMPLERATE=48000
7
 
8
 while getopts 'hr:vs:p:' param ; do
9
    case $param in
10
@@ -55,7 +55,7 @@
11
            echo "  -h                  show brief help"
12
            echo "  -r <remote>         remote daemon name"
13
            echo "  -v                  verbose debug info"
14
-           echo "  -s                  samplerate (default \"$SAMPLERATE\")"
15
+           echo "  -s                  samplerate (default \"$DEFAULT_SAMPLERATE\")"
16
            echo "  -p                  period in samples"
17
            exit 0
18
            ;;
19
@@ -65,8 +65,12 @@
20
 shift $(( OPTIND - 1 ))
21
 
22
 if [ -n "$PERIOD" ]; then
23
-   PIPEWIRE_LATENCY="$PERIOD/$SAMPLERATE"
24
-   export PIPEWIRE_LATENCY
25
+   if [ -n "$SAMPLERATE" ]; then
26
+       PIPEWIRE_QUANTUM="$PERIOD/$SAMPLERATE"
27
+   else
28
+       PIPEWIRE_QUANTUM="$PERIOD/$DEFAULT_SAMPLERATE"
29
+   fi
30
+   export PIPEWIRE_QUANTUM
31
 fi
32
 LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
33
 export LD_LIBRARY_PATH
34
pipewire-0.3.43.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c -> pipewire-0.3.44.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c Changed
17
 
1
@@ -1119,12 +1119,13 @@
2
 
3
    file->v4l2_format = fmt;
4
 
5
-   buffers = file->reqbufs;
6
+   buffers = SPA_CLAMP(file->reqbufs, 2u, MAX_BUFFERS);
7
    size = 0;
8
 
9
    params[n_params++] = spa_pod_builder_add_object(&b,
10
            SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
11
-           SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(buffers),
12
+           SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(buffers,
13
+                           2, MAX_BUFFERS),
14
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
15
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(size, 0, INT_MAX),
16
            SPA_PARAM_BUFFERS_stride,  SPA_POD_CHOICE_RANGE_Int(0, 0, INT_MAX),
17
pipewire-0.3.43.tar.gz/spa/include/spa/buffer/meta.h -> pipewire-0.3.44.tar.gz/spa/include/spa/buffer/meta.h Changed
10
 
1
@@ -81,7 +81,7 @@
2
 #define SPA_META_HEADER_FLAG_DELTA_UNIT    (1 << 5)    /**< cannot be decoded independently */
3
    uint32_t flags;             /**< flags */
4
    uint32_t offset;            /**< offset in current cycle */
5
-   int64_t pts;                /**< presentation timestamp */
6
+   int64_t pts;                /**< presentation timestamp in nanoseconds */
7
    int64_t dts_offset;         /**< decoding timestamp as a difference with pts */
8
    uint64_t seq;               /**< sequence number, increments with a
9
                          *  media specific frequency */
10
pipewire-0.3.43.tar.gz/spa/include/spa/debug/types.h -> pipewire-0.3.44.tar.gz/spa/include/spa/debug/types.h Changed
28
 
1
@@ -96,6 +96,26 @@
2
    return SPA_ID_INVALID;
3
 }
4
 
5
+static inline const struct spa_type_info *spa_debug_type_find_short(const struct spa_type_info *info, const char *name)
6
+{
7
+   while (info && info->name) {
8
+       if (strcmp(spa_debug_type_short_name(info->name), name) == 0)
9
+           return info;
10
+       if (strcmp(info->name, name) == 0)
11
+           return info;
12
+       if (info->type != 0 && info->type == (uint32_t)atoi(name))
13
+           return info;
14
+       info++;
15
+   }
16
+   return NULL;
17
+}
18
+
19
+static inline uint32_t spa_debug_type_find_type_short(const struct spa_type_info *info, const char *name)
20
+{
21
+   if ((info = spa_debug_type_find_short(info, name)) == NULL)
22
+       return SPA_ID_INVALID;
23
+   return info->type;
24
+}
25
 /**
26
  * \}
27
  */
28
pipewire-0.3.43.tar.gz/spa/include/spa/support/thread.h -> pipewire-0.3.44.tar.gz/spa/include/spa/support/thread.h Changed
12
 
1
@@ -68,7 +68,9 @@
2
 
3
    /** get realtime priority range for threads created with \a props */
4
    int (*get_rt_range) (void *data, const struct spa_dict *props, int *min, int *max);
5
-   /** acquire realtime priority */
6
+   /** acquire realtime priority, a priority of -1 refers to the priority
7
+    * configured in the realtime module
8
+    */
9
    int (*acquire_rt) (void *data, struct spa_thread *thread, int priority);
10
    /** drop realtime priority */
11
    int (*drop_rt) (void *data, struct spa_thread *thread);
12
pipewire-0.3.43.tar.gz/spa/include/spa/utils/dict.h -> pipewire-0.3.44.tar.gz/spa/include/spa/utils/dict.h Changed
23
 
1
@@ -74,8 +74,9 @@
2
 
3
 static inline void spa_dict_qsort(struct spa_dict *dict)
4
 {
5
-   qsort((void*)dict->items, dict->n_items, sizeof(struct spa_dict_item),
6
-           spa_dict_item_compare);
7
+   if (dict->n_items > 0)
8
+       qsort((void*)dict->items, dict->n_items, sizeof(struct spa_dict_item),
9
+               spa_dict_item_compare);
10
    SPA_FLAG_SET(dict->flags, SPA_DICT_FLAG_SORTED);
11
 }
12
 
13
@@ -84,7 +85,8 @@
14
 {
15
    const struct spa_dict_item *item;
16
 
17
-   if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED)) {
18
+   if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED) &&
19
+           dict->n_items > 0) {
20
        struct spa_dict_item k = SPA_DICT_ITEM_INIT(key, NULL);
21
        item = (const struct spa_dict_item *)bsearch(&k,
22
                (const void *) dict->items, dict->n_items,
23
pipewire-0.3.44.tar.gz/spa/include/spa/utils/json-pod.h Added
179
 
1
@@ -0,0 +1,177 @@
2
+/* Simple Plugin API
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef SPA_UTILS_JSON_POD_H
27
+#define SPA_UTILS_JSON_POD_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+#include <spa/utils/string.h>
34
+#include <spa/utils/json.h>
35
+#include <spa/pod/pod.h>
36
+#include <spa/pod/builder.h>
37
+#include <spa/debug/types.h>
38
+
39
+/** \defgroup spa_json_pod JSON to POD
40
+ * JSON to POD conversion
41
+ */
42
+
43
+/**
44
+ * \addtogroup spa_json_pod
45
+ * \{
46
+ */
47
+
48
+static inline int spa_json_to_pod_part(struct spa_pod_builder *b, uint32_t flags, uint32_t id,
49
+       const struct spa_type_info *info, struct spa_json *iter, const char *value, int len)
50
+{
51
+   const struct spa_type_info *ti;
52
+   char key[256];
53
+   struct spa_pod_frame f[1];
54
+   struct spa_json it[1];
55
+   int l, res;
56
+   const char *v;
57
+   uint32_t type;
58
+
59
+   if (spa_json_is_object(value, len) && info != NULL) {
60
+       if ((ti = spa_debug_type_find(NULL, info->parent)) == NULL)
61
+           return -EINVAL;
62
+
63
+       spa_pod_builder_push_object(b, &f[0], info->parent, id);
64
+
65
+       spa_json_enter(iter, &it[0]);
66
+       while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
67
+           const struct spa_type_info *pi;
68
+           if ((l = spa_json_next(&it[0], &v)) <= 0)
69
+               break;
70
+           if ((pi = spa_debug_type_find_short(ti->values, key)) != NULL)
71
+               type = pi->type;
72
+           else if (!spa_atou32(key, &type, 0))
73
+               continue;
74
+           spa_pod_builder_prop(b, type, 0);
75
+           if ((res = spa_json_to_pod_part(b, flags, id, pi, &it[0], v, l)) < 0)
76
+               return res;
77
+       }
78
+       spa_pod_builder_pop(b, &f[0]);
79
+   }
80
+   else if (spa_json_is_array(value, len)) {
81
+       if (info == NULL || info->parent == SPA_TYPE_Struct) {
82
+           spa_pod_builder_push_struct(b, &f[0]);
83
+       } else {
84
+           spa_pod_builder_push_array(b, &f[0]);
85
+           info = info->values;
86
+       }
87
+       spa_json_enter(iter, &it[0]);
88
+       while ((l = spa_json_next(&it[0], &v)) > 0)
89
+           if ((res = spa_json_to_pod_part(b, flags, id, info, &it[0], v, l)) < 0)
90
+               return res;
91
+       spa_pod_builder_pop(b, &f[0]);
92
+   }
93
+   else if (spa_json_is_float(value, len)) {
94
+       float val = 0.0f;
95
+       spa_json_parse_float(value, len, &val);
96
+       switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) {
97
+       case SPA_TYPE_Bool:
98
+           spa_pod_builder_bool(b, val >= 0.5f);
99
+           break;
100
+       case SPA_TYPE_Id:
101
+           spa_pod_builder_id(b, val);
102
+           break;
103
+       case SPA_TYPE_Int:
104
+           spa_pod_builder_int(b, val);
105
+           break;
106
+       case SPA_TYPE_Long:
107
+           spa_pod_builder_long(b, val);
108
+           break;
109
+       case SPA_TYPE_Struct:
110
+           if (spa_json_is_int(value, len))
111
+               spa_pod_builder_int(b, val);
112
+           else
113
+               spa_pod_builder_float(b, val);
114
+           break;
115
+       case SPA_TYPE_Float:
116
+           spa_pod_builder_float(b, val);
117
+           break;
118
+       case SPA_TYPE_Double:
119
+           spa_pod_builder_double(b, val);
120
+           break;
121
+       default:
122
+           spa_pod_builder_none(b);
123
+           break;
124
+       }
125
+   }
126
+   else if (spa_json_is_bool(value, len)) {
127
+       bool val = false;
128
+       spa_json_parse_bool(value, len, &val);
129
+       spa_pod_builder_bool(b, val);
130
+   }
131
+   else if (spa_json_is_null(value, len)) {
132
+       spa_pod_builder_none(b);
133
+   }
134
+   else {
135
+       char *val = (char*)alloca(len+1);
136
+       spa_json_parse_stringn(value, len, val, len+1);
137
+       switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) {
138
+       case SPA_TYPE_Id:
139
+           if ((ti = spa_debug_type_find_short(info->values, val)) != NULL)
140
+               type = ti->type;
141
+           else if (!spa_atou32(val, &type, 0))
142
+               return -EINVAL;
143
+           spa_pod_builder_id(b, type);
144
+           break;
145
+       case SPA_TYPE_Struct:
146
+       case SPA_TYPE_String:
147
+           spa_pod_builder_string(b, val);
148
+           break;
149
+       default:
150
+           spa_pod_builder_none(b);
151
+           break;
152
+       }
153
+   }
154
+   return 0;
155
+}
156
+
157
+static inline int spa_json_to_pod(struct spa_pod_builder *b, uint32_t flags,
158
+       const struct spa_type_info *info, const char *value, int len)
159
+{
160
+   struct spa_json iter;
161
+   const char *val;
162
+
163
+   spa_json_init(&iter, value, len);
164
+   if ((len = spa_json_next(&iter, &val)) <= 0)
165
+       return -EINVAL;
166
+
167
+   return spa_json_to_pod_part(b, flags, info->type, info, &iter, val, len);
168
+}
169
+
170
+/**
171
+ * \}
172
+ */
173
+
174
+#ifdef __cplusplus
175
+} /* extern "C" */
176
+#endif
177
+
178
+#endif /* SPA_UTILS_JSON_POD_H */
179
pipewire-0.3.43.tar.gz/spa/meson.build -> pipewire-0.3.44.tar.gz/spa/meson.build Changed
9
 
1
@@ -9,6 +9,7 @@
2
   include_directories : [
3
     include_directories('include'),
4
   ],
5
+  dependencies : [atomic_dep],
6
   version : spaversion,
7
   variables : {
8
     'plugindir' : meson.current_build_dir() / 'plugins',
9
pipewire-0.3.43.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules Changed
11
 
1
@@ -113,8 +113,7 @@
2
 ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{ACP_PROFILE_SET}="sb-omni-surround-5.1.conf"
3
 ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
4
 ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="402e", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
5
-ATTRS{idVendor}=="1397", ATTRS{idProduct}=="0507", ENV{ACP_PROFILE_SET}="behringer-umc22.conf"
6
-ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf"
7
+#ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf"
8
 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0269", ENV{ACP_PROFILE_SET}="hp-tbt-dock-120w-g2.conf"
9
 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0567", ENV{ACP_PROFILE_SET}="hp-tbt-dock-audio-module.conf"
10
 
11
pipewire-0.3.43.tar.gz/spa/plugins/alsa/acp/compat.h -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/acp/compat.h Changed
57
 
1
@@ -34,6 +34,9 @@
2
 #include <inttypes.h>
3
 #include <stdlib.h>
4
 #include <unistd.h>
5
+#include <math.h>
6
+
7
+#include <spa/utils/string.h>
8
 
9
 typedef struct pa_core pa_core;
10
 
11
@@ -545,25 +548,35 @@
12
 
13
 static inline int pa_atod(const char *s, double *ret_d)
14
 {
15
-   char *x;
16
-   *ret_d = strtod(s, &x);
17
-   return 0;
18
+   if (spa_atod(s, ret_d) && !isnan(*ret_d))
19
+       return 0;
20
+   errno = EINVAL;
21
+   return -1;
22
 }
23
 static inline int pa_atoi(const char *s, int32_t *ret_i)
24
 {
25
-   *ret_i = (int32_t) atoi(s);
26
-   return 0;
27
+   if (spa_atoi32(s, ret_i, 0))
28
+       return 0;
29
+   errno = EINVAL;
30
+   return -1;
31
 }
32
 static inline int pa_atou(const char *s, uint32_t *ret_u)
33
 {
34
-   *ret_u = (uint32_t) atoi(s);
35
-   return 0;
36
+   if (spa_atou32(s, ret_u, 0))
37
+       return 0;
38
+   errno = EINVAL;
39
+   return -1;
40
 }
41
 static inline int pa_atol(const char *s, long *ret_l)
42
 {
43
-   char *x;
44
-   *ret_l = strtol(s, &x, 0);
45
-   return 0;
46
+   int64_t res;
47
+   if (spa_atoi64(s, &res, 0)) {
48
+       *ret_l = res;
49
+       if (*ret_l == res)
50
+           return 0;
51
+   }
52
+   errno = EINVAL;
53
+   return -1;
54
 }
55
 
56
 static inline int pa_parse_boolean(const char *v)
57
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c Changed
100
 
1
@@ -42,14 +42,10 @@
2
 #define CHECK_PORT(this,d,p)    ((d) == SPA_DIRECTION_INPUT && (p) == 0)
3
 
4
 static const char default_device[] = "hw:0";
5
-static const uint32_t default_min_latency = MIN_LATENCY;
6
-static const uint32_t default_max_latency = MAX_LATENCY;
7
 
8
 static void reset_props(struct props *props)
9
 {
10
    strncpy(props->device, default_device, 64);
11
-   props->min_latency = default_min_latency;
12
-   props->max_latency = default_max_latency;
13
    props->use_chmap = DEFAULT_USE_CHMAP;
14
 }
15
 
16
@@ -68,7 +64,7 @@
17
        items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Sink");
18
        items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true");
19
        if (this->have_format) {
20
-           snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 4, this->rate);
21
+           snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate);
22
            items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency);
23
        }
24
        this->info.props = &SPA_DICT_INIT(items, n_items);
25
@@ -162,25 +158,11 @@
26
        case 3:
27
            param = spa_pod_builder_add_object(&b,
28
                SPA_TYPE_OBJECT_PropInfo, id,
29
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_minLatency),
30
-               SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"),
31
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX));
32
-           break;
33
-       case 4:
34
-           param = spa_pod_builder_add_object(&b,
35
-               SPA_TYPE_OBJECT_PropInfo, id,
36
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_maxLatency),
37
-               SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"),
38
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX));
39
-           break;
40
-       case 5:
41
-           param = spa_pod_builder_add_object(&b,
42
-               SPA_TYPE_OBJECT_PropInfo, id,
43
                SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_latencyOffsetNsec),
44
                SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"),
45
                SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX));
46
            break;
47
-       case 6:
48
+       case 4:
49
            if (!this->is_iec958 && !this->is_hdmi)
50
                goto next;
51
            param = spa_pod_builder_add_object(&b,
52
@@ -193,7 +175,7 @@
53
                                 SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array));
54
            break;
55
        default:
56
-           param = spa_alsa_enum_propinfo(this, result.index - 7, &b);
57
+           param = spa_alsa_enum_propinfo(this, result.index - 5, &b);
58
            if (param == NULL)
59
                return 0;
60
        }
61
@@ -213,8 +195,6 @@
62
                SPA_PROP_device,       SPA_POD_Stringn(p->device, sizeof(p->device)),
63
                SPA_PROP_deviceName,   SPA_POD_Stringn(p->device_name, sizeof(p->device_name)),
64
                SPA_PROP_cardName,     SPA_POD_Stringn(p->card_name, sizeof(p->card_name)),
65
-               SPA_PROP_minLatency,   SPA_POD_Int(p->min_latency),
66
-               SPA_PROP_maxLatency,   SPA_POD_Int(p->max_latency),
67
                SPA_PROP_latencyOffsetNsec,   SPA_POD_Long(this->process_latency.ns),
68
                0);
69
 
70
@@ -343,8 +323,6 @@
71
        spa_pod_parse_object(param,
72
            SPA_TYPE_OBJECT_Props, NULL,
73
            SPA_PROP_device,       SPA_POD_OPT_Stringn(p->device, sizeof(p->device)),
74
-           SPA_PROP_minLatency,   SPA_POD_OPT_Int(&p->min_latency),
75
-           SPA_PROP_maxLatency,   SPA_POD_OPT_Int(&p->max_latency),
76
            SPA_PROP_latencyOffsetNsec,   SPA_POD_OPT_Long(&info.ns),
77
            SPA_PROP_iec958Codecs, SPA_POD_OPT_Pod(&iec958_codecs),
78
            SPA_PROP_params,       SPA_POD_OPT_Pod(&params));
79
@@ -363,8 +341,8 @@
80
            this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
81
            this->port_params[PORT_EnumFormat].user++;
82
        }
83
-       handle_process_latency(this, &info);
84
        spa_alsa_parse_prop_params(this, params);
85
+       handle_process_latency(this, &info);
86
 
87
        emit_node_info(this, false);
88
        emit_port_info(this, false);
89
@@ -551,8 +529,8 @@
90
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
91
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(this->blocks),
92
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
93
-                           this->props.max_latency * this->frame_size,
94
-                           this->props.min_latency * this->frame_size,
95
+                           this->quantum_limit * this->frame_size,
96
+                           16 * this->frame_size,
97
                            INT32_MAX),
98
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->frame_size));
99
        break;
100
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm-source.c Changed
88
 
1
@@ -44,14 +44,10 @@
2
 #define CHECK_PORT(this,d,p)    ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
3
 
4
 static const char default_device[] = "hw:0";
5
-static const uint32_t default_min_latency = MIN_LATENCY;
6
-static const uint32_t default_max_latency = MAX_LATENCY;
7
 
8
 static void reset_props(struct props *props)
9
 {
10
    strncpy(props->device, default_device, 64);
11
-   props->min_latency = default_min_latency;
12
-   props->max_latency = default_max_latency;
13
    props->use_chmap = DEFAULT_USE_CHMAP;
14
 }
15
 
16
@@ -69,7 +65,7 @@
17
        items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Source");
18
        items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true");
19
        if (this->have_format) {
20
-           snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 4, this->rate);
21
+           snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate);
22
            items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency);
23
        }
24
        this->info.props = &SPA_DICT_INIT(items, n_items);
25
@@ -162,26 +158,12 @@
26
        case 3:
27
            param = spa_pod_builder_add_object(&b,
28
                SPA_TYPE_OBJECT_PropInfo, id,
29
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_minLatency),
30
-               SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"),
31
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX));
32
-           break;
33
-       case 4:
34
-           param = spa_pod_builder_add_object(&b,
35
-               SPA_TYPE_OBJECT_PropInfo, id,
36
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_maxLatency),
37
-               SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"),
38
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX));
39
-           break;
40
-       case 5:
41
-           param = spa_pod_builder_add_object(&b,
42
-               SPA_TYPE_OBJECT_PropInfo, id,
43
                SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_latencyOffsetNsec),
44
                SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"),
45
                SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX));
46
            break;
47
        default:
48
-           param = spa_alsa_enum_propinfo(this, result.index - 6, &b);
49
+           param = spa_alsa_enum_propinfo(this, result.index - 4, &b);
50
            if (param == NULL)
51
                return 0;
52
        }
53
@@ -199,8 +181,6 @@
54
                SPA_PROP_device,       SPA_POD_Stringn(p->device, sizeof(p->device)),
55
                SPA_PROP_deviceName,   SPA_POD_Stringn(p->device_name, sizeof(p->device_name)),
56
                SPA_PROP_cardName,     SPA_POD_Stringn(p->card_name, sizeof(p->card_name)),
57
-               SPA_PROP_minLatency,   SPA_POD_Int(p->min_latency),
58
-               SPA_PROP_maxLatency,   SPA_POD_Int(p->max_latency),
59
                SPA_PROP_latencyOffsetNsec,   SPA_POD_Long(this->process_latency.ns),
60
                0);
61
            spa_alsa_add_prop_params(this, &b);
62
@@ -323,13 +303,11 @@
63
        spa_pod_parse_object(param,
64
            SPA_TYPE_OBJECT_Props, NULL,
65
            SPA_PROP_device,       SPA_POD_OPT_Stringn(p->device, sizeof(p->device)),
66
-           SPA_PROP_minLatency,   SPA_POD_OPT_Int(&p->min_latency),
67
-           SPA_PROP_maxLatency,   SPA_POD_OPT_Int(&p->max_latency),
68
            SPA_PROP_latencyOffsetNsec,   SPA_POD_OPT_Long(&info.ns),
69
            SPA_PROP_params,       SPA_POD_OPT_Pod(&params));
70
 
71
-       handle_process_latency(this, &info);
72
        spa_alsa_parse_prop_params(this, params);
73
+       handle_process_latency(this, &info);
74
 
75
        emit_node_info(this, false);
76
        emit_port_info(this, false);
77
@@ -500,8 +478,8 @@
78
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
79
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(this->blocks),
80
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
81
-                           this->props.max_latency * this->frame_size,
82
-                           this->props.min_latency * this->frame_size,
83
+                           this->quantum_limit * this->frame_size,
84
+                           16 * this->frame_size,
85
                            INT32_MAX),
86
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->frame_size));
87
        break;
88
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
154
 
1
@@ -125,6 +125,10 @@
2
        state->props.use_chmap = spa_atob(s);
3
    } else if (spa_streq(k, "api.alsa.multi-rate")) {
4
        state->multi_rate = spa_atob(s);
5
+   } else if (spa_streq(k, "latency.internal.rate")) {
6
+       state->process_latency.rate = atoi(s);
7
+   } else if (spa_streq(k, "latency.internal.ns")) {
8
+       state->process_latency.ns = atoi(s);
9
    } else if (spa_streq(k, "clock.name")) {
10
        spa_scnprintf(state->clock_name,
11
                sizeof(state->clock_name), "%s", s);
12
@@ -295,6 +299,22 @@
13
    case 13:
14
        param = spa_pod_builder_add_object(b,
15
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
16
+           SPA_PROP_INFO_name, SPA_POD_String("latency.internal.rate"),
17
+           SPA_PROP_INFO_description, SPA_POD_String("Internal latency in samples"),
18
+           SPA_PROP_INFO_type, SPA_POD_Int(state->process_latency.rate),
19
+           SPA_PROP_INFO_params, SPA_POD_Bool(true));
20
+       break;
21
+   case 14:
22
+       param = spa_pod_builder_add_object(b,
23
+           SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
24
+           SPA_PROP_INFO_name, SPA_POD_String("latency.internal.ns"),
25
+           SPA_PROP_INFO_description, SPA_POD_String("Internal latency in nanoseconds"),
26
+           SPA_PROP_INFO_type, SPA_POD_Long(state->process_latency.ns),
27
+           SPA_PROP_INFO_params, SPA_POD_Bool(true));
28
+       break;
29
+   case 15:
30
+       param = spa_pod_builder_add_object(b,
31
+           SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
32
            SPA_PROP_INFO_name, SPA_POD_String("clock.name"),
33
            SPA_PROP_INFO_description, SPA_POD_String("The name of the clock"),
34
            SPA_PROP_INFO_type, SPA_POD_String(state->clock_name),
35
@@ -358,6 +378,12 @@
36
    spa_pod_builder_string(b, "api.alsa.multi-rate");
37
    spa_pod_builder_bool(b, state->multi_rate);
38
 
39
+   spa_pod_builder_string(b, "latency.internal.rate");
40
+   spa_pod_builder_int(b, state->process_latency.rate);
41
+
42
+   spa_pod_builder_string(b, "latency.internal.ns");
43
+   spa_pod_builder_long(b, state->process_latency.ns);
44
+
45
    spa_pod_builder_string(b, "clock.name");
46
    spa_pod_builder_string(b, state->clock_name);
47
 
48
@@ -391,8 +417,11 @@
49
        if (spa_pod_is_string(pod)) {
50
            spa_pod_copy_string(pod, sizeof(value), value);
51
        } else if (spa_pod_is_int(pod)) {
52
-           snprintf(value, sizeof(value), "%u",
53
+           snprintf(value, sizeof(value), "%d",
54
                    SPA_POD_VALUE(struct spa_pod_int, pod));
55
+       } else if (spa_pod_is_long(pod)) {
56
+           snprintf(value, sizeof(value), "%"PRIi64,
57
+                   SPA_POD_VALUE(struct spa_pod_long, pod));
58
        } else if (spa_pod_is_bool(pod)) {
59
            snprintf(value, sizeof(value), "%s",
60
                    SPA_POD_VALUE(struct spa_pod_bool, pod) ?
61
@@ -427,10 +456,8 @@
62
            state->card_index = atoi(s);
63
        } else if (spa_streq(k, SPA_KEY_API_ALSA_OPEN_UCM)) {
64
            state->open_ucm = spa_atob(s);
65
-       } else if (spa_streq(k, "latency.internal.rate")) {
66
-           state->process_latency.rate = atoi(s);
67
-       } else if (spa_streq(k, "latency.internal.ns")) {
68
-           state->process_latency.ns = atoi(s);
69
+       } else if (spa_streq(k, "clock.quantum-limit")) {
70
+           spa_atou32(s, &state->quantum_limit, 0);
71
        } else {
72
            alsa_set_param(state, k, s);
73
        }
74
@@ -732,31 +759,32 @@
75
    CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
76
    CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max");
77
 
78
-   rate = state->default_rate;
79
    if (!state->multi_rate && state->card->format_ref > 0)
80
        rate = state->card->rate;
81
+   else
82
+       rate = state->default_rate;
83
 
84
-   if (rate != 0 && !all) {
85
-       if (min < rate)
86
-           min = rate;
87
-       if (max > rate)
88
-           max = rate;
89
-   }
90
+   if (rate < min || rate > max)
91
+       rate = 0;
92
+
93
+   if (rate != 0 && !all)
94
+       min = max = rate;
95
+
96
+   if (rate == 0)
97
+       rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE;
98
+
99
+   rate = SPA_CLAMP(rate, min, max);
100
 
101
    spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0);
102
 
103
    spa_pod_builder_push_choice(b, &f[0], SPA_CHOICE_None, 0);
104
    choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f[0]);
105
 
106
-   if (rate == 0)
107
-       rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE;
108
-
109
    if (state->n_allowed_rates > 0) {
110
        uint32_t i, v, last = 0, count = 0;
111
 
112
-       v = SPA_CLAMP(rate, min, max);
113
-       if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, v)) {
114
-           spa_pod_builder_int(b, v * scale);
115
+       if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, rate)) {
116
+           spa_pod_builder_int(b, rate * scale);
117
            count++;
118
        }
119
        for (i = 0; i < state->n_allowed_rates; i++) {
120
@@ -773,7 +801,7 @@
121
        if (count > 1)
122
            choice->body.type = SPA_CHOICE_Enum;
123
    } else {
124
-       spa_pod_builder_int(b, SPA_CLAMP(rate, min, max) * scale);
125
+       spa_pod_builder_int(b, rate * scale);
126
 
127
        if (min != max) {
128
            spa_pod_builder_int(b, min * scale);
129
@@ -1419,9 +1447,13 @@
130
    if (is_batch) {
131
        if (period_size == 0)
132
            period_size = state->position ? state->position->clock.duration : DEFAULT_PERIOD;
133
+       if (period_size == 0)
134
+           period_size = DEFAULT_PERIOD;
135
        /* batch devices get their hw pointers updated every period. Make
136
-        * the period smaller and add one period of headroom */
137
-       period_size /= 2;
138
+        * the period smaller and add one period of headroom. Limit the
139
+        * period size to our default so that we don't create too much
140
+        * headroom. */
141
+       period_size = SPA_MIN(period_size, DEFAULT_PERIOD) / 2;
142
        spa_log_info(state->log, "%s: batch mode, period_size:%ld",
143
            state->props.device, period_size);
144
    } else {
145
@@ -2306,7 +2338,7 @@
146
    else {
147
        spa_log_warn(state->log, "%s: no position set, using defaults",
148
                state->props.device);
149
-       state->duration = state->props.min_latency;
150
+       state->duration = 1024;
151
        state->rate_denom = state->rate;
152
    }
153
 
154
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
28
 
1
@@ -52,9 +52,6 @@
2
 
3
 #include "dll.h"
4
 
5
-#define MIN_LATENCY    16
6
-#define MAX_LATENCY    8192
7
-
8
 #define MAX_RATES  16
9
 
10
 #define DEFAULT_PERIOD     1024u
11
@@ -66,8 +63,6 @@
12
    char device[64];
13
    char device_name[128];
14
    char card_name[128];
15
-   uint32_t min_latency;
16
-   uint32_t max_latency;
17
    bool use_chmap;
18
 };
19
 
20
@@ -148,6 +143,7 @@
21
    unsigned int disable_mmap;
22
    unsigned int disable_batch;
23
    char clock_name[64];
24
+   uint32_t quantum_limit;
25
 
26
    snd_pcm_uframes_t buffer_frames;
27
    snd_pcm_uframes_t period_frames;
28
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-udev.c Changed
201
 
1
@@ -47,6 +47,9 @@
2
 
3
 #define MAX_DEVICES    64
4
 
5
+#define RETRY_COUNT    1
6
+#define RETRY_MSEC 2000
7
+
8
 #define ACTION_ADD 0
9
 #define ACTION_REMOVE  1
10
 #define ACTION_DISABLE 2
11
@@ -54,6 +57,7 @@
12
 struct device {
13
    uint32_t id;
14
    struct udev_device *dev;
15
+   uint8_t retry;
16
    unsigned int accessible:1;
17
    unsigned int ignored:1;
18
    unsigned int emitted:1;
19
@@ -65,6 +69,7 @@
20
 
21
    struct spa_log *log;
22
    struct spa_loop *main_loop;
23
+   struct spa_system *main_system;
24
 
25
    struct spa_hook_list hooks;
26
 
27
@@ -79,6 +84,7 @@
28
 
29
    struct spa_source source;
30
    struct spa_source notify;
31
+   struct spa_source retry_timer;
32
    unsigned int use_acp:1;
33
 };
34
 
35
@@ -243,6 +249,39 @@
36
    *d = 0;
37
 }
38
 
39
+static int check_device_busy(struct impl *this, struct device *device, snd_ctl_t *ctl_hndl)
40
+{
41
+   int dev;
42
+
43
+   /* Check if some pcm devices of the card cannot be opened because they are busy */
44
+
45
+   for (dev = -1; snd_ctl_pcm_next_device(ctl_hndl, &dev) >= 0 && dev >= 0;) {
46
+       char devpath[64];
47
+       int i;
48
+
49
+       snprintf(devpath, sizeof(devpath), "hw:%u,%u", device->id, dev);
50
+
51
+       for (i = 0; i < 2; ++i) {
52
+           snd_pcm_t *handle;
53
+           int res;
54
+
55
+           res = snd_pcm_open(&handle, devpath,
56
+                   (i == 0) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE,
57
+                   SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE |
58
+                   SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT);
59
+           if (res == -EBUSY) {
60
+               spa_log_debug(this->log, "pcm device %s busy", devpath);
61
+               return -EBUSY;
62
+           } else if (res >= 0) {
63
+               snd_pcm_close(handle);
64
+           }
65
+       }
66
+       spa_log_debug(this->log, "pcm device %s free", devpath);
67
+   }
68
+
69
+   return 0;
70
+}
71
+
72
 static int emit_object_info(struct impl *this, struct device *device)
73
 {
74
    struct spa_device_object_info info;
75
@@ -267,20 +306,24 @@
76
    pcm = -1;
77
    res = snd_ctl_pcm_next_device(ctl_hndl, &pcm);
78
 
79
-   spa_log_debug(this->log, "close card %s", path);
80
-   snd_ctl_close(ctl_hndl);
81
-
82
    if (res < 0) {
83
        spa_log_error(this->log, "error iterating devices: %s", snd_strerror(res));
84
        device->ignored = true;
85
-       return res;
86
-   }
87
-   if (pcm < 0) {
88
+   } else if (pcm < 0) {
89
        spa_log_debug(this->log, "no pcm devices for %s", path);
90
        device->ignored = true;
91
-       return 0;
92
+       res = 0;
93
+   } else if (device->retry > 0) {
94
+       /* Check if we can open all PCM devices (retry later if not) */
95
+       res = check_device_busy(this, device, ctl_hndl);
96
    }
97
 
98
+   spa_log_debug(this->log, "close card %s", path);
99
+   snd_ctl_close(ctl_hndl);
100
+
101
+   if (res < 0 || device->ignored)
102
+       return res;
103
+
104
    info = SPA_DEVICE_OBJECT_INFO_INIT();
105
 
106
    info.type = SPA_TYPE_INTERFACE_Device;
107
@@ -393,6 +436,82 @@
108
    return 1;
109
 }
110
 
111
+static void start_retry(struct impl *this);
112
+
113
+static void stop_retry(struct impl *this);
114
+
115
+static void retry_timer_event(struct spa_source *source)
116
+{
117
+   struct impl *this = source->data;
118
+   bool have_retry = false;
119
+   size_t i;
120
+
121
+   stop_retry(this);
122
+
123
+   for (i = 0; i < this->n_devices; ++i) {
124
+       struct device *device = &this->devices[i];
125
+       if (device->ignored)
126
+           device->retry = 0;
127
+       if (device->retry > 0) {
128
+           --device->retry;
129
+
130
+           spa_log_debug(this->log, "retrying device %u", device->id);
131
+
132
+           if (emit_object_info(this, device) == -EBUSY) {
133
+               spa_log_debug(this->log, "device %u busy (remaining retries %u)",
134
+                       device->id, device->retry);
135
+           } else {
136
+               device->retry = 0;
137
+           }
138
+       }
139
+       if (device->retry > 0)
140
+           have_retry = true;
141
+   }
142
+
143
+   if (have_retry)
144
+       start_retry(this);
145
+}
146
+
147
+static void start_retry(struct impl *this)
148
+{
149
+   struct itimerspec ts;
150
+
151
+   spa_log_debug(this->log, "start retry");
152
+
153
+   if (this->retry_timer.data == NULL) {
154
+       this->retry_timer.data = this;
155
+       this->retry_timer.func = retry_timer_event;
156
+       this->retry_timer.mask = SPA_IO_IN;
157
+       this->retry_timer.rmask = 0;
158
+       spa_loop_add_source(this->main_loop, &this->retry_timer);
159
+   }
160
+
161
+   ts.it_value.tv_sec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) / SPA_NSEC_PER_SEC;
162
+   ts.it_value.tv_nsec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) % SPA_NSEC_PER_SEC;
163
+   ts.it_interval.tv_sec = 0;
164
+   ts.it_interval.tv_nsec = 0;
165
+   spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL);
166
+}
167
+
168
+static void stop_retry(struct impl *this)
169
+{
170
+   struct itimerspec ts;
171
+
172
+   if (this->retry_timer.data == NULL)
173
+       return;
174
+
175
+   spa_log_debug(this->log, "stop retry");
176
+
177
+   spa_loop_remove_source(this->main_loop, &this->retry_timer);
178
+   this->retry_timer.data = NULL;
179
+
180
+   ts.it_value.tv_sec = 0;
181
+   ts.it_value.tv_nsec = 0;
182
+   ts.it_interval.tv_sec = 0;
183
+   ts.it_interval.tv_nsec = 0;
184
+   spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL);
185
+}
186
+
187
 static bool check_access(struct impl *this, struct device *device)
188
 {
189
    char path[128];
190
@@ -425,7 +544,14 @@
191
            return;
192
        if (!check_access(this, device))
193
            return;
194
-       emit_object_info(this, device);
195
+       device->retry = RETRY_COUNT;
196
+       if (emit_object_info(this, device) == -EBUSY) {
197
+           spa_log_debug(this->log, "device %u busy (remaining retries %u)",
198
+                   device->id, device->retry);
199
+           start_retry(this);
200
+       } else {
201
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
27
 
1
@@ -118,19 +118,20 @@
2
                 struct spa_pod_builder *builder)
3
 {
4
    int res;
5
-   if (result->next < 0x10000) {
6
+   if (result->next < 0x100000) {
7
        if ((res = spa_node_enum_params_sync(this->convert,
8
                id, &result->next, filter, &result->param, builder)) == 1)
9
            return res;
10
-       result->next = 0x10000;
11
+       result->next = 0x100000;
12
    }
13
-   if (result->next >= 0x10000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) {
14
-       result->next &= 0xffff;
15
+   if (result->next < 0x200000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) {
16
+       result->next &= 0xfffff;
17
        if ((res = spa_node_enum_params_sync(this->follower,
18
                id, &result->next, filter, &result->param, builder)) == 1) {
19
-           result->next |= 0x10000;
20
+           result->next |= 0x100000;
21
            return res;
22
        }
23
+       result->next = 0x200000;
24
    }
25
    return 0;
26
 }
27
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
51
 
1
@@ -472,13 +472,22 @@
2
        }
3
        result->next = 0x1000;
4
    }
5
-   if (result->next >= 0x1000) {
6
+   if (result->next < 0x2000) {
7
        result->next &= 0xfff;
8
        if ((res = spa_node_enum_params_sync(this->channelmix,
9
                id, &result->next, filter, &result->param, builder)) == 1) {
10
            result->next |= 0x1000;
11
            return res;
12
        }
13
+       result->next = 0x2000;
14
+   }
15
+   if (result->next >= 0x2000) {
16
+       result->next &= 0xfff;
17
+       if ((res = spa_node_enum_params_sync(this->resample,
18
+               id, &result->next, filter, &result->param, builder)) == 1) {
19
+           result->next |= 0x2000;
20
+           return res;
21
+       }
22
    }
23
    return 0;
24
 }
25
@@ -881,6 +890,7 @@
26
        if (this->fmt[SPA_DIRECTION_INPUT] == this->merger)
27
            res = spa_node_set_param(this->merger, id, flags, param);
28
        res = spa_node_set_param(this->channelmix, id, flags, param);
29
+       res = spa_node_set_param(this->resample, id, flags, param);
30
        break;
31
    }
32
    default:
33
@@ -1112,11 +1122,12 @@
34
 
35
    switch (id) {
36
    case SPA_PARAM_Latency:
37
-       target = this->fmt[SPA_DIRECTION_REVERSE(direction)];
38
-       port_id = 0;
39
-       if ((res = spa_node_port_set_param(target,
40
-                   direction, port_id, id, flags, param)) < 0)
41
-           return res;
42
+       if (port_id == 0) {
43
+           target = this->fmt[SPA_DIRECTION_REVERSE(direction)];
44
+           if ((res = spa_node_port_set_param(target,
45
+                       direction, port_id, id, flags, param)) < 0)
46
+               return res;
47
+       }
48
        break;
49
    }
50
 
51
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix-ops.c Changed
87
 
1
@@ -149,17 +149,16 @@
2
    float matrix[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS] = {{ 0.0f }};
3
    uint64_t src_mask = mix->src_mask;
4
    uint64_t dst_mask = mix->dst_mask;
5
-   uint64_t unassigned;
6
+   uint64_t unassigned, keep;
7
    uint32_t i, j, ic, jc, matrix_encoding = MATRIX_NORMAL;
8
    float clev = SQRT1_2;
9
    float slev = SQRT1_2;
10
    float llev = 0.5f;
11
    float maxsum = 0.0f;
12
-   bool do_upmix = SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX);
13
 #define _MATRIX(s,d)   matrix[_CH(s)][_CH(d)]
14
 
15
-   spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64,
16
-           src_mask, dst_mask);
17
+   spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64
18
+           " options:%08x", src_mask, dst_mask, mix->options);
19
 
20
    /* move the MONO mask to FRONT so that the lower bits can be shifted
21
     * away. */
22
@@ -207,6 +206,14 @@
23
    }
24
 
25
    unassigned = src_mask & ~dst_mask;
26
+   keep = dst_mask & ~src_mask;
27
+
28
+   if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX))
29
+       keep = 0;
30
+
31
+   keep |= FRONT;
32
+   if (mix->lfe_cutoff > 0.0f)
33
+       keep |= _MASK(LFE);
34
 
35
    spa_log_debug(mix->log, "unassigned downmix %08" PRIx64, unassigned);
36
 
37
@@ -232,6 +239,7 @@
38
            _MATRIX(FC,FR) += SQRT1_2;
39
            if (src_mask & FRONT)
40
                _MATRIX(FC,FC) = clev * SQRT2;
41
+           keep &= ~FRONT;
42
        } else {
43
            spa_log_warn(mix->log, "can't assign STEREO");
44
        }
45
@@ -374,12 +382,10 @@
46
        }
47
    }
48
 
49
-   if (!do_upmix)
50
-       goto done;
51
-
52
-   unassigned = dst_mask & ~src_mask;
53
+   unassigned = dst_mask & ~src_mask & keep;
54
 
55
-   spa_log_debug(mix->log, "unassigned upmix %08" PRIx64, unassigned);
56
+   spa_log_debug(mix->log, "unassigned upmix %08"PRIx64" lfe:%f",
57
+           unassigned, mix->lfe_cutoff);
58
 
59
    if (unassigned & FRONT) {
60
        if ((src_mask & STEREO) == STEREO) {
61
@@ -390,7 +396,7 @@
62
            spa_log_warn(mix->log, "can't produce FC");
63
        }
64
    }
65
-   if (unassigned & _MASK(LFE) && mix->lfe_cutoff > 0.0f) {
66
+   if (unassigned & _MASK(LFE)) {
67
        if ((src_mask & STEREO) == STEREO) {
68
            spa_log_debug(mix->log, "produce LFE from STEREO");
69
            _MATRIX(LFE,FL) += llev;
70
@@ -445,7 +451,7 @@
71
            sum += fabs(matrix[i][j]);
72
        }
73
        maxsum = SPA_MAX(maxsum, sum);
74
-       if (i == _CH(LFE) && do_upmix && mix->lfe_cutoff > 0.0f) {
75
+       if (i == _CH(LFE) && mix->lfe_cutoff > 0.0f) {
76
            spa_log_debug(mix->log, "channel %d is LFE", ic);
77
            lr4_set(&mix->lr4[ic], BQ_LOWPASS, mix->lfe_cutoff / mix->freq);
78
            mix->lr4_info[ic] = 1;
79
@@ -456,6 +462,7 @@
80
    }
81
    if (SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE) &&
82
        maxsum > 1.0f) {
83
+       spa_log_debug(mix->log, "normalize %f", maxsum);
84
        for (i = 0; i < ic; i++)
85
            for (j = 0; j < jc; j++)
86
                        mix->matrix_orig[i][j] /= maxsum;
87
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix.c Changed
147
 
1
@@ -48,7 +48,6 @@
2
 #define DEFAULT_RATE       48000
3
 #define DEFAULT_CHANNELS   2
4
 
5
-#define DEFAULT_SAMPLES    8192
6
 #define MAX_BUFFERS    32
7
 #define MAX_DATAS  SPA_AUDIO_MAX_CHANNELS
8
 
9
@@ -82,6 +81,7 @@
10
    struct volumes soft;
11
    struct volumes monitor;
12
    unsigned int have_soft_volume:1;
13
+   unsigned int disabled:1;
14
 };
15
 
16
 static void props_reset(struct props *props)
17
@@ -142,6 +142,7 @@
18
 
19
    struct spa_log *log;
20
    struct spa_cpu *cpu;
21
+   uint32_t quantum_limit;
22
 
23
    struct spa_io_position *io_position;
24
 
25
@@ -363,6 +364,8 @@
26
    emit_props_changed(this);
27
 
28
    this->is_passthrough = SPA_FLAG_IS_SET(this->mix.flags, CHANNELMIX_FLAG_IDENTITY);
29
+   if (!this->is_passthrough && this->props.disabled)
30
+       return -EINVAL;
31
 
32
    spa_log_debug(this->log, "%p: got channelmix features %08x:%08x flags:%08x passthrough:%d",
33
            this, this->cpu_flags, this->mix.cpu_flags,
34
@@ -495,6 +498,14 @@
35
                    this->mix.lfe_cutoff, 0.0, 1000.0),
36
                SPA_PROP_INFO_params, SPA_POD_Bool(true));
37
            break;
38
+       case 12:
39
+           param = spa_pod_builder_add_object(&b,
40
+               SPA_TYPE_OBJECT_PropInfo, id,
41
+               SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"),
42
+               SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"),
43
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled),
44
+               SPA_PROP_INFO_params, SPA_POD_Bool(true));
45
+           break;
46
        default:
47
            return 0;
48
        }
49
@@ -544,6 +555,8 @@
50
                        CHANNELMIX_OPTION_UPMIX));
51
            spa_pod_builder_string(&b, "channelmix.lfe-cutoff");
52
            spa_pod_builder_float(&b, this->mix.lfe_cutoff);
53
+           spa_pod_builder_string(&b, "channelmix.disable");
54
+           spa_pod_builder_bool(&b, this->props.disabled);
55
            spa_pod_builder_pop(&b, &f[1]);
56
            param = spa_pod_builder_pop(&b, &f[0]);
57
            break;
58
@@ -577,6 +590,8 @@
59
        SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_UPMIX, spa_atob(s));
60
    else if (spa_streq(k, "channelmix.lfe-cutoff"))
61
        this->mix.lfe_cutoff = atoi(s);
62
+   else if (spa_streq(k, "channelmix.disable"))
63
+       this->props.disabled = spa_atob(s);
64
    return 0;
65
 }
66
 
67
@@ -634,6 +649,9 @@
68
    if (param == NULL)
69
        return 0;
70
 
71
+   if (this->props.disabled)
72
+       return 0;
73
+
74
    SPA_POD_OBJECT_FOREACH(obj, prop) {
75
        switch (prop->key) {
76
        case SPA_PROP_volume:
77
@@ -716,6 +734,9 @@
78
    if (size < 3)
79
        return -EINVAL;
80
 
81
+   if (this->props.disabled)
82
+       return 0;
83
+
84
    if ((val[0] & 0xf0) != 0xb0 || val[1] != 7)
85
        return 0;
86
 
87
@@ -863,6 +884,7 @@
88
        } else {
89
            struct spa_pod_frame f;
90
            struct port *other;
91
+           int32_t channels, min = 1, max = INT32_MAX;
92
 
93
            other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0);
94
 
95
@@ -875,19 +897,24 @@
96
                0);
97
 
98
            if (other->have_format) {
99
+               channels = other->format.info.raw.channels;
100
+               if (this->props.disabled)
101
+                   min = max = channels;
102
+
103
                spa_pod_builder_add(builder,
104
                    SPA_FORMAT_AUDIO_rate, SPA_POD_Int(other->format.info.raw.rate),
105
                    SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
106
-                       other->format.info.raw.channels, 1, INT32_MAX),
107
+                       channels, min, max),
108
                    0);
109
            } else {
110
                uint32_t rate = this->io_position ?
111
                    this->io_position->clock.rate.denom : DEFAULT_RATE;
112
+               channels = DEFAULT_CHANNELS;
113
 
114
                spa_pod_builder_add(builder,
115
                    SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(rate, 0, INT32_MAX),
116
                    SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
117
-                       DEFAULT_CHANNELS, 1, INT32_MAX),
118
+                       channels, min, max),
119
                    0);
120
            }
121
            *param = spa_pod_builder_pop(builder, &f);
122
@@ -978,7 +1005,7 @@
123
                size = other->size / other->stride;
124
            } else {
125
                buffers = 1;
126
-               size = DEFAULT_SAMPLES;
127
+               size = this->quantum_limit;
128
            }
129
 
130
            param = spa_pod_builder_add_object(&b,
131
@@ -1539,11 +1566,15 @@
132
 
133
    props_reset(&this->props);
134
 
135
+   this->mix.options = CHANNELMIX_OPTION_NORMALIZE;
136
+
137
    for (i = 0; info && i < info->n_items; i++) {
138
        const char *k = info->items[i].key;
139
        const char *s = info->items[i].value;
140
        if (spa_streq(k, SPA_KEY_AUDIO_POSITION))
141
            this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s));
142
+       else if (spa_streq(k, "clock.quantum-limit"))
143
+           spa_atou32(s, &this->quantum_limit, 0);
144
        else
145
            channelmix_set_param(this, k, s);
146
 
147
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c Changed
201
 
1
@@ -99,6 +99,22 @@
2
 }
3
 
4
 void
5
+conv_copy64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
6
+       uint32_t n_samples)
7
+{
8
+   uint32_t i, n_channels = conv->n_channels;
9
+   for (i = 0; i < n_channels; i++)
10
+       spa_memcpy(dst[i], src[i], n_samples * sizeof(int64_t));
11
+}
12
+
13
+void
14
+conv_copy64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
15
+       uint32_t n_samples)
16
+{
17
+   spa_memcpy(dst[0], src[0], n_samples * sizeof(int64_t) * conv->n_channels);
18
+}
19
+
20
+void
21
 conv_u8d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
22
        uint32_t n_samples)
23
 {
24
@@ -650,6 +666,77 @@
25
 }
26
 
27
 void
28
+conv_f64d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
29
+       uint32_t n_samples)
30
+{
31
+   uint32_t i, j, n_channels = conv->n_channels;
32
+
33
+   for (i = 0; i < n_channels; i++) {
34
+       const double *s = src[i];
35
+       float *d = dst[i];
36
+
37
+       for (j = 0; j < n_samples; j++)
38
+           d[j] = s[j];
39
+   }
40
+}
41
+
42
+void
43
+conv_f64_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
44
+       uint32_t n_samples)
45
+{
46
+   uint32_t i, n_channels = conv->n_channels;
47
+   const double *s = src[0];
48
+   float *d = dst[0];
49
+
50
+   n_samples *= n_channels;
51
+
52
+   for (i = 0; i < n_samples; i++)
53
+       d[i] = s[i];
54
+}
55
+
56
+void
57
+conv_f64_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
58
+       uint32_t n_samples)
59
+{
60
+   const double *s = src[0];
61
+   float **d = (float **) dst;
62
+   uint32_t i, j, n_channels = conv->n_channels;
63
+
64
+   for (j = 0; j < n_samples; j++) {
65
+       for (i = 0; i < n_channels; i++)
66
+           d[i][j] = *s++;
67
+   }
68
+}
69
+
70
+void
71
+conv_f64s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
72
+       uint32_t n_samples)
73
+{
74
+   const double *s = src[0];
75
+   float **d = (float **) dst;
76
+   uint32_t i, j, n_channels = conv->n_channels;
77
+
78
+   for (j = 0; j < n_samples; j++) {
79
+       for (i = 0; i < n_channels; i++)
80
+           d[i][j] = bswap_64(*s++);
81
+   }
82
+}
83
+
84
+void
85
+conv_f64d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
86
+       uint32_t n_samples)
87
+{
88
+   const double **s = (const double **) src;
89
+   float *d = dst[0];
90
+   uint32_t i, j, n_channels = conv->n_channels;
91
+
92
+   for (j = 0; j < n_samples; j++) {
93
+       for (i = 0; i < n_channels; i++)
94
+           *d++ = s[i][j];
95
+   }
96
+}
97
+
98
+void
99
 conv_f32d_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
100
        uint32_t n_samples)
101
 {
102
@@ -989,6 +1076,77 @@
103
 }
104
 
105
 void
106
+conv_f32d_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
107
+       uint32_t n_samples)
108
+{
109
+   uint32_t i, j, n_channels = conv->n_channels;
110
+
111
+   for (i = 0; i < n_channels; i++) {
112
+       const float *s = src[i];
113
+       double *d = dst[i];
114
+
115
+       for (j = 0; j < n_samples; j++)
116
+           d[j] = s[j];
117
+   }
118
+}
119
+
120
+void
121
+conv_f32_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
122
+       uint32_t n_samples)
123
+{
124
+   uint32_t i, n_channels = conv->n_channels;
125
+   const float *s = src[0];
126
+   double *d = dst[0];
127
+
128
+   n_samples *= n_channels;
129
+
130
+   for (i = 0; i < n_samples; i++)
131
+       d[i] = s[i];
132
+}
133
+
134
+void
135
+conv_f32_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
136
+       uint32_t n_samples)
137
+{
138
+   const float *s = src[0];
139
+   double **d = (double **) dst;
140
+   uint32_t i, j, n_channels = conv->n_channels;
141
+
142
+   for (j = 0; j < n_samples; j++) {
143
+       for (i = 0; i < n_channels; i++)
144
+           d[i][j] = *s++;
145
+   }
146
+}
147
+
148
+void
149
+conv_f32d_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
150
+       uint32_t n_samples)
151
+{
152
+   const float **s = (const float **) src;
153
+   double *d = dst[0];
154
+   uint32_t i, j, n_channels = conv->n_channels;
155
+
156
+   for (j = 0; j < n_samples; j++) {
157
+       for (i = 0; i < n_channels; i++)
158
+           *d++ = s[i][j];
159
+   }
160
+}
161
+
162
+void
163
+conv_f32d_to_f64s_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
164
+       uint32_t n_samples)
165
+{
166
+   const float **s = (const float **) src;
167
+   double *d = dst[0];
168
+   uint32_t i, j, n_channels = conv->n_channels;
169
+
170
+   for (j = 0; j < n_samples; j++) {
171
+       for (i = 0; i < n_channels; i++)
172
+           *d++ = bswap_32(s[i][j]);
173
+   }
174
+}
175
+
176
+void
177
 conv_f32_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
178
        uint32_t n_samples)
179
 {
180
@@ -1273,6 +1431,20 @@
181
 }
182
 
183
 void
184
+conv_deinterleave_64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
185
+       uint32_t n_samples)
186
+{
187
+   const uint64_t *s = src[0];
188
+   uint64_t **d = (uint64_t **) dst;
189
+   uint32_t i, j, n_channels = conv->n_channels;
190
+
191
+   for (j = 0; j < n_samples; j++) {
192
+       for (i = 0; i < n_channels; i++)
193
+           d[i][j] = *s++;
194
+   }
195
+}
196
+
197
+void
198
 conv_interleave_8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
199
        uint32_t n_samples)
200
 {
201
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops.c Changed
42
 
1
@@ -138,6 +138,13 @@
2
 
3
    { SPA_AUDIO_FORMAT_S24_32_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24_32s_to_f32d_c },
4
 
5
+   { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F32, 0, 0, conv_f64_to_f32_c },
6
+   { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64d_to_f32d_c },
7
+   { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64_to_f32d_c },
8
+   { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_f64d_to_f32_c },
9
+
10
+   { SPA_AUDIO_FORMAT_F64_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64s_to_f32d_c },
11
+
12
    /* from f32 */
13
    { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0, 0, conv_f32_to_u8_c },
14
    { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_f32d_to_u8d_c },
15
@@ -219,6 +226,13 @@
16
 
17
    { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32_OE, 0, 0, conv_f32d_to_s24_32s_c },
18
 
19
+   { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64, 0, 0, conv_f32_to_f64_c },
20
+   { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_f32d_to_f64d_c },
21
+   { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_f32_to_f64d_c },
22
+   { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64, 0, 0, conv_f32d_to_f64_c },
23
+
24
+   { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64_OE, 0, 0, conv_f32d_to_f64s_c },
25
+
26
    /* u8 */
27
    { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0, 0, conv_copy8_c },
28
    { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_copy8d_c },
29
@@ -259,6 +273,12 @@
30
    { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_copy32d_c },
31
    { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_deinterleave_32_c },
32
    { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_interleave_32_c },
33
+
34
+   /* F64 */
35
+   { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F64, 0, 0, conv_copy64_c },
36
+   { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_copy64d_c },
37
+   { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_deinterleave_64_c },
38
+   { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F64, 0, 0, conv_interleave_64_c },
39
 };
40
 
41
 #define MATCH_CHAN(a,b)        ((a) == 0 || (a) == (b))
42
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops.h Changed
56
 
1
@@ -27,6 +27,7 @@
2
 #include <sys/endian.h>
3
 #define bswap_16 bswap16
4
 #define bswap_32 bswap32
5
+#define bswap_64 bswap64
6
 #else
7
 #include <byteswap.h>
8
 #endif
9
@@ -207,6 +208,8 @@
10
 DEFINE_FUNCTION(copy24, c);
11
 DEFINE_FUNCTION(copy32d, c);
12
 DEFINE_FUNCTION(copy32, c);
13
+DEFINE_FUNCTION(copy64d, c);
14
+DEFINE_FUNCTION(copy64, c);
15
 DEFINE_FUNCTION(u8d_to_f32d, c);
16
 DEFINE_FUNCTION(u8_to_f32, c);
17
 DEFINE_FUNCTION(u8_to_f32d, c);
18
@@ -245,6 +248,11 @@
19
 DEFINE_FUNCTION(s24_32_to_f32d, c);
20
 DEFINE_FUNCTION(s24_32s_to_f32d, c);
21
 DEFINE_FUNCTION(s24_32d_to_f32, c);
22
+DEFINE_FUNCTION(f64d_to_f32d, c);
23
+DEFINE_FUNCTION(f64_to_f32, c);
24
+DEFINE_FUNCTION(f64_to_f32d, c);
25
+DEFINE_FUNCTION(f64s_to_f32d, c);
26
+DEFINE_FUNCTION(f64d_to_f32, c);
27
 DEFINE_FUNCTION(f32d_to_u8d, c);
28
 DEFINE_FUNCTION(f32_to_u8, c);
29
 DEFINE_FUNCTION(f32_to_u8d, c);
30
@@ -283,16 +291,25 @@
31
 DEFINE_FUNCTION(f32_to_s24_32d, c);
32
 DEFINE_FUNCTION(f32d_to_s24_32, c);
33
 DEFINE_FUNCTION(f32d_to_s24_32s, c);
34
+DEFINE_FUNCTION(f32d_to_f64d, c);
35
+DEFINE_FUNCTION(f32_to_f64, c);
36
+DEFINE_FUNCTION(f32_to_f64d, c);
37
+DEFINE_FUNCTION(f32d_to_f64, c);
38
+DEFINE_FUNCTION(f32d_to_f64s, c);
39
 DEFINE_FUNCTION(deinterleave_8, c);
40
 DEFINE_FUNCTION(deinterleave_16, c);
41
 DEFINE_FUNCTION(deinterleave_24, c);
42
 DEFINE_FUNCTION(deinterleave_32, c);
43
 DEFINE_FUNCTION(deinterleave_32s, c);
44
+DEFINE_FUNCTION(deinterleave_64, c);
45
+DEFINE_FUNCTION(deinterleave_64s, c);
46
 DEFINE_FUNCTION(interleave_8, c);
47
 DEFINE_FUNCTION(interleave_16, c);
48
 DEFINE_FUNCTION(interleave_24, c);
49
 DEFINE_FUNCTION(interleave_32, c);
50
 DEFINE_FUNCTION(interleave_32s, c);
51
+DEFINE_FUNCTION(interleave_64, c);
52
+DEFINE_FUNCTION(interleave_64s, c);
53
 
54
 #if defined(HAVE_NEON)
55
 DEFINE_FUNCTION(s16_to_f32d_2, neon);
56
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmtconvert.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmtconvert.c Changed
84
 
1
@@ -52,7 +52,6 @@
2
 #define DEFAULT_RATE       48000
3
 #define DEFAULT_CHANNELS   2
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_BUFFERS    32
7
 #define MAX_ALIGN  16
8
 #define MAX_DATAS  SPA_AUDIO_MAX_CHANNELS
9
@@ -118,6 +117,8 @@
10
 
11
    struct spa_log *log;
12
    struct spa_cpu *cpu;
13
+   uint32_t cpu_flags;
14
+   uint32_t quantum_limit;
15
 
16
    struct spa_io_position *io_position;
17
 
18
@@ -136,7 +137,6 @@
19
 
20
    struct spa_latency_info latency[2];
21
 
22
-   uint32_t cpu_flags;
23
    struct convert conv;
24
    unsigned int started:1;
25
    unsigned int is_passthrough:1;
26
@@ -400,11 +400,14 @@
27
                info.info.raw.format == SPA_AUDIO_FORMAT_F32P ||
28
                info.info.raw.format == SPA_AUDIO_FORMAT_F32) {
29
                spa_pod_builder_add(builder,
30
-                   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(26,
31
+                   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(29,
32
                                info.info.raw.format,
33
                                SPA_AUDIO_FORMAT_F32P,
34
                                SPA_AUDIO_FORMAT_F32,
35
                                SPA_AUDIO_FORMAT_F32_OE,
36
+                               SPA_AUDIO_FORMAT_F64P,
37
+                               SPA_AUDIO_FORMAT_F64,
38
+                               SPA_AUDIO_FORMAT_F64_OE,
39
                                SPA_AUDIO_FORMAT_S32P,
40
                                SPA_AUDIO_FORMAT_S32,
41
                                SPA_AUDIO_FORMAT_S32_OE,
42
@@ -542,7 +545,7 @@
43
                SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
44
                SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
45
                SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
46
-                               MAX_SAMPLES * 2 * port->stride,
47
+                               this->quantum_limit * 2 * port->stride,
48
                                16 * port->stride,
49
                                INT32_MAX),
50
                SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->stride));
51
@@ -619,6 +622,10 @@
52
    case SPA_AUDIO_FORMAT_S24_OE:
53
    case SPA_AUDIO_FORMAT_U24:
54
        return 3;
55
+   case SPA_AUDIO_FORMAT_F64P:
56
+   case SPA_AUDIO_FORMAT_F64:
57
+   case SPA_AUDIO_FORMAT_F64_OE:
58
+       return 8;
59
    default:
60
        return 4;
61
    }
62
@@ -1070,6 +1077,7 @@
63
      uint32_t n_support)
64
 {
65
    struct impl *this;
66
+   uint32_t i;
67
 
68
    spa_return_val_if_fail(factory != NULL, -EINVAL);
69
    spa_return_val_if_fail(handle != NULL, -EINVAL);
70
@@ -1086,6 +1094,13 @@
71
    if (this->cpu)
72
        this->cpu_flags = spa_cpu_get_flags(this->cpu);
73
 
74
+   for (i = 0; info && i < info->n_items; i++) {
75
+       const char *k = info->items[i].key;
76
+       const char *s = info->items[i].value;
77
+       if (spa_streq(k, "clock.quantum-limit"))
78
+           spa_atou32(s, &this->quantum_limit, 0);
79
+   }
80
+
81
    this->node.iface = SPA_INTERFACE_INIT(
82
            SPA_TYPE_INTERFACE_Node,
83
            SPA_VERSION_NODE,
84
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/merger.c Changed
155
 
1
@@ -55,7 +55,6 @@
2
 #define DEFAULT_RATE       48000
3
 #define DEFAULT_CHANNELS   2
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_ALIGN  16
7
 #define MAX_BUFFERS    32
8
 #define MAX_DATAS  SPA_AUDIO_MAX_CHANNELS
9
@@ -146,6 +145,9 @@
10
    struct spa_log *log;
11
    struct spa_cpu *cpu;
12
 
13
+   uint32_t cpu_flags;
14
+   uint32_t quantum_limit;
15
+
16
    struct spa_io_position *io_position;
17
 
18
    uint64_t info_all;
19
@@ -167,7 +169,6 @@
20
    unsigned int have_profile:1;
21
 
22
    struct convert conv;
23
-   uint32_t cpu_flags;
24
    unsigned int is_passthrough:1;
25
    unsigned int started:1;
26
    unsigned int monitor:1;
27
@@ -181,7 +182,8 @@
28
 
29
    struct spa_latency_info latency[2];
30
 
31
-   float empty[MAX_SAMPLES + MAX_ALIGN];
32
+   uint32_t empty_size;
33
+   float *empty;
34
 };
35
 
36
 #define CHECK_IN_PORT(this,d,p)        ((d) == SPA_DIRECTION_INPUT && (p) < this->port_count)
37
@@ -622,7 +624,9 @@
38
 
39
        info.info.raw.rate = 0;
40
 
41
-       if (this->have_profile && memcmp(&this->format, &info, sizeof(info)) == 0)
42
+       if (this->have_profile &&
43
+           memcmp(&this->format, &info, sizeof(info)) == 0 &&
44
+           this->monitor == monitor)
45
            return 0;
46
 
47
        spa_log_debug(this->log, "%p: port config %d/%d %d", this,
48
@@ -775,11 +779,14 @@
49
                SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
50
                SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
51
                SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
52
-               SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(22,
53
+               SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(25,
54
                            SPA_AUDIO_FORMAT_F32P,
55
                            SPA_AUDIO_FORMAT_F32P,
56
                            SPA_AUDIO_FORMAT_F32,
57
                            SPA_AUDIO_FORMAT_F32_OE,
58
+                           SPA_AUDIO_FORMAT_F64P,
59
+                           SPA_AUDIO_FORMAT_F64,
60
+                           SPA_AUDIO_FORMAT_F64_OE,
61
                            SPA_AUDIO_FORMAT_S32P,
62
                            SPA_AUDIO_FORMAT_S32,
63
                            SPA_AUDIO_FORMAT_S32_OE,
64
@@ -869,7 +876,7 @@
65
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
66
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
67
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
68
-                               MAX_SAMPLES * port->stride,
69
+                               this->quantum_limit * port->stride,
70
                                16 * port->stride,
71
                                INT32_MAX),
72
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->stride));
73
@@ -1008,6 +1015,10 @@
74
    case SPA_AUDIO_FORMAT_S24:
75
    case SPA_AUDIO_FORMAT_S24_OE:
76
        return 3;
77
+   case SPA_AUDIO_FORMAT_F64P:
78
+   case SPA_AUDIO_FORMAT_F64:
79
+   case SPA_AUDIO_FORMAT_F64_OE:
80
+       return 8;
81
    default:
82
        return 4;
83
    }
84
@@ -1024,7 +1035,11 @@
85
    enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
86
    uint32_t i;
87
 
88
-   spa_log_debug(this->log, "%p: set latency direction:%d", this, direction);
89
+   spa_log_debug(this->log, "%p: set latency direction:%d id:%d",
90
+           this, direction, port_id);
91
+
92
+   if (direction == SPA_DIRECTION_OUTPUT && port_id != 0)
93
+       return 0;
94
 
95
    if (latency == NULL) {
96
        this->latency[other] = SPA_LATENCY_INFO(other);
97
@@ -1212,7 +1227,7 @@
98
 {
99
    struct impl *this = object;
100
    struct port *port;
101
-   uint32_t i, j;
102
+   uint32_t i, j, maxsize;
103
 
104
    spa_return_val_if_fail(this != NULL, -EINVAL);
105
 
106
@@ -1227,6 +1242,7 @@
107
 
108
    clear_buffers(this, port);
109
 
110
+   maxsize = 0;
111
    for (i = 0; i < n_buffers; i++) {
112
        struct buffer *b;
113
        uint32_t n_datas = buffers[i]->n_datas;
114
@@ -1257,11 +1273,19 @@
115
            if (direction == SPA_DIRECTION_OUTPUT &&
116
                !SPA_FLAG_IS_SET(d[j].flags, SPA_DATA_FLAG_DYNAMIC))
117
                this->is_passthrough = false;
118
-       }
119
 
120
+           maxsize = SPA_MAX(maxsize, d[j].maxsize);
121
+       }
122
        if (direction == SPA_DIRECTION_OUTPUT)
123
            queue_buffer(this, port, i);
124
    }
125
+   if (maxsize > this->empty_size) {
126
+       this->empty = realloc(this->empty, maxsize + MAX_ALIGN);
127
+       if (this->empty == NULL)
128
+           return -errno;
129
+       memset(this->empty, 0, maxsize + MAX_ALIGN);
130
+       this->empty_size = maxsize;
131
+   }
132
    port->n_buffers = n_buffers;
133
 
134
    return 0;
135
@@ -1519,6 +1543,7 @@
136
        free(this->in_ports[i]);
137
    for (i = 0; i < MAX_PORTS+1; i++)
138
        free(this->out_ports[i]);
139
+   free(this->empty);
140
    return 0;
141
 }
142
 
143
@@ -1557,7 +1582,10 @@
144
    for (i = 0; info && i < info->n_items; i++) {
145
        const char *k = info->items[i].key;
146
        const char *s = info->items[i].value;
147
-       merger_set_param(this, k, s);
148
+       if (spa_streq(k, "clock.quantum-limit"))
149
+           spa_atou32(s, &this->quantum_limit, 0);
150
+       else
151
+           merger_set_param(this, k, s);
152
    }
153
 
154
    this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
155
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/meson.build -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/meson.build Changed
27
 
1
@@ -140,7 +140,7 @@
2
       install : installed_tests_enabled,
3
       install_dir : installed_tests_execdir / 'audioconvert'),
4
       env : [
5
-        'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')),
6
+        'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')),
7
         ])
8
 
9
     if installed_tests_enabled
10
@@ -170,7 +170,7 @@
11
       install : installed_tests_enabled,
12
       install_dir : installed_tests_execdir / 'audioconvert'),
13
       env : [
14
-        'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')),
15
+        'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')),
16
         ])
17
 
18
     if installed_tests_enabled
19
@@ -191,7 +191,6 @@
20
     ]
21
   executable('spa-resample',
22
     sparesample_sources,
23
-    c_args : [ simd_cargs ],
24
     link_with : [ test_lib ],
25
     dependencies : [ spa_dep, sndfile_dep, mathlib, audioconvert_dep ],
26
     install : true,
27
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h Changed
10
 
1
@@ -31,7 +31,7 @@
2
 struct peaks_data {
3
    uint32_t o_count;
4
    uint32_t i_count;
5
-   float max_f[0];
6
+   float max_f[];
7
 };
8
 
9
 #if defined (HAVE_SSE)
10
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample-peaks.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample-peaks.c Changed
10
 
1
@@ -146,7 +146,7 @@
2
    r->delay = impl_peaks_delay;
3
    r->in_len = impl_peaks_in_len;
4
 
5
-   d = r->data = calloc(1, sizeof(struct peaks_data) * sizeof(float) * r->channels);
6
+   d = r->data = calloc(1, sizeof(struct peaks_data) + sizeof(float) * r->channels);
7
    if (r->data == NULL)
8
        return -errno;
9
 
10
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample.c Changed
201
 
1
@@ -48,7 +48,6 @@
2
 #define DEFAULT_RATE       48000
3
 #define DEFAULT_CHANNELS   2
4
 
5
-#define MAX_SAMPLES    8192u
6
 #define MAX_ALIGN  16
7
 #define MAX_BUFFERS    32
8
 
9
@@ -57,12 +56,14 @@
10
 struct props {
11
    double rate;
12
    int quality;
13
+   bool disabled;
14
 };
15
 
16
 static void props_reset(struct props *props)
17
 {
18
    props->rate = 1.0;
19
    props->quality = RESAMPLE_DEFAULT_QUALITY;
20
+   props->disabled = false;
21
 }
22
 
23
 struct buffer {
24
@@ -104,6 +105,8 @@
25
    struct spa_log *log;
26
    struct spa_cpu *cpu;
27
 
28
+   uint32_t quantum_limit;
29
+
30
    struct spa_io_position *io_position;
31
    struct spa_io_rate_match *io_rate_match;
32
 
33
@@ -127,8 +130,6 @@
34
    struct resample resample;
35
 
36
    double rate_scale;
37
-
38
-   float empty[MAX_SAMPLES + MAX_ALIGN];
39
 };
40
 
41
 #define CHECK_PORT(this,d,id)      (id == 0)
42
@@ -183,7 +184,147 @@
43
                 uint32_t id, uint32_t start, uint32_t num,
44
                 const struct spa_pod *filter)
45
 {
46
-   return -ENOTSUP;
47
+   struct impl *this = object;
48
+   struct spa_pod *param;
49
+   struct spa_pod_builder b = { 0 };
50
+   uint8_t buffer[4096];
51
+   struct spa_result_node_params result;
52
+   uint32_t count = 0;
53
+
54
+   spa_return_val_if_fail(this != NULL, -EINVAL);
55
+   spa_return_val_if_fail(num != 0, -EINVAL);
56
+
57
+   result.id = id;
58
+   result.next = start;
59
+      next:
60
+   result.index = result.next++;
61
+
62
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
63
+
64
+   switch (id) {
65
+   case SPA_PARAM_PropInfo:
66
+   {
67
+       struct props *p = &this->props;
68
+
69
+       switch (result.index) {
70
+       case 0:
71
+           param = spa_pod_builder_add_object(&b,
72
+               SPA_TYPE_OBJECT_PropInfo, id,
73
+               SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate),
74
+               SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"),
75
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0));
76
+           break;
77
+       case 1:
78
+           param = spa_pod_builder_add_object(&b,
79
+               SPA_TYPE_OBJECT_PropInfo, id,
80
+               SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality),
81
+               SPA_PROP_INFO_name, SPA_POD_String("resample.quality"),
82
+               SPA_PROP_INFO_description, SPA_POD_String("Resample Quality"),
83
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->quality, 0, 14),
84
+               SPA_PROP_INFO_params, SPA_POD_Bool(true));
85
+           break;
86
+       case 2:
87
+           param = spa_pod_builder_add_object(&b,
88
+               SPA_TYPE_OBJECT_PropInfo, id,
89
+               SPA_PROP_INFO_name, SPA_POD_String("resample.disable"),
90
+               SPA_PROP_INFO_description, SPA_POD_String("Disable Resampling"),
91
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled),
92
+               SPA_PROP_INFO_params, SPA_POD_Bool(true));
93
+           break;
94
+       default:
95
+           return 0;
96
+       }
97
+       break;
98
+   }
99
+   case SPA_PARAM_Props:
100
+   {
101
+       struct props *p = &this->props;
102
+       struct spa_pod_frame f[2];
103
+
104
+       switch (result.index) {
105
+       case 0:
106
+           spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Props, id);
107
+           spa_pod_builder_add(&b,
108
+               SPA_PROP_rate,          SPA_POD_Double(p->rate),
109
+               SPA_PROP_quality,       SPA_POD_Int(p->quality),
110
+               0);
111
+           spa_pod_builder_prop(&b, SPA_PROP_params, 0);
112
+           spa_pod_builder_push_struct(&b, &f[1]);
113
+           spa_pod_builder_string(&b, "resample.quality");
114
+           spa_pod_builder_int(&b, p->quality);
115
+           spa_pod_builder_string(&b, "resample.disable");
116
+           spa_pod_builder_bool(&b, p->disabled);
117
+           spa_pod_builder_pop(&b, &f[1]);
118
+           param = spa_pod_builder_pop(&b, &f[0]);
119
+           break;
120
+       default:
121
+           return 0;
122
+       }
123
+       break;
124
+   }
125
+   default:
126
+       return -ENOENT;
127
+   }
128
+
129
+   if (spa_pod_filter(&b, &result.param, param, filter) < 0)
130
+       goto next;
131
+
132
+   spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
133
+
134
+   if (++count != num)
135
+       goto next;
136
+
137
+   return 0;
138
+}
139
+
140
+static int resample_set_param(struct impl *this, const char *k, const char *s)
141
+{
142
+   if (spa_streq(k, "resample.quality"))
143
+       this->props.quality = atoi(s);
144
+   else if (spa_streq(k, "resample.disable"))
145
+       this->props.disabled = spa_atob(s);
146
+   return 0;
147
+}
148
+
149
+static int parse_prop_params(struct impl *this, struct spa_pod *params)
150
+{
151
+   struct spa_pod_parser prs;
152
+   struct spa_pod_frame f;
153
+
154
+   spa_pod_parser_pod(&prs, params);
155
+   if (spa_pod_parser_push_struct(&prs, &f) < 0)
156
+       return 0;
157
+
158
+   while (true) {
159
+       const char *name;
160
+       struct spa_pod *pod;
161
+       char value[512];
162
+
163
+       if (spa_pod_parser_get_string(&prs, &name) < 0)
164
+           break;
165
+
166
+       if (spa_pod_parser_get_pod(&prs, &pod) < 0)
167
+           break;
168
+
169
+       if (spa_pod_is_string(pod)) {
170
+           spa_pod_copy_string(pod, sizeof(value), value);
171
+       } else if (spa_pod_is_float(pod)) {
172
+           snprintf(value, sizeof(value), "%f",
173
+                   SPA_POD_VALUE(struct spa_pod_float, pod));
174
+       } else if (spa_pod_is_int(pod)) {
175
+           snprintf(value, sizeof(value), "%d",
176
+                   SPA_POD_VALUE(struct spa_pod_int, pod));
177
+       } else if (spa_pod_is_bool(pod)) {
178
+           snprintf(value, sizeof(value), "%s",
179
+                   SPA_POD_VALUE(struct spa_pod_bool, pod) ?
180
+                   "true" : "false");
181
+       } else
182
+           continue;
183
+
184
+       spa_log_info(this->log, "key:'%s' val:'%s'", name, value);
185
+       resample_set_param(this, name, value);
186
+   }
187
+   return 0;
188
 }
189
 
190
 static int apply_props(struct impl *this, const struct spa_pod *param)
191
@@ -191,22 +332,28 @@
192
    struct spa_pod_prop *prop;
193
    struct spa_pod_object *obj = (struct spa_pod_object *) param;
194
    struct props *p = &this->props;
195
+   int changed = 0;
196
 
197
    SPA_POD_OBJECT_FOREACH(obj, prop) {
198
        switch (prop->key) {
199
        case SPA_PROP_rate:
200
            if (spa_pod_get_double(&prop->value, &p->rate) == 0) {
201
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/spa-resample.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/spa-resample.c Changed
52
 
1
@@ -49,6 +49,7 @@
2
    int rate;
3
    int format;
4
    int quality;
5
+   int cpu_flags;
6
 
7
    const char *iname;
8
    SF_INFO iinfo;
9
@@ -61,7 +62,7 @@
10
 
11
 #define STR_FMTS "(s8|s16|s32|f32|f64)"
12
 
13
-#define OPTIONS        "hvr:f:q:"
14
+#define OPTIONS        "hvr:f:q:c:"
15
 static const struct option long_options[] = {
16
    { "help",   no_argument,        NULL, 'h'},
17
    { "verbose",    no_argument,        NULL, 'v'},
18
@@ -69,6 +70,7 @@
19
    { "rate",   required_argument,  NULL, 'r' },
20
    { "format", required_argument,  NULL, 'f' },
21
    { "quality",    required_argument,  NULL, 'q' },
22
+   { "cpuflags",   required_argument,  NULL, 'c' },
23
 
24
         { NULL, 0, NULL, 0 }
25
 };
26
@@ -88,6 +90,7 @@
27
        "  -r  --rate                            Output sample rate (default as input)\n"
28
        "  -f  --format                          Output sample format %s (default as input)\n"
29
        "  -q  --quality                         Resampler quality (default %u)\n"
30
+       "  -c  --cpuflags                        CPU flags (default 0)\n"
31
        "\n",
32
        STR_FMTS, DEFAULT_QUALITY);
33
 }
34
@@ -191,6 +194,7 @@
35
    bool flushing = false;
36
 
37
    spa_zero(r);
38
+   r.cpu_flags = d->cpu_flags;
39
    r.log = &logger.log;
40
    r.channels = channels;
41
    r.i_rate = d->iinfo.samplerate;
42
@@ -297,6 +301,9 @@
43
            }
44
            data.quality = ret;
45
            break;
46
+       case 'c':
47
+           data.cpu_flags = strtol(optarg, NULL, 0);
48
+           break;
49
                 default:
50
            fprintf(stderr, "error: unknown option '%c'\n", c);
51
            goto error_usage;
52
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/splitter.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/splitter.c Changed
164
 
1
@@ -53,7 +53,6 @@
2
 #define DEFAULT_CHANNELS   2
3
 #define DEFAULT_MASK       (1LL << SPA_AUDIO_CHANNEL_FL) | (1LL << SPA_AUDIO_CHANNEL_FR)
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_ALIGN  16
7
 #define MAX_BUFFERS    32
8
 #define MAX_DATAS  SPA_AUDIO_MAX_CHANNELS
9
@@ -107,6 +106,9 @@
10
    struct spa_log *log;
11
    struct spa_cpu *cpu;
12
 
13
+   uint32_t cpu_flags;
14
+   uint32_t quantum_limit;
15
+
16
    struct spa_io_position *io_position;
17
 
18
    uint64_t info_all;
19
@@ -124,7 +126,6 @@
20
    struct spa_audio_info format;
21
    unsigned int have_profile:1;
22
 
23
-   uint32_t cpu_flags;
24
    struct convert conv;
25
    unsigned int is_passthrough:1;
26
    unsigned int started:1;
27
@@ -134,7 +135,8 @@
28
    uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS];
29
    uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS];
30
 
31
-   float empty[MAX_SAMPLES + MAX_ALIGN];
32
+   uint32_t empty_size;
33
+   float *empty;
34
 };
35
 
36
 #define CHECK_OUT_PORT(this,d,p)   ((d) == SPA_DIRECTION_OUTPUT && (p) < this->port_count)
37
@@ -456,11 +458,14 @@
38
                SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
39
                SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
40
                SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
41
-               SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(22,
42
+               SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(25,
43
                            SPA_AUDIO_FORMAT_F32P,
44
                            SPA_AUDIO_FORMAT_F32P,
45
                            SPA_AUDIO_FORMAT_F32,
46
                            SPA_AUDIO_FORMAT_F32_OE,
47
+                           SPA_AUDIO_FORMAT_F64P,
48
+                           SPA_AUDIO_FORMAT_F64,
49
+                           SPA_AUDIO_FORMAT_F64_OE,
50
                            SPA_AUDIO_FORMAT_S32P,
51
                            SPA_AUDIO_FORMAT_S32,
52
                            SPA_AUDIO_FORMAT_S32_OE,
53
@@ -550,9 +555,9 @@
54
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
55
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
56
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
57
-                           MAX_SAMPLES * port->stride,
58
+                           this->quantum_limit * port->stride,
59
                            16 * port->stride,
60
-                           MAX_SAMPLES * port->stride),
61
+                           INT32_MAX),
62
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->stride));
63
        break;
64
 
65
@@ -690,6 +695,10 @@
66
    case SPA_AUDIO_FORMAT_S24:
67
    case SPA_AUDIO_FORMAT_S24_OE:
68
        return 3;
69
+   case SPA_AUDIO_FORMAT_F64P:
70
+   case SPA_AUDIO_FORMAT_F64:
71
+   case SPA_AUDIO_FORMAT_F64_OE:
72
+       return 8;
73
    default:
74
        return 4;
75
    }
76
@@ -877,7 +886,7 @@
77
 {
78
    struct impl *this = object;
79
    struct port *port;
80
-   uint32_t i, j;
81
+   uint32_t i, j, maxsize;
82
 
83
    spa_return_val_if_fail(this != NULL, -EINVAL);
84
    spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
85
@@ -890,6 +899,7 @@
86
 
87
    clear_buffers(this, port);
88
 
89
+   maxsize = 0;
90
    for (i = 0; i < n_buffers; i++) {
91
        struct buffer *b;
92
        uint32_t n_datas = buffers[i]->n_datas;
93
@@ -917,11 +927,19 @@
94
 
95
            spa_log_debug(this->log, "%p: buffer %d data %d flags:%08x %p",
96
                    this, i, j, d[j].flags, b->datas[j]);
97
-       }
98
 
99
+           maxsize = SPA_MAX(maxsize, d[j].maxsize);
100
+       }
101
        if (direction == SPA_DIRECTION_OUTPUT)
102
            queue_buffer(this, port, i);
103
    }
104
+   if (maxsize > this->empty_size) {
105
+       this->empty = realloc(this->empty, maxsize + MAX_ALIGN);
106
+       if (this->empty == NULL)
107
+           return -errno;
108
+       memset(this->empty, 0, maxsize + MAX_ALIGN);
109
+       this->empty_size = maxsize;
110
+   }
111
    port->n_buffers = n_buffers;
112
 
113
    return 0;
114
@@ -975,7 +993,6 @@
115
    uint32_t n_src_datas, n_dst_datas;
116
    const void **src_datas;
117
    void **dst_datas;
118
-   int res = 0;
119
 
120
    spa_return_val_if_fail(this != NULL, -EINVAL);
121
 
122
@@ -1063,10 +1080,8 @@
123
        convert_process(&this->conv, dst_datas, src_datas, n_samples);
124
 
125
    inio->status = SPA_STATUS_NEED_DATA;
126
-   res |= SPA_STATUS_NEED_DATA;
127
-   res |= SPA_STATUS_HAVE_DATA;
128
 
129
-   return res;
130
+   return SPA_STATUS_NEED_DATA | SPA_STATUS_HAVE_DATA;
131
 }
132
 
133
 static const struct spa_node_methods impl_node = {
134
@@ -1115,6 +1130,7 @@
135
 
136
    for (i = 0; i < MAX_PORTS; i++)
137
        free(this->out_ports[i]);
138
+   free(this->empty);
139
    return 0;
140
 }
141
 
142
@@ -1134,6 +1150,7 @@
143
 {
144
    struct impl *this;
145
    struct port *port;
146
+   uint32_t i;
147
 
148
    spa_return_val_if_fail(factory != NULL, -EINVAL);
149
    spa_return_val_if_fail(handle != NULL, -EINVAL);
150
@@ -1150,6 +1167,13 @@
151
    if (this->cpu)
152
        this->cpu_flags = spa_cpu_get_flags(this->cpu);
153
 
154
+   for (i = 0; info && i < info->n_items; i++) {
155
+       const char *k = info->items[i].key;
156
+       const char *s = info->items[i].value;
157
+       if (spa_streq(k, "clock.quantum-limit"))
158
+           spa_atou32(s, &this->quantum_limit, 0);
159
+   }
160
+
161
    spa_hook_list_init(&this->hooks);
162
 
163
    this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
164
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-channelmix.c Changed
10
 
1
@@ -162,7 +162,7 @@
2
    test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC),
3
            MATRIX(1.0, 0.0, 0.707107, 0.0,
4
                   0.0, 1.0, 0.0, 0.707107,
5
-                  0.0, 0.0, 0.0, 0.0,
6
+                  0.707107, 0.707107, 0.0, 0.0,
7
                   0.0, 0.0, 0.0, 0.0));
8
 }
9
 
10
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c Changed
70
 
1
@@ -41,10 +41,10 @@
2
 
3
 static uint32_t cpu_flags;
4
 
5
-static uint8_t samp_in[N_SAMPLES * 4];
6
-static uint8_t samp_out[N_SAMPLES * 4];
7
-static uint8_t temp_in[N_SAMPLES * N_CHANNELS * 4];
8
-static uint8_t temp_out[N_SAMPLES * N_CHANNELS * 4];
9
+static uint8_t samp_in[N_SAMPLES * 8];
10
+static uint8_t samp_out[N_SAMPLES * 8];
11
+static uint8_t temp_in[N_SAMPLES * N_CHANNELS * 8];
12
+static uint8_t temp_out[N_SAMPLES * N_CHANNELS * 8];
13
 
14
 static void compare_mem(int i, int j, const void *m1, const void *m2, size_t size)
15
 {
16
@@ -92,6 +92,9 @@
17
        case 4:
18
            conv_interleave_32_c(&conv, tp, ip, N_SAMPLES);
19
            break;
20
+       case 8:
21
+           conv_interleave_64_c(&conv, tp, ip, N_SAMPLES);
22
+           break;
23
        default:
24
            fprintf(stderr, "unknown size %zd\n", in_size);
25
            return;
26
@@ -430,6 +433,35 @@
27
            false, false, conv_s24_32d_to_f32d_c);
28
 }
29
 
30
+static void test_f64_f32(void)
31
+{
32
+   static const double in[] = { 0.0, 1.0, -1.0, 0.4999999404, -0.4999999404, };
33
+   static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, };
34
+
35
+   run_test("test_f64_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
36
+           true, false, conv_f64_to_f32d_c);
37
+   run_test("test_f64d_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
38
+           false, true, conv_f64d_to_f32_c);
39
+   run_test("test_f64_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
40
+           true, true, conv_f64_to_f32_c);
41
+   run_test("test_f64d_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
42
+           false, false, conv_f64d_to_f32d_c);
43
+}
44
+
45
+static void test_f32_f64(void)
46
+{
47
+   static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f };
48
+   static const double out[] = { 0.0, 1.0, -1.0, 0.5, -0.5, 1.1, -1.1 };
49
+
50
+   run_test("test_f32_f64", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
51
+           true, true, conv_f32_to_f64_c);
52
+   run_test("test_f32d_f64", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
53
+           false, true, conv_f32d_to_f64_c);
54
+   run_test("test_f32_f64d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
55
+           true, false, conv_f32_to_f64d_c);
56
+   run_test("test_f32d_f64d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out),
57
+           false, false, conv_f32d_to_f64d_c);
58
+}
59
 int main(int argc, char *argv[])
60
 {
61
    cpu_flags = get_cpu_flags();
62
@@ -453,5 +485,7 @@
63
    test_u24_32_f32();
64
    test_f32_s24_32();
65
    test_s24_32_f32();
66
+   test_f32_f64();
67
+   test_f64_f32();
68
    return 0;
69
 }
70
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-source.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-source.c Changed
49
 
1
@@ -45,7 +45,6 @@
2
 #define DEFAULT_RATE       44100
3
 #define DEFAULT_CHANNELS   2
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_BUFFERS    32
7
 
8
 struct impl;
9
@@ -101,6 +100,8 @@
10
 
11
    struct spa_log *log;
12
 
13
+   uint32_t quantum_limit;
14
+
15
    struct spa_hook_list hooks;
16
 
17
    uint64_t info_all;
18
@@ -458,7 +459,7 @@
19
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
20
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
21
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
22
-                           MAX_SAMPLES * port->stride,
23
+                           this->quantum_limit * port->stride,
24
                            16 * port->stride,
25
                            INT32_MAX),
26
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->stride));
27
@@ -830,6 +831,7 @@
28
 {
29
    struct impl *this;
30
    struct port *port;
31
+   uint32_t i;
32
 
33
    spa_return_val_if_fail(factory != NULL, -EINVAL);
34
    spa_return_val_if_fail(handle != NULL, -EINVAL);
35
@@ -841,6 +843,13 @@
36
 
37
    this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
38
 
39
+   for (i = 0; info && i < info->n_items; i++) {
40
+       const char *k = info->items[i].key;
41
+       const char *s = info->items[i].value;
42
+       if (spa_streq(k, "clock.quantum-limit"))
43
+           spa_atou32(s, &this->quantum_limit, 0);
44
+   }
45
+
46
    spa_log_debug(this->log, NAME " %p: init", this);
47
    spa_hook_list_init(&this->hooks);
48
 
49
pipewire-0.3.43.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/audiomixer.c Changed
146
 
1
@@ -45,11 +45,9 @@
2
 #define SPA_LOG_TOPIC_DEFAULT log_topic
3
 static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer");
4
 
5
-#define MAX_SAMPLES     8192
6
 #define MAX_BUFFERS     64
7
 #define MAX_PORTS       128
8
 #define MAX_CHANNELS    64
9
-#define MAX_BUFFER_SIZE    (MAX_SAMPLES * MAX_CHANNELS * 8)
10
 
11
 #define PORT_DEFAULT_VOLUME    1.0
12
 #define PORT_DEFAULT_MUTE  false
13
@@ -74,8 +72,6 @@
14
    struct spa_buffer *buffer;
15
    struct spa_meta_header *h;
16
    struct spa_buffer buf;
17
-   struct spa_data datas[1];
18
-   struct spa_chunk chunk[1];
19
 };
20
 
21
 struct port {
22
@@ -107,6 +103,7 @@
23
    struct spa_log *log;
24
    struct spa_cpu *cpu;
25
    uint32_t cpu_flags;
26
+   uint32_t quantum_limit;
27
 
28
    struct mix_ops ops;
29
 
30
@@ -128,9 +125,6 @@
31
    unsigned int started:1;
32
    uint32_t stride;
33
    uint32_t blocks;
34
-
35
-   uint8_t empty[MAX_BUFFER_SIZE];
36
-
37
 };
38
 
39
 #define PORT_VALID(p)                ((p) != NULL && (p)->valid)
40
@@ -421,7 +415,7 @@
41
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
42
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(this->blocks),
43
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
44
-                               MAX_SAMPLES * this->stride,
45
+                               this->quantum_limit * this->stride,
46
                                16 * this->stride,
47
                                INT32_MAX),
48
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->stride));
49
@@ -520,6 +514,10 @@
50
    case SPA_AUDIO_FORMAT_S24_OE:
51
    case SPA_AUDIO_FORMAT_U24:
52
        return 3;
53
+   case SPA_AUDIO_FORMAT_F64P:
54
+   case SPA_AUDIO_FORMAT_F64:
55
+   case SPA_AUDIO_FORMAT_F64_OE:
56
+       return 8;
57
    default:
58
        return 4;
59
    }
60
@@ -653,6 +651,7 @@
61
        b->flags = 0;
62
        b->id = i;
63
        b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
64
+       b->buf = *buffers[i];
65
 
66
        if (d[0].data == NULL) {
67
            spa_log_error(this->log, "%p: invalid memory on buffer %p", this,
68
@@ -721,9 +720,9 @@
69
    struct impl *this = object;
70
    struct port *outport;
71
    struct spa_io_buffers *outio;
72
-   uint32_t n_samples, n_buffers, i, maxsize;
73
+   uint32_t n_buffers, i, maxsize;
74
    struct buffer **buffers;
75
-        struct buffer *outb;
76
+   struct buffer *outb;
77
    const void **datas;
78
 
79
    spa_return_val_if_fail(this != NULL, -EINVAL);
80
@@ -748,7 +747,7 @@
81
         datas = alloca(MAX_PORTS * sizeof(void *));
82
         n_buffers = 0;
83
 
84
-   maxsize = MAX_SAMPLES * this->stride;
85
+   maxsize = UINT32_MAX;
86
 
87
    for (i = 0; i < this->last_port; i++) {
88
        struct port *inport = GET_IN_PORT(this, i);
89
@@ -785,22 +784,22 @@
90
                 return -EPIPE;
91
         }
92
 
93
-   n_samples = maxsize / this->stride;
94
-
95
    if (n_buffers == 1) {
96
        *outb->buffer = *buffers[0]->buffer;
97
    }
98
    else {
99
-       outb->buffer->n_datas = 1;
100
-       outb->buffer->datas = outb->datas;
101
-       outb->datas[0].data = this->empty;
102
-       outb->datas[0].chunk = outb->chunk;
103
-       outb->datas[0].chunk->offset = 0;
104
-       outb->datas[0].chunk->size = n_samples * this->stride;
105
-       outb->datas[0].chunk->stride = this->stride;
106
-       outb->datas[0].maxsize = maxsize;
107
-
108
-       mix_ops_process(&this->ops, outb->datas[0].data, datas, n_buffers, n_samples);
109
+       struct spa_data *d = outb->buf.datas;
110
+
111
+       *outb->buffer = outb->buf;
112
+
113
+       maxsize = SPA_MIN(maxsize, d[0].maxsize);
114
+
115
+       d[0].chunk->offset = 0;
116
+       d[0].chunk->size = maxsize;
117
+       d[0].chunk->stride = this->stride;
118
+
119
+       mix_ops_process(&this->ops, d[0].data,
120
+               datas, n_buffers, maxsize / this->stride);
121
    }
122
 
123
    outio->buffer_id = outb->id;
124
@@ -875,6 +874,7 @@
125
 {
126
    struct impl *this;
127
    struct port *port;
128
+   uint32_t i;
129
 
130
    spa_return_val_if_fail(factory != NULL, -EINVAL);
131
    spa_return_val_if_fail(handle != NULL, -EINVAL);
132
@@ -891,6 +891,13 @@
133
    if (this->cpu)
134
        this->cpu_flags = spa_cpu_get_flags(this->cpu);
135
 
136
+   for (i = 0; info && i < info->n_items; i++) {
137
+       const char *k = info->items[i].key;
138
+       const char *s = info->items[i].value;
139
+       if (spa_streq(k, "clock.quantum-limit"))
140
+           spa_atou32(s, &this->quantum_limit, 0);
141
+   }
142
+
143
    spa_hook_list_init(&this->hooks);
144
 
145
    this->node.iface = SPA_INTERFACE_INIT(
146
pipewire-0.3.43.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/mixer-dsp.c Changed
138
 
1
@@ -47,7 +47,6 @@
2
 
3
 #define MAX_BUFFERS    64
4
 #define MAX_PORTS  128
5
-#define MAX_SAMPLES    8192
6
 #define MAX_ALIGN  64
7
 
8
 #define PORT_DEFAULT_VOLUME    1.0
9
@@ -73,8 +72,6 @@
10
    struct spa_buffer *buffer;
11
    struct spa_meta_header *h;
12
    struct spa_buffer buf;
13
-        struct spa_data datas[1];
14
-        struct spa_chunk chunk[1];
15
 };
16
 
17
 struct port {
18
@@ -107,6 +104,8 @@
19
    struct spa_cpu *cpu;
20
    uint32_t cpu_flags;
21
 
22
+   uint32_t quantum_limit;
23
+
24
    struct mix_ops ops;
25
 
26
    uint64_t info_all;
27
@@ -126,8 +125,6 @@
28
 
29
    unsigned int have_format:1;
30
    unsigned int started:1;
31
-
32
-   float empty[MAX_SAMPLES + MAX_ALIGN];
33
 };
34
 
35
 #define PORT_VALID(p)                ((p) != NULL && (p)->valid)
36
@@ -400,7 +397,7 @@
37
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
38
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
39
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
40
-                               MAX_SAMPLES * this->stride,
41
+                               this->quantum_limit * this->stride,
42
                                16 * this->stride,
43
                                INT32_MAX),
44
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->stride));
45
@@ -601,12 +598,13 @@
46
        b->flags = 0;
47
        b->id = i;
48
        b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
49
+       b->buf = *buffers[i];
50
 
51
        if (d[0].data == NULL) {
52
            spa_log_error(this->log, "%p: invalid memory on buffer %d", this, i);
53
            return -EINVAL;
54
        }
55
-       if (!SPA_IS_ALIGNED(d[0].data, 16)) {
56
+       if (!SPA_IS_ALIGNED(d[0].data, 32)) {
57
            spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i);
58
        }
59
        if (direction == SPA_DIRECTION_OUTPUT)
60
@@ -668,9 +666,9 @@
61
    struct impl *this = object;
62
    struct port *outport;
63
    struct spa_io_buffers *outio;
64
-   uint32_t n_samples, n_buffers, i, maxsize;
65
-        struct buffer **buffers;
66
-        struct buffer *outb;
67
+   uint32_t n_buffers, i, maxsize;
68
+   struct buffer **buffers;
69
+   struct buffer *outb;
70
    const void **datas;
71
 
72
    spa_return_val_if_fail(this != NULL, -EINVAL);
73
@@ -695,7 +693,7 @@
74
         datas = alloca(MAX_PORTS * sizeof(void *));
75
         n_buffers = 0;
76
 
77
-   maxsize = MAX_SAMPLES * sizeof(float);
78
+   maxsize = UINT32_MAX;
79
 
80
    for (i = 0; i < this->last_port; i++) {
81
        struct port *inport = GET_IN_PORT(this, i);
82
@@ -732,21 +730,20 @@
83
                 return -EPIPE;
84
         }
85
 
86
-   n_samples = maxsize / sizeof(float);
87
-
88
    if (n_buffers == 1) {
89
        *outb->buffer = *buffers[0]->buffer;
90
-   }
91
-   else {
92
-       outb->buffer->n_datas = 1;
93
-       outb->buffer->datas = outb->datas;
94
-       outb->datas[0].data = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void);
95
-       outb->datas[0].chunk = outb->chunk;
96
-       outb->datas[0].chunk->offset = 0;
97
-       outb->datas[0].chunk->size = n_samples * sizeof(float);
98
-       outb->datas[0].chunk->stride = sizeof(float);
99
-
100
-       mix_ops_process(&this->ops, outb->datas[0].data, datas, n_buffers, n_samples);
101
+   } else {
102
+       struct spa_data *d = outb->buf.datas;
103
+       *outb->buffer = outb->buf;
104
+
105
+       maxsize = SPA_MIN(maxsize, d[0].maxsize);
106
+
107
+       d[0].chunk->offset = 0;
108
+       d[0].chunk->size = maxsize;
109
+       d[0].chunk->stride = sizeof(float);
110
+
111
+       mix_ops_process(&this->ops, d[0].data,
112
+               datas, n_buffers, maxsize / sizeof(float));
113
    }
114
 
115
    outio->buffer_id = outb->id;
116
@@ -820,6 +817,7 @@
117
 {
118
    struct impl *this;
119
    struct port *port;
120
+   uint32_t i;
121
 
122
    spa_return_val_if_fail(factory != NULL, -EINVAL);
123
    spa_return_val_if_fail(handle != NULL, -EINVAL);
124
@@ -836,6 +834,13 @@
125
    if (this->cpu)
126
        this->cpu_flags = spa_cpu_get_flags(this->cpu);
127
 
128
+   for (i = 0; info && i < info->n_items; i++) {
129
+       const char *k = info->items[i].key;
130
+       const char *s = info->items[i].value;
131
+       if (spa_streq(k, "clock.quantum-limit"))
132
+           spa_atou32(s, &this->quantum_limit, 0);
133
+   }
134
+
135
    spa_hook_list_init(&this->hooks);
136
 
137
    this->node.iface = SPA_INTERFACE_INIT(
138
pipewire-0.3.43.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c Changed
48
 
1
@@ -75,7 +75,6 @@
2
    props->volume = DEFAULT_VOLUME;
3
 }
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_BUFFERS    16
7
 #define MAX_PORTS  1
8
 
9
@@ -119,6 +118,8 @@
10
    struct spa_loop *data_loop;
11
    struct spa_system *data_system;
12
 
13
+   uint32_t quantum_limit;
14
+
15
    uint64_t info_all;
16
    struct spa_node_info info;
17
    struct spa_param_info params[2];
18
@@ -646,7 +647,7 @@
19
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
20
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
21
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
22
-                           MAX_SAMPLES * port->bpf,
23
+                           this->quantum_limit * port->bpf,
24
                            16 * port->bpf,
25
                            INT32_MAX),
26
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->bpf));
27
@@ -1014,6 +1015,7 @@
28
 {
29
    struct impl *this;
30
    struct port *port;
31
+   uint32_t i;
32
 
33
    spa_return_val_if_fail(factory != NULL, -EINVAL);
34
    spa_return_val_if_fail(handle != NULL, -EINVAL);
35
@@ -1027,6 +1029,12 @@
36
    this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
37
    this->data_system = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataSystem);
38
 
39
+   for (i = 0; info && i < info->n_items; i++) {
40
+       const char *k = info->items[i].key;
41
+       const char *s = info->items[i].value;
42
+       if (spa_streq(k, "clock.quantum-limit"))
43
+           spa_atou32(s, &this->quantum_limit, 0);
44
+   }
45
    spa_hook_list_init(&this->hooks);
46
 
47
    this->node.iface = SPA_INTERFACE_INIT(
48
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c Changed
10
 
1
@@ -1088,7 +1088,7 @@
2
    }
3
 
4
    d = spa_bt_device_find_by_address(backend->monitor, endpoint->remote_address, endpoint->local_address);
5
-   if (!d) {
6
+   if (!d || !d->adapter) {
7
        spa_log_debug(backend->log, "No device for %s", endpoint->path);
8
        return DBUS_HANDLER_RESULT_HANDLED;
9
    }
10
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-native.c Changed
127
 
1
@@ -137,6 +137,8 @@
2
    unsigned int msbc_supported_by_hfp:1;
3
    unsigned int hfp_ag_switching_codec:1;
4
    unsigned int hfp_ag_initial_codec_setup:2;
5
+   unsigned int cind_call_active:1;
6
+   unsigned int cind_call_notify:1;
7
    enum hfp_hf_state hf_state;
8
    enum hsp_hs_state hs_state;
9
    unsigned int codec;
10
@@ -676,6 +678,22 @@
11
    }
12
 }
13
 
14
+static void rfcomm_hfp_ag_set_cind(struct rfcomm *rfcomm, bool call_active)
15
+{
16
+   if (rfcomm->profile != SPA_BT_PROFILE_HFP_HF)
17
+       return;
18
+
19
+   if (call_active == rfcomm->cind_call_active)
20
+       return;
21
+
22
+   rfcomm->cind_call_active = call_active;
23
+
24
+   if (!rfcomm->cind_call_notify)
25
+       return;
26
+
27
+   rfcomm_send_reply(rfcomm, "+CIEV: 2,%d", rfcomm->cind_call_active);
28
+}
29
+
30
 static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
31
 {
32
    struct impl *backend = rfcomm->backend;
33
@@ -762,12 +780,20 @@
34
        rfcomm_send_reply(rfcomm, "+CIND:(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2))");
35
        rfcomm_send_reply(rfcomm, "OK");
36
    } else if (spa_strstartswith(buf, "AT+CIND?")) {
37
-       rfcomm_send_reply(rfcomm, "+CIND: 0,0,0,0");
38
+       rfcomm_send_reply(rfcomm, "+CIND: 0,%d,0,0", rfcomm->cind_call_active);
39
        rfcomm_send_reply(rfcomm, "OK");
40
    } else if (spa_strstartswith(buf, "AT+CMER")) {
41
+       int mode, keyp, disp, ind;
42
+
43
        rfcomm->slc_configured = true;
44
        rfcomm_send_reply(rfcomm, "OK");
45
 
46
+       rfcomm->cind_call_active = false;
47
+       if (sscanf(buf, "AT+CMER= %d , %d , %d , %d", &mode, &keyp, &disp, &ind) == 4)
48
+           rfcomm->cind_call_notify = ind ? true : false;
49
+       else
50
+           rfcomm->cind_call_notify = false;
51
+
52
        /* switch codec to mSBC by sending unsolicited +BCS message */
53
        if (rfcomm->codec_negotiation_supported && rfcomm->msbc_supported_by_hfp) {
54
            spa_log_debug(backend->log, "RFCOMM initial codec setup");
55
@@ -785,7 +811,6 @@
56
                rfcomm_emit_volume_changed(rfcomm, -1, SPA_BT_VOLUME_INVALID);
57
            }
58
        }
59
-
60
    } else if (!rfcomm->slc_configured) {
61
        spa_log_warn(backend->log, "RFCOMM receive command before SLC completed: %s", buf);
62
        rfcomm_send_reply(rfcomm, "ERROR");
63
@@ -829,6 +854,11 @@
64
        rfcomm_send_reply(rfcomm, "OK");
65
        if (was_switching_codec)
66
            spa_bt_device_emit_codec_switched(rfcomm->device, 0);
67
+   } else if (spa_strstartswith(buf, "AT+BIA=")) {
68
+       /* We only support 'call' indicator, which HFP 4.35.1 defines as
69
+          always active (assuming CMER enabled it), so we don't need to
70
+          parse anything here. */
71
+       rfcomm_send_reply(rfcomm, "OK");
72
    } else if (sscanf(buf, "AT+VGM=%u", &gain) == 1) {
73
        if (gain <= SPA_BT_VOLUME_HS_MAX) {
74
            if (!rfcomm->broken_mic_hw_volume)
75
@@ -1172,12 +1202,17 @@
76
 static int sco_acquire_cb(void *data, bool optional)
77
 {
78
    struct spa_bt_transport *t = data;
79
+   struct transport_data *td = t->user_data;
80
    struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
81
    int sock;
82
    socklen_t len;
83
 
84
    spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t);
85
 
86
+#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
87
+   rfcomm_hfp_ag_set_cind(td->rfcomm, true);
88
+#endif
89
+
90
    if (optional || t->fd > 0)
91
        sock = t->fd;
92
    else
93
@@ -1217,10 +1252,15 @@
94
 static int sco_release_cb(void *data)
95
 {
96
    struct spa_bt_transport *t = data;
97
+   struct transport_data *td = t->user_data;
98
    struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
99
 
100
    spa_log_info(backend->log, "Transport %s released", t->path);
101
 
102
+#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
103
+   rfcomm_hfp_ag_set_cind(td->rfcomm, false);
104
+#endif
105
+
106
    if (t->sco_io) {
107
        spa_bt_sco_io_destroy(t->sco_io);
108
        t->sco_io = NULL;
109
@@ -1689,7 +1729,7 @@
110
    dbus_message_iter_get_basic(&it[0], &path);
111
 
112
    d = spa_bt_device_find(backend->monitor, path);
113
-   if (d == NULL) {
114
+   if (d == NULL || d->adapter == NULL) {
115
        spa_log_warn(backend->log, "unknown device for path %s", path);
116
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
117
    }
118
@@ -1816,7 +1856,7 @@
119
    dbus_message_iter_get_basic(&it[0], &path);
120
 
121
    d = spa_bt_device_find(backend->monitor, path);
122
-   if (d == NULL) {
123
+   if (d == NULL || d->adapter == NULL) {
124
        spa_log_warn(backend->log, "unknown device for path %s", path);
125
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
126
    }
127
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-ofono.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-ofono.c Changed
10
 
1
@@ -364,7 +364,7 @@
2
    }
3
 
4
    d = spa_bt_device_find_by_address(backend->monitor, remote_address, local_address);
5
-   if (!d) {
6
+   if (!d || !d->adapter) {
7
        spa_log_error(backend->log, "Device doesn’t exist for %s", path);
8
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9
    }
10
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
201
 
1
@@ -229,7 +229,7 @@
2
        device->battery_pending_call = NULL;
3
    }
4
 
5
-   if (!device->adapter->has_battery_provider || !device->has_battery)
6
+   if (!device->adapter || !device->adapter->has_battery_provider || !device->has_battery)
7
        return;
8
 
9
    spa_log_debug(device->monitor->log, "Removing virtual battery: %s", device->battery_path);
10
@@ -694,6 +694,22 @@
11
    return 0;
12
 }
13
 
14
+static void adapter_update_devices(struct spa_bt_adapter *adapter)
15
+{
16
+   struct spa_bt_monitor *monitor = adapter->monitor;
17
+   struct spa_bt_device *device;
18
+
19
+   /*
20
+    * Update devices when new adapter appears.
21
+    * Devices may appear on DBus before or after the adapter does.
22
+    */
23
+
24
+   spa_list_for_each(device, &monitor->device_list, link) {
25
+       if (device->adapter == NULL && spa_streq(device->adapter_path, adapter->path))
26
+           device->adapter = adapter;
27
+   }
28
+}
29
+
30
 static void adapter_register_player(struct spa_bt_adapter *adapter)
31
 {
32
    if (adapter->player_registered || !adapter->monitor->dummy_avrcp_player)
33
@@ -785,11 +801,20 @@
34
    return d;
35
 }
36
 
37
+static void device_free(struct spa_bt_device *device);
38
+
39
 static void adapter_free(struct spa_bt_adapter *adapter)
40
 {
41
    struct spa_bt_monitor *monitor = adapter->monitor;
42
+   struct spa_bt_device *d, *td;
43
+
44
    spa_log_debug(monitor->log, "%p", adapter);
45
 
46
+   /* Devices should be destroyed before their assigned adapter */
47
+   spa_list_for_each_safe(d, td, &monitor->device_list, link)
48
+       if (d->adapter == adapter)
49
+           device_free(d);
50
+
51
    spa_bt_player_destroy(adapter->dummy_player);
52
 
53
    spa_list_remove(&adapter->link);
54
@@ -1159,7 +1184,7 @@
55
 }
56
 
57
 #define DEVICE_RECONNECT_TIMEOUT_SEC 2
58
-#define DEVICE_PROFILE_TIMEOUT_SEC 3
59
+#define DEVICE_PROFILE_TIMEOUT_SEC 6
60
 
61
 static void device_timer_event(struct spa_source *source)
62
 {
63
@@ -1238,19 +1263,34 @@
64
 {
65
    struct spa_bt_monitor *monitor = device->monitor;
66
    uint32_t connected_profiles = device->connected_profiles;
67
+   uint32_t direction_masks[2] = {
68
+       SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_AUDIO,
69
+       SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY,
70
+   };
71
+   bool direction_connected = false;
72
+   bool all_connected;
73
+   size_t i;
74
 
75
    if (connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT)
76
        connected_profiles |= SPA_BT_PROFILE_HEADSET_HEAD_UNIT;
77
    if (connected_profiles & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY)
78
        connected_profiles |= SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY;
79
 
80
+   for (i = 0; i < SPA_N_ELEMENTS(direction_masks); ++i) {
81
+       uint32_t mask = direction_masks[i] & device->profiles;
82
+       if (mask && (connected_profiles & mask) == mask)
83
+           direction_connected = true;
84
+   }
85
+
86
+   all_connected = (device->profiles & connected_profiles) == device->profiles;
87
+
88
    spa_log_debug(monitor->log, "device %p: profiles %08x %08x %d",
89
            device, device->profiles, connected_profiles, device->added);
90
 
91
    if (connected_profiles == 0 && spa_list_is_empty(&device->codec_switch_list)) {
92
        device_stop_timer(device);
93
        device_connected(monitor, device, BT_DEVICE_DISCONNECTED);
94
-   } else if (force || (device->profiles & connected_profiles) == device->profiles) {
95
+   } else if (force || direction_connected || all_connected) {
96
        device_stop_timer(device);
97
        device_connected(monitor, device, BT_DEVICE_CONNECTED);
98
    } else {
99
@@ -1349,7 +1389,7 @@
100
 
101
                device->adapter = adapter_find(monitor, value);
102
                if (device->adapter == NULL) {
103
-                   spa_log_warn(monitor->log, "unknown adapter %s", value);
104
+                   spa_log_info(monitor->log, "unknown adapter %s", value);
105
                }
106
            }
107
            else if (spa_streq(key, "Icon")) {
108
@@ -1455,6 +1495,15 @@
109
    return 0;
110
 }
111
 
112
+static bool device_props_ready(struct spa_bt_device *device)
113
+{
114
+   /*
115
+    * In some cases, BlueZ device props may be missing part of
116
+    * the information required when the interface first appears.
117
+    */
118
+   return device->adapter && device->address;
119
+}
120
+
121
 bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec)
122
 {
123
    struct spa_bt_monitor *monitor = device->monitor;
124
@@ -2091,9 +2140,16 @@
125
                spa_bt_transport_set_state(transport, spa_bt_transport_state_from_string(value));
126
            }
127
            else if (spa_streq(key, "Device")) {
128
-               transport->device = spa_bt_device_find(monitor, value);
129
-               if (transport->device == NULL)
130
-                   spa_log_warn(monitor->log, "could not find device %s", value);
131
+               struct spa_bt_device *device = spa_bt_device_find(monitor, value);
132
+               if (transport->device != device) {
133
+                   if (transport->device != NULL)
134
+                       spa_list_remove(&transport->device_link);
135
+                   transport->device = device;
136
+                   if (device != NULL)
137
+                       spa_list_append(&device->transport_list, &transport->device_link);
138
+                   else
139
+                       spa_log_warn(monitor->log, "could not find device %s", value);
140
+               }
141
            }
142
        }
143
        else if (spa_streq(key, "Codec")) {
144
@@ -2874,7 +2930,6 @@
145
    DBusMessageIter it[2];
146
    DBusMessage *r;
147
    struct spa_bt_transport *transport;
148
-   bool is_new = false;
149
    const struct a2dp_codec *codec;
150
    int profile;
151
 
152
@@ -2897,9 +2952,8 @@
153
    dbus_message_iter_recurse(&it[0], &it[1]);
154
 
155
    transport = spa_bt_transport_find(monitor, transport_path);
156
-   is_new = transport == NULL;
157
 
158
-   if (is_new) {
159
+   if (transport == NULL) {
160
        char *tpath = strdup(transport_path);
161
 
162
        transport = spa_bt_transport_create(monitor, tpath, 0);
163
@@ -2928,14 +2982,10 @@
164
    transport->a2dp_codec = codec;
165
    transport_update_props(transport, &it[1], NULL);
166
 
167
-   if (transport->device == NULL) {
168
+   if (transport->device == NULL || transport->device->adapter == NULL) {
169
        spa_log_warn(monitor->log, "no device found for transport");
170
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
171
    }
172
-   spa_bt_device_add_profile(transport->device, transport->profile);
173
-
174
-   if (is_new)
175
-       spa_list_append(&transport->device->transport_list, &transport->device_link);
176
 
177
    device_update_last_bluez_action_time(transport->device);
178
 
179
@@ -2966,6 +3016,8 @@
180
    spa_log_info(monitor->log, "%p: %s validate conf channels:%d",
181
            monitor, path, transport->n_channels);
182
 
183
+   spa_bt_device_add_profile(transport->device, transport->profile);
184
+
185
    spa_bt_device_connect_profile(transport->device, transport->profile);
186
 
187
    /* Sync initial volumes */
188
@@ -3585,6 +3637,7 @@
189
        adapter_update_props(a, props_iter, NULL);
190
        adapter_register_application(a);
191
        adapter_register_player(a);
192
+       adapter_update_devices(a);
193
    }
194
    else if (spa_streq(interface_name, BLUEZ_PROFILE_MANAGER_INTERFACE)) {
195
        if (monitor->backends[BACKEND_NATIVE])
196
@@ -3607,6 +3660,9 @@
197
        device_update_props(d, props_iter, NULL);
198
        d->reconnect_state = BT_DEVICE_RECONNECT_INIT;
199
 
200
+       if (!device_props_ready(d))
201
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
149
 
1
@@ -137,6 +137,7 @@
2
 
3
    uint32_t profile;
4
    unsigned int switching_codec:1;
5
+   unsigned int save_profile:1;
6
    uint32_t prev_bt_connected_profiles;
7
 
8
    const struct a2dp_codec **supported_codecs;
9
@@ -757,7 +758,7 @@
10
 static bool validate_profile(struct impl *this, uint32_t profile,
11
        enum spa_bluetooth_audio_codec codec);
12
 
13
-static int set_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_audio_codec codec)
14
+static int set_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_audio_codec codec, bool save)
15
 {
16
    if (!validate_profile(this, profile, codec)) {
17
        spa_log_warn(this->log, "trying to set invalid profile %d, codec %d, %08x %08x",
18
@@ -766,6 +767,8 @@
19
        return -EINVAL;
20
    }
21
 
22
+   this->save_profile = save;
23
+
24
    if (this->profile == profile &&
25
        (this->profile != DEVICE_PROFILE_A2DP || codec == this->props.codec) &&
26
        (this->profile != DEVICE_PROFILE_HSP_HFP || codec == this->props.codec))
27
@@ -1104,6 +1107,8 @@
28
    /* If default profile is set to HSP/HFP, first try those and exit if found. */
29
    if (this->bt_dev->settings != NULL) {
30
        const char *str = spa_dict_lookup(this->bt_dev->settings, "bluez5.profile");
31
+       if (spa_streq(str, "off"))
32
+           goto off;
33
        if (spa_streq(str, "headset-head-unit") && set_initial_hsp_hfp_profile(this))
34
            return;
35
    }
36
@@ -1126,6 +1131,7 @@
37
    if (set_initial_hsp_hfp_profile(this))
38
        return;
39
 
40
+off:
41
    spa_log_debug(this->log, "initial profile off");
42
 
43
    this->profile = DEVICE_PROFILE_OFF;
44
@@ -1133,7 +1139,8 @@
45
 }
46
 
47
 static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *b,
48
-       uint32_t id, uint32_t index, uint32_t profile_index, enum spa_bluetooth_audio_codec codec)
49
+       uint32_t id, uint32_t index, uint32_t profile_index, enum spa_bluetooth_audio_codec codec,
50
+       bool current)
51
 {
52
    struct spa_bt_device *device = this->bt_dev;
53
    struct spa_pod_frame f[2];
54
@@ -1266,6 +1273,10 @@
55
        }
56
        spa_pod_builder_pop(b, &f[1]);
57
    }
58
+   if (current) {
59
+                spa_pod_builder_prop(b, SPA_PARAM_PROFILE_save, 0);
60
+                spa_pod_builder_bool(b, this->save_profile);
61
+   }
62
 
63
    if (name_and_codec)
64
        free(name_and_codec);
65
@@ -1282,7 +1293,7 @@
66
    uint8_t buffer[1024];
67
 
68
    spa_pod_builder_init(&b, buffer, sizeof(buffer));
69
-   return (build_profile(this, &b, 0, 0, profile, codec) != NULL);
70
+   return (build_profile(this, &b, 0, 0, profile, codec, false) != NULL);
71
 }
72
 
73
 static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b,
74
@@ -1597,7 +1608,7 @@
75
        case DEVICE_PROFILE_AG:
76
        case DEVICE_PROFILE_A2DP:
77
        case DEVICE_PROFILE_HSP_HFP:
78
-           param = build_profile(this, &b, id, result.index, profile, codec);
79
+           param = build_profile(this, &b, id, result.index, profile, codec, false);
80
            if (param == NULL)
81
                goto next;
82
            break;
83
@@ -1613,7 +1624,7 @@
84
        switch (result.index) {
85
        case 0:
86
            index = get_index_from_profile(this, this->profile, this->props.codec);
87
-           param = build_profile(this, &b, id, index, this->profile, this->props.codec);
88
+           param = build_profile(this, &b, id, index, this->profile, this->props.codec, true);
89
            if (param == NULL)
90
                return 0;
91
            break;
92
@@ -1858,13 +1869,15 @@
93
        uint32_t idx, next;
94
        uint32_t profile;
95
        enum spa_bluetooth_audio_codec codec;
96
+       bool save = false;
97
 
98
        if (param == NULL)
99
            return -EINVAL;
100
 
101
        if ((res = spa_pod_parse_object(param,
102
                SPA_TYPE_OBJECT_ParamProfile, NULL,
103
-               SPA_PARAM_PROFILE_index, SPA_POD_Int(&idx))) < 0) {
104
+               SPA_PARAM_PROFILE_index, SPA_POD_Int(&idx),
105
+               SPA_PARAM_PROFILE_save, SPA_POD_OPT_Bool(&save))) < 0) {
106
            spa_log_warn(this->log, "can't parse profile");
107
            spa_debug_pod(0, NULL, param);
108
            return res;
109
@@ -1874,8 +1887,8 @@
110
        if (profile == SPA_ID_INVALID)
111
            return -EINVAL;
112
 
113
-       spa_log_debug(this->log, "setting profile %d codec:%d", profile, codec);
114
-       return set_profile(this, profile, codec);
115
+       spa_log_debug(this->log, "setting profile %d codec:%d save:%d", profile, codec, (int)save);
116
+       return set_profile(this, profile, codec, save);
117
    }
118
    case SPA_PARAM_Route:
119
    {
120
@@ -1927,6 +1940,8 @@
121
            return res;
122
        }
123
 
124
+       spa_log_debug(this->log, "setting props codec:%d", codec_id);
125
+
126
        if (codec_id == SPA_ID_INVALID)
127
            return 0;
128
 
129
@@ -1934,16 +1949,16 @@
130
            size_t j;
131
            for (j = 0; j < this->supported_codec_count; ++j) {
132
                if (this->supported_codecs[j]->id == codec_id) {
133
-                   return set_profile(this, this->profile, codec_id);
134
+                   return set_profile(this, this->profile, codec_id, true);
135
                }
136
            }
137
        } else if (this->profile == DEVICE_PROFILE_HSP_HFP) {
138
            if (codec_id == SPA_BLUETOOTH_AUDIO_CODEC_CVSD &&
139
                    spa_bt_device_supports_hfp_codec(this->bt_dev, HFP_AUDIO_CODEC_CVSD) == 1) {
140
-               return set_profile(this, this->profile, codec_id);
141
+               return set_profile(this, this->profile, codec_id, true);
142
            } else if (codec_id == SPA_BLUETOOTH_AUDIO_CODEC_MSBC &&
143
                    spa_bt_device_supports_hfp_codec(this->bt_dev, HFP_AUDIO_CODEC_MSBC) == 1) {
144
-               return set_profile(this, this->profile, codec_id);
145
+               return set_profile(this, this->profile, codec_id, true);
146
            }
147
        }
148
        return -EINVAL;
149
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/quirks.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/quirks.c Changed
19
 
1
@@ -332,7 +332,7 @@
2
    }
3
 
4
    /* Adapter */
5
-   if (this->adapter_rules) {
6
+   if (this->adapter_rules && adapter) {
7
        uint32_t no_features = 0;
8
        int nitems = 0;
9
        char vendor_id[64], product_id[64], address[64];
10
@@ -357,7 +357,7 @@
11
    }
12
 
13
    /* Device */
14
-   if (this->device_rules) {
15
+   if (this->device_rules && device) {
16
        uint32_t no_features = 0;
17
        int nitems = 0;
18
        char vendor_id[64], product_id[64], version_id[64], address[64];
19
pipewire-0.3.43.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.44.tar.gz/spa/plugins/support/loop.c Changed
10
 
1
@@ -187,7 +187,7 @@
2
    int32_t filled;
3
    uint32_t avail, idx, offset, l0;
4
 
5
-   if (pthread_equal(impl->thread, pthread_self()))
6
+   if (impl->thread == 0 || pthread_equal(impl->thread, pthread_self()))
7
        return loop_invoke_inthread(impl, func, seq, data, size, block, user_data);
8
 
9
    filled = spa_ringbuffer_get_write_index(&impl->buffer, &idx);
10
pipewire-0.3.43.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.44.tar.gz/spa/plugins/support/null-audio-sink.c Changed
46
 
1
@@ -70,7 +70,6 @@
2
 #define DEFAULT_CHANNELS   2
3
 #define DEFAULT_RATE       44100
4
 
5
-#define MAX_SAMPLES    8192
6
 #define MAX_BUFFERS    16
7
 #define MAX_PORTS  1
8
 
9
@@ -107,6 +106,8 @@
10
    struct spa_loop *data_loop;
11
    struct spa_system *data_system;
12
 
13
+   uint32_t quantum_limit;
14
+
15
    struct props props;
16
 
17
    uint64_t info_all;
18
@@ -538,7 +539,7 @@
19
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
20
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(port->blocks),
21
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
22
-                           MAX_SAMPLES * port->bpf,
23
+                           this->quantum_limit * port->bpf,
24
                            16 * port->bpf,
25
                            INT32_MAX),
26
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->bpf));
27
@@ -856,7 +857,6 @@
28
        spa_log_error(this->log, "a data_system is needed");
29
        return -EINVAL;
30
    }
31
-
32
    spa_hook_list_init(&this->hooks);
33
 
34
    this->node.iface = SPA_INTERFACE_INIT(
35
@@ -904,7 +904,9 @@
36
    for (i = 0; info && i < info->n_items; i++) {
37
        const char *k = info->items[i].key;
38
        const char *s = info->items[i].value;
39
-       if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) {
40
+       if (spa_streq(k, "clock.quantum-limit")) {
41
+           spa_atou32(s, &this->quantum_limit, 0);
42
+       } else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) {
43
            this->props.channels = atoi(s);
44
        } else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) {
45
            this->props.rate = atoi(s);
46
pipewire-0.3.43.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.44.tar.gz/spa/plugins/v4l2/v4l2-udev.c Changed
29
 
1
@@ -311,18 +311,17 @@
2
        }
3
    }
4
 
5
-   str = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
6
+   str = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
7
    if (!(str && *str)) {
8
-       str = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
9
+       str = udev_device_get_property_value(dev, "ID_MODEL_ENC");
10
        if (!(str && *str)) {
11
-           str = udev_device_get_property_value(dev, "ID_MODEL_ENC");
12
-           if (!(str && *str)) {
13
-               str = udev_device_get_property_value(dev, "ID_MODEL");
14
-           } else {
15
-               char *t = alloca(strlen(str) + 1);
16
-               unescape(str, t);
17
-               str = t;
18
-           }
19
+           str = udev_device_get_property_value(dev, "ID_MODEL");
20
+           if (!(str && *str))
21
+               str = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
22
+       } else {
23
+           char *t = alloca(strlen(str) + 1);
24
+           unescape(str, t);
25
+           str = t;
26
        }
27
    }
28
    if (str && *str)
29
pipewire-0.3.43.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.44.tar.gz/spa/plugins/volume/volume.c Changed
48
 
1
@@ -53,7 +53,6 @@
2
    props->mute = DEFAULT_MUTE;
3
 }
4
 
5
-#define MAX_SAMPLES     8192
6
 #define MAX_BUFFERS     16
7
 
8
 struct buffer {
9
@@ -90,6 +89,7 @@
10
    struct spa_node node;
11
 
12
    struct spa_log *log;
13
+   uint32_t quantum_limit;
14
 
15
    uint64_t info_all;
16
    struct spa_node_info info;
17
@@ -386,7 +386,7 @@
18
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
19
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
20
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
21
-                           MAX_SAMPLES * this->bpf,
22
+                           this->quantum_limit * this->bpf,
23
                            16 * this->bpf,
24
                            INT32_MAX),
25
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->bpf));
26
@@ -777,6 +777,7 @@
27
 {
28
    struct impl *this;
29
    struct port *port;
30
+   uint32_t i;
31
 
32
    spa_return_val_if_fail(factory != NULL, -EINVAL);
33
    spa_return_val_if_fail(handle != NULL, -EINVAL);
34
@@ -788,6 +789,13 @@
35
 
36
    this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
37
 
38
+   for (i = 0; info && i < info->n_items; i++) {
39
+       const char *k = info->items[i].key;
40
+       const char *s = info->items[i].value;
41
+       if (spa_streq(k, "clock.quantum-limit"))
42
+           spa_atou32(s, &this->quantum_limit, 0);
43
+   }
44
+
45
    spa_hook_list_init(&this->hooks);
46
 
47
    this->node.iface = SPA_INTERFACE_INIT(
48
pipewire-0.3.43.tar.gz/spa/tests/meson.build -> pipewire-0.3.44.tar.gz/spa/tests/meson.build Changed
32
 
1
@@ -9,15 +9,16 @@
2
                             '-name', '*.h',
3
                             '-not', '-name', 'type-info.h',
4
                             '-type', 'f',
5
-                            '-printf', '%P\n')
6
+                            '-printf', '%P\n',
7
+                            check: false)
8
   foreach spa_header : spa_headers.stdout().split('\n')
9
     if spa_header.endswith('.h')  # skip empty lines
10
       ext = have_cpp ? 'cpp' : 'c'
11
-      c = configuration_data()
12
-      c.set('INCLUDE', spa_header)
13
       src = configure_file(input: 'spa-include-test-template.c',
14
-                          output: 'spa-include-test-@0@.@1@'.format(spa_header.underscorify(), ext),
15
-                          configuration: c)
16
+                           output: 'spa-include-test-@0@.@1@'.format(spa_header.underscorify(), ext),
17
+                           configuration: {
18
+                             'INCLUDE': spa_header,
19
+                           })
20
       executable('spa-include-test-@0@'.format(spa_header.underscorify()),
21
                  src,
22
                  dependencies: [ spa_dep ],
23
@@ -40,7 +41,7 @@
24
       install_dir : installed_tests_execdir,
25
     ),
26
     env : [
27
-      'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')),
28
+      'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')),
29
     ]
30
   )
31
 
32
pipewire-0.3.43.tar.gz/spa/tests/stress-ringbuffer.c -> pipewire-0.3.44.tar.gz/spa/tests/stress-ringbuffer.c Changed
11
 
1
@@ -13,7 +13,8 @@
2
 
3
 #ifdef __FreeBSD__
4
 #include <sys/param.h>
5
-#if __FreeBSD_version < 1400043
6
+#if (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400043) \
7
+    || (__FreeBSD_version < 1300523)
8
 static int sched_getcpu(void) { return -1; };
9
 #endif
10
 #endif
11
pipewire-0.3.43.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/client-rt.conf.in Changed
37
 
1
@@ -9,6 +9,8 @@
2
     #mem.allow-mlock = true
3
     #mem.mlock-all   = false
4
     log.level        = 0
5
+
6
+    #default.clock.quantum-limit = 8192
7
 }
8
 
9
 context.spa-libs = {
10
@@ -32,13 +34,12 @@
11
     # If ifexists is given, the module is ignored when it is not found.
12
     # If nofail is given, module initialization failures are ignored.
13
     #
14
-    # Uses RTKit to boost the data thread priority.
15
-    { name = libpipewire-module-rtkit
16
+    # Uses realtime scheduling to boost the audio thread priorities
17
+    { name = libpipewire-module-rt
18
         args = {
19
-            #nice.level   = -11
20
             #rt.prio      = 88
21
-            #rt.time.soft = 2000000
22
-            #rt.time.hard = 2000000
23
+            #rt.time.soft = -1
24
+            #rt.time.hard = -1
25
         }
26
         flags = [ ifexists nofail ]
27
     }
28
@@ -75,7 +76,7 @@
29
     #node.latency          = 1024/48000
30
     #node.autoconnect      = true
31
     #resample.quality      = 4
32
-    #channelmix.normalize  = false
33
+    #channelmix.normalize  = true
34
     #channelmix.mix-lfe    = true
35
     #channelmix.upmix      = false
36
     #channelmix.lfe-cutoff = 0
37
pipewire-0.3.43.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/client.conf.in Changed
19
 
1
@@ -9,6 +9,8 @@
2
     #mem.allow-mlock = true
3
     #mem.mlock-all   = false
4
     log.level        = 0
5
+
6
+    #default.clock.quantum-limit = 8192
7
 }
8
 
9
 context.spa-libs = {
10
@@ -65,7 +67,7 @@
11
     #node.latency          = 1024/48000
12
     #node.autoconnect      = true
13
     #resample.quality      = 4
14
-    #channelmix.normalize  = false
15
+    #channelmix.normalize  = true
16
     #channelmix.mix-lfe    = false
17
     #channelmix.upmix      = false
18
     #channelmix.lfe-cutoff = 0
19
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/demonic.conf Changed
19
 
1
@@ -19,13 +19,12 @@
2
 }
3
 
4
 context.modules = [
5
-    # Uses RTKit to boost the data thread priority.
6
-    { name = libpipewire-module-rtkit
7
+    # Uses realtime scheduling to boost the audio thread priorities
8
+    { name = libpipewire-module-rt
9
         args = {
10
-            #nice.level   = -11
11
             #rt.prio      = 88
12
-            #rt.time.soft = 2000000
13
-            #rt.time.hard = 2000000
14
+            #rt.time.soft = -1
15
+            #rt.time.hard = -1
16
         }
17
         flags = [ ifexists nofail ]
18
     }
19
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf Changed
17
 
1
@@ -12,12 +12,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-eq6.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-eq6.conf Changed
17
 
1
@@ -12,12 +12,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf Changed
17
 
1
@@ -13,12 +13,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf Changed
17
 
1
@@ -12,12 +12,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf Changed
17
 
1
@@ -12,12 +12,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/source-rnnoise.conf Changed
17
 
1
@@ -12,12 +12,11 @@
2
 }
3
 
4
 context.modules = [
5
-    { name = libpipewire-module-rtkit
6
+    { name = libpipewire-module-rt
7
         args = {
8
-            #nice.level   = -11
9
             #rt.prio      = 88
10
-            #rt.time.soft = 2000000
11
-            #rt.time.hard = 2000000
12
+            #rt.time.soft = -1
13
+            #rt.time.hard = -1
14
         }
15
         flags = [ ifexists nofail ]
16
     }
17
pipewire-0.3.43.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/jack.conf.in Changed
23
 
1
@@ -9,6 +9,8 @@
2
     #mem.allow-mlock = true
3
     #mem.mlock-all   = false
4
     log.level        = 0
5
+
6
+    #default.clock.quantum-limit = 8192
7
 }
8
 
9
 context.spa-libs = {
10
@@ -35,10 +37,9 @@
11
     # Boost the data thread priority.
12
     { name = libpipewire-module-rt
13
         args = {
14
-            #nice.level   = -11
15
             #rt.prio      = 88
16
-            #rt.time.soft = 2000000
17
-            #rt.time.hard = 2000000
18
+            #rt.time.soft = -1
19
+            #rt.time.hard = -1
20
         }
21
         flags = [ ifexists nofail ]
22
     }
23
pipewire-0.3.43.tar.gz/src/daemon/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/meson.build Changed
9
 
1
@@ -68,6 +68,7 @@
2
  'client.conf',
3
  'client-rt.conf',
4
  'jack.conf',
5
+ 'minimal.conf',
6
  'pipewire-pulse.conf',
7
 ]
8
 
9
pipewire-0.3.44.tar.gz/src/daemon/minimal.conf.in Added
201
 
1
@@ -0,0 +1,297 @@
2
+# Simple daemon 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
+context.properties = {
8
+    ## Configure properties in the system.
9
+    #library.name.system                   = support/libspa-support
10
+    #context.data-loop.library.name.system = support/libspa-support
11
+    #support.dbus                          = true
12
+    #link.max-buffers                      = 64
13
+    link.max-buffers                       = 16                       # version < 3 clients can't handle more
14
+    #mem.warn-mlock                        = false
15
+    #mem.allow-mlock                       = true
16
+    #mem.mlock-all                         = false
17
+    #clock.power-of-two-quantum            = true
18
+    #log.level                             = 2
19
+    #cpu.zero.denormals                    = true
20
+
21
+    core.daemon = true              # listening for socket connections
22
+    core.name   = pipewire-0        # core name and socket name
23
+
24
+    ## Properties for the DSP configuration.
25
+    #default.clock.rate          = 48000
26
+    #default.clock.allowed-rates = [ 48000 ]
27
+    #default.clock.quantum       = 1024
28
+    #default.clock.min-quantum   = 32
29
+    #default.clock.max-quantum   = 2048
30
+    #default.clock.quantum-limit = 8192
31
+    #default.video.width         = 640
32
+    #default.video.height        = 480
33
+    #default.video.rate.num      = 25
34
+    #default.video.rate.denom    = 1
35
+    #
36
+    settings.check-quantum      = true
37
+    settings.check-rate         = true
38
+    #
39
+    # These overrides are only applied when running in a vm.
40
+    vm.overrides = {
41
+        default.clock.min-quantum = 1024
42
+    }
43
+}
44
+
45
+context.spa-libs = {
46
+    #<factory-name regex> = <library-name>
47
+    #
48
+    # Used to find spa factory names. It maps an spa factory name
49
+    # regular expression to a library name that should contain
50
+    # that factory.
51
+    #
52
+    audio.convert.* = audioconvert/libspa-audioconvert
53
+    api.alsa.*      = alsa/libspa-alsa
54
+    support.*       = support/libspa-support
55
+}
56
+
57
+context.modules = [
58
+    #{ name = <module-name>
59
+    #    [ args  = { <key> = <value> ... } ]
60
+    #    [ flags = [ [ ifexists ] [ nofail ] ]
61
+    #}
62
+    #
63
+    # Loads a module with the given parameters.
64
+    # If ifexists is given, the module is ignored when it is not found.
65
+    # If nofail is given, module initialization failures are ignored.
66
+    #
67
+
68
+    # Uses realtime scheduling to boost the audio thread priorities. This uses
69
+    # RTKit if the user doesn't have permission to use regular realtime
70
+    # scheduling.
71
+    { name = libpipewire-module-rt
72
+        args = {
73
+            nice.level   = -11
74
+            #rt.prio      = 88
75
+            #rt.time.soft = -1
76
+            #rt.time.hard = -1
77
+        }
78
+        flags = [ ifexists nofail ]
79
+    }
80
+
81
+    # The native communication protocol.
82
+    { name = libpipewire-module-protocol-native }
83
+
84
+    # The profile module. Allows application to access profiler
85
+    # and performance data. It provides an interface that is used
86
+    # by pw-top and pw-profiler.
87
+    { name = libpipewire-module-profiler }
88
+
89
+    # Allows applications to create metadata objects. It creates
90
+    # a factory for Metadata objects.
91
+    { name = libpipewire-module-metadata }
92
+
93
+    # Creates a factory for making nodes that run in the
94
+    # context of the PipeWire server.
95
+    { name = libpipewire-module-spa-node-factory }
96
+
97
+    # Allows creating nodes that run in the context of the
98
+    # client. Is used by all clients that want to provide
99
+    # data to PipeWire.
100
+    { name = libpipewire-module-client-node }
101
+
102
+    # The access module can perform access checks and block
103
+    # new clients.
104
+    { name = libpipewire-module-access
105
+        args = {
106
+            # access.allowed to list an array of paths of allowed
107
+            # apps.
108
+            #access.allowed = [
109
+            #    @session_manager_path@
110
+            #]
111
+
112
+            # An array of rejected paths.
113
+            #access.rejected = [ ]
114
+
115
+            # An array of paths with restricted access.
116
+            #access.restricted = [ ]
117
+
118
+            # Anything not in the above lists gets assigned the
119
+            # access.force permission.
120
+            #access.force = flatpak
121
+        }
122
+    }
123
+
124
+    # Makes a factory for wrapping nodes in an adapter with a
125
+    # converter and resampler.
126
+    { name = libpipewire-module-adapter }
127
+
128
+    # Makes a factory for creating links between ports.
129
+    { name = libpipewire-module-link-factory }
130
+]
131
+
132
+context.objects = [
133
+    #{ factory = <factory-name>
134
+    #    [ args  = { <key> = <value> ... } ]
135
+    #    [ flags = [ [ nofail ] ]
136
+    #}
137
+    #
138
+    # Creates an object from a PipeWire factory with the given parameters.
139
+    # If nofail is given, errors are ignored (and no object is created).
140
+    #
141
+    #{ factory = spa-node-factory   args = { factory.name = videotestsrc node.name = videotestsrc Spa:Pod:Object:Param:Props:patternType = 1 } }
142
+    #{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags = [ nofail ] }
143
+    #{ factory = spa-device-factory args = { factory.name = api.alsa.enum.udev } }
144
+    #{ factory = spa-node-factory   args = { factory.name = api.alsa.seq.bridge node.name = Internal-MIDI-Bridge } }
145
+    #{ factory = adapter            args = { factory.name = audiotestsrc node.name = my-test } }
146
+    #{ factory = spa-node-factory   args = { factory.name = api.vulkan.compute.source node.name = my-compute-source } }
147
+
148
+    # Make a default metadata store
149
+    { factory = metadata            args = { metadata.name = default } }
150
+
151
+    # A default dummy driver. This handles nodes marked with the "node.always-driver"
152
+    # property when no other driver is currently active. JACK clients need this.
153
+    { factory = spa-node-factory
154
+        args = {
155
+            factory.name    = support.node.driver
156
+            node.name       = Dummy-Driver
157
+            node.group      = pipewire.dummy
158
+            priority.driver = 20000
159
+        }
160
+    }
161
+    { factory = spa-node-factory
162
+        args = {
163
+            factory.name    = support.node.driver
164
+            node.name       = Freewheel-Driver
165
+            priority.driver = 19000
166
+            node.group      = pipewire.freewheel
167
+            node.freewheel  = true
168
+        }
169
+    }
170
+
171
+    # This creates a single PCM source device for the given
172
+    # alsa device path hw:0. You can change source to sink
173
+    # to make a sink in the same way.
174
+    { factory = adapter
175
+        args = {
176
+            factory.name           = api.alsa.pcm.source
177
+            node.name              = "system"
178
+            node.description       = "system"
179
+            media.class            = "Audio/Source"
180
+            api.alsa.path          = "hw:0"
181
+            #api.alsa.period-size   = 0
182
+            #api.alsa.period-num    = 0
183
+            #api.alsa.headroom      = 0
184
+            #api.alsa.start-delay   = 0
185
+            #api.alsa.disable-mmap  = false
186
+            #api.alsa.disable-batch = false
187
+       #api.alsa.use-chmap     = false
188
+       #api.alsa.multirate     = true
189
+       #latency.internal.rate  = 0
190
+       #latency.internal.ns    = 0
191
+       #clock.name             = api.alsa.0
192
+            node.suspend-on-idle   = true
193
+            #audio.format           = "S32"
194
+            #audio.rate             = 48000
195
+            #audio.allowed-rates    = [ ]
196
+            #audio.channels         = 4
197
+            #audio.position         = [ FL FR RL RR ]
198
+            #resample.quality       = 4
199
+            resample.disable       = true
200
+            #monitor.channel-volumes = false
201
pipewire-0.3.43.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
93
 
1
@@ -9,6 +9,8 @@
2
     #mem.allow-mlock = true
3
     #mem.mlock-all   = false
4
     #log.level       = 2
5
+
6
+    #default.clock.quantum-limit = 8192
7
 }
8
 
9
 context.spa-libs = {
10
@@ -17,12 +19,12 @@
11
 }
12
 
13
 context.modules = [
14
-    { name = libpipewire-module-rtkit
15
+    { name = libpipewire-module-rt
16
         args = {
17
-            #nice.level   = -11
18
+            nice.level   = -11
19
             #rt.prio      = 88
20
-            #rt.time.soft = 2000000
21
-            #rt.time.hard = 2000000
22
+            #rt.time.soft = -1
23
+            #rt.time.hard = -1
24
         }
25
         flags = [ ifexists nofail ]
26
     }
27
@@ -42,7 +44,7 @@
28
                 #"tcp:127.0.0.1:8888"               # IPv4 on a single address
29
                 #
30
                 #{ address = "tcp:4713"             # address
31
-                #  max-clients = 64                 # maximume number of clients
32
+                #  max-clients = 64                 # maximum number of clients
33
                 #  listen-backlog = 32              # backlog in the server listen queue
34
                 #  client.access = "restricted"     # permissions for clients
35
                 #}
36
@@ -73,8 +75,55 @@
37
     #node.latency          = 1024/48000
38
     #node.autoconnect      = true
39
     #resample.quality      = 4
40
-    #channelmix.normalize  = false
41
+    #channelmix.normalize  = true
42
     #channelmix.mix-lfe    = false
43
     #channelmix.upmix      = false
44
     #channelmix.lfe-cutoff = 0
45
 }
46
+
47
+# client/stream specific properties
48
+pulse.rules = [
49
+    {
50
+        matches = [
51
+            {
52
+                # all keys must match the value. ~ starts regex.
53
+                #client.name                = "Firefox"
54
+                #application.process.binary = "teams"
55
+                #application.name           = "~speech-dispatcher.*"
56
+            }
57
+        ]
58
+        actions = {
59
+            update-props = {
60
+                #node.latency = 512/48000
61
+            }
62
+            # Possible quirks:"
63
+            #    force-s16-info                 forces sink and source info as S16 format
64
+            #    remove-capture-dont-move       removes the capture DONT_MOVE flag
65
+            #quirks = [ ]
66
+        }
67
+    }
68
+    {
69
+        # skype does not want to use devices that don't have an S16 sample format.
70
+        matches = [
71
+             { application.process.binary = "teams" }
72
+             { application.process.binary = "skypeforlinux" }
73
+        ]
74
+        actions = { quirks = [ force-s16-info ] }
75
+    }
76
+    {
77
+        # firefox marks the capture streams as don't move and then they
78
+        # can't be moved with pavucontrol or other tools.
79
+        matches = [ { application.process.binary = "firefox" } ]
80
+        actions = { quirks = [ remove-capture-dont-move ] }
81
+    }
82
+    {
83
+        # speech dispatcher asks for too small latency and then underruns.
84
+        matches = [ { application.name = "~speech-dispatcher*" } ]
85
+        actions = {
86
+            update-props = {
87
+                pulse.min.req          = 1024/48000     # 21ms
88
+                pulse.min.quantum      = 1024/48000     # 21ms
89
+            }
90
+        }
91
+    }
92
+]
93
pipewire-0.3.43.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/pipewire.conf.in Changed
72
 
1
@@ -25,12 +25,16 @@
2
     #default.clock.allowed-rates = [ 48000 ]
3
     #default.clock.quantum       = 1024
4
     #default.clock.min-quantum   = 32
5
-    #default.clock.max-quantum   = 8192
6
+    #default.clock.max-quantum   = 2048
7
+    #default.clock.quantum-limit = 8192
8
     #default.video.width         = 640
9
     #default.video.height        = 480
10
     #default.video.rate.num      = 25
11
     #default.video.rate.denom    = 1
12
     #
13
+    #settings.check-quantum      = false
14
+    #settings.check-rate         = false
15
+    #
16
     # These overrides are only applied when running in a vm.
17
     vm.overrides = {
18
         default.clock.min-quantum = 1024
19
@@ -67,28 +71,19 @@
20
     # If nofail is given, module initialization failures are ignored.
21
     #
22
 
23
-    # Uses RTKit to boost the data thread priority.
24
-    { name = libpipewire-module-rtkit
25
+    # Uses realtime scheduling to boost the audio thread priorities. This uses
26
+    # RTKit if the user doesn't have permission to use regular realtime
27
+    # scheduling.
28
+    { name = libpipewire-module-rt
29
         args = {
30
-            #nice.level   = -11
31
+            nice.level    = -11
32
             #rt.prio      = 88
33
-            #rt.time.soft = 2000000
34
-            #rt.time.hard = 2000000
35
+            #rt.time.soft = -1
36
+            #rt.time.hard = -1
37
         }
38
         flags = [ ifexists nofail ]
39
     }
40
 
41
-    # Set thread priorities without using RTKit.
42
-    #{ name = libpipewire-module-rt
43
-    #    args = {
44
-    #        nice.level   = -11
45
-    #        rt.prio      = 88
46
-    #        rt.time.soft = 2000000
47
-    #        rt.time.hard = 2000000
48
-    #    }
49
-    #    flags = [ ifexists nofail ]
50
-    #}
51
-
52
     # The native communication protocol.
53
     { name = libpipewire-module-protocol-native }
54
 
55
@@ -156,6 +151,16 @@
56
 
57
     # Provides factories to make session manager objects.
58
     { name = libpipewire-module-session-manager }
59
+
60
+    # Use libcanberra to play X11 Bell
61
+    #{ name = libpipewire-module-x11-bell
62
+    #  args = {
63
+    #      #sink.name = "@DEFAULT_SINK@"
64
+    #      #sample.name = "bell-window-system"
65
+    #      #x11.display = null
66
+    #      #x11.xauthority = null
67
+    #  }
68
+    #}
69
 ]
70
 
71
 context.objects = [
72
pipewire-0.3.43.tar.gz/src/daemon/systemd/system/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/systemd/system/meson.build Changed
10
 
1
@@ -1,4 +1,7 @@
2
-systemd_system_services_dir = systemd.get_variable(pkgconfig: 'systemdsystemunitdir', pkgconfig_define : [ 'rootprefix', prefix])
3
+systemd_system_services_dir = systemd.get_variable('systemdsystemunitdir', pkgconfig_define : [ 'rootprefix', prefix])
4
+if get_option('systemd-system-unit-dir') != ''
5
+  systemd_system_services_dir = get_option('systemd-system-unit-dir')
6
+endif
7
 
8
 install_data(sources : 'pipewire.socket',
9
              install_dir : systemd_system_services_dir)
10
pipewire-0.3.43.tar.gz/src/daemon/systemd/user/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/systemd/user/meson.build Changed
7
 
1
@@ -1,4 +1,4 @@
2
-systemd_user_services_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', pkgconfig_define : [ 'prefix', prefix])
3
+systemd_user_services_dir = systemd.get_variable('systemduserunitdir', pkgconfig_define : [ 'prefix', prefix])
4
 if get_option('systemd-user-unit-dir') != ''
5
   systemd_user_services_dir = get_option('systemd-user-unit-dir')
6
 endif
7
pipewire-0.3.43.tar.gz/src/modules/meson.build -> pipewire-0.3.44.tar.gz/src/modules/meson.build Changed
89
 
1
@@ -21,12 +21,12 @@
2
   'module-protocol-simple.c',
3
   'module-pulse-tunnel.c',
4
   'module-rt.c',
5
-  'module-rtkit.c',
6
   'module-raop-discover.c',
7
   'module-session-manager.c',
8
   'module-zeroconf-discover.c',
9
   'module-roc-source.c',
10
   'module-roc-sink.c',
11
+  'module-x11-bell.c',
12
 ]
13
 
14
 pipewire_module_access = shared_library('pipewire-module-access', [ 'module-access.c' ],
15
@@ -137,21 +137,18 @@
16
   dependencies : [spa_dep, mathlib, dl_lib, pipewire_dep],
17
 )
18
 
19
-build_module_rt = build_machine.system() == 'linux'
20
+build_module_rt = dbus_dep.found()
21
 if build_module_rt
22
 pipewire_module_rt = shared_library('pipewire-module-rt', [ 'module-rt.c' ],
23
   include_directories : [configinc],
24
   install : true,
25
   install_dir : modules_install_dir,
26
   install_rpath: modules_install_dir,
27
-  dependencies : [dl_lib, pipewire_dep],
28
+  dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep],
29
 )
30
-endif
31
-summary({'rt': build_module_rt}, bool_yn: true, section: 'Optional Modules')
32
-
33
-build_module_rtkit = dbus_dep.found()
34
-if build_module_rtkit
35
-pipewire_module_rtkit = shared_library('pipewire-module-rtkit', [ 'module-rtkit.c' ],
36
+# TODO: This serves as a temporary alias to prevent breaking existing setups
37
+#       while `module-rtkit` is being migrated to `module-rt`
38
+pipewire_module_rtkit = shared_library('pipewire-module-rtkit', [ 'module-rt.c' ],
39
   include_directories : [configinc],
40
   install : true,
41
   install_dir : modules_install_dir,
42
@@ -159,7 +156,7 @@
43
   dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep],
44
 )
45
 endif
46
-summary({'rtkit': build_module_rtkit}, bool_yn: true, section: 'Optional Modules')
47
+summary({'rt': build_module_rt}, bool_yn: true, section: 'Optional Modules')
48
 
49
 build_module_portal = dbus_dep.found()
50
 if build_module_portal
51
@@ -259,6 +256,7 @@
52
   'module-protocol-pulse/modules/module-switch-on-connect.c',
53
   'module-protocol-pulse/modules/module-tunnel-sink.c',
54
   'module-protocol-pulse/modules/module-tunnel-source.c',
55
+  'module-protocol-pulse/modules/module-x11-bell.c',
56
   'module-protocol-pulse/modules/module-zeroconf-discover.c',
57
 ]
58
 
59
@@ -370,9 +368,9 @@
60
     install_dir : installed_tests_execdir,
61
   ),
62
   env : [
63
-    'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')),
64
-    'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'confdatadir')),
65
-    'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'moduledir')),
66
+    'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')),
67
+    'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable('confdatadir')),
68
+    'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable('moduledir')),
69
   ]
70
 )
71
 
72
@@ -488,3 +486,16 @@
73
 endif
74
 summary({'roc-sink': build_module_roc}, bool_yn: true, section: 'Optional Modules')
75
 summary({'roc-source': build_module_roc}, bool_yn: true, section: 'Optional Modules')
76
+
77
+build_module_x11_bell = x11_dep.found() and canberra_dep.found()
78
+if build_module_x11_bell
79
+pipewire_module_x11_bell = shared_library('pipewire-module-x11-bell',
80
+  [ 'module-x11-bell.c' ],
81
+  include_directories : [configinc],
82
+  install : true,
83
+  install_dir : modules_install_dir,
84
+  install_rpath: modules_install_dir,
85
+  dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, canberra_dep],
86
+)
87
+endif
88
+summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules')
89
pipewire-0.3.43.tar.gz/src/modules/module-adapter/adapter.c -> pipewire-0.3.44.tar.gz/src/modules/module-adapter/adapter.c Changed
201
 
1
@@ -38,10 +38,15 @@
2
 #include <spa/utils/string.h>
3
 #include <spa/utils/type-info.h>
4
 #include <spa/param/format.h>
5
+#include <spa/param/audio/format.h>
6
+#include <spa/param/audio/format-utils.h>
7
 #include <spa/param/format-utils.h>
8
 #include <spa/debug/types.h>
9
+#include <spa/debug/pod.h>
10
+#include <spa/utils/json-pod.h>
11
 
12
 #include "pipewire/pipewire.h"
13
+#include "pipewire/private.h"
14
 
15
 #include "modules/spa/spa-node.h"
16
 
17
@@ -170,6 +175,29 @@
18
    .port_init = node_port_init,
19
 };
20
 
21
+static int handle_node_param(struct pw_impl_node *node, const char *key, const char *value)
22
+{
23
+   const struct spa_type_info *ti;
24
+   uint8_t buffer[1024];
25
+   struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
26
+   struct spa_pod *pod;
27
+   int res;
28
+
29
+   ti = spa_debug_type_find_short(spa_type_param, key);
30
+   if (ti == NULL)
31
+       return -ENOENT;
32
+
33
+   if ((res = spa_json_to_pod(&b, 0, ti, value, strlen(value))) < 0)
34
+       return res;
35
+
36
+   if ((pod = spa_pod_builder_deref(&b, 0)) == NULL)
37
+       return -ENOSPC;
38
+
39
+   if ((res = pw_impl_node_set_param(node, ti->type, 0, pod)) < 0)
40
+       return res;
41
+
42
+   return 0;
43
+}
44
 
45
 static int find_format(struct pw_impl_node *node, enum pw_direction direction,
46
        uint32_t *media_type, uint32_t *media_subtype)
47
@@ -201,6 +229,113 @@
48
    return 0;
49
 }
50
 
51
+static int do_auto_port_config(struct node *n, const char *str)
52
+{
53
+   uint32_t state = 0, i;
54
+   uint8_t buffer[4096];
55
+   struct spa_pod_builder b;
56
+#define POSITION_PRESERVE 0
57
+#define POSITION_AUX 1
58
+#define POSITION_UNKNOWN 2
59
+   int res, position = POSITION_PRESERVE;
60
+   struct spa_pod *param;
61
+   uint32_t media_type, media_subtype;
62
+   bool have_format = false, monitor = false;
63
+   struct spa_audio_info format = { 0, };
64
+   enum spa_param_port_config_mode mode = SPA_PARAM_PORT_CONFIG_MODE_none;
65
+   struct spa_json it[2];
66
+   char key[1024], val[256];
67
+
68
+   spa_json_init(&it[0], str, strlen(str));
69
+   if (spa_json_enter_object(&it[0], &it[1]) <= 0)
70
+       return -EINVAL;
71
+
72
+   while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
73
+       if (spa_json_get_string(&it[1], val, sizeof(val)) <= 0)
74
+           break;
75
+
76
+       if (spa_streq(key, "mode")) {
77
+           mode = spa_debug_type_find_type_short(spa_type_param_port_config_mode, val);
78
+           if (mode == SPA_ID_INVALID)
79
+               mode = SPA_PARAM_PORT_CONFIG_MODE_none;
80
+       } else if (spa_streq(key, "monitor")) {
81
+           monitor = spa_atob(val);
82
+       } else if (spa_streq(key, "position")) {
83
+           if (spa_streq(val, "unknown"))
84
+               position = POSITION_UNKNOWN;
85
+           else if (spa_streq(val, "aux"))
86
+               position = POSITION_AUX;
87
+           else
88
+               position = POSITION_PRESERVE;
89
+       }
90
+        }
91
+
92
+   while (true) {
93
+       struct spa_audio_info info = { 0, };
94
+       struct spa_pod *position = NULL;
95
+       uint32_t n_position = 0;
96
+
97
+       spa_pod_builder_init(&b, buffer, sizeof(buffer));
98
+       if ((res = spa_node_port_enum_params_sync(pw_impl_node_get_implementation(n->follower),
99
+                   n->direction == PW_DIRECTION_INPUT ?
100
+                       SPA_DIRECTION_INPUT :
101
+                       SPA_DIRECTION_OUTPUT, 0,
102
+                   SPA_PARAM_EnumFormat, &state,
103
+                   NULL, &param, &b)) != 1)
104
+           break;
105
+
106
+       if ((res = spa_format_parse(param, &media_type, &media_subtype)) < 0)
107
+           continue;
108
+
109
+       if (media_type != SPA_MEDIA_TYPE_audio ||
110
+           media_subtype != SPA_MEDIA_SUBTYPE_raw)
111
+           continue;
112
+
113
+       spa_pod_object_fixate((struct spa_pod_object*)param);
114
+
115
+       if (spa_pod_parse_object(param,
116
+               SPA_TYPE_OBJECT_Format, NULL,
117
+               SPA_FORMAT_AUDIO_format,        SPA_POD_Id(&info.info.raw.format),
118
+               SPA_FORMAT_AUDIO_rate,          SPA_POD_Int(&info.info.raw.rate),
119
+               SPA_FORMAT_AUDIO_channels,      SPA_POD_Int(&info.info.raw.channels),
120
+               SPA_FORMAT_AUDIO_position,      SPA_POD_OPT_Pod(&position)) < 0)
121
+           continue;
122
+
123
+       if (position != NULL)
124
+           n_position = spa_pod_copy_array(position, SPA_TYPE_Id,
125
+                   info.info.raw.position, SPA_AUDIO_MAX_CHANNELS);
126
+       if (n_position == 0 || n_position != info.info.raw.channels)
127
+           SPA_FLAG_SET(info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED);
128
+
129
+       if (format.info.raw.channels >= info.info.raw.channels)
130
+           continue;
131
+
132
+       format = info;
133
+       have_format = true;
134
+   }
135
+   if (!have_format)
136
+       return -ENOENT;
137
+
138
+   if (position == POSITION_AUX) {
139
+       for (i = 0; i < format.info.raw.channels; i++)
140
+           format.info.raw.position[i] = SPA_AUDIO_CHANNEL_START_Aux + i;
141
+   } else if (position == POSITION_UNKNOWN) {
142
+       for (i = 0; i < format.info.raw.channels; i++)
143
+           format.info.raw.position[i] = SPA_AUDIO_CHANNEL_UNKNOWN;
144
+   }
145
+
146
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
147
+   param = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &format.info.raw);
148
+   param = spa_pod_builder_add_object(&b,
149
+       SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
150
+       SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(n->direction),
151
+       SPA_PARAM_PORT_CONFIG_mode,      SPA_POD_Id(mode),
152
+       SPA_PARAM_PORT_CONFIG_monitor,   SPA_POD_Bool(monitor),
153
+       SPA_PARAM_PORT_CONFIG_format,    SPA_POD_Pod(param));
154
+   pw_impl_node_set_param(n->node, SPA_PARAM_PortConfig, 0, param);
155
+
156
+   return 0;
157
+}
158
 
159
 struct pw_impl_node *pw_adapter_new(struct pw_context *context,
160
        struct pw_impl_node *follower,
161
@@ -214,6 +349,8 @@
162
    enum pw_direction direction;
163
    int res;
164
    uint32_t media_type, media_subtype;
165
+   const struct spa_dict_item *it;
166
+   struct pw_properties *copy;
167
 
168
    info = pw_impl_node_get_info(follower);
169
    if (info == NULL) {
170
@@ -272,11 +409,16 @@
171
        goto error;
172
    }
173
 
174
+   copy = pw_properties_new(NULL, NULL);
175
+   spa_dict_for_each(it, &props->dict) {
176
+       if (!spa_strstartswith(it->key, "node.param.") &&
177
+           !spa_strstartswith(it->key, "port.param."))
178
+           pw_properties_set(copy, it->key, it->value);
179
+   }
180
    node = pw_spa_node_load(context,
181
                factory_name,
182
                PW_SPA_NODE_FLAG_ACTIVATE | PW_SPA_NODE_FLAG_NO_REGISTER,
183
-               pw_properties_copy(props),
184
-               sizeof(struct node) + user_data_size);
185
+               copy, sizeof(struct node) + user_data_size);
186
         if (node == NULL) {
187
        res = -errno;
188
        pw_log_error("can't load spa node: %m");
189
@@ -298,6 +440,15 @@
190
 
191
    pw_impl_node_add_listener(node, &n->node_listener, &node_events, n);
192
 
193
+   if ((str = pw_properties_get(props, "adapter.auto-port-config")) != NULL)
194
+       do_auto_port_config(n, str);
195
+
196
+   spa_dict_for_each(it, &props->dict) {
197
+       if (spa_strstartswith(it->key, "node.param.")) {
198
+           if ((res = handle_node_param(node, &it->key[11], it->value)) < 0)
199
+               pw_log_warn("can't set node param: %s", spa_strerror(res));
200
+       }
201
pipewire-0.3.43.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.44.tar.gz/src/modules/module-client-node/client-node.c Changed
27
 
1
@@ -219,6 +219,8 @@
2
    if (mix_id >= len) {
3
        size_t need = sizeof(struct mix) * (mix_id + 1 - len);
4
        void *ptr = pw_array_add(&p->mix, need);
5
+       if (ptr == NULL)
6
+           return NULL;
7
        memset(ptr, 0, need);
8
    }
9
    mix = pw_array_get_unchecked(&p->mix, mix_id, struct mix);
10
@@ -1388,8 +1390,15 @@
11
        return -ENOMEM;
12
 
13
    mix->id = pw_map_insert_new(&impl->io_map, NULL);
14
-   if (mix->id == SPA_ID_INVALID)
15
+   if (mix->id == SPA_ID_INVALID) {
16
+       m->valid = false;
17
        return -errno;
18
+   }
19
+   if (mix->id > MAX_AREAS) {
20
+       pw_map_remove(&impl->io_map, mix->id);
21
+       m->valid = false;
22
+       return -ENOMEM;
23
+   }
24
 
25
    mix->io = SPA_PTROFF(impl->io_areas->map->ptr,
26
            mix->id * sizeof(struct spa_io_buffers), void);
27
pipewire-0.3.43.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.44.tar.gz/src/modules/module-echo-cancel.c Changed
167
 
1
@@ -109,6 +109,15 @@
2
  *
3
  */
4
 
5
+/**
6
+ * .--------.     .---------.     .--------.     .----------.     .-------.
7
+ * | source | --> | capture | --> |        | --> |  source  | --> |  app  |
8
+ * '--------'     '---------'     | echo   |     '----------'     '-------'
9
+ *                                | cancel |
10
+ * .--------.     .---------.     |        |     .----------.     .--------.
11
+ * |  app   | --> |  sink   | --> |        | --> | playback | --> |  sink  |
12
+ * '--------'     '---------'     '--------'     '----------'     '--------'
13
+ */
14
 #define NAME "echo-cancel"
15
 
16
 PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
17
@@ -117,6 +126,7 @@
18
 /* Hopefully this is enough for any combination of AEC engine and resampler
19
  * input requirement for rate matching */
20
 #define MAX_BUFSIZE_MS 100
21
+#define DELAY_MS 0
22
 
23
 static const struct spa_dict_item module_props[] = {
24
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
25
@@ -126,6 +136,8 @@
26
                "[ audio.rate=<sample rate> ] "
27
                "[ audio.channels=<number of channels> ] "
28
                "[ audio.position=<channel map> ] "
29
+               "[ buffer.max_size=<max buffer size in ms> ] "
30
+               "[ buffer.play_delay=<play delay in ms> ] "
31
                "[ aec.method=<aec method> ] "
32
                "[ aec.args=<aec arguments> ] "
33
                "[ source.props=<properties> ] "
34
@@ -166,6 +178,7 @@
35
    void *play_buffer[SPA_AUDIO_MAX_CHANNELS];
36
    uint32_t play_ringsize;
37
    struct spa_ringbuffer play_ring;
38
+   struct spa_ringbuffer play_delayed_ring;
39
    struct spa_io_rate_match *play_rate_match;
40
 
41
    void *out_buffer[SPA_AUDIO_MAX_CHANNELS];
42
@@ -181,6 +194,9 @@
43
 
44
    unsigned int do_disconnect:1;
45
    unsigned int unloading:1;
46
+
47
+   uint32_t max_buffer_size;
48
+   uint32_t buffer_delay;
49
 };
50
 
51
 static void do_unload_module(void *obj, void *data, int res, uint32_t id)
52
@@ -202,13 +218,15 @@
53
    struct pw_buffer *pout;
54
    float rec_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)];
55
    float play_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)];
56
+   float play_delayed_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)];
57
    float out_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)];
58
    const float *rec[impl->info.channels];
59
    const float *play[impl->info.channels];
60
+   const float *play_delayed[impl->info.channels];
61
    float *out[impl->info.channels];
62
    struct spa_data *dd;
63
    uint32_t i, size;
64
-   uint32_t rindex, pindex, oindex, avail;
65
+   uint32_t rindex, pindex, oindex, pdindex, avail;
66
    int32_t stride = 0;
67
 
68
    if ((pout = pw_stream_dequeue_buffer(impl->playback)) == NULL) {
69
@@ -222,12 +240,15 @@
70
 
71
    spa_ringbuffer_get_read_index(&impl->rec_ring, &rindex);
72
    spa_ringbuffer_get_read_index(&impl->play_ring, &pindex);
73
+   spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &pdindex);
74
 
75
    for (i = 0; i < impl->info.channels; i++) {
76
        /* captured samples, with echo from sink */
77
        rec[i] = &rec_buf[i][0];
78
        /* echo from sink */
79
        play[i] = &play_buf[i][0];
80
+       /* echo from sink delayed */
81
+       play_delayed[i] = &play_delayed_buf[i][0];
82
        /* filtered samples, without echo from sink */
83
        out[i] = &out_buf[i][0];
84
 
85
@@ -241,6 +262,11 @@
86
                impl->play_ringsize, pindex % impl->play_ringsize,
87
                (void *)play[i], size);
88
 
89
+       stride = 0;
90
+       spa_ringbuffer_read_data(&impl->play_delayed_ring, impl->play_buffer[i],
91
+               impl->play_ringsize, pdindex % impl->play_ringsize,
92
+               (void *)play_delayed[i], size);
93
+
94
        /* output to sink, just copy */
95
        dd = &pout->buffer->datas[i];
96
        memcpy(dd->data, play[i], size);
97
@@ -252,11 +278,12 @@
98
 
99
    spa_ringbuffer_read_update(&impl->rec_ring, rindex + size);
100
    spa_ringbuffer_read_update(&impl->play_ring, pindex + size);
101
+   spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + size);
102
 
103
    pw_stream_queue_buffer(impl->playback, pout);
104
 
105
    /* Now run the canceller */
106
-   echo_cancel_run(impl->aec_info, impl->aec, rec, play, out, size / sizeof(float));
107
+   echo_cancel_run(impl->aec_info, impl->aec, rec, play_delayed, out, size / sizeof(float));
108
 
109
    /* Next, copy over the output to the output ringbuffer */
110
    avail = spa_ringbuffer_get_write_index(&impl->out_ring, &oindex);
111
@@ -544,6 +571,9 @@
112
        spa_ringbuffer_get_read_index(&impl->play_ring, &rindex);
113
        spa_ringbuffer_read_update(&impl->play_ring, rindex + drop);
114
 
115
+       spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &rindex);
116
+       spa_ringbuffer_read_update(&impl->play_delayed_ring, rindex + drop);
117
+
118
        avail += drop;
119
    }
120
 
121
@@ -604,6 +634,7 @@
122
    struct spa_pod_builder b;
123
    struct pw_properties *props;
124
    const char *str;
125
+   uint32_t index;
126
 
127
    props = pw_properties_new(
128
            PW_KEY_NODE_NAME, "echo-cancel-capture",
129
@@ -710,9 +741,9 @@
130
            params, n_params)) < 0)
131
        return res;
132
 
133
-   impl->rec_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000;
134
-   impl->play_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000;
135
-   impl->out_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000;
136
+   impl->rec_ringsize = sizeof(float) * impl->max_buffer_size * impl->info.rate / 1000;
137
+   impl->play_ringsize = sizeof(float) * (impl->max_buffer_size + impl->buffer_delay) * impl->info.rate / 1000;
138
+   impl->out_ringsize = sizeof(float) * impl->max_buffer_size * impl->info.rate / 1000;
139
    for (i = 0; i < impl->info.channels; i++) {
140
        impl->rec_buffer[i] = malloc(impl->rec_ringsize);
141
        impl->play_buffer[i] = malloc(impl->play_ringsize);
142
@@ -720,8 +751,14 @@
143
    }
144
    spa_ringbuffer_init(&impl->rec_ring);
145
    spa_ringbuffer_init(&impl->play_ring);
146
+   spa_ringbuffer_init(&impl->play_delayed_ring);
147
    spa_ringbuffer_init(&impl->out_ring);
148
 
149
+   spa_ringbuffer_get_write_index(&impl->play_ring, &index);
150
+   spa_ringbuffer_write_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay) * impl->info.rate / 1000));
151
+   spa_ringbuffer_get_read_index(&impl->play_ring, &index);
152
+   spa_ringbuffer_read_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay) * impl->info.rate / 1000));
153
+
154
    return 0;
155
 }
156
 
157
@@ -997,6 +1034,9 @@
158
    copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
159
    copy_props(impl, props, PW_KEY_NODE_LATENCY);
160
 
161
+   impl->max_buffer_size = pw_properties_get_uint32(props,"buffer.max_size", MAX_BUFSIZE_MS);
162
+   impl->buffer_delay = pw_properties_get_uint32(props,"buffer.play_delay", DELAY_MS);
163
+
164
    pw_properties_free(props);
165
 
166
    pw_proxy_add_listener((struct pw_proxy*)impl->core,
167
pipewire-0.3.43.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.44.tar.gz/src/modules/module-filter-chain.c Changed
84
 
1
@@ -343,7 +343,7 @@
2
    char *col, *node_name, *port_name, *str;
3
    struct port *ports;
4
    const struct fc_descriptor *d;
5
-   uint32_t i, n_ports;
6
+   uint32_t i, n_ports, port_id = SPA_ID_INVALID;
7
 
8
    str = strdupa(name);
9
    col = strchr(str, ':');
10
@@ -359,6 +359,9 @@
11
    if (node == NULL)
12
        return NULL;
13
 
14
+   if (!spa_atou32(port_name, &port_id, 0))
15
+       port_id = SPA_ID_INVALID;
16
+
17
    if (FC_IS_PORT_INPUT(descriptor)) {
18
        if (FC_IS_PORT_CONTROL(descriptor)) {
19
            ports = node->control_port;
20
@@ -381,7 +384,8 @@
21
    d = node->desc->desc;
22
    for (i = 0; i < n_ports; i++) {
23
        struct port *port = &ports[i];
24
-       if (spa_streq(d->ports[port->p].name, port_name))
25
+       if (i == port_id ||
26
+           spa_streq(d->ports[port->p].name, port_name))
27
            return port;
28
    }
29
    return NULL;
30
@@ -1701,11 +1705,8 @@
31
    if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
32
        pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
33
 
34
-   if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
35
-       pw_properties_setf(props, PW_KEY_NODE_NAME, "filter-chain-%u", id);
36
    if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
37
-       pw_properties_set(props, PW_KEY_NODE_DESCRIPTION,
38
-               pw_properties_get(props, PW_KEY_NODE_NAME));
39
+       pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, "filter-chain-%u", id);
40
 
41
    if ((str = pw_properties_get(props, "capture.props")) != NULL)
42
        pw_properties_update_string(impl->capture_props, str, strlen(str));
43
@@ -1715,7 +1716,6 @@
44
    copy_props(impl, props, PW_KEY_AUDIO_RATE);
45
    copy_props(impl, props, PW_KEY_AUDIO_CHANNELS);
46
    copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
47
-   copy_props(impl, props, PW_KEY_NODE_NAME);
48
    copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
49
    copy_props(impl, props, PW_KEY_NODE_GROUP);
50
    copy_props(impl, props, PW_KEY_NODE_LINK_GROUP);
51
@@ -1726,18 +1726,25 @@
52
    parse_audio_info(impl->capture_props, &impl->capture_info);
53
    parse_audio_info(impl->playback_props, &impl->playback_info);
54
 
55
+   if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL)
56
+       pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME,
57
+               "input.filter-chain-%u", id);
58
+   if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL)
59
+       pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME,
60
+               "output.filter-chain-%u", id);
61
+
62
+   if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL)
63
+       pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input",
64
+               pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION));
65
+   if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL)
66
+       pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output",
67
+               pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION));
68
+
69
    if ((res = load_graph(&impl->graph, props)) < 0) {
70
        pw_log_error("can't load graph: %s", spa_strerror(res));
71
        goto error;
72
    }
73
 
74
-   if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL)
75
-       pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "filter input %s",
76
-               pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME));
77
-   if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL)
78
-       pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "filter output %s",
79
-               pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME));
80
-
81
    impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
82
    if (impl->core == NULL) {
83
        str = pw_properties_get(props, PW_KEY_REMOTE_NAME);
84
pipewire-0.3.43.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.44.tar.gz/src/modules/module-loopback.c Changed
53
 
1
@@ -461,11 +461,9 @@
2
    if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
3
        pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
4
 
5
-   if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
6
-       pw_properties_setf(props, PW_KEY_NODE_NAME, "loopback-%u", id);
7
    if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
8
-       pw_properties_set(props, PW_KEY_NODE_DESCRIPTION,
9
-               pw_properties_get(props, PW_KEY_NODE_NAME));
10
+       pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
11
+               "loopback-%u", id);
12
 
13
    if ((str = pw_properties_get(props, "capture.props")) != NULL)
14
        pw_properties_update_string(impl->capture_props, str, strlen(str));
15
@@ -475,25 +473,29 @@
16
    copy_props(impl, props, PW_KEY_AUDIO_RATE);
17
    copy_props(impl, props, PW_KEY_AUDIO_CHANNELS);
18
    copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
19
-   copy_props(impl, props, PW_KEY_NODE_NAME);
20
    copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
21
    copy_props(impl, props, PW_KEY_NODE_GROUP);
22
    copy_props(impl, props, PW_KEY_NODE_LINK_GROUP);
23
    copy_props(impl, props, PW_KEY_NODE_LATENCY);
24
    copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
25
+   copy_props(impl, props, PW_KEY_MEDIA_NAME);
26
+
27
+   if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL)
28
+       pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME,
29
+               "input.loopback-%u", id);
30
+   if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL)
31
+       pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME,
32
+               "output.loopback-%u", id);
33
 
34
    parse_audio_info(impl->capture_props, &impl->capture_info);
35
    parse_audio_info(impl->playback_props, &impl->playback_info);
36
 
37
    if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL)
38
-       pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME,
39
-               "loopback input %s",
40
-               pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME));
41
-
42
+       pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input",
43
+               pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION));
44
    if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL)
45
-       pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME,
46
-               "loopback output %s",
47
-               pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME));
48
+       pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output",
49
+               pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION));
50
 
51
    impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
52
    if (impl->core == NULL) {
53
pipewire-0.3.43.tar.gz/src/modules/module-metadata.c -> pipewire-0.3.44.tar.gz/src/modules/module-metadata.c Changed
90
 
1
@@ -74,43 +74,70 @@
2
               uint32_t new_id)
3
 {
4
    struct factory_data *data = _data;
5
+   struct pw_context *context = pw_impl_module_get_context(data->module);
6
    void *result;
7
-   struct pw_resource *metadata_resource;
8
-   struct pw_impl_client *client = pw_resource_get_client(resource);
9
+   struct pw_resource *metadata_resource = NULL;
10
+   struct pw_impl_client *client = resource ? pw_resource_get_client(resource) : NULL;
11
    int res;
12
 
13
-   metadata_resource = pw_resource_new(client, new_id, PW_PERM_ALL, type, version, 0);
14
-   if (metadata_resource == NULL) {
15
-       res = -errno;
16
-       goto error_resource;
17
-   }
18
+   if (properties == NULL)
19
+       properties = pw_properties_new(NULL, NULL);
20
+   if (properties == NULL)
21
+       return NULL;
22
+
23
+   pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
24
+           pw_impl_factory_get_info(data->this)->id);
25
+   pw_properties_setf(properties, PW_KEY_MODULE_ID, "%d",
26
+           pw_impl_module_get_info(data->module)->id);
27
+
28
+   if (pw_properties_get(properties, PW_KEY_METADATA_NAME) == NULL)
29
+       pw_properties_set(properties, PW_KEY_METADATA_NAME, "default");
30
+
31
+   if (client) {
32
+       metadata_resource = pw_resource_new(client, new_id, PW_PERM_ALL, type, version, 0);
33
+       if (metadata_resource == NULL) {
34
+           res = -errno;
35
+           goto error_resource;
36
+       }
37
 
38
-   if (properties) {
39
-       pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
40
-               pw_impl_factory_get_info(data->this)->id);
41
        pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
42
                pw_impl_client_get_info(client)->id);
43
-   }
44
 
45
-   result = pw_metadata_new(pw_impl_client_get_context(client), metadata_resource, properties);
46
-   if (result == NULL) {
47
-       res = -errno;
48
-       goto error_node;
49
+       result = pw_metadata_new(context, metadata_resource, properties);
50
+       if (result == NULL) {
51
+           properties = NULL;
52
+           res = -errno;
53
+           goto error_node;
54
+       }
55
+   } else {
56
+       result = pw_context_create_metadata(context, NULL, properties, 0);
57
+       if (result == NULL) {
58
+           properties = NULL;
59
+           res = -errno;
60
+           goto error_node;
61
+       }
62
+       pw_impl_metadata_register(result, NULL);
63
    }
64
    return result;
65
 
66
 error_resource:
67
    pw_log_error("can't create resource: %s", spa_strerror(res));
68
-   pw_resource_errorf_id(resource, new_id, res, "can't create resource: %s", spa_strerror(res));
69
+   if (resource)
70
+       pw_resource_errorf_id(resource, new_id, res,
71
+               "can't create resource: %s", spa_strerror(res));
72
    goto error_exit;
73
 error_node:
74
    pw_log_error("can't create metadata: %s", spa_strerror(res));
75
-   pw_resource_errorf_id(resource, new_id, res, "can't create metadata: %s", spa_strerror(res));
76
+   if (resource)
77
+       pw_resource_errorf_id(resource, new_id, res,
78
+               "can't create metadata: %s", spa_strerror(res));
79
    goto error_exit_free;
80
 
81
 error_exit_free:
82
-   pw_resource_remove(metadata_resource);
83
+   if (metadata_resource)
84
+       pw_resource_remove(metadata_resource);
85
 error_exit:
86
+   pw_properties_free(properties);
87
    errno = -res;
88
    return NULL;
89
 }
90
pipewire-0.3.43.tar.gz/src/modules/module-metadata/metadata.c -> pipewire-0.3.44.tar.gz/src/modules/module-metadata/metadata.c Changed
11
 
1
@@ -271,9 +271,6 @@
2
        return NULL;
3
    }
4
 
5
-   if (pw_properties_get(properties, PW_KEY_METADATA_NAME) == NULL)
6
-       pw_properties_set(properties, PW_KEY_METADATA_NAME, "default");
7
-
8
    pw_resource_install_marshal(resource, true);
9
 
10
    impl->global = pw_global_new(context,
11
pipewire-0.3.43.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.44.tar.gz/src/modules/module-profiler.c Changed
27
 
1
@@ -379,6 +379,10 @@
2
    struct pw_properties *props;
3
    struct impl *impl;
4
    struct pw_loop *main_loop = pw_context_get_main_loop(context);
5
+   static const char * const keys[] = {
6
+       PW_KEY_OBJECT_SERIAL,
7
+       NULL
8
+   };
9
 
10
    PW_LOG_TOPIC_INIT(mod_topic);
11
 
12
@@ -409,9 +413,14 @@
13
        free(impl);
14
        return -errno;
15
    }
16
+   pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", impl->global->id);
17
+   pw_properties_setf(impl->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64,
18
+           pw_global_get_serial(impl->global));
19
 
20
    impl->flush_timeout = pw_loop_add_timer(main_loop, flush_timeout, impl);
21
 
22
+   pw_global_update_keys(impl->global, &impl->properties->dict, keys);
23
+
24
    pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
25
 
26
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
27
pipewire-0.3.43.tar.gz/src/modules/module-protocol-native/connection.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-native/connection.c Changed
77
 
1
@@ -175,10 +175,37 @@
2
        pw_log_error("connection %p: could not recvmsg on fd:%d: %s", conn, conn->fd, strerror(res));
3
 }
4
 
5
+static size_t cmsg_data_length(const struct cmsghdr *cmsg)
6
+{
7
+   const void *begin = CMSG_DATA(cmsg);
8
+   const void *end = SPA_PTROFF(cmsg, cmsg->cmsg_len, void);
9
+
10
+   spa_assert(begin <= end);
11
+
12
+   return SPA_PTRDIFF(end, begin);
13
+}
14
+
15
+static void close_all_fds(struct msghdr *msg, struct cmsghdr *from)
16
+{
17
+   for (; from != NULL; from = CMSG_NXTHDR(msg, from)) {
18
+       if (from->cmsg_level != SOL_SOCKET || from->cmsg_type != SCM_RIGHTS)
19
+           continue;
20
+
21
+       size_t n_fds = cmsg_data_length(from) / sizeof(int);
22
+       for (size_t i = 0; i < n_fds; i++) {
23
+           const void *p = SPA_PTROFF(CMSG_DATA(from), sizeof(int) * i, void);
24
+           int fd;
25
+
26
+           memcpy(&fd, p, sizeof(fd));
27
+           close(fd);
28
+       }
29
+   }
30
+}
31
+
32
 static int refill_buffer(struct pw_protocol_native_connection *conn, struct buffer *buf)
33
 {
34
    ssize_t len;
35
-   struct cmsghdr *cmsg;
36
+   struct cmsghdr *cmsg = NULL;
37
    struct msghdr msg = { 0 };
38
    struct iovec iov[1];
39
    char cmsgbuf[CMSG_SPACE(MAX_FDS_MSG * sizeof(int))];
40
@@ -198,7 +225,7 @@
41
    while (true) {
42
        len = recvmsg(conn->fd, &msg, msg.msg_flags);
43
        if (msg.msg_flags & MSG_CTRUNC)
44
-           return -EPROTO;
45
+           goto cmsgs_truncated;
46
        if (len == 0 && avail != 0)
47
            return -EPIPE;
48
        else if (len < 0) {
49
@@ -218,10 +245,9 @@
50
        if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
51
            continue;
52
 
53
-       n_fds =
54
-           (cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) / sizeof(int);
55
+       n_fds = cmsg_data_length(cmsg) / sizeof(int);
56
        if (n_fds + buf->n_fds > MAX_FDS)
57
-           return -EPROTO;
58
+           goto too_many_fds;
59
        memcpy(&buf->fds[buf->n_fds], CMSG_DATA(cmsg), n_fds * sizeof(int));
60
        buf->n_fds += n_fds;
61
    }
62
@@ -234,6 +260,14 @@
63
 recv_error:
64
    handle_connection_error(conn, errno);
65
    return -errno;
66
+
67
+cmsgs_truncated:
68
+   close_all_fds(&msg, CMSG_FIRSTHDR(&msg));
69
+   return -EPROTO;
70
+
71
+too_many_fds:
72
+   close_all_fds(&msg, cmsg);
73
+   return -EPROTO;
74
 }
75
 
76
 static void clear_buffer(struct buffer *buf, bool fds)
77
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/client.c Changed
116
 
1
@@ -295,23 +295,34 @@
2
    return 0;
3
 }
4
 
5
-/* returns true if an event with the (mask, event, id) triplet should be dropped because it is redundant */
6
-static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t id)
7
+static bool drop_from_out_queue(struct client *client, struct message *m)
8
 {
9
-   struct impl *impl = client->impl;
10
-   struct message *m, *t, *first;
11
+   spa_assert(!spa_list_is_empty(&client->out_messages));
12
 
13
-   if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW)
14
+   struct message *first = spa_list_first(&client->out_messages, struct message, link);
15
+   if (m == first && client->out_index > 0)
16
        return false;
17
 
18
-   first = spa_list_first(&client->out_messages, struct message, link);
19
+   message_free(client->impl, m, true, false);
20
+
21
+   return true;
22
+}
23
+
24
+/* returns true if an event with the (mask, event, index) triplet should be dropped because it is redundant */
25
+static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t index)
26
+{
27
+   struct message *m, *t;
28
+
29
+   if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW)
30
+       return false;
31
 
32
+   /* NOTE: reverse iteration */
33
    spa_list_for_each_safe_reverse(m, t, &client->out_messages, link) {
34
        if (m->extra[0] != COMMAND_SUBSCRIBE_EVENT)
35
            continue;
36
        if ((m->extra[1] ^ event) & SUBSCRIPTION_EVENT_FACILITY_MASK)
37
            continue;
38
-       if (m->extra[2] != id)
39
+       if (m->extra[2] != index)
40
            continue;
41
 
42
        if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_REMOVE) {
43
@@ -319,25 +330,39 @@
44
             * point in keeping the old events regarding
45
             * entry in the queue. */
46
 
47
-           /* if the first message has already been partially sent, do not drop it */
48
-           if (m != first || client->out_index == 0) {
49
-               message_free(impl, m, true, false);
50
-               pw_log_debug("client %p: dropped redundant event due to remove event", client);
51
+           bool is_new = (m->extra[1] & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW;
52
+
53
+           if (drop_from_out_queue(client, m)) {
54
+               pw_log_debug("client %p: dropped redundant event due to remove event for object %u",
55
+                        client, index);
56
+
57
+               /* if the NEW event for the current object could successfully be dropped,
58
+                  there is no need to deliver the REMOVE event */
59
+               if (is_new)
60
+                   goto drop;
61
            }
62
+
63
+           /* stop if the NEW event for the current object is reached */
64
+           if (is_new)
65
+               break;
66
        }
67
 
68
        if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_CHANGE) {
69
            /* This object has changed. If a "new" or "change" event for
70
             * this object is still in the queue we can exit. */
71
-           pw_log_debug("client %p: dropped redundant event due to change event", client);
72
-           return true;
73
+           goto drop;
74
        }
75
    }
76
 
77
    return false;
78
+
79
+drop:
80
+   pw_log_debug("client %p: dropped redundant event for object %u", client, index);
81
+
82
+   return true;
83
 }
84
 
85
-int client_queue_subscribe_event(struct client *client, uint32_t mask, uint32_t event, uint32_t id)
86
+int client_queue_subscribe_event(struct client *client, uint32_t mask, uint32_t event, uint32_t index)
87
 {
88
    if (client->disconnect)
89
        return -ENOTCONN;
90
@@ -345,21 +370,21 @@
91
    if (!(client->subscribed & mask))
92
        return 0;
93
 
94
-   pw_log_debug("client %p: SUBSCRIBE event:%08x id:%u", client, event, id);
95
+   pw_log_debug("client %p: SUBSCRIBE event:%08x index:%u", client, event, index);
96
 
97
-   if (client_prune_subscribe_events(client, mask, event, id))
98
+   if (client_prune_subscribe_events(client, mask, event, index))
99
        return 0;
100
 
101
    struct message *reply = message_alloc(client->impl, -1, 0);
102
    reply->extra[0] = COMMAND_SUBSCRIBE_EVENT;
103
    reply->extra[1] = event;
104
-   reply->extra[2] = id;
105
+   reply->extra[2] = index;
106
 
107
    message_put(reply,
108
        TAG_U32, COMMAND_SUBSCRIBE_EVENT,
109
        TAG_U32, -1,
110
        TAG_U32, event,
111
-       TAG_U32, id,
112
+       TAG_U32, index,
113
        TAG_INVALID);
114
 
115
    return client_queue_message(client, reply);
116
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/collect.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/collect.c Changed
201
 
1
@@ -58,19 +58,41 @@
2
            continue;
3
        if (o->id == s->id)
4
            return o;
5
+       if (o->index == s->index)
6
+           return o;
7
        if (s->accumulate)
8
            s->accumulate(s, o);
9
        if (o->props && s->key != NULL && s->value != NULL &&
10
            (str = pw_properties_get(o->props, s->key)) != NULL &&
11
            spa_streq(str, s->value))
12
            return o;
13
-       if (s->value != NULL && (uint32_t)atoi(s->value) == o->id)
14
+       if (s->value != NULL && (uint32_t)atoi(s->value) == o->index)
15
            return o;
16
    }
17
    return s->best;
18
 }
19
 
20
-bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction)
21
+uint32_t id_to_index(struct pw_manager *m, uint32_t id)
22
+{
23
+   struct pw_manager_object *o;
24
+   spa_list_for_each(o, &m->object_list, link) {
25
+       if (o->id == id)
26
+           return o->index;
27
+   }
28
+   return SPA_ID_INVALID;
29
+}
30
+
31
+uint32_t index_to_id(struct pw_manager *m, uint32_t index)
32
+{
33
+   struct pw_manager_object *o;
34
+   spa_list_for_each(o, &m->object_list, link) {
35
+       if (o->index == index)
36
+           return o->id;
37
+   }
38
+   return SPA_ID_INVALID;
39
+}
40
+
41
+bool collect_is_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction)
42
 {
43
    struct pw_manager_object *o;
44
    uint32_t in_node, out_node;
45
@@ -83,14 +105,14 @@
46
                     pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0)
47
                         continue;
48
 
49
-       if ((direction == PW_DIRECTION_OUTPUT && obj_id == out_node) ||
50
-           (direction == PW_DIRECTION_INPUT && obj_id == in_node))
51
+       if ((direction == PW_DIRECTION_OUTPUT && id == out_node) ||
52
+           (direction == PW_DIRECTION_INPUT && id == in_node))
53
            return true;
54
    }
55
    return false;
56
 }
57
 
58
-struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction)
59
+struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction)
60
 {
61
    struct pw_manager_object *o, *p;
62
    uint32_t in_node, out_node;
63
@@ -103,12 +125,12 @@
64
                     pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0)
65
                         continue;
66
 
67
-       if (direction == PW_DIRECTION_OUTPUT && obj_id == out_node) {
68
+       if (direction == PW_DIRECTION_OUTPUT && id == out_node) {
69
            struct selector sel = { .id = in_node, .type = pw_manager_object_is_sink, };
70
            if ((p = select_object(m, &sel)) != NULL)
71
                return p;
72
        }
73
-       if (direction == PW_DIRECTION_INPUT && obj_id == in_node) {
74
+       if (direction == PW_DIRECTION_INPUT && id == in_node) {
75
            struct selector sel = { .id = out_node, .type = pw_manager_object_is_recordable, };
76
            if ((p = select_object(m, &sel)) != NULL)
77
                return p;
78
@@ -157,7 +179,7 @@
79
 
80
        if (spa_pod_parse_object(p->param,
81
                SPA_TYPE_OBJECT_ParamProfile, NULL,
82
-               SPA_PARAM_PROFILE_index, SPA_POD_Int(&pi->id),
83
+               SPA_PARAM_PROFILE_index, SPA_POD_Int(&pi->index),
84
                SPA_PARAM_PROFILE_name,  SPA_POD_String(&pi->name),
85
                SPA_PARAM_PROFILE_description,  SPA_POD_OPT_String(&pi->description),
86
                SPA_PARAM_PROFILE_priority,  SPA_POD_OPT_Int(&pi->priority),
87
@@ -167,7 +189,7 @@
88
        }
89
        if (pi->description == NULL)
90
            pi->description = pi->name;
91
-       if (pi->id == card_info->active_profile)
92
+       if (pi->index == card_info->active_profile)
93
            card_info->active_profile_name = pi->name;
94
 
95
        if (classes != NULL) {
96
@@ -198,12 +220,12 @@
97
    return n;
98
 }
99
 
100
-uint32_t find_profile_id(struct pw_manager_object *card, const char *name)
101
+uint32_t find_profile_index(struct pw_manager_object *card, const char *name)
102
 {
103
    struct pw_manager_param *p;
104
 
105
    spa_list_for_each(p, &card->param_list, link) {
106
-       uint32_t id;
107
+       uint32_t index;
108
        const char *test_name;
109
 
110
        if (p->id != SPA_PARAM_EnumProfile)
111
@@ -211,12 +233,12 @@
112
 
113
        if (spa_pod_parse_object(p->param,
114
                SPA_TYPE_OBJECT_ParamProfile, NULL,
115
-               SPA_PARAM_PROFILE_index, SPA_POD_Int(&id),
116
+               SPA_PARAM_PROFILE_index, SPA_POD_Int(&index),
117
                SPA_PARAM_PROFILE_name,  SPA_POD_String(&test_name)) < 0)
118
            continue;
119
 
120
        if (spa_streq(test_name, name))
121
-           return id;
122
+           return index;
123
 
124
    }
125
    return SPA_ID_INVALID;
126
@@ -229,7 +251,7 @@
127
 
128
    if (card && !monitor) {
129
        spa_list_for_each(p, &card->param_list, link) {
130
-           uint32_t id, dev;
131
+           uint32_t index, dev;
132
            struct spa_pod *props;
133
 
134
            if (p->id != SPA_PARAM_Route)
135
@@ -237,13 +259,13 @@
136
 
137
            if (spa_pod_parse_object(p->param,
138
                    SPA_TYPE_OBJECT_ParamRoute, NULL,
139
-                   SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
140
+                   SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
141
                    SPA_PARAM_ROUTE_device,  SPA_POD_Int(&dev),
142
                    SPA_PARAM_ROUTE_props,  SPA_POD_OPT_Pod(&props)) < 0)
143
                continue;
144
            if (dev != dev_info->device)
145
                continue;
146
-           dev_info->active_port = id;
147
+           dev_info->active_port = index;
148
            if (props) {
149
                volume_parse_param(props, &dev_info->volume_info, monitor);
150
                dev_info->have_volume = true;
151
@@ -316,7 +338,7 @@
152
 
153
        if (spa_pod_parse_object(p->param,
154
                SPA_TYPE_OBJECT_ParamRoute, NULL,
155
-               SPA_PARAM_ROUTE_index, SPA_POD_Int(&pi->id),
156
+               SPA_PARAM_ROUTE_index, SPA_POD_Int(&pi->index),
157
                SPA_PARAM_ROUTE_direction, SPA_POD_Id(&pi->direction),
158
                SPA_PARAM_ROUTE_name,  SPA_POD_String(&pi->name),
159
                SPA_PARAM_ROUTE_description,  SPA_POD_OPT_String(&pi->description),
160
@@ -341,7 +363,7 @@
161
                continue;
162
            if (!array_contains(pi->devices, pi->n_devices, dev_info->device))
163
                continue;
164
-           if (pi->id == dev_info->active_port)
165
+           if (pi->index == dev_info->active_port)
166
                dev_info->active_port_name = pi->name;
167
        }
168
 
169
@@ -377,12 +399,12 @@
170
    return n;
171
 }
172
 
173
-uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name)
174
+uint32_t find_port_index(struct pw_manager_object *card, uint32_t direction, const char *port_name)
175
 {
176
    struct pw_manager_param *p;
177
 
178
    spa_list_for_each(p, &card->param_list, link) {
179
-       uint32_t id, dir;
180
+       uint32_t index, dir;
181
        const char *name;
182
 
183
        if (p->id != SPA_PARAM_EnumRoute)
184
@@ -390,14 +412,14 @@
185
 
186
        if (spa_pod_parse_object(p->param,
187
                SPA_TYPE_OBJECT_ParamRoute, NULL,
188
-               SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
189
+               SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
190
                SPA_PARAM_ROUTE_direction, SPA_POD_Id(&dir),
191
                SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0)
192
            continue;
193
        if (dir != direction)
194
            continue;
195
        if (spa_streq(name, port_name))
196
-           return id;
197
+           return index;
198
 
199
    }
200
    return SPA_ID_INVALID;
201
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/collect.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/collect.h Changed
50
 
1
@@ -44,6 +44,7 @@
2
 struct selector {
3
    bool (*type) (struct pw_manager_object *o);
4
    uint32_t id;
5
+   uint32_t index;
6
    const char *key;
7
    const char *value;
8
    void (*accumulate) (struct selector *sel, struct pw_manager_object *o);
9
@@ -52,6 +53,8 @@
10
 };
11
 
12
 struct pw_manager_object *select_object(struct pw_manager *m, struct selector *s);
13
+uint32_t id_to_index(struct pw_manager *m, uint32_t id);
14
+uint32_t index_to_id(struct pw_manager *m, uint32_t index);
15
 void select_best(struct selector *s, struct pw_manager_object *o);
16
 
17
 /* ========================================================================== */
18
@@ -103,7 +106,7 @@
19
 /* ========================================================================== */
20
 
21
 struct profile_info {
22
-   uint32_t id;
23
+   uint32_t index;
24
    const char *name;
25
    const char *description;
26
    uint32_t priority;
27
@@ -118,7 +121,7 @@
28
 /* ========================================================================== */
29
 
30
 struct port_info {
31
-   uint32_t id;
32
+   uint32_t index;
33
    uint32_t direction;
34
    const char *name;
35
    const char *description;
36
@@ -154,9 +157,9 @@
37
 /* ========================================================================== */
38
 
39
 struct spa_dict *collect_props(struct spa_pod *info, struct spa_dict *dict);
40
-uint32_t find_profile_id(struct pw_manager_object *card, const char *name);
41
-uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name);
42
-struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction);
43
-bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction);
44
+uint32_t find_profile_index(struct pw_manager_object *card, const char *name);
45
+uint32_t find_port_index(struct pw_manager_object *card, uint32_t direction, const char *port_name);
46
+struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction);
47
+bool collect_is_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction);
48
 
49
 #endif
50
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/defs.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/defs.h Changed
15
 
1
@@ -56,10 +56,9 @@
2
 
3
 #define SCACHE_ENTRY_SIZE_MAX  (1024*1024*16)
4
 
5
-#define INDEX_MASK     0xffffu
6
-#define MONITOR_FLAG       (1u << 16)
7
-#define EXTENSION_FLAG     (1u << 17)
8
-#define MODULE_FLAG        (1u << 18)
9
+#define MODULE_INDEX_MASK  0xfffffffu
10
+#define MODULE_EXTENSION_FLAG  (1u << 28)
11
+#define MODULE_FLAG        (1u << 29)
12
 
13
 #define DEFAULT_SINK       "@DEFAULT_SINK@"
14
 #define DEFAULT_SOURCE     "@DEFAULT_SOURCE@"
15
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extension.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extension.c Changed
24
 
1
@@ -30,17 +30,17 @@
2
 #include "extensions/registry.h"
3
 
4
 static const struct extension extensions[] = {
5
-   { "module-stream-restore", 0 | EXTENSION_FLAG, do_extension_stream_restore, },
6
-   { "module-device-restore", 1 | EXTENSION_FLAG, do_extension_device_restore, },
7
-   { "module-device-manager", 2 | EXTENSION_FLAG, do_extension_device_manager, },
8
+   { "module-stream-restore", 0 | MODULE_EXTENSION_FLAG, do_extension_stream_restore, },
9
+   { "module-device-restore", 1 | MODULE_EXTENSION_FLAG, do_extension_device_restore, },
10
+   { "module-device-manager", 2 | MODULE_EXTENSION_FLAG, do_extension_device_manager, },
11
 };
12
 
13
-const struct extension *extension_find(uint32_t idx, const char *name)
14
+const struct extension *extension_find(uint32_t index, const char *name)
15
 {
16
    const struct extension *ext;
17
 
18
    SPA_FOR_EACH_ELEMENT(extensions, ext) {
19
-       if (idx == ext->idx || spa_streq(name, ext->name))
20
+       if (index == ext->index || spa_streq(name, ext->name))
21
            return ext;
22
    }
23
 
24
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extension.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extension.h Changed
14
 
1
@@ -38,10 +38,10 @@
2
 
3
 struct extension {
4
    const char *name;
5
-   uint32_t idx;
6
+   uint32_t index;
7
    int (*process)(struct client *client, uint32_t tag, struct message *m);
8
 };
9
 
10
-const struct extension *extension_find(uint32_t idx, const char *name);
11
+const struct extension *extension_find(uint32_t index, const char *name);
12
 
13
 #endif /* PULSE_SERVER_EXTENSION_H */
14
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c Changed
46
 
1
@@ -108,7 +108,7 @@
2
    }
3
    message_put(d->reply,
4
        TAG_U32, DEVICE_TYPE_SINK,
5
-       TAG_U32, o->id,
6
+       TAG_U32, o->index,          /* sink index */
7
        TAG_U8, n_info,             /* n_formats */
8
        TAG_INVALID);
9
    for (i = 0; i < n_info; i++) {
10
@@ -157,7 +157,7 @@
11
    }
12
 
13
    spa_zero(sel);
14
-   sel.id = sink_index;
15
+   sel.index = sink_index;
16
    sel.type = pw_manager_object_is_sink;
17
 
18
    o = select_object(manager, &sel);
19
@@ -173,7 +173,7 @@
20
    return client_queue_message(client, data.reply);
21
 }
22
 
23
-static int set_card_codecs(struct pw_manager_object *o, uint32_t id,
24
+static int set_card_codecs(struct pw_manager_object *o, uint32_t port_index,
25
        uint32_t device_id, uint32_t n_codecs, uint32_t *codecs)
26
 {
27
    char buf[1024];
28
@@ -190,7 +190,7 @@
29
    spa_pod_builder_push_object(&b, &f[0],
30
            SPA_TYPE_OBJECT_ParamRoute, SPA_PARAM_Route);
31
    spa_pod_builder_add(&b,
32
-           SPA_PARAM_ROUTE_index, SPA_POD_Int(id),
33
+           SPA_PARAM_ROUTE_index, SPA_POD_Int(port_index),
34
            SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id),
35
            0);
36
    spa_pod_builder_prop(&b, SPA_PARAM_ROUTE_props, 0);
37
@@ -279,7 +279,7 @@
38
        return -ENOTSUP;
39
 
40
    spa_zero(sel);
41
-   sel.id = sink_index;
42
+   sel.index = sink_index;
43
    sel.type = pw_manager_object_is_sink;
44
 
45
    o = select_object(manager, &sel);
46
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/internal.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/internal.h Changed
10
 
1
@@ -51,7 +51,7 @@
2
    struct spa_fraction min_quantum;
3
    struct sample_spec sample_spec;
4
    struct channel_map channel_map;
5
-   uint32_t max_quantum;
6
+   uint32_t quantum_limit;
7
 };
8
 
9
 struct stats {
10
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/manager.c Changed
106
 
1
@@ -64,7 +64,7 @@
2
 
3
 struct object_data {
4
    struct spa_list link;
5
-   const char *id;
6
+   const char *key;
7
    size_t size;
8
 };
9
 
10
@@ -163,7 +163,7 @@
11
 }
12
 
13
 
14
-static struct object *find_object(struct manager *m, uint32_t id)
15
+static struct object *find_object_by_id(struct manager *m, uint32_t id)
16
 {
17
    struct object *o;
18
    spa_list_for_each(o, &m->this.object_list, this.link) {
19
@@ -586,6 +586,7 @@
20
    struct manager *m = data;
21
    struct object *o;
22
    const struct object_info *info;
23
+   const char *str;
24
    struct pw_proxy *proxy;
25
 
26
    info = find_info(type, version);
27
@@ -603,10 +604,15 @@
28
        pw_proxy_destroy(proxy);
29
        return;
30
    }
31
+   str = props ? spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL) : NULL;
32
+   if (!spa_atou64(str, &o->this.serial, 0))
33
+       o->this.serial = SPA_ID_INVALID;
34
+
35
    o->this.id = id;
36
    o->this.permissions = permissions;
37
    o->this.type = info->type;
38
    o->this.version = version;
39
+   o->this.index = o->this.serial < (1ULL<<32) ? o->this.serial : SPA_ID_INVALID;
40
    o->this.props = props ? pw_properties_new_dict(props) : NULL;
41
    o->this.proxy = proxy;
42
    o->this.creating = true;
43
@@ -638,7 +644,7 @@
44
    struct manager *m = object;
45
    struct object *o;
46
 
47
-   if ((o = find_object(m, id)) == NULL)
48
+   if ((o = find_object_by_id(m, id)) == NULL)
49
        return;
50
 
51
    o->this.removing = true;
52
@@ -757,7 +763,7 @@
53
    char buf[1024];
54
    char *value;
55
 
56
-   if ((s = find_object(m, subject)) == NULL)
57
+   if ((s = find_object_by_id(m, subject)) == NULL)
58
        return -ENOENT;
59
    if (!SPA_FLAG_IS_SET(s->this.permissions, PW_PERM_M))
60
        return -EACCES;
61
@@ -793,7 +799,7 @@
62
    int res;
63
 
64
    spa_list_for_each(o, &m->this.object_list, this.link) {
65
-       if (o->this.creating)
66
+       if (o->this.creating || o->this.removing)
67
            continue;
68
        if ((res = callback(data, &o->this)) != 0)
69
            return res;
70
@@ -820,22 +826,22 @@
71
    free(m);
72
 }
73
 
74
-static struct object_data *object_find_data(struct object *o, const char *id)
75
+static struct object_data *object_find_data(struct object *o, const char *key)
76
 {
77
    struct object_data *d;
78
    spa_list_for_each(d, &o->data_list, link) {
79
-       if (spa_streq(d->id, id))
80
+       if (spa_streq(d->key, key))
81
            return d;
82
    }
83
    return NULL;
84
 }
85
 
86
-void *pw_manager_object_add_data(struct pw_manager_object *obj, const char *id, size_t size)
87
+void *pw_manager_object_add_data(struct pw_manager_object *obj, const char *key, size_t size)
88
 {
89
    struct object *o = SPA_CONTAINER_OF(obj, struct object, this);
90
    struct object_data *d;
91
 
92
-   d = object_find_data(o, id);
93
+   d = object_find_data(o, key);
94
    if (d != NULL) {
95
        if (d->size == size)
96
            goto done;
97
@@ -844,7 +850,7 @@
98
    }
99
 
100
    d = calloc(1, sizeof(struct object_data) + size);
101
-   d->id = id;
102
+   d->key = key;
103
    d->size = size;
104
 
105
    spa_list_append(&o->data_list, &d->link);
106
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/manager.h Changed
25
 
1
@@ -75,10 +75,12 @@
2
 
3
 struct pw_manager_object {
4
    struct spa_list link;           /**< link in manager object_list */
5
+   uint64_t serial;
6
    uint32_t id;
7
    uint32_t permissions;
8
    const char *type;
9
    uint32_t version;
10
+   uint32_t index;
11
    struct pw_properties *props;
12
    struct pw_proxy *proxy;
13
    char *message_object_path;
14
@@ -111,8 +113,8 @@
15
        int (*callback) (void *data, struct pw_manager_object *object),
16
        void *data);
17
 
18
-void *pw_manager_object_add_data(struct pw_manager_object *o, const char *id, size_t size);
19
-void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *id);
20
+void *pw_manager_object_add_data(struct pw_manager_object *o, const char *key, size_t size);
21
+void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *key);
22
 
23
 bool pw_manager_object_is_client(struct pw_manager_object *o);
24
 bool pw_manager_object_is_module(struct pw_manager_object *o);
25
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/message-handler.c Changed
10
 
1
@@ -122,7 +122,7 @@
2
 {
3
    const char *str;
4
 
5
-   if (o->id == 0) {
6
+   if (o->id == PW_ID_CORE) {
7
        free(o->message_object_path);
8
        o->message_object_path = strdup("/core");
9
        o->message_handler = core_object_message_handler;
10
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.c Changed
73
 
1
@@ -42,7 +42,7 @@
2
 #include "log.h"
3
 #include "module.h"
4
 
5
-static void on_module_unload(void *obj, void *data, int res, uint32_t id)
6
+static void on_module_unload(void *obj, void *data, int res, uint32_t index)
7
 {
8
    struct module *module = obj;
9
    module_unload(NULL, module);
10
@@ -83,7 +83,7 @@
11
 
12
 int module_load(struct client *client, struct module *module)
13
 {
14
-   pw_log_info("load module id:%u name:%s", module->idx, module->name);
15
+   pw_log_info("load module index:%u name:%s", module->index, module->name);
16
    if (module->methods->load == NULL)
17
        return -ENOTSUP;
18
    /* subscription event is sent when the module does a
19
@@ -97,8 +97,8 @@
20
 
21
    module_emit_destroy(module);
22
 
23
-   if (module->idx != SPA_ID_INVALID)
24
-       pw_map_remove(&impl->modules, module->idx & INDEX_MASK);
25
+   if (module->index != SPA_ID_INVALID)
26
+       pw_map_remove(&impl->modules, module->index & MODULE_INDEX_MASK);
27
 
28
    spa_hook_list_clean(&module->listener_list);
29
    pw_work_queue_cancel(impl->work_queue, module, SPA_ID_INVALID);
30
@@ -118,7 +118,7 @@
31
    /* Note that client can be NULL (when the module is being unloaded
32
     * internally and not by a client request */
33
 
34
-   pw_log_info("unload module id:%u name:%s", module->idx, module->name);
35
+   pw_log_info("unload module index:%u name:%s", module->index, module->name);
36
 
37
    if (module->methods->unload)
38
        res = module->methods->unload(client, module);
39
@@ -127,7 +127,7 @@
40
        broadcast_subscribe_event(impl,
41
            SUBSCRIPTION_MASK_MODULE,
42
            SUBSCRIPTION_EVENT_REMOVE | SUBSCRIPTION_EVENT_MODULE,
43
-           module->idx);
44
+           module->index);
45
 
46
    module_free(module);
47
 
48
@@ -270,6 +270,7 @@
49
 #endif
50
    { "module-roc-sink", create_module_roc_sink, },
51
    { "module-roc-source", create_module_roc_source, },
52
+   { "module-x11-bell", create_module_x11_bell, },
53
 };
54
 
55
 static const struct module_info *find_module_info(const char *name)
56
@@ -299,13 +300,13 @@
57
    if (module == NULL)
58
        return NULL;
59
 
60
-   module->idx = pw_map_insert_new(&impl->modules, module);
61
-   if (module->idx == SPA_ID_INVALID) {
62
+   module->index = pw_map_insert_new(&impl->modules, module);
63
+   if (module->index == SPA_ID_INVALID) {
64
        module_unload(client, module);
65
        return NULL;
66
    }
67
    module->name = strdup(name);
68
    module->args = args ? strdup(args) : NULL;
69
-   module->idx |= MODULE_FLAG;
70
+   module->index |= MODULE_FLAG;
71
    return module;
72
 }
73
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.h Changed
10
 
1
@@ -57,7 +57,7 @@
2
 };
3
 
4
 struct module {
5
-   uint32_t idx;
6
+   uint32_t index;
7
    const char *name;
8
    const char *args;
9
    struct pw_properties *props;
10
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c Changed
27
 
1
@@ -262,11 +262,11 @@
2
 
3
    props = pw_properties_new(NULL, NULL);
4
    pw_properties_setf(props, PW_KEY_NODE_NAME,
5
-           "combine_output.sink-%u.%s", data->module->idx, sink_name);
6
+           "combine_output.sink-%u.%s", data->module->index, sink_name);
7
    pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, data->sink_name);
8
    pw_properties_set(props, PW_KEY_NODE_TARGET, sink_name);
9
-   pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->idx);
10
-   pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->idx);
11
+   pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index);
12
+   pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index);
13
    pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true");
14
    pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
15
    pw_properties_set(props, PW_KEY_NODE_PASSIVE, "true");
16
@@ -351,8 +351,8 @@
17
    pw_properties_set(props, PW_KEY_NODE_NAME, data->sink_name);
18
    pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, data->sink_name);
19
    pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
20
-   pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->idx);
21
-   pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->idx);
22
+   pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index);
23
+   pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index);
24
    pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
25
 
26
    if ((str = pw_properties_get(module->props, "sink_properties")) != NULL)
27
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c Changed
47
 
1
@@ -73,8 +73,8 @@
2
    if ((label = pw_properties_get(module->props, "label")) == NULL)
3
        return -EINVAL;
4
 
5
-   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->idx);
6
-   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->idx);
7
+   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index);
8
+   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index);
9
 
10
    f = open_memstream(&args, &size);
11
    fprintf(f, "{");
12
@@ -84,11 +84,24 @@
13
    fprintf(f, " type = ladspa ");
14
    fprintf(f, " plugin = \"%s\" ", plugin);
15
    fprintf(f, " label = \"%s\" ", label);
16
+   if ((str = pw_properties_get(module->props, "control")) != NULL) {
17
+       size_t len;
18
+       const char *s, *state = NULL;
19
+       int count = 0;
20
+
21
+       fprintf(f, " control = {");
22
+       while ((s = pw_split_walk(str, ", ", &len, &state))) {
23
+           fprintf(f, " \"%d\" = %.*s", count, (int)len, s);
24
+           count++;
25
+       }
26
+       fprintf(f, " }");
27
+   }
28
+   fprintf(f, " } ]");
29
    if ((str = pw_properties_get(module->props, "inputs")) != NULL)
30
        fprintf(f, " inputs = [ %s ] ", str);
31
    if ((str = pw_properties_get(module->props, "outputs")) != NULL)
32
        fprintf(f, " outputs = [ %s ] ", str);
33
-   fprintf(f, " } ] }");
34
+   fprintf(f, " }");
35
    fprintf(f, " capture.props = {");
36
    pw_properties_serialize_dict(f, &data->capture_props->dict, 0);
37
    fprintf(f, " } playback.props = {");
38
@@ -190,7 +203,7 @@
39
        module_args_add_props(props, argument);
40
 
41
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
42
-       pw_properties_set(props, PW_KEY_NODE_NAME, str);
43
+       pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
44
        pw_properties_set(props, "sink_name", NULL);
45
    }
46
    if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
47
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c Changed
48
 
1
@@ -73,8 +73,8 @@
2
    if ((label = pw_properties_get(module->props, "label")) == NULL)
3
        return -EINVAL;
4
 
5
-   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->idx);
6
-   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->idx);
7
+   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index);
8
+   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index);
9
 
10
    f = open_memstream(&args, &size);
11
    fprintf(f, "{");
12
@@ -84,11 +84,24 @@
13
    fprintf(f, " type = ladspa ");
14
    fprintf(f, " plugin = \"%s\" ", plugin);
15
    fprintf(f, " label = \"%s\" ", label);
16
+   if ((str = pw_properties_get(module->props, "control")) != NULL) {
17
+       size_t len;
18
+       const char *s, *state = NULL;
19
+       int count = 0;
20
+
21
+       fprintf(f, " control = {");
22
+       while ((s = pw_split_walk(str, ", ", &len, &state))) {
23
+           fprintf(f, " \"%d\" = %.*s", count, (int)len, s);
24
+           count++;
25
+       }
26
+       fprintf(f, " }");
27
+   }
28
+   fprintf(f, " } ]");
29
    if ((str = pw_properties_get(module->props, "inputs")) != NULL)
30
        fprintf(f, " inputs = [ %s ] ", str);
31
    if ((str = pw_properties_get(module->props, "outputs")) != NULL)
32
        fprintf(f, " outputs = [ %s ] ", str);
33
-   fprintf(f, " } ] }");
34
+   fprintf(f, " }");
35
    fprintf(f, " capture.props = {");
36
    pw_properties_serialize_dict(f, &data->capture_props->dict, 0);
37
    fprintf(f, " } playback.props = {");
38
@@ -190,8 +203,7 @@
39
        module_args_add_props(props, argument);
40
 
41
    if ((str = pw_properties_get(props, "source_name")) != NULL) {
42
-       pw_properties_set(props, PW_KEY_NODE_NAME, str);
43
-       pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
44
+       pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
45
        pw_properties_set(props, "source_name", NULL);
46
    }
47
    if ((str = pw_properties_get(props, "source_properties")) != NULL) {
48
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c Changed
12
 
1
@@ -70,8 +70,8 @@
2
    char *args;
3
    size_t size, i;
4
 
5
-   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->idx);
6
-   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->idx);
7
+   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
8
+   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
9
 
10
    f = open_memstream(&args, &size);
11
    fprintf(f, "{");
12
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c Changed
21
 
1
@@ -67,8 +67,8 @@
2
    char *args;
3
    size_t size;
4
 
5
-   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->idx);
6
-   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->idx);
7
+   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index);
8
+   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index);
9
 
10
    f = open_memstream(&args, &size);
11
    fprintf(f, "{");
12
@@ -169,7 +169,7 @@
13
        module_args_add_props(props, argument);
14
 
15
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
16
-       pw_properties_set(props, PW_KEY_NODE_NAME, str);
17
+       pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
18
        pw_properties_set(props, "sink_name", NULL);
19
    }
20
    if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
21
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c Changed
21
 
1
@@ -67,8 +67,8 @@
2
    char *args;
3
    size_t size;
4
 
5
-   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->idx);
6
-   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->idx);
7
+   pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index);
8
+   pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index);
9
 
10
    f = open_memstream(&args, &size);
11
    fprintf(f, "{");
12
@@ -169,7 +169,7 @@
13
        module_args_add_props(props, argument);
14
 
15
    if ((str = pw_properties_get(props, "source_name")) != NULL) {
16
-       pw_properties_set(props, PW_KEY_NODE_NAME, str);
17
+       pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
18
        pw_properties_set(props, "source_name", NULL);
19
    }
20
    if ((str = pw_properties_get(props, "source_properties")) != NULL) {
21
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c Added
147
 
1
@@ -0,0 +1,145 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <pipewire/pipewire.h>
27
+
28
+#include "../module.h"
29
+
30
+#define NAME "x11-bell"
31
+
32
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
33
+#define PW_LOG_TOPIC_DEFAULT mod_topic
34
+
35
+struct module_x11_bell_data {
36
+   struct module *module;
37
+
38
+   struct pw_impl_module *mod;
39
+   struct spa_hook mod_listener;
40
+};
41
+
42
+static void module_destroy(void *data)
43
+{
44
+   struct module_x11_bell_data *d = data;
45
+   spa_hook_remove(&d->mod_listener);
46
+   d->mod = NULL;
47
+   module_schedule_unload(d->module);
48
+}
49
+
50
+static const struct pw_impl_module_events module_events = {
51
+   PW_VERSION_IMPL_MODULE_EVENTS,
52
+   .destroy = module_destroy
53
+};
54
+
55
+static int module_x11_bell_load(struct client *client, struct module *module)
56
+{
57
+   struct module_x11_bell_data *data = module->user_data;
58
+   FILE *f;
59
+   char *args;
60
+   const char *str;
61
+   size_t size;
62
+
63
+   f = open_memstream(&args, &size);
64
+   fprintf(f, "{");
65
+   if ((str = pw_properties_get(module->props, "sink")) != NULL)
66
+       fprintf(f, " sink.name = \"%s\"", str);
67
+   if ((str = pw_properties_get(module->props, "sample")) != NULL)
68
+       fprintf(f, " sample.name = \"%s\"", str);
69
+   if ((str = pw_properties_get(module->props, "display")) != NULL)
70
+       fprintf(f, " x11.display = \"%s\"", str);
71
+   if ((str = pw_properties_get(module->props, "xauthority")) != NULL)
72
+       fprintf(f, " x11.xauthority = \"%s\"", str);
73
+   fprintf(f, " }");
74
+   fclose(f);
75
+
76
+   data->mod = pw_context_load_module(module->impl->context,
77
+           "libpipewire-module-x11-bell",
78
+           args, NULL);
79
+   free(args);
80
+
81
+   if (data->mod == NULL)
82
+       return -errno;
83
+
84
+   pw_impl_module_add_listener(data->mod,
85
+           &data->mod_listener,
86
+           &module_events, data);
87
+   return 0;
88
+}
89
+
90
+static int module_x11_bell_unload(struct client *client, struct module *module)
91
+{
92
+   struct module_x11_bell_data *d = module->user_data;
93
+
94
+   if (d->mod) {
95
+       spa_hook_remove(&d->mod_listener);
96
+       pw_impl_module_destroy(d->mod);
97
+       d->mod = NULL;
98
+   }
99
+   return 0;
100
+}
101
+
102
+static const struct module_methods module_x11_bell_methods = {
103
+   VERSION_MODULE_METHODS,
104
+   .load = module_x11_bell_load,
105
+   .unload = module_x11_bell_unload,
106
+};
107
+
108
+static const struct spa_dict_item module_x11_bell_info[] = {
109
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
110
+   { PW_KEY_MODULE_DESCRIPTION, "X11 bell interceptor" },
111
+   { PW_KEY_MODULE_USAGE,  "sink=<sink to connect to> "
112
+               "sample=<the sample to play> "
113
+               "display=<X11 display> "
114
+               "xauthority=<X11 Authority>" },
115
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
116
+};
117
+
118
+struct module *create_module_x11_bell(struct impl *impl, const char *argument)
119
+{
120
+   struct module *module;
121
+   struct pw_properties *props = NULL;
122
+   int res;
123
+
124
+   PW_LOG_TOPIC_INIT(mod_topic);
125
+
126
+   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_x11_bell_info));
127
+   if (props == NULL) {
128
+       res = -EINVAL;
129
+       goto out;
130
+   }
131
+   if (argument)
132
+       module_args_add_props(props, argument);
133
+
134
+   module = module_new(impl, &module_x11_bell_methods, sizeof(struct module_x11_bell_data));
135
+   if (module == NULL) {
136
+       res = -errno;
137
+       goto out;
138
+   }
139
+   module->props = props;
140
+
141
+   return module;
142
+out:
143
+   pw_properties_free(props);
144
+   errno = -res;
145
+   return NULL;
146
+}
147
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/registry.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/registry.h Changed
8
 
1
@@ -48,5 +48,6 @@
2
 struct module *create_module_zeroconf_publish(struct impl *impl, const char *argument);
3
 struct module *create_module_roc_sink(struct impl *impl, const char *argument);
4
 struct module *create_module_roc_source(struct impl *impl, const char *argument);
5
+struct module *create_module_x11_bell(struct impl *impl, const char *argument);
6
 
7
 #endif
8
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
201
 
1
@@ -97,12 +97,12 @@
2
    unsigned int initialized:1;
3
 };
4
 
5
-static struct sample *find_sample(struct impl *impl, uint32_t idx, const char *name)
6
+static struct sample *find_sample(struct impl *impl, uint32_t index, const char *name)
7
 {
8
    union pw_map_item *item;
9
 
10
-   if (idx != SPA_ID_INVALID)
11
-       return pw_map_lookup(&impl->samples, idx);
12
+   if (index != SPA_ID_INVALID)
13
+       return pw_map_lookup(&impl->samples, index);
14
 
15
    pw_array_for_each(item, &impl->samples.items) {
16
        struct sample *s = item->data;
17
@@ -113,13 +113,13 @@
18
    return NULL;
19
 }
20
 
21
-void broadcast_subscribe_event(struct impl *impl, uint32_t mask, uint32_t event, uint32_t id)
22
+void broadcast_subscribe_event(struct impl *impl, uint32_t mask, uint32_t event, uint32_t index)
23
 {
24
    struct server *s;
25
    spa_list_for_each(s, &impl->servers, link) {
26
        struct client *c;
27
        spa_list_for_each(c, &s->clients, link)
28
-           client_queue_subscribe_event(c, mask, event, id);
29
+           client_queue_subscribe_event(c, mask, event, index);
30
    }
31
 }
32
 
33
@@ -159,23 +159,25 @@
34
 
35
 static int reply_set_client_name(struct client *client, uint32_t tag)
36
 {
37
+   struct pw_manager *manager = client->manager;
38
    struct message *reply;
39
    struct pw_client *c;
40
-   uint32_t id;
41
+   uint32_t id, index;
42
 
43
    c = pw_core_get_client(client->core);
44
    if (c == NULL)
45
        return -ENOENT;
46
 
47
    id = pw_proxy_get_bound_id((struct pw_proxy*)c);
48
+   index = id_to_index(manager, id);
49
 
50
-   pw_log_info("[%s] reply tag:%u id:%u", client->name, tag, id);
51
+   pw_log_info("[%s] reply tag:%u id:%u index:%u", client->name, tag, id, index);
52
 
53
    reply = reply_new(client, tag);
54
 
55
    if (client->version >= 13) {
56
        message_put(reply,
57
-           TAG_U32, id,        /* client index */
58
+           TAG_U32, index,     /* client index */
59
            TAG_INVALID);
60
    }
61
    return client_queue_message(client, reply);
62
@@ -196,13 +198,13 @@
63
        operation_complete(o);
64
 }
65
 
66
-static struct stream *find_stream(struct client *client, uint32_t id)
67
+static struct stream *find_stream(struct client *client, uint32_t index)
68
 {
69
    union pw_map_item *item;
70
    pw_array_for_each(item, &client->streams.items) {
71
        struct stream *s = item->data;
72
        if (!pw_map_item_is_free(item) &&
73
-           s->id == id)
74
+           s->index == index)
75
            return s;
76
    }
77
    return NULL;
78
@@ -211,17 +213,15 @@
79
 static int send_object_event(struct client *client, struct pw_manager_object *o,
80
        uint32_t facility)
81
 {
82
-   uint32_t event = 0, mask = 0, res_id = o->id;
83
+   uint32_t event = 0, mask = 0, res_index = o->index;
84
 
85
    if (pw_manager_object_is_sink(o)) {
86
        client_queue_subscribe_event(client,
87
                SUBSCRIPTION_MASK_SINK,
88
                SUBSCRIPTION_EVENT_SINK | facility,
89
-               res_id);
90
+               res_index);
91
    }
92
    if (pw_manager_object_is_source_or_monitor(o)) {
93
-       if (!pw_manager_object_is_source(o))
94
-           res_id |= MONITOR_FLAG;
95
        mask = SUBSCRIPTION_MASK_SOURCE;
96
        event = SUBSCRIPTION_EVENT_SOURCE;
97
    }
98
@@ -251,12 +251,12 @@
99
        client_queue_subscribe_event(client,
100
                mask,
101
                event | facility,
102
-               res_id);
103
+               res_index);
104
    return 0;
105
 }
106
 
107
 static struct pw_manager_object *find_device(struct client *client,
108
-       uint32_t id, const char *name, bool sink, bool *is_monitor);
109
+       uint32_t index, const char *name, bool sink, bool *is_monitor);
110
 
111
 static int64_t get_node_latency_offset(struct pw_manager_object *o)
112
 {
113
@@ -276,6 +276,7 @@
114
 
115
 static void send_latency_offset_subscribe_event(struct client *client, struct pw_manager_object *o)
116
 {
117
+   struct pw_manager *manager = client->manager;
118
    struct latency_offset_data *d;
119
    struct pw_node_info *info;
120
    const char *str;
121
@@ -310,7 +311,7 @@
122
        client_queue_subscribe_event(client,
123
                SUBSCRIPTION_MASK_CARD,
124
                SUBSCRIPTION_EVENT_CARD | SUBSCRIPTION_EVENT_CHANGE,
125
-               card_id);
126
+               id_to_index(manager, card_id));
127
 }
128
 
129
 static void send_default_change_subscribe_event(struct client *client, bool sink, bool source)
130
@@ -370,8 +371,8 @@
131
    struct defs *defs = &s->impl->defs;
132
 
133
    frame_size = s->frame_size;
134
-   minreq = frac_to_bytes_round_up(defs->min_req, &s->ss);
135
-   max_latency = defs->max_quantum * frame_size;
136
+   minreq = frac_to_bytes_round_up(s->min_req, &s->ss);
137
+   max_latency = defs->quantum_limit * frame_size;
138
 
139
    if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH)
140
        attr->maxlength = MAXLENGTH;
141
@@ -379,7 +380,7 @@
142
    attr->maxlength = SPA_MAX(attr->maxlength, frame_size);
143
 
144
    if (attr->tlength == (uint32_t) -1)
145
-       attr->tlength = frac_to_bytes_round_up(defs->default_tlength, &s->ss);
146
+       attr->tlength = frac_to_bytes_round_up(s->default_tlength, &s->ss);
147
    if (attr->tlength > attr->maxlength)
148
        attr->tlength = attr->maxlength;
149
    attr->tlength -= attr->tlength % frame_size;
150
@@ -387,7 +388,7 @@
151
    attr->tlength = SPA_MAX(attr->tlength, minreq);
152
 
153
    if (attr->minreq == (uint32_t) -1) {
154
-       uint32_t process = frac_to_bytes_round_up(defs->default_req, &s->ss);
155
+       uint32_t process = frac_to_bytes_round_up(s->default_req, &s->ss);
156
        /* With low-latency, tlength/4 gives a decent default in all of traditional,
157
         * adjust latency and early request modes. */
158
        uint32_t m = attr->tlength / 4;
159
@@ -434,7 +435,6 @@
160
        attr->prebuf = max_prebuf;
161
    attr->prebuf -= attr->prebuf % frame_size;
162
 
163
-   s->missing = attr->tlength;
164
    attr->fragsize = 0;
165
 
166
    pw_log_info("[%s] maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u %u",
167
@@ -447,8 +447,9 @@
168
 static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer)
169
 {
170
    struct client *client = stream->client;
171
+   struct pw_manager *manager = client->manager;
172
    struct message *reply;
173
-   uint32_t missing, peer_id;
174
+   uint32_t missing, peer_index;
175
    struct spa_dict_item items[5];
176
    char latency[32];
177
    char attr_maxlength[32];
178
@@ -458,7 +459,6 @@
179
    const char *peer_name;
180
    struct spa_fraction lat;
181
    uint64_t lat_usec;
182
-   struct defs *defs = &stream->impl->defs;
183
 
184
    lat.denom = stream->ss.rate;
185
    lat.num = fix_playback_buffer_attr(stream, &stream->attr);
186
@@ -467,9 +467,9 @@
187
    if (stream->buffer == NULL)
188
        return -errno;
189
 
190
-   if (lat.num * defs->min_quantum.denom / lat.denom < defs->min_quantum.num)
191
-       lat.num = (defs->min_quantum.num * lat.denom +
192
-               (defs->min_quantum.denom -1)) / defs->min_quantum.denom;
193
+   if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num)
194
+       lat.num = (stream->min_quantum.num * lat.denom +
195
+               (stream->min_quantum.denom -1)) / stream->min_quantum.denom;
196
    lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
197
 
198
    snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
199
@@ -489,22 +489,23 @@
200
        stream->in_prebuf = true;
201
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/quirks.c Changed
201
 
1
@@ -30,23 +30,7 @@
2
 
3
 #include "log.h"
4
 #include "quirks.h"
5
-
6
-#define QUOTE(...) #__VA_ARGS__
7
-
8
-static const char quirks_rules[] =
9
-"# List of quirks"
10
-"#"
11
-"# All key/value pairs need to match before the quirks are applied."
12
-"#"
13
-"# Possible quirks:"
14
-"#    force-s16-info       forces sink and source info as S16 format"
15
-"#    remove-capture-dont-move removes the capture DONT_MOVE flag"
16
-"#\n"
17
-"["
18
-"    { application.process.binary = teams, quirks = [ force-s16-info ] },"
19
-"    { application.process.binary = skypeforlinux, quirks = [ force-s16-info ] },"
20
-"    { application.process.binary = firefox, quirks = [ remove-capture-dont-move ] },"
21
-"]";
22
+#include "internal.h"
23
 
24
 static uint64_t parse_quirks(const char *str)
25
 {
26
@@ -62,72 +46,139 @@
27
    return 0;
28
 }
29
 
30
-static int match(const char *rules, struct spa_dict *dict, uint64_t *quirks)
31
+static bool find_match(struct spa_json *arr, const struct spa_dict *props)
32
 {
33
-   struct spa_json rules_json = SPA_JSON_INIT(rules, strlen(rules));
34
-   struct spa_json rules_arr, it[2];
35
-
36
-   if (spa_json_enter_array(&rules_json, &rules_arr) <= 0)
37
-       return -EINVAL;
38
+   struct spa_json it[1];
39
 
40
-   while (spa_json_enter_object(&rules_arr, &it[0]) > 0) {
41
-       char key[256];
42
-       int match = true;
43
-       uint64_t quirks_cur = 0;
44
+   while (spa_json_enter_object(arr, &it[0]) > 0) {
45
+       char key[256], val[1024];
46
+       const char *str, *value;
47
+       int match = 0, fail = 0;
48
+       int len;
49
 
50
        while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
51
-           char val[4096];
52
-           const char *str, *value;
53
-           int len;
54
            bool success = false;
55
 
56
-           if (spa_streq(key, "quirks")) {
57
-               if (spa_json_enter_array(&it[0], &it[1]) > 0) {
58
-                   while (spa_json_get_string(&it[1], val, sizeof(val)) > 0)
59
-                       quirks_cur |= parse_quirks(val);
60
-               }
61
-               continue;
62
-           }
63
            if ((len = spa_json_next(&it[0], &value)) <= 0)
64
                break;
65
 
66
+           str = spa_dict_lookup(props, key);
67
+
68
            if (spa_json_is_null(value, len)) {
69
-               value = NULL;
70
+               success = str == NULL;
71
            } else {
72
                if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0)
73
                    continue;
74
                value = val;
75
+               len = strlen(val);
76
            }
77
-           str = spa_dict_lookup(dict, key);
78
-           if (value == NULL) {
79
-               success = str == NULL;
80
-           } else if (str != NULL) {
81
+           if (str != NULL) {
82
                if (value[0] == '~') {
83
-                   regex_t r;
84
-                   if (regcomp(&r, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
85
-                       if (regexec(&r, str, 0, NULL, 0) == 0)
86
+                   regex_t preg;
87
+                   if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
88
+                       if (regexec(&preg, str, 0, NULL, 0) == 0)
89
                            success = true;
90
-                       regfree(&r);
91
+                       regfree(&preg);
92
                    }
93
-               } else if (spa_streq(str, value)) {
94
+               } else if (strncmp(str, value, len) == 0 &&
95
+                   strlen(str) == (size_t)len) {
96
                    success = true;
97
                }
98
            }
99
+           if (success) {
100
+               match++;
101
+               pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
102
+           }
103
+           else
104
+               fail++;
105
+       }
106
+       if (match > 0 && fail == 0)
107
+           return true;
108
+   }
109
+   return false;
110
+}
111
 
112
-           if (!success) {
113
-               match = false;
114
-               break;
115
+static int pw_conf_match_rules(const char *rules, size_t size, const struct spa_dict *props,
116
+       int (*matched) (void *data, const char *action, const char *val, int len),
117
+       void *data)
118
+{
119
+   const char *val;
120
+   struct spa_json it[4], actions;
121
+   int count = 0;
122
+
123
+   spa_json_init(&it[0], rules, size);
124
+   if (spa_json_enter_array(&it[0], &it[1]) < 0)
125
+       return 0;
126
+
127
+   while (spa_json_enter_object(&it[1], &it[2]) > 0) {
128
+       char key[64];
129
+       bool have_match = false, have_actions = false;
130
+
131
+       while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
132
+           if (spa_streq(key, "matches")) {
133
+               if (spa_json_enter_array(&it[2], &it[3]) < 0)
134
+                   break;
135
+
136
+               have_match = find_match(&it[3], props);
137
            }
138
-                }
139
-       if (match) {
140
-           *quirks = quirks_cur;
141
-           return 1;
142
+           else if (spa_streq(key, "actions")) {
143
+               if (spa_json_enter_object(&it[2], &actions) > 0)
144
+                   have_actions = true;
145
+           }
146
+           else if (spa_json_next(&it[2], &val) <= 0)
147
+                                break;
148
+       }
149
+       if (!have_match || !have_actions)
150
+           continue;
151
+
152
+       while (spa_json_get_string(&actions, key, sizeof(key)) > 0) {
153
+           int res, len;
154
+           pw_log_debug("action %s", key);
155
+
156
+           if ((len = spa_json_next(&actions, &val)) <= 0)
157
+               break;
158
+
159
+           if (spa_json_is_container(val, len))
160
+               len = spa_json_container_len(&actions, val, len);
161
+
162
+           if ((res = matched(data, key, val, len)) < 0)
163
+               return res;
164
+
165
+           count += res;
166
+       }
167
+   }
168
+   return count;
169
+}
170
+
171
+static int client_rule_matched(void *data, const char *action, const char *val, int len)
172
+{
173
+   struct client *client = data;
174
+
175
+   if (spa_streq(action, "update-props")) {
176
+       pw_properties_update_string(client->props, val, len);
177
+   } else if (spa_streq(action, "quirks")) {
178
+       struct spa_json quirks = SPA_JSON_INIT(val, len), it[1];
179
+       uint64_t quirks_cur = 0;
180
+       char v[128];
181
+
182
+       if (spa_json_enter_array(&quirks, &it[0]) > 0) {
183
+           while (spa_json_get_string(&it[0], v, sizeof(v)) > 0)
184
+               quirks_cur |= parse_quirks(v);
185
        }
186
+       client->quirks = quirks_cur;
187
    }
188
    return 0;
189
 }
190
 
191
 int client_update_quirks(struct client *client)
192
 {
193
-   return match(quirks_rules, &client->props->dict, &client->quirks);
194
+   struct impl *impl = client->impl;
195
+   struct pw_context *context = impl->context;
196
+   const char *rules;
197
+
198
+   if ((rules = pw_context_get_conf_section(context, "pulse.rules")) == NULL)
199
+       return 0;
200
+
201
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/server.c Changed
55
 
1
@@ -167,7 +167,6 @@
2
    index += diff;
3
    filled += diff;
4
    stream->write_index += diff;
5
-   stream->missing -= diff;
6
 
7
    if (filled < 0) {
8
        /* underrun, reported on reader side */
9
@@ -188,6 +187,8 @@
10
    spa_ringbuffer_write_update(&stream->ring, index);
11
    stream->requested -= SPA_MIN(msg->length, stream->requested);
12
 
13
+   stream_send_request(stream);
14
+
15
 finish:
16
    message_free(impl, msg, false, false);
17
    return res;
18
@@ -378,7 +379,7 @@
19
        goto error;
20
    }
21
 
22
-   if (server->n_clients >= MAX_CLIENTS) {
23
+   if (server->n_clients >= server->max_clients) {
24
        close(client_fd);
25
        errno = ECONNREFUSED;
26
        goto error;
27
@@ -943,7 +944,7 @@
28
    while ((len = spa_json_next(&it[1], &v)) > 0) {
29
        char addr_str[FORMATTED_SOCKET_ADDR_STRLEN] = { 0 };
30
        char key[128], client_access[64] = { 0 };
31
-       struct sockaddr_storage addr[2];
32
+       struct sockaddr_storage addrs[2];
33
        int i, max_clients = MAX_CLIENTS, listen_backlog = LISTEN_BACKLOG, n_addr;
34
 
35
        if (spa_json_is_object(v, len)) {
36
@@ -966,7 +967,7 @@
37
            spa_json_parse_stringn(v, len, addr_str, sizeof(addr_str));
38
        }
39
 
40
-       n_addr = parse_address(addr_str, addr, 2);
41
+       n_addr = parse_address(addr_str, addrs, SPA_N_ELEMENTS(addrs));
42
        if (n_addr < 0) {
43
            pw_log_warn("pulse-server %p: failed to parse address '%s': %s",
44
                    impl, addr_str, spa_strerror(n_addr));
45
@@ -976,7 +977,9 @@
46
 
47
        /* try to create sockets for each address in the list */
48
        for (i = 0; i < n_addr; i++) {
49
+           const struct sockaddr_storage *addr = &addrs[i];
50
            struct server * const server = server_new(impl);
51
+
52
            if (server == NULL) {
53
                UPDATE_ERR(-errno);
54
                continue;
55
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.c Changed
117
 
1
@@ -44,11 +44,25 @@
2
 #include "reply.h"
3
 #include "stream.h"
4
 
5
+static int parse_frac(struct pw_properties *props, const char *key,
6
+       const struct spa_fraction *def, struct spa_fraction *res)
7
+{
8
+   const char *str;
9
+   if (props == NULL ||
10
+       (str = pw_properties_get(props, key)) == NULL ||
11
+       sscanf(str, "%u/%u", &res->num, &res->denom) != 2 ||
12
+        res->denom == 0) {
13
+       *res = *def;
14
+   }
15
+   return 0;
16
+}
17
+
18
 struct stream *stream_new(struct client *client, enum stream_type type, uint32_t create_tag,
19
              const struct sample_spec *ss, const struct channel_map *map,
20
              const struct buffer_attr *attr)
21
 {
22
    int res;
23
+   struct defs *defs = &client->impl->defs;
24
 
25
    struct stream *stream = calloc(1, sizeof(*stream));
26
    if (stream == NULL)
27
@@ -67,6 +81,13 @@
28
    stream->attr = *attr;
29
    spa_ringbuffer_init(&stream->ring);
30
 
31
+   parse_frac(client->props, "pulse.min.req", &defs->min_req, &stream->min_req);
32
+   parse_frac(client->props, "pulse.min.frag", &defs->min_frag, &stream->min_frag);
33
+   parse_frac(client->props, "pulse.min.quantum", &defs->min_quantum, &stream->min_quantum);
34
+   parse_frac(client->props, "pulse.default.req", &defs->default_req, &stream->default_req);
35
+   parse_frac(client->props, "pulse.default.frag", &defs->default_frag, &stream->default_frag);
36
+   parse_frac(client->props, "pulse.default.tlength", &defs->default_tlength, &stream->default_tlength);
37
+
38
    switch (type) {
39
    case STREAM_TYPE_RECORD:
40
        stream->direction = PW_DIRECTION_INPUT;
41
@@ -136,9 +157,6 @@
42
        stream->ring.writeindex = stream->ring.readindex;
43
        stream->write_index = stream->read_index;
44
 
45
-       stream->missing = stream->attr.tlength -
46
-           SPA_MIN(stream->requested, stream->attr.tlength);
47
-
48
        if (stream->attr.prebuf > 0)
49
            stream->in_prebuf = true;
50
 
51
@@ -153,13 +171,8 @@
52
    }
53
 }
54
 
55
-static bool stream_prebuf_active(struct stream *stream)
56
+static bool stream_prebuf_active(struct stream *stream, int32_t avail)
57
 {
58
-   uint32_t index;
59
-   int32_t avail;
60
-
61
-   avail = spa_ringbuffer_get_write_index(&stream->ring, &index);
62
-
63
    if (stream->in_prebuf) {
64
        if (avail >= (int32_t) stream->attr.prebuf)
65
            stream->in_prebuf = false;
66
@@ -172,30 +185,34 @@
67
 
68
 uint32_t stream_pop_missing(struct stream *stream)
69
 {
70
-   uint32_t missing;
71
+   int64_t missing, avail;
72
+
73
+   avail = stream->write_index - stream->read_index;
74
+
75
+   missing = stream->attr.tlength;
76
+   missing -= stream->requested;
77
+   missing -= avail;
78
 
79
-   if (stream->missing <= 0)
80
+   if (missing <= 0)
81
        return 0;
82
 
83
-   if (stream->missing < stream->attr.minreq && !stream_prebuf_active(stream))
84
+   if (missing < stream->attr.minreq && !stream_prebuf_active(stream, avail))
85
        return 0;
86
 
87
-   missing = stream->missing;
88
    stream->requested += missing;
89
-   stream->missing = 0;
90
 
91
    return missing;
92
 }
93
 
94
-int stream_send_underflow(struct stream *stream, int64_t offset, uint32_t underrun_for)
95
+int stream_send_underflow(struct stream *stream, int64_t offset)
96
 {
97
    struct client *client = stream->client;
98
    struct impl *impl = client->impl;
99
    struct message *reply;
100
 
101
    if (ratelimit_test(&impl->rate_limit, stream->timestamp, SPA_LOG_LEVEL_INFO)) {
102
-       pw_log_info("[%s]: UNDERFLOW channel:%u offset:%" PRIi64 " underrun:%u",
103
-               client->name, stream->channel, offset, underrun_for);
104
+       pw_log_info("[%s]: UNDERFLOW channel:%u offset:%" PRIi64,
105
+               client->name, stream->channel, offset);
106
    }
107
 
108
    reply = message_alloc(impl, -1, 0);
109
@@ -314,7 +331,6 @@
110
    if (new_tlength <= old_tlength)
111
        return 0;
112
 
113
-   stream->missing += new_tlength - old_tlength;
114
    stream->attr.tlength = new_tlength;
115
 
116
    if (client->version >= 15) {
117
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.h Changed
35
 
1
@@ -58,6 +58,7 @@
2
    uint32_t create_tag;
3
    uint32_t channel;   /* index in map */
4
    uint32_t id;        /* id of global */
5
+   uint32_t index;     /* index */
6
 
7
    struct impl *impl;
8
    struct client *client;
9
@@ -83,9 +84,15 @@
10
    int64_t delay;
11
 
12
    uint32_t last_quantum;
13
-   int64_t missing;
14
    int64_t requested;
15
 
16
+   struct spa_fraction min_req;
17
+   struct spa_fraction default_req;
18
+   struct spa_fraction min_frag;
19
+   struct spa_fraction default_frag;
20
+   struct spa_fraction default_tlength;
21
+   struct spa_fraction min_quantum;
22
+
23
    struct sample_spec ss;
24
    struct channel_map map;
25
    struct buffer_attr attr;
26
@@ -116,7 +123,7 @@
27
 void stream_flush(struct stream *stream);
28
 uint32_t stream_pop_missing(struct stream *stream);
29
 
30
-int stream_send_underflow(struct stream *stream, int64_t offset, uint32_t underrun_for);
31
+int stream_send_underflow(struct stream *stream, int64_t offset);
32
 int stream_send_overflow(struct stream *stream);
33
 int stream_send_killed(struct stream *stream);
34
 int stream_send_started(struct stream *stream);
35
pipewire-0.3.43.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-simple.c Changed
28
 
1
@@ -111,7 +111,7 @@
2
         struct spa_hook core_proxy_listener;
3
 
4
    struct spa_source *source;
5
-   char name[512];
6
+   char name[128];
7
 
8
    struct pw_stream *capture;
9
    struct spa_hook capture_listener;
10
@@ -477,7 +477,7 @@
11
 {
12
    struct server *server = data;
13
    struct impl *impl = server->impl;
14
-   struct sockaddr addr;
15
+   struct sockaddr_in addr;
16
    socklen_t addrlen;
17
    int client_fd, val;
18
    struct client *client = NULL;
19
@@ -503,7 +503,7 @@
20
    spa_list_append(&server->client_list, &client->link);
21
    server->n_clients++;
22
 
23
-   if (inet_ntop(addr.sa_family, addr.sa_data, client->name, sizeof(client->name)) == NULL)
24
+   if (inet_ntop(addr.sin_family, &addr.sin_addr.s_addr, client->name, sizeof(client->name)) == NULL)
25
        snprintf(client->name, sizeof(client->name), "client %d", client_fd);
26
 
27
    client->source = pw_loop_add_io(impl->loop,
28
pipewire-0.3.43.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.44.tar.gz/src/modules/module-raop/rtsp-client.c Changed
29
 
1
@@ -203,9 +203,12 @@
2
        if (res == 0)
3
            return -EPIPE;
4
        if (res < 0) {
5
-           if (res == EAGAIN)
6
-               return 0;
7
-           return -errno;
8
+           res = -errno;
9
+           if (res == -EINTR)
10
+               continue;
11
+           if (res != -EAGAIN && res != -EWOULDBLOCK)
12
+               return res;
13
+           return 0;
14
        }
15
        if (c == '\n') {
16
            client->line_buf[client->line_pos] = '\0';
17
@@ -435,9 +438,10 @@
18
            true, on_source_io, client);
19
 
20
    if (client->source == NULL) {
21
+       res = -errno;
22
        pw_log_error("%p: source create failed: %m", client);
23
        close(fd);
24
-       return -errno;
25
+       return res;
26
    }
27
    client->connecting = true;
28
    free(client->session_id);
29
pipewire-0.3.43.tar.gz/src/modules/module-roc-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-roc-sink.c Changed
10
 
1
@@ -441,8 +441,6 @@
2
        pw_properties_set(capture_props, PW_KEY_NODE_VIRTUAL, "true");
3
    if (pw_properties_get(capture_props, PW_KEY_NODE_NETWORK) == NULL)
4
        pw_properties_set(capture_props, PW_KEY_NODE_NETWORK, "true");
5
-   if (pw_properties_get(capture_props, PW_KEY_NODE_PASSIVE) == NULL)
6
-       pw_properties_set(capture_props, PW_KEY_NODE_PASSIVE, "true");
7
    if ((str = pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS)) == NULL)
8
        pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
9
 
10
pipewire-0.3.43.tar.gz/src/modules/module-roc-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-roc-source.c Changed
10
 
1
@@ -486,8 +486,6 @@
2
        pw_properties_set(playback_props, PW_KEY_NODE_VIRTUAL, "true");
3
    if (pw_properties_get(playback_props, PW_KEY_NODE_NETWORK) == NULL)
4
        pw_properties_set(playback_props, PW_KEY_NODE_NETWORK, "true");
5
-   if (pw_properties_get(playback_props, PW_KEY_NODE_PASSIVE) == NULL)
6
-       pw_properties_set(playback_props, PW_KEY_NODE_PASSIVE, "true");
7
    if ((str = pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS)) == NULL)
8
        pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source");
9
 
10
pipewire-0.3.43.tar.gz/src/modules/module-rt.c -> pipewire-0.3.44.tar.gz/src/modules/module-rt.c Changed
201
 
1
@@ -1,6 +1,6 @@
2
 /* PipeWire
3
  *
4
- * Copyright © 2021 Axis Communications AB
5
+ * Copyright © 2018 Wim Taymans
6
  *
7
  * Permission is hereby granted, free of charge, to any person obtaining a
8
  * copy of this software and associated documentation files (the "Software"),
9
@@ -22,76 +22,452 @@
10
  * DEALINGS IN THE SOFTWARE.
11
  */
12
 
13
-#include <errno.h>
14
-#include <sched.h>
15
-#include <stdbool.h>
16
 #include <stdlib.h>
17
-#include <unistd.h>
18
-#include <sys/types.h>
19
+#include <stdbool.h>
20
+#include <string.h>
21
+#include <stdio.h>
22
+#include <errno.h>
23
 #include <sys/stat.h>
24
-#include <sys/syscall.h>
25
-#include <sys/time.h>
26
-#include <sys/resource.h>
27
+#ifdef __FreeBSD__
28
+#include <sys/thr.h>
29
+#endif
30
+#include <fcntl.h>
31
+#include <unistd.h>
32
 #include <pthread.h>
33
+#include <sys/resource.h>
34
 
35
-#include <spa/utils/dict.h>
36
+#include "config.h"
37
+
38
+#include <spa/support/dbus.h>
39
 #include <spa/utils/result.h>
40
+#include <spa/utils/string.h>
41
 
42
 #include <pipewire/impl.h>
43
 #include <pipewire/thread.h>
44
 
45
-#include "config.h"
46
-
47
 /** \page page_module_rt PipeWire Module: RT
48
+ *
49
+ * The `rt` module uses the operating system's scheduler to enable realtime
50
+ * scheduling for certain threads to assist with low latency audio processing.
51
+ * This requires `RLIMIT_RTPRIO` to be set to a value that's equal to this
52
+ * module's `rt.prio` parameter or higher. Most distros will come with some
53
+ * package that configures this for certain groups or users. If this is not set
54
+ * up and DBus is available, then this module will fall back to using RTKit.
55
  */
56
 
57
-
58
 #define NAME "rt"
59
 
60
 PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
61
 #define PW_LOG_TOPIC_DEFAULT mod_topic
62
 
63
-#define DEFAULT_POLICY SCHED_FIFO
64
+#define REALTIME_POLICY         SCHED_FIFO
65
+#ifdef SCHED_RESET_ON_FORK
66
+#define PW_SCHED_RESET_ON_FORK  SCHED_RESET_ON_FORK
67
+#else
68
+/* FreeBSD compat */
69
+#define PW_SCHED_RESET_ON_FORK  0
70
+#endif
71
 
72
-#define DEFAULT_NICE_LEVEL -11
73
-#define DEFAULT_RT_PRIO 88
74
-#define DEFAULT_RT_TIME_SOFT 2000000
75
-#define DEFAULT_RT_TIME_HARD 2000000
76
+#define IS_VALID_NICE_LEVEL(l) ((l)>=-20 && (l)<=19)
77
 
78
-#define MODULE_USAGE \
79
-   "[nice.level=<priority: default " SPA_STRINGIFY(DEFAULT_NICE_LEVEL) ">] " \
80
-   "[rt.prio=<priority: default " SPA_STRINGIFY(DEFAULT_RT_PRIO) ">] " \
81
-   "[rt.time.soft=<in usec: default " SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] " \
82
-   "[rt.time.hard=<in usec: default " SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] "
83
+#define DEFAULT_NICE_LEVEL      20
84
+#define DEFAULT_RT_PRIO        88
85
+#define DEFAULT_RT_TIME_SOFT   -1
86
+#define DEFAULT_RT_TIME_HARD   -1
87
 
88
-#ifndef RLIMIT_RTTIME
89
-#define RLIMIT_RTTIME 15
90
-#endif
91
+#define MODULE_USAGE   "[nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL)"(don't change)>] "   \
92
+           "[rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO)">] "       \
93
+           "[rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] "   \
94
+           "[rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] "
95
 
96
 static const struct spa_dict_item module_props[] = {
97
-   { PW_KEY_MODULE_AUTHOR, "Jonas Holmberg <jonashg@axis.com>" },
98
-   { PW_KEY_MODULE_DESCRIPTION, "Set thread priorities" },
99
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
100
+   { PW_KEY_MODULE_DESCRIPTION, "Use realtime thread scheduling, falling back to RTKit" },
101
    { PW_KEY_MODULE_USAGE, MODULE_USAGE },
102
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
103
 };
104
 
105
+struct pw_rtkit_bus;
106
+
107
+struct thread {
108
+   struct impl *impl;
109
+   struct spa_list link;
110
+   pthread_t thread;
111
+   pid_t pid;
112
+   void *(*start)(void*);
113
+   void *arg;
114
+};
115
+
116
 struct impl {
117
    struct pw_context *context;
118
 
119
    struct spa_thread_utils thread_utils;
120
 
121
+   int nice_level;
122
    int rt_prio;
123
    rlim_t rt_time_soft;
124
    rlim_t rt_time_hard;
125
 
126
    struct spa_hook module_listener;
127
+
128
+   bool use_rtkit;
129
+   struct pw_rtkit_bus *system_bus;
130
+
131
+   /* These are only for the RTKit implementation to fill in the `thread`
132
+    * struct. Since there's barely any overhead here we'll do this
133
+    * regardless of which backend is used. */
134
+   pthread_mutex_t lock;
135
+   pthread_cond_t cond;
136
+   struct spa_list threads_list;
137
 };
138
 
139
+/***
140
+  Copyright 2009 Lennart Poettering
141
+  Copyright 2010 David Henningsson <diwic@ubuntu.com>
142
+
143
+  Permission is hereby granted, free of charge, to any person
144
+  obtaining a copy of this software and associated documentation files
145
+  (the "Software"), to deal in the Software without restriction,
146
+  including without limitation the rights to use, copy, modify, merge,
147
+  publish, distribute, sublicense, and/or sell copies of the Software,
148
+  and to permit persons to whom the Software is furnished to do so,
149
+  subject to the following conditions:
150
+
151
+  The above copyright notice and this permission notice shall be
152
+  included in all copies or substantial portions of the Software.
153
+
154
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
155
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
156
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
157
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
158
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
159
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
160
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
161
+  SOFTWARE.
162
+***/
163
+
164
+#include <dbus/dbus.h>
165
+
166
+#include "config.h"
167
+
168
+#include <sys/syscall.h>
169
+
170
+#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
171
+#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
172
+
173
+#ifndef RLIMIT_RTTIME
174
+#define RLIMIT_RTTIME 15
175
+#endif
176
+
177
+/** \cond */
178
+struct pw_rtkit_bus {
179
+   DBusConnection *bus;
180
+};
181
+/** \endcond */
182
+
183
+struct pw_rtkit_bus *pw_rtkit_bus_get_system(void)
184
+{
185
+   struct pw_rtkit_bus *bus;
186
+   DBusError error;
187
+
188
+   if (getenv("DISABLE_RTKIT")) {
189
+       errno = ENOTSUP;
190
+       return NULL;
191
+   }
192
+
193
+   dbus_error_init(&error);
194
+
195
+   bus = calloc(1, sizeof(struct pw_rtkit_bus));
196
+   if (bus == NULL)
197
+       return NULL;
198
+
199
+   bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
200
+   if (bus->bus == NULL)
201
pipewire-0.3.44.tar.gz/src/modules/module-x11-bell.c Added
201
 
1
@@ -0,0 +1,291 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <string.h>
27
+#include <stdio.h>
28
+#include <errno.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <fcntl.h>
32
+#include <unistd.h>
33
+
34
+#include "config.h"
35
+
36
+#include <spa/utils/string.h>
37
+
38
+#include <X11/Xlib.h>
39
+#include <X11/Xlib-xcb.h>
40
+#include <X11/XKBlib.h>
41
+
42
+#include <canberra.h>
43
+
44
+#include "pipewire/pipewire.h"
45
+#include "pipewire/impl.h"
46
+
47
+/** \page page_module_x11_bell PipeWire Module: X11 Bell
48
+ *
49
+ * The `x11-bell` module intercept the X11 bell events and uses libcanberra to
50
+ * play a sound.
51
+ *
52
+ * ## Module Options
53
+ *
54
+ * - `sink.name = <str>`: node.name of the sink to connect to
55
+ * - `sample.name = <str>`: the name of the sample to play, default 'bell-window-system'
56
+ * - `x11.display = <str>`: the X11 display to use
57
+ * - `x11.xauthority = <str>`: the X11 XAuthority string placed in XAUTHORITY env
58
+ *
59
+ * ## General options
60
+ *
61
+ * There are no general options for this module.
62
+ *
63
+ * ## Example configuration
64
+ *\code{.unparsed}
65
+ * context.modules = [
66
+ *  {   name = libpipewire-x11-bell }
67
+ *      args = {
68
+ *          #sink.name = @DEFAULT_SINK@
69
+ *          sample.name = "bell-window-system"
70
+ *          #x11.display = ":1"
71
+ *          #x11.xauthority = "test"
72
+ * ]
73
+ *\endcode
74
+ *
75
+ */
76
+
77
+#define NAME "x11-bell"
78
+
79
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
80
+#define PW_LOG_TOPIC_DEFAULT mod_topic
81
+
82
+struct impl {
83
+   struct pw_context *context;
84
+   struct pw_thread_loop *thread_loop;
85
+   struct pw_loop *loop;
86
+   struct spa_source *source;
87
+
88
+   struct pw_properties *properties;
89
+
90
+   struct spa_hook module_listener;
91
+
92
+   Display *display;
93
+   int xkb_event_base;
94
+};
95
+
96
+static int play_sample(struct impl *impl, const char *sample)
97
+{
98
+   int res;
99
+   ca_context *ca;
100
+
101
+   if ((res = ca_context_create(&ca)) < 0) {
102
+       pw_log_error("canberra context create error: %s", ca_strerror(res));
103
+       res = -EIO;
104
+       goto exit;
105
+   }
106
+   if ((res = ca_context_open(ca)) < 0) {
107
+       pw_log_error("canberra context open error: %s", ca_strerror(res));
108
+       res = -EIO;
109
+       goto exit_destroy;
110
+   }
111
+   if ((res = ca_context_play(ca, 0,
112
+           CA_PROP_EVENT_ID, sample,
113
+           CA_PROP_MEDIA_NAME, "X11 bell event",
114
+           CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
115
+           NULL)) < 0) {
116
+       pw_log_warn("can't play sample (%s): %s", sample, ca_strerror(res));
117
+   }
118
+
119
+exit_destroy:
120
+   ca_context_destroy(ca);
121
+exit:
122
+   return res;
123
+}
124
+static void display_io(void *data, int fd, uint32_t mask)
125
+{
126
+   struct impl *impl = data;
127
+   XEvent e;
128
+   const char *sample = NULL;
129
+
130
+   while (XPending(impl->display)) {
131
+       XNextEvent(impl->display, &e);
132
+
133
+       if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify)
134
+           continue;
135
+
136
+       if (impl->properties)
137
+           sample = pw_properties_get(impl->properties, "sample.name");
138
+       if (sample == NULL)
139
+           sample = "bell-window-system";
140
+
141
+       pw_log_debug("play sample %s", sample);
142
+       play_sample(impl, sample);
143
+   }
144
+}
145
+
146
+static void x11_close(struct impl *impl)
147
+{
148
+   if (impl->source) {
149
+       pw_loop_destroy_source(impl->loop, impl->source);
150
+       impl->source = NULL;
151
+   }
152
+   if (impl->display) {
153
+       XCloseDisplay(impl->display);
154
+       impl->display = NULL;
155
+   }
156
+}
157
+
158
+static int x11_connect(struct impl *impl, const char *name)
159
+{
160
+   int res, major, minor;
161
+   unsigned int auto_ctrls, auto_values;
162
+
163
+   if (!(impl->display = XOpenDisplay(name))) {
164
+       pw_log_warn("XOpenDisplay() failed");
165
+       res = -EIO;
166
+       goto error;
167
+   }
168
+
169
+   impl->source = pw_loop_add_io(impl->loop,
170
+           ConnectionNumber(impl->display),
171
+           SPA_IO_IN, false, display_io, impl);
172
+
173
+   major = XkbMajorVersion;
174
+   minor = XkbMinorVersion;
175
+
176
+   if (!XkbLibraryVersion(&major, &minor)) {
177
+       pw_log_warn("XkbLibraryVersion() failed");
178
+       res = -EIO;
179
+       goto error;
180
+   }
181
+
182
+   major = XkbMajorVersion;
183
+   minor = XkbMinorVersion;
184
+
185
+   if (!XkbQueryExtension(impl->display, NULL, &impl->xkb_event_base,
186
+               NULL, &major, &minor)) {
187
+       res = -EIO;
188
+       pw_log_warn("XkbQueryExtension() failed");
189
+       goto error;
190
+   }
191
+
192
+   XkbSelectEvents(impl->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask);
193
+   auto_ctrls = auto_values = XkbAudibleBellMask;
194
+   XkbSetAutoResetControls(impl->display, XkbAudibleBellMask, &auto_ctrls, &auto_values);
195
+   XkbChangeEnabledControls(impl->display, XkbUseCoreKbd, XkbAudibleBellMask, 0);
196
+
197
+   res = 0;
198
+error:
199
+   if (res < 0)
200
+       x11_close(impl);
201
pipewire-0.3.43.tar.gz/src/modules/spa/spa-node.c -> pipewire-0.3.44.tar.gz/src/modules/spa/spa-node.c Changed
15
 
1
@@ -242,6 +242,13 @@
2
    int res;
3
    struct spa_handle *handle;
4
    void *iface;
5
+   const struct pw_properties *p;
6
+
7
+   if (properties) {
8
+       p = pw_context_get_properties(context);
9
+       pw_properties_set(properties, "clock.quantum-limit",
10
+               pw_properties_get(p, "default.clock.quantum-limit"));
11
+   }
12
 
13
    handle = pw_context_load_spa_handle(context,
14
            factory_name,
15
pipewire-0.3.43.tar.gz/src/pipewire/conf.c -> pipewire-0.3.44.tar.gz/src/pipewire/conf.c Changed
19
 
1
@@ -49,7 +49,7 @@
2
 PW_LOG_TOPIC_EXTERN(log_conf);
3
 #define PW_LOG_TOPIC_DEFAULT log_conf
4
 
5
-static int make_path(char *path, int size, const char *paths[])
6
+static int make_path(char *path, size_t size, const char *paths[])
7
 {
8
    int i, len;
9
    char *p = path;
10
@@ -57,7 +57,7 @@
11
        len = snprintf(p, size, "%s%s", i == 0 ? "" : "/", paths[i]);
12
        if (len < 0)
13
            return -errno;
14
-       if (len >= size)
15
+       if ((size_t)len >= size)
16
            return -ENOSPC;
17
        p += len;
18
        size -= len;
19
pipewire-0.3.43.tar.gz/src/pipewire/context.c -> pipewire-0.3.44.tar.gz/src/pipewire/context.c Changed
140
 
1
@@ -134,7 +134,8 @@
2
        res = pw_thread_utils_drop_rt(thr);
3
    } else {
4
        pw_log_info("%p: exit freewheel", context);
5
-       res = pw_thread_utils_acquire_rt(thr, 88);
6
+       // Use the priority as configured within the realtime module
7
+       res = pw_thread_utils_acquire_rt(thr, -1);
8
    }
9
    if (res < 0)
10
        pw_log_info("%p: freewheel error:%s", context, spa_strerror(res));
11
@@ -893,24 +894,31 @@
12
    return pw_impl_node_set_state(node, state);
13
 }
14
 
15
-static int collect_nodes(struct pw_context *context, struct pw_impl_node *driver)
16
+static int collect_nodes(struct pw_context *context, struct pw_impl_node *node)
17
 {
18
    struct spa_list queue;
19
-   struct pw_impl_node *n, *t;
20
+   struct pw_impl_node *n, *t, *driver;
21
    struct pw_impl_port *p;
22
    struct pw_impl_link *l;
23
 
24
-   spa_list_consume(t, &driver->follower_list, follower_link) {
25
-       spa_list_remove(&t->follower_link);
26
-       spa_list_init(&t->follower_link);
27
-   }
28
+   pw_log_debug("node %p: '%s'", node, node->name);
29
 
30
-   pw_log_debug("driver %p: '%s'", driver, driver->name);
31
+   if (node->driver) {
32
+       driver = node;
33
+       spa_list_consume(t, &driver->follower_list, follower_link) {
34
+           spa_list_remove(&t->follower_link);
35
+           spa_list_init(&t->follower_link);
36
+       }
37
+   } else {
38
+       driver = node->driver_node;
39
+       if (driver == NULL)
40
+           return -EINVAL;
41
+   }
42
 
43
-   /* start with driver in the queue */
44
+   /* start with node in the queue */
45
    spa_list_init(&queue);
46
-   spa_list_append(&queue, &driver->sort_link);
47
-   driver->visited = true;
48
+   spa_list_append(&queue, &node->sort_link);
49
+   node->visited = true;
50
 
51
    /* now follow all the links from the nodes in the queue
52
     * and add the peers to the queue. */
53
@@ -980,26 +988,32 @@
54
 }
55
 
56
 static inline void get_quantums(struct pw_context *context, uint32_t *def,
57
-       uint32_t *min, uint32_t *max, uint32_t *rate)
58
+       uint32_t *min, uint32_t *max, uint32_t *limit, uint32_t *rate)
59
 {
60
    struct settings *s = &context->settings;
61
-   *def = s->clock_force_quantum == 0 ? s->clock_quantum : s->clock_force_quantum;
62
-   *min = s->clock_force_quantum == 0 ? s->clock_min_quantum : s->clock_force_quantum;
63
-   *max = s->clock_force_quantum == 0 ? s->clock_max_quantum : s->clock_force_quantum;
64
-   *rate = s->clock_force_quantum == 0 ? s->clock_rate : s->clock_force_rate;
65
+   if (s->clock_force_quantum != 0) {
66
+       *def = *min = *max = s->clock_force_quantum;
67
+       *rate = 0;
68
+   } else {
69
+       *def = s->clock_quantum;
70
+       *min = s->clock_min_quantum;
71
+       *max = s->clock_max_quantum;
72
+       *rate = s->clock_rate;
73
+   }
74
+   *limit = s->clock_quantum_limit;
75
 }
76
 
77
 static inline uint32_t *get_rates(struct pw_context *context, uint32_t *def, uint32_t *n_rates,
78
-       bool *force_rate)
79
+       bool *force)
80
 {
81
    struct settings *s = &context->settings;
82
    if (s->clock_force_rate != 0) {
83
-       *force_rate = true;
84
+       *force = true;
85
        *n_rates = 1;
86
        *def = s->clock_force_rate;
87
        return &s->clock_force_rate;
88
    } else {
89
-       *force_rate = false;
90
+       *force = false;
91
        *n_rates = s->n_clock_rates;
92
        *def = s->clock_rate;
93
        return s->clock_rates;
94
@@ -1053,7 +1067,7 @@
95
 {
96
    struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this);
97
    struct pw_impl_node *n, *s, *target, *fallback;
98
-   uint32_t max_quantum, min_quantum, def_quantum, rate_quantum;
99
+   uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum;
100
    uint32_t *rates, n_rates, def_rate;
101
    bool freewheel = false, force_rate;
102
 
103
@@ -1067,7 +1081,7 @@
104
 again:
105
    impl->recalc = true;
106
 
107
-   get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum);
108
+   get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum);
109
    rates = get_rates(context, &def_rate, &n_rates, &force_rate);
110
 
111
    /* start from all drivers and group all nodes that are linked
112
@@ -1135,8 +1149,10 @@
113
            pw_impl_node_set_driver(n, t);
114
            if (t == NULL)
115
                ensure_state(n, false);
116
-           else
117
+           else {
118
                t->passive = false;
119
+               collect_nodes(context, n);
120
+           }
121
        }
122
        n->visited = false;
123
    }
124
@@ -1221,6 +1237,7 @@
125
        if (rate_quantum != 0 && current_rate != rate_quantum) {
126
            def_quantum = def_quantum * current_rate / rate_quantum;
127
            min_quantum = min_quantum * current_rate / rate_quantum;
128
+           max_quantum = max_quantum * current_rate / rate_quantum;
129
        }
130
 
131
        /* calculate desired quantum */
132
@@ -1234,6 +1251,7 @@
133
        if (latency.denom != 0)
134
            quantum = (latency.num * current_rate / latency.denom);
135
        quantum = SPA_CLAMP(quantum, min_quantum, max_quantum);
136
+       quantum = SPA_MIN(quantum, lim_quantum);
137
 
138
        if (context->settings.clock_power_of_two_quantum)
139
            quantum = flp2(quantum);
140
pipewire-0.3.43.tar.gz/src/pipewire/filter.c -> pipewire-0.3.44.tar.gz/src/pipewire/filter.c Changed
36
 
1
@@ -52,7 +52,6 @@
2
 #define MASK_BUFFERS   (MAX_BUFFERS-1)
3
 #define MAX_PORTS  1024
4
 
5
-static float empty[MAX_SAMPLES];
6
 static bool mlock_warned = false;
7
 
8
 static uint32_t mappable_dataTypes = (1<<SPA_DATA_MemFd);
9
@@ -1223,6 +1222,17 @@
10
    }
11
    if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
12
        pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
13
+   if ((str = getenv("PIPEWIRE_RATE")) != NULL)
14
+       pw_properties_set(props, PW_KEY_NODE_RATE, str);
15
+   if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) {
16
+       struct spa_fraction q;
17
+       if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) {
18
+           pw_properties_setf(props, PW_KEY_NODE_RATE,
19
+                   "1/%u", q.denom);
20
+           pw_properties_setf(props, PW_KEY_NODE_LATENCY,
21
+                   "%u/%u", q.num, q.denom);
22
+       }
23
+   }
24
 
25
    spa_hook_list_init(&impl->hooks);
26
    this->properties = props;
27
@@ -1860,7 +1870,7 @@
28
    struct spa_data *d;
29
 
30
    if ((buf = pw_filter_dequeue_buffer(port_data)) == NULL)
31
-       return empty;
32
+       return NULL;
33
 
34
    d = &buf->buffer->datas[0];
35
 
36
pipewire-0.3.43.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-link.c Changed
86
 
1
@@ -451,7 +451,7 @@
2
    return res;
3
 }
4
 
5
-static int select_io(struct pw_impl_link *this)
6
+static void select_io(struct pw_impl_link *this)
7
 {
8
    struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
9
    struct spa_io_buffers *io;
10
@@ -461,13 +461,9 @@
11
        io = this->rt.out_mix.io;
12
    if (io == NULL)
13
        io = &impl->io;
14
-   if (io == NULL)
15
-       return -EIO;
16
 
17
    this->io = io;
18
    *this->io = SPA_IO_BUFFERS_INIT;
19
-
20
-   return 0;
21
 }
22
 
23
 static int do_allocation(struct pw_impl_link *this)
24
@@ -1133,7 +1129,7 @@
25
 
26
    if (check_permission(this->context, this->output, this->input, this->properties) < 0) {
27
        pw_impl_link_destroy(this);
28
-   } else {
29
+   } else if (this->global != NULL) {
30
        pw_global_update_permissions(this->global, client, old, new);
31
    }
32
 }
33
@@ -1229,6 +1225,16 @@
34
    spa_hook_list_init(&this->listener_list);
35
 
36
    impl->format_filter = format_filter;
37
+   this->info.format = NULL;
38
+   this->info.props = &this->properties->dict;
39
+
40
+   this->rt.out_mix.peer_id = input->global->id;
41
+   this->rt.in_mix.peer_id = output->global->id;
42
+
43
+   if ((res = pw_impl_port_init_mix(output, &this->rt.out_mix)) < 0)
44
+       goto error_output_mix;
45
+   if ((res = pw_impl_port_init_mix(input, &this->rt.in_mix)) < 0)
46
+       goto error_input_mix;
47
 
48
    pw_impl_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl);
49
    pw_impl_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl);
50
@@ -1245,19 +1251,9 @@
51
    spa_list_append(&output->links, &this->output_link);
52
    spa_list_append(&input->links, &this->input_link);
53
 
54
-   this->info.format = NULL;
55
-   this->info.props = &this->properties->dict;
56
-
57
    impl->io = SPA_IO_BUFFERS_INIT;
58
 
59
-   this->rt.out_mix.peer_id = input->global->id;
60
-   this->rt.in_mix.peer_id = output->global->id;
61
-
62
-   pw_impl_port_init_mix(output, &this->rt.out_mix);
63
-   pw_impl_port_init_mix(input, &this->rt.in_mix);
64
-
65
-   if ((res = select_io(this)) < 0)
66
-       goto error_no_io;
67
+   select_io(this);
68
 
69
    if (this->feedback) {
70
        impl->inode = output_node;
71
@@ -1317,8 +1313,12 @@
72
    res = -errno;
73
    pw_log_debug("work queue failed: %m");
74
    goto error_free;
75
-error_no_io:
76
-   pw_log_debug("%p: can't set io %d (%s)", this, res, spa_strerror(res));
77
+error_output_mix:
78
+   pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res));
79
+   goto error_free;
80
+error_input_mix:
81
+   pw_log_error("%p: can't get input mix %d (%s)", this, res, spa_strerror(res));
82
+   pw_impl_port_release_mix(output, &this->rt.out_mix);
83
    goto error_free;
84
 error_free:
85
    free(impl);
86
pipewire-0.3.43.tar.gz/src/pipewire/impl-metadata.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-metadata.c Changed
19
 
1
@@ -523,14 +523,15 @@
2
 int pw_impl_metadata_register(struct pw_impl_metadata *metadata,
3
             struct pw_properties *properties)
4
 {
5
+   struct pw_context *context = metadata->context;
6
    static const char * const keys[] = {
7
+       PW_KEY_OBJECT_SERIAL,
8
        PW_KEY_MODULE_ID,
9
+       PW_KEY_FACTORY_ID,
10
        PW_KEY_METADATA_NAME,
11
        NULL
12
    };
13
 
14
-   struct pw_context *context = metadata->context;
15
-
16
    if (metadata->registered)
17
        goto error_existed;
18
 
19
pipewire-0.3.43.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-module.c Changed
33
 
1
@@ -171,6 +171,11 @@
2
    const char *state = NULL, *p;
3
    size_t len;
4
    char path_part[PATH_MAX];
5
+   static const char * const keys[] = {
6
+       PW_KEY_OBJECT_SERIAL,
7
+       PW_KEY_MODULE_NAME,
8
+       NULL
9
+   };
10
 
11
    module_dir = getenv("PIPEWIRE_MODULE_DIR");
12
    if (module_dir == NULL) {
13
@@ -234,9 +239,7 @@
14
    this->global = pw_global_new(context,
15
                     PW_TYPE_INTERFACE_Module,
16
                     PW_VERSION_MODULE,
17
-                    pw_properties_new(
18
-                        PW_KEY_MODULE_NAME, name,
19
-                        NULL),
20
+                    NULL,
21
                     global_bind,
22
                     this);
23
 
24
@@ -251,6 +254,8 @@
25
            pw_global_get_serial(this->global));
26
    this->info.props = &this->properties->dict;
27
 
28
+   pw_global_update_keys(this->global, &this->properties->dict, keys);
29
+
30
    pw_impl_module_emit_initialized(this);
31
 
32
    pw_global_add_listener(this->global, &this->global_listener, &global_events, this);
33
pipewire-0.3.43.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-node.c Changed
48
 
1
@@ -59,6 +59,7 @@
2
    struct spa_list pending_list;
3
 
4
    unsigned int pause_on_idle:1;
5
+   unsigned int suspend_on_idle:1;
6
    unsigned int cache_params:1;
7
    unsigned int pending_play:1;
8
 };
9
@@ -387,6 +388,10 @@
10
        spa_list_for_each(resource, &node->global->resource_list, link)
11
            pw_resource_error(resource, res, error);
12
    }
13
+   if (old == PW_NODE_STATE_RUNNING &&
14
+       state == PW_NODE_STATE_IDLE &&
15
+       impl->suspend_on_idle)
16
+        pw_impl_node_set_state(node, PW_NODE_STATE_SUSPENDED);
17
 }
18
 
19
 static int suspend_node(struct pw_impl_node *this)
20
@@ -867,8 +872,9 @@
21
    }
22
 
23
    impl->pause_on_idle = pw_properties_get_bool(node->properties, PW_KEY_NODE_PAUSE_ON_IDLE, true);
24
+   impl->suspend_on_idle = pw_properties_get_bool(node->properties, PW_KEY_NODE_SUSPEND_ON_IDLE, false);
25
    impl->cache_params =  pw_properties_get_bool(node->properties, PW_KEY_NODE_CACHE_PARAMS, true);
26
-   node->transport_sync = pw_properties_get_bool(node->properties, "node.transport.sync", false);
27
+   node->transport_sync = pw_properties_get_bool(node->properties, PW_KEY_NODE_TRANSPORT_SYNC, false);
28
    driver = pw_properties_get_bool(node->properties, PW_KEY_NODE_DRIVER, false);
29
 
30
    if (node->driver != driver) {
31
@@ -1654,6 +1660,16 @@
32
    if (SPA_UNLIKELY(node->driver && !node->driving))
33
        return 0;
34
 
35
+   if (!node->driver) {
36
+       struct timespec ts;
37
+       struct pw_node_activation *a = node->rt.activation;
38
+       struct spa_system *data_system = node->context->data_system;
39
+
40
+       spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts);
41
+       a->status = PW_NODE_ACTIVATION_AWAKE;
42
+       a->signal_time = a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts);
43
+   }
44
+
45
    if (status & SPA_STATUS_HAVE_DATA) {
46
        spa_list_for_each(p, &node->rt.output_mix, rt.node_link)
47
            spa_node_process(p->mix);
48
pipewire-0.3.43.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-port.c Changed
96
 
1
@@ -214,16 +214,16 @@
2
    if (port_id == SPA_ID_INVALID)
3
        return -errno;
4
 
5
+   if ((res = spa_node_add_port(port->mix, port->direction, port_id, NULL)) < 0 &&
6
+       res != -ENOTSUP)
7
+       goto error_remove_map;
8
+
9
    mix->port.direction = port->direction;
10
    mix->port.port_id = port_id;
11
-
12
-   spa_list_append(&port->mix_list, &mix->link);
13
-   port->n_mix++;
14
    mix->p = port;
15
 
16
-   spa_node_add_port(port->mix, port->direction, port_id, NULL);
17
-
18
-   res = pw_impl_port_call_init_mix(port, mix);
19
+   if ((res = pw_impl_port_call_init_mix(port, mix)) < 0)
20
+       goto error_remove_port;
21
 
22
    /* set the same format on the mixer as on the port if any */
23
    {
24
@@ -242,11 +242,20 @@
25
        }
26
    }
27
 
28
+   spa_list_append(&port->mix_list, &mix->link);
29
+   port->n_mix++;
30
+
31
    pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port,
32
            port->n_mix, port->port_id, mix->port.port_id,
33
            mix->io, spa_strerror(res));
34
 
35
    return res;
36
+
37
+error_remove_port:
38
+   spa_node_remove_port(port->mix, port->direction, port_id);
39
+error_remove_map:
40
+   pw_map_remove(&port->mix_port_map, port_id);
41
+   return res;
42
 }
43
 
44
 SPA_EXPORT
45
@@ -261,7 +270,9 @@
46
 
47
    res = pw_impl_port_call_release_mix(port, mix);
48
 
49
-   spa_node_remove_port(port->mix, port->direction, port_id);
50
+   if ((res = spa_node_remove_port(port->mix, port->direction, port_id)) < 0 &&
51
+       res != -ENOTSUP)
52
+       pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res));
53
 
54
    pw_log_debug("%p: release mix %d %d.%d", port,
55
            port->n_mix, port->port_id, mix->port.port_id);
56
@@ -583,8 +594,10 @@
57
    int res;
58
    const char *fallback_lib, *factory_name;
59
    struct spa_handle *handle;
60
-   struct spa_dict_item items[1];
61
+   struct spa_dict_item items[2];
62
+   char quantum_limit[16];
63
    void *iface;
64
+   struct pw_context *context = port->node->context;
65
 
66
    if ((res = spa_format_parse(param, &media_type, &media_subtype)) < 0)
67
        return res;
68
@@ -634,7 +647,11 @@
69
    }
70
 
71
    items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_LIBRARY_NAME, fallback_lib);
72
-   handle = pw_context_load_spa_handle(port->node->context, factory_name,
73
+   spa_scnprintf(quantum_limit, sizeof(quantum_limit), "%u",
74
+           context->settings.clock_quantum_limit);
75
+   items[1] = SPA_DICT_ITEM_INIT("clock.quantum-limit", quantum_limit);
76
+
77
+   handle = pw_context_load_spa_handle(context, factory_name,
78
            &SPA_DICT_INIT_ARRAY(items));
79
    if (handle == NULL)
80
        return -errno;
81
@@ -1070,10 +1087,12 @@
82
    }
83
 
84
    if (port->direction == PW_DIRECTION_INPUT) {
85
-       pw_map_insert_at(&node->input_port_map, port->port_id, NULL);
86
+       if ((res = pw_map_insert_at(&node->input_port_map, port->port_id, NULL)) < 0)
87
+           pw_log_warn("%p: can't remove input port: %s", port, spa_strerror(res));
88
        node->info.n_input_ports--;
89
    } else {
90
-       pw_map_insert_at(&node->output_port_map, port->port_id, NULL);
91
+       if ((res = pw_map_insert_at(&node->output_port_map, port->port_id, NULL)) < 0)
92
+           pw_log_warn("%p: can't remove output port: %s", port, spa_strerror(res));
93
        node->info.n_output_ports--;
94
    }
95
 
96
pipewire-0.3.43.tar.gz/src/pipewire/keys.h -> pipewire-0.3.44.tar.gz/src/pipewire/keys.h Changed
20
 
1
@@ -171,7 +171,9 @@
2
 #define PW_KEY_NODE_WANT_DRIVER        "node.want-driver"  /**< the node wants to be grouped with a driver
3
                                  *  node in order to schedule the graph. */
4
 #define PW_KEY_NODE_PAUSE_ON_IDLE  "node.pause-on-idle"    /**< pause the node when idle */
5
+#define PW_KEY_NODE_SUSPEND_ON_IDLE    "node.suspend-on-idle"  /**< suspend the node when idle */
6
 #define PW_KEY_NODE_CACHE_PARAMS   "node.cache-params" /**< cache the node params */
7
+#define PW_KEY_NODE_TRANSPORT_SYNC "node.transport.sync"   /**< the node handles transport sync */
8
 #define PW_KEY_NODE_DRIVER     "node.driver"       /**< node can drive the graph */
9
 #define PW_KEY_NODE_STREAM     "node.stream"       /**< node is a stream, the server side should
10
                                  *  add a converter */
11
@@ -326,6 +328,8 @@
12
 #define PW_KEY_PRIORITY_MASTER     "priority.master"   /**< deprecated */
13
 #endif /* PW_ENABLE_DEPRECATED */
14
 
15
+#define PW_KEY_TARGET_OBJECT       "target.object"     /**< a target object to link to */
16
+
17
 /** \}
18
  */
19
 
20
pipewire-0.3.43.tar.gz/src/pipewire/private.h -> pipewire-0.3.44.tar.gz/src/pipewire/private.h Changed
26
 
1
@@ -51,7 +51,7 @@
2
 
3
 #define MAX_RATES              16u
4
 #define CLOCK_MIN_QUANTUM          4u
5
-#define CLOCK_MAX_QUANTUM          8192u
6
+#define CLOCK_MAX_QUANTUM          65536u
7
 
8
 struct settings {
9
    uint32_t log_level;
10
@@ -61,12 +61,15 @@
11
    uint32_t clock_quantum;         /* default quantum */
12
    uint32_t clock_min_quantum;     /* min quantum */
13
    uint32_t clock_max_quantum;     /* max quantum */
14
+   uint32_t clock_quantum_limit;       /* quantum limit */
15
    struct spa_rectangle video_size;
16
    struct spa_fraction video_rate;
17
    uint32_t link_max_buffers;
18
    unsigned int mem_warn_mlock:1;
19
    unsigned int mem_allow_mlock:1;
20
    unsigned int clock_power_of_two_quantum:1;
21
+   unsigned int check_quantum:1;
22
+   unsigned int check_rate:1;
23
 #define CLOCK_RATE_UPDATE_MODE_HARD 0
24
 #define CLOCK_RATE_UPDATE_MODE_SOFT 1
25
    int clock_rate_update_mode;
26
pipewire-0.3.43.tar.gz/src/pipewire/settings.c -> pipewire-0.3.44.tar.gz/src/pipewire/settings.c Changed
71
 
1
@@ -43,7 +43,8 @@
2
 #define DEFAULT_CLOCK_RATE         48000u
3
 #define DEFAULT_CLOCK_QUANTUM          1024u
4
 #define DEFAULT_CLOCK_MIN_QUANTUM      32u
5
-#define DEFAULT_CLOCK_MAX_QUANTUM      8192u
6
+#define DEFAULT_CLOCK_MAX_QUANTUM      2048u
7
+#define DEFAULT_CLOCK_QUANTUM_LIMIT        8192u
8
 #define DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM true
9
 #define DEFAULT_VIDEO_WIDTH            640
10
 #define DEFAULT_VIDEO_HEIGHT           480
11
@@ -52,6 +53,8 @@
12
 #define DEFAULT_LINK_MAX_BUFFERS       64u
13
 #define DEFAULT_MEM_WARN_MLOCK         false
14
 #define DEFAULT_MEM_ALLOW_MLOCK            true
15
+#define DEFAULT_CHECK_QUANTUM          false
16
+#define DEFAULT_CHECK_RATE         false
17
 
18
 struct impl {
19
    struct pw_context *context;
20
@@ -184,12 +187,23 @@
21
        recalc = true;
22
    } else if (spa_streq(key, "clock.force-rate")) {
23
        v = value ? atoi(value) : 0;
24
-       s->clock_force_rate = v;
25
-       recalc = true;
26
+       if (v != 0 && s->check_rate &&
27
+           !uint32_array_contains(s->clock_rates, s->n_clock_rates, v)) {
28
+           pw_log_info("invalid %s: %d not in allowed rates", key, v);
29
+       } else {
30
+           s->clock_force_rate = v;
31
+           recalc = true;
32
+       }
33
    } else if (spa_streq(key, "clock.force-quantum")) {
34
        v = value ? atoi(value) : 0;
35
-       s->clock_force_quantum = SPA_MIN(v, 8192u);
36
-       recalc = true;
37
+       if (v != 0 && s->check_quantum &&
38
+           (v < s->clock_min_quantum || v > s->clock_max_quantum)) {
39
+           pw_log_info("invalid %s: %d not in (%d-%d)", key, v,
40
+                   s->clock_min_quantum, s->clock_max_quantum);
41
+       } else {
42
+           s->clock_force_quantum = v;
43
+           recalc = true;
44
+       }
45
    }
46
    if (recalc)
47
        pw_context_recalc_graph(context, "settings changed");
48
@@ -213,6 +227,7 @@
49
    d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
50
    d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM);
51
    d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM);
52
+   d->clock_quantum_limit = get_default_int(p, "default.clock.quantum-limit", DEFAULT_CLOCK_QUANTUM_LIMIT);
53
    d->video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH);
54
    d->video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT);
55
    d->video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM);
56
@@ -225,8 +240,13 @@
57
    d->mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK);
58
    d->mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK);
59
 
60
-   d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum,
61
+   d->check_quantum = get_default_bool(p, "settings.check-quantum", DEFAULT_CHECK_QUANTUM);
62
+   d->check_rate = get_default_bool(p, "settings.check-rate", DEFAULT_CHECK_RATE);
63
+
64
+   d->clock_quantum_limit = SPA_CLAMP(d->clock_quantum_limit,
65
            CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM);
66
+   d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum,
67
+           CLOCK_MIN_QUANTUM, d->clock_quantum_limit);
68
    d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum,
69
            CLOCK_MIN_QUANTUM, d->clock_max_quantum);
70
    d->clock_quantum = SPA_CLAMP(d->clock_quantum,
71
pipewire-0.3.43.tar.gz/src/pipewire/stream.c -> pipewire-0.3.44.tar.gz/src/pipewire/stream.c Changed
19
 
1
@@ -1358,6 +1358,17 @@
2
    }
3
    if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
4
        pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
5
+   if ((str = getenv("PIPEWIRE_RATE")) != NULL)
6
+       pw_properties_set(props, PW_KEY_NODE_RATE, str);
7
+   if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) {
8
+       struct spa_fraction q;
9
+       if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) {
10
+           pw_properties_setf(props, PW_KEY_NODE_RATE,
11
+                   "1/%u", q.denom);
12
+           pw_properties_setf(props, PW_KEY_NODE_LATENCY,
13
+                   "%u/%u", q.num, q.denom);
14
+       }
15
+   }
16
 
17
    spa_hook_list_init(&impl->hooks);
18
    this->properties = props;
19
pipewire-0.3.43.tar.gz/src/tests/meson.build -> pipewire-0.3.44.tar.gz/src/tests/meson.build Changed
14
 
1
@@ -13,9 +13,9 @@
2
       install : installed_tests_enabled,
3
       install_dir : installed_tests_execdir),
4
     env : [
5
-      'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')),
6
-      'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'confdatadir')),
7
-      'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'moduledir')),
8
+      'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')),
9
+      'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable('confdatadir')),
10
+      'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable('moduledir')),
11
       ])
12
 
13
   if installed_tests_enabled
14
pipewire-0.3.43.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.44.tar.gz/src/tools/pw-cat.c Changed
15
 
1
@@ -1906,9 +1906,10 @@
2
            spa_list_for_each(target, &data.targets, link) {
3
                if (target->type != TARGET_TYPE_SINK)
4
                    continue;
5
-               printf("%s\t%"PRIu32": sink description=\"%s\" prio=%d\n",
6
-                      target == target_default ? "*" : "",
7
-                      target->id, target->desc, target->prio);
8
+               printf("%s\t%"PRIu32": %s description=\"%s\" prio=%d\n",
9
+                   target == target_default ? "*" : "",
10
+                   target->id, data.mode == mode_record ? "monitor" : "sink",
11
+                   target->desc, target->prio);
12
            }
13
            spa_list_for_each(target, &data.targets, link) {
14
                if (target->type != TARGET_TYPE_STREAM)
15
pipewire-0.3.43.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.44.tar.gz/src/tools/pw-cli.c Changed
201
 
1
@@ -32,6 +32,7 @@
2
 #include <alloca.h>
3
 #endif
4
 #include <getopt.h>
5
+#include <fnmatch.h>
6
 #include <readline/readline.h>
7
 #include <readline/history.h>
8
 
9
@@ -41,7 +42,7 @@
10
 #include <spa/utils/string.h>
11
 #include <spa/debug/pod.h>
12
 #include <spa/utils/keys.h>
13
-#include <spa/utils/json.h>
14
+#include <spa/utils/json-pod.h>
15
 #include <spa/pod/builder.h>
16
 
17
 #include <pipewire/impl.h>
18
@@ -53,6 +54,18 @@
19
 static char prompt[64];
20
 
21
 struct remote_data;
22
+struct proxy_data;
23
+
24
+typedef void (*info_func_t) (struct proxy_data *pd);
25
+
26
+struct class {
27
+   const char *type;
28
+   uint32_t version;
29
+   const void *events;
30
+   pw_destroy_t destroy;
31
+   info_func_t info;
32
+   const char *name_key;
33
+};
34
 
35
 struct data {
36
    struct pw_main_loop *loop;
37
@@ -73,6 +86,7 @@
38
    uint32_t permissions;
39
    uint32_t version;
40
    char *type;
41
+   const struct class *class;
42
    struct pw_proxy *proxy;
43
    bool info_pending;
44
    struct pw_properties *properties;
45
@@ -96,19 +110,15 @@
46
    struct pw_map globals;
47
 };
48
 
49
-struct proxy_data;
50
-
51
-typedef void (*info_func_t) (struct proxy_data *pd);
52
 
53
 struct proxy_data {
54
    struct remote_data *rd;
55
    struct global *global;
56
    struct pw_proxy *proxy;
57
-        void *info;
58
-   info_func_t info_func;
59
-        pw_destroy_t destroy;
60
-        struct spa_hook proxy_listener;
61
-        struct spa_hook object_listener;
62
+   void *info;
63
+   const struct class *class;
64
+   struct spa_hook proxy_listener;
65
+   struct spa_hook object_listener;
66
 };
67
 
68
 struct command {
69
@@ -303,6 +313,29 @@
70
    }
71
 }
72
 
73
+static bool global_matches(struct global *g, const char *pattern)
74
+{
75
+   const char *str;
76
+
77
+   if (g->properties == NULL)
78
+       return false;
79
+
80
+   if (strstr(g->type, pattern) != NULL)
81
+       return true;
82
+   if ((str = pw_properties_get(g->properties, PW_KEY_OBJECT_PATH)) != NULL &&
83
+       fnmatch(pattern, str, FNM_EXTMATCH) == 0)
84
+       return true;
85
+   if ((str = pw_properties_get(g->properties, PW_KEY_OBJECT_SERIAL)) != NULL &&
86
+       spa_streq(pattern, str))
87
+       return true;
88
+   if (g->class != NULL && g->class->name_key != NULL &&
89
+       (str = pw_properties_get(g->properties, g->class->name_key)) != NULL &&
90
+       fnmatch(pattern, str, FNM_EXTMATCH) == 0)
91
+       return true;
92
+
93
+   return false;
94
+}
95
+
96
 static int print_global(void *obj, void *data)
97
 {
98
    struct global *global = obj;
99
@@ -311,7 +344,7 @@
100
    if (global == NULL)
101
        return 0;
102
 
103
-   if (filter && !strstr(global->type, filter))
104
+   if (filter && !global_matches(global, filter))
105
        return 0;
106
 
107
    fprintf(stdout, "\tid %d, type %s/%d\n", global->id,
108
@@ -403,6 +436,24 @@
109
    .global_remove = registry_event_global_remove,
110
 };
111
 
112
+static struct global *find_global(struct remote_data *rd, const char *pattern)
113
+{
114
+   uint32_t id;
115
+   union pw_map_item *item;
116
+
117
+   if (spa_atou32(pattern, &id, 0))
118
+       return pw_map_lookup(&rd->globals, id);
119
+
120
+   pw_array_for_each(item, &rd->globals.items) {
121
+       struct global *g = item->data;
122
+       if (pw_map_item_is_free(item) || g == NULL)
123
+           continue;
124
+       if (global_matches(g, pattern))
125
+           return g;
126
+        }
127
+   return NULL;
128
+}
129
+
130
 static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message)
131
 {
132
    struct remote_data *rd = _data;
133
@@ -1106,14 +1157,14 @@
134
    spa_hook_remove(&pd->proxy_listener);
135
    spa_hook_remove(&pd->object_listener);
136
 
137
-   if (pd->info == NULL)
138
-       return;
139
-
140
    if (pd->global)
141
        pd->global->proxy = NULL;
142
 
143
-   if (pd->destroy)
144
-       pd->destroy(pd->info);
145
+   if (pd->info == NULL)
146
+       return;
147
+
148
+   if (pd->class->destroy)
149
+       pd->class->destroy(pd->info);
150
    pd->info = NULL;
151
 }
152
 
153
@@ -1130,88 +1181,150 @@
154
    return true;
155
 }
156
 
157
+static const struct class core_class = {
158
+   .type = PW_TYPE_INTERFACE_Core,
159
+   .version = PW_VERSION_CORE,
160
+   .events = &core_events,
161
+   .destroy = (pw_destroy_t) pw_core_info_free,
162
+   .info = info_core,
163
+   .name_key = PW_KEY_CORE_NAME,
164
+};
165
+static const struct class module_class = {
166
+   .type = PW_TYPE_INTERFACE_Module,
167
+   .version = PW_VERSION_MODULE,
168
+   .events = &module_events,
169
+   .destroy = (pw_destroy_t) pw_module_info_free,
170
+   .info = info_module,
171
+   .name_key = PW_KEY_MODULE_NAME,
172
+};
173
+
174
+static const struct class factory_class = {
175
+   .type = PW_TYPE_INTERFACE_Factory,
176
+   .version = PW_VERSION_FACTORY,
177
+   .events = &factory_events,
178
+   .destroy = (pw_destroy_t) pw_factory_info_free,
179
+   .info = info_factory,
180
+   .name_key = PW_KEY_FACTORY_NAME,
181
+};
182
+
183
+static const struct class client_class = {
184
+   .type = PW_TYPE_INTERFACE_Client,
185
+   .version = PW_VERSION_CLIENT,
186
+   .events = &client_events,
187
+   .destroy = (pw_destroy_t) pw_client_info_free,
188
+   .info = info_client,
189
+   .name_key = PW_KEY_APP_NAME,
190
+};
191
+static const struct class device_class = {
192
+   .type = PW_TYPE_INTERFACE_Device,
193
+   .version = PW_VERSION_DEVICE,
194
+   .events = &device_events,
195
+   .destroy = (pw_destroy_t) pw_device_info_free,
196
+   .info = info_device,
197
+   .name_key = PW_KEY_DEVICE_NAME,
198
+};
199
+static const struct class node_class = {
200
+   .type = PW_TYPE_INTERFACE_Node,
201
pipewire-0.3.43.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.44.tar.gz/src/tools/pw-dump.c Changed
153
 
1
@@ -30,6 +30,7 @@
2
 #include <getopt.h>
3
 #include <limits.h>
4
 #include <math.h>
5
+#include <fnmatch.h>
6
 
7
 #include <spa/utils/result.h>
8
 #include <spa/utils/string.h>
9
@@ -37,6 +38,7 @@
10
 #include <spa/debug/types.h>
11
 #include <spa/utils/json.h>
12
 #include <spa/utils/ansi.h>
13
+#include <spa/utils/string.h>
14
 
15
 #include <pipewire/pipewire.h>
16
 #include <pipewire/extensions/metadata.h>
17
@@ -65,7 +67,7 @@
18
 
19
    struct spa_list object_list;
20
 
21
-   uint32_t id;
22
+   const char *pattern;
23
 
24
    FILE *out;
25
    int level;
26
@@ -93,6 +95,7 @@
27
    const void *events;
28
    void (*destroy) (struct object *object);
29
    void (*dump) (struct object *object);
30
+   const char *name_key;
31
 };
32
 
33
 struct object {
34
@@ -552,6 +555,7 @@
35
    .type = PW_TYPE_INTERFACE_Core,
36
    .version = PW_VERSION_CORE,
37
    .dump = core_dump,
38
+   .name_key = PW_KEY_CORE_NAME,
39
 };
40
 
41
 /* client */
42
@@ -608,6 +612,7 @@
43
    .events = &client_events,
44
    .destroy = client_destroy,
45
    .dump = client_dump,
46
+   .name_key = PW_KEY_APP_NAME,
47
 };
48
 
49
 /* module */
50
@@ -667,6 +672,7 @@
51
    .events = &module_events,
52
    .destroy = module_destroy,
53
    .dump = module_dump,
54
+   .name_key = PW_KEY_MODULE_NAME,
55
 };
56
 
57
 /* factory */
58
@@ -726,6 +732,7 @@
59
    .events = &factory_events,
60
    .destroy = factory_destroy,
61
    .dump = factory_dump,
62
+   .name_key = PW_KEY_FACTORY_NAME,
63
 };
64
 
65
 /* device */
66
@@ -810,6 +817,7 @@
67
    .events = &device_events,
68
    .destroy = device_destroy,
69
    .dump = device_dump,
70
+   .name_key = PW_KEY_DEVICE_NAME,
71
 };
72
 
73
 /* node */
74
@@ -906,6 +914,7 @@
75
    .events = &node_events,
76
    .destroy = node_destroy,
77
    .dump = node_dump,
78
+   .name_key = PW_KEY_NODE_NAME,
79
 };
80
 
81
 /* port */
82
@@ -991,6 +1000,7 @@
83
    .events = &port_events,
84
    .destroy = port_destroy,
85
    .dump = port_dump,
86
+   .name_key = PW_KEY_PORT_NAME,
87
 };
88
 
89
 /* link */
90
@@ -1206,6 +1216,7 @@
91
    .events = &metadata_events,
92
    .destroy = metadata_destroy,
93
    .dump = metadata_dump,
94
+   .name_key = PW_KEY_METADATA_NAME,
95
 };
96
 
97
 static const struct class *classes[] =
98
@@ -1331,6 +1342,32 @@
99
    .global_remove = registry_event_global_remove,
100
 };
101
 
102
+static bool object_matches(struct object *o, const char *pattern)
103
+{
104
+   uint32_t id;
105
+   const char *str;
106
+
107
+   if (spa_atou32(pattern, &id, 0) && o->id == id)
108
+       return true;
109
+
110
+   if (o->props == NULL)
111
+       return false;
112
+
113
+   if (strstr(o->type, pattern) != NULL)
114
+       return true;
115
+   if ((str = pw_properties_get(o->props, PW_KEY_OBJECT_PATH)) != NULL &&
116
+       fnmatch(pattern, str, FNM_EXTMATCH) == 0)
117
+       return true;
118
+   if ((str = pw_properties_get(o->props, PW_KEY_OBJECT_SERIAL)) != NULL &&
119
+       spa_streq(pattern, str))
120
+       return true;
121
+   if (o->class != NULL && o->class->name_key != NULL &&
122
+       (str = pw_properties_get(o->props, o->class->name_key)) != NULL &&
123
+       fnmatch(pattern, str, FNM_EXTMATCH) == 0)
124
+       return true;
125
+   return false;
126
+}
127
+
128
 static void dump_objects(struct data *d)
129
 {
130
    static const struct flags_info fl[] = {
131
@@ -1345,7 +1382,7 @@
132
 
133
    d->state = STATE_FIRST;
134
    spa_list_for_each(o, &d->object_list, link) {
135
-       if (d->id != SPA_ID_INVALID && d->id != o->id)
136
+       if (d->pattern != NULL && !object_matches(o, d->pattern))
137
            continue;
138
        if (o->changed == 0)
139
            continue;
140
@@ -1493,10 +1530,8 @@
141
        }
142
    }
143
 
144
-   data.id = SPA_ID_INVALID;
145
-   if (optind < argc) {
146
-       spa_atou32(argv[optind++], &data.id, 0);
147
-   }
148
+   if (optind < argc)
149
+       data.pattern = argv[optind++];
150
 
151
    data.loop = pw_main_loop_new(NULL);
152
    if (data.loop == NULL) {
153
pipewire-0.3.43.tar.gz/src/tools/pw-metadata.c -> pipewire-0.3.44.tar.gz/src/tools/pw-metadata.c Changed
11
 
1
@@ -96,7 +96,8 @@
2
    if (!spa_streq(type, PW_TYPE_INTERFACE_Metadata))
3
        return;
4
 
5
-   if ((str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL &&
6
+   if (props != NULL &&
7
+       (str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL &&
8
        !spa_streq(str, d->opt_name))
9
        return;
10
 
11