We truncated the diff of some files because they were too big.
If you want to see the full diff for every file, click here.
Changes of Revision 2
pipewire-aptx.changes
Changed
x
1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
-.. This file is part of PipeWire.
3
-
4
pw-cat
5
######
6
7
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
2
-.. This file is part of PipeWire.
3
-
4
pw-cli
5
######
6
7
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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(¶ms));
79
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
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
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
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
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
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
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(¶ms));
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
int rate;
3
int format;
4
int quality;
5
+ int cpu_flags;
6
7
const char *iname;
8
SF_INFO iinfo;
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
props->volume = DEFAULT_VOLUME;
3
}
4
5
-#define MAX_SAMPLES 8192
6
#define MAX_BUFFERS 16
7
#define MAX_PORTS 1
8
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
props->mute = DEFAULT_MUTE;
3
}
4
5
-#define MAX_SAMPLES 8192
6
#define MAX_BUFFERS 16
7
8
struct buffer {
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, ¶m, &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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
18
19
struct spa_list object_list;
20
21
- uint32_t id;
22
+ const char *pattern;
23
24
FILE *out;
25
int level;
26
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
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
43
.events = &client_events,
44
.destroy = client_destroy,
45
.dump = client_dump,
46
+ .name_key = PW_KEY_APP_NAME,
47
};
48
49
/* module */
50
51
.events = &module_events,
52
.destroy = module_destroy,
53
.dump = module_dump,
54
+ .name_key = PW_KEY_MODULE_NAME,
55
};
56
57
/* factory */
58
59
.events = &factory_events,
60
.destroy = factory_destroy,
61
.dump = factory_dump,
62
+ .name_key = PW_KEY_FACTORY_NAME,
63
};
64
65
/* device */
66
67
.events = &device_events,
68
.destroy = device_destroy,
69
.dump = device_dump,
70
+ .name_key = PW_KEY_DEVICE_NAME,
71
};
72
73
/* node */
74
75
.events = &node_events,
76
.destroy = node_destroy,
77
.dump = node_dump,
78
+ .name_key = PW_KEY_NODE_NAME,
79
};
80
81
/* port */
82
83
.events = &port_events,
84
.destroy = port_destroy,
85
.dump = port_dump,
86
+ .name_key = PW_KEY_PORT_NAME,
87
};
88
89
/* link */
90
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
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
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
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
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