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 35
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Sun Oct 8 16:26:36 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.81
6
+
7
+-------------------------------------------------------------------
8
Fri Sep 22 17:21:32 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
10
- Update to version 0.3.80
11
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.80
6
+Version: 0.3.81
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.80.tar.gz/.gitlab-ci.yml -> pipewire-0.3.81.tar.gz/.gitlab-ci.yml
Changed
18
1
2
extends:
3
- .build_on_fedora
4
stage: analysis
5
+ variables:
6
+ MESON_OPTIONS: >-
7
+ -Dpipewire-v4l2=enabled
8
+ -Dpipewire-jack=enabled
9
script:
10
- - shellcheck $(git grep -l "#\!/.*bin/.*sh")
11
+ - echo "Configuring with meson options $MESON_OPTIONS"
12
+ - meson setup "$BUILD_DIR" --prefix="$PREFIX" $MESON_OPTIONS
13
+ - shellcheck $(git ls-files '*.sh')
14
+ - shellcheck $(grep -rl "#\!/.*bin/.*sh" "$BUILD_DIR")
15
16
spellcheck:
17
extends:
18
pipewire-0.3.80.tar.gz/NEWS -> pipewire-0.3.81.tar.gz/NEWS
Changed
100
1
2
+# PipeWire 0.3.81 (2023-10-06)
3
+
4
+This is the first 1.0 release candidate that is API and ABI compatible
5
+with previous 0.3.x releases.
6
+
7
+## Highlights
8
+ - jackdbus support is now enabled by default.
9
+ - IRQ based scheduling in ALSA was improved and enabled by default for
10
+ Pro-Audio profile. It will also link the pcms together to get lower
11
+ latency. This now matches what JACK does and gives equal latency to
12
+ PipeWire for Pro-Audio profiles.
13
+ - Support both old and new versions of webrtc-audio-processing to make
14
+ the transition easier.
15
+ - Forced quantum changes by nodes or metadata will now also force a
16
+ suspend and resume of the graph, like the rate changes to make sure all
17
+ nodes adapt to the new quantum. This is important for Pro-Audio nodes
18
+ that need to reconfigure the hardware to a new period in IRQ based
19
+ scheduling.
20
+ - Fix a regression in regex parsing.
21
+ - Many bugfixes and improvements.
22
+
23
+
24
+## PipeWire
25
+ - jackdbus is by default enabled now. The idea is that when jackdbus is
26
+ installed, the real libjack.so is in the path and we can become a
27
+ real JACK client.
28
+ - Forces quantum changes by nodes or metadata will now also force a
29
+ suspend and resume in the graph, like the rate changes to make sure all
30
+ nodes adapt to the new quantum. This is important for Pro-Audio nodes
31
+ that need to reconfigure the hardware to a new period.
32
+ - The stream now has an EARLY_PROCESS option that can be used to implement
33
+ custum buffer fill levels. (#3480)
34
+ - Fix a regression in regex parsing. (#3528)
35
+ - Fix a bug in position reporting in the driver node. (#3189) (#3544)
36
+ - Destroying a link will now recalculate the graph correctly.
37
+ - Fix the rate comparison for finding the best rate in the graph.
38
+ - Use malloc_trim() when available to release memory. (#1840)
39
+
40
+## Tools
41
+ - pw-cat now supports DFF DSD files.
42
+ - pw-cli avoid some NULL derefs in some cases.
43
+
44
+## Modules
45
+ - The RAOP sink has seen some cleanups and improvements. It will now ask
46
+ for feedback every 2 seconds to keep some devices alive.
47
+ - A bug in filter-chain was fixed where it would fail to apply the gain
48
+ when mixing just one source.
49
+ - The filter-chain can now pass the stream volume to a control in the
50
+ filter-chain graph. (#3434)
51
+ - Improve volume handling in RAOP sink.
52
+
53
+## Pulse-server
54
+ - Some cleanup in the pending_stream handling.
55
+ - Fix a regression in the event emission code where it failed to emit
56
+ a changed event when a node was linked. (#3522)
57
+ - Lower the realtime priority of pulseaudio clients.
58
+ - Set pulse.module.id on the echo-cancel streams. (#3541)
59
+
60
+## SPA
61
+ - Support both old and new versions of webrtc-audio-processing to make
62
+ the transition easier.
63
+ - The ALSA driver now does the sync of all followers directly from the
64
+ wakeup event. This results in more stable rate matching.
65
+ - IRQ based scheduling in ALSA was improved and enabled by default for
66
+ Pro-Audio profile. It will also link the pcms together to get lower
67
+ latency. This now matches what JACK does and gives equal latency to
68
+ PipeWire for Pro-Audio profiles.
69
+ - GNU/Hurd support was added.
70
+ - Some improvements to passthrough handling.
71
+
72
+## Bluetooth
73
+ - Improvements to the codec handling when PipeWire is used as Audio
74
+ Gateway.
75
+ - Adapt to new Bluez API for BAP devices.
76
+
77
+## JACK
78
+ - When the jack library is set in the default library path, avoid using
79
+ LD_LIBRARY_PATH because this can cause confusion.
80
+ - Handle clearing the latency on a port.
81
+ - jack_property now always manages to actually change the metadata because
82
+ it waits for a roundtrip before exiting.
83
+
84
+Older versions:
85
+
86
+
87
# PipeWire 0.3.80 (2023-09-14)
88
89
This is a bugfix release that is API and ABI compatible with previous
90
91
- The mixer io areas are updated and handled safely now to avoid
92
crashes. (#3506)
93
94
-Older versions:
95
-
96
-
97
# PipeWire 0.3.79 (2023-08-29)
98
99
This is a quick bugfix release that is API and ABI compatible with previous
100
pipewire-0.3.80.tar.gz/doc/input-filter-h.sh -> pipewire-0.3.81.tar.gz/doc/input-filter-h.sh
Changed
9
1
2
# Add \ingroup commands for the file, for each \addgroup in it
3
BASEFILE=$(echo "$FILENAME" | sed -e 's@.*src/pipewire/@pipewire/@; s@.*spa/include/spa/@spa/@; s@.*src/test/@test/@;')
4
5
+# shellcheck disable=SC2028 # \file is not an escape sequence
6
echo "/** \file"
7
echo "\`$BASEFILE\`"
8
sed -n -e '/.*\\addtogroup a-zA-Z0-9_.*/ { s/.*addtogroup /\\ingroup /; p; }' < "$FILENAME" | sort | uniq
9
pipewire-0.3.80.tar.gz/meson.build -> pipewire-0.3.81.tar.gz/meson.build
Changed
57
1
2
project('pipewire', 'c' ,
3
- version : '0.3.80',
4
+ version : '0.3.81',
5
license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
meson_version : '>= 0.61.1',
7
default_options : 'warning_level=3',
8
9
spaversion = '0.2'
10
apiversion = '0.3'
11
soversion = 0
12
-libversion = '@0@.@1@.0'.format(soversion, pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int())
13
+libversion_minor = pipewire_version_major.to_int() * 1000 + pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()
14
+libversion = '@0@.@1@.0'.format(soversion, libversion_minor)
15
16
# LADI/jack
17
# 3, for PipeWire being the third JACK implementation, after JACK1 and jackdmp/JACK2)
18
jack_version_major = 3
19
-jack_version_minor = pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()
20
+jack_version_minor = libversion_minor
21
# libjackserver version has 0 for major (for compatibility with other implementations),
22
-# 3 for minor, and "100*pipewire_version_minor + pipewire_version_micro"
23
-# as micro version (the minor libpipewire soversion number)
24
+# 3 for minor, and "1000*major + 100*minor + micro" as micro version (the minor libpipewire soversion number)
25
libjackversion = '@0@.@1@.@2@'.format(soversion, jack_version_major, jack_version_minor)
26
27
pipewire_name = 'pipewire-@0@'.format(apiversion)
28
29
30
webrtc_dep = dependency('webrtc-audio-processing-1',
31
version : '>= 1.2' ,
32
- required : get_option('echo-cancel-webrtc'))
33
-summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
34
-cdata.set('HAVE_WEBRTC', webrtc_dep.found())
35
+ required : false)
36
+cdata.set('HAVE_WEBRTC1', webrtc_dep.found())
37
+if webrtc_dep.found()
38
+ summary({'WebRTC Echo Canceling >= 1.2': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
39
+else
40
+ webrtc_dep = dependency('webrtc-audio-processing',
41
+ version : '>= 0.2', '< 1.0',
42
+ required : get_option('echo-cancel-webrtc'))
43
+ cdata.set('HAVE_WEBRTC', webrtc_dep.found())
44
+ summary({'WebRTC Echo Canceling < 1.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
45
+endif
46
47
# On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd()
48
epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
49
50
'reallocarray', '#include <stdlib.h>', '-D_GNU_SOURCE', ,
51
'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', ,
52
'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep,
53
+ 'malloc_trim', '#include <malloc.h>', , ,
54
55
56
foreach f : check_functions
57
pipewire-0.3.80.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.81.tar.gz/pipewire-jack/src/meson.build
Changed
21
1
2
if libjack_path == ''
3
libjack_path = modules_install_dir / 'jack'
4
libjack_path_dlopen = modules_install_dir_dlopen / 'jack'
5
+ libjack_path_enable = ''
6
+elif libjack_path == get_option('libdir') or libjack_path == pipewire_libdir
7
+ libjack_path = pipewire_libdir
8
+ libjack_path_dlopen = libjack_path
9
+ libjack_path_enable = '#'
10
else
11
libjack_path_dlopen = libjack_path
12
+ libjack_path_enable = ''
13
endif
14
15
tools_config = configuration_data()
16
tools_config.set('LIBJACK_PATH', libjack_path_dlopen)
17
+tools_config.set('LIBJACK_PATH_ENABLE', libjack_path_enable)
18
19
configure_file(input : 'pw-jack.in',
20
output : 'pw-jack',
21
pipewire-0.3.80.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/metadata.c
Changed
47
1
2
pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", o->id, subject, key, value, type);
3
if (update_property(c, subject, key, type, value))
4
pw_metadata_set_property(c->metadata->proxy, o->id, key, type, value);
5
- res = 0;
6
+ res = do_sync(c);
7
done:
8
pw_thread_loop_unlock(c->context.loop);
9
10
11
pw_log_info("remove id:%u (%"PRIu64") '%s'", id, subject, key);
12
pw_metadata_set_property(c->metadata->proxy,
13
id, key, NULL, NULL);
14
- res = 0;
15
+ res = do_sync(c);
16
done:
17
pw_thread_loop_unlock(c->context.loop);
18
19
20
pw_log_info("remove id:%u (%"PRIu64")", id, subject);
21
pw_metadata_set_property(c->metadata->proxy,
22
id, NULL, NULL, NULL);
23
- res = 0;
24
+ res = do_sync(c);
25
done:
26
pw_thread_loop_unlock(c->context.loop);
27
28
29
SPA_EXPORT
30
int jack_remove_all_properties (jack_client_t* client)
31
{
32
+ int res;
33
struct client *c = (struct client *) client;
34
35
spa_return_val_if_fail(c != NULL, -EINVAL);
36
37
pw_thread_loop_lock(c->context.loop);
38
pw_metadata_clear(c->metadata->proxy);
39
+ res = do_sync(c);
40
pw_thread_loop_unlock(c->context.loop);
41
42
- return 0;
43
+ return res;
44
}
45
46
SPA_EXPORT
47
pipewire-0.3.80.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
24
1
2
int res;
3
4
if (param == NULL)
5
- return 0;
6
- if ((res = spa_latency_parse(param, &info)) < 0)
7
+ info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(p->direction));
8
+ else if ((res = spa_latency_parse(param, &info)) < 0)
9
return res;
10
+ if (info.direction == p->direction)
11
+ return 0;
12
13
current = &p->object->port.latencyinfo.direction;
14
if (spa_latency_info_compare(current, &info) == 0)
15
16
info.min_rate, info.max_rate,
17
info.min_ns, info.max_ns);
18
19
- if (info.direction == p->direction)
20
- return 0;
21
22
if (info.direction == SPA_DIRECTION_INPUT)
23
mode = JackPlaybackLatency;
24
pipewire-0.3.80.tar.gz/pipewire-jack/src/pw-jack.in -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pw-jack.in
Changed
13
1
2
fi
3
export PIPEWIRE_QUANTUM
4
fi
5
-LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
6
-export LD_LIBRARY_PATH
7
+
8
+# shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell
9
+@LIBJACK_PATH_ENABLE@LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
10
+@LIBJACK_PATH_ENABLE@export LD_LIBRARY_PATH
11
12
exec "$@"
13
pipewire-0.3.80.tar.gz/pipewire-v4l2/src/pw-v4l2.in -> pipewire-0.3.81.tar.gz/pipewire-v4l2/src/pw-v4l2.in
Changed
9
1
2
if "$PW_UNINSTALLED" = 1 ; then
3
PW_V4L2_LD_PRELOAD="$PW_BUILDDIR"'/pipewire-v4l2/src/libpw-v4l2.so'
4
else
5
+ # shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell
6
PW_V4L2_LD_PRELOAD='@LIBV4L2_PATH@/libpw-v4l2.so'
7
fi
8
9
pipewire-0.3.80.tar.gz/spa/examples/adapter-control.c -> pipewire-0.3.81.tar.gz/spa/examples/adapter-control.c
Changed
13
1
2
printf("got error %d\n", res);
3
}
4
5
-static char *getscale(uint32_t scale)
6
+static const char *getscale(uint32_t scale)
7
{
8
- char *scale_s = NULL;
9
+ const char *scale_s = NULL;
10
11
if (scale == SPA_AUDIO_VOLUME_RAMP_LINEAR)
12
scale_s = LINEAR;
13
pipewire-0.3.80.tar.gz/spa/include/spa/debug/log.h -> pipewire-0.3.81.tar.gz/spa/include/spa/debug/log.h
Changed
12
1
2
#include <spa/utils/defs.h>
3
#include <spa/support/log.h>
4
#include <spa/debug/context.h>
5
+#include <spa/debug/dict.h>
6
+#include <spa/debug/format.h>
7
+#include <spa/debug/mem.h>
8
+#include <spa/debug/pod.h>
9
10
/**
11
* \addtogroup spa_debug
12
pipewire-0.3.80.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-0.3.81.tar.gz/spa/include/spa/utils/cleanup.h
Changed
47
1
2
3
#define spa_exchange(var, new_value) \
4
__extension__ ({ \
5
- __typeof__(var) _old_value = (var); \
6
- (var) = (new_value); \
7
+ __typeof__(var) *_ptr = &(var); \
8
+ __typeof__(var) _old_value = *_ptr; \
9
+ *_ptr = (new_value); \
10
_old_value; \
11
})
12
13
-#if __GNUC__ > 10 || defined(__clang__)
14
+#if __GNUC__ >= 10 || defined(__clang__)
15
#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
16
#else
17
-#define spa_steal_ptr(ptr) ((__typeof__(ptr)) spa_exchange((ptr), NULL))
18
+#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
19
#endif
20
21
#define spa_steal_fd(fd) spa_exchange((fd), -1)
22
23
24
#include <stdlib.h>
25
26
-
27
-#if __GNUC__ > 10 || defined(__clang__)
28
-#define spa_clear_ptr(ptr, destructor) \
29
-__extension__ ({ \
30
- __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \
31
- if (_old_value) \
32
- destructor(_old_value); \
33
- (void) 0; \
34
-})
35
-#else
36
#define spa_clear_ptr(ptr, destructor) \
37
__extension__ ({ \
38
__typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
39
40
destructor(_old_value); \
41
(void) 0; \
42
})
43
-#endif
44
45
static inline void _spa_autofree_cleanup_func(void *p)
46
{
47
pipewire-0.3.80.tar.gz/spa/plugins/aec/aec-webrtc.cpp -> pipewire-0.3.81.tar.gz/spa/plugins/aec/aec-webrtc.cpp
Changed
196
1
2
/* SPDX-FileCopyrightText: Copyright © 2021 Arun Raghavan <arun@asymptotic.io> */
3
/* SPDX-License-Identifier: MIT */
4
5
+#include "config.h"
6
+
7
#include <memory>
8
#include <utility>
9
10
11
#include <spa/utils/json.h>
12
#include <spa/support/plugin.h>
13
14
+#ifdef HAVE_WEBRTC
15
+#include <webrtc/modules/audio_processing/include/audio_processing.h>
16
+#include <webrtc/modules/interface/module_common_types.h>
17
+#include <webrtc/system_wrappers/include/trace.h>
18
+#else
19
#include <modules/audio_processing/include/audio_processing.h>
20
+#endif
21
22
struct impl_data {
23
struct spa_handle handle;
24
25
return default_value;
26
}
27
28
+#ifdef HAVE_WEBRTC
29
+/* f0 f1 f2 */
30
+static int parse_point(struct spa_json *it, float (&f)3)
31
+{
32
+ struct spa_json arr;
33
+ int i, res;
34
+
35
+ if (spa_json_enter_array(it, &arr) <= 0)
36
+ return -EINVAL;
37
+
38
+ for (i = 0; i < 3; i++) {
39
+ if ((res = spa_json_get_float(&arr, &fi)) <= 0)
40
+ return -EINVAL;
41
+ }
42
+ return 0;
43
+}
44
+
45
+/* point1 point2 ... */
46
+static int parse_mic_geometry(struct impl_data *impl, const char *mic_geometry,
47
+ std::vector<webrtc::Point>& geometry)
48
+{
49
+ int res;
50
+ size_t i;
51
+ struct spa_json it2;
52
+
53
+ spa_json_init(&it0, mic_geometry, strlen(mic_geometry));
54
+ if (spa_json_enter_array(&it0, &it1) <= 0) {
55
+ spa_log_error(impl->log, "Error: webrtc.mic-geometry expects an array");
56
+ return -EINVAL;
57
+ }
58
+
59
+ for (i = 0; i < geometry.size(); i++) {
60
+ float f3;
61
+
62
+ if ((res = parse_point(&it1, f)) < 0) {
63
+ spa_log_error(impl->log, "Error: can't parse webrtc.mic-geometry points: %d", res);
64
+ return res;
65
+ }
66
+
67
+ spa_log_info(impl->log, "mic %zd position: (%g %g %g)", i, f0, f1, f2);
68
+ geometryi.c0 = f0;
69
+ geometryi.c1 = f1;
70
+ geometryi.c2 = f2;
71
+ }
72
+ return 0;
73
+}
74
+#endif
75
+
76
static int webrtc_init2(void *object, const struct spa_dict *args,
77
struct spa_audio_info_raw *rec_info, struct spa_audio_info_raw *out_info,
78
struct spa_audio_info_raw *play_info)
79
80
81
bool high_pass_filter = webrtc_get_spa_bool(args, "webrtc.high_pass_filter", true);
82
bool noise_suppression = webrtc_get_spa_bool(args, "webrtc.noise_suppression", true);
83
- bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true);
84
bool voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true);
85
-
86
+#ifdef HAVE_WEBRTC
87
+ bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true);
88
+ bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true);
89
+ // Disable experimental flags by default
90
+ bool experimental_agc = webrtc_get_spa_bool(args, "webrtc.experimental_agc", false);
91
+ bool experimental_ns = webrtc_get_spa_bool(args, "webrtc.experimental_ns", false);
92
+
93
+ bool beamforming = webrtc_get_spa_bool(args, "webrtc.beamforming", false);
94
+#else
95
+ bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true);
96
+#endif
97
// Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech,
98
// result in very poor performance, disable by default
99
bool gain_control = webrtc_get_spa_bool(args, "webrtc.gain_control", false);
100
101
// This filter will modify playback buffer (when calling ProcessReverseStream), but now
102
// playback buffer modifications are discarded.
103
104
+#ifdef HAVE_WEBRTC
105
+ webrtc::Config config;
106
+ config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(extended_filter));
107
+ config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(delay_agnostic));
108
+ config.Set<webrtc::ExperimentalAgc>(new webrtc::ExperimentalAgc(experimental_agc));
109
+ config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(experimental_ns));
110
+
111
+ if (beamforming) {
112
+ std::vector<webrtc::Point> geometry(rec_info->channels);
113
+ const char *mic_geometry, *target_direction;
114
+
115
+ /* The beamformer gives a single mono channel */
116
+ out_info->channels = 1;
117
+ out_info->position0 = SPA_AUDIO_CHANNEL_MONO;
118
+
119
+ if ((mic_geometry = spa_dict_lookup(args, "webrtc.mic-geometry")) == NULL) {
120
+ spa_log_error(impl->log, "Error: webrtc.beamforming requires webrtc.mic-geometry");
121
+ return -EINVAL;
122
+ }
123
+
124
+ if ((res = parse_mic_geometry(impl, mic_geometry, geometry)) < 0)
125
+ return res;
126
+
127
+ if ((target_direction = spa_dict_lookup(args, "webrtc.target-direction")) != NULL) {
128
+ webrtc::SphericalPointf direction(0.0f, 0.0f, 0.0f);
129
+ struct spa_json it;
130
+ float f3;
131
+
132
+ spa_json_init(&it, target_direction, strlen(target_direction));
133
+ if (parse_point(&it, f) < 0) {
134
+ spa_log_error(impl->log, "Error: can't parse target-direction %s",
135
+ target_direction);
136
+ return -EINVAL;
137
+ }
138
+
139
+ direction.s0 = f0;
140
+ direction.s1 = f1;
141
+ direction.s2 = f2;
142
+
143
+ config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry, direction));
144
+ } else {
145
+ config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
146
+ }
147
+ }
148
+#else
149
webrtc::AudioProcessing::Config config;
150
config.echo_canceller.enabled = true;
151
// FIXME: Example code enables both gain controllers, but that seems sus
152
153
// FIXME: expose pre/postamp gain
154
config.transient_suppression.enabled = transient_suppression;
155
config.voice_detection.enabled = voice_detection;
156
+#endif
157
158
webrtc::ProcessingConfig pconfig = {{
159
webrtc::StreamConfig(rec_info->rate, rec_info->channels, false), /* input stream */
160
161
webrtc::StreamConfig(play_info->rate, play_info->channels, false), /* reverse output stream */
162
}};
163
164
+#ifdef HAVE_WEBRTC
165
+ auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
166
+#else
167
auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessingBuilder().Create());
168
169
apm->ApplyConfig(config);
170
+#endif
171
172
if ((res = apm->Initialize(pconfig)) != webrtc::AudioProcessing::kNoError) {
173
spa_log_error(impl->log, "Error initialising webrtc audio processing module: %d", res);
174
return -EINVAL;
175
}
176
177
+#ifdef HAVE_WEBRTC
178
+ apm->high_pass_filter()->Enable(high_pass_filter);
179
+ // Always disable drift compensation since PipeWire will already do
180
+ // drift compensation on all sinks and sources linked to this echo-canceler
181
+ apm->echo_cancellation()->enable_drift_compensation(false);
182
+ apm->echo_cancellation()->Enable(true);
183
+ // TODO: wire up supression levels to args
184
+ apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression);
185
+ apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh);
186
+ apm->noise_suppression()->Enable(noise_suppression);
187
+ apm->voice_detection()->Enable(voice_detection);
188
+ // TODO: wire up AGC parameters to args
189
+ apm->gain_control()->set_analog_level_limits(0, 255);
190
+ apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
191
+ apm->gain_control()->Enable(gain_control);
192
+#endif
193
impl->apm = std::move(apm);
194
impl->rec_info = *rec_info;
195
impl->out_info = *out_info;
196
pipewire-0.3.80.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
19
1
2
pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
3
pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
4
pa_proplist_setf(m->output_proplist, "device.profile.pro", "true");
5
+ pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
6
+ pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
7
pa_alsa_close(&m->output_pcm);
8
m->supported = true;
9
pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
10
11
pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
12
pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
13
pa_proplist_setf(m->input_proplist, "device.profile.pro", "true");
14
+ pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
15
+ pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
16
pa_alsa_close(&m->input_pcm);
17
m->supported = true;
18
pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
19
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c
Changed
16
1
2
3
nextptr = device + 3;
4
for (value_index = 0; ; ++value_index) {
5
- char *value_label;
6
+ const char *value_label;
7
8
switch (value_index) {
9
case 0: value_label = "card"; break;
10
case 1: value_label = "device"; break;
11
- default: assert(false);
12
+ default: spa_assert_not_reached();
13
}
14
15
errno = 0;
16
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
15
1
2
3
switch (id) {
4
case SPA_IO_Clock:
5
+ if (size > 0 && size < sizeof(struct spa_io_clock))
6
+ return -EINVAL;
7
this->clock = data;
8
break;
9
case SPA_IO_Position:
10
+ if (size > 0 && size < sizeof(struct spa_io_position))
11
+ return -EINVAL;
12
this->position = data;
13
break;
14
default:
15
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
10
1
2
this->clock = data;
3
break;
4
case SPA_IO_Position:
5
+ if (size > 0 && size < sizeof(struct spa_io_position))
6
+ return -EINVAL;
7
this->position = data;
8
break;
9
default:
10
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
201
1
2
#include "alsa-pcm.h"
3
4
static struct spa_list cards = SPA_LIST_INIT(&cards);
5
+static struct spa_list states = SPA_LIST_INIT(&states);
6
7
static struct card *find_card(uint32_t index)
8
{
9
10
int err;
11
const char *str;
12
13
+ spa_list_init(&state->followers);
14
+ spa_list_init(&state->rt.followers);
15
+
16
snd_config_update_free_global();
17
18
if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL)
19
20
21
state->multi_rate = true;
22
state->htimestamp = false;
23
+ state->disable_tsched = state->is_pro;
24
for (i = 0; info && i < info->n_items; i++) {
25
const char *k = info->itemsi.key;
26
const char *s = info->itemsi.value;
27
28
}
29
CHECK(snd_output_stdio_attach(&state->output, state->log_file, 0), "attach failed");
30
31
+ spa_list_append(&states, &state->link);
32
+
33
state->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
34
state->rate_limit.burst = 1;
35
36
37
{
38
int err;
39
40
+ spa_list_remove(&state->link);
41
release_card(state->card);
42
43
state->card = NULL;
44
45
err = snd_ctl_open(&state->ctl, device_name, SND_CTL_NONBLOCK);
46
if (err < 0) {
47
spa_log_info(state->log, "%s could not find ctl device: %s",
48
- state->props.device, snd_strerror(err));
49
+ device_name, snd_strerror(err));
50
state->ctl = NULL;
51
goto error;
52
}
53
54
err = snd_ctl_elem_read(state->ctl, state->pitch_elem);
55
if (err < 0) {
56
spa_log_debug(state->log, "%s: did not find ctl %s: %s",
57
- state->props.device, elem_name, snd_strerror(err));
58
+ device_name, elem_name, snd_strerror(err));
59
60
snd_ctl_elem_value_free(state->pitch_elem);
61
state->pitch_elem = NULL;
62
63
CHECK(snd_ctl_elem_write(state->ctl, state->pitch_elem), "snd_ctl_elem_write");
64
state->last_rate = 1.0;
65
66
- spa_log_info(state->log, "%s: found ctl %s", state->props.device, elem_name);
67
+ spa_log_info(state->log, "%s: found ctl %s", device_name, elem_name);
68
err = 0;
69
error:
70
snd_lib_error_set_handler(NULL);
71
return err;
72
}
73
74
+static int do_link(struct state *driver, struct state *state)
75
+{
76
+ int res;
77
+ snd_pcm_status_t *status;
78
+
79
+ snd_pcm_status_alloca(&status);
80
+ snd_pcm_status(driver->hndl, status);
81
+ snd_pcm_status_dump(status, state->output);
82
+ snd_pcm_status(state->hndl, status);
83
+ snd_pcm_status_dump(status, state->output);
84
+ fflush(state->log_file);
85
+
86
+ res = snd_pcm_link(driver->hndl, state->hndl);
87
+ if (res >= 0 || res == -EALREADY)
88
+ state->linked = true;
89
+
90
+ spa_log_info(state->log, "%p: linked to driver %p: %u (%s)",
91
+ state, driver, state->linked, snd_strerror(res));
92
+ return 0;
93
+}
94
+
95
int spa_alsa_open(struct state *state, const char *params)
96
{
97
int err;
98
99
spa_scnprintf(device_name, sizeof(device_name), "%s%s%s",
100
state->card->ucm_prefix ? state->card->ucm_prefix : "",
101
props->device, params ? params : "");
102
+ spa_scnprintf(state->name, sizeof(state->name), "%s%s",
103
+ props->device, state->stream == SND_PCM_STREAM_CAPTURE ? "c" : "p");
104
105
spa_log_info(state->log, "%p: ALSA device open '%s' %s", state, device_name,
106
state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback");
107
108
* these are initialised in spa_alsa_start() */
109
}
110
111
- if (state->clock)
112
- spa_scnprintf(state->clock->name, sizeof(state->clock->name),
113
- "%s", state->clock_name);
114
state->opened = true;
115
state->sample_count = 0;
116
state->sample_time = 0;
117
118
return 0;
119
120
error_exit_close:
121
- spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->props.device,
122
+ spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->name,
123
spa_strerror(err));
124
snd_pcm_close(state->hndl);
125
return err;
126
}
127
128
+static void try_unlink(struct state *state)
129
+{
130
+ struct state *follower;
131
+
132
+ if (state->driver != NULL && state->linked) {
133
+ snd_pcm_unlink(state->hndl);
134
+ spa_log_info(state->log, "%p: unlinked from driver %p",
135
+ state, state->driver);
136
+ state->linked = false;
137
+ }
138
+ spa_list_for_each(follower, &state->followers, driver_link) {
139
+ if (follower->opened && follower->linked) {
140
+ snd_pcm_unlink(follower->hndl);
141
+ spa_log_info(state->log, "%p: follower unlinked from driver %p",
142
+ follower, state);
143
+ follower->linked = false;
144
+ }
145
+ }
146
+}
147
+
148
int spa_alsa_close(struct state *state)
149
{
150
int err = 0;
151
152
if (!state->opened)
153
return 0;
154
155
+ try_unlink(state);
156
+
157
spa_alsa_pause(state);
158
159
- spa_log_info(state->log, "%p: Device '%s' closing", state, state->props.device);
160
+ spa_log_info(state->log, "%p: Device '%s' closing", state, state->name);
161
if ((err = snd_pcm_close(state->hndl)) < 0)
162
- spa_log_warn(state->log, "%s: close failed: %s", state->props.device,
163
+ spa_log_warn(state->log, "%s: close failed: %s", state->name,
164
snd_strerror(err));
165
166
if (!state->disable_tsched)
167
168
169
state->have_format = false;
170
state->opened = false;
171
+ state->linked = false;
172
173
if (state->pitch_elem) {
174
snd_ctl_elem_value_free(state->pitch_elem);
175
176
CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &rchannels), "set_channels");
177
if (state->default_channels != rchannels) {
178
spa_log_warn(state->log, "%s: Channels doesn't match (requested %u, got %u)",
179
- state->props.device, state->default_channels, rchannels);
180
+ state->name, state->default_channels, rchannels);
181
}
182
}
183
if (state->default_rate != 0) {
184
185
CHECK(snd_pcm_hw_params_set_rate_near(hndl, params, &rrate, 0), "set_rate_near");
186
if (state->default_rate != rrate) {
187
spa_log_warn(state->log, "%s: Rate doesn't match (requested %u, got %u)",
188
- state->props.device, state->default_rate, rrate);
189
+ state->name, state->default_rate, rrate);
190
}
191
}
192
193
194
}
195
}
196
spa_log_warn(state->log, "%s: no format found (def:%d) formats:%s",
197
- state->props.device, state->default_format, buf);
198
+ state->name, state->default_format, buf);
199
200
for (i = 0, offs = 0; i <= SND_PCM_ACCESS_LAST; i++) {
201
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
111
1
2
uint32_t rate;
3
};
4
5
+struct rt_state {
6
+ struct spa_list followers;
7
+ struct state *driver;
8
+ struct spa_list driver_link;
9
+
10
+ unsigned int sources_added:1;
11
+ unsigned int following:1;
12
+};
13
+
14
struct state {
15
struct spa_handle handle;
16
struct spa_node node;
17
18
struct card *card;
19
snd_pcm_stream_t stream;
20
snd_output_t *output;
21
+ char name64;
22
23
struct spa_hook_list hooks;
24
struct spa_callbacks callbacks;
25
26
struct spa_param_info paramsN_NODE_PARAMS;
27
struct props props;
28
29
- bool opened;
30
+ unsigned int opened:1;
31
+ unsigned int prepared:1;
32
+ unsigned int started:1;
33
snd_pcm_t *hndl;
34
35
bool have_format;
36
37
uint32_t allowed_ratesMAX_RATES;
38
uint32_t n_allowed_rates;
39
struct channel_map default_pos;
40
- unsigned int disable_mmap;
41
- unsigned int disable_batch;
42
- unsigned int disable_tsched;
43
+ unsigned int disable_mmap:1;
44
+ unsigned int disable_batch:1;
45
+ unsigned int disable_tsched:1;
46
char clock_name64;
47
uint32_t quantum_limit;
48
49
50
size_t frame_size;
51
size_t frame_scale;
52
int blocks;
53
- uint32_t rate_denom;
54
uint32_t delay;
55
uint32_t read_size;
56
+ uint32_t max_read;
57
58
uint64_t port_info_all;
59
struct spa_port_info port_info;
60
61
62
size_t ready_offset;
63
64
- bool started;
65
/* Either a single source for tsched, or a set of pollfds from ALSA */
66
struct spa_source sourceMAX_POLL;
67
int timerfd;
68
69
uint32_t max_delay;
70
uint32_t htimestamp_error;
71
72
- uint32_t duration;
73
+ struct spa_fraction driver_rate;
74
+ uint32_t driver_duration;
75
+
76
unsigned int alsa_started:1;
77
unsigned int alsa_sync:1;
78
unsigned int alsa_sync_warning:1;
79
80
unsigned int multi_rate:1;
81
unsigned int htimestamp:1;
82
unsigned int is_pro:1;
83
+ unsigned int sources_added:1;
84
+ unsigned int linked:1;
85
86
uint64_t iec958_codecs;
87
88
89
snd_ctl_t *ctl;
90
snd_ctl_elem_value_t *pitch_elem;
91
double last_rate;
92
+
93
+ struct spa_list link;
94
+
95
+ struct spa_list followers;
96
+ struct state *driver;
97
+ struct spa_list driver_link;
98
+
99
+ struct rt_state rt;
100
};
101
102
struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
103
104
int spa_alsa_clear(struct state *state);
105
106
int spa_alsa_open(struct state *state, const char *params);
107
+int spa_alsa_prepare(struct state *state);
108
int spa_alsa_start(struct state *state);
109
int spa_alsa_reassign_follower(struct state *state);
110
int spa_alsa_pause(struct state *state);
111
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
79
1
2
struct spa_data *datas;
3
uint64_t follower_flags, conv_flags;
4
5
- if (this->target == this->follower)
6
- return 0;
7
-
8
spa_log_debug(this->log, "%p: n_buffers:%d", this, this->n_buffers);
9
10
if (this->n_buffers > 0)
11
12
this->have_format = format != NULL;
13
if (format == NULL) {
14
this->n_buffers = 0;
15
- } else {
16
+ } else if (this->target != this->follower) {
17
res = negotiate_buffers(this);
18
}
19
-
20
return res;
21
}
22
23
24
struct spa_latency_info latency;
25
int res;
26
27
- spa_log_info(this->log, "%p: %d:%d", this, direction, port_id);
28
+ spa_log_debug(this->log, "%p: %d:%d", this, direction, port_id);
29
30
if (this->target == this->follower)
31
return 0;
32
33
int res = 0;
34
struct spa_hook l;
35
36
- spa_log_info(this->log, "%p: passthrough mode %d", this, passthrough);
37
+ spa_log_debug(this->log, "%p: passthrough mode %d", this, passthrough);
38
39
if (this->passthrough != passthrough) {
40
if (passthrough) {
41
42
struct spa_pod_builder b = { 0 };
43
int res;
44
45
- if (this->target == this->follower)
46
- return 0;
47
-
48
spa_log_debug(this->log, "%p: have_format:%d", this, this->have_format);
49
50
if (this->have_format)
51
52
switch (SPA_NODE_COMMAND_ID(command)) {
53
case SPA_NODE_COMMAND_Start:
54
spa_log_debug(this->log, "%p: starting %d", this, this->started);
55
- if (this->started)
56
- return 0;
57
- if ((res = negotiate_format(this)) < 0)
58
- return res;
59
- if ((res = negotiate_buffers(this)) < 0)
60
- return res;
61
+ if (this->target != this->follower) {
62
+ if (this->started)
63
+ return 0;
64
+ if ((res = negotiate_format(this)) < 0)
65
+ return res;
66
+ }
67
this->ready = true;
68
this->warned = false;
69
break;
70
71
uint32_t i;
72
int res;
73
74
- spa_log_info(this->log, "%p: convert port info %s %p %08"PRIx64, this,
75
+ spa_log_debug(this->log, "%p: convert port info %s %p %08"PRIx64, this,
76
this->direction == SPA_DIRECTION_INPUT ?
77
"Input" : "Output", info, info->change_mask);
78
79
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
120
1
2
}
3
spa_list_init(&port->queue);
4
5
- spa_log_info(this->log, "%p: add port %d:%d position:%s %d %d %d",
6
- this, direction, port_id, port->position, is_dsp, is_monitor, is_control);
7
+ spa_log_debug(this->log, "%p: add port %d:%d position:%s %d %d %d",
8
+ this, direction, port_id, port->position, is_dsp,
9
+ is_monitor, is_control);
10
emit_port_info(this, port, true);
11
12
return 0;
13
14
(info == NULL || memcmp(&dir->format, info, sizeof(*info)) == 0))
15
return 0;
16
17
- spa_log_info(this->log, "%p: port config direction:%d monitor:%d control:%d mode:%d %d", this,
18
- direction, monitor, control, mode, dir->n_ports);
19
+ spa_log_debug(this->log, "%p: port config direction:%d monitor:%d "
20
+ "control:%d mode:%d %d", this, direction, monitor,
21
+ control, mode, dir->n_ports);
22
23
for (i = 0; i < dir->n_ports; i++) {
24
spa_node_emit_port_info(&this->hooks, direction, i, NULL);
25
26
SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_QUEUED);
27
}
28
29
+static void free_tmp(struct impl *this)
30
+{
31
+ uint32_t i;
32
+
33
+ spa_log_debug(this->log, "free tmp %d", this->empty_size);
34
+
35
+ free(this->empty);
36
+ this->empty = NULL;
37
+ this->empty_size = 0;
38
+ free(this->scratch);
39
+ this->scratch = NULL;
40
+ free(this->tmp0);
41
+ this->tmp0 = NULL;
42
+ free(this->tmp1);
43
+ this->tmp1 = NULL;
44
+ for (i = 0; i < MAX_PORTS; i++) {
45
+ this->tmp_datas0i = NULL;
46
+ this->tmp_datas1i = NULL;
47
+ }
48
+}
49
+
50
+static int ensure_tmp(struct impl *this, uint32_t maxsize)
51
+{
52
+ if (maxsize > this->empty_size) {
53
+ float *empty, *scratch, *tmp2;
54
+
55
+ spa_log_debug(this->log, "resize tmp %d -> %d", this->empty_size, maxsize);
56
+
57
+ if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL)
58
+ this->empty = empty;
59
+ if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL)
60
+ this->scratch = scratch;
61
+ if ((tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL)
62
+ this->tmp0 = tmp0;
63
+ if ((tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL)
64
+ this->tmp1 = tmp1;
65
+
66
+ if (empty == NULL || scratch == NULL || tmp0 == NULL || tmp1 == NULL) {
67
+ free_tmp(this);
68
+ return -ENOMEM;
69
+ }
70
+ memset(this->empty, 0, maxsize + MAX_ALIGN);
71
+ this->empty_size = maxsize;
72
+ }
73
+ return 0;
74
+}
75
+
76
static int
77
impl_node_port_use_buffers(void *object,
78
enum spa_direction direction,
79
80
struct impl *this = object;
81
struct port *port;
82
uint32_t i, j, maxsize;
83
+ int res;
84
85
spa_return_val_if_fail(this != NULL, -EINVAL);
86
87
88
if (direction == SPA_DIRECTION_OUTPUT)
89
queue_buffer(this, port, i);
90
}
91
- if (maxsize > this->empty_size) {
92
- this->empty = realloc(this->empty, maxsize + MAX_ALIGN);
93
- this->scratch = realloc(this->scratch, maxsize + MAX_ALIGN);
94
- this->tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS);
95
- this->tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS);
96
- if (this->empty == NULL || this->scratch == NULL ||
97
- this->tmp0 == NULL || this->tmp1 == NULL)
98
- return -errno;
99
- memset(this->empty, 0, maxsize + MAX_ALIGN);
100
- this->empty_size = maxsize;
101
- }
102
+ if ((res = ensure_tmp(this, maxsize)) < 0)
103
+ return res;
104
+
105
port->n_buffers = n_buffers;
106
107
return 0;
108
109
free_dir(&this->dirSPA_DIRECTION_INPUT);
110
free_dir(&this->dirSPA_DIRECTION_OUTPUT);
111
112
- free(this->empty);
113
- free(this->scratch);
114
- free(this->tmp0);
115
- free(this->tmp1);
116
+ free_tmp(this);
117
118
if (this->resample.free)
119
resample_free(&this->resample);
120
pipewire-0.3.80.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
14
1
2
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
3
spa_log_topic_init(this->log, log_topic);
4
5
+ this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
6
+ if (this->data_loop == NULL) {
7
+ spa_log_error(this->log, "a data loop is needed");
8
+ return -EINVAL;
9
+ }
10
+
11
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
12
if (this->cpu) {
13
this->cpu_flags = spa_cpu_get_flags(this->cpu);
14
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c
Changed
10
1
2
OPUS_05_SET_LOCATION(caps->bidi, props->bidi_location);
3
break;
4
default:
5
- spa_assert(false);
6
+ spa_assert_not_reached();
7
};
8
9
return 0;
10
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
51
1
2
.destroy = sco_destroy_cb,
3
};
4
5
-static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device)
6
+static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device,
7
+ enum spa_bt_profile profile)
8
{
9
struct rfcomm *rfcomm;
10
spa_list_for_each(rfcomm, &backend->rfcomm_list, link) {
11
- if (rfcomm->device == device)
12
+ if (rfcomm->device == device && (rfcomm->profile & profile))
13
return rfcomm;
14
}
15
return NULL;
16
17
struct impl *backend = data;
18
struct rfcomm *rfcomm;
19
20
- rfcomm = device_find_rfcomm(backend, device);
21
- if (rfcomm == NULL || rfcomm->profile != SPA_BT_PROFILE_HFP_HF)
22
+ rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF);
23
+ if (rfcomm == NULL)
24
return -ENOTSUP;
25
26
if (codec == HFP_AUDIO_CODEC_CVSD)
27
28
int res;
29
30
res = backend_native_supports_codec(data, device, codec);
31
- if (res <= 0)
32
+ if (res < 0)
33
+ return res;
34
+ else if (!res)
35
return -EINVAL;
36
37
- rfcomm = device_find_rfcomm(backend, device);
38
+ rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF);
39
if (rfcomm == NULL)
40
return -ENOTSUP;
41
42
43
DBusMessageIter it4;
44
dbus_bool_t autoconnect;
45
dbus_uint16_t version, chan, features;
46
- char *str;
47
+ const char *str;
48
49
if (!(backend->enabled_profiles & spa_bt_profile_from_uuid(uuid)))
50
return -ECANCELED;
51
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bap-codec-caps.h -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bap-codec-caps.h
Changed
40
1
2
};
3
4
struct bap_endpoint_qos {
5
- uint8_t framing;
6
- uint8_t phy;
7
- uint8_t retransmission;
8
- uint16_t latency;
9
- uint32_t delay_min;
10
- uint32_t delay_max;
11
- uint32_t preferred_delay_min;
12
- uint32_t preferred_delay_max;
13
+ uint8_t framing;
14
+ uint8_t phy;
15
+ uint8_t retransmission;
16
+ uint16_t latency;
17
+ uint32_t delay_min;
18
+ uint32_t delay_max;
19
+ uint32_t preferred_delay_min;
20
+ uint32_t preferred_delay_max;
21
+ uint32_t locations;
22
+ uint16_t supported_context;
23
+ uint16_t context;
24
};
25
26
struct bap_codec_qos {
27
28
uint8_t target_latency;
29
};
30
31
+struct bap_codec_qos_full {
32
+ uint8_t cig;
33
+ uint8_t cis;
34
+ uint8_t big;
35
+ uint8_t bis;
36
+ struct bap_codec_qos qos;
37
+};
38
+
39
#endif
40
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
201
1
2
static void append_basic_array_variant_dict_entry(DBusMessageIter *dict, const char* key, const char* variant_type_str, const char* array_type_str, int array_type_int, void* data, int data_size);
3
static struct spa_bt_remote_endpoint *remote_endpoint_find(struct spa_bt_monitor *monitor, const char *path);
4
5
+static bool check_iter_signature(DBusMessageIter *it, const char *sig)
6
+{
7
+ char *v;
8
+ bool res;
9
+ v = dbus_message_iter_get_signature(it);
10
+ res = spa_streq(v, sig);
11
+ dbus_free(v);
12
+ return res;
13
+}
14
+
15
+static void parse_codec_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter, struct bap_codec_qos_full *qos)
16
+{
17
+ DBusMessageIter dict_iter = *iter;
18
+
19
+ memset(qos, 0, sizeof(*qos));
20
+ qos->cig = 0xff;
21
+ qos->cis = 0xff;
22
+ qos->big = 0xff;
23
+ qos->bis = 0xff;
24
+
25
+ if (!check_iter_signature(&dict_iter, "{sv}")) {
26
+ spa_log_warn(monitor->log, "Invalid BAP QoS in DBus");
27
+ return;
28
+ }
29
+
30
+ while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
31
+ DBusMessageIter it2;
32
+ const char *key;
33
+ int type;
34
+
35
+ dbus_message_iter_recurse(&dict_iter, &it0);
36
+ dbus_message_iter_get_basic(&it0, &key);
37
+ dbus_message_iter_next(&it0);
38
+ dbus_message_iter_recurse(&it0, &it1);
39
+
40
+ type = dbus_message_iter_get_arg_type(&it1);
41
+
42
+ if (type == DBUS_TYPE_BYTE) {
43
+ uint8_t value;
44
+
45
+ dbus_message_iter_get_basic(&it1, &value);
46
+ spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
47
+
48
+ if (spa_streq(key, "PHY"))
49
+ qos->qos.phy = value;
50
+ else if (spa_streq(key, "Retransmissions"))
51
+ qos->qos.retransmission = value;
52
+ else if (spa_streq(key, "CIG"))
53
+ qos->cig = value;
54
+ else if (spa_streq(key, "CIS"))
55
+ qos->cis = value;
56
+ else if (spa_streq(key, "BIG"))
57
+ qos->big = value;
58
+ else if (spa_streq(key, "BIS"))
59
+ qos->bis = value;
60
+ else if (spa_streq(key, "TargetLatency"))
61
+ qos->qos.target_latency = value;
62
+ else if (spa_streq(key, "Framing"))
63
+ qos->qos.framing = value;
64
+ }
65
+ else if (type == DBUS_TYPE_UINT16) {
66
+ dbus_uint16_t value;
67
+
68
+ dbus_message_iter_get_basic(&it1, &value);
69
+ spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
70
+
71
+ if (spa_streq(key, "SDU"))
72
+ qos->qos.sdu = value;
73
+ else if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency"))
74
+ qos->qos.latency = value;
75
+ }
76
+ else if (type == DBUS_TYPE_UINT32) {
77
+ dbus_uint32_t value;
78
+
79
+ dbus_message_iter_get_basic(&it1, &value);
80
+ spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value);
81
+
82
+ if (spa_streq(key, "Interval"))
83
+ qos->qos.interval = value;
84
+ else if (spa_streq(key, "PresentationDelay"))
85
+ qos->qos.delay = value;
86
+ }
87
+
88
+ dbus_message_iter_next(&dict_iter);
89
+ }
90
+}
91
+
92
+static void parse_endpoint_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter,
93
+ struct bap_endpoint_qos *qos)
94
+{
95
+ DBusMessageIter dict_iter = *iter;
96
+
97
+ if (!check_iter_signature(&dict_iter, "{sv}")) {
98
+ spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus");
99
+ return;
100
+ }
101
+
102
+ while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
103
+ DBusMessageIter it2;
104
+ const char *key;
105
+ int type;
106
+
107
+ dbus_message_iter_recurse(&dict_iter, &it0);
108
+ dbus_message_iter_get_basic(&it0, &key);
109
+ dbus_message_iter_next(&it0);
110
+ dbus_message_iter_recurse(&it0, &it1);
111
+
112
+ type = dbus_message_iter_get_arg_type(&it1);
113
+
114
+ if (type == DBUS_TYPE_BYTE) {
115
+ uint8_t value;
116
+
117
+ dbus_message_iter_get_basic(&it1, &value);
118
+ spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
119
+
120
+ if (spa_streq(key, "Framing"))
121
+ qos->framing = value;
122
+ else if (spa_streq(key, "PHY"))
123
+ qos->phy = value;
124
+ else if (spa_streq(key, "Retransmissions"))
125
+ qos->retransmission = value;
126
+ } else if (type == DBUS_TYPE_UINT16) {
127
+ dbus_uint16_t value;
128
+
129
+ dbus_message_iter_get_basic(&it1, &value);
130
+ spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
131
+
132
+ if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency"))
133
+ qos->latency = value;
134
+ else if (spa_streq(key, "Context"))
135
+ qos->context = value;
136
+ else if (spa_streq(key, "SupportedContext"))
137
+ qos->supported_context = value;
138
+ } else if (type == DBUS_TYPE_UINT32) {
139
+ dbus_uint32_t value;
140
+
141
+ dbus_message_iter_get_basic(&it1, &value);
142
+ spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value);
143
+
144
+ if (spa_streq(key, "MinimumDelay"))
145
+ qos->delay_min = value;
146
+ else if (spa_streq(key, "MaximumDelay"))
147
+ qos->delay_max = value;
148
+ else if (spa_streq(key, "PreferredMinimumDelay"))
149
+ qos->preferred_delay_min = value;
150
+ else if (spa_streq(key, "PreferredMaximumDelay"))
151
+ qos->preferred_delay_max = value;
152
+ else if (spa_streq(key, "Locations") || spa_streq(key, "Location"))
153
+ qos->locations = value;
154
+ }
155
+
156
+ dbus_message_iter_next(&dict_iter);
157
+ }
158
+}
159
+
160
+static int parse_endpoint_props(struct spa_bt_monitor *monitor, DBusMessageIter *iter,
161
+ uint8_t capsA2DP_MAX_CAPS_SIZE, int *caps_size, const char **endpoint_path,
162
+ struct bap_endpoint_qos *qos)
163
+{
164
+ DBusMessageIter dict_iter = *iter;
165
+ const char *key = NULL;
166
+ int type = 0;
167
+
168
+ memset(caps, 0, A2DP_MAX_CAPS_SIZE);
169
+ *endpoint_path = NULL;
170
+ memset(qos, 0, sizeof(*qos));
171
+
172
+ if (!check_iter_signature(&dict_iter, "{sv}")) {
173
+ spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus");
174
+ return -EINVAL;
175
+ }
176
+
177
+ while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
178
+ DBusMessageIter it3;
179
+
180
+ dbus_message_iter_recurse(&dict_iter, &it0);
181
+ dbus_message_iter_get_basic(&it0, &key);
182
+ dbus_message_iter_next(&it0);
183
+ dbus_message_iter_recurse(&it0, &it1);
184
+
185
+ type = dbus_message_iter_get_arg_type(&it1);
186
+
187
+ if (spa_streq(key, "Capabilities")) {
188
+ uint8_t *buf;
189
+
190
+ if (type != DBUS_TYPE_ARRAY)
191
+ goto bad_property;
192
+
193
+ dbus_message_iter_recurse(&it1, &it2);
194
+ type = dbus_message_iter_get_arg_type(&it2);
195
+ if (type != DBUS_TYPE_BYTE)
196
+ goto bad_property;
197
+
198
+ dbus_message_iter_get_fixed_array(&it2, &buf, caps_size);
199
+ if (*caps_size > A2DP_MAX_CAPS_SIZE) {
200
+ spa_log_error(monitor->log, "%s size:%d too large", key, (int)*caps_size);
201
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
20
1
2
name = "audio-gateway";
3
desc = _("Audio Gateway (A2DP Source & HSP/HFP AG)");
4
}
5
- priority = 256;
6
+
7
+ /*
8
+ * If the remote is A2DP sink and HF, we likely should prioritize being
9
+ * A2DP sender, not gateway. This can occur in PW<->PW if RFCOMM gets
10
+ * connected both as AG and HF.
11
+ */
12
+ if ((device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) &&
13
+ (device->connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT))
14
+ priority = 15;
15
+ else
16
+ priority = 256;
17
break;
18
}
19
case DEVICE_PROFILE_A2DP:
20
pipewire-0.3.80.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/loop.c
Changed
55
1
2
#include <spa/support/plugin.h>
3
#include <spa/utils/list.h>
4
#include <spa/utils/names.h>
5
+#include <spa/utils/ratelimit.h>
6
#include <spa/utils/result.h>
7
#include <spa/utils/type.h>
8
#include <spa/utils/ringbuffer.h>
9
10
11
struct spa_source *wakeup;
12
int ack_fd;
13
+ struct spa_ratelimit rate_limit;
14
15
struct spa_ringbuffer buffer;
16
uint8_t *buffer_data;
17
18
};
19
/** \endcond */
20
21
+static inline uint64_t get_time_ns(struct spa_system *system)
22
+{
23
+ struct timespec ts;
24
+ spa_system_clock_gettime(system, CLOCK_MONOTONIC, &ts);
25
+ return SPA_TIMESPEC_TO_NSEC(&ts);
26
+}
27
+
28
static int loop_add_source(void *object, struct spa_source *source)
29
{
30
struct impl *impl = object;
31
32
item->item_size = SPA_ROUND_UP_N(l0 + size, ITEM_ALIGN);
33
}
34
if (avail < item->item_size) {
35
- spa_log_warn(impl->log, "%p: queue full %d, need %zd", impl, avail,
36
- item->item_size);
37
+ int suppressed;
38
+ uint64_t nsec = get_time_ns(impl->system);
39
+ if ((suppressed = spa_ratelimit_test(&impl->rate_limit, nsec)) >= 0) {
40
+ spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)",
41
+ impl, avail, item->item_size, suppressed);
42
+ }
43
return -EPIPE;
44
}
45
if (data && size > 0)
46
47
res = -EINVAL;
48
goto error_exit;
49
}
50
+ impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
51
+ impl->rate_limit.burst = 1;
52
53
if ((res = spa_system_pollfd_create(impl->system, SPA_FD_CLOEXEC)) < 0) {
54
spa_log_error(impl->log, "%p: can't create pollfd: %s",
55
pipewire-0.3.80.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/node-driver.c
Changed
22
1
2
#ifdef CLOCK_MONOTONIC_RAW
3
{ "monotonic-raw", CLOCK_MONOTONIC_RAW },
4
#endif
5
+#ifdef CLOCK_BOOTTIME
6
{ "boottime", CLOCK_BOOTTIME },
7
+#endif
8
};
9
10
static bool clock_for_timerfd(clockid_t id)
11
{
12
return id == CLOCK_REALTIME ||
13
- id == CLOCK_MONOTONIC ||
14
- id == CLOCK_BOOTTIME;
15
+#ifdef CLOCK_BOOTTIME
16
+ id == CLOCK_BOOTTIME ||
17
+#endif
18
+ id == CLOCK_MONOTONIC;
19
}
20
21
static clockid_t clock_name_to_id(const char *name)
22
pipewire-0.3.80.tar.gz/spa/tests/stress-ringbuffer.c -> pipewire-0.3.81.tar.gz/spa/tests/stress-ringbuffer.c
Changed
15
1
2
#define ARRAY_SIZE 63
3
#define MAX_VALUE 0x10000
4
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined (__GNU__)
7
#include <sys/param.h>
8
#if (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400043) \
9
- || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__)
10
+ || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__) \
11
+ || defined (__GNU__)
12
static int sched_getcpu(void) { return -1; };
13
#endif
14
#endif
15
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/demonic.conf
Changed
13
1
2
# ~/.config/pipewire/filter-chain.conf.d/
3
#
4
context.modules =
5
- { name = libpipewire-module-filter-chain
6
- args = {
7
+ { name = libpipewire-module-filter-chain
8
+ flags = nofail
9
+ args = {
10
#audio.format = F32
11
#audio.rate = 48000
12
audio.channels = 2
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf
Changed
9
1
2
#
3
context.modules =
4
{ name = libpipewire-module-filter-chain
5
+ flags = nofail
6
args = {
7
node.description = "Dolby Surround Sink"
8
media.name = "Dolby Surround Sink"
9
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf
Changed
9
1
2
3
context.modules =
4
{ name = libpipewire-module-filter-chain
5
+ flags = nofail
6
args = {
7
node.description = "Matrix Spatialiser"
8
media.name = "Matrix Spatialiser"
9
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf
Changed
13
1
2
# Copy this file into a conf.d/ directory such as
3
# ~/.config/pipewire/filter-chain.conf.d/
4
#
5
+# Adjust the paths to the convolver files to match your system
6
+#
7
context.modules =
8
{ name = libpipewire-module-filter-chain
9
+ flags = nofail
10
args = {
11
node.description = "Virtual Surround Sink"
12
media.name = "Virtual Surround Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf
Changed
13
1
2
# Copy this file into a conf.d/ directory such as
3
# ~/.config/pipewire/filter-chain.conf.d/
4
#
5
+# Adjust the paths to the convolver files to match your system
6
+#
7
context.modules =
8
{ name = libpipewire-module-filter-chain
9
+ flags = nofail
10
args = {
11
node.description = "Virtual Surround Sink"
12
media.name = "Virtual Surround Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/source-rnnoise.conf
Changed
28
1
2
# Copy this file into a conf.d/ directory such as
3
# ~/.config/pipewire/filter-chain.conf.d/
4
#
5
+# Adjust the paths to the rnnoise plugin to match your system
6
+#
7
context.modules =
8
{ name = libpipewire-module-filter-chain
9
+ flags = nofail
10
args = {
11
node.description = "Noise Canceling source"
12
media.name = "Noise Canceling source"
13
14
{
15
type = ladspa
16
name = rnnoise
17
- plugin = librnnoise_ladspa
18
+ # The path to the plugin. The suffix .so is appended to
19
+ # this string and then the file is then located in the directories
20
+ # listed in the environment variable LADSPA_PATH or
21
+ # /usr/lib64/ladspa, /usr/lib/ladspa or the system library directory
22
+ # as a fallback.
23
+ # You might want to use an absolute path here to avoid problems.
24
+ plugin = "librnnoise_ladspa"
25
label = noise_suppressor_stereo
26
control = {
27
"VAD Threshold (%)" 50.0
28
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf
Changed
13
1
2
# Copy this file into a conf.d/ directory such as
3
# ~/.config/pipewire/filter-chain.conf.d/
4
#
5
+# Adjust the paths to the sofa file to match your system.
6
+#
7
context.modules =
8
{ name = libpipewire-module-filter-chain
9
+ flags = nofail
10
args = {
11
node.description = "Spatial Sink"
12
media.name = "Spatial Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-single.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-single.conf
Changed
13
1
2
# Copy this file into a conf.d/ directory such as
3
# ~/.config/pipewire/filter-chain.conf.d/
4
#
5
+# Adjust the paths to the sofa files to match your system
6
+#
7
context.modules =
8
{ name = libpipewire-module-filter-chain
9
+ flags = nofail
10
args = {
11
node.description = "3D Sink"
12
media.name = "3D Sink"
13
pipewire-0.3.80.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
9
1
2
args = {
3
nice.level = -11
4
#rt.prio = 88
5
+ rt.prio = 65
6
#rt.time.soft = -1
7
#rt.time.hard = -1
8
}
9
pipewire-0.3.80.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire.conf.in
Changed
40
1
2
# enables autoloading of access module, when disabled an alternative
3
# access module needs to be loaded.
4
module.access = true
5
+ # enables autoloading of module-jackdbus-detect
6
+ module.jackdbus-detect = true
7
}
8
9
context.spa-libs = {
10
11
flags = ifexists nofail
12
condition = { module.x11.bell = true }
13
}
14
+ { name = libpipewire-module-jackdbus-detect
15
+ args {
16
+ #jack.library = libjack.so.0
17
+ #jack.server = null
18
+ #jack.client-name = PipeWire
19
+ #jack.connect = true
20
+ #tunnel.mode = duplex # source|sink|duplex
21
+ source.props = {
22
+ #audio.channels = 2
23
+ #midi.ports = 1
24
+ #audio.position = FL FR
25
+ # extra sink properties
26
+ }
27
+ sink.props = {
28
+ #audio.channels = 2
29
+ #midi.ports = 1
30
+ #audio.position = FL FR
31
+ # extra sink properties
32
+ }
33
+ }
34
+ flags = ifexists nofail
35
+ condition = { module.jackdbus-detect = true }
36
+ }
37
38
39
context.objects =
40
pipewire-0.3.80.tar.gz/src/modules/module-access.c -> pipewire-0.3.81.tar.gz/src/modules/module-access.c
Changed
10
1
2
* (in the current namespace).
3
*/
4
5
-#if defined(__linux__)
6
+#if defined(__linux__) || defined(__GNU__)
7
spa_scnprintf(path, sizeof(path), "/proc/%u/exe", pid);
8
#elif defined(__FreeBSD__) || defined(__MidnightBSD__)
9
spa_scnprintf(path, sizeof(path), "/proc/%u/file", pid);
10
pipewire-0.3.80.tar.gz/src/modules/module-ffado-driver.c -> pipewire-0.3.81.tar.gz/src/modules/module-ffado-driver.c
Changed
37
1
2
* ## Module Options
3
*
4
* - `driver.mode`: the driver mode, sink|source|duplex, default duplex
5
- * - `ffado.devices`: array of devices to open, default hw:0
6
+ * - `ffado.devices`: array of devices to open, default "hw:0"
7
* - `ffado.period-size`: period size,default 1024
8
* - `ffado.period-num`: period number,default 3
9
* - `ffado.sample-rate`: sample-rate, default 48000
10
11
* { name = libpipewire-module-ffado-driver
12
* args = {
13
* #driver.mode = duplex
14
- * #ffado.devices = hw:0
15
+ * #ffado.devices = "hw:0"
16
* #ffado.period-size = 1024
17
* #ffado.period-num = 3
18
* #ffado.sample-rate = 48000
19
20
21
#define MAX_PORTS 128
22
23
-#define DEFAULT_DEVICES " hw:0 "
24
+#define DEFAULT_DEVICES " \"hw:0\" "
25
#define DEFAULT_PERIOD_SIZE 1024
26
#define DEFAULT_PERIOD_NUM 3
27
#define DEFAULT_SAMPLE_RATE 48000
28
29
30
#define MODULE_USAGE "( remote.name=<remote> ) " \
31
"( driver.mode=<sink|source|duplex> ) " \
32
- "( ffado.devices=<devices array size, default hw:0> ) " \
33
+ "( ffado.devices=<devices array size, default \"hw:0\"> ) " \
34
"( ffado.period-size=<period size, default 1024> ) " \
35
"( ffado.period-num=<period num, default 3> ) " \
36
"( ffado.sample-rate=<sampe rate, default 48000> ) " \
37
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain.c
Changed
201
1
2
*
3
* inputs = <portname> ...
4
* outputs = <portname> ...
5
+ * capture.volumes =
6
+ * { control = <portname> min = <value> max = <value> scale = <scale> } ...
7
+ *
8
+ * playback.volumes =
9
+ * { control = <portname> min = <value> max = <value> scale = <scale> } ...
10
+ *
11
* }
12
*\endcode
13
*
14
15
* graph will then be duplicated as many times to match the number of input/output
16
* channels of the streams.
17
*
18
+ * ### Volumes
19
+ *
20
+ * Normally the volume of the sink/source is handled by the stream software volume.
21
+ * With the capture.volumes and playback.volumes properties this can be handled
22
+ * by a control port in the graph instead.
23
+ *
24
+ * The min and max values (defaults 0.0 and 1.0) respectively can be used to scale
25
+ * and translate the volume min and max values.
26
+ *
27
+ * Normally the control values are linear and it is assumed that the plugin does not
28
+ * perform any scaling to the values. This can be changed with the scale property. By
29
+ * default this is linear but it can be set to cubic when the control applies a
30
+ * cubic transformation.
31
+ *
32
* ## Builtin filters
33
*
34
* There are some useful builtin filters available. You select them with the label
35
36
uint32_t n_links;
37
uint32_t external;
38
39
- float control_data;
40
+ float control_dataMAX_HNDL;
41
float *audio_dataMAX_HNDL;
42
};
43
44
45
void **hndl;
46
};
47
48
+struct volume {
49
+ bool mute;
50
+ uint32_t n_volumes;
51
+ float volumesSPA_AUDIO_MAX_CHANNELS;
52
+
53
+ uint32_t n_ports;
54
+ struct port *portsSPA_AUDIO_MAX_CHANNELS;
55
+ float minSPA_AUDIO_MAX_CHANNELS;
56
+ float maxSPA_AUDIO_MAX_CHANNELS;
57
+#define SCALE_LINEAR 0
58
+#define SCALE_CUBIC 1
59
+ int scaleSPA_AUDIO_MAX_CHANNELS;
60
+};
61
+
62
struct graph {
63
struct impl *impl;
64
65
66
uint32_t n_control;
67
struct port **control_port;
68
69
+ struct volume capture_volume;
70
+ struct volume playback_volume;
71
+
72
unsigned instantiated:1;
73
};
74
75
76
77
spa_pod_builder_string(b, name);
78
if (p->hint & FC_HINT_BOOLEAN) {
79
- spa_pod_builder_bool(b, port->control_data <= 0.0f ? false : true);
80
+ spa_pod_builder_bool(b, port->control_data0 <= 0.0f ? false : true);
81
} else if (p->hint & FC_HINT_INTEGER) {
82
- spa_pod_builder_int(b, port->control_data);
83
+ spa_pod_builder_int(b, port->control_data0);
84
} else {
85
- spa_pod_builder_float(b, port->control_data);
86
+ spa_pod_builder_float(b, port->control_data0);
87
}
88
}
89
spa_pod_builder_pop(b, &f1);
90
return spa_pod_builder_pop(b, &f0);
91
}
92
93
+static int port_set_control_value(struct port *port, float *value, uint32_t id)
94
+{
95
+ struct node *node = port->node;
96
+ struct descriptor *desc = node->desc;
97
+ float old;
98
+
99
+ old = port->control_dataid;
100
+ port->control_dataid = value ? *value : desc->default_controlport->idx;
101
+ pw_log_info("control %d %d ('%s') from %f to %f", port->idx, id,
102
+ desc->desc->portsport->p.name, old, port->control_dataid);
103
+ node->control_changed = old != port->control_dataid;
104
+ return node->control_changed ? 1 : 0;
105
+}
106
+
107
static int set_control_value(struct node *node, const char *name, float *value)
108
{
109
- struct descriptor *desc;
110
struct port *port;
111
- float old;
112
+ int count = 0;
113
+ uint32_t i, n_hndl;
114
115
port = find_port(node, name, FC_PORT_INPUT | FC_PORT_CONTROL);
116
if (port == NULL)
117
return -ENOENT;
118
119
- node = port->node;
120
- desc = node->desc;
121
+ /* if we don't have any instances yet, set the first control value, we will
122
+ * copy to other instances later */
123
+ n_hndl = SPA_MAX(1u, port->node->n_hndl);
124
+ for (i = 0; i < n_hndl; i++)
125
+ count += port_set_control_value(port, value, i);
126
127
- old = port->control_data;
128
- port->control_data = value ? *value : desc->default_controlport->idx;
129
- pw_log_info("control %d ('%s') from %f to %f", port->idx, name, old, port->control_data);
130
- node->control_changed = old != port->control_data;
131
- return node->control_changed ? 1 : 0;
132
+ return count;
133
}
134
135
static int parse_params(struct graph *graph, const struct spa_pod *pod)
136
137
spa_pod_dynamic_builder_clean(&b);
138
}
139
140
-static void param_props_changed(struct impl *impl, const struct spa_pod *param)
141
+static int sync_volume(struct graph *graph, struct volume *vol)
142
+{
143
+ uint32_t i;
144
+ int res = 0;
145
+
146
+ if (vol->n_ports == 0)
147
+ return 0;
148
+ for (i = 0; i < vol->n_volumes; i++) {
149
+ uint32_t n_port = i % vol->n_ports, n_hndl;
150
+ struct port *p = vol->portsn_port;
151
+ float v = vol->mute ? 0.0f : vol->volumesi;
152
+ switch (vol->scalen_port) {
153
+ case SCALE_CUBIC:
154
+ v = cbrt(v);
155
+ break;
156
+ }
157
+ v = v * (vol->maxn_port - vol->minn_port) + vol->minn_port;
158
+
159
+ n_hndl = SPA_MAX(1u, p->node->n_hndl);
160
+ res += port_set_control_value(p, &v, i % n_hndl);
161
+ }
162
+ return res;
163
+}
164
+
165
+static void param_props_changed(struct impl *impl, const struct spa_pod *param,
166
+ bool capture)
167
{
168
struct spa_pod_object *obj = (struct spa_pod_object *) param;
169
+ struct spa_pod_frame f1;
170
const struct spa_pod_prop *prop;
171
struct graph *graph = &impl->graph;
172
int changed = 0;
173
+ char buf1024;
174
+ struct spa_pod_dynamic_builder b;
175
+ struct volume *vol = capture ? &graph->capture_volume :
176
+ &graph->playback_volume;
177
+ bool do_volume = false;
178
+
179
+ spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 1024);
180
+ spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
181
182
SPA_POD_OBJECT_FOREACH(obj, prop) {
183
- if (prop->key == SPA_PROP_params)
184
+ switch (prop->key) {
185
+ case SPA_PROP_params:
186
changed += parse_params(graph, &prop->value);
187
+ spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop));
188
+ break;
189
+ case SPA_PROP_mute:
190
+ {
191
+ bool mute;
192
+ if (spa_pod_get_bool(&prop->value, &mute) == 0) {
193
+ if (vol->mute != mute) {
194
+ vol->mute = mute;
195
+ do_volume = true;
196
+ }
197
+ }
198
+ spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop));
199
+ break;
200
+ }
201
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c
Changed
11
1
2
uint32_t i;
3
if (n_src == 0) {
4
dsp_clear_c(ops, dst, n_samples);
5
- } else if (n_src == 1) {
6
- if (dst != src0)
7
- dsp_copy_c(ops, dst, src0, n_samples);
8
} else {
9
if (gain0 == 1.0f)
10
dsp_copy_c(ops, dst, src0, n_samples);
11
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c
Changed
10
1
2
{
3
if (n_src == 0) {
4
memset(dst, 0, n_samples * sizeof(float));
5
- } else if (n_src == 1) {
6
+ } else if (n_src == 1 && gain0 == 1.0f) {
7
if (dst != src0)
8
spa_memcpy(dst, src0, n_samples * sizeof(float));
9
} else {
10
pipewire-0.3.80.tar.gz/src/modules/module-pipe-tunnel.c -> pipewire-0.3.81.tar.gz/src/modules/module-pipe-tunnel.c
Changed
9
1
2
#include <errno.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5
+#include <sys/uio.h>
6
#include <fcntl.h>
7
#include <unistd.h>
8
#include <stdlib.h>
9
pipewire-0.3.80.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.81.tar.gz/src/modules/module-profiler.c
Changed
10
1
2
n->count++;
3
}
4
5
-static struct pw_impl_node_rt_events node_rt_events = {
6
+static const struct pw_impl_node_rt_events node_rt_events = {
7
PW_VERSION_IMPL_NODE_RT_EVENTS,
8
.complete = context_do_profile,
9
.incomplete = context_do_profile,
10
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
9
1
2
spa_list_init(&client->out_messages);
3
spa_list_init(&client->operations);
4
spa_list_init(&client->pending_samples);
5
- spa_list_init(&client->pending_streams);
6
spa_hook_list_init(&client->listener_list);
7
8
spa_list_append(&server->clients, &client->link);
9
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.h
Changed
10
1
2
3
struct spa_list pending_samples;
4
5
- struct spa_list pending_streams;
6
-
7
unsigned int disconnect:1;
8
unsigned int new_msg_since_last_flush:1;
9
unsigned int authenticated:1;
10
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/manager.c
Changed
12
1
2
case SPA_PARAM_PropInfo:
3
case SPA_PARAM_Format:
4
case SPA_PARAM_EnumFormat:
5
+ /* also emit changed for the Latency param because the stream might
6
+ * now be linked. FIXME, we should check if a new link is made for
7
+ * a stream and only emit a changed event in that case. */
8
+ case SPA_PARAM_Latency:
9
changed++;
10
break;
11
default:
12
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
13
1
2
char *args;
3
size_t size;
4
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->source_props, "pulse.module.id", "%u", module->index);
7
+ pw_properties_setf(data->sink_props, "pulse.module.id", "%u", module->index);
8
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
9
+
10
if ((f = open_memstream(&args, &size)) == NULL)
11
return -errno;
12
13
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
160
1
2
}
3
4
if (spa_streq(o->type, PW_TYPE_INTERFACE_Link)) {
5
- struct stream *s, *t;
6
struct pw_manager_object *peer = NULL;
7
union pw_map_item *item;
8
pw_array_for_each(item, &client->streams.items) {
9
struct stream *s = item->data;
10
const char *peer_name;
11
12
- if (pw_map_item_is_free(item) || s->pending)
13
+ if (pw_map_item_is_free(item))
14
continue;
15
- if (s->peer_index == SPA_ID_INVALID)
16
+
17
+ if (!s->pending && s->peer_index == SPA_ID_INVALID)
18
continue;
19
20
peer = find_peer_for_link(manager, o, s->id, s->direction);
21
- if (peer == NULL || peer->props == NULL ||
22
- peer->index == s->peer_index)
23
+ if (peer == NULL)
24
continue;
25
26
- s->peer_index = peer->index;
27
-
28
- peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
29
- if (peer_name && s->direction == PW_DIRECTION_INPUT &&
30
- pw_manager_object_is_monitor(peer)) {
31
- int len = strlen(peer_name) + 10;
32
- char *tmp = alloca(len);
33
- snprintf(tmp, len, "%s.monitor", peer_name);
34
- peer_name = tmp;
35
- }
36
- if (peer_name != NULL)
37
- stream_send_moved(s, peer->index, peer_name);
38
- }
39
- spa_list_for_each_safe(s, t, &client->pending_streams, link) {
40
- peer = find_peer_for_link(manager, o, s->id, s->direction);
41
- if (peer) {
42
+ if (s->pending) {
43
reply_create_stream(s, peer);
44
- spa_list_remove(&s->link);
45
s->pending = false;
46
+ } else {
47
+ if (s->peer_index == peer->index)
48
+ continue;
49
+ if (peer->props == NULL)
50
+ continue;
51
+
52
+ s->peer_index = peer->index;
53
+
54
+ peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
55
+ if (peer_name && s->direction == PW_DIRECTION_INPUT &&
56
+ pw_manager_object_is_monitor(peer)) {
57
+ int len = strlen(peer_name) + 10;
58
+ char *tmp = alloca(len);
59
+ snprintf(tmp, len, "%s.monitor", peer_name);
60
+ peer_name = tmp;
61
+ }
62
+ if (peer_name != NULL)
63
+ stream_send_moved(s, peer->index, peer_name);
64
}
65
}
66
}
67
68
if (peer) {
69
reply_create_stream(stream, peer);
70
} else {
71
- spa_list_append(&stream->client->pending_streams, &stream->link);
72
stream->pending = true;
73
}
74
}
75
76
const char *str;
77
int res = 0;
78
79
+ debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
80
+
81
impl = calloc(1, sizeof(*impl) + user_data_size);
82
if (impl == NULL)
83
- goto error_exit;
84
+ goto error_free_props;
85
+
86
+ impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
87
+ impl->rate_limit.burst = 1;
88
+ spa_hook_list_init(&impl->hooks);
89
+ spa_list_init(&impl->servers);
90
+ pw_map_init(&impl->samples, 16, 16);
91
+ pw_map_init(&impl->modules, 16, 16);
92
+ spa_list_init(&impl->cleanup_clients);
93
+ spa_list_init(&impl->free_messages);
94
+
95
+ impl->loop = pw_context_get_main_loop(context);
96
+ impl->work_queue = pw_context_get_work_queue(context);
97
98
if (props == NULL)
99
props = pw_properties_new(NULL, NULL);
100
101
pw_properties_set(props, "vm.overrides", NULL);
102
}
103
104
- load_defaults(&impl->defs, props);
105
-
106
- debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
107
-
108
- impl->context = context;
109
- impl->loop = pw_context_get_main_loop(context);
110
- impl->props = props;
111
-
112
- impl->work_queue = pw_context_get_work_queue(context);
113
-
114
- spa_hook_list_init(&impl->hooks);
115
- spa_list_init(&impl->servers);
116
- impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
117
- impl->rate_limit.burst = 1;
118
- pw_map_init(&impl->samples, 16, 16);
119
- pw_map_init(&impl->modules, 16, 16);
120
- spa_list_init(&impl->cleanup_clients);
121
- spa_list_init(&impl->free_messages);
122
-
123
str = pw_properties_get(props, "server.address");
124
if (str == NULL) {
125
pw_properties_setf(props, "server.address",
126
127
pw_log_warn("%p: can't create pid file: %s",
128
impl, spa_strerror(res));
129
}
130
- pw_context_add_listener(context, &impl->context_listener,
131
- &context_events, impl);
132
133
#ifdef HAVE_DBUS
134
str = pw_properties_get(props, "server.dbus-name");
135
136
if (strlen(str) > 0)
137
impl->dbus_name = dbus_request_name(context, str);
138
#endif
139
+
140
+ load_defaults(&impl->defs, props);
141
+ impl->props = spa_steal_ptr(props);
142
+
143
+ pw_context_add_listener(context, &impl->context_listener,
144
+ &context_events, impl);
145
+ impl->context = context;
146
+
147
cmd_run(impl);
148
149
return (struct pw_protocol_pulse *) impl;
150
151
error_free:
152
- free(impl);
153
+ impl_free(impl);
154
155
-error_exit:
156
+error_free_props:
157
pw_properties_free(props);
158
159
if (res < 0)
160
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
11
1
2
3
pw_log_debug("client %p: stream %p channel:%d", client, stream, stream->channel);
4
5
- if (stream->pending)
6
- spa_list_remove(&stream->link);
7
-
8
if (stream->drain_tag)
9
reply_error(client, -1, stream->drain_tag, -ENOENT);
10
11
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
9
1
2
};
3
4
struct stream {
5
- struct spa_list link;
6
uint32_t create_tag;
7
uint32_t channel; /* index in map */
8
uint32_t id; /* id of global */
9
pipewire-0.3.80.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop-sink.c
Changed
201
1
2
#include <pipewire/i18n.h>
3
4
#include "module-raop/rtsp-client.h"
5
+#include "module-rtp/rtp.h"
6
7
/** \page page_module_raop_sink PipeWire Module: AirPlay Sink
8
*
9
10
#endif
11
#define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH)
12
13
-#define DEFAULT_USER_AGENT "iTunes/11.0.4 (Windows; N)"
14
-#define DEFAULT_USER_NAME "iTunes"
15
+#define DEFAULT_USER_NAME "PipeWire"
16
+#define RAOP_AUTH_USER_NAME "iTunes"
17
18
#define MAX_PORT_RETRY 128
19
20
21
#define DEFAULT_CHANNELS 2
22
#define DEFAULT_POSITION " FL FR "
23
24
-#define VOLUME_MAX 0.0
25
-#define VOLUME_DEF -30.0
26
-#define VOLUME_MIN -144.0
27
+#define VOLUME_MAX 0.0
28
+#define VOLUME_MIN -30.0
29
+#define VOLUME_MUTE -144.0
30
31
#define MODULE_USAGE "( raop.ip=<ip address of host> ) " \
32
"( raop.port=<remote port> ) " \
33
34
35
unsigned int do_disconnect:1;
36
37
- uint8_t keyAES_CHUNK_SIZE; /* Key for aes-cbc */
38
- uint8_t ivAES_CHUNK_SIZE; /* Initialization vector for cbc */
39
+ uint8_t aes_keyAES_CHUNK_SIZE; /* Key for aes-cbc */
40
+ uint8_t aes_ivAES_CHUNK_SIZE; /* Initialization vector for cbc */
41
EVP_CIPHER_CTX *ctx;
42
43
uint16_t control_port;
44
int control_fd;
45
struct spa_source *control_source;
46
+ struct spa_source *feedback_timer;
47
48
uint16_t timing_port;
49
int timing_fd;
50
51
uint32_t block_size;
52
uint32_t latency;
53
54
- uint16_t seq;
55
+ uint16_t seq, cseq;
56
uint32_t rtptime;
57
uint32_t ssrc;
58
uint32_t sync;
59
60
static int aes_encrypt(struct impl *impl, uint8_t *data, int len)
61
{
62
int i = len & ~0xf, clen = i;
63
- EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->key, impl->iv);
64
+ EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->aes_key, impl->aes_iv);
65
EVP_EncryptUpdate(impl->ctx, data, &clen, data, i);
66
return i;
67
}
68
69
static int send_udp_sync_packet(struct impl *impl,
70
struct sockaddr *dest_addr, socklen_t addrlen)
71
{
72
- uint32_t pkt5;
73
+ uint32_t out3;
74
uint32_t rtptime = impl->rtptime;
75
uint32_t latency = impl->latency;
76
uint64_t transmitted;
77
+ struct rtp_header header;
78
+ struct iovec iov2;
79
+ struct msghdr msg;
80
+ int res;
81
82
- pkt0 = htonl(0x80d40007);
83
+ spa_zero(header);
84
+ header.v = 2;
85
if (impl->first)
86
- pkt0 |= htonl(0x10000000);
87
- pkt1 = htonl(rtptime - latency);
88
+ header.x = 1;
89
+ header.m = 1;
90
+ header.pt = 84;
91
+ header.sequence_number = htons(impl->cseq);
92
+ header.timestamp = htonl(rtptime - latency);
93
+
94
+ iov0.iov_base = &header;
95
+ iov0.iov_len = 8;
96
+
97
transmitted = ntp_now();
98
- pkt2 = htonl(transmitted >> 32);
99
- pkt3 = htonl(transmitted & 0xffffffff);
100
- pkt4 = htonl(rtptime);
101
+ out0 = htonl(transmitted >> 32);
102
+ out1 = htonl(transmitted & 0xffffffff);
103
+ out2 = htonl(rtptime);
104
+
105
+ iov1.iov_base = out;
106
+ iov1.iov_len = sizeof(out);
107
+
108
+ msg.msg_name = dest_addr;
109
+ msg.msg_namelen = addrlen;
110
+ msg.msg_iov = iov;
111
+ msg.msg_iovlen = 2;
112
+ msg.msg_control = NULL;
113
+ msg.msg_controllen = 0;
114
+ msg.msg_flags = 0;
115
+
116
+ res = sendmsg(impl->control_fd, &msg, MSG_NOSIGNAL);
117
+ if (res < 0) {
118
+ res = -errno;
119
+ pw_log_warn("error sending control packet: %d", res);
120
+ }
121
+
122
+ impl->cseq = (impl->cseq + 1) & 0xffff;
123
124
- pw_log_debug("sync: first:%d latency:%u now:%"PRIx64" rtptime:%u",
125
- impl->first, latency, transmitted, rtptime);
126
+ pw_log_debug("raop control sync: cseq:%d first:%d latency:%u now:%"PRIx64" rtptime:%u",
127
+ impl->cseq, impl->first, latency, transmitted, rtptime);
128
129
- return sendto(impl->control_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen);
130
+ return res;
131
}
132
133
static int send_udp_timing_packet(struct impl *impl, uint64_t remote, uint64_t received,
134
struct sockaddr *dest_addr, socklen_t addrlen)
135
{
136
- uint32_t pkt8;
137
+ uint32_t out6;
138
uint64_t transmitted;
139
+ struct rtp_header header;
140
+ struct iovec iov2;
141
+ struct msghdr msg;
142
+ int res;
143
144
- pkt0 = htonl(0x80d30007);
145
- pkt1 = 0x00000000;
146
- pkt2 = htonl(remote >> 32);
147
- pkt3 = htonl(remote & 0xffffffff);
148
- pkt4 = htonl(received >> 32);
149
- pkt5 = htonl(received & 0xffffffff);
150
- transmitted = ntp_now();
151
- pkt6 = htonl(transmitted >> 32);
152
- pkt7 = htonl(transmitted & 0xffffffff);
153
+ spa_zero(header);
154
+ header.v = 2;
155
+ header.pt = 83;
156
+ header.m = 1;
157
+
158
+ iov0.iov_base = &header;
159
+ iov0.iov_len = 8;
160
+
161
+ out0 = htonl(remote >> 32);
162
+ out1 = htonl(remote & 0xffffffff);
163
164
- pw_log_debug("sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64,
165
+ out2 = htonl(received >> 32);
166
+ out3 = htonl(received & 0xffffffff);
167
+ transmitted = ntp_now();
168
+ out4 = htonl(transmitted >> 32);
169
+ out5 = htonl(transmitted & 0xffffffff);
170
+
171
+ iov1.iov_base = out;
172
+ iov1.iov_len = sizeof(out);
173
+
174
+ msg.msg_name = dest_addr;
175
+ msg.msg_namelen = addrlen;
176
+ msg.msg_iov = iov;
177
+ msg.msg_iovlen = 2;
178
+ msg.msg_control = NULL;
179
+ msg.msg_controllen = 0;
180
+ msg.msg_flags = 0;
181
+
182
+ res = sendmsg(impl->timing_fd, &msg, MSG_NOSIGNAL);
183
+ if (res < 0) {
184
+ res = -errno;
185
+ pw_log_warn("error sending timing packet: %d", res);
186
+ }
187
+ pw_log_debug("raop timing sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64,
188
remote, received, transmitted);
189
190
- return sendto(impl->timing_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen);
191
+ return res;
192
}
193
194
static int write_codec_pcm(void *dst, void *frames, uint32_t n_frames)
195
196
197
static int flush_to_udp_packet(struct impl *impl)
198
{
199
- const size_t max = 12 + 8 + impl->block_size;
200
- uint32_t pktmax, len, n_frames;
201
pipewire-0.3.80.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
23
1
2
3
struct message {
4
struct spa_list link;
5
- void *data;
6
size_t len;
7
size_t offset;
8
uint32_t cseq;
9
int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content);
10
void *user_data;
11
+ unsigned char data;
12
};
13
14
enum client_recv_state {
15
16
17
fclose(f);
18
19
- msg->data = SPA_PTROFF(msg, sizeof(*msg), void);
20
msg->len = len - sizeof(*msg);
21
msg->offset = 0;
22
msg->reply = reply;
23
pipewire-0.3.80.tar.gz/src/modules/module-rt.c -> pipewire-0.3.81.tar.gz/src/modules/module-rt.c
Changed
21
1
2
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
3
#include <sys/thr.h>
4
#endif
5
+#if defined(__GNU__)
6
+#include <mach.h>
7
+#endif
8
#include <fcntl.h>
9
#include <unistd.h>
10
#include <pthread.h>
11
12
long pid;
13
thr_self(&pid);
14
return (pid_t)pid;
15
+#elif defined(__GNU__)
16
+ mach_port_t thread = mach_thread_self();
17
+ return (pid_t)thread;
18
#else
19
#error "No gettid impl"
20
#endif
21
pipewire-0.3.80.tar.gz/src/modules/module-rtp-session.c -> pipewire-0.3.81.tar.gz/src/modules/module-rtp-session.c
Changed
11
1
2
if (spa_streq(service_name, "_pipewire-audio._udp")) {
3
uint32_t mask = 0;
4
for (l = txt; l && compatible; l = l->next) {
5
- char *key, *value, *k = NULL;
6
+ const char *k = NULL;
7
+ char *key, *value;
8
9
if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0)
10
break;
11
pipewire-0.3.80.tar.gz/src/pipewire/conf.c -> pipewire-0.3.81.tar.gz/src/pipewire/conf.c
Changed
23
1
2
#ifdef HAVE_PWD_H
3
#include <pwd.h>
4
#endif
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
7
#ifndef O_PATH
8
#define O_PATH 0
9
#endif
10
11
char key256, val1024;
12
const char *str, *value;
13
int match = 0, fail = 0;
14
- int len, skip = 0;
15
+ int len;
16
17
while (spa_json_get_string(&it0, key, sizeof(key)) > 0) {
18
bool success = false;
19
+ int skip = 0;
20
21
if ((len = spa_json_next(&it0, &value)) <= 0)
22
break;
23
pipewire-0.3.80.tar.gz/src/pipewire/context.c -> pipewire-0.3.81.tar.gz/src/pipewire/context.c
Changed
145
1
2
struct spa_fraction latency = SPA_FRACTION(0, 0);
3
struct spa_fraction max_latency = SPA_FRACTION(0, 0);
4
struct spa_fraction rate = SPA_FRACTION(0, 0);
5
- uint32_t quantum, target_rate, current_rate;
6
+ uint32_t target_quantum, target_rate, current_rate, current_quantum;
7
uint64_t quantum_stamp = 0, rate_stamp = 0;
8
- bool force_rate, force_quantum, restore_rate = false;
9
+ bool force_rate, force_quantum, restore_rate = false, restore_quantum = false;
10
+ bool do_reconfigure = false, was_target_pending;
11
const uint32_t *node_rates;
12
uint32_t node_n_rates, node_def_rate;
13
uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum;
14
15
fraction_compare(&s->max_latency, &max_latency) < 0))
16
max_latency = s->max_latency;
17
18
- /* largest rate */
19
+ /* largest rate, which is in fact the smallest fraction */
20
if (rate.denom == 0 ||
21
(s->rate.denom > 0 &&
22
- fraction_compare(&s->rate, &rate) > 0))
23
+ fraction_compare(&s->rate, &rate) < 0))
24
rate = s->rate;
25
26
if (s->active)
27
28
pw_log_info("(%s-%u) restore rate", n->name, n->info.id);
29
restore_rate = true;
30
}
31
+ if (n->forced_quantum && !force_quantum && n->runnable) {
32
+ /* A node that was forced to a quantum but is no longer being
33
+ * forced can restore its quantum */
34
+ pw_log_info("(%s-%u) restore quantum", n->name, n->info.id);
35
+ restore_quantum = true;
36
+ }
37
38
if (force_quantum)
39
lock_quantum = false;
40
41
rate.denom, target_rate);
42
}
43
44
+ was_target_pending = n->target_pending;
45
+
46
if (target_rate != current_rate) {
47
- bool do_reconfigure = false;
48
/* we doing a rate switch */
49
pw_log_info("(%s-%u) state:%s new rate:%u/(%u)->%u",
50
n->name, n->info.id,
51
52
53
if (force_rate) {
54
if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD)
55
- do_reconfigure = !n->target_pending;
56
+ do_reconfigure |= !was_target_pending;
57
} else {
58
if (n->info.state >= PW_NODE_STATE_SUSPENDED)
59
- do_reconfigure = !n->target_pending;
60
+ do_reconfigure |= !was_target_pending;
61
}
62
- if (do_reconfigure)
63
- reconfigure_driver(context, n);
64
-
65
/* we're setting the pending rate. This will become the new
66
* current rate in the next iteration of the graph. */
67
n->target_rate = SPA_FRACTION(1, target_rate);
68
- n->target_pending = true;
69
n->forced_rate = force_rate;
70
+ n->target_pending = true;
71
current_rate = target_rate;
72
- /* we might be suspended now and the links need to be prepared again */
73
- if (do_reconfigure)
74
- goto again;
75
}
76
77
if (node_rate_quantum != 0 && current_rate != node_rate_quantum) {
78
79
node_max_quantum = tmp;
80
}
81
82
- quantum = node_def_quantum;
83
- if (latency.denom != 0)
84
- quantum = (latency.num * current_rate / latency.denom);
85
- quantum = SPA_CLAMP(quantum, node_min_quantum, node_max_quantum);
86
- quantum = SPA_MIN(quantum, lim_quantum);
87
-
88
- if (settings->clock_power_of_two_quantum)
89
- quantum = flp2(quantum);
90
+ current_quantum = n->target_quantum;
91
+ if (!restore_quantum &&
92
+ (lock_quantum || n->reconfigure || !running ||
93
+ (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE))))
94
+ target_quantum = current_quantum;
95
+ else {
96
+ target_quantum = node_def_quantum;
97
+ if (latency.denom != 0)
98
+ target_quantum = (latency.num * current_rate / latency.denom);
99
+ target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum);
100
+ target_quantum = SPA_MIN(target_quantum, lim_quantum);
101
+
102
+ if (settings->clock_power_of_two_quantum)
103
+ target_quantum = flp2(target_quantum);
104
+ }
105
106
- if (running && quantum != n->target_quantum && !lock_quantum) {
107
+ if (target_quantum != current_quantum) {
108
pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u",
109
n->name, n->info.id,
110
n->target_quantum,
111
- quantum);
112
+ target_quantum);
113
/* this is the new pending quantum */
114
- n->target_quantum = quantum;
115
+ n->target_quantum = target_quantum;
116
+ n->forced_quantum = force_quantum;
117
n->target_pending = true;
118
+
119
+ if (force_quantum)
120
+ do_reconfigure |= !was_target_pending;
121
}
122
123
if (n->target_pending) {
124
+ if (do_reconfigure) {
125
+ reconfigure_driver(context, n);
126
+ /* we might be suspended now and the links need to be prepared again */
127
+ goto again;
128
+ }
129
/* we have a pending change. We place the new values in the
130
* pending fields so that they are picked up by the driver in
131
* the next cycle */
132
133
n->target_rate = n->rt.position->clock.target_rate;
134
}
135
136
- pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u '%s'",
137
- context, n, running, n->runnable, quantum, n->name);
138
+ pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u rate:%u (%"PRIu64"/%u)'%s'",
139
+ context, n, running, n->runnable, target_quantum, target_rate,
140
+ n->rt.position->clock.target_duration,
141
+ n->rt.position->clock.target_rate.denom, n->name);
142
143
/* first change the node states of the followers to the new target */
144
spa_list_for_each(s, &n->follower_list, follower_link) {
145
pipewire-0.3.80.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-link.c
Changed
18
1
2
void pw_impl_link_destroy(struct pw_impl_link *link)
3
{
4
struct impl *impl = SPA_CONTAINER_OF(link, struct impl, this);
5
+ bool was_prepared = link->prepared;
6
7
pw_log_debug("%p: destroy", impl);
8
pw_log_info("(%s) destroy", link->name);
9
10
pw_global_destroy(link->global);
11
}
12
13
- if (link->prepared)
14
+ if (was_prepared)
15
pw_context_recalc_graph(link->context, "link destroy");
16
17
pw_log_debug("%p: free", impl);
18
pipewire-0.3.80.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-node.c
Changed
42
1
2
#include <unistd.h>
3
#include <errno.h>
4
#include <time.h>
5
+#include <malloc.h>
6
7
#include <spa/support/system.h>
8
#include <spa/pod/parser.h>
9
10
11
this->target_rate = SPA_FRACTION(1, rate);
12
this->target_quantum = quantum;
13
+ this->elapsed = 0;
14
15
pos->clock.rate = pos->clock.target_rate = this->target_rate;
16
pos->clock.duration = pos->clock.target_duration = this->target_quantum;
17
18
if (all_ready)
19
a->position.state = SPA_IO_POSITION_STATE_RUNNING;
20
}
21
- if (SPA_LIKELY(a->position.state != SPA_IO_POSITION_STATE_RUNNING))
22
- a->position.offset += a->position.clock.duration;
23
+ if (SPA_LIKELY(a->position.state == SPA_IO_POSITION_STATE_RUNNING))
24
+ node->elapsed += a->position.clock.duration;
25
+
26
+ a->position.offset = a->position.clock.position - node->elapsed;
27
}
28
29
/* Called from the data-loop and it is the starting point for driver nodes.
30
31
32
spa_system_close(node->data_system, node->source.fd);
33
free(impl);
34
+
35
+#ifdef HAVE_MALLOC_TRIM
36
+ int res = malloc_trim(0);
37
+ pw_log_debug("malloc_trim(): %d", res);
38
+#endif
39
}
40
41
SPA_EXPORT
42
pipewire-0.3.80.tar.gz/src/pipewire/mem.c -> pipewire-0.3.81.tar.gz/src/pipewire/mem.c
Changed
20
1
2
PW_LOG_TOPIC_EXTERN(log_mem);
3
#define PW_LOG_TOPIC_DEFAULT log_mem
4
5
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(HAVE_MEMFD_CREATE)
6
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__) \
7
+ && !defined(HAVE_MEMFD_CREATE)
8
/*
9
* No glibc wrappers exist for memfd_create(2), so provide our own.
10
*
11
12
#define HAVE_MEMFD_CREATE 1
13
#endif
14
15
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
16
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
17
#define MAP_LOCKED 0
18
#endif
19
20
pipewire-0.3.80.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.81.tar.gz/src/pipewire/pipewire.c
Changed
28
1
2
#include <unistd.h>
3
#include <limits.h>
4
#include <stdio.h>
5
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
6
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__)
7
#include <sys/prctl.h>
8
#endif
9
#include <pwd.h>
10
11
static char namePATH_MAX;
12
13
spa_memzero(name, sizeof(name));
14
-#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__)
15
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__) || defined(__GNU__)
16
{
17
if (readlink("/proc/self/exe", name, sizeof(name)-1) > 0) {
18
prgname = strrchr(name, '/') + 1;
19
20
}
21
}
22
#endif
23
-#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
24
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__)
25
{
26
if (prctl(PR_GET_NAME, (unsigned long) name, 0, 0, 0) == 0) {
27
prgname = name;
28
pipewire-0.3.80.tar.gz/src/pipewire/private.h -> pipewire-0.3.81.tar.gz/src/pipewire/private.h
Changed
26
1
2
#include <spa/utils/result.h>
3
#include <spa/utils/type-info.h>
4
5
-#if defined(__FreeBSD__) || defined(__MidnightBSD__)
6
+#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__)
7
struct ucred {
8
};
9
#endif
10
11
unsigned int suspend_on_idle:1;
12
unsigned int reconfigure:1;
13
unsigned int forced_rate:1;
14
+ unsigned int forced_quantum:1;
15
unsigned int trigger:1; /**< has the TRIGGER property and needs an extra
16
* trigger to start processing. */
17
unsigned int can_suspend:1;
18
19
uint64_t target_quantum;
20
21
uint64_t driver_start;
22
+ uint64_t elapsed; /* elapsed time in playing */
23
24
void *user_data; /**< extra user data */
25
};
26
pipewire-0.3.80.tar.gz/src/pipewire/stream.c -> pipewire-0.3.81.tar.gz/src/pipewire/stream.c
Changed
35
1
2
unsigned int driving:1;
3
unsigned int using_trigger:1;
4
unsigned int trigger:1;
5
+ unsigned int early_process:1;
6
int in_set_param;
7
int in_emit_param_changed;
8
};
9
10
* rate matching node (audioconvert) has been scheduled to
11
* update the values. */
12
ask_more = !impl->process_rt && impl->rate_match == NULL &&
13
- queue_is_empty(impl, &impl->queued) &&
14
+ (impl->early_process || queue_is_empty(impl, &impl->queued)) &&
15
!queue_is_empty(impl, &impl->dequeued);
16
pw_log_trace_fp("%p: pop %d %p ask_more:%u %p", stream, b->id, io,
17
ask_more, impl->rate_match);
18
19
}
20
} else {
21
ask_more = !impl->process_rt &&
22
- queue_is_empty(impl, &impl->queued) &&
23
+ (impl->early_process || queue_is_empty(impl, &impl->queued)) &&
24
!queue_is_empty(impl, &impl->dequeued);
25
}
26
27
28
impl->node_methods.process = impl_node_process_output;
29
30
impl->process_rt = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_RT_PROCESS);
31
+ impl->early_process = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_EARLY_PROCESS);
32
33
impl->impl_node.iface = SPA_INTERFACE_INIT(
34
SPA_TYPE_INTERFACE_Node,
35
pipewire-0.3.80.tar.gz/src/pipewire/stream.h -> pipewire-0.3.81.tar.gz/src/pipewire/stream.h
Changed
13
1
2
* does a trigger_process() that will then
3
* dequeue/queue a buffer from another process()
4
* function. since 0.3.73 */
5
+ PW_STREAM_FLAG_EARLY_PROCESS = (1 << 11), /**< Call process as soon as there is a buffer
6
+ * to dequeue. This is only relevant for
7
+ * playback and when not using RT_PROCESS. It
8
+ * can be used to keep the maximum number of
9
+ * buffers queued. Since 0.3.81 */
10
};
11
12
/** Create a new unconneced \ref pw_stream
13
pipewire-0.3.80.tar.gz/src/pipewire/thread.c -> pipewire-0.3.81.tar.gz/src/pipewire/thread.c
Changed
11
1
2
}
3
#endif
4
#endif
5
+#if defined(__GNU__)
6
+int pthread_setname_np(pthread_t thread, const char *name) { return 0; }
7
+#endif
8
9
static struct spa_thread *impl_create(void *object,
10
const struct spa_dict *props,
11
pipewire-0.3.80.tar.gz/src/pipewire/utils.h -> pipewire-0.3.81.tar.gz/src/pipewire/utils.h
Changed
9
1
2
#ifndef _POSIX_C_SOURCE
3
# include <sys/mount.h>
4
#endif
5
+#include <errno.h>
6
7
#ifndef ENODATA
8
#define ENODATA 9919
9
pipewire-0.3.81.tar.gz/src/tools/dfffile.c
Added
201
1
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <errno.h>
7
+#include <sys/mman.h>
8
+#include <sys/stat.h>
9
+#include <unistd.h>
10
+#include <fcntl.h>
11
+#include <math.h>
12
+
13
+#include <spa/utils/string.h>
14
+#include <spa/debug/mem.h>
15
+
16
+#include "dfffile.h"
17
+
18
+struct dff_file {
19
+ uint8_t *data;
20
+ size_t size;
21
+
22
+ int mode;
23
+ int fd;
24
+
25
+ struct dff_file_info info;
26
+
27
+ uint8_t *p;
28
+ size_t offset;
29
+};
30
+
31
+struct dff_chunk {
32
+ uint32_t id;
33
+ uint64_t size;
34
+ void *data;
35
+};
36
+
37
+#define FOURCC(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
38
+
39
+static inline uint16_t parse_be16(const uint8_t *in)
40
+{
41
+ return (in0 << 8) | in1;
42
+}
43
+static inline uint32_t parse_be32(const uint8_t *in)
44
+{
45
+ return FOURCC(in0, in1, in2, in3);
46
+}
47
+
48
+static inline uint64_t parse_be64(const uint8_t *in)
49
+{
50
+ uint64_t res = in7;
51
+ res |= ((uint64_t)in6) << 8;
52
+ res |= ((uint64_t)in5) << 16;
53
+ res |= ((uint64_t)in4) << 24;
54
+ res |= ((uint64_t)in3) << 32;
55
+ res |= ((uint64_t)in2) << 40;
56
+ res |= ((uint64_t)in1) << 48;
57
+ res |= ((uint64_t)in0) << 56;
58
+ return res;
59
+}
60
+
61
+static inline int f_avail(struct dff_file *f)
62
+{
63
+ if (f->p < f->data + f->size)
64
+ return f->size + f->data - f->p;
65
+ return 0;
66
+}
67
+
68
+static int read_chunk(struct dff_file *f, struct dff_chunk *c)
69
+{
70
+ if (f_avail(f) < 12)
71
+ return -ENOSPC;
72
+
73
+ c->id = parse_be32(f->p); /* id of this chunk */
74
+ c->size = parse_be64(f->p + 4); /* size of this chunk */
75
+ f->p += 12;
76
+ c->data = f->p;
77
+ return 0;
78
+}
79
+
80
+static int skip_chunk(struct dff_file *f, const struct dff_chunk *c)
81
+{
82
+ f->p = SPA_PTROFF(c->data, c->size, uint8_t);
83
+ return 0;
84
+}
85
+
86
+static int read_PROP(struct dff_file *f, struct dff_chunk *prop)
87
+{
88
+ struct dff_chunk c1;
89
+ int res;
90
+
91
+ if (f_avail(f) < 4 ||
92
+ memcmp(prop->data, "SND ", 4) != 0)
93
+ return -EINVAL;
94
+ f->p += 4;
95
+
96
+ while (f->p < SPA_PTROFF(prop->data, prop->size, uint8_t)) {
97
+ if ((res = read_chunk(f, &c0)) < 0)
98
+ return res;
99
+
100
+ switch (c0.id) {
101
+ case FOURCC('F', 'S', ' ', ' '):
102
+ f->info.rate = parse_be32(f->p);
103
+ break;
104
+ case FOURCC('C', 'H', 'N', 'L'):
105
+ f->info.channels = parse_be16(f->p);
106
+ switch (f->info.channels) {
107
+ case 2:
108
+ f->info.channel_type = 2;
109
+ break;
110
+ case 5:
111
+ f->info.channel_type = 6;
112
+ break;
113
+ case 6:
114
+ f->info.channel_type = 7;
115
+ break;
116
+ }
117
+ break;
118
+ case FOURCC('C', 'M', 'P', 'R'):
119
+ {
120
+ uint32_t cmpr = parse_be32(f->p);
121
+ if (cmpr != FOURCC('D', 'S', 'D', ' '))
122
+ return -ENOTSUP;
123
+ break;
124
+ }
125
+ case FOURCC('A', 'B', 'S', 'S'):
126
+ break;
127
+ case FOURCC('L', 'S', 'C', 'O'):
128
+ break;
129
+ default:
130
+ break;
131
+ }
132
+ skip_chunk(f, &c0);
133
+ }
134
+ return 0;
135
+}
136
+
137
+static int read_FRM8(struct dff_file *f)
138
+{
139
+ struct dff_chunk c2;
140
+ int res;
141
+ bool found_dsd = false;
142
+
143
+ if ((res = read_chunk(f, &c0)) < 0)
144
+ return res;
145
+ if (c0.id != FOURCC('F','R','M','8'))
146
+ return -EINVAL;
147
+ if (f_avail(f) < 4 ||
148
+ memcmp(c0.data, "DSD ", 4) != 0)
149
+ return -EINVAL;
150
+ f->p += 4;
151
+
152
+ while (true) {
153
+ if ((res = read_chunk(f, &c1)) < 0)
154
+ return res;
155
+
156
+ switch (c1.id) {
157
+ case FOURCC('F', 'V', 'E', 'R'):
158
+ break;
159
+ case FOURCC('P', 'R', 'O', 'P'):
160
+ read_PROP(f, &c1);
161
+ break;
162
+ case FOURCC('D', 'S', 'D', ' '):
163
+ {
164
+ f->info.length = c1.size;
165
+ f->info.samples = c1.size / f->info.channels;
166
+ f->info.lsb = 0;
167
+ f->info.blocksize = 1;
168
+ found_dsd = true;
169
+ break;
170
+ }
171
+ default:
172
+ break;
173
+ }
174
+ if (found_dsd)
175
+ break;
176
+
177
+ skip_chunk(f, &c1);
178
+ }
179
+ return 0;
180
+}
181
+
182
+static int open_read(struct dff_file *f, const char *filename, struct dff_file_info *info)
183
+{
184
+ int res;
185
+ struct stat st;
186
+
187
+ if ((f->fd = open(filename, O_RDONLY)) < 0) {
188
+ res = -errno;
189
+ goto exit;
190
+ }
191
+ if (fstat(f->fd, &st) < 0) {
192
+ res = -errno;
193
+ goto exit_close;
194
+ }
195
+ f->size = st.st_size;
196
+
197
+ f->data = mmap(NULL, f->size, PROT_READ, MAP_SHARED, f->fd, 0);
198
+ if (f->data == MAP_FAILED) {
199
+ res = -errno;
200
+ goto exit_close;
201
pipewire-0.3.81.tar.gz/src/tools/dfffile.h
Added
33
1
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <stdio.h>
7
+
8
+#include <spa/utils/defs.h>
9
+
10
+struct dff_file;
11
+
12
+struct dff_file_info {
13
+ uint32_t channel_type;
14
+ uint32_t channels;
15
+ uint32_t rate;
16
+ bool lsb;
17
+ uint64_t samples;
18
+ uint64_t length;
19
+ uint32_t blocksize;
20
+};
21
+
22
+struct dff_layout {
23
+ int32_t interleave;
24
+ uint32_t channels;
25
+ bool lsb;
26
+};
27
+
28
+struct dff_file * dff_file_open(const char *filename, const char *mode, struct dff_file_info *info);
29
+
30
+ssize_t dff_file_read(struct dff_file *f, void *data, size_t samples, const struct dff_layout *layout);
31
+
32
+int dff_file_close(struct dff_file *f);
33
pipewire-0.3.80.tar.gz/src/tools/meson.build -> pipewire-0.3.81.tar.gz/src/tools/meson.build
Changed
9
1
2
pwcat_sources =
3
'pw-cat.c',
4
'midifile.c',
5
+ 'dfffile.c',
6
'dsffile.c',
7
8
9
pipewire-0.3.80.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cat.c
Changed
130
1
2
#endif
3
4
#include "midifile.h"
5
+#include "dfffile.h"
6
#include "dsffile.h"
7
8
#define DEFAULT_MEDIA_TYPE "Audio"
9
10
struct dsf_file_info info;
11
struct dsf_layout layout;
12
} dsf;
13
+ struct {
14
+ struct dff_file *file;
15
+ struct dff_file_info info;
16
+ struct dff_layout layout;
17
+ } dff;
18
19
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
20
struct {
21
22
data->dsf.layout.channels = info.info.dsd.channels;
23
data->dsf.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb;
24
25
+ data->dff.layout.interleave = info.info.dsd.interleave,
26
+ data->dff.layout.channels = info.info.dsd.channels;
27
+ data->dff.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb;
28
+
29
data->stride = data->dsf.layout.channels * SPA_ABS(data->dsf.layout.interleave);
30
31
if (data->verbose) {
32
33
return dsf_file_read(d->dsf.file, src, n_frames, &d->dsf.layout);
34
}
35
36
-static int setup_dsffile(struct data *data)
37
+static int dff_play(struct data *d, void *src, unsigned int n_frames, bool *null_frame)
38
+{
39
+ return dff_file_read(d->dff.file, src, n_frames, &d->dff.layout);
40
+}
41
+
42
+static int setup_dsdfile(struct data *data)
43
{
44
if (data->mode == mode_record)
45
return -ENOTSUP;
46
47
data->dsf.file = dsf_file_open(data->filename, "r", &data->dsf.info);
48
if (data->dsf.file == NULL) {
49
- fprintf(stderr, "dsffile: can't read dsf file '%s': %m\n", data->filename);
50
- return -errno;
51
+ data->dff.file = dff_file_open(data->filename, "r", &data->dff.info);
52
+ if (data->dff.file == NULL) {
53
+ fprintf(stderr, "dsdfile: can't read dsd file '%s': %m\n", data->filename);
54
+ return -errno;
55
+ }
56
}
57
58
- if (data->verbose)
59
- printf("dsffile: opened file \"%s\" channels:%d rate:%d samples:%"PRIu64" bitorder:%s\n",
60
+ if (data->dsf.file != NULL) {
61
+ if (data->verbose)
62
+ printf("dsffile: opened file \"%s\" channels:%d rate:%d "
63
+ "samples:%"PRIu64" bitorder:%s\n",
64
data->filename,
65
data->dsf.info.channels, data->dsf.info.rate,
66
data->dsf.info.samples,
67
data->dsf.info.lsb ? "lsb" : "msb");
68
69
- data->fill = dsf_play;
70
+ data->fill = dsf_play;
71
+ } else {
72
+ if (data->verbose)
73
+ printf("dfffile: opened file \"%s\" channels:%d rate:%d "
74
+ "samples:%"PRIu64" bitorder:%s\n",
75
+ data->filename,
76
+ data->dff.info.channels, data->dff.info.rate,
77
+ data->dff.info.samples,
78
+ data->dff.info.lsb ? "lsb" : "msb");
79
80
+ data->fill = dff_play;
81
+ }
82
return 0;
83
}
84
85
86
ret = setup_midifile(&data);
87
break;
88
case TYPE_DSD:
89
- ret = setup_dsffile(&data);
90
+ ret = setup_dsdfile(&data);
91
break;
92
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
93
case TYPE_ENCODED:
94
95
case TYPE_DSD:
96
{
97
struct spa_audio_info_dsd info;
98
+ uint32_t channel_type;
99
100
spa_zero(info);
101
- info.channels = data.dsf.info.channels;
102
- info.rate = data.dsf.info.rate / 8;
103
+ if (data.dsf.file != NULL) {
104
+ info.channels = data.dsf.info.channels;
105
+ info.rate = data.dsf.info.rate / 8;
106
+ channel_type = data.dsf.info.channel_type;
107
+ } else {
108
+ info.channels = data.dff.info.channels;
109
+ info.rate = data.dff.info.rate / 8;
110
+ channel_type = data.dff.info.channel_type;
111
+ }
112
113
SPA_FOR_EACH_ELEMENT_VAR(dsd_layouts, i) {
114
- if (i->type != data.dsf.info.channel_type)
115
+ if (i->type != channel_type)
116
continue;
117
info.channels = i->info.n_channels;
118
memcpy(info.position, i->info.position,
119
120
sf_close(data.file);
121
if (data.midi.file)
122
midi_file_close(data.midi.file);
123
+ if (data.dsf.file)
124
+ dsf_file_close(data.dsf.file);
125
+ if (data.dff.file)
126
+ dff_file_close(data.dff.file);
127
#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION
128
if (data.encoded.packet)
129
av_packet_free(&data.encoded.packet);
130
pipewire-0.3.80.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cli.c
Changed
201
1
2
bool ret;
3
4
global = calloc(1, sizeof(struct global));
5
+ if (global == NULL) {
6
+ fprintf(stderr, "Allocation failed: %m");
7
+ return;
8
+ }
9
global->rd = rd;
10
global->id = id;
11
global->permissions = permissions;
12
13
struct pw_core_info *info = pd->info;
14
15
info_global(pd);
16
+ if (info == NULL)
17
+ return;
18
printf("\tcookie: %u\n", info->cookie);
19
printf("\tuser-name: \"%s\"\n", info->user_name);
20
printf("\thost-name: \"%s\"\n", info->host_name);
21
22
struct pw_module_info *info = pd->info;
23
24
info_global(pd);
25
+ if (info == NULL)
26
+ return;
27
printf("\tname: \"%s\"\n", info->name);
28
printf("\tfilename: \"%s\"\n", info->filename);
29
printf("\targs: \"%s\"\n", info->args);
30
31
struct pw_node_info *info = pd->info;
32
33
info_global(pd);
34
+ if (info == NULL)
35
+ return;
36
printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS),
37
info->n_input_ports, info->max_input_ports);
38
printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS),
39
40
struct pw_port_info *info = pd->info;
41
42
info_global(pd);
43
+ if (info == NULL)
44
+ return;
45
printf("\tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
46
print_properties(info->props, MARK_CHANGE(PW_PORT_CHANGE_MASK_PROPS), true);
47
print_params(info->params, info->n_params, MARK_CHANGE(PW_PORT_CHANGE_MASK_PARAMS), true);
48
49
struct pw_factory_info *info = pd->info;
50
51
info_global(pd);
52
+ if (info == NULL)
53
+ return;
54
printf("\tname: \"%s\"\n", info->name);
55
printf("\tobject-type: %s/%d\n", info->type, info->version);
56
print_properties(info->props, MARK_CHANGE(PW_FACTORY_CHANGE_MASK_PROPS), true);
57
58
struct pw_client_info *info = pd->info;
59
60
info_global(pd);
61
+ if (info == NULL)
62
+ return;
63
print_properties(info->props, MARK_CHANGE(PW_CLIENT_CHANGE_MASK_PROPS), true);
64
info->change_mask = 0;
65
}
66
67
struct pw_link_info *info = pd->info;
68
69
info_global(pd);
70
+ if (info == NULL)
71
+ return;
72
printf("\toutput-node-id: %u\n", info->output_node_id);
73
printf("\toutput-port-id: %u\n", info->output_port_id);
74
printf("\tinput-node-id: %u\n", info->input_node_id);
75
76
struct pw_device_info *info = pd->info;
77
78
info_global(pd);
79
+ if (info == NULL)
80
+ return;
81
print_properties(info->props, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PROPS), true);
82
print_params(info->params, info->n_params, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PARAMS), true);
83
info->change_mask = 0;
84
85
struct pw_session_info *info = pd->info;
86
87
info_global(pd);
88
+ if (info == NULL)
89
+ return;
90
print_properties(info->props, MARK_CHANGE(0), true);
91
print_params(info->params, info->n_params, MARK_CHANGE(1), true);
92
info->change_mask = 0;
93
94
const char *direction;
95
96
info_global(pd);
97
+ if (info == NULL)
98
+ return;
99
printf("\tname: %s\n", info->name);
100
printf("\tmedia-class: %s\n", info->media_class);
101
switch(info->direction) {
102
103
struct pw_endpoint_stream_info *info = pd->info;
104
105
info_global(pd);
106
+ if (info == NULL)
107
+ return;
108
printf("\tid: %u\n", info->id);
109
printf("\tendpoint-id: %u\n", info->endpoint_id);
110
printf("\tname: %s\n", info->name);
111
112
struct remote_data *rd = pd->rd;
113
struct pw_session_info *info = pd->info;
114
115
- if (!info) {
116
+ if (info == NULL)
117
info = pd->info = calloc(1, sizeof(*info));
118
+ if (info != NULL) {
119
info->id = update->id;
120
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
121
+ info->n_params = update->n_params;
122
+ free(info->params);
123
+ info->params = malloc(info->n_params * sizeof(struct spa_param_info));
124
+ memcpy(info->params, update->params,
125
+ info->n_params * sizeof(struct spa_param_info));
126
+ }
127
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
128
+ pw_properties_free ((struct pw_properties *)info->props);
129
+ info->props =
130
+ (struct spa_dict *) pw_properties_new_dict (update->props);
131
+ }
132
}
133
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
134
- info->n_params = update->n_params;
135
- free(info->params);
136
- info->params = malloc(info->n_params * sizeof(struct spa_param_info));
137
- memcpy(info->params, update->params,
138
- info->n_params * sizeof(struct spa_param_info));
139
- }
140
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
141
- pw_properties_free ((struct pw_properties *)info->props);
142
- info->props =
143
- (struct spa_dict *) pw_properties_new_dict (update->props);
144
- }
145
-
146
if (pd->global == NULL)
147
- pd->global = pw_map_lookup(&rd->globals, info->id);
148
+ pd->global = pw_map_lookup(&rd->globals, update->id);
149
if (pd->global && pd->global->info_pending) {
150
info_session(pd);
151
pd->global->info_pending = false;
152
153
struct remote_data *rd = pd->rd;
154
struct pw_endpoint_info *info = pd->info;
155
156
- if (!info) {
157
+ if (info == NULL)
158
info = pd->info = calloc(1, sizeof(*info));
159
+ if (info != NULL) {
160
info->id = update->id;
161
info->name = update->name ? strdup(update->name) : NULL;
162
info->media_class = update->media_class ? strdup(update->media_class) : NULL;
163
info->direction = update->direction;
164
info->flags = update->flags;
165
- }
166
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS)
167
- info->n_streams = update->n_streams;
168
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION)
169
- info->session_id = update->session_id;
170
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
171
- info->n_params = update->n_params;
172
- free(info->params);
173
- info->params = malloc(info->n_params * sizeof(struct spa_param_info));
174
- memcpy(info->params, update->params,
175
- info->n_params * sizeof(struct spa_param_info));
176
- }
177
- if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
178
- pw_properties_free ((struct pw_properties *)info->props);
179
- info->props =
180
- (struct spa_dict *) pw_properties_new_dict (update->props);
181
- }
182
183
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS)
184
+ info->n_streams = update->n_streams;
185
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION)
186
+ info->session_id = update->session_id;
187
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
188
+ info->n_params = update->n_params;
189
+ free(info->params);
190
+ info->params = malloc(info->n_params * sizeof(struct spa_param_info));
191
+ memcpy(info->params, update->params,
192
+ info->n_params * sizeof(struct spa_param_info));
193
+ }
194
+ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
195
+ pw_properties_free ((struct pw_properties *)info->props);
196
+ info->props =
197
+ (struct spa_dict *) pw_properties_new_dict (update->props);
198
+ }
199
+ }
200
if (pd->global == NULL)
201
pipewire-0.3.80.tar.gz/src/tools/pw-link.c -> pipewire-0.3.81.tar.gz/src/tools/pw-link.c
Changed
12
1
2
static void print_port(struct data *data, const char *prefix, struct object *n,
3
struct object *p, bool verbose)
4
{
5
- char buffer1024, id64 = "", *prefix2 = "";
6
+ char buffer1024, id64 = "";
7
+ const char *prefix2 = "";
8
+
9
if (data->opt_id) {
10
snprintf(id, sizeof(id), "%4d ", p->id);
11
prefix2 = " ";
12
pipewire-0.3.80.tar.gz/test/pwtest.c -> pipewire-0.3.81.tar.gz/test/pwtest.c
Changed
10
1
2
time_t t = time(NULL);
3
struct tm *tm = localtime(&t);
4
char *dir;
5
- char *tmpdir = getenv("TMPDIR");
6
+ const char *tmpdir = getenv("TMPDIR");
7
char pathPATH_MAX;
8
FILE *fp;
9
10
pipewire-0.3.80.tar.gz/test/test-logger.c -> pipewire-0.3.81.tar.gz/test/test-logger.c
Changed
19
1
2
enum spa_log_level level = pwtest_get_iteration(current_test);
3
enum spa_log_level default_level = pw_log_level;
4
struct spa_log *default_logger = pw_log_get();
5
- char *lvl = NULL;
6
+ const char *lvl = NULL;
7
char *oldenv = getenv("PIPEWIRE_DEBUG");
8
9
if (oldenv)
10
11
struct spa_log *default_logger = pw_log_get();
12
char *oldenv = getenv("PIPEWIRE_DEBUG");
13
char lvlstr32;
14
- char *lvl = "X";
15
+ const char *lvl = "X";
16
17
if (oldenv)
18
oldenv = strdup(oldenv);
19
pipewire-0.3.80.tar.gz/test/test-spa-json.c -> pipewire-0.3.81.tar.gz/test/test-spa-json.c
Changed
29
1
2
return PWTEST_PASS;
3
}
4
5
-static void test_array(char *str, char **vals)
6
+static void test_array(const char *str, const char * const vals)
7
{
8
struct spa_json it2;
9
char val256;
10
11
12
PWTEST(json_array)
13
{
14
- test_array("FL,FR", (char *){ "FL", "FR", NULL });
15
- test_array(" FL , FR ", (char *){ "FL", "FR", NULL });
16
- test_array(" FL , FR ", (char *){ "FL", "FR", NULL });
17
- test_array("FL FR", (char *){ "FL", "FR", NULL });
18
- test_array("FL FR", (char *){ "FL", "FR", NULL });
19
- test_array(" FL FR ", (char *){ "FL", "FR", NULL });
20
+ test_array("FL,FR", (const char *){ "FL", "FR", NULL });
21
+ test_array(" FL , FR ", (const char *){ "FL", "FR", NULL });
22
+ test_array(" FL , FR ", (const char *){ "FL", "FR", NULL });
23
+ test_array("FL FR", (const char *){ "FL", "FR", NULL });
24
+ test_array("FL FR", (const char *){ "FL", "FR", NULL });
25
+ test_array(" FL FR ", (const char *){ "FL", "FR", NULL });
26
27
return PWTEST_PASS;
28
}
29