Overview
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Thu Mar 3 11:50:58 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.48
6
+
7
+-------------------------------------------------------------------
8
Fri Feb 18 14:59:46 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
10
- Update to version 0.3.47
11
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.47
6
+Version: 0.3.48
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.47.tar.gz/NEWS -> pipewire-0.3.48.tar.gz/NEWS
Changed
92
1
2
+# PipeWire 0.3.48 (2022-03-03)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+ - Fix IEC958 passthrough again.
9
+ - Fix pulse-server crashes when playing a sample.
10
+ - Support for more a more advanced upmixing algorithm.
11
+ - filter-chain now supports arbitrary many ports.
12
+ - Fix multichannel support in WINE. (with new WirePlumber).
13
+ - Many bugfixes and improvements.
14
+
15
+
16
+## PipeWire
17
+ - The work queue is now created in the context so we can fail early and
18
+ avoid further error checking in various places.
19
+ - Fix a potential use after free with threaded loops.
20
+ - The protocol now has a message footer. This is used to pass around
21
+ global state such as the last registered object serial number. This can
22
+ be used to detect when a client tries to bind to old (but reused)
23
+ object ids. This avoids some races in the session manager but also
24
+ when binding objects.
25
+ - The zero-denormals CPU flag is now not touched anymore unless explicitly
26
+ selected by the user. Denormals are avoided in filter-chain now in
27
+ software. If the zero-denormals are now only configured in the data
28
+ thread. This should fix issues with luajit. (#2160)
29
+ - Configuration parsing will not actually fail on errors.
30
+ - pw-top now correctly clips unicode characters.
31
+ - Many places now use a dynamic POD builder to support arbitrary large
32
+ property sets.
33
+ - pw-stream now support PropInfo parameters so that they can announce
34
+ custom properties.
35
+ - Serial number are now also set on metadata and session-manager objects.
36
+
37
+## SPA
38
+ - audioadapter is now smarter when trying to fixate the format. It will
39
+ use the PortConfig format to fill in any wildcards. This results in
40
+ the least amount of conversions when the stream can handle it. It also
41
+ is part of a fix (also requires a session manager fix) for WINE
42
+ multichannel support. (#876).
43
+ - Fix 5.1 to 2 channels mixing. It was using the volume of the stereo
44
+ pair on all channels.
45
+ - Fix some weird volume issues when a source is capturing and
46
+ channelmixing.
47
+ - Add stereo to 7.1 upmixing.
48
+ - The channelmix parameters can be changed at runtime now.
49
+ - Many improvements to the upmixing algorithms. Rear channels are now
50
+ constructed from the ambient sound and can have delay and phase shift
51
+ applied to them to improve spacialization. The stereo channels can
52
+ be filtered so that the dialog is more concentrated in the center
53
+ channel. (#861)
54
+
55
+## modules
56
+ - Module X11 bell received cleanups and improvements.
57
+ - The module now has a private method to schedule unload later. This
58
+ simplifies cleanup in many modules.
59
+ - module-filter-chain now handles arbitrary many ports and control
60
+ ports. (#2179)
61
+ - Fix a bug in RAOP where it was reading from the wrong port. (#2183)
62
+
63
+## pulse-server
64
+ - Nodes with the DONT_MOVE property should fail with -EINVAL when
65
+ they are moved.
66
+ - Fix a segfault when playing a sample. (#2151)
67
+ - The _FIX flags in pulse-server also now ignore the configured
68
+ sample format, just like pulseaudio does. (#876)
69
+ - Fix IEC958 passthrough again. It got accidentally broken since
70
+ 0.3.45 with a fix for another issue. (#1442)
71
+ - Fix module-null-sink device.description. (#2166)
72
+
73
+## Bluetooth
74
+ - Don't try to connect HSP/HFP when no backend is available.
75
+
76
+
77
+Older versions:
78
+
79
+
80
# PipeWire 0.3.47 (2022-02-18)
81
82
This is a bugfix release that is API and ABI compatible with previous
83
84
proxy. This might access invalid memory and cause infinite
85
loops in older wireplumber.
86
87
-Older versions:
88
-
89
# PipeWire 0.3.46 (2022-02-17)
90
91
This is a bugfix release that is API and ABI compatible with previous
92
pipewire-0.3.47.tar.gz/meson.build -> pipewire-0.3.48.tar.gz/meson.build
Changed
60
1
2
project('pipewire', ['c' ],
3
- version : '0.3.47',
4
+ version : '0.3.48',
5
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
6
meson_version : '>= 0.59.0',
7
default_options : [ 'warning_level=3',
8
9
cdata.set(h.get(1), cc.has_header(h.get(0)))
10
endforeach
11
12
-check_functions = [
13
- ['gettid', '#include <unistd.h>', ['-D_GNU_SOURCE']],
14
- ['memfd_create', '#include <sys/mman.h>', ['-D_GNU_SOURCE']],
15
- ['getrandom', '#include <stddef.h>\n#include <sys/random.h>', ['-D_GNU_SOURCE']],
16
- ['sigabbrev_np', '#include <string.h>', ['-D_GNU_SOURCE']],
17
-]
18
-
19
-foreach f : check_functions
20
- cdata.set('HAVE_' + f.get(0).to_upper(),
21
- cc.has_function(f.get(0), prefix: f.get(1), args: f.get(2)))
22
-endforeach
23
-
24
cdata.set('HAVE_PIDFD_OPEN',
25
cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '')
26
27
28
summary({'X11 (x11-bell)': x11_dep.found()}, bool_yn: true,
29
section: 'Misc dependencies')
30
31
+xfixes_dep = dependency('xfixes', required : get_option('x11-xfixes'), version: '>= 6')
32
+cdata.set('HAVE_XFIXES_6', xfixes_dep.found())
33
+
34
canberra_dep = dependency('libcanberra', required : get_option('libcanberra'))
35
summary({'libcanberra (x11-bell)': canberra_dep.found()}, bool_yn: true,
36
section: 'Misc dependencies')
37
38
summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true)
39
cdata.set('HAVE_LILV', lilv_lib.found())
40
41
+check_functions = [
42
+ ['gettid', '#include <unistd.h>', ['-D_GNU_SOURCE'], []],
43
+ ['memfd_create', '#include <sys/mman.h>', ['-D_GNU_SOURCE'], []],
44
+ ['getrandom', '#include <stddef.h>\n#include <sys/random.h>', ['-D_GNU_SOURCE'], []],
45
+ ['sigabbrev_np', '#include <string.h>', ['-D_GNU_SOURCE'], []],
46
+ ['XSetIOErrorExitHandler', '#include <X11/Xlib.h>', [], [x11_dep]],
47
+]
48
+
49
+foreach f : check_functions
50
+ cdata.set('HAVE_' + f.get(0).to_upper(),
51
+ cc.has_function(f.get(0),
52
+ prefix: f.get(1),
53
+ args: f.get(2),
54
+ dependencies: f.get(3)))
55
+endforeach
56
+
57
installed_tests_metadir = pipewire_datadir / 'installed-tests' / pipewire_name
58
installed_tests_execdir = pipewire_libexecdir / 'installed-tests' / pipewire_name
59
installed_tests_enabled = get_option('installed_tests').allowed()
60
pipewire-0.3.47.tar.gz/meson_options.txt -> pipewire-0.3.48.tar.gz/meson_options.txt
Changed
12
1
2
description: 'Enable code that depends on X11',
3
type: 'feature',
4
value: 'auto')
5
+option('x11-xfixes',
6
+ description: 'Enable code that depends on XFixes',
7
+ type: 'feature',
8
+ value: 'auto')
9
option('libcanberra',
10
description: 'Enable code that depends on libcanberra',
11
type: 'feature',
12
pipewire-0.3.47.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.48.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
10
1
2
res = is_def2 - is_def1;
3
else if ((*o1)->port.priority != (*o2)->port.priority)
4
res = (*o2)->port.priority - (*o1)->port.priority;
5
- else if ((res = strcmp((*o1)->port.alias1, (*o2)->port.alias1) == 0)) {
6
+ else if ((res = strcmp((*o1)->port.alias1, (*o2)->port.alias1)) == 0) {
7
res = (*o1)->port.node_id - (*o2)->port.node_id;
8
if (res == 0)
9
res = (*o1)->port.system_id - (*o2)->port.system_id;
10
pipewire-0.3.48.tar.gz/spa/include/spa/pod/dynamic.h
Added
83
1
2
+/* Simple Plugin API
3
+ *
4
+ * Copyright © 2018 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef SPA_POD_DYNAMIC_H
27
+#define SPA_POD_DYNAMIC_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+#include <spa/pod/builder.h>
34
+
35
+struct spa_pod_dynamic_builder {
36
+ struct spa_pod_builder b;
37
+ void *data;
38
+ uint32_t extend;
39
+ uint32_t _padding;
40
+};
41
+
42
+static int spa_pod_dynamic_builder_overflow(void *data, uint32_t size)
43
+{
44
+ struct spa_pod_dynamic_builder *d = (struct spa_pod_dynamic_builder*)data;
45
+ int32_t old_size = d->b.size;
46
+ int32_t new_size = SPA_ROUND_UP_N(size, d->extend);
47
+ void *old_data = d->b.data;
48
+
49
+ if (old_data == d->data)
50
+ d->b.data = NULL;
51
+ if ((d->b.data = realloc(d->b.data, new_size)) == NULL)
52
+ return -errno;
53
+ if (old_data == d->data && d->b.data != old_data && old_size > 0)
54
+ memcpy(d->b.data, old_data, old_size);
55
+ d->b.size = new_size;
56
+ return 0;
57
+}
58
+
59
+static inline void spa_pod_dynamic_builder_init(struct spa_pod_dynamic_builder *builder,
60
+ void *data, uint32_t size, uint32_t extend)
61
+{
62
+ static const struct spa_pod_builder_callbacks spa_pod_dynamic_builder_callbacks = {
63
+ SPA_VERSION_POD_BUILDER_CALLBACKS,
64
+ .overflow = spa_pod_dynamic_builder_overflow
65
+ };
66
+ builder->b = SPA_POD_BUILDER_INIT(data, size);
67
+ spa_pod_builder_set_callbacks(&builder->b, &spa_pod_dynamic_builder_callbacks, builder);
68
+ builder->extend = extend;
69
+ builder->data = data;
70
+}
71
+
72
+static inline void spa_pod_dynamic_builder_clean(struct spa_pod_dynamic_builder *builder)
73
+{
74
+ if (builder->data != builder->b.data)
75
+ free(builder->b.data);
76
+}
77
+
78
+#ifdef __cplusplus
79
+} /* extern "C" */
80
+#endif
81
+
82
+#endif /* SPA_POD_DYNAMIC_H */
83
pipewire-0.3.47.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c -> pipewire-0.3.48.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c
Changed
21
1
2
int count = 0;
3
4
f = open_memstream(&ptr, &size);
5
+ if (f == NULL) {
6
+ pa_log("failed to open memstream: %m");
7
+ return -1;
8
+ }
9
10
if (p->output_mappings)
11
PA_IDXSET_FOREACH(m, p->output_mappings, idx) {
12
13
size_t size;
14
15
f = open_memstream(&ptr, &size);
16
+ if (f == NULL)
17
+ return;
18
19
pa_assert(db_fix->min_step <= db_fix->max_step);
20
nsteps = db_fix->max_step - db_fix->min_step + 1;
21
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
202
1
2
#include <spa/buffer/alloc.h>
3
#include <spa/pod/parser.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/param/param.h>
7
#include <spa/param/audio/format-utils.h>
8
#include <spa/param/latency-utils.h>
9
10
struct spa_hook follower_listener;
11
uint32_t follower_flags;
12
struct spa_audio_info follower_current_format;
13
+ struct spa_audio_info default_format;
14
15
struct spa_handle *hnd_convert;
16
struct spa_node *convert;
17
18
const struct spa_pod *filter)
19
{
20
struct impl *this = object;
21
- struct spa_pod_builder b = { 0 };
22
uint8_t buffer[4096];
23
+ struct spa_pod_dynamic_builder b;
24
struct spa_result_node_params result;
25
uint32_t count = 0;
26
int res;
27
28
29
spa_log_debug(this->log, "%p: %d id:%u", this, seq, id);
30
31
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
32
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
33
34
switch (id) {
35
case SPA_PARAM_EnumPortConfig:
36
37
res = spa_node_enum_params(this->convert, seq, id, start, num, filter);
38
return res;
39
case SPA_PARAM_PropInfo:
40
- if ((res = follower_enum_params(this,
41
- id, IDX_PropInfo, &result, filter, &b)) != 1)
42
- return res;
43
+ res = follower_enum_params(this,
44
+ id, IDX_PropInfo, &result, filter, &b.b);
45
break;
46
case SPA_PARAM_Props:
47
- if ((res = follower_enum_params(this,
48
- id, IDX_Props, &result, filter, &b)) != 1)
49
- return res;
50
+ res = follower_enum_params(this,
51
+ id, IDX_Props, &result, filter, &b.b);
52
break;
53
case SPA_PARAM_ProcessLatency:
54
- if ((res = follower_enum_params(this,
55
- id, IDX_ProcessLatency, &result, filter, &b)) != 1)
56
- return res;
57
+ res = follower_enum_params(this,
58
+ id, IDX_ProcessLatency, &result, filter, &b.b);
59
break;
60
case SPA_PARAM_EnumFormat:
61
case SPA_PARAM_Format:
62
case SPA_PARAM_Latency:
63
- if ((res = spa_node_port_enum_params_sync(this->follower,
64
+ res = spa_node_port_enum_params_sync(this->follower,
65
this->direction, 0,
66
- id, &result.next, filter, &result.param, &b)) != 1)
67
- return res;
68
+ id, &result.next, filter, &result.param, &b.b);
69
break;
70
default:
71
return -ENOENT;
72
}
73
74
- spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
75
+ if (res == 1) {
76
+ spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
77
+ count++;
78
+ }
79
+ spa_pod_dynamic_builder_clean(&b);
80
81
- if (++count != num)
82
+ if (res != 1)
83
+ return res;
84
+
85
+ if (count != num)
86
goto next;
87
88
return 0;
89
90
return 0;
91
}
92
93
+static int format_audio_raw_parse_opt(const struct spa_pod *format, struct spa_audio_info_raw *info)
94
+{
95
+ struct spa_pod *position = NULL;
96
+ uint32_t media_type, media_subtype;
97
+ int res;
98
+ if ((res = spa_format_parse(format, &media_type, &media_subtype)) < 0)
99
+ return res;
100
+ if (media_type != SPA_MEDIA_TYPE_audio ||
101
+ media_subtype != SPA_MEDIA_SUBTYPE_raw)
102
+ return -ENOTSUP;
103
+
104
+ spa_zero(*info);
105
+ res = spa_pod_parse_object(format,
106
+ SPA_TYPE_OBJECT_Format, NULL,
107
+ SPA_FORMAT_AUDIO_format, SPA_POD_OPT_Id(&info->format),
108
+ SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate),
109
+ SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
110
+ SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
111
+ if (position == NULL ||
112
+ !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
113
+ SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
114
+
115
+ return res;
116
+}
117
+
118
static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
119
const struct spa_pod *param)
120
{
121
122
SPA_PARAM_PORT_CONFIG_format, SPA_POD_OPT_Pod(&format)) < 0)
123
return -EINVAL;
124
125
+ if (format) {
126
+ struct spa_audio_info info;
127
+ if (format_audio_raw_parse_opt(format, &info.info.raw) >= 0)
128
+ this->default_format = info;
129
+ }
130
+
131
switch (mode) {
132
case SPA_PARAM_PORT_CONFIG_MODE_none:
133
return -ENOTSUP;
134
135
return res;
136
}
137
138
+static struct spa_pod *merge_objects(struct impl *this, struct spa_pod_builder *b, uint32_t id,
139
+ struct spa_pod_object *o1, struct spa_pod_object *o2)
140
+{
141
+ const struct spa_pod_prop *p1, *p2;
142
+ struct spa_pod_frame f;
143
+ struct spa_pod_builder_state state;
144
+ int res = 0;
145
+
146
+ if (o2 == NULL || SPA_POD_TYPE(o1) != SPA_POD_TYPE(o2))
147
+ return (struct spa_pod*)o1;
148
+
149
+ spa_pod_builder_push_object(b, &f, o1->body.type, o1->body.id);
150
+ p2 = NULL;
151
+ SPA_POD_OBJECT_FOREACH(o1, p1) {
152
+ p2 = spa_pod_object_find_prop(o2, p2, p1->key);
153
+ if (p2 != NULL) {
154
+ spa_pod_builder_get_state(b, &state);
155
+ res = spa_pod_filter_prop(b, p1, p2);
156
+ if (res < 0)
157
+ spa_pod_builder_reset(b, &state);
158
+ }
159
+ if (p2 == NULL || res < 0)
160
+ spa_pod_builder_raw_padded(b, p1, SPA_POD_PROP_SIZE(p1));
161
+ }
162
+ p1 = NULL;
163
+ SPA_POD_OBJECT_FOREACH(o2, p2) {
164
+ p1 = spa_pod_object_find_prop(o1, p1, p2->key);
165
+ if (p1 != NULL)
166
+ continue;
167
+ spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2));
168
+ }
169
+ return spa_pod_builder_pop(b, &f);
170
+}
171
+
172
static int negotiate_format(struct impl *this)
173
{
174
uint32_t state;
175
- struct spa_pod *format;
176
+ struct spa_pod *format, *def;
177
uint8_t buffer[4096];
178
struct spa_pod_builder b = { 0 };
179
int res;
180
181
goto done;
182
}
183
}
184
-
185
if (this->convert) {
186
state = 0;
187
if ((res = spa_node_port_enum_params_sync(this->convert,
188
189
goto done;
190
}
191
192
+ def = spa_format_audio_raw_build(&b,
193
+ SPA_PARAM_Format, &this->default_format.info.raw);
194
+
195
+ format = merge_objects(this, &b, SPA_PARAM_Format,
196
+ (struct spa_pod_object*)format,
197
+ (struct spa_pod_object*)def);
198
+
199
spa_pod_fixate(format);
200
201
res = configure_format(this, 0, format);
202
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops-c.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops-c.c
Changed
359
1
2
#include "channelmix-ops.h"
3
4
void
5
-channelmix_copy_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
6
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
7
+channelmix_copy_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
8
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
9
{
10
- uint32_t i, n;
11
+ uint32_t i, n, n_dst = mix->dst_chan;
12
float **d = (float **)dst;
13
const float **s = (const float **)src;
14
15
16
#define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch)
17
18
void
19
-channelmix_f32_n_m_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
20
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
21
+channelmix_f32_n_m_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
22
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
23
{
24
- uint32_t i, j, n;
25
+ uint32_t i, j, n, n_dst = mix->dst_chan, n_src = mix->src_chan;
26
float **d = (float **) dst;
27
const float **s = (const float **) src;
28
29
30
d[i][n] = sum;
31
}
32
}
33
- for (i = 0; i < n_dst; i++) {
34
- if (mix->lr4_info[i] > 0)
35
- lr4_process(&mix->lr4[i], d[i], n_samples);
36
- }
37
+ for (i = 0; i < n_dst; i++)
38
+ lr4_process(&mix->lr4[i], d[i], d[i], 1.0f, n_samples);
39
}
40
}
41
42
43
#define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN)
44
45
void
46
-channelmix_f32_1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
47
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
48
+channelmix_f32_1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
49
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
50
{
51
uint32_t n;
52
float **d = (float **)dst;
53
54
}
55
56
void
57
-channelmix_f32_2_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
58
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
59
+channelmix_f32_2_1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
60
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
61
{
62
uint32_t n;
63
float **d = (float **)dst;
64
65
}
66
67
void
68
-channelmix_f32_4_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
69
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
70
+channelmix_f32_4_1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
71
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
72
{
73
uint32_t n;
74
float **d = (float **)dst;
75
76
}
77
78
void
79
-channelmix_f32_3p1_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
80
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
81
+channelmix_f32_3p1_1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
82
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
83
{
84
uint32_t n;
85
float **d = (float **)dst;
86
87
#define MASK_QUAD _M(FL)|_M(FR)|_M(RL)|_M(RR)|_M(UNKNOWN)
88
89
void
90
-channelmix_f32_2_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
91
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
92
+channelmix_f32_2_4_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
93
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
94
{
95
- uint32_t i, n;
96
+ uint32_t i, n, n_dst = mix->dst_chan;
97
float **d = (float **)dst;
98
const float **s = (const float **)src;
99
const float v0 = mix->matrix[0][0];
100
101
102
#define MASK_3_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)
103
void
104
-channelmix_f32_2_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
105
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
106
+channelmix_f32_2_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
107
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
108
{
109
- uint32_t i, n;
110
+ uint32_t i, n, n_dst = mix->dst_chan;
111
float **d = (float **)dst;
112
const float **s = (const float **)src;
113
const float v0 = mix->matrix[0][0];
114
115
else if (v0 == 1.0f && v1 == 1.0f) {
116
for (n = 0; n < n_samples; n++) {
117
float c = s[0][n] + s[1][n];
118
- d[0][n] = s[0][n];
119
- d[1][n] = s[1][n];
120
- d[2][n] = c * v2;
121
- d[3][n] = c * v3;
122
+ float w = c * mix->widen;
123
+ d[0][n] = s[0][n] - w;
124
+ d[1][n] = s[1][n] - w;
125
+ d[2][n] = c;
126
}
127
- if (v3 > 0.0f)
128
- lr4_process(&mix->lr4[3], d[3], n_samples);
129
+ lr4_process(&mix->lr4[3], d[3], d[2], v3, n_samples);
130
+ lr4_process(&mix->lr4[2], d[2], d[2], v2, n_samples);
131
}
132
else {
133
for (n = 0; n < n_samples; n++) {
134
float c = s[0][n] + s[1][n];
135
- d[0][n] = s[0][n] * v0;
136
- d[1][n] = s[1][n] * v1;
137
- d[2][n] = c * v2;
138
- d[3][n] = c * v3;
139
+ float w = c * mix->widen;
140
+ d[0][n] = (s[0][n] - w) * v0;
141
+ d[1][n] = (s[1][n] - w) * v1;
142
+ d[2][n] = c;
143
}
144
- if (v3 > 0.0f)
145
- lr4_process(&mix->lr4[3], d[3], n_samples);
146
+ lr4_process(&mix->lr4[3], d[3], d[2], v3, n_samples);
147
+ lr4_process(&mix->lr4[2], d[2], d[2], v2, n_samples);
148
}
149
}
150
151
#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
152
void
153
-channelmix_f32_2_5p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
154
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
155
+channelmix_f32_2_5p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
156
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
157
+{
158
+ uint32_t i, n, n_dst = mix->dst_chan;
159
+ float **d = (float **)dst;
160
+ const float **s = (const float **)src;
161
+ const float v0 = mix->matrix[0][0];
162
+ const float v1 = mix->matrix[1][1];
163
+ const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f;
164
+ const float v3 = (mix->matrix[3][0] + mix->matrix[3][1]) * 0.5f;
165
+ const float v4 = mix->matrix[4][0];
166
+ const float v5 = mix->matrix[5][1];
167
+
168
+ if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
169
+ for (i = 0; i < n_dst; i++)
170
+ memset(d[i], 0, n_samples * sizeof(float));
171
+ }
172
+ else if (v0 == 1.0f && v1 == 1.0f) {
173
+ for (n = 0; n < n_samples; n++) {
174
+ float c = s[0][n] + s[1][n];
175
+ float w = c * mix->widen;
176
+ float m = s[0][n] - s[1][n];
177
+ d[0][n] = s[0][n] - w;
178
+ d[1][n] = s[1][n] - w;
179
+ d[3][n] = c;
180
+ d[5][n] = m;
181
+ }
182
+ lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples);
183
+ lr4_process(&mix->lr4[3], d[3], d[3], v3, n_samples);
184
+
185
+ delay_convolve_run(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
186
+ mix->taps, mix->n_taps, d[4], d[5], v4, n_samples);
187
+ delay_convolve_run(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
188
+ mix->taps, mix->n_taps, d[5], d[5], -v5, n_samples);
189
+ }
190
+ else {
191
+ for (n = 0; n < n_samples; n++) {
192
+ float c = s[0][n] + s[1][n];
193
+ float w = c * mix->widen;
194
+ float m = s[0][n] - s[1][n];
195
+ d[0][n] = (s[0][n] - w) * v0;
196
+ d[1][n] = (s[1][n] - w) * v1;
197
+ d[3][n] = c;
198
+ d[5][n] = m;
199
+ }
200
+ lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples);
201
+ lr4_process(&mix->lr4[3], d[3], d[3], v3, n_samples);
202
+
203
+ delay_convolve_run(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
204
+ mix->taps, mix->n_taps, d[4], d[5], v4, n_samples);
205
+ delay_convolve_run(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
206
+ mix->taps, mix->n_taps, d[5], d[5], -v5, n_samples);
207
+ }
208
+}
209
+
210
+void
211
+channelmix_f32_2_7p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
212
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
213
{
214
- uint32_t i, n;
215
+ uint32_t i, n, n_dst = mix->dst_chan;
216
float **d = (float **)dst;
217
const float **s = (const float **)src;
218
const float v0 = mix->matrix[0][0];
219
220
const float v3 = (mix->matrix[3][0] + mix->matrix[3][1]) * 0.5f;
221
const float v4 = mix->matrix[4][0];
222
const float v5 = mix->matrix[5][1];
223
+ const float v6 = mix->matrix[6][0];
224
+ const float v7 = mix->matrix[7][1];
225
226
if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
227
for (i = 0; i < n_dst; i++)
228
229
else if (v0 == 1.0f && v1 == 1.0f && v4 == 1.0f && v5 == 1.0f) {
230
for (n = 0; n < n_samples; n++) {
231
float c = s[0][n] + s[1][n];
232
- d[0][n] = d[4][n] = s[0][n];
233
- d[1][n] = d[5][n] = s[1][n];
234
- d[2][n] = c * v2;
235
- d[3][n] = c * v3;
236
+ float w = c * mix->widen;
237
+ float m = s[0][n] - s[1][n];
238
+ d[0][n] = s[0][n] - w;
239
+ d[1][n] = s[1][n] - w;
240
+ d[3][n] = c;
241
+ d[4][n] = s[0][n];
242
+ d[5][n] = s[1][n];
243
+ d[7][n] = m;
244
}
245
- if (v3 > 0.0f)
246
- lr4_process(&mix->lr4[3], d[3], n_samples);
247
+ lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples);
248
+ lr4_process(&mix->lr4[3], d[3], d[3], v3, n_samples);
249
+
250
+ delay_convolve_run(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
251
+ mix->taps, mix->n_taps, d[6], d[7], v6, n_samples);
252
+ delay_convolve_run(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
253
+ mix->taps, mix->n_taps, d[7], d[7], -v7, n_samples);
254
}
255
else {
256
for (n = 0; n < n_samples; n++) {
257
float c = s[0][n] + s[1][n];
258
- d[0][n] = s[0][n] * v0;
259
- d[1][n] = s[1][n] * v1;
260
- d[2][n] = c * v2;
261
- d[3][n] = c * v3;
262
+ float w = c * mix->widen;
263
+ float m = s[0][n] - s[1][n];
264
+ d[0][n] = (s[0][n] - w) * v0;
265
+ d[1][n] = (s[1][n] - w) * v1;
266
+ d[3][n] = c;
267
d[4][n] = s[0][n] * v4;
268
d[5][n] = s[1][n] * v5;
269
+ d[7][n] = m;
270
}
271
- if (v3 > 0.0f)
272
- lr4_process(&mix->lr4[3], d[3], n_samples);
273
+ lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples);
274
+ lr4_process(&mix->lr4[3], d[3], d[3], v3, n_samples);
275
+
276
+ delay_convolve_run(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay,
277
+ mix->taps, mix->n_taps, d[6], d[7], v6, n_samples);
278
+ delay_convolve_run(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay,
279
+ mix->taps, mix->n_taps, d[7], d[7], -v7, n_samples);
280
}
281
}
282
283
/* FL+FR+FC+LFE+SL+SR -> FL+FR */
284
void
285
-channelmix_f32_5p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
286
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
287
+channelmix_f32_5p1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
288
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
289
{
290
uint32_t n;
291
float **d = (float **) dst;
292
293
294
/* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/
295
void
296
-channelmix_f32_5p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
297
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
298
+channelmix_f32_5p1_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
299
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
300
{
301
- uint32_t i, n;
302
+ uint32_t i, n, n_dst = mix->dst_chan;
303
float **d = (float **) dst;
304
const float **s = (const float **) src;
305
const float v0 = mix->matrix[0][0];
306
307
308
/* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/
309
void
310
-channelmix_f32_5p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
311
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
312
+channelmix_f32_5p1_4_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
313
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
314
{
315
- uint32_t i, n;
316
+ uint32_t i, n, n_dst = mix->dst_chan;
317
float **d = (float **) dst;
318
const float **s = (const float **) src;
319
const float clev = mix->matrix[0][2];
320
321
322
/* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR */
323
void
324
-channelmix_f32_7p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
325
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
326
+channelmix_f32_7p1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
327
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
328
{
329
uint32_t n;
330
float **d = (float **) dst;
331
332
333
/* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+FC+LFE*/
334
void
335
-channelmix_f32_7p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
336
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
337
+channelmix_f32_7p1_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
338
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
339
{
340
- uint32_t i, n;
341
+ uint32_t i, n, n_dst = mix->dst_chan;
342
float **d = (float **) dst;
343
const float **s = (const float **) src;
344
const float v0 = mix->matrix[0][0];
345
346
347
/* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+RL+RR*/
348
void
349
-channelmix_f32_7p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
350
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
351
+channelmix_f32_7p1_4_c(struct channelmix *mix, void * SPA_RESTRICT dst[],
352
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
353
{
354
- uint32_t i, n;
355
+ uint32_t i, n, n_dst = mix->dst_chan;
356
float **d = (float **) dst;
357
const float **s = (const float **) src;
358
const float v0 = mix->matrix[0][0];
359
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c
Changed
100
1
2
3
#include <xmmintrin.h>
4
5
-void channelmix_copy_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
6
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
7
+void channelmix_copy_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
8
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
9
{
10
- uint32_t i, n, unrolled;
11
+ uint32_t i, n, unrolled, n_dst = mix->dst_chan;
12
float **d = (float **)dst;
13
const float **s = (const float **)src;
14
15
16
}
17
18
void
19
-channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
20
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
21
+channelmix_f32_2_4_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
22
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
23
{
24
- uint32_t i, n, unrolled;
25
+ uint32_t i, n, unrolled, n_dst = mix->dst_chan;
26
float **d = (float **)dst;
27
const float **s = (const float **)src;
28
const float m00 = mix->matrix[0][0];
29
30
31
/* FL+FR+FC+LFE+SL+SR -> FL+FR */
32
void
33
-channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
34
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
35
+channelmix_f32_5p1_2_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
36
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
37
{
38
uint32_t n, unrolled;
39
float **d = (float **) dst;
40
41
ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev));
42
in = _mm_mul_ps(_mm_load_ps(&sSL[n]), slev0);
43
in = _mm_add_ps(in, ctr);
44
- in = _mm_add_ps(in, _mm_load_ps(&sFL[n]));
45
- in = _mm_mul_ps(in, v0);
46
+ in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFL[n]), v0));
47
_mm_store_ps(&dFL[n], in);
48
in = _mm_mul_ps(_mm_load_ps(&sSR[n]), slev1);
49
in = _mm_add_ps(in, ctr);
50
- in = _mm_add_ps(in, _mm_load_ps(&sFR[n]));
51
- in = _mm_mul_ps(in, v1);
52
+ in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFR[n]), v1));
53
_mm_store_ps(&dFR[n], in);
54
}
55
for(; n < n_samples; n++) {
56
57
ctr = _mm_add_ss(ctr, _mm_mul_ss(_mm_load_ss(&sLFE[n]), llev));
58
in = _mm_mul_ss(_mm_load_ss(&sSL[n]), slev0);
59
in = _mm_add_ss(in, ctr);
60
- in = _mm_add_ss(in, _mm_load_ss(&sFL[n]));
61
- in = _mm_mul_ss(in, v0);
62
+ in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFL[n]), v0));
63
_mm_store_ss(&dFL[n], in);
64
in = _mm_mul_ss(_mm_load_ss(&sSR[n]), slev1);
65
in = _mm_add_ss(in, ctr);
66
- in = _mm_add_ss(in, _mm_load_ss(&sFR[n]));
67
- in = _mm_mul_ss(in, v1);
68
+ in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFR[n]), v1));
69
_mm_store_ss(&dFR[n], in);
70
}
71
}
72
73
74
/* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/
75
void
76
-channelmix_f32_5p1_3p1_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
77
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
78
+channelmix_f32_5p1_3p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
79
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
80
{
81
- uint32_t i, n, unrolled;
82
+ uint32_t i, n, unrolled, n_dst = mix->dst_chan;
83
float **d = (float **) dst;
84
const float **s = (const float **) src;
85
const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]);
86
87
88
/* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/
89
void
90
-channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
91
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples)
92
+channelmix_f32_5p1_4_sse(struct channelmix *mix, void * SPA_RESTRICT dst[],
93
+ const void * SPA_RESTRICT src[], uint32_t n_samples)
94
{
95
- uint32_t i, n, unrolled;
96
+ uint32_t i, n, unrolled, n_dst = mix->dst_chan;
97
float **d = (float **) dst;
98
const float **s = (const float **) src;
99
const __m128 clev = _mm_set1_ps(mix->matrix[0][2]);
100
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
90
1
2
#define VOLUME_NORM 1.0f
3
4
#include "channelmix-ops.h"
5
+#include "hilbert.h"
6
7
#undef SPA_LOG_TOPIC_DEFAULT
8
#define SPA_LOG_TOPIC_DEFAULT log_topic
9
10
#define ANY ((uint32_t)-1)
11
#define EQ ((uint32_t)-2)
12
13
-typedef void (*channelmix_func_t) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
14
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples);
15
+typedef void (*channelmix_func_t) (struct channelmix *mix, void * SPA_RESTRICT dst[],
16
+ const void * SPA_RESTRICT src[], uint32_t n_samples);
17
18
static const struct channelmix_info {
19
uint32_t src_chan;
20
21
{ 2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_c, 0, "f32_2_4_c" },
22
{ 2, MASK_STEREO, 4, MASK_3_1, channelmix_f32_2_3p1_c, 0, "f32_2_3p1_c" },
23
{ 2, MASK_STEREO, 6, MASK_5_1, channelmix_f32_2_5p1_c, 0, "f32_2_5p1_c" },
24
+ { 2, MASK_STEREO, 8, MASK_7_1, channelmix_f32_2_7p1_c, 0, "f32_2_7p1_c" },
25
#if defined (HAVE_SSE)
26
{ 6, MASK_5_1, 2, MASK_STEREO, channelmix_f32_5p1_2_sse, SPA_CPU_FLAG_SSE, "f32_5p1_2_sse" },
27
#endif
28
29
keep |= FRONT;
30
if (mix->lfe_cutoff > 0.0f)
31
keep |= _MASK(LFE);
32
+ else
33
+ keep &= ~_MASK(LFE);
34
35
- spa_log_debug(mix->log, "unassigned downmix %08" PRIx64, unassigned);
36
+ spa_log_debug(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep);
37
38
if (unassigned & FRONT){
39
if ((dst_mask & STEREO) == STEREO){
40
41
}
42
maxsum = SPA_MAX(maxsum, sum);
43
if (i == _CH(LFE) && mix->lfe_cutoff > 0.0f) {
44
- spa_log_debug(mix->log, "channel %d is LFE", ic);
45
+ spa_log_debug(mix->log, "channel %d is LFE cutoff:%f", ic, mix->lfe_cutoff);
46
lr4_set(&mix->lr4[ic], BQ_LOWPASS, mix->lfe_cutoff / mix->freq);
47
- mix->lr4_info[ic] = 1;
48
+ } else if (i == _CH(FC) && mix->fc_cutoff > 0.0f) {
49
+ spa_log_debug(mix->log, "channel %d is FC cutoff:%f", ic, mix->fc_cutoff);
50
+ lr4_set(&mix->lr4[ic], BQ_LOWPASS, mix->fc_cutoff / mix->freq);
51
} else {
52
- mix->lr4_info[ic] = 0;
53
+ mix->lr4[ic].active = false;
54
}
55
ic++;
56
}
57
58
for (j = 0; j < jc; j++)
59
mix->matrix_orig[i][j] /= maxsum;
60
}
61
+
62
return 0;
63
}
64
65
66
if (info == NULL)
67
return -ENOTSUP;
68
69
- spa_log_debug(mix->log, "selected %s", info->name);
70
-
71
mix->free = impl_channelmix_free;
72
mix->process = info->process;
73
mix->set_volume = impl_channelmix_set_volume;
74
mix->cpu_flags = info->cpu_flags;
75
+ mix->delay = mix->rear_delay * mix->freq / 1000.0f;
76
+
77
+ spa_log_debug(mix->log, "selected %s delay:%d options:%08x", info->name, mix->delay,
78
+ mix->options);
79
+
80
+ if (mix->hilbert_taps > 0) {
81
+ mix->n_taps = SPA_CLAMP(mix->hilbert_taps, 15u, 255u) | 1;
82
+ blackman_window(mix->taps, mix->n_taps);
83
+ hilbert_generate(mix->taps, mix->n_taps);
84
+ } else {
85
+ mix->n_taps = 1;
86
+ mix->taps[0] = 1.0f;
87
+ }
88
return make_matrix(mix);
89
}
90
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops.h -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops.h
Changed
66
1
2
extern struct spa_log_topic *log_topic;
3
4
#include "crossover.h"
5
+#include "delay.h"
6
7
#define VOLUME_MIN 0.0f
8
#define VOLUME_NORM 1.0f
9
10
#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
11
#define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
12
13
+#define BUFFER_SIZE 4096
14
+
15
+#define BUFFER_SIZE 4096
16
+#define MAX_TAPS 255
17
18
struct channelmix {
19
uint32_t src_chan;
20
21
22
float freq; /* sample frequency */
23
float lfe_cutoff; /* in Hz, 0 is disabled */
24
- uint32_t lr4_info[SPA_AUDIO_MAX_CHANNELS];
25
+ float fc_cutoff; /* in Hz, 0 is disabled */
26
+ float rear_delay; /* in ms, 0 is disabled */
27
+ float widen; /* stereo widen. 0 is disabled */
28
+ uint32_t hilbert_taps; /* to phase shift, 0 disabled */
29
struct lr4 lr4[SPA_AUDIO_MAX_CHANNELS];
30
31
- void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
32
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples);
33
+ float buffer[2][BUFFER_SIZE];
34
+ uint32_t pos[2];
35
+ uint32_t delay;
36
+ float taps[MAX_TAPS];
37
+ uint32_t n_taps;
38
+
39
+ void (*process) (struct channelmix *mix, void * SPA_RESTRICT dst[],
40
+ const void * SPA_RESTRICT src[], uint32_t n_samples);
41
void (*set_volume) (struct channelmix *mix, float volume, bool mute,
42
uint32_t n_channel_volumes, float *channel_volumes);
43
void (*free) (struct channelmix *mix);
44
45
#define channelmix_set_volume(mix,...) (mix)->set_volume(mix, __VA_ARGS__)
46
#define channelmix_free(mix) (mix)->free(mix)
47
48
-#define DEFINE_FUNCTION(name,arch) \
49
-void channelmix_##name##_##arch(struct channelmix *mix, \
50
- uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], \
51
- uint32_t n_src, const void * SPA_RESTRICT src[n_src], \
52
+#define DEFINE_FUNCTION(name,arch) \
53
+void channelmix_##name##_##arch(struct channelmix *mix, \
54
+ void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], \
55
uint32_t n_samples);
56
57
#define CHANNELMIX_OPS_MAX_ALIGN 16
58
59
DEFINE_FUNCTION(f32_2_4, c);
60
DEFINE_FUNCTION(f32_2_3p1, c);
61
DEFINE_FUNCTION(f32_2_5p1, c);
62
+DEFINE_FUNCTION(f32_2_7p1, c);
63
DEFINE_FUNCTION(f32_5p1_2, c);
64
DEFINE_FUNCTION(f32_5p1_3p1, c);
65
DEFINE_FUNCTION(f32_5p1_4, c);
66
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix.c
Changed
269
1
2
struct spa_cpu *cpu;
3
uint32_t quantum_limit;
4
5
+ enum spa_direction direction;
6
struct spa_io_position *io_position;
7
8
struct spa_hook_list hooks;
9
10
if ((res = channelmix_init(&this->mix)) < 0)
11
return res;
12
13
- remap_volumes(this, src_info);
14
+ remap_volumes(this, this->direction == SPA_DIRECTION_INPUT ? src_info : dst_info);
15
set_volume(this);
16
17
emit_props_changed(this);
18
19
case 8:
20
param = spa_pod_builder_add_object(&b,
21
SPA_TYPE_OBJECT_PropInfo, id,
22
+ SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"),
23
+ SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"),
24
+ SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled),
25
+ SPA_PROP_INFO_params, SPA_POD_Bool(true));
26
+ break;
27
+ case 9:
28
+ param = spa_pod_builder_add_object(&b,
29
+ SPA_TYPE_OBJECT_PropInfo, id,
30
SPA_PROP_INFO_name, SPA_POD_String("channelmix.normalize"),
31
SPA_PROP_INFO_description, SPA_POD_String("Normalize Volumes"),
32
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(
33
SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_NORMALIZE)),
34
SPA_PROP_INFO_params, SPA_POD_Bool(true));
35
break;
36
- case 9:
37
+ case 10:
38
param = spa_pod_builder_add_object(&b,
39
SPA_TYPE_OBJECT_PropInfo, id,
40
SPA_PROP_INFO_name, SPA_POD_String("channelmix.mix-lfe"),
41
42
SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_MIX_LFE)),
43
SPA_PROP_INFO_params, SPA_POD_Bool(true));
44
break;
45
- case 10:
46
+ case 11:
47
param = spa_pod_builder_add_object(&b,
48
SPA_TYPE_OBJECT_PropInfo, id,
49
SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix"),
50
51
SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_UPMIX)),
52
SPA_PROP_INFO_params, SPA_POD_Bool(true));
53
break;
54
- case 11:
55
+ case 12:
56
param = spa_pod_builder_add_object(&b,
57
SPA_TYPE_OBJECT_PropInfo, id,
58
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lfe-cutoff"),
59
- SPA_PROP_INFO_description, SPA_POD_String("LFE cutoff frequency"),
60
+ SPA_PROP_INFO_description, SPA_POD_String("LFE cutoff frequency (Hz)"),
61
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
62
this->mix.lfe_cutoff, 0.0, 1000.0),
63
SPA_PROP_INFO_params, SPA_POD_Bool(true));
64
break;
65
- case 12:
66
+ case 13:
67
param = spa_pod_builder_add_object(&b,
68
SPA_TYPE_OBJECT_PropInfo, id,
69
- SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"),
70
- SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"),
71
- SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled),
72
+ SPA_PROP_INFO_name, SPA_POD_String("channelmix.fc-cutoff"),
73
+ SPA_PROP_INFO_description, SPA_POD_String("FC cutoff frequency (Hz)"),
74
+ SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
75
+ this->mix.fc_cutoff, 0.0, 48000.0),
76
+ SPA_PROP_INFO_params, SPA_POD_Bool(true));
77
+ break;
78
+ case 14:
79
+ param = spa_pod_builder_add_object(&b,
80
+ SPA_TYPE_OBJECT_PropInfo, id,
81
+ SPA_PROP_INFO_name, SPA_POD_String("channelmix.rear-delay"),
82
+ SPA_PROP_INFO_description, SPA_POD_String("Rear channels delay (ms)"),
83
+ SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
84
+ this->mix.rear_delay, 0.0, 1000.0),
85
+ SPA_PROP_INFO_params, SPA_POD_Bool(true));
86
+ break;
87
+ case 15:
88
+ param = spa_pod_builder_add_object(&b,
89
+ SPA_TYPE_OBJECT_PropInfo, id,
90
+ SPA_PROP_INFO_name, SPA_POD_String("channelmix.stereo-widen"),
91
+ SPA_PROP_INFO_description, SPA_POD_String("Stereo widen"),
92
+ SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
93
+ this->mix.widen, 0.0, 1.0),
94
+ SPA_PROP_INFO_params, SPA_POD_Bool(true));
95
+ break;
96
+ case 16:
97
+ param = spa_pod_builder_add_object(&b,
98
+ SPA_TYPE_OBJECT_PropInfo, id,
99
+ SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"),
100
+ SPA_PROP_INFO_description, SPA_POD_String("Taps for phase shift of rear"),
101
+ SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(
102
+ this->mix.hilbert_taps, 0, MAX_TAPS),
103
SPA_PROP_INFO_params, SPA_POD_Bool(true));
104
break;
105
default:
106
107
0);
108
spa_pod_builder_prop(&b, SPA_PROP_params, 0);
109
spa_pod_builder_push_struct(&b, &f[1]);
110
+ spa_pod_builder_string(&b, "channelmix.disable");
111
+ spa_pod_builder_bool(&b, this->props.disabled);
112
spa_pod_builder_string(&b, "channelmix.normalize");
113
spa_pod_builder_bool(&b, SPA_FLAG_IS_SET(this->mix.options,
114
CHANNELMIX_OPTION_NORMALIZE));
115
116
CHANNELMIX_OPTION_UPMIX));
117
spa_pod_builder_string(&b, "channelmix.lfe-cutoff");
118
spa_pod_builder_float(&b, this->mix.lfe_cutoff);
119
- spa_pod_builder_string(&b, "channelmix.disable");
120
- spa_pod_builder_bool(&b, this->props.disabled);
121
+ spa_pod_builder_string(&b, "channelmix.fc-cutoff");
122
+ spa_pod_builder_float(&b, this->mix.fc_cutoff);
123
+ spa_pod_builder_string(&b, "channelmix.rear-delay");
124
+ spa_pod_builder_float(&b, this->mix.rear_delay);
125
+ spa_pod_builder_string(&b, "channelmix.stereo-widen");
126
+ spa_pod_builder_float(&b, this->mix.widen);
127
+ spa_pod_builder_string(&b, "channelmix.hilbert-taps");
128
+ spa_pod_builder_int(&b, this->mix.hilbert_taps);
129
spa_pod_builder_pop(&b, &f[1]);
130
param = spa_pod_builder_pop(&b, &f[0]);
131
break;
132
133
134
static int channelmix_set_param(struct impl *this, const char *k, const char *s)
135
{
136
- if (spa_streq(k, "channelmix.normalize"))
137
+ if (spa_streq(k, "channelmix.disable"))
138
+ this->props.disabled = spa_atob(s);
139
+ else if (spa_streq(k, "channelmix.normalize"))
140
SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_NORMALIZE, spa_atob(s));
141
else if (spa_streq(k, "channelmix.mix-lfe"))
142
SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_MIX_LFE, spa_atob(s));
143
else if (spa_streq(k, "channelmix.upmix"))
144
SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_UPMIX, spa_atob(s));
145
else if (spa_streq(k, "channelmix.lfe-cutoff"))
146
- this->mix.lfe_cutoff = atoi(s);
147
- else if (spa_streq(k, "channelmix.disable"))
148
- this->props.disabled = spa_atob(s);
149
- return 0;
150
+ spa_atof(s, &this->mix.lfe_cutoff);
151
+ else if (spa_streq(k, "channelmix.fc-cutoff"))
152
+ spa_atof(s, &this->mix.fc_cutoff);
153
+ else if (spa_streq(k, "channelmix.rear-delay"))
154
+ spa_atof(s, &this->mix.rear_delay);
155
+ else if (spa_streq(k, "channelmix.stereo-widen"))
156
+ spa_atof(s, &this->mix.widen);
157
+ else if (spa_streq(k, "channelmix.hilbert-taps"))
158
+ spa_atou32(s, &this->mix.hilbert_taps, 0);
159
+ else
160
+ return 0;
161
+ return 1;
162
}
163
164
static int parse_prop_params(struct impl *this, struct spa_pod *params)
165
{
166
struct spa_pod_parser prs;
167
struct spa_pod_frame f;
168
+ int changed = 0;
169
170
spa_pod_parser_pod(&prs, params);
171
if (spa_pod_parser_push_struct(&prs, &f) < 0)
172
173
continue;
174
175
spa_log_info(this->log, "key:'%s' val:'%s'", name, value);
176
- channelmix_set_param(this, name, value);
177
+ changed += channelmix_set_param(this, name, value);
178
}
179
- return 0;
180
+ if (changed)
181
+ channelmix_init(&this->mix);
182
+ return changed;
183
}
184
185
static int apply_props(struct impl *this, const struct spa_pod *param)
186
187
}
188
}
189
if (changed) {
190
- struct port *port = GET_IN_PORT(this, 0);
191
+ struct port *port = GET_PORT(this, this->direction, 0);
192
if (have_soft_volume)
193
p->have_soft_volume = true;
194
else if (have_channel_volume)
195
196
}
197
198
static int channelmix_process_control(struct impl *this, struct port *ctrlport,
199
- uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
200
- uint32_t n_src, const void * SPA_RESTRICT src[n_src],
201
+ void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[],
202
uint32_t n_samples)
203
{
204
struct spa_pod_control *c, *prev = NULL;
205
206
spa_log_trace_fp(this->log, "%p: process %d %d", this,
207
c->offset, chunk);
208
209
- channelmix_process(&this->mix, n_dst, dst, n_src, src, chunk);
210
- for (i = 0; i < n_src; i++)
211
+ channelmix_process(&this->mix, dst, src, chunk);
212
+ for (i = 0; i < this->mix.src_chan; i++)
213
s[i] += chunk;
214
- for (i = 0; i < n_dst; i++)
215
+ for (i = 0; i < this->mix.dst_chan; i++)
216
d[i] += chunk;
217
218
avail_samples -= chunk;
219
220
* remaining samples */
221
spa_log_trace_fp(this->log, "%p: remain %d", this, avail_samples);
222
if (avail_samples > 0)
223
- channelmix_process(&this->mix, n_dst, dst, n_src, src, avail_samples);
224
+ channelmix_process(&this->mix, dst, src, avail_samples);
225
226
return 1;
227
}
228
229
if (!is_passthrough) {
230
if (ctrlport->ctrl != NULL) {
231
/* if return value is 1, the sequence has been processed */
232
- if (channelmix_process_control(this, ctrlport, n_dst_datas, dst_datas,
233
- n_src_datas, src_datas, n_samples) == 1) {
234
+ if (channelmix_process_control(this, ctrlport, dst_datas,
235
+ src_datas, n_samples) == 1) {
236
ctrlio->status = SPA_STATUS_OK;
237
ctrlport->ctrl = NULL;
238
}
239
} else {
240
- channelmix_process(&this->mix, n_dst_datas, dst_datas,
241
- n_src_datas, src_datas, n_samples);
242
+ channelmix_process(&this->mix, dst_datas,
243
+ src_datas, n_samples);
244
}
245
}
246
}
247
248
props_reset(&this->props);
249
250
this->mix.options = CHANNELMIX_OPTION_NORMALIZE;
251
+ this->mix.log = this->log;
252
+ this->mix.rear_delay = 12.0f;
253
254
for (i = 0; info && i < info->n_items; i++) {
255
const char *k = info->items[i].key;
256
257
this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s));
258
else if (spa_streq(k, "clock.quantum-limit"))
259
spa_atou32(s, &this->quantum_limit, 0);
260
+ else if (spa_streq(k, "factory.mode")) {
261
+ if (spa_streq(s, "merge"))
262
+ this->direction = SPA_DIRECTION_OUTPUT;
263
+ else
264
+ this->direction = SPA_DIRECTION_INPUT;
265
+ }
266
else
267
channelmix_set_param(this, k, s);
268
269
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/crossover.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/crossover.c
Changed
71
1
2
3
#include "config.h"
4
5
+#include <float.h>
6
+#include <string.h>
7
+
8
#include "crossover.h"
9
10
void lr4_set(struct lr4 *lr4, enum biquad_type type, float freq)
11
12
lr4->y2 = 0;
13
lr4->z1 = 0;
14
lr4->z2 = 0;
15
+ lr4->active = true;
16
}
17
18
-void lr4_process(struct lr4 *lr4, float *data, int samples)
19
+void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples)
20
{
21
float lx1 = lr4->x1;
22
float lx2 = lr4->x2;
23
24
float lb2 = lr4->bq.b2;
25
float la1 = lr4->bq.a1;
26
float la2 = lr4->bq.a2;
27
-
28
int i;
29
+
30
+ if (vol == 0.0f) {
31
+ memset(dst, 0, samples * sizeof(float));
32
+ return;
33
+ } else if (!lr4->active) {
34
+ if (src != dst || vol != 1.0f) {
35
+ for (i = 0; i < samples; i++)
36
+ dst[i] = src[i] * vol;
37
+ }
38
+ return;
39
+ }
40
+
41
for (i = 0; i < samples; i++) {
42
float x, y, z;
43
- x = data[i];
44
+ x = src[i];
45
y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2;
46
z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2;
47
lx2 = lx1;
48
49
ly1 = y;
50
lz2 = lz1;
51
lz1 = z;
52
- data[i] = z;
53
+ dst[i] = z * vol;
54
}
55
-
56
- lr4->x1 = lx1;
57
- lr4->x2 = lx2;
58
- lr4->y1 = ly1;
59
- lr4->y2 = ly2;
60
- lr4->z1 = lz1;
61
- lr4->z2 = lz2;
62
+#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
63
+ lr4->x1 = F(lx1);
64
+ lr4->x2 = F(lx2);
65
+ lr4->y1 = F(ly1);
66
+ lr4->y2 = F(ly2);
67
+ lr4->z1 = F(lz1);
68
+ lr4->z2 = F(lz2);
69
+#undef F
70
}
71
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/crossover.h -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/crossover.h
Changed
23
1
2
#ifndef CROSSOVER_H_
3
#define CROSSOVER_H_
4
5
+#include <stdbool.h>
6
+
7
#include "biquad.h"
8
/* An LR4 filter is two biquads with the same parameters connected in series:
9
*
10
11
float x1, x2;
12
float y1, y2;
13
float z1, z2;
14
+ bool active;
15
};
16
17
void lr4_set(struct lr4 *lr4, enum biquad_type type, float freq);
18
19
-void lr4_process(struct lr4 *lr4, float *data, int samples);
20
+void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples);
21
22
#endif /* CROSSOVER_H_ */
23
pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/delay.h
Added
74
1
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef DELAY_H
27
+#define DELAY_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+static inline void delay_run(float *buffer, uint32_t *pos,
34
+ uint32_t n_buffer, uint32_t delay,
35
+ float *dst, const float *src, const float vol, uint32_t n_samples)
36
+{
37
+ uint32_t i;
38
+ uint32_t p = *pos;
39
+
40
+ for (i = 0; i < n_samples; i++) {
41
+ buffer[p] = src[i];
42
+ dst[i] = buffer[(p - delay) & (n_buffer-1)] * vol;
43
+ p = (p + 1) & (n_buffer-1);
44
+ }
45
+ *pos = p;
46
+}
47
+
48
+static inline void delay_convolve_run(float *buffer, uint32_t *pos,
49
+ uint32_t n_buffer, uint32_t delay,
50
+ const float *taps, uint32_t n_taps,
51
+ float *dst, const float *src, const float vol, uint32_t n_samples)
52
+{
53
+ uint32_t i, j;
54
+ uint32_t p = *pos;
55
+
56
+ for (i = 0; i < n_samples; i++) {
57
+ float sum = 0.0f;
58
+
59
+ buffer[p] = src[i];
60
+ for (j = 0; j < n_taps; j++)
61
+ sum += (taps[j] * buffer[((p - delay) - j) & (n_buffer-1)]);
62
+ dst[i] = sum * vol;
63
+
64
+ p = (p + 1) & (n_buffer-1);
65
+ }
66
+ *pos = p;
67
+}
68
+
69
+#ifdef __cplusplus
70
+}
71
+#endif
72
+
73
+#endif /* DELAY_H */
74
pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/hilbert.h
Added
71
1
2
+/* Hilbert function
3
+ *
4
+ * Copyright © 2021 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef HILBERT_H
27
+#define HILBERT_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+#include <errno.h>
34
+#include <stddef.h>
35
+#include <math.h>
36
+
37
+static inline void blackman_window(float *taps, int n_taps)
38
+{
39
+ int n;
40
+ for (n = 0; n < n_taps; n++) {
41
+ float w = 2 * M_PI * n / (n_taps-1);
42
+ taps[n] = 0.3635819 - 0.4891775 * cos(w)
43
+ + 0.1365995 * cos(2 * w) - 0.0106411 * cos(3 * w);
44
+ }
45
+}
46
+
47
+static inline int hilbert_generate(float *taps, int n_taps)
48
+{
49
+ int i;
50
+
51
+ if ((n_taps & 1) == 0)
52
+ return -EINVAL;
53
+
54
+ for (i = 0; i < n_taps; i++) {
55
+ int k = -(n_taps / 2) + i;
56
+ if (k & 1) {
57
+ float pk = M_PI * k;
58
+ taps[i] *= (1.0f - cosf(pk)) / pk;
59
+ } else {
60
+ taps[i] = 0.0f;
61
+ }
62
+ }
63
+ return 0;
64
+}
65
+
66
+#ifdef __cplusplus
67
+} /* extern "C" */
68
+#endif
69
+
70
+#endif /* HILBERT_H */
71
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/merger.c
Changed
23
1
2
3
case SPA_PARAM_Props:
4
{
5
+#if 0
6
struct props *p = &this->props;
7
struct spa_pod_frame f[2];
8
+#endif
9
10
switch (result.index) {
11
+#if 0
12
case 0:
13
spa_pod_builder_push_object(&b, &f[0],
14
SPA_TYPE_OBJECT_Props, id);
15
16
spa_pod_builder_pop(&b, &f[1]);
17
param = spa_pod_builder_pop(&b, &f[0]);
18
break;
19
+#endif
20
default:
21
return 0;
22
}
23
pipewire-0.3.47.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.48.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
22
1
2
dbus_message_iter_get_basic(&iter, &uuid);
3
4
profile = spa_bt_profile_from_uuid(uuid);
5
- if (profile && (device->profiles & profile) == 0) {
6
- spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid);
7
- device->profiles |= profile;
8
+
9
+ /* Only add A2DP profiles if HSP/HFP backed is none.
10
+ * This allows BT device to connect instantly instead of waiting for
11
+ * profile timeout, because all available profiles are connected.
12
+ */
13
+ if (monitor->backend_selection != BACKEND_NONE || (monitor->backend_selection == BACKEND_NONE &&
14
+ profile & (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_A2DP_SOURCE))) {
15
+ if (profile && (device->profiles & profile) == 0) {
16
+ spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid);
17
+ device->profiles |= profile;
18
+ }
19
}
20
dbus_message_iter_next(&iter);
21
}
22
pipewire-0.3.47.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.48.tar.gz/spa/plugins/support/loop.c
Changed
66
1
2
struct spa_system *system;
3
4
struct spa_list source_list;
5
+ struct spa_list destroy_list;
6
struct spa_hook_list hooks_list;
7
8
int poll_fd;
9
10
impl->thread = 0;
11
}
12
13
+static inline void process_destroy(struct impl *impl)
14
+{
15
+ struct source_impl *source, *tmp;
16
+ spa_list_for_each_safe(source, tmp, &impl->destroy_list, link)
17
+ free(source);
18
+ spa_list_init(&impl->destroy_list);
19
+}
20
+
21
static int loop_iterate(void *object, int timeout)
22
{
23
struct impl *impl = object;
24
25
}
26
for (i = 0; i < nfds; i++) {
27
struct spa_source *s = ep[i].data;
28
- if (SPA_LIKELY(s && s->rmask)) {
29
+ if (SPA_LIKELY(s && s->rmask && s->loop)) {
30
s->priv = NULL;
31
s->func(s);
32
}
33
}
34
+ if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
35
+ process_destroy(impl);
36
+
37
return nfds;
38
}
39
40
41
spa_system_close(impl->impl->system, source->fd);
42
source->fd = -1;
43
}
44
- free(source);
45
+ spa_list_insert(&impl->impl->destroy_list, &impl->link);
46
}
47
48
static const struct spa_loop_methods impl_loop = {
49
50
spa_list_consume(source, &impl->source_list, link)
51
loop_destroy_source(impl, &source->source);
52
53
+ process_destroy(impl);
54
+
55
spa_system_close(impl->system, impl->ack_fd);
56
spa_system_close(impl->system, impl->poll_fd);
57
58
59
impl->poll_fd = res;
60
61
spa_list_init(&impl->source_list);
62
+ spa_list_init(&impl->destroy_list);
63
spa_hook_list_init(&impl->hooks_list);
64
65
impl->buffer_data = SPA_PTR_ALIGN(impl->buffer_mem, MAX_ALIGN, uint8_t);
66
pipewire-0.3.47.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/client-rt.conf.in
Changed
10
1
2
#channelmix.mix-lfe = true
3
#channelmix.upmix = false
4
#channelmix.lfe-cutoff = 0
5
+ #channelmix.fc-cutoff = 0
6
+ #channelmix.rear-delay = 12.0
7
+ #channelmix.stereo-widen = 0.0
8
+ #channelmix.hilbert-taps = 0
9
}
10
pipewire-0.3.47.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/client.conf.in
Changed
10
1
2
#channelmix.mix-lfe = false
3
#channelmix.upmix = false
4
#channelmix.lfe-cutoff = 0
5
+ #channelmix.fc-cutoff = 0
6
+ #channelmix.rear-delay = 12.0
7
+ #channelmix.stereo-widen = 0.0
8
+ #channelmix.hilbert-taps = 0
9
}
10
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/demonic.conf
Changed
23
1
2
#audio.format = F32
3
#audio.rate = 48000
4
audio.channels = 2
5
- #audio.position = [ FL FR ]
6
- node.name = "filter-chain-demonic"
7
+ audio.position = [ FL FR ]
8
node.description = "Demonic example"
9
media.name = "Demonic example"
10
filter.graph = {
11
12
outputs = [ "rev2:Out L" ]
13
}
14
capture.props = {
15
+ node.name = "effect_input.filter-chain-demonic"
16
#media.class = Audio/Sink
17
}
18
playback.props = {
19
+ node.name = "effect_output.filter-chain-demonic"
20
#media.class = Audio/Source
21
}
22
}
23
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/duplicate-FL.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/duplicate-FL.conf
Changed
22
1
2
context.modules = [
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "remap-FL-to-FL-FR"
6
node.description = "Remap example"
7
media.name = "Remap example"
8
filter.graph = {
9
10
outputs = [ "copyOL:Out" "copyOR:Out" ]
11
}
12
capture.props = {
13
+ node.name = "remap_input.remap-FL-to-FL-FR"
14
audio.position = [ FL ]
15
stream.dont-remix = true
16
}
17
playback.props = {
18
+ node.name = "remap_output.remap-FL-to-FL-FR"
19
audio.position = [ FL FR ]
20
}
21
}
22
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf
Changed
23
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_output.dolby_surround"
6
node.description = "Dolby Surround Sink"
7
media.name = "Dolby Surround Sink"
8
filter.graph = {
9
10
outputs = [ "enc:Lt" "enc:Rt" ]
11
}
12
capture.props = {
13
+ node.name = "effect_input.dolby_surround"
14
media.class = Audio/Sink
15
audio.channels = 6
16
audio.position = [ FL FR FC LFE SL SR ]
17
}
18
playback.props = {
19
+ node.name = "effect_output.dolby_surround"
20
node.passive = true
21
audio.channels = 2
22
audio.position = [ FL FR ]
23
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-eq6.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-eq6.conf
Changed
21
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_output.eq6"
6
node.description = "Equalizer Sink"
7
media.name = "Equalizer Sink"
8
filter.graph = {
9
10
]
11
}
12
capture.props = {
13
+ node.name = "effect_input.eq6"
14
media.class = Audio/Sink
15
}
16
playback.props = {
17
+ node.name = "effect_output.eq6"
18
node.passive = true
19
}
20
}
21
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf
Changed
31
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_output.matrix_spatialiser"
6
node.description = "Matrix Spatialiser"
7
media.name = "Matrix Spatialiser"
8
filter.graph = {
9
10
inputs = [ "matrix:Input L" "matrix:Input R" ]
11
outputs = [ "matrix:Output L" "matrix:Output R" ]
12
}
13
+ audio.channels = 2
14
+ audio.position = [ FL FR ]
15
capture.props = {
16
+ node.name = "effect_input.matrix_spatialiser"
17
media.class = Audio/Sink
18
- audio.channels = 2
19
- audio.position = [ FL FR ]
20
}
21
playback.props = {
22
- #media.class = Audio/Source
23
- #node.passive = true
24
- audio.channels = 2
25
- audio.position = [ FL FR ]
26
+ node.name = "effect_output.matrix_spatialiser"
27
+ node.passive = true
28
}
29
}
30
}
31
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf
Changed
23
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_output.virtual-surround-5.1-kemar"
6
node.description = "Virtual Surround Sink"
7
media.name = "Virtual Surround Sink"
8
filter.graph = {
9
10
11
}
12
capture.props = {
13
+ node.name = "effect_input.virtual-surround-5.1-kemar"
14
media.class = Audio/Sink
15
audio.channels = 6
16
audio.position = [ FL FR FC LFE SL SR]
17
}
18
playback.props = {
19
+ node.name = "effect_output.virtual-surround-5.1-kemar"
20
node.passive = true
21
audio.channels = 2
22
audio.position = [ FL FR ]
23
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf
Changed
23
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_output.virtual-surround-7.1-hesuvi"
6
node.description = "Virtual Surround Sink"
7
media.name = "Virtual Surround Sink"
8
filter.graph = {
9
10
outputs = [ "mixL:Out" "mixR:Out" ]
11
}
12
capture.props = {
13
+ node.name = "effect_input.virtual-surround-7.1-hesuvi"
14
media.class = Audio/Sink
15
audio.channels = 8
16
audio.position = [ FL FR FC LFE RL RR SL SR ]
17
}
18
playback.props = {
19
+ node.name = "effect_output.virtual-surround-7.1-hesuvi"
20
node.passive = true
21
audio.channels = 2
22
audio.position = [ FL FR ]
23
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/source-rnnoise.conf
Changed
23
1
2
3
{ name = libpipewire-module-filter-chain
4
args = {
5
- node.name = "effect_input.rnnoise"
6
node.description = "Noise Canceling source"
7
media.name = "Noise Canceling source"
8
filter.graph = {
9
10
}
11
]
12
}
13
+ audio.position = [ FL FR ]
14
capture.props = {
15
+ node.name = "effect_input.rnnoise"
16
node.passive = true
17
}
18
playback.props = {
19
+ node.name = "effect_output.rnnoise"
20
media.class = Audio/Source
21
}
22
}
23
pipewire-0.3.47.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/minimal.conf.in
Changed
75
1
2
#mem.mlock-all = false
3
#clock.power-of-two-quantum = true
4
#log.level = 2
5
- #cpu.zero.denormals = true
6
+ #cpu.zero.denormals = false
7
8
core.daemon = true # listening for socket connections
9
core.name = pipewire-0 # core name and socket name
10
11
#channelmix.mix-lfe = false
12
#channelmix.upmix = false
13
#channelmix.lfe-cutoff = 0
14
+ #channelmix.fc-cutoff = 0
15
+ #channelmix.rear-delay = 12.0
16
+ #channelmix.stereo-widen = 0.0
17
+ #channelmix.hilbert-taps = 0
18
channelmix.disable = true
19
#node.param.Props = {
20
# params = [
21
22
#channelmix.mix-lfe = false
23
#channelmix.upmix = false
24
#channelmix.lfe-cutoff = 0
25
+ #channelmix.fc-cutoff = 0
26
+ #channelmix.rear-delay = 12.0
27
+ #channelmix.stereo-widen = 0.0
28
+ #channelmix.hilbert-taps = 0
29
channelmix.disable = true
30
#node.param.Props = {
31
# params = [
32
33
#}
34
}
35
}
36
+ # This creates a new Source node. It will have input ports
37
+ # that you can link, to provide audio for this source.
38
+ #{ factory = adapter
39
+ # args = {
40
+ # factory.name = support.null-audio-sink
41
+ # node.name = "my-mic"
42
+ # node.description = "Microphone"
43
+ # media.class = "Audio/Source/Virtual"
44
+ # audio.position = "FL,FR"
45
+ # adapter.auto-port-config = {
46
+ # mode = dsp
47
+ # monitor = true
48
+ # position = preserve # unknown, aux, preserve
49
+ # }
50
+ # }
51
+ #}
52
+ # This creates a new link between the source and the virtual
53
+ # source ports.
54
+ #{ factory = link-factory
55
+ # args = {
56
+ # link.output.node = system
57
+ # link.output.port = capture_1
58
+ # link.input.node = my-mic
59
+ # link.input.port = input_FL
60
+ # link.passive = true
61
+ # }
62
+ #}
63
+ #{ factory = link-factory
64
+ # args = {
65
+ # link.output.node = system
66
+ # link.output.port = capture_2
67
+ # link.input.node = my-mic
68
+ # link.input.port = input_FR
69
+ # link.passive = true
70
+ # }
71
+ #}
72
]
73
74
context.exec = [
75
pipewire-0.3.47.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
12
1
2
#channelmix.mix-lfe = false
3
#channelmix.upmix = false
4
#channelmix.lfe-cutoff = 0
5
+ #channelmix.fc-cutoff = 0
6
+ #channelmix.rear-delay = 12.0
7
+ #channelmix.stereo-widen = 0.0
8
+ #channelmix.hilbert-taps = 0
9
}
10
11
# client/stream specific properties
12
pipewire-0.3.47.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/pipewire.conf.in
Changed
10
1
2
#mem.mlock-all = false
3
#clock.power-of-two-quantum = true
4
#log.level = 2
5
- #cpu.zero.denormals = true
6
+ #cpu.zero.denormals = false
7
8
core.daemon = true # listening for socket connections
9
core.name = pipewire-0 # core name and socket name
10
pipewire-0.3.47.tar.gz/src/modules/meson.build -> pipewire-0.3.48.tar.gz/src/modules/meson.build
Changed
18
1
2
'module-protocol-native/portal-screencast.c',
3
'module-protocol-native/protocol-native.c',
4
'module-protocol-native/v0/protocol-native.c',
5
+ 'module-protocol-native/protocol-footer.c',
6
'module-protocol-native/connection.c' ],
7
include_directories : [configinc],
8
install : true,
9
10
install : true,
11
install_dir : modules_install_dir,
12
install_rpath: modules_install_dir,
13
- dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, canberra_dep],
14
+ dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, xfixes_dep, canberra_dep],
15
)
16
endif
17
summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules')
18
pipewire-0.3.47.tar.gz/src/modules/module-client-device/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-device/protocol-native.c
Changed
10
1
2
3
#include <pipewire/extensions/protocol-native.h>
4
5
-#define MAX_DICT 256
6
+#define MAX_DICT 1024
7
#define MAX_PARAM_INFO 128
8
9
static inline void push_item(struct spa_pod_builder *b, const struct spa_dict_item *item)
10
pipewire-0.3.47.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/client-node.c
Changed
73
1
2
#include <spa/node/node.h>
3
#include <spa/node/utils.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/pod/parser.h>
7
#include <spa/debug/types.h>
8
9
10
{
11
struct node *this = object;
12
uint8_t buffer[1024];
13
- struct spa_pod_builder b = { 0 };
14
+ struct spa_pod_dynamic_builder b;
15
struct spa_result_node_params result;
16
uint32_t count = 0;
17
bool found = false;
18
19
if (result.index < start)
20
continue;
21
22
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
23
- if (spa_pod_filter(&b, &result.param, param, filter) != 0)
24
- continue;
25
-
26
- pw_log_debug("%p: %d param %u", this, seq, result.index);
27
- spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
28
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
29
+ if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
30
+ pw_log_debug("%p: %d param %u", this, seq, result.index);
31
+ spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
32
+ count++;
33
+ }
34
+ spa_pod_dynamic_builder_clean(&b);
35
36
- if (++count == num)
37
+ if (count == num)
38
break;
39
}
40
return found ? 0 : -ENOENT;
41
42
struct node *this = object;
43
struct port *port;
44
uint8_t buffer[1024];
45
- struct spa_pod_builder b = { 0 };
46
+ struct spa_pod_dynamic_builder b;
47
struct spa_result_node_params result;
48
uint32_t count = 0;
49
bool found = false;
50
51
if (result.index < start)
52
continue;
53
54
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
55
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
56
- continue;
57
-
58
- pw_log_debug("%p: %d param %u", this, seq, result.index);
59
- spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
60
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
61
+ if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
62
+ pw_log_debug("%p: %d param %u", this, seq, result.index);
63
+ spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
64
+ count++;
65
+ }
66
+ spa_pod_dynamic_builder_clean(&b);
67
68
- if (++count == num)
69
+ if (count == num)
70
break;
71
}
72
return found ? 0 : -ENOENT;
73
pipewire-0.3.47.tar.gz/src/modules/module-client-node/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/protocol-native.c
Changed
12
1
2
#include <pipewire/extensions/protocol-native.h>
3
#include <pipewire/extensions/client-node.h>
4
5
-#define MAX_DICT 256
6
-#define MAX_PARAMS 128
7
+#define MAX_DICT 1024
8
+#define MAX_PARAMS 4096
9
#define MAX_PARAM_INFO 128
10
#define MAX_BUFFERS 64
11
#define MAX_METAS 16u
12
pipewire-0.3.47.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/remote-node.c
Changed
79
1
2
#include <sys/mman.h>
3
4
#include <spa/pod/parser.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/node/utils.h>
7
#include <spa/utils/result.h>
8
#include <spa/debug/types.h>
9
10
if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) {
11
uint32_t i, idx, id;
12
uint8_t buf[4096];
13
- struct spa_pod_builder b = { 0 };
14
+ struct spa_pod_dynamic_builder b;
15
16
for (i = 0; i < node->info.n_params; i++) {
17
struct spa_pod *param;
18
19
continue;
20
21
for (idx = 0;;) {
22
- spa_pod_builder_init(&b, buf, sizeof(buf));
23
- if (spa_node_enum_params_sync(node->node,
24
- id, &idx,
25
- NULL, ¶m, &b) != 1)
26
- break;
27
+ spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 4096);
28
29
- params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
30
- params[n_params++] = spa_pod_copy(param);
31
+ res = spa_node_enum_params_sync(node->node,
32
+ id, &idx, NULL, ¶m, &b.b);
33
+ if (res == 1) {
34
+ params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
35
+ params[n_params++] = spa_pod_copy(param);
36
+ }
37
+ spa_pod_dynamic_builder_clean(&b);
38
+ if (res != 1)
39
+ break;
40
}
41
}
42
}
43
44
if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) {
45
uint32_t i, idx, id;
46
uint8_t buf[4096];
47
- struct spa_pod_builder b = { 0 };
48
+ struct spa_pod_dynamic_builder b;
49
50
for (i = 0; i < port->info.n_params; i++) {
51
struct spa_pod *param;
52
53
continue;
54
55
for (idx = 0;;) {
56
- spa_pod_builder_init(&b, buf, sizeof(buf));
57
- if (spa_node_port_enum_params_sync(port->node->node,
58
+ spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 4096);
59
+
60
+ res = spa_node_port_enum_params_sync(port->node->node,
61
port->direction, port->port_id,
62
- id, &idx,
63
- NULL, ¶m, &b) != 1)
64
+ id, &idx, NULL, ¶m, &b.b);
65
+ if (res == 1) {
66
+ params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
67
+ params[n_params++] = spa_pod_copy(param);
68
+ }
69
+ spa_pod_dynamic_builder_clean(&b);
70
+
71
+ if (res != 1)
72
break;
73
74
- params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
75
- params[n_params++] = spa_pod_copy(param);
76
}
77
}
78
}
79
pipewire-0.3.47.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.48.tar.gz/src/modules/module-echo-cancel.c
Changed
108
1
2
struct pw_context *context;
3
4
struct pw_impl_module *module;
5
- struct pw_work_queue *work;
6
struct spa_hook module_listener;
7
8
uint32_t id;
9
10
unsigned int sink_ready:1;
11
12
unsigned int do_disconnect:1;
13
- unsigned int unloading:1;
14
15
uint32_t max_buffer_size;
16
uint32_t buffer_delay;
17
18
struct spa_plugin_loader *loader;
19
};
20
21
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
22
-{
23
- struct impl *impl = data;
24
- pw_impl_module_destroy(impl->module);
25
-}
26
-static void unload_module(struct impl *impl)
27
-{
28
- if (!impl->unloading) {
29
- impl->unloading = true;
30
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
31
- }
32
-}
33
-
34
static void process(struct impl *impl)
35
{
36
struct pw_buffer *cout;
37
38
id, seq, res, spa_strerror(res), message);
39
40
if (id == PW_ID_CORE && res == -EPIPE)
41
- unload_module(impl);
42
+ pw_impl_module_schedule_destroy(impl->module);
43
}
44
45
static const struct pw_core_events core_events = {
46
47
struct impl *impl = d;
48
spa_hook_remove(&impl->core_listener);
49
impl->core = NULL;
50
- unload_module(impl);
51
+ pw_impl_module_schedule_destroy(impl->module);
52
}
53
54
static const struct pw_proxy_events core_proxy_events = {
55
56
pw_properties_free(impl->source_props);
57
pw_properties_free(impl->sink_props);
58
59
- if (impl->work)
60
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
61
-
62
for (i = 0; i < impl->info.channels; i++) {
63
if (impl->rec_buffer[i])
64
free(impl->rec_buffer[i]);
65
66
static void module_destroy(void *data)
67
{
68
struct impl *impl = data;
69
- impl->unloading = true;
70
spa_hook_remove(&impl->module_listener);
71
impl_destroy(impl);
72
}
73
74
impl->id = id;
75
impl->module = module;
76
impl->context = context;
77
- impl->work = pw_context_get_work_queue(context);
78
- if (impl->work == NULL) {
79
- res = -errno;
80
- pw_log_error( "can't create work queue: %m");
81
- goto error;
82
- }
83
84
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
85
pw_properties_setf(props, PW_KEY_NODE_GROUP, "echo-cancel-%u", id);
86
87
else
88
aec_props = pw_properties_new(NULL, NULL);
89
90
- if (spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info)) {
91
- pw_log_error("codec plugin %s create failed", impl->aec->name);
92
- res = -ENOENT;
93
- goto error;
94
- }
95
+ res = spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info);
96
97
pw_properties_free(aec_props);
98
99
+ if (res < 0) {
100
+ pw_log_error("codec plugin %s create failed: %s", impl->aec->name,
101
+ spa_strerror(res));
102
+ goto error;
103
+ }
104
+
105
if (impl->aec->latency) {
106
unsigned int num, denom, req_num, req_denom;
107
unsigned int factor = 0;
108
pipewire-0.3.47.tar.gz/src/modules/module-example-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-example-sink.c
Changed
13
1
2
impl->module = module;
3
impl->context = context;
4
impl->work = pw_context_get_work_queue(context);
5
- if (impl->work == NULL) {
6
- res = -errno;
7
- pw_log_error( "can't get work queue: %m");
8
- goto error;
9
- }
10
11
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
12
pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
13
pipewire-0.3.47.tar.gz/src/modules/module-example-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-example-source.c
Changed
13
1
2
impl->module = module;
3
impl->context = context;
4
impl->work = pw_context_get_work_queue(context);
5
- if (impl->work == NULL) {
6
- res = -errno;
7
- pw_log_error( "can't get work queue: %m");
8
- goto error;
9
- }
10
11
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
12
pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
13
pipewire-0.3.47.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.48.tar.gz/src/modules/module-filter-chain.c
Changed
460
1
2
#include <spa/utils/string.h>
3
#include <spa/utils/json.h>
4
#include <spa/param/profiler.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/debug/pod.h>
7
8
#include <pipewire/utils.h>
9
10
#include <pipewire/pipewire.h>
11
12
#define MAX_HNDL 64
13
-#define MAX_PORTS 64
14
-#define MAX_CONTROLS 256
15
#define MAX_SAMPLES 8192
16
17
static float silence_data[MAX_SAMPLES];
18
19
uint32_t n_output;
20
uint32_t n_control;
21
uint32_t n_notify;
22
- unsigned long input[MAX_PORTS];
23
- unsigned long output[MAX_PORTS];
24
- unsigned long control[MAX_PORTS];
25
- unsigned long notify[MAX_PORTS];
26
- float default_control[MAX_PORTS];
27
+ unsigned long *input;
28
+ unsigned long *output;
29
+ unsigned long *control;
30
+ unsigned long *notify;
31
+ float *default_control;
32
};
33
34
struct port {
35
36
char name[256];
37
char *config;
38
39
- struct port input_port[MAX_PORTS];
40
- struct port output_port[MAX_PORTS];
41
- struct port control_port[MAX_PORTS];
42
- struct port notify_port[MAX_PORTS];
43
+ struct port *input_port;
44
+ struct port *output_port;
45
+ struct port *control_port;
46
+ struct port *notify_port;
47
48
uint32_t n_hndl;
49
void *hndl[MAX_HNDL];
50
51
struct spa_list link_list;
52
53
uint32_t n_input;
54
- struct graph_port input[MAX_PORTS];
55
+ struct graph_port *input;
56
57
uint32_t n_output;
58
- struct graph_port output[MAX_PORTS];
59
+ struct graph_port *output;
60
61
uint32_t n_hndl;
62
- struct graph_hndl hndl[MAX_HNDL];
63
+ struct graph_hndl *hndl;
64
65
uint32_t n_control;
66
- struct port *control_port[MAX_CONTROLS];
67
+ struct port **control_port;
68
};
69
70
struct impl {
71
struct pw_context *context;
72
73
struct pw_impl_module *module;
74
- struct pw_work_queue *work;
75
76
struct spa_hook module_listener;
77
78
79
struct spa_audio_info_raw playback_info;
80
81
unsigned int do_disconnect:1;
82
- unsigned int unloading:1;
83
84
long unsigned rate;
85
86
struct graph graph;
87
};
88
89
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
90
-{
91
- struct impl *impl = data;
92
- pw_impl_module_destroy(impl->module);
93
-}
94
-static void unload_module(struct impl *impl)
95
-{
96
- if (!impl->unloading) {
97
- impl->unloading = true;
98
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
99
- }
100
-}
101
-
102
static void capture_destroy(void *d)
103
{
104
struct impl *impl = d;
105
106
.param_changed = param_changed
107
};
108
109
-static int builder_overflow(void *data, uint32_t size)
110
-{
111
- struct spa_pod_builder *b = data;
112
- b->size = SPA_ROUND_UP_N(size, 4096);
113
- if ((b->data = realloc(b->data, b->size)) == NULL)
114
- return -errno;
115
- return 0;
116
-}
117
-
118
-static const struct spa_pod_builder_callbacks builder_callbacks = {
119
- SPA_VERSION_POD_BUILDER_CALLBACKS,
120
- .overflow = builder_overflow
121
-};
122
-
123
static int setup_streams(struct impl *impl)
124
{
125
int res;
126
uint32_t i, n_params;
127
- const struct spa_pod *params[256];
128
- struct spa_pod_builder b;
129
+ uint32_t offsets[512];
130
+ const struct spa_pod *params[512];
131
+ struct spa_pod_dynamic_builder b;
132
struct graph *graph = &impl->graph;
133
134
impl->capture = pw_stream_new(impl->core,
135
136
&out_stream_events, impl);
137
138
n_params = 0;
139
- spa_pod_builder_init(&b, NULL, 0);
140
- spa_pod_builder_set_callbacks(&b, &builder_callbacks, &b);
141
+ spa_pod_dynamic_builder_init(&b, NULL, 0, 4096);
142
143
- params[n_params++] = spa_format_audio_raw_build(&b,
144
+ offsets[n_params++] = b.b.state.offset;
145
+ spa_format_audio_raw_build(&b.b,
146
SPA_PARAM_EnumFormat, &impl->capture_info);
147
148
- for (i = 0; i < graph->n_control; i++)
149
- params[n_params++] = get_prop_info(graph, &b, i);
150
+ for (i = 0; i < graph->n_control; i++) {
151
+ offsets[n_params++] = b.b.state.offset;
152
+ get_prop_info(graph, &b.b, i);
153
+ }
154
155
- params[n_params++] = get_props_param(graph, &b);
156
+ offsets[n_params++] = b.b.state.offset;
157
+ get_props_param(graph, &b.b);
158
+
159
+ for (i = 0; i < n_params; i++)
160
+ params[i] = spa_pod_builder_deref(&b.b, offsets[i]);
161
162
res = pw_stream_connect(impl->capture,
163
PW_DIRECTION_INPUT,
164
165
PW_STREAM_FLAG_MAP_BUFFERS |
166
PW_STREAM_FLAG_RT_PROCESS,
167
params, n_params);
168
- free(b.data);
169
+
170
+ spa_pod_dynamic_builder_clean(&b);
171
if (res < 0)
172
return res;
173
174
n_params = 0;
175
- spa_pod_builder_init(&b, NULL, 0);
176
- spa_pod_builder_set_callbacks(&b, &builder_callbacks, &b);
177
- params[n_params++] = spa_format_audio_raw_build(&b,
178
+ spa_pod_dynamic_builder_init(&b, NULL, 0, 4096);
179
+ params[n_params++] = spa_format_audio_raw_build(&b.b,
180
SPA_PARAM_EnumFormat, &impl->playback_info);
181
182
res = pw_stream_connect(impl->playback,
183
184
PW_STREAM_FLAG_RT_PROCESS |
185
PW_STREAM_FLAG_TRIGGER,
186
params, n_params);
187
- free(b.data);
188
+ spa_pod_dynamic_builder_clean(&b);
189
190
if (res < 0)
191
return res;
192
193
{
194
struct fc_plugin *pl = NULL;
195
struct plugin *hndl;
196
- int res = 0;
197
const struct spa_support *support;
198
uint32_t n_support;
199
200
201
pl = load_lv2_plugin(support, n_support, path, NULL);
202
}
203
#endif
204
+ else {
205
+ pl = NULL;
206
+ errno = EINVAL;
207
+ }
208
+
209
if (pl == NULL)
210
goto exit;
211
212
213
spa_list_append(&impl->plugin_list, &hndl->link);
214
215
return hndl;
216
-
217
exit:
218
- errno = -res;
219
return NULL;
220
}
221
222
223
224
spa_list_remove(&desc->link);
225
plugin_unref(desc->plugin);
226
+ free(desc->input);
227
+ free(desc->output);
228
+ free(desc->control);
229
+ free(desc->default_control);
230
+ free(desc->notify);
231
free(desc);
232
}
233
234
235
struct plugin *hndl;
236
struct descriptor *desc;
237
const struct fc_descriptor *d;
238
- uint32_t i;
239
+ uint32_t i, n_input, n_output, n_control, n_notify;
240
unsigned long p;
241
int res;
242
243
244
desc = calloc(1, sizeof(*desc));
245
desc->ref = 1;
246
desc->plugin = hndl;
247
+ spa_list_init(&desc->link);
248
249
if ((d = hndl->plugin->make_desc(hndl->plugin, label)) == NULL) {
250
pw_log_error("cannot find label %s", label);
251
252
desc->desc = d;
253
snprintf(desc->label, sizeof(desc->label), "%s", label);
254
255
+ n_input = n_output = n_control = n_notify = 0;
256
+ for (p = 0; p < d->n_ports; p++) {
257
+ struct fc_port *fp = &d->ports[p];
258
+ if (FC_IS_PORT_AUDIO(fp->flags)) {
259
+ if (FC_IS_PORT_INPUT(fp->flags))
260
+ n_input++;
261
+ else if (FC_IS_PORT_OUTPUT(fp->flags))
262
+ n_output++;
263
+ } else if (FC_IS_PORT_CONTROL(fp->flags)) {
264
+ if (FC_IS_PORT_INPUT(fp->flags))
265
+ n_control++;
266
+ else if (FC_IS_PORT_OUTPUT(fp->flags))
267
+ n_notify++;
268
+ }
269
+ }
270
+ desc->input = calloc(n_input, sizeof(unsigned long));
271
+ desc->output = calloc(n_output, sizeof(unsigned long));
272
+ desc->control = calloc(n_control, sizeof(unsigned long));
273
+ desc->default_control = calloc(n_control, sizeof(float));
274
+ desc->notify = calloc(n_notify, sizeof(unsigned long));
275
+
276
for (p = 0; p < d->n_ports; p++) {
277
struct fc_port *fp = &d->ports[p];
278
279
280
return desc;
281
282
exit:
283
- if (hndl != NULL)
284
- plugin_unref(hndl);
285
- free(desc);
286
+ descriptor_unref(desc);
287
errno = -res;
288
return NULL;
289
}
290
291
node->desc = desc;
292
snprintf(node->name, sizeof(node->name), "%s", name);
293
294
+ node->input_port = calloc(desc->n_input, sizeof(struct port));
295
+ node->output_port = calloc(desc->n_output, sizeof(struct port));
296
+ node->control_port = calloc(desc->n_control, sizeof(struct port));
297
+ node->notify_port = calloc(desc->n_notify, sizeof(struct port));
298
+
299
for (i = 0; i < desc->n_input; i++) {
300
struct port *port = &node->input_port[i];
301
port->node = node;
302
303
d->cleanup(node->hndl[i]);
304
}
305
descriptor_unref(node->desc);
306
+ free(node->input_port);
307
+ free(node->output_port);
308
+ free(node->control_port);
309
+ free(node->notify_port);
310
free(node);
311
}
312
313
314
struct port *port;
315
struct graph_port *gp;
316
struct graph_hndl *gh;
317
- uint32_t i, j, n_input, n_output, n_hndl = 0;
318
+ uint32_t i, j, n_nodes, n_input, n_output, n_control, n_hndl = 0;
319
int res;
320
unsigned long p;
321
struct descriptor *desc;
322
const struct fc_descriptor *d;
323
char v[256];
324
325
- graph->n_input = 0;
326
- graph->n_output = 0;
327
-
328
first = spa_list_first(&graph->node_list, struct node, link);
329
last = spa_list_last(&graph->node_list, struct node, link);
330
331
332
res = -EINVAL;
333
goto error;
334
}
335
+ if (n_hndl > MAX_HNDL) {
336
+ pw_log_error("too many channels");
337
+ res = -EINVAL;
338
+ goto error;
339
+ }
340
pw_log_info("using %d instances %d %d", n_hndl, n_input, n_output);
341
342
- /* now go over all nodes and create instances. We can also link
343
- * the control and notify ports already */
344
- graph->n_control = 0;
345
+ /* now go over all nodes and create instances. */
346
+ n_control = 0;
347
+ n_nodes = 0;
348
spa_list_for_each(node, &graph->node_list, link) {
349
float *sd = silence_data, *dd = discard_data;
350
351
352
if (d->activate)
353
d->activate(node->hndl[i]);
354
}
355
- /* collect all control ports on the graph */
356
- for (j = 0; j < desc->n_control; j++) {
357
- graph->control_port[graph->n_control] = &node->control_port[j];
358
- graph->n_control++;
359
- }
360
+ n_control += desc->n_control;
361
+ n_nodes++;
362
}
363
pw_log_info("suggested rate:%lu capture:%d playback:%d", impl->rate,
364
impl->capture_info.rate, impl->playback_info.rate);
365
366
if (impl->playback_info.rate == 0)
367
impl->playback_info.rate = impl->rate;
368
369
+ graph->n_input = 0;
370
+ graph->input = calloc(n_input * n_hndl, sizeof(struct graph_port));
371
+ graph->n_output = 0;
372
+ graph->output = calloc(n_output * n_hndl, sizeof(struct graph_port));
373
+
374
/* now collect all input and output ports for all the handles. */
375
for (i = 0; i < n_hndl; i++) {
376
if (inputs == NULL) {
377
378
379
/* order all nodes based on dependencies */
380
graph->n_hndl = 0;
381
+ graph->hndl = calloc(n_nodes * n_hndl, sizeof(struct graph_hndl));
382
+ graph->n_control = 0;
383
+ graph->control_port = calloc(n_control, sizeof(struct port *));
384
while (true) {
385
if ((node = find_next_node(graph)) == NULL)
386
break;
387
388
389
for (i = 0; i < desc->n_output; i++)
390
setup_output_port(graph, &node->output_port[i]);
391
+
392
+ /* collect all control ports on the graph */
393
+ for (i = 0; i < desc->n_control; i++) {
394
+ graph->control_port[graph->n_control] = &node->control_port[i];
395
+ graph->n_control++;
396
+ }
397
}
398
return 0;
399
400
401
link_free(link);
402
spa_list_consume(node, &graph->node_list, link)
403
node_free(node);
404
+ free(graph->input);
405
+ free(graph->output);
406
+ free(graph->hndl);
407
+ free(graph->control_port);
408
}
409
410
static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
411
412
id, seq, res, spa_strerror(res), message);
413
414
if (id == PW_ID_CORE && res == -EPIPE)
415
- unload_module(impl);
416
+ pw_impl_module_schedule_destroy(impl->module);
417
}
418
419
static const struct pw_core_events core_events = {
420
421
struct impl *impl = d;
422
spa_hook_remove(&impl->core_listener);
423
impl->core = NULL;
424
- unload_module(impl);
425
+ pw_impl_module_schedule_destroy(impl->module);
426
}
427
428
static const struct pw_proxy_events core_proxy_events = {
429
430
pw_core_disconnect(impl->core);
431
pw_properties_free(impl->capture_props);
432
pw_properties_free(impl->playback_props);
433
- if (impl->work)
434
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
435
graph_free(&impl->graph);
436
free(impl);
437
}
438
439
static void module_destroy(void *data)
440
{
441
struct impl *impl = data;
442
- impl->unloading = true;
443
spa_hook_remove(&impl->module_listener);
444
impl_destroy(impl);
445
}
446
447
448
impl->module = module;
449
impl->context = context;
450
- impl->work = pw_context_get_work_queue(context);
451
- if (impl->work == NULL) {
452
- res = -errno;
453
- pw_log_error( "can't create work queue: %m");
454
- goto error;
455
- }
456
+
457
impl->rate = 48000;
458
impl->graph.impl = impl;
459
spa_list_init(&impl->plugin_list);
460
pipewire-0.3.47.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.48.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
26
1
2
3
#include "config.h"
4
5
+#include <float.h>
6
#include <math.h>
7
#ifdef HAVE_SNDFILE
8
#include <sndfile.h>
9
10
y2 = y1;
11
y1 = y;
12
}
13
- bq->x1 = x1;
14
- bq->x2 = x2;
15
- bq->y1 = y1;
16
- bq->y2 = y2;
17
+#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
18
+ bq->x1 = F(x1);
19
+ bq->x2 = F(x2);
20
+ bq->y1 = F(y1);
21
+ bq->y2 = F(y2);
22
+#undef F
23
}
24
25
/** bq_lowpass */
26
pipewire-0.3.47.tar.gz/src/modules/module-link-factory.c -> pipewire-0.3.48.tar.gz/src/modules/module-link-factory.c
Changed
22
1
2
struct pw_context *context = pw_impl_module_get_context(module);
3
struct pw_impl_factory *factory;
4
struct factory_data *data;
5
- int res;
6
7
PW_LOG_TOPIC_INIT(mod_topic);
8
9
10
data->module = module;
11
data->context = context;
12
data->work = pw_context_get_work_queue(context);
13
- if (data->work == NULL) {
14
- res = -errno;
15
- pw_log_error( "can't get work queue: %m");
16
- pw_impl_factory_destroy(factory);
17
- return res;
18
- }
19
20
spa_list_init(&data->link_list);
21
22
pipewire-0.3.47.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.48.tar.gz/src/modules/module-loopback.c
Changed
79
1
2
struct pw_context *context;
3
4
struct pw_impl_module *module;
5
- struct pw_work_queue *work;
6
7
struct spa_hook module_listener;
8
9
10
struct spa_audio_info_raw playback_info;
11
12
unsigned int do_disconnect:1;
13
- unsigned int unloading:1;
14
};
15
16
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
17
-{
18
- struct impl *impl = data;
19
- pw_impl_module_destroy(impl->module);
20
-}
21
-static void unload_module(struct impl *impl)
22
-{
23
- if (!impl->unloading) {
24
- impl->unloading = true;
25
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
26
- }
27
-}
28
-
29
static void capture_destroy(void *d)
30
{
31
struct impl *impl = d;
32
33
id, seq, res, spa_strerror(res), message);
34
35
if (id == PW_ID_CORE && res == -EPIPE)
36
- unload_module(impl);
37
+ pw_impl_module_schedule_destroy(impl->module);
38
}
39
40
static const struct pw_core_events core_events = {
41
42
struct impl *impl = d;
43
spa_hook_remove(&impl->core_listener);
44
impl->core = NULL;
45
- unload_module(impl);
46
+ pw_impl_module_schedule_destroy(impl->module);
47
}
48
49
static const struct pw_proxy_events core_proxy_events = {
50
51
pw_core_disconnect(impl->core);
52
pw_properties_free(impl->capture_props);
53
pw_properties_free(impl->playback_props);
54
- if (impl->work)
55
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
56
free(impl);
57
}
58
59
static void module_destroy(void *data)
60
{
61
struct impl *impl = data;
62
- impl->unloading = true;
63
spa_hook_remove(&impl->module_listener);
64
impl_destroy(impl);
65
}
66
67
68
impl->module = module;
69
impl->context = context;
70
- impl->work = pw_context_get_work_queue(context);
71
- if (impl->work == NULL) {
72
- res = -errno;
73
- pw_log_error( "can't get work queue: %m");
74
- goto error;
75
- }
76
77
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
78
pw_properties_setf(props, PW_KEY_NODE_GROUP, "loopback-%u", id);
79
pipewire-0.3.47.tar.gz/src/modules/module-metadata/metadata.c -> pipewire-0.3.48.tar.gz/src/modules/module-metadata/metadata.c
Changed
28
1
2
struct pw_properties *properties)
3
{
4
struct impl *impl;
5
+ char serial_str[32];
6
+ struct spa_dict_item items[1] = {
7
+ SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
8
+ };
9
+ struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
10
+ static const char * const keys[] = {
11
+ PW_KEY_OBJECT_SERIAL,
12
+ NULL
13
+ };
14
15
if (properties == NULL)
16
properties = pw_properties_new(NULL, NULL);
17
18
impl->resource = resource;
19
impl->metadata = (struct pw_metadata*)resource;
20
21
+ spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
22
+ pw_global_get_serial(impl->global));
23
+ pw_global_update_keys(impl->global, &extra_props, keys);
24
+
25
pw_context_add_listener(context, &impl->context_listener,
26
&context_events, impl);
27
28
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native.c
Changed
141
1
2
3
#include "modules/module-protocol-native/connection.h"
4
#include "modules/module-protocol-native/defs.h"
5
+#include "modules/module-protocol-native/protocol-footer.h"
6
7
8
#define NAME "protocol-native"
9
10
11
int ref;
12
13
+ struct footer_core_global_state footer_state;
14
+
15
unsigned int connected:1;
16
unsigned int disconnecting:1;
17
unsigned int need_flush:1;
18
19
struct pw_protocol_native_connection *connection;
20
struct spa_hook conn_listener;
21
22
+ struct footer_client_global_state footer_state;
23
+
24
unsigned int busy:1;
25
unsigned int need_flush:1;
26
27
28
"%s: id:%d op:%d size:%d seq:%d", prefix,
29
msg->id, msg->opcode, msg->size, msg->seq);
30
31
- if ((pod = spa_pod_from_data(msg->data, msg->size, 0, msg->size)) != NULL)
32
+ if ((pod = get_first_pod_from_data(msg->data, msg->size, 0)) != NULL)
33
spa_debug_pod(0, NULL, pod);
34
else
35
hex = true;
36
37
spa_debug_mem(0, msg->data, msg->size);
38
}
39
40
+static void pre_demarshal(struct pw_protocol_native_connection *conn,
41
+ const struct pw_protocol_native_message *msg,
42
+ void *object, const struct footer_demarshal *opcodes, size_t n_opcodes)
43
+{
44
+ struct spa_pod *footer = NULL;
45
+ struct spa_pod_parser parser;
46
+ struct spa_pod_frame f[2];
47
+ uint32_t opcode;
48
+ int ret;
49
+
50
+ footer = pw_protocol_native_connection_get_footer(conn, msg);
51
+ if (footer == NULL)
52
+ return; /* No valid footer. Ignore silently. */
53
+
54
+ /*
55
+ * Version 3 footer
56
+ *
57
+ * spa_pod Struct { [Id opcode, Struct { ... }]* }
58
+ */
59
+
60
+ spa_pod_parser_pod(&parser, footer);
61
+ if (spa_pod_parser_push_struct(&parser, &f[0]) < 0) {
62
+ pw_log_error("malformed message footer");
63
+ return;
64
+ }
65
+
66
+ while (1) {
67
+ if (spa_pod_parser_get_id(&parser, &opcode) < 0)
68
+ break;
69
+ if (spa_pod_parser_push_struct(&parser, &f[1]) < 0)
70
+ break;
71
+ if (opcode < n_opcodes) {
72
+ if ((ret = opcodes[opcode].demarshal(object, &parser)) < 0)
73
+ pw_log_error("failed processing message footer (opcode %u): %d (%s)",
74
+ opcode, ret, spa_strerror(ret));
75
+ } else {
76
+ /* Ignore (don't log errors), in case we need to extend this later. */
77
+ pw_log_debug("unknown message footer opcode %u", opcode);
78
+ }
79
+ spa_pod_parser_pop(&parser, &f[1]);
80
+ }
81
+}
82
+
83
static int
84
process_messages(struct client_data *data)
85
{
86
87
if (debug_messages)
88
debug_msg("<<<<<< in", msg, false);
89
90
+ pre_demarshal(conn, msg, client, footer_client_demarshal,
91
+ SPA_N_ELEMENTS(footer_client_demarshal));
92
+
93
resource = pw_impl_client_find_resource(client, msg->id);
94
if (resource == NULL) {
95
pw_resource_errorf(client->core_resource,
96
97
if (debug_messages)
98
debug_msg("<<<<<< in", msg, false);
99
100
+ pre_demarshal(conn, msg, this, footer_core_demarshal,
101
+ SPA_N_ELEMENTS(footer_core_demarshal));
102
+
103
proxy = pw_core_find_proxy(this, msg->id);
104
if (proxy == NULL || proxy->zombie) {
105
if (proxy == NULL)
106
107
return pw_protocol_native_connection_get_fd(impl->connection, index);
108
}
109
110
+static void assert_single_pod(struct spa_pod_builder *builder)
111
+{
112
+ /*
113
+ * Check the invariant that the message we just marshaled
114
+ * consists of at most one POD.
115
+ */
116
+ struct spa_pod *pod = builder->data;
117
+ spa_assert(builder->data == NULL ||
118
+ builder->state.offset < sizeof(struct spa_pod) ||
119
+ builder->state.offset == SPA_POD_SIZE(pod));
120
+}
121
+
122
static int impl_ext_end_proxy(struct pw_proxy *proxy,
123
struct spa_pod_builder *builder)
124
{
125
struct pw_core *core = proxy->core;
126
struct client *impl = SPA_CONTAINER_OF(core->conn, struct client, this);
127
+ assert_single_pod(builder);
128
+ marshal_core_footers(&impl->footer_state, core, builder);
129
return core->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
130
}
131
132
133
{
134
struct client_data *data = resource->client->user_data;
135
struct pw_impl_client *client = resource->client;
136
+ assert_single_pod(builder);
137
+ marshal_client_footers(&data->footer_state, client, builder);
138
return client->send_seq = pw_protocol_native_connection_end(data->connection, builder);
139
}
140
static const struct pw_protocol_native_ext protocol_ext_impl = {
141
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/connection.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/connection.c
Changed
48
1
2
#include <spa/debug/pod.h>
3
4
#include "connection.h"
5
+#include "defs.h"
6
7
#define MAX_BUFFER_SIZE (1024 * 32)
8
#define MAX_FDS 1024u
9
10
return 1;
11
}
12
13
+/** Get footer data from the tail of the current packet.
14
+ *
15
+ * \param conn the connection
16
+ * \param msg current message
17
+ * \return footer POD, or NULL if no valid footer present
18
+ *
19
+ * \memberof pw_protocol_native_connection
20
+ */
21
+struct spa_pod *pw_protocol_native_connection_get_footer(struct pw_protocol_native_connection *conn,
22
+ const struct pw_protocol_native_message *msg)
23
+{
24
+ struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
25
+ struct spa_pod *pod;
26
+
27
+ if (impl->version != 3)
28
+ return NULL;
29
+
30
+ /*
31
+ * Protocol version 3 footer: a single SPA POD
32
+ */
33
+
34
+ /* Footer immediately follows the message POD, if it is present */
35
+ if ((pod = get_first_pod_from_data(msg->data, msg->size, 0)) == NULL)
36
+ return NULL;
37
+ pod = get_first_pod_from_data(msg->data, msg->size, SPA_POD_SIZE(pod));
38
+ if (pod == NULL)
39
+ return NULL;
40
+ pw_log_trace("connection %p: recv message footer, size:%zu",
41
+ conn, (size_t)SPA_POD_SIZE(pod));
42
+ return pod;
43
+}
44
+
45
static inline void *begin_write(struct pw_protocol_native_connection *conn, uint32_t size)
46
{
47
struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
48
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/connection.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/connection.h
Changed
11
1
2
void pw_protocol_native_connection_enter(struct pw_protocol_native_connection *conn);
3
void pw_protocol_native_connection_leave(struct pw_protocol_native_connection *conn);
4
5
+struct spa_pod *pw_protocol_native_connection_get_footer(struct pw_protocol_native_connection *conn,
6
+ const struct pw_protocol_native_message *msg);
7
+
8
#ifdef __cplusplus
9
} /* extern "C" */
10
#endif
11
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/defs.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/defs.h
Changed
16
1
2
const struct spa_dict *props,
3
void (*done_callback) (void *data, int res),
4
void *data);
5
+
6
+static inline void *get_first_pod_from_data(void *data, size_t maxsize, off_t offset)
7
+{
8
+ void *pod;
9
+ if (offset + sizeof(struct spa_pod) > maxsize)
10
+ return NULL;
11
+ pod = SPA_PTROFF(data, offset, void);
12
+ if (offset + SPA_POD_SIZE(pod) > maxsize)
13
+ return NULL;
14
+ return pod;
15
+}
16
pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-footer.c
Added
154
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2018 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <stdio.h>
27
+#include <errno.h>
28
+
29
+#include <spa/pod/builder.h>
30
+#include <spa/pod/parser.h>
31
+#include <spa/utils/result.h>
32
+
33
+#include <pipewire/private.h>
34
+
35
+#include "connection.h"
36
+#include "protocol-footer.h"
37
+#include "defs.h"
38
+
39
+PW_LOG_TOPIC_EXTERN(mod_topic);
40
+#define PW_LOG_TOPIC_DEFAULT mod_topic
41
+
42
+struct footer_builder {
43
+ struct spa_pod_builder *builder;
44
+ struct spa_pod_frame outer;
45
+ struct spa_pod_frame inner;
46
+ unsigned int started:1;
47
+};
48
+
49
+#define FOOTER_BUILDER_INIT(builder) (struct footer_builder) { builder }
50
+
51
+static void start_footer_entry(struct footer_builder *fb, uint32_t opcode)
52
+{
53
+ if (!fb->started) {
54
+ spa_pod_builder_push_struct(fb->builder, &fb->outer);
55
+ fb->started = true;
56
+ }
57
+
58
+ spa_pod_builder_id(fb->builder, opcode);
59
+ spa_pod_builder_push_struct(fb->builder, &fb->inner);
60
+}
61
+
62
+static void end_footer_entry(struct footer_builder *fb)
63
+{
64
+ spa_pod_builder_pop(fb->builder, &fb->inner);
65
+}
66
+
67
+static void end_footer(struct footer_builder *fb)
68
+{
69
+ if (!fb->started)
70
+ return;
71
+
72
+ spa_pod_builder_pop(fb->builder, &fb->outer);
73
+}
74
+
75
+void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core,
76
+ struct spa_pod_builder *builder)
77
+{
78
+ struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
79
+
80
+ if (core->recv_generation != state->last_recv_generation) {
81
+ state->last_recv_generation = core->recv_generation;
82
+
83
+ pw_log_trace("core %p: send client registry generation:%"PRIu64,
84
+ core, core->recv_generation);
85
+
86
+ start_footer_entry(&fb, FOOTER_CLIENT_OPCODE_GENERATION);
87
+ spa_pod_builder_long(fb.builder, core->recv_generation);
88
+ end_footer_entry(&fb);
89
+ }
90
+
91
+ end_footer(&fb);
92
+}
93
+
94
+void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client,
95
+ struct spa_pod_builder *builder)
96
+{
97
+ struct footer_builder fb = FOOTER_BUILDER_INIT(builder);
98
+
99
+ if (client->context->generation != client->sent_generation) {
100
+ client->sent_generation = client->context->generation;
101
+
102
+ pw_log_trace("impl-client %p: send server registry generation:%"PRIu64,
103
+ client, client->context->generation);
104
+
105
+ start_footer_entry(&fb, FOOTER_CORE_OPCODE_GENERATION);
106
+ spa_pod_builder_long(fb.builder, client->context->generation);
107
+ end_footer_entry(&fb);
108
+ }
109
+
110
+ end_footer(&fb);
111
+}
112
+
113
+int demarshal_core_generation(void *object, struct spa_pod_parser *parser)
114
+{
115
+ struct pw_core *core = object;
116
+ int64_t generation;
117
+
118
+ if (spa_pod_parser_get_long(parser, &generation) < 0)
119
+ return -EINVAL;
120
+
121
+ core->recv_generation = SPA_MAX(core->recv_generation,
122
+ (uint64_t)generation);
123
+
124
+ pw_log_trace("core %p: recv server registry generation:%"PRIu64,
125
+ core, generation);
126
+
127
+ return 0;
128
+}
129
+
130
+int demarshal_client_generation(void *object, struct spa_pod_parser *parser)
131
+{
132
+ struct pw_impl_client *client = object;
133
+ int64_t generation;
134
+
135
+ if (spa_pod_parser_get_long(parser, &generation) < 0)
136
+ return -EINVAL;
137
+
138
+ client->recv_generation = SPA_MAX(client->recv_generation,
139
+ (uint64_t)generation);
140
+
141
+ pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64,
142
+ client, generation);
143
+
144
+ return 0;
145
+}
146
+
147
+const struct footer_demarshal footer_core_demarshal[FOOTER_CORE_OPCODE_LAST] = {
148
+ [FOOTER_CORE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_core_generation },
149
+};
150
+
151
+const struct footer_demarshal footer_client_demarshal[FOOTER_CLIENT_OPCODE_LAST] = {
152
+ [FOOTER_CLIENT_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_client_generation },
153
+};
154
pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-footer.h
Added
61
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2018 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+/*
27
+ * Protocol footer.
28
+ *
29
+ * For passing around general state data that is not associated with
30
+ * messages sent to objects.
31
+ */
32
+
33
+enum {
34
+ FOOTER_CORE_OPCODE_GENERATION = 0,
35
+ FOOTER_CORE_OPCODE_LAST
36
+};
37
+
38
+enum {
39
+ FOOTER_CLIENT_OPCODE_GENERATION = 0,
40
+ FOOTER_CLIENT_OPCODE_LAST
41
+};
42
+
43
+struct footer_core_global_state {
44
+ uint64_t last_recv_generation;
45
+};
46
+
47
+struct footer_client_global_state {
48
+};
49
+
50
+struct footer_demarshal {
51
+ int (*demarshal)(void *object, struct spa_pod_parser *parser);
52
+};
53
+
54
+extern const struct footer_demarshal footer_core_demarshal[FOOTER_CORE_OPCODE_LAST];
55
+extern const struct footer_demarshal footer_client_demarshal[FOOTER_CLIENT_OPCODE_LAST];
56
+
57
+void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core,
58
+ struct spa_pod_builder *builder);
59
+void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client,
60
+ struct spa_pod_builder *builder);
61
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-native.c
Changed
13
1
2
3
#include "connection.h"
4
5
-#define MAX_DICT 256
6
+#define MAX_DICT 1024
7
#define MAX_PARAM_INFO 128
8
-#define MAX_PERMISSIONS 1024
9
+#define MAX_PERMISSIONS 4096
10
11
PW_LOG_TOPIC_EXTERN(mod_topic);
12
#define PW_LOG_TOPIC_DEFAULT mod_topic
13
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/collect.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/collect.c
Changed
17
1
2
{
3
struct spa_pod *copy = spa_pod_copy(p->param);
4
spa_pod_fixate(copy);
5
- format_parse_param(copy, &dev_info->ss, &dev_info->map,
6
+ format_parse_param(copy, true, &dev_info->ss, &dev_info->map,
7
&defs->sample_spec, &defs->channel_map);
8
free(copy);
9
break;
10
}
11
case SPA_PARAM_Format:
12
- format_parse_param(p->param, &dev_info->ss, &dev_info->map,
13
+ format_parse_param(p->param, true, &dev_info->ss, &dev_info->map,
14
NULL, NULL);
15
break;
16
17
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/defs.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/defs.h
Changed
8
1
2
#define METADATA_CONFIG_DEFAULT_SINK "default.configured.audio.sink"
3
#define METADATA_CONFIG_DEFAULT_SOURCE "default.configured.audio.source"
4
#define METADATA_TARGET_NODE "target.node"
5
+#define METADATA_TARGET_OBJECT "target.object"
6
7
#endif /* PULSE_SERVER_DEFS_H */
8
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c
Changed
12
1
2
if (name == NULL || name[0] == '\0')
3
return -EPROTO;
4
5
- f = open_memstream(&ptr, &size);
6
+ if ((f = open_memstream(&ptr, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
fprintf(f, " \"mute\": %s", mute ? "true" : "false");
11
if (vol.channels > 0) {
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/format.c
Changed
40
1
2
return res;
3
}
4
5
-int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map,
6
+int format_parse_param(const struct spa_pod *param, bool collect,
7
+ struct sample_spec *ss, struct channel_map *map,
8
const struct sample_spec *def_ss, const struct channel_map *def_map)
9
{
10
struct spa_audio_info info = { 0 };
11
12
{
13
struct spa_audio_info_iec958 iec;
14
15
+ if (collect)
16
+ break;
17
+
18
if (spa_format_audio_iec958_parse(param, &iec) < 0)
19
return -ENOTSUP;
20
21
info.info.raw.format = SPA_AUDIO_FORMAT_S16;
22
info.info.raw.rate = iec.rate;
23
+ info.info.raw.channels = 2;
24
+ info.info.raw.position[0] = SPA_AUDIO_CHANNEL_FL;
25
+ info.info.raw.position[1] = SPA_AUDIO_CHANNEL_FR;
26
break;
27
}
28
default:
29
30
size_t size;
31
FILE *f;
32
33
- f = open_memstream(&ptr, &size);
34
+ if ((f = open_memstream(&ptr, &size)) == NULL)
35
+ return -errno;
36
+
37
fprintf(f, "[");
38
for (i = 1; i < n_values; i++)
39
fprintf(f, "%s %d", i == 1 ? "" : ",", values[i]);
40
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/format.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/format.h
Changed
10
1
2
void channel_map_parse(const char *str, struct channel_map *map);
3
bool channel_map_valid(const struct channel_map *map);
4
5
-int format_parse_param(const struct spa_pod *param, struct sample_spec *ss,
6
+int format_parse_param(const struct spa_pod *param, bool collect, struct sample_spec *ss,
7
struct channel_map *map, const struct sample_spec *def_ss,
8
const struct channel_map *def_map);
9
10
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/message-handler.c
Changed
19
1
2
3
r = open_memstream(response, &size);
4
if (r == NULL)
5
- return -ENOMEM;
6
+ return -errno;
7
8
fputc('[', r);
9
for (i = 0; i < n_codecs; ++i) {
10
11
12
r = open_memstream(response, &size);
13
if (r == NULL)
14
- return -ENOMEM;
15
+ return -errno;
16
17
fputc('[', r);
18
spa_list_for_each(o, &m->object_list, link) {
19
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c
Changed
12
1
2
const char *str;
3
size_t size;
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
if ((str = pw_properties_get(module->props, "sink_name")) != NULL)
11
fprintf(f, " sink.name = \"%s\"", str);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
12
1
2
char *args;
3
size_t size;
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
/* Can't just serialise this dict because the "null" method gets
11
* interpreted as a JSON null */
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
12
1
2
pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
3
pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " filter.graph = {");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
12
1
2
pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
3
pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " filter.graph = {");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
12
1
2
pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
3
pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
if (data->info.channels != 0) {
11
fprintf(f, " audio.channels = %u", data->info.channels);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
13
1
2
if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
3
pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
4
5
- if ((str = pw_properties_get(props, "device.description")) != NULL) {
6
- pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
7
- pw_properties_set(props, "device.description", NULL);
8
- } else {
9
+ if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL) {
10
const char *name, *class;
11
12
name = pw_properties_get(props, PW_KEY_NODE_NAME);
13
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
12
1
2
pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
3
pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " capture.props = {");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
12
1
2
pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
3
pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " capture.props = { ");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
12
1
2
pw_properties_setf(data->sink_props, "pulse.module.id",
3
"%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &data->roc_props->dict, 0);
11
fprintf(f, " } sink.props = {");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
12
1
2
pw_properties_setf(data->source_props, "pulse.module.id",
3
"%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &data->roc_props->dict, 0);
11
fprintf(f, " } source.props = {");
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c
Changed
12
1
2
uint32_t i;
3
FILE *f;
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
if (data->info.rate != 0)
11
fprintf(f, " \"audio.rate\": %u,", data->info.rate);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
12
1
2
pw_properties_setf(data->stream_props, "pulse.module.id",
3
"%u", module->index);
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " pulse.server.address = \"%s\" ", server);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
12
1
2
3
server = pw_properties_get(module->props, "server");
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
fprintf(f, " pulse.server.address = \"%s\" ", server);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c
Changed
12
1
2
const char *str;
3
size_t size;
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL)
7
+ return -errno;
8
+
9
fprintf(f, "{");
10
if ((str = pw_properties_get(module->props, "sink")) != NULL)
11
fprintf(f, " sink.name = \"%s\"", str);
12
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/operation.c
Changed
30
1
2
free(o);
3
}
4
5
+struct operation *operation_find(struct client *client, uint32_t tag)
6
+{
7
+ struct operation *o;
8
+ spa_list_for_each(o, &client->operations, link) {
9
+ if (o->tag == tag)
10
+ return o;
11
+ }
12
+ return NULL;
13
+}
14
+
15
void operation_complete(struct operation *o)
16
{
17
struct client *client = o->client;
18
19
pw_log_info("[%s]: tag:%u complete", client->name, o->tag);
20
21
+ spa_list_remove(&o->link);
22
+
23
if (o->callback)
24
o->callback(o->data, client, o->tag);
25
else
26
reply_simple_ack(client, o->tag);
27
- operation_free(o);
28
+ free(o);
29
}
30
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/operation.h
Changed
9
1
2
int operation_new_cb(struct client *client, uint32_t tag,
3
void (*callback) (void *data, struct client *client, uint32_t tag),
4
void *data);
5
+struct operation *operation_find(struct client *client, uint32_t tag);
6
void operation_free(struct operation *o);
7
void operation_complete(struct operation *o);
8
9
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pending-sample.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pending-sample.c
Changed
24
1
2
#include "client.h"
3
#include "internal.h"
4
#include "log.h"
5
+#include "operation.h"
6
#include "pending-sample.h"
7
#include "sample-play.h"
8
9
10
{
11
struct client * const client = ps->client;
12
struct impl * const impl = client->impl;
13
+ struct operation *o;
14
15
spa_list_remove(&ps->link);
16
spa_hook_remove(&ps->listener);
17
pw_work_queue_cancel(impl->work_queue, ps, SPA_ID_INVALID);
18
19
+ if ((o = operation_find(client, ps->tag)) != NULL)
20
+ operation_free(o);
21
+
22
sample_play_destroy(ps->play);
23
}
24
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pending-sample.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pending-sample.h
Changed
10
1
2
struct sample_play *play;
3
struct spa_hook listener;
4
uint32_t tag;
5
+ unsigned ready:1;
6
+ unsigned done:1;
7
};
8
9
void pending_sample_free(struct pending_sample *ps);
10
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
221
1
2
reply_set_client_name(client, client->connect_tag);
3
client->connect_tag = SPA_ID_INVALID;
4
}
5
+
6
+ client->ref++;
7
spa_list_consume(o, &client->operations, link)
8
operation_complete(o);
9
+ client_unref(client);
10
}
11
12
static struct stream *find_stream(struct client *client, uint32_t index)
13
14
{
15
struct spa_fraction lat;
16
uint64_t lat_usec;
17
- struct spa_dict_item items[5];
18
- char latency[32];
19
+ struct spa_dict_item items[6];
20
+ char latency[32], rate[32];
21
char attr_maxlength[32];
22
char attr_tlength[32];
23
char attr_prebuf[32];
24
25
lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
26
27
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
28
+ snprintf(rate, sizeof(rate), "1/%u", lat.denom);
29
snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength);
30
snprintf(attr_tlength, sizeof(attr_tlength), "%u", s->attr.tlength);
31
snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", s->attr.prebuf);
32
snprintf(attr_minreq, sizeof(attr_minreq), "%u", s->attr.minreq);
33
34
items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency);
35
- items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
36
- items[2] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength);
37
- items[3] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf);
38
- items[4] = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq);
39
- pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 5));
40
+ items[1] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate);
41
+ items[2] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
42
+ items[3] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength);
43
+ items[4] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf);
44
+ items[5] = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq);
45
+ pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 6));
46
47
if (s->attr.prebuf > 0)
48
s->in_prebuf = true;
49
50
51
static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr)
52
{
53
- struct spa_dict_item items[3];
54
- char latency[32];
55
+ struct spa_dict_item items[4];
56
+ char latency[32], rate[32];
57
char attr_maxlength[32];
58
char attr_fragsize[32];
59
struct spa_fraction lat;
60
61
lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
62
63
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
64
+ snprintf(rate, sizeof(rate), "1/%u", lat.denom);
65
66
snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength);
67
snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", s->attr.fragsize);
68
69
items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency);
70
- items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
71
- items[2] = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize);
72
- pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 3));
73
+ items[1] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate);
74
+ items[2] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
75
+ items[3] = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize);
76
+ pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 4));
77
78
return lat_usec;
79
}
80
81
stream->killed = true;
82
destroy_stream = true;
83
break;
84
- case PW_STREAM_STATE_CONNECTING:
85
case PW_STREAM_STATE_PAUSED:
86
+ stream->id = pw_stream_get_node_id(stream->stream);
87
+ break;
88
+ case PW_STREAM_STATE_CONNECTING:
89
case PW_STREAM_STATE_STREAMING:
90
break;
91
}
92
93
if (id != SPA_PARAM_Format || param == NULL)
94
return;
95
96
- if ((res = format_parse_param(param, &stream->ss, &stream->map, NULL, NULL)) < 0) {
97
+ if ((res = format_parse_param(param, false, &stream->ss, &stream->map, NULL, NULL)) < 0) {
98
pw_stream_set_error(stream->stream, res, "format not supported");
99
return;
100
}
101
102
103
if (stream->create_tag != SPA_ID_INVALID) {
104
struct pw_manager_object *peer;
105
- stream->id = pw_stream_get_node_id(stream->stream);
106
107
if (stream->volume_set) {
108
pw_stream_set_control(stream->stream,
109
110
n_valid_formats++;
111
}
112
}
113
- if (n_params < MAX_FORMATS &&
114
+ else if (n_params < MAX_FORMATS &&
115
(params[n_params] = format_build_param(&b,
116
SPA_PARAM_EnumFormat, &ss,
117
ss.channels > 0 ? &map : NULL)) != NULL) {
118
119
return o;
120
}
121
122
+static void sample_play_finish(struct pending_sample *ps)
123
+{
124
+ struct client *client = ps->client;
125
+ pending_sample_free(ps);
126
+ client_unref(client);
127
+}
128
+
129
static void sample_play_ready_reply(void *data, struct client *client, uint32_t tag)
130
{
131
struct pending_sample *ps = data;
132
133
pw_log_info("[%s] PLAY_SAMPLE tag:%u index:%u",
134
client->name, ps->tag, index);
135
136
+ ps->ready = true;
137
+
138
reply = reply_new(client, ps->tag);
139
if (client->version >= 13)
140
message_put(reply,
141
142
TAG_INVALID);
143
144
client_queue_message(client, reply);
145
+
146
+ if (ps->done)
147
+ sample_play_finish(ps);
148
}
149
150
static void sample_play_ready(void *data, uint32_t id)
151
152
static void on_sample_done(void *obj, void *data, int res, uint32_t id)
153
{
154
struct pending_sample *ps = obj;
155
- struct client *client = ps->client;
156
-
157
- pending_sample_free(ps);
158
- client_unref(client);
159
+ ps->done = true;
160
+ if (ps->ready)
161
+ sample_play_finish(ps);
162
}
163
164
static void sample_play_done(void *data, int res)
165
166
struct pw_manager_object *o, *dev, *dev_default;
167
uint32_t index, index_device;
168
int target_id;
169
+ int64_t target_serial;
170
const char *name_device;
171
+ struct pw_node_info *info;
172
struct selector sel;
173
int res;
174
bool sink = command == COMMAND_MOVE_SINK_INPUT;
175
176
if (o == NULL)
177
return -ENOENT;
178
179
+ info = o->info;
180
+ if (info == NULL || info->props == NULL)
181
+ return -EINVAL;
182
+ if (spa_atob(spa_dict_lookup(info->props, PW_KEY_NODE_DONT_RECONNECT)))
183
+ return -EINVAL;
184
+
185
if ((dev = find_device(client, index_device, name_device, sink, NULL)) == NULL)
186
return -ENOENT;
187
188
189
* forgetting target.node. Follow that behavior here.
190
*/
191
target_id = -1;
192
+ target_serial = -1;
193
} else {
194
target_id = dev->id;
195
+ target_serial = dev->serial;
196
}
197
198
if ((res = pw_manager_set_metadata(manager, client->metadata_default,
199
200
SPA_TYPE_INFO_BASE"Id", "%d", target_id)) < 0)
201
return res;
202
203
+ if ((res = pw_manager_set_metadata(manager, client->metadata_default,
204
+ o->id,
205
+ METADATA_TARGET_OBJECT,
206
+ SPA_TYPE_INFO_BASE"Id", "%"PRIi64, target_serial)) < 0)
207
+ return res;
208
+
209
return reply_simple_ack(client, tag);
210
}
211
212
213
impl->props = props;
214
215
impl->work_queue = pw_context_get_work_queue(context);
216
- if (impl->work_queue == NULL)
217
- goto error_free;
218
219
spa_list_init(&impl->servers);
220
impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
221
pipewire-0.3.47.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-simple.c
Changed
12
1
2
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
3
4
impl->work_queue = pw_context_get_work_queue(context);
5
- if (impl->work_queue == NULL) {
6
- res = -errno;
7
- goto error_free;
8
- }
9
10
if ((res = parse_params(impl)) < 0)
11
goto error_free;
12
pipewire-0.3.47.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.48.tar.gz/src/modules/module-pulse-tunnel.c
Changed
98
1
2
3
#include <pipewire/impl.h>
4
#include <pipewire/i18n.h>
5
+#include <pipewire/private.h>
6
7
#include <pulse/pulseaudio.h>
8
#include "module-protocol-pulse/format.h"
9
10
struct pw_properties *props;
11
12
struct pw_impl_module *module;
13
- struct pw_work_queue *work;
14
15
struct spa_hook module_listener;
16
17
18
pa_stream *pa_stream;
19
20
unsigned int do_disconnect:1;
21
- unsigned int unloading:1;
22
};
23
24
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
25
-{
26
- struct impl *impl = data;
27
- pw_impl_module_destroy(impl->module);
28
-}
29
-
30
-static void unload_module(struct impl *impl)
31
-{
32
- if (!impl->unloading) {
33
- impl->unloading = true;
34
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
35
- }
36
-}
37
-
38
static void cork_stream(struct impl *impl, bool cork)
39
{
40
pa_operation *operation;
41
42
switch (state) {
43
case PW_STREAM_STATE_ERROR:
44
case PW_STREAM_STATE_UNCONNECTED:
45
- unload_module(impl);
46
+ pw_impl_module_schedule_destroy(impl->module);
47
break;
48
case PW_STREAM_STATE_PAUSED:
49
cork_stream(impl, true);
50
51
id, seq, res, spa_strerror(res), message);
52
53
if (id == PW_ID_CORE && res == -EPIPE)
54
- unload_module(impl);
55
+ pw_impl_module_schedule_destroy(impl->module);
56
}
57
58
static const struct pw_core_events core_events = {
59
60
struct impl *impl = d;
61
spa_hook_remove(&impl->core_listener);
62
impl->core = NULL;
63
- unload_module(impl);
64
+ pw_impl_module_schedule_destroy(impl->module);
65
}
66
67
static const struct pw_proxy_events core_proxy_events = {
68
69
pw_properties_free(impl->stream_props);
70
pw_properties_free(impl->props);
71
72
- if (impl->work)
73
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
74
free(impl->buffer);
75
free(impl);
76
}
77
78
static void module_destroy(void *data)
79
{
80
struct impl *impl = data;
81
- impl->unloading = true;
82
spa_hook_remove(&impl->module_listener);
83
impl_destroy(impl);
84
}
85
86
87
impl->module = module;
88
impl->context = context;
89
- impl->work = pw_context_get_work_queue(context);
90
- if (impl->work == NULL) {
91
- res = -errno;
92
- pw_log_error( "can't get work queue: %m");
93
- goto error;
94
- }
95
96
spa_ringbuffer_init(&impl->ring);
97
impl->buffer = calloc(1, RINGBUFFER_SIZE);
98
pipewire-0.3.47.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop-discover.c
Changed
90
1
2
3
struct pw_impl_module *module;
4
struct spa_hook module_listener;
5
- struct pw_work_queue *work;
6
7
struct pw_properties *properties;
8
9
10
AvahiServiceBrowser *sink_browser;
11
12
struct spa_list tunnel_list;
13
-
14
- unsigned int unloading:1;
15
};
16
17
struct tunnel_info {
18
19
20
static int start_client(struct impl *impl);
21
22
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
23
-{
24
- struct impl *impl = data;
25
- pw_impl_module_destroy(impl->module);
26
-}
27
-
28
-static void unload_module(struct impl *impl)
29
-{
30
- if (!impl->unloading) {
31
- impl->unloading = true;
32
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
33
- }
34
-}
35
-
36
static struct tunnel *make_tunnel(struct impl *impl, const struct tunnel_info *info)
37
{
38
struct tunnel *t;
39
40
if (impl->avahi_poll)
41
pw_avahi_poll_free(impl->avahi_poll);
42
pw_properties_free(impl->properties);
43
- if (impl->work)
44
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
45
free(impl);
46
}
47
48
49
}
50
51
52
- f = open_memstream(&args, &size);
53
+ if ((f = open_memstream(&args, &size)) == NULL) {
54
+ pw_log_error("Can't open memstream: %m");
55
+ goto done;
56
+ }
57
+
58
fprintf(f, "{");
59
pw_properties_serialize_dict(f, &props->dict, 0);
60
fprintf(f, " stream.props = {");
61
62
}
63
return;
64
error:
65
- unload_module(impl);
66
+ pw_impl_module_schedule_destroy(impl->module);
67
}
68
69
static int start_client(struct impl *impl)
70
71
client_callback, impl,
72
&res)) == NULL) {
73
pw_log_error("can't create client: %s", avahi_strerror(res));
74
- unload_module(impl);
75
+ pw_impl_module_schedule_destroy(impl->module);
76
return -EIO;
77
}
78
return 0;
79
80
impl->context = context;
81
impl->properties = props;
82
83
- impl->work = pw_context_get_work_queue(context);
84
- if (impl->work == NULL)
85
- goto error_errno;
86
-
87
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
88
89
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
90
pipewire-0.3.47.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop-sink.c
Changed
126
1
2
3
#include <pipewire/impl.h>
4
#include <pipewire/i18n.h>
5
+#include <pipewire/private.h>
6
7
#include "module-raop/rtsp-client.h"
8
9
10
11
struct pw_impl_module *module;
12
struct pw_loop *loop;
13
- struct pw_work_queue *work;
14
15
struct spa_hook module_listener;
16
17
18
char *password;
19
20
unsigned int do_disconnect:1;
21
- unsigned int unloading:1;
22
23
uint8_t key[AES_CHUNK_SIZE]; /* Key for aes-cbc */
24
uint8_t iv[AES_CHUNK_SIZE]; /* Initialization vector for cbc */
25
26
uint32_t filled;
27
};
28
29
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
30
-{
31
- struct impl *impl = data;
32
- pw_impl_module_destroy(impl->module);
33
-}
34
-
35
-static void unload_module(struct impl *impl)
36
-{
37
- if (!impl->unloading) {
38
- impl->unloading = true;
39
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
40
- }
41
-}
42
-
43
static void stream_destroy(void *d)
44
{
45
struct impl *impl = d;
46
47
48
received = ntp_now(CLOCK_MONOTONIC);
49
bytes = read(impl->timing_fd, packet, sizeof(packet));
50
+ if (bytes < 0) {
51
+ pw_log_debug("error reading timing packet: %m");
52
+ return;
53
+ }
54
if (bytes != sizeof(packet)) {
55
pw_log_warn("discarding short (%zd < %zd) timing packet",
56
bytes, sizeof(bytes));
57
58
uint32_t hdr;
59
uint16_t seq, num;
60
61
- bytes = read(impl->timing_fd, packet, sizeof(packet));
62
+ bytes = read(impl->control_fd, packet, sizeof(packet));
63
+ if (bytes < 0) {
64
+ pw_log_debug("error reading control packet: %m");
65
+ return;
66
+ }
67
if (bytes != sizeof(packet)) {
68
pw_log_warn("discarding short (%zd < %zd) control packet",
69
bytes, sizeof(bytes));
70
71
switch (state) {
72
case PW_STREAM_STATE_ERROR:
73
case PW_STREAM_STATE_UNCONNECTED:
74
- unload_module(impl);
75
+ pw_impl_module_schedule_destroy(impl->module);
76
break;
77
case PW_STREAM_STATE_PAUSED:
78
rtsp_do_flush(impl);
79
80
id, seq, res, spa_strerror(res), message);
81
82
if (id == PW_ID_CORE && res == -EPIPE)
83
- unload_module(impl);
84
+ pw_impl_module_schedule_destroy(impl->module);
85
}
86
87
static const struct pw_core_events core_events = {
88
89
struct impl *impl = d;
90
spa_hook_remove(&impl->core_listener);
91
impl->core = NULL;
92
- unload_module(impl);
93
+ pw_impl_module_schedule_destroy(impl->module);
94
}
95
96
static const struct pw_proxy_events core_proxy_events = {
97
98
pw_properties_free(impl->stream_props);
99
pw_properties_free(impl->props);
100
free(impl->password);
101
- if (impl->work)
102
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
103
free(impl);
104
}
105
106
static void module_destroy(void *data)
107
{
108
struct impl *impl = data;
109
- impl->unloading = true;
110
spa_hook_remove(&impl->module_listener);
111
impl_destroy(impl);
112
}
113
114
impl->module = module;
115
impl->context = context;
116
impl->loop = pw_context_get_main_loop(context);
117
- impl->work = pw_context_get_work_queue(context);
118
- if (impl->work == NULL) {
119
- res = -errno;
120
- pw_log_error( "can't get work queue: %m");
121
- goto error;
122
- }
123
124
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
125
pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
126
pipewire-0.3.47.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
11
1
2
struct message *msg;
3
int cseq;
4
5
- f = open_memstream((char**)&msg, &len);
6
+ if ((f = open_memstream((char**)&msg, &len)) == NULL)
7
+ return -errno;
8
9
fseek(f, sizeof(*msg), SEEK_SET);
10
11
pipewire-0.3.47.tar.gz/src/modules/module-roc-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-roc-sink.c
Changed
95
1
2
3
struct module_roc_sink_data {
4
struct pw_impl_module *module;
5
- struct pw_work_queue *work;
6
struct spa_hook module_listener;
7
struct pw_properties *props;
8
struct pw_context *module_context;
9
10
struct pw_properties *capture_props;
11
12
unsigned int do_disconnect:1;
13
- unsigned int unloading:1;
14
15
roc_address local_addr;
16
roc_address remote_source_addr;
17
18
int remote_repair_port;
19
};
20
21
-static void do_unload_module(void *obj, void *d, int res, uint32_t id)
22
-{
23
- struct module_roc_sink_data *data = d;
24
- pw_impl_module_destroy(data->module);
25
-}
26
-
27
-static void unload_module(struct module_roc_sink_data *data)
28
-{
29
- if (!data->unloading) {
30
- data->unloading = true;
31
- pw_work_queue_add(data->work, data, 0, do_unload_module, data);
32
- }
33
-}
34
-
35
static void stream_destroy(void *d)
36
{
37
struct module_roc_sink_data *data = d;
38
39
id, seq, res, spa_strerror(res), message);
40
41
if (id == PW_ID_CORE && res == -EPIPE)
42
- unload_module(data);
43
+ pw_impl_module_schedule_destroy(data->module);
44
}
45
46
static const struct pw_core_events core_events = {
47
48
switch (state) {
49
case PW_STREAM_STATE_UNCONNECTED:
50
pw_log_info("stream disconnected, unloading");
51
- unload_module(data);
52
+ pw_impl_module_schedule_destroy(data->module);
53
break;
54
case PW_STREAM_STATE_ERROR:
55
pw_log_error("stream error: %s", error);
56
57
struct module_roc_sink_data *data = d;
58
spa_hook_remove(&data->core_listener);
59
data->core = NULL;
60
- unload_module(data);
61
+ pw_impl_module_schedule_destroy(data->module);
62
}
63
64
static const struct pw_proxy_events core_proxy_events = {
65
66
pw_properties_free(data->capture_props);
67
pw_properties_free(data->props);
68
69
- if (data->work)
70
- pw_work_queue_cancel(data->work, data, SPA_ID_INVALID);
71
if (data->sender)
72
roc_sender_close(data->sender);
73
if (data->context)
74
75
static void module_destroy(void *d)
76
{
77
struct module_roc_sink_data *data = d;
78
- data->unloading = true;
79
spa_hook_remove(&data->module_listener);
80
impl_destroy(data);
81
}
82
83
84
data->module = module;
85
data->module_context = context;
86
- data->work = pw_context_get_work_queue(context);
87
- if (data->work == NULL) {
88
- res = -errno;
89
- pw_log_error( "can't get work queue: %m");
90
- goto out;
91
- }
92
93
if ((str = pw_properties_get(props, "sink.name")) != NULL) {
94
pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
95
pipewire-0.3.47.tar.gz/src/modules/module-roc-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-roc-source.c
Changed
104
1
2
3
struct module_roc_source_data {
4
struct pw_impl_module *module;
5
- struct pw_work_queue *work;
6
struct spa_hook module_listener;
7
struct pw_properties *props;
8
struct pw_context *module_context;
9
10
struct pw_properties *playback_props;
11
12
unsigned int do_disconnect:1;
13
- unsigned int unloading:1;
14
15
roc_address local_addr;
16
roc_address local_source_addr;
17
18
int sess_latency_msec;
19
};
20
21
-static void do_unload_module(void *obj, void *d, int res, uint32_t id)
22
-{
23
- struct module_roc_source_data *data = d;
24
- pw_impl_module_destroy(data->module);
25
-}
26
-
27
-static void unload_module(struct module_roc_source_data *data)
28
-{
29
- if (!data->unloading) {
30
- data->unloading = true;
31
- pw_work_queue_add(data->work, data, 0, do_unload_module, data);
32
- }
33
-}
34
-
35
static void stream_destroy(void *d)
36
{
37
struct module_roc_source_data *data = d;
38
39
if (roc_receiver_read(impl->receiver, &frame) != 0) {
40
/* Handle EOF and error */
41
pw_log_error("Failed to read from roc source");
42
- unload_module(data);
43
+ pw_impl_module_schedule_destroy(impl->module);
44
return;
45
}
46
47
48
id, seq, res, spa_strerror(res), message);
49
50
if (id == PW_ID_CORE && res == -EPIPE)
51
- unload_module(data);
52
+ pw_impl_module_schedule_destroy(data->module);
53
}
54
55
static const struct pw_core_events core_events = {
56
57
switch (state) {
58
case PW_STREAM_STATE_UNCONNECTED:
59
pw_log_info("stream disconnected, unloading");
60
- unload_module(data);
61
+ pw_impl_module_schedule_destroy(data->module);
62
break;
63
case PW_STREAM_STATE_ERROR:
64
pw_log_error("stream error: %s", error);
65
66
struct module_roc_source_data *data = d;
67
spa_hook_remove(&data->core_listener);
68
data->core = NULL;
69
- unload_module(data);
70
+ pw_impl_module_schedule_destroy(data->module);
71
}
72
73
static const struct pw_proxy_events core_proxy_events = {
74
75
pw_properties_free(data->playback_props);
76
pw_properties_free(data->props);
77
78
- if (data->work)
79
- pw_work_queue_cancel(data->work, data, SPA_ID_INVALID);
80
if (data->receiver)
81
roc_receiver_close(data->receiver);
82
if (data->context)
83
84
static void module_destroy(void *d)
85
{
86
struct module_roc_source_data *data = d;
87
- data->unloading = true;
88
spa_hook_remove(&data->module_listener);
89
impl_destroy(data);
90
}
91
92
93
data->module = module;
94
data->module_context = context;
95
- data->work = pw_context_get_work_queue(context);
96
- if (data->work == NULL) {
97
- res = -errno;
98
- pw_log_error( "can't get work queue: %m");
99
- goto out;
100
- }
101
102
if ((str = pw_properties_get(props, "source.name")) != NULL) {
103
pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
104
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint-link.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint-link.c
Changed
28
1
2
struct pw_properties *properties)
3
{
4
struct impl *impl;
5
+ char serial_str[32];
6
+ struct spa_dict_item items[1] = {
7
+ SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
8
+ };
9
+ struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
10
+ static const char * const keys[] = {
11
+ PW_KEY_OBJECT_SERIAL,
12
+ NULL
13
+ };
14
15
impl = calloc(1, sizeof(*impl));
16
if (impl == NULL) {
17
18
}
19
impl->resource = resource;
20
21
+ spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
22
+ pw_global_get_serial(impl->global));
23
+ pw_global_update_keys(impl->global, &extra_props, keys);
24
+
25
spa_list_init(&impl->cached_params);
26
27
/* handle destroy events */
28
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint-stream.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint-stream.c
Changed
28
1
2
struct pw_properties *properties)
3
{
4
struct impl *impl;
5
+ char serial_str[32];
6
+ struct spa_dict_item items[1] = {
7
+ SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
8
+ };
9
+ struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
10
+ static const char * const keys[] = {
11
+ PW_KEY_OBJECT_SERIAL,
12
+ NULL
13
+ };
14
15
impl = calloc(1, sizeof(*impl));
16
if (impl == NULL) {
17
18
}
19
impl->resource = resource;
20
21
+ spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
22
+ pw_global_get_serial(impl->global));
23
+ pw_global_update_keys(impl->global, &extra_props, keys);
24
+
25
spa_list_init(&impl->cached_params);
26
27
/* handle destroy events */
28
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint.c
Changed
28
1
2
struct pw_properties *properties)
3
{
4
struct impl *impl;
5
+ char serial_str[32];
6
+ struct spa_dict_item items[1] = {
7
+ SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
8
+ };
9
+ struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
10
+ static const char * const keys[] = {
11
+ PW_KEY_OBJECT_SERIAL,
12
+ NULL
13
+ };
14
15
impl = calloc(1, sizeof(*impl));
16
if (impl == NULL) {
17
18
}
19
impl->resource = resource;
20
21
+ spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
22
+ pw_global_get_serial(impl->global));
23
+ pw_global_update_keys(impl->global, &extra_props, keys);
24
+
25
spa_list_init(&impl->cached_params);
26
27
/* handle destroy events */
28
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/protocol-native.c
Changed
12
1
2
#include <pipewire/extensions/session-manager.h>
3
#include <pipewire/extensions/protocol-native.h>
4
5
-#define MAX_DICT 256
6
-#define MAX_PARAMS 128
7
+#define MAX_DICT 1024
8
+#define MAX_PARAMS 4096
9
#define MAX_PARAM_INFO 128
10
11
static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict)
12
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/session.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/session.c
Changed
28
1
2
struct pw_properties *properties)
3
{
4
struct impl *impl;
5
+ char serial_str[32];
6
+ struct spa_dict_item items[1] = {
7
+ SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str),
8
+ };
9
+ struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items);
10
+ static const char * const keys[] = {
11
+ PW_KEY_OBJECT_SERIAL,
12
+ NULL
13
+ };
14
15
impl = calloc(1, sizeof(*impl));
16
if (impl == NULL) {
17
18
}
19
impl->resource = resource;
20
21
+ spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64,
22
+ pw_global_get_serial(impl->global));
23
+ pw_global_update_keys(impl->global, &extra_props, keys);
24
+
25
spa_list_init(&impl->cached_params);
26
27
/* handle destroy events */
28
pipewire-0.3.47.tar.gz/src/modules/module-x11-bell.c -> pipewire-0.3.48.tar.gz/src/modules/module-x11-bell.c
Changed
297
1
2
#include <X11/Xlib-xcb.h>
3
#include <X11/XKBlib.h>
4
5
+#ifdef HAVE_XFIXES_6
6
+#include <X11/extensions/Xfixes.h>
7
+#endif
8
+
9
#include <canberra.h>
10
11
-#include "pipewire/pipewire.h"
12
-#include "pipewire/impl.h"
13
+#include <pipewire/pipewire.h>
14
+#include <pipewire/impl.h>
15
+#include <pipewire/private.h>
16
17
/** \page page_module_x11_bell PipeWire Module: X11 Bell
18
*
19
20
struct impl {
21
struct pw_context *context;
22
struct pw_thread_loop *thread_loop;
23
+ struct pw_loop *thread_loop_loop;
24
struct pw_loop *loop;
25
struct spa_source *source;
26
27
struct pw_properties *properties;
28
29
+ struct pw_impl_module *module;
30
struct spa_hook module_listener;
31
32
Display *display;
33
- int xkb_event_base;
34
};
35
36
-static int play_sample(struct impl *impl, const char *sample)
37
+static int play_sample(struct impl *impl)
38
{
39
- int res;
40
+ const char *sample = NULL;
41
ca_context *ca;
42
+ int res;
43
+
44
+ if (impl->properties)
45
+ sample = pw_properties_get(impl->properties, "sample.name");
46
+ if (sample == NULL)
47
+ sample = "bell-window-system";
48
+
49
+ pw_log_debug("play sample %s", sample);
50
51
if ((res = ca_context_create(&ca)) < 0) {
52
pw_log_error("canberra context create error: %s", ca_strerror(res));
53
54
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
55
NULL)) < 0) {
56
pw_log_warn("can't play sample (%s): %s", sample, ca_strerror(res));
57
+ res = -EIO;
58
+ goto exit_destroy;
59
}
60
61
exit_destroy:
62
63
exit:
64
return res;
65
}
66
+
67
+static int do_play_sample(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data)
68
+{
69
+ play_sample(user_data);
70
+ return 0;
71
+}
72
+
73
static void display_io(void *data, int fd, uint32_t mask)
74
{
75
struct impl *impl = data;
76
XEvent e;
77
- const char *sample = NULL;
78
79
while (XPending(impl->display)) {
80
XNextEvent(impl->display, &e);
81
82
if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify)
83
continue;
84
85
- if (impl->properties)
86
- sample = pw_properties_get(impl->properties, "sample.name");
87
- if (sample == NULL)
88
- sample = "bell-window-system";
89
-
90
- pw_log_debug("play sample %s", sample);
91
- play_sample(impl, sample);
92
+ pw_loop_invoke(impl->thread_loop_loop, do_play_sample, 0, NULL, 0, false, impl);
93
}
94
}
95
96
-static void x11_close(struct impl *impl)
97
+#ifdef HAVE_XSETIOERROREXITHANDLER
98
+static void x11_io_error_exit_handler(Display *display, void *data)
99
{
100
- if (impl->source) {
101
- pw_loop_destroy_source(impl->loop, impl->source);
102
- impl->source = NULL;
103
- }
104
- if (impl->display) {
105
- XCloseDisplay(impl->display);
106
- impl->display = NULL;
107
- }
108
+ struct impl *impl = data;
109
+
110
+ spa_assert(display == impl->display);
111
+
112
+ pw_log_warn("X11 display (%s) has encountered a fatal I/O error", DisplayString(display));
113
+
114
+ pw_loop_destroy_source(impl->loop, impl->source);
115
+ impl->source = NULL;
116
+
117
+ pw_impl_module_schedule_destroy(impl->module);
118
}
119
+#endif
120
121
static int x11_connect(struct impl *impl, const char *name)
122
{
123
- int res, major, minor;
124
+ int major, minor;
125
unsigned int auto_ctrls, auto_values;
126
127
if (!(impl->display = XOpenDisplay(name))) {
128
- pw_log_warn("XOpenDisplay() failed");
129
- res = -EIO;
130
- goto error;
131
+ pw_log_error("XOpenDisplay() failed");
132
+ return -EIO;
133
}
134
135
impl->source = pw_loop_add_io(impl->loop,
136
ConnectionNumber(impl->display),
137
SPA_IO_IN, false, display_io, impl);
138
+ if (!impl->source)
139
+ return -errno;
140
+
141
+#ifdef HAVE_XSETIOERROREXITHANDLER
142
+ XSetIOErrorExitHandler(impl->display, x11_io_error_exit_handler, impl);
143
+#endif
144
+
145
+#ifdef HAVE_XFIXES_6
146
+ XFixesSetClientDisconnectMode(impl->display, XFixesClientDisconnectFlagTerminate);
147
+#endif
148
149
major = XkbMajorVersion;
150
minor = XkbMinorVersion;
151
152
if (!XkbLibraryVersion(&major, &minor)) {
153
- pw_log_warn("XkbLibraryVersion() failed");
154
- res = -EIO;
155
- goto error;
156
+ pw_log_error("XkbLibraryVersion() failed");
157
+ return -EIO;
158
}
159
160
major = XkbMajorVersion;
161
minor = XkbMinorVersion;
162
163
- if (!XkbQueryExtension(impl->display, NULL, &impl->xkb_event_base,
164
- NULL, &major, &minor)) {
165
- res = -EIO;
166
- pw_log_warn("XkbQueryExtension() failed");
167
- goto error;
168
+ if (!XkbQueryExtension(impl->display, NULL, NULL, NULL, &major, &minor)) {
169
+ pw_log_error("XkbQueryExtension() failed");
170
+ return -EIO;
171
}
172
173
XkbSelectEvents(impl->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask);
174
175
XkbSetAutoResetControls(impl->display, XkbAudibleBellMask, &auto_ctrls, &auto_values);
176
XkbChangeEnabledControls(impl->display, XkbUseCoreKbd, XkbAudibleBellMask, 0);
177
178
- res = 0;
179
-error:
180
- if (res < 0)
181
- x11_close(impl);
182
- return res;
183
+ return 0;
184
}
185
186
static void module_destroy(void *data)
187
{
188
struct impl *impl = data;
189
190
- spa_hook_remove(&impl->module_listener);
191
+ if (impl->module)
192
+ spa_hook_remove(&impl->module_listener);
193
194
- if (impl->thread_loop)
195
- pw_thread_loop_lock(impl->thread_loop);
196
+ if (impl->source)
197
+ pw_loop_destroy_source(impl->loop, impl->source);
198
199
- x11_close(impl);
200
+ if (impl->display)
201
+ XCloseDisplay(impl->display);
202
203
- if (impl->thread_loop) {
204
- pw_thread_loop_unlock(impl->thread_loop);
205
+ if (impl->thread_loop)
206
pw_thread_loop_destroy(impl->thread_loop);
207
- }
208
209
pw_properties_free(impl->properties);
210
211
212
pw_log_debug("module %p: new", impl);
213
214
impl->context = context;
215
+ impl->loop = pw_context_get_main_loop(context);
216
+
217
impl->thread_loop = pw_thread_loop_new("X11 Bell", NULL);
218
if (impl->thread_loop == NULL) {
219
res = -errno;
220
pw_log_error("can't create thread loop: %m");
221
goto error;
222
}
223
- impl->loop = pw_thread_loop_get_loop(impl->thread_loop);
224
+ impl->thread_loop_loop = pw_thread_loop_get_loop(impl->thread_loop);
225
impl->properties = args ? pw_properties_new_string(args) : NULL;
226
227
+ impl->module = module;
228
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
229
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_x11_bell_info));
230
231
232
* to pipewire eventually and will then block the mainloop. */
233
pw_thread_loop_start(impl->thread_loop);
234
235
- pw_thread_loop_lock(impl->thread_loop);
236
- x11_connect(impl, name);
237
- pw_thread_loop_unlock(impl->thread_loop);
238
+ res = x11_connect(impl, name);
239
+ if (res < 0)
240
+ goto error;
241
242
return 0;
243
error:
244
245
return res;
246
247
}
248
+
249
+static int x11_error_handler(Display *display, XErrorEvent *error)
250
+{
251
+ pw_log_warn("X11 error handler called on display %s with error %d",
252
+ DisplayString(display), error->error_code);
253
+ return 0;
254
+}
255
+
256
+static int x11_io_error_handler(Display *display)
257
+{
258
+ pw_log_warn("X11 I/O error handler called on display %s", DisplayString(display));
259
+ return 0;
260
+}
261
+
262
+__attribute__((constructor))
263
+static void set_x11_handlers(void)
264
+{
265
+ {
266
+ XErrorHandler prev = XSetErrorHandler(NULL);
267
+ XErrorHandler def = XSetErrorHandler(x11_error_handler);
268
+
269
+ if (prev != def)
270
+ XSetErrorHandler(prev);
271
+ }
272
+
273
+ {
274
+ XIOErrorHandler prev = XSetIOErrorHandler(NULL);
275
+ XIOErrorHandler def = XSetIOErrorHandler(x11_io_error_handler);
276
+
277
+ if (prev != def)
278
+ XSetIOErrorHandler(prev);
279
+ }
280
+}
281
+
282
+__attribute__((destructor))
283
+static void restore_x11_handlers(void)
284
+{
285
+ {
286
+ XErrorHandler prev = XSetErrorHandler(NULL);
287
+ if (prev != x11_error_handler)
288
+ XSetErrorHandler(prev);
289
+ }
290
+
291
+ {
292
+ XIOErrorHandler prev = XSetIOErrorHandler(NULL);
293
+ if (prev != x11_io_error_handler)
294
+ XSetIOErrorHandler(prev);
295
+ }
296
+}
297
pipewire-0.3.47.tar.gz/src/modules/module-zeroconf-discover.c -> pipewire-0.3.48.tar.gz/src/modules/module-zeroconf-discover.c
Changed
90
1
2
3
struct pw_impl_module *module;
4
struct spa_hook module_listener;
5
- struct pw_work_queue *work;
6
7
struct pw_properties *properties;
8
9
10
AvahiServiceBrowser *source_browser;
11
12
struct spa_list tunnel_list;
13
-
14
- unsigned int unloading:1;
15
};
16
17
struct tunnel_info {
18
19
20
static int start_client(struct impl *impl);
21
22
-static void do_unload_module(void *obj, void *data, int res, uint32_t id)
23
-{
24
- struct impl *impl = data;
25
- pw_impl_module_destroy(impl->module);
26
-}
27
-
28
-static void unload_module(struct impl *impl)
29
-{
30
- if (!impl->unloading) {
31
- impl->unloading = true;
32
- pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl);
33
- }
34
-}
35
-
36
static struct tunnel *make_tunnel(struct impl *impl, const struct tunnel_info *info)
37
{
38
struct tunnel *t;
39
40
if (impl->avahi_poll)
41
pw_avahi_poll_free(impl->avahi_poll);
42
pw_properties_free(impl->properties);
43
- if (impl->work)
44
- pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID);
45
free(impl);
46
}
47
48
49
_("%s on %s"), desc, fqdn);
50
}
51
52
- f = open_memstream(&args, &size);
53
+ if ((f = open_memstream(&args, &size)) == NULL) {
54
+ pw_log_error("Can't open memstream: %m");
55
+ goto done;
56
+ }
57
+
58
fprintf(f, "{");
59
pw_properties_serialize_dict(f, &props->dict, 0);
60
fprintf(f, " stream.props = {");
61
62
}
63
return;
64
error:
65
- unload_module(impl);
66
+ pw_impl_module_schedule_destroy(impl->module);
67
}
68
69
static int start_client(struct impl *impl)
70
71
client_callback, impl,
72
&res)) == NULL) {
73
pw_log_error("can't create client: %s", avahi_strerror(res));
74
- unload_module(impl);
75
+ pw_impl_module_schedule_destroy(impl->module);
76
return -EIO;
77
}
78
return 0;
79
80
impl->context = context;
81
impl->properties = props;
82
83
- impl->work = pw_context_get_work_queue(context);
84
- if (impl->work == NULL)
85
- goto error_errno;
86
-
87
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
88
89
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
90
pipewire-0.3.47.tar.gz/src/pipewire/conf.c -> pipewire-0.3.48.tar.gz/src/pipewire/conf.c
Changed
45
1
2
struct pw_properties *conf, const char *section)
3
{
4
struct data data = { .context = context };
5
+ int res;
6
7
if (spa_streq(section, "context.spa-libs"))
8
- pw_context_conf_section_for_each(context, section,
9
+ res = pw_context_conf_section_for_each(context, section,
10
parse_spa_libs, &data);
11
else if (spa_streq(section, "context.modules"))
12
- pw_context_conf_section_for_each(context, section,
13
+ res = pw_context_conf_section_for_each(context, section,
14
parse_modules, &data);
15
else if (spa_streq(section, "context.objects"))
16
- pw_context_conf_section_for_each(context, section,
17
+ res = pw_context_conf_section_for_each(context, section,
18
parse_objects, &data);
19
else if (spa_streq(section, "context.exec"))
20
- pw_context_conf_section_for_each(context, section,
21
+ res = pw_context_conf_section_for_each(context, section,
22
parse_exec, &data);
23
else
24
- data.count = -EINVAL;
25
+ res = -EINVAL;
26
27
- return data.count;
28
+ return res == 0 ? data.count : res;
29
}
30
31
static int update_props(void *user_data, const char *location, const char *key,
32
33
const char *section, struct pw_properties *props)
34
{
35
struct data data = { .context = context, .props = props };
36
- pw_context_conf_section_for_each(context, section,
37
+ int res;
38
+ res = pw_context_conf_section_for_each(context, section,
39
update_props, &data);
40
- return data.count;
41
+ return res == 0 ? data.count : res;
42
}
43
44
struct match {
45
pipewire-0.3.47.tar.gz/src/pipewire/context.c -> pipewire-0.3.48.tar.gz/src/pipewire/context.c
Changed
66
1
2
impl);
3
}
4
5
+static int do_data_loop_setup(struct spa_loop *loop, bool async, uint32_t seq,
6
+ const void *data, size_t size, void *user_data)
7
+{
8
+ struct pw_context *this = user_data;
9
+ const char *str;
10
+ struct spa_cpu *cpu;
11
+
12
+ cpu = spa_support_find(this->support, this->n_support, SPA_TYPE_INTERFACE_CPU);
13
+
14
+ if ((str = pw_properties_get(this->properties, SPA_KEY_CPU_ZERO_DENORMALS)) != NULL &&
15
+ cpu != NULL) {
16
+ pw_log_info("setting zero denormals: %s", str);
17
+ spa_cpu_zero_denormals(cpu, spa_atob(str));
18
+ }
19
+ return 0;
20
+}
21
22
/** Create a new context object
23
*
24
25
if (pw_properties_get(properties, PW_KEY_CPU_MAX_ALIGN) == NULL)
26
pw_properties_setf(properties, PW_KEY_CPU_MAX_ALIGN,
27
"%u", spa_cpu_get_max_align(cpu));
28
- if ((str = pw_properties_get(properties, SPA_KEY_CPU_ZERO_DENORMALS)) == NULL)
29
- str = "true";
30
- spa_cpu_zero_denormals(cpu, spa_atob(str));
31
}
32
33
if (getenv("PIPEWIRE_DEBUG") == NULL &&
34
35
this->data_system = this->data_loop->system;
36
this->main_loop = main_loop;
37
38
+ this->work_queue = pw_work_queue_new(this->main_loop);
39
+ if (this->work_queue == NULL) {
40
+ res = -errno;
41
+ goto error_free;
42
+ }
43
+
44
init_plugin_loader(impl);
45
46
this->support[n_support++] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_System, this->main_loop->system);
47
48
if ((res = pw_data_loop_start(this->data_loop_impl)) < 0)
49
goto error_free;
50
51
+ pw_data_loop_invoke(this->data_loop_impl,
52
+ do_data_loop_setup, 0, NULL, 0, false, this);
53
+
54
context_set_freewheel(this, false);
55
56
pw_settings_expose(this);
57
58
SPA_EXPORT
59
struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context)
60
{
61
- if (context->work_queue == NULL)
62
- context->work_queue = pw_work_queue_new(context->main_loop);
63
return context->work_queue;
64
}
65
66
pipewire-0.3.47.tar.gz/src/pipewire/filter.c -> pipewire-0.3.48.tar.gz/src/pipewire/filter.c
Changed
70
1
2
#include <spa/utils/ringbuffer.h>
3
#include <spa/utils/string.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/debug/format.h>
7
#include <spa/debug/types.h>
8
#include <spa/debug/pod.h>
9
10
uint32_t change_mask_all;
11
struct spa_node_info info;
12
struct spa_list param_list;
13
-#define IDX_Props 0
14
-#define IDX_ProcessLatency 1
15
-#define N_NODE_PARAMS 2
16
+#define IDX_PropInfo 0
17
+#define IDX_Props 1
18
+#define IDX_ProcessLatency 2
19
+#define N_NODE_PARAMS 3
20
struct spa_param_info params[N_NODE_PARAMS];
21
22
struct spa_process_latency_info process_latency;
23
24
static int get_param_index(uint32_t id)
25
{
26
switch (id) {
27
+ case SPA_PARAM_PropInfo:
28
+ return IDX_PropInfo;
29
case SPA_PARAM_Props:
30
return IDX_Props;
31
case SPA_PARAM_ProcessLatency:
32
33
{
34
struct spa_result_node_params result;
35
uint8_t buffer[1024];
36
- struct spa_pod_builder b = { 0 };
37
+ struct spa_pod_dynamic_builder b;
38
uint32_t count = 0;
39
struct param *p;
40
bool found = false;
41
42
43
found = true;
44
45
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
46
- if (spa_pod_filter(&b, &result.param, param, filter) != 0)
47
- continue;
48
-
49
- spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
50
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
51
+ if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
52
+ spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
53
+ count++;
54
+ }
55
+ spa_pod_dynamic_builder_clean(&b);
56
57
- if (++count == num)
58
+ if (count == num)
59
break;
60
}
61
return found ? 0 : -ENOENT;
62
63
impl->info.max_output_ports = UINT32_MAX;
64
impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0;
65
impl->info.props = &filter->properties->dict;
66
+ impl->params[IDX_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
67
impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
68
impl->params[IDX_ProcessLatency] = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0);
69
impl->info.params = impl->params;
70
pipewire-0.3.47.tar.gz/src/pipewire/global.c -> pipewire-0.3.48.tar.gz/src/pipewire/global.c
Changed
60
1
2
{
3
struct pw_resource *registry;
4
struct pw_context *context = global->context;
5
+ struct pw_impl_client *client;
6
7
if (global->registered)
8
return -EEXIST;
9
10
spa_list_append(&context->global_list, &global->link);
11
global->registered = true;
12
13
+ global->generation = ++context->generation;
14
+
15
spa_list_for_each(registry, &context->registry_resource_list, link) {
16
uint32_t permissions = pw_global_get_permissions(global, registry->client);
17
- pw_log_debug("registry %p: global %d %08x serial:%"PRIu64,
18
- registry, global->id, permissions, global->serial);
19
+ pw_log_debug("registry %p: global %d %08x serial:%"PRIu64" generation:%"PRIu64,
20
+ registry, global->id, permissions, global->serial, global->generation);
21
if (PW_PERM_IS_R(permissions))
22
pw_registry_resource_global(registry,
23
global->id,
24
25
&global->properties->dict);
26
}
27
28
+ /* Ensure a message is sent also to clients without registries, to force
29
+ * generation number update. */
30
+ spa_list_for_each(client, &context->client_list, link) {
31
+ uint32_t permissions;
32
+
33
+ if (client->sent_generation >= context->generation)
34
+ continue;
35
+ if (!client->core_resource)
36
+ continue;
37
+
38
+ permissions = pw_global_get_permissions(global, client);
39
+ if (PW_PERM_IS_R(permissions)) {
40
+ pw_log_debug("impl-client %p: (no registry) global %d %08x serial:%"PRIu64
41
+ " generation:%"PRIu64, client, global->id, permissions, global->serial,
42
+ global->generation);
43
+ pw_core_resource_done(client->core_resource, global->id, 0);
44
+ }
45
+ }
46
+
47
pw_log_debug("%p: registered %u", global, global->id);
48
pw_context_emit_global_added(context, global);
49
50
51
}
52
else if (do_show) {
53
pw_log_debug("client %p: resource %p show global %d serial:%"PRIu64,
54
- client, resource, global->id,
55
- global->serial);
56
+ client, resource, global->id, global->serial);
57
pw_registry_resource_global(resource,
58
global->id,
59
new_permissions,
60
pipewire-0.3.47.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-client.c
Changed
30
1
2
pw_global_update_keys(client->global, client->info.props, keys);
3
pw_global_register(client->global);
4
5
+#ifdef OLD_MEDIA_SESSION_WORKAROUND
6
+ /*
7
+ * XXX: temporary workaround for pipewire-media-session, see #2159
8
+ */
9
+ if (spa_streq(spa_dict_lookup(client->info.props, PW_KEY_APP_NAME),
10
+ "pipewire-media-session")) {
11
+ client->recv_generation = UINT64_MAX;
12
+ pw_log_info("impl-client %p: enable old pipewire-media-session workaround",
13
+ client);
14
+ }
15
+#endif
16
+
17
return 0;
18
}
19
20
21
if ((global = pw_context_find_global(context, global_id)) == NULL)
22
return -ENOENT;
23
24
+ if (client->recv_generation != 0 && global->generation > client->recv_generation)
25
+ return -ESTALE;
26
+
27
perms = pw_global_get_permissions(global, client);
28
if ((perms & permissions) != permissions)
29
return -EPERM;
30
pipewire-0.3.47.tar.gz/src/pipewire/impl-core.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-core.c
Changed
48
1
2
if (!PW_PERM_IS_R(permissions))
3
goto error_no_id;
4
5
+ if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation)
6
+ goto error_stale_id;
7
+
8
if (!spa_streq(global->type, type))
9
goto error_wrong_interface;
10
11
12
13
return NULL;
14
15
+error_stale_id:
16
+ pw_log_debug("registry %p: not binding stale global "
17
+ "id %u to %u, generation:%"PRIu64" recv-generation:%"PRIu64,
18
+ resource, id, new_id, global->generation, resource->client->recv_generation);
19
+ pw_resource_errorf_id(resource, new_id, -ESTALE, "no global %u any more", id);
20
+ goto error_exit_clean;
21
error_no_id:
22
pw_log_debug("registry %p: no global with id %u to bind to %u", resource, id, new_id);
23
pw_resource_errorf_id(resource, new_id, -ENOENT, "no global %u", id);
24
25
if (!PW_PERM_IS_R(permissions))
26
goto error_no_id;
27
28
+ if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation)
29
+ goto error_stale_id;
30
+
31
if (id == PW_ID_CORE || !PW_PERM_IS_X(permissions))
32
goto error_not_allowed;
33
34
35
pw_global_destroy(global);
36
return 0;
37
38
+error_stale_id:
39
+ pw_log_debug("registry %p: not destroying stale global "
40
+ "id %u, generation:%"PRIu64" recv-generation:%"PRIu64,
41
+ resource, id, global->generation, resource->client->recv_generation);
42
+ pw_resource_errorf(resource, -ESTALE, "no global %u any more", id);
43
+ res = -ESTALE;
44
+ goto error_exit;
45
error_no_id:
46
pw_log_debug("registry %p: no global with id %u to destroy", resource, id);
47
pw_resource_errorf(resource, -ENOENT, "no global %u", id);
48
pipewire-0.3.47.tar.gz/src/pipewire/impl-device.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-device.c
Changed
41
1
2
#include <spa/debug/types.h>
3
#include <spa/monitor/utils.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/utils/string.h>
7
8
#include "pipewire/impl.h"
9
10
if (pi->user == 1) {
11
struct pw_param *p;
12
uint8_t buffer[4096];
13
- struct spa_pod_builder b = { 0 };
14
+ struct spa_pod_dynamic_builder b;
15
struct spa_result_device_params result;
16
uint32_t count = 0;
17
18
19
if (result.index < index)
20
continue;
21
22
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
23
- if (spa_pod_filter(&b, &result.param, p->param, filter) != 0)
24
- continue;
25
-
26
- pw_log_debug("%p: %d param %u", device, seq, result.index);
27
- result_device_params(&user_data, seq, 0, SPA_RESULT_TYPE_DEVICE_PARAMS, &result);
28
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
29
+ if (spa_pod_filter(&b.b, &result.param, p->param, filter) == 0) {
30
+ pw_log_debug("%p: %d param %u", device, seq, result.index);
31
+ result_device_params(&user_data, seq, 0, SPA_RESULT_TYPE_DEVICE_PARAMS, &result);
32
+ count++;
33
+ }
34
+ spa_pod_dynamic_builder_clean(&b);
35
36
- if (++count == max)
37
+ if (count == max)
38
break;
39
}
40
res = 0;
41
pipewire-0.3.47.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-link.c
Changed
21
1
2
this->user_data = SPA_PTROFF(impl, sizeof(struct impl), void);
3
4
impl->work = pw_context_get_work_queue(context);
5
- if (impl->work == NULL)
6
- goto error_work_queue;
7
8
this->context = context;
9
this->properties = properties;
10
11
res = -errno;
12
pw_log_debug("alloc failed: %m");
13
goto error_exit;
14
-error_work_queue:
15
- res = -errno;
16
- pw_log_debug("work queue failed: %m");
17
- goto error_free;
18
error_output_mix:
19
pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res));
20
goto error_free;
21
pipewire-0.3.47.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-module.c
Changed
49
1
2
struct impl {
3
struct pw_impl_module this;
4
void *hnd;
5
+ uint32_t destroy_work_id;
6
};
7
8
#define pw_module_resource_info(r,...) pw_resource_call(r,struct pw_module_events,info,0,__VA_ARGS__)
9
10
goto error_no_mem;
11
12
impl->hnd = hnd;
13
+ impl->destroy_work_id = SPA_ID_INVALID;
14
hnd = NULL;
15
16
this = &impl->this;
17
18
19
spa_hook_list_clean(&module->listener_list);
20
21
+ if (impl->destroy_work_id != SPA_ID_INVALID)
22
+ pw_work_queue_cancel(pw_context_get_work_queue(module->context),
23
+ module, SPA_ID_INVALID);
24
+
25
if (!pw_in_valgrind() && dlclose(impl->hnd) != 0)
26
pw_log_warn("%p: dlclose failed: %s", module, dlerror());
27
free(impl);
28
29
{
30
spa_hook_list_append(&module->listener_list, listener, events, data);
31
}
32
+
33
+static void do_destroy_module(void *obj, void *data, int res, uint32_t id)
34
+{
35
+ pw_impl_module_destroy(obj);
36
+}
37
+
38
+SPA_EXPORT
39
+void pw_impl_module_schedule_destroy(struct pw_impl_module *module)
40
+{
41
+ struct impl *impl = SPA_CONTAINER_OF(module, struct impl, this);
42
+
43
+ if (impl->destroy_work_id != SPA_ID_INVALID)
44
+ return;
45
+
46
+ impl->destroy_work_id = pw_work_queue_add(pw_context_get_work_queue(module->context),
47
+ module, 0, do_destroy_module, NULL);
48
+}
49
pipewire-0.3.47.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-node.c
Changed
52
1
2
#include <spa/support/system.h>
3
#include <spa/pod/parser.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/node/utils.h>
7
#include <spa/debug/types.h>
8
#include <spa/utils/string.h>
9
10
}
11
12
impl->work = pw_context_get_work_queue(this->context);
13
- if (impl->work == NULL) {
14
- res = -errno;
15
- goto error_clean;
16
- }
17
impl->pending_id = SPA_ID_INVALID;
18
19
this->data_loop = context->data_loop;
20
21
if (pi->user == 1) {
22
struct pw_param *p;
23
uint8_t buffer[4096];
24
- struct spa_pod_builder b = { 0 };
25
+ struct spa_pod_dynamic_builder b;
26
struct spa_result_node_params result;
27
uint32_t count = 0;
28
29
30
if (result.index < index)
31
continue;
32
33
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
34
- if (spa_pod_filter(&b, &result.param, p->param, filter) != 0)
35
- continue;
36
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
37
38
- pw_log_debug("%p: %d param %u", node, seq, result.index);
39
- result_node_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
40
+ if (spa_pod_filter(&b.b, &result.param, p->param, filter) == 0) {
41
+ pw_log_debug("%p: %d param %u", node, seq, result.index);
42
+ result_node_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
43
+ count++;
44
+ }
45
+ spa_pod_dynamic_builder_clean(&b);
46
47
- if (++count == max)
48
+ if (count == max)
49
break;
50
}
51
res = 0;
52
pipewire-0.3.47.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-port.c
Changed
64
1
2
#include <spa/utils/string.h>
3
#include <spa/debug/types.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
7
#include "pipewire/impl.h"
8
#include "pipewire/private.h"
9
10
{
11
uint32_t idx = 0;
12
uint8_t buffer[1024];
13
- struct spa_pod_builder b;
14
+ struct spa_pod_dynamic_builder b;
15
struct spa_pod *param;
16
17
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
18
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
19
+
20
if (spa_node_port_enum_params_sync(port->mix,
21
pw_direction_reverse(port->direction), 0,
22
- SPA_PARAM_Format, &idx, NULL, ¶m, &b) == 1) {
23
+ SPA_PARAM_Format, &idx, NULL, ¶m, &b.b) == 1) {
24
spa_node_port_set_param(port->mix,
25
port->direction, port_id,
26
SPA_PARAM_Format, 0, param);
27
}
28
+ spa_pod_dynamic_builder_clean(&b);
29
}
30
31
spa_list_append(&port->mix_list, &mix->link);
32
33
if (pi->user == 1) {
34
struct pw_param *p;
35
uint8_t buffer[1024];
36
- struct spa_pod_builder b = { 0 };
37
+ struct spa_pod_dynamic_builder b;
38
struct spa_result_node_params result;
39
uint32_t count = 0;
40
41
42
if (result.index < index)
43
continue;
44
45
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
46
- if (spa_pod_filter(&b, &result.param, p->param, filter) != 0)
47
- continue;
48
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
49
50
- pw_log_debug("%p: %d param %u", port, seq, result.index);
51
- result_port_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
52
+ if (spa_pod_filter(&b.b, &result.param, p->param, filter) >= 0) {
53
+ pw_log_debug("%p: %d param %u", port, seq, result.index);
54
+ result_port_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
55
+ count++;
56
+ }
57
+ spa_pod_dynamic_builder_clean(&b);
58
59
- if (++count == max)
60
+ if (count == max)
61
break;
62
}
63
res = 0;
64
pipewire-0.3.47.tar.gz/src/pipewire/meson.build -> pipewire-0.3.48.tar.gz/src/pipewire/meson.build
Changed
9
1
2
install_headers(pipewire_headers, subdir : pipewire_headers_dir)
3
4
libpipewire_c_args = [
5
+ '-DOLD_MEDIA_SESSION_WORKAROUND=1'
6
]
7
8
if build_machine.system() != 'freebsd'
9
pipewire-0.3.47.tar.gz/src/pipewire/private.h -> pipewire-0.3.48.tar.gz/src/pipewire/private.h
Changed
43
1
2
struct pw_protocol *protocol; /**< protocol in use */
3
int recv_seq; /**< last received sequence number */
4
int send_seq; /**< last sender sequence number */
5
+ uint64_t recv_generation; /**< last received registry generation */
6
+ uint64_t sent_generation; /**< last sent registry generation */
7
8
void *user_data; /**< extra user data */
9
10
11
pw_global_bind_func_t func; /**< bind function */
12
void *object; /**< object associated with the interface */
13
uint64_t serial; /**< increasing serial number */
14
+ uint64_t generation; /**< registry generation number */
15
16
struct spa_list resource_list; /**< The list of resources of this global */
17
18
19
20
uint64_t stamp;
21
uint64_t serial;
22
+ uint64_t generation; /**< registry generation number */
23
struct pw_map globals; /**< map of globals */
24
25
struct spa_list core_impl_list; /**< list of core_imp */
26
27
struct pw_protocol_client *conn; /**< the protocol client connection */
28
int recv_seq; /**< last received sequence number */
29
int send_seq; /**< last protocol result code */
30
+ uint64_t recv_generation; /**< last received registry generation */
31
32
unsigned int removed:1;
33
unsigned int destroyed:1;
34
35
int pw_settings_expose(struct pw_context *context);
36
void pw_settings_clean(struct pw_context *context);
37
38
+void pw_impl_module_schedule_destroy(struct pw_impl_module *module);
39
+
40
/** \endcond */
41
42
#ifdef __cplusplus
43
pipewire-0.3.47.tar.gz/src/pipewire/stream.c -> pipewire-0.3.48.tar.gz/src/pipewire/stream.c
Changed
68
1
2
#include <spa/node/utils.h>
3
#include <spa/utils/ringbuffer.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/debug/format.h>
7
#include <spa/debug/types.h>
8
#include <spa/debug/pod.h>
9
10
11
uint32_t change_mask_all;
12
struct spa_node_info info;
13
-#define IDX_Props 0
14
-#define N_NODE_PARAMS 1
15
+#define IDX_PropInfo 0
16
+#define IDX_Props 1
17
+#define N_NODE_PARAMS 2
18
struct spa_param_info params[N_NODE_PARAMS];
19
20
uint32_t media_type;
21
22
static int get_param_index(uint32_t id)
23
{
24
switch (id) {
25
+ case SPA_PARAM_PropInfo:
26
+ return IDX_PropInfo;
27
case SPA_PARAM_Props:
28
return IDX_Props;
29
default:
30
31
struct stream *d = object;
32
struct spa_result_node_params result;
33
uint8_t buffer[1024];
34
- struct spa_pod_builder b = { 0 };
35
+ struct spa_pod_dynamic_builder b;
36
uint32_t count = 0;
37
struct param *p;
38
bool found = false;
39
40
41
found = true;
42
43
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
44
- if (spa_pod_filter(&b, &result.param, param, filter) != 0)
45
- continue;
46
-
47
- spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
48
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
49
+ if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
50
+ spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
51
+ count++;
52
+ }
53
+ spa_pod_dynamic_builder_clean(&b);
54
55
- if (++count == num)
56
+ if (count == num)
57
break;
58
}
59
return found ? 0 : -ENOENT;
60
61
if (!impl->process_rt)
62
impl->info.flags |= SPA_NODE_FLAG_ASYNC;
63
impl->info.props = &stream->properties->dict;
64
+ impl->params[IDX_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
65
impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
66
impl->info.params = impl->params;
67
impl->info.n_params = N_NODE_PARAMS;
68
pipewire-0.3.47.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.48.tar.gz/src/tools/pw-cli.c
Changed
10
1
2
#define FNM_EXTMATCH 0
3
#endif
4
5
-#define spa_debug(fmt,...) printf(fmt, ## __VA_ARGS__)
6
+#define spa_debug(fmt,...) printf(fmt"\n", ## __VA_ARGS__)
7
8
#include <spa/utils/result.h>
9
#include <spa/utils/string.h>
10
pipewire-0.3.47.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.48.tar.gz/src/tools/pw-loopback.c
Changed
14
1
2
}
3
4
5
- f = open_memstream(&args, &size);
6
+ if ((f = open_memstream(&args, &size)) == NULL) {
7
+ fprintf(stderr, "can't open memstream: %m\n");
8
+ goto exit;
9
+ }
10
+
11
fprintf(f, "{");
12
13
if (opt_remote != NULL)
14
pipewire-0.3.47.tar.gz/src/tools/pw-top.c -> pipewire-0.3.48.tar.gz/src/tools/pw-top.c
Changed
64
1
2
return buf;
3
}
4
5
-static void print_node(struct data *d, struct driver *i, struct node *n)
6
+static void print_node(struct data *d, struct driver *i, struct node *n, int y)
7
{
8
- char line[1024];
9
char buf1[64];
10
char buf2[64];
11
char buf3[64];
12
13
waiting = (n->measurement.awake - n->measurement.signal) / 1000000000.f,
14
busy = (n->measurement.finish - n->measurement.awake) / 1000000000.f,
15
16
- snprintf(line, sizeof(line), "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s",
17
+ mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s",
18
n->measurement.status != 3 ? "!" : " ",
19
n->id,
20
frac.num, frac.denom,
21
22
i->xrun_count + n->errors,
23
n->driver == n ? "" : " + ",
24
n->name);
25
-
26
- wprintw(d->win, "%.*s\n", COLS-1, line);
27
}
28
29
static void do_refresh(struct data *d)
30
{
31
struct node *n, *t, *f;
32
+ int y = 1;
33
34
wclear(d->win);
35
wattron(d->win, A_REVERSE);
36
37
if (n->driver != n)
38
continue;
39
40
- print_node(d, &n->info, n);
41
+ print_node(d, &n->info, n, y++);
42
+ if(y > LINES)
43
+ break;
44
45
spa_list_for_each(f, &d->node_list, link) {
46
if (f->driver != n || f == n)
47
continue;
48
49
- print_node(d, &n->info, f);
50
+ print_node(d, &n->info, f, y++);
51
+ if(y > LINES)
52
+ break;
53
+
54
}
55
}
56
+
57
+ // Clear from last line to the end of the window to hide text wrapping from the last node
58
+ wmove(d->win, y, 0);
59
+ wclrtobot(d->win);
60
+
61
wrefresh(d->win);
62
}
63
64
pipewire-0.3.47.tar.gz/test/test-loop.c -> pipewire-0.3.48.tar.gz/test/test-loop.c
Changed
47
1
2
return PWTEST_PASS;
3
}
4
5
+PWTEST(thread_loop_destroy_between_poll_and_lock)
6
+{
7
+ pw_init(NULL, NULL);
8
+
9
+ struct pw_thread_loop *thread_loop = pw_thread_loop_new("uaf", NULL);
10
+ pwtest_ptr_notnull(thread_loop);
11
+
12
+ struct pw_loop *loop = pw_thread_loop_get_loop(thread_loop);
13
+ pwtest_ptr_notnull(loop);
14
+
15
+ int evfd = eventfd(0, 0);
16
+ pwtest_errno_ok(evfd);
17
+
18
+ struct spa_source *source = pw_loop_add_io(loop, evfd, SPA_IO_IN, true, NULL, NULL);
19
+ pwtest_ptr_notnull(source);
20
+
21
+ pw_thread_loop_start(thread_loop);
22
+
23
+ pw_thread_loop_lock(thread_loop);
24
+ {
25
+ write(evfd, &(uint64_t){1}, sizeof(uint64_t));
26
+ sleep(1);
27
+ pw_loop_destroy_source(loop, source);
28
+ }
29
+ pw_thread_loop_unlock(thread_loop);
30
+
31
+ pw_thread_loop_destroy(thread_loop);
32
+
33
+ pw_deinit();
34
+
35
+ return PWTEST_PASS;
36
+}
37
+
38
PWTEST_SUITE(support)
39
{
40
pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG);
41
pwtest_add(pwtest_loop_recurse1, PWTEST_NOARG);
42
pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG);
43
+ pwtest_add(thread_loop_destroy_between_poll_and_lock, PWTEST_NOARG);
44
45
return PWTEST_PASS;
46
}
47
Refresh
No build results available
Refresh
No rpmlint results available
Login required, please
login
or
signup
in order to comment