We truncated the diff of some files because they were too big.
If you want to see the full diff for every file, click here.
Changes of Revision 4
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Fri Feb 18 14:59:46 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.47
6
+
7
+-------------------------------------------------------------------
8
+Thu Feb 17 13:55:01 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
+
10
+- Update to version 0.3.46
11
+
12
+-------------------------------------------------------------------
13
Fri Feb 4 06:41:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
14
15
- Update to version 0.3.45
16
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.45
6
+Version: 0.3.47
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.45.tar.gz/pipewire-jack/src/match-rules.c
Deleted
143
1
2
-/* PipeWire
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
-#include <string.h>
27
-#include <stdio.h>
28
-#include <errno.h>
29
-#include <math.h>
30
-#include <time.h>
31
-#include <regex.h>
32
-
33
-#include "config.h"
34
-
35
-#include <spa/utils/json.h>
36
-#include <spa/utils/string.h>
37
-
38
-#include <pipewire/pipewire.h>
39
-
40
-static bool find_match(struct spa_json *arr, const struct spa_dict *props)
41
-{
42
- struct spa_json it[1];
43
-
44
- while (spa_json_enter_object(arr, &it[0]) > 0) {
45
- char key[256], val[1024];
46
- const char *str, *value;
47
- int match = 0, fail = 0;
48
- int len;
49
-
50
- while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
51
- bool success = false;
52
-
53
- if ((len = spa_json_next(&it[0], &value)) <= 0)
54
- break;
55
-
56
- str = spa_dict_lookup(props, key);
57
-
58
- if (spa_json_is_null(value, len)) {
59
- success = str == NULL;
60
- } else {
61
- if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0)
62
- continue;
63
- value = val;
64
- len = strlen(val);
65
- }
66
- if (str != NULL) {
67
- if (value[0] == '~') {
68
- regex_t preg;
69
- if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
70
- if (regexec(&preg, str, 0, NULL, 0) == 0)
71
- success = true;
72
- regfree(&preg);
73
- }
74
- } else if (strncmp(str, value, len) == 0 &&
75
- strlen(str) == (size_t)len) {
76
- success = true;
77
- }
78
- }
79
- if (success) {
80
- match++;
81
- pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
82
- }
83
- else
84
- fail++;
85
- }
86
- if (match > 0 && fail == 0)
87
- return true;
88
- }
89
- return false;
90
-}
91
-
92
-int pw_jack_match_rules(const char *rules, size_t size, const struct spa_dict *props,
93
- int (*matched) (void *data, const char *action, const char *val, size_t len),
94
- void *data)
95
-{
96
- const char *val;
97
- struct spa_json it[4], actions;
98
- int count = 0;
99
-
100
- spa_json_init(&it[0], rules, size);
101
- if (spa_json_enter_array(&it[0], &it[1]) < 0)
102
- return 0;
103
-
104
- while (spa_json_enter_object(&it[1], &it[2]) > 0) {
105
- char key[64];
106
- bool have_match = false, have_actions = false;
107
-
108
- while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
109
- if (spa_streq(key, "matches")) {
110
- if (spa_json_enter_array(&it[2], &it[3]) < 0)
111
- break;
112
-
113
- have_match = find_match(&it[3], props);
114
- }
115
- else if (spa_streq(key, "actions")) {
116
- if (spa_json_enter_object(&it[2], &actions) > 0)
117
- have_actions = true;
118
- }
119
- else if (spa_json_next(&it[2], &val) <= 0)
120
- break;
121
- }
122
- if (!have_match || !have_actions)
123
- continue;
124
-
125
- while (spa_json_get_string(&actions, key, sizeof(key)) > 0) {
126
- int res, len;
127
- pw_log_debug("action %s", key);
128
-
129
- if ((len = spa_json_next(&actions, &val)) <= 0)
130
- break;
131
-
132
- if (spa_json_is_container(val, len))
133
- len = spa_json_container_len(&actions, val, len);
134
-
135
- if ((res = matched(data, key, val, len)) < 0)
136
- return res;
137
-
138
- count += res;
139
- }
140
- }
141
- return count;
142
-}
143
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel
Deleted
2
1
-(directory)
2
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/aec-null.c
Deleted
66
1
2
-/* PipeWire
3
- *
4
- * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a
7
- * copy of this software and associated documentation files (the "Software"),
8
- * to deal in the Software without restriction, including without limitation
9
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
- * and/or sell copies of the Software, and to permit persons to whom the
11
- * Software is furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice (including the next
14
- * paragraph) shall be included in all copies or substantial portions of the
15
- * Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
- * DEALINGS IN THE SOFTWARE.
24
- */
25
-
26
-#include "echo-cancel.h"
27
-
28
-struct impl {
29
- uint32_t channels;
30
-};
31
-
32
-static void *null_create(const struct pw_properties *args, const struct spa_audio_info_raw *info)
33
-{
34
- struct impl *impl;
35
- impl = calloc(1, sizeof(struct impl));
36
- impl->channels = info->channels;
37
- return impl;
38
-}
39
-
40
-static void null_destroy(void *ec)
41
-{
42
- free(ec);
43
-}
44
-
45
-static int null_run(void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples)
46
-{
47
- struct impl *impl = ec;
48
- uint32_t i;
49
- for (i = 0; i < impl->channels; i++)
50
- memcpy(out[i], rec[i], n_samples * sizeof(float));
51
- return 0;
52
-}
53
-
54
-static const struct echo_cancel_info echo_cancel_null_impl = {
55
- .name = "null",
56
- .info = SPA_DICT_INIT(NULL, 0),
57
- .latency = NULL,
58
-
59
- .create = null_create,
60
- .destroy = null_destroy,
61
-
62
- .run = null_run,
63
-};
64
-
65
-const struct echo_cancel_info *echo_cancel_null = &echo_cancel_null_impl;
66
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/aec-webrtc.cpp
Deleted
165
1
2
-/* PipeWire
3
- *
4
- * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
- * © 2021 Arun Raghavan <arun@asymptotic.io>
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a
8
- * copy of this software and associated documentation files (the "Software"),
9
- * to deal in the Software without restriction, including without limitation
10
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
- * and/or sell copies of the Software, and to permit persons to whom the
12
- * Software is furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice (including the next
15
- * paragraph) shall be included in all copies or substantial portions of the
16
- * Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
- * DEALINGS IN THE SOFTWARE.
25
- */
26
-
27
-#include <memory>
28
-#include <utility>
29
-
30
-#include "echo-cancel.h"
31
-
32
-#include <pipewire/pipewire.h>
33
-
34
-#include <webrtc/modules/audio_processing/include/audio_processing.h>
35
-#include <webrtc/modules/interface/module_common_types.h>
36
-#include <webrtc/system_wrappers/include/trace.h>
37
-
38
-struct impl {
39
- std::unique_ptr<webrtc::AudioProcessing> apm;
40
- spa_audio_info_raw info;
41
- std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer;
42
-
43
- impl(std::unique_ptr<webrtc::AudioProcessing> apm, const spa_audio_info_raw& info)
44
- : apm(std::move(apm)),
45
- info(info),
46
- play_buffer(std::make_unique<float *[]>(info.channels)),
47
- rec_buffer(std::make_unique<float *[]>(info.channels)),
48
- out_buffer(std::make_unique<float *[]>(info.channels))
49
- { }
50
-};
51
-
52
-static void *webrtc_create(const struct pw_properties *args, const spa_audio_info_raw *info)
53
-{
54
- bool extended_filter = pw_properties_get_bool(args, "webrtc.extended_filter", true);
55
- bool delay_agnostic = pw_properties_get_bool(args, "webrtc.delay_agnostic", true);
56
- bool high_pass_filter = pw_properties_get_bool(args, "webrtc.high_pass_filter", true);
57
- bool noise_suppression = pw_properties_get_bool(args, "webrtc.noise_suppression", true);
58
- bool voice_detection = pw_properties_get_bool(args, "webrtc.voice_detection", true);
59
-
60
- // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech,
61
- // result in very poor performance, disable by default
62
- bool gain_control = pw_properties_get_bool(args, "webrtc.gain_control", false);
63
-
64
- // Disable experimental flags by default
65
- bool experimental_agc = pw_properties_get_bool(args, "webrtc.experimental_agc", false);
66
- bool experimental_ns = pw_properties_get_bool(args, "webrtc.experimental_ns", false);
67
-
68
- // FIXME: Intelligibility enhancer is not currently supported
69
- // This filter will modify playback buffer (when calling ProcessReverseStream), but now
70
- // playback buffer modifications are discarded.
71
-
72
- webrtc::Config config;
73
- config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(extended_filter));
74
- config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(delay_agnostic));
75
- config.Set<webrtc::ExperimentalAgc>(new webrtc::ExperimentalAgc(experimental_agc));
76
- config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(experimental_ns));
77
-
78
- webrtc::ProcessingConfig pconfig = {{
79
- webrtc::StreamConfig(info->rate, info->channels, false), /* input stream */
80
- webrtc::StreamConfig(info->rate, info->channels, false), /* output stream */
81
- webrtc::StreamConfig(info->rate, info->channels, false), /* reverse input stream */
82
- webrtc::StreamConfig(info->rate, info->channels, false), /* reverse output stream */
83
- }};
84
-
85
- auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
86
- if (apm->Initialize(pconfig) != webrtc::AudioProcessing::kNoError) {
87
- pw_log_error("Error initialising webrtc audio processing module");
88
- return nullptr;
89
- }
90
-
91
- apm->high_pass_filter()->Enable(high_pass_filter);
92
- // Always disable drift compensation since it requires drift sampling
93
- apm->echo_cancellation()->enable_drift_compensation(false);
94
- apm->echo_cancellation()->Enable(true);
95
- // TODO: wire up supression levels to args
96
- apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression);
97
- apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh);
98
- apm->noise_suppression()->Enable(noise_suppression);
99
- apm->voice_detection()->Enable(voice_detection);
100
- // TODO: wire up AGC parameters to args
101
- apm->gain_control()->set_analog_level_limits(0, 255);
102
- apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
103
- apm->gain_control()->Enable(gain_control);
104
-
105
- return new impl(std::move(apm), *info);
106
-}
107
-
108
-static void webrtc_destroy(void *ec)
109
-{
110
- auto impl = static_cast<struct impl *>(ec);
111
-
112
- delete impl;
113
-}
114
-
115
-static int webrtc_run(void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples)
116
-{
117
- auto impl = static_cast<struct impl *>(ec);
118
- webrtc::StreamConfig config =
119
- webrtc::StreamConfig(impl->info.rate, impl->info.channels, false);
120
- unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10;
121
-
122
- if (n_samples * 1000 / impl->info.rate % 10 != 0) {
123
- pw_log_error("Buffers must be multiples of 10ms in length (currently %u samples)", n_samples);
124
- return -1;
125
- }
126
-
127
- for (size_t i = 0; i < num_blocks; i ++) {
128
- for (size_t j = 0; j < impl->info.channels; j++) {
129
- impl->play_buffer[j] = const_cast<float *>(play[j]) + config.num_frames() * i;
130
- impl->rec_buffer[j] = const_cast<float *>(rec[j]) + config.num_frames() * i;
131
- impl->out_buffer[j] = out[j] + config.num_frames() * i;
132
- }
133
- /* FIXME: ProcessReverseStream may change the playback buffer, in which
134
- * case we should use that, if we ever expose the intelligibility
135
- * enhancer */
136
- if (impl->apm->ProcessReverseStream(impl->play_buffer.get(), config, config, impl->play_buffer.get()) !=
137
- webrtc::AudioProcessing::kNoError) {
138
- pw_log_error("Processing reverse stream failed");
139
- }
140
-
141
- // Extra delay introduced by multiple frames
142
- impl->apm->set_stream_delay_ms((num_blocks - 1) * 10);
143
-
144
- if (impl->apm->ProcessStream(impl->rec_buffer.get(), config, config, impl->out_buffer.get()) !=
145
- webrtc::AudioProcessing::kNoError) {
146
- pw_log_error("Processing stream failed");
147
- }
148
- }
149
-
150
- return 0;
151
-}
152
-
153
-static const struct echo_cancel_info echo_cancel_webrtc_impl = {
154
- .name = "webrtc",
155
- .info = SPA_DICT_INIT(NULL, 0),
156
- .latency = "480/48000",
157
-
158
- .create = webrtc_create,
159
- .destroy = webrtc_destroy,
160
-
161
- .run = webrtc_run,
162
-};
163
-
164
-const struct echo_cancel_info *echo_cancel_webrtc = &echo_cancel_webrtc_impl;
165
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/echo-cancel.h
Deleted
52
1
2
-/* PipeWire
3
- *
4
- * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a
7
- * copy of this software and associated documentation files (the "Software"),
8
- * to deal in the Software without restriction, including without limitation
9
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
- * and/or sell copies of the Software, and to permit persons to whom the
11
- * Software is furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice (including the next
14
- * paragraph) shall be included in all copies or substantial portions of the
15
- * Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
- * DEALINGS IN THE SOFTWARE.
24
- */
25
-
26
-#include "config.h"
27
-
28
-#include <spa/utils/dict.h>
29
-#include <spa/param/audio/raw.h>
30
-
31
-#include <pipewire/properties.h>
32
-
33
-struct echo_cancel_info {
34
- const char *name;
35
- const struct spa_dict info;
36
- const char *latency;
37
-
38
- void *(*create) (const struct pw_properties *args, const struct spa_audio_info_raw *info);
39
- void (*destroy) (void *ec);
40
-
41
- int (*run) (void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples);
42
-};
43
-
44
-#define echo_cancel_create(i,...) (i)->create(__VA_ARGS__)
45
-#define echo_cancel_destroy(i,...) (i)->destroy(__VA_ARGS__)
46
-#define echo_cancel_run(i,...) (i)->run(__VA_ARGS__)
47
-
48
-#ifdef HAVE_WEBRTC
49
-extern const struct echo_cancel_info *echo_cancel_webrtc;
50
-#endif
51
-extern const struct echo_cancel_info *echo_cancel_null;
52
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/media-roles.c
Deleted
42
1
2
-/* PipeWire
3
- *
4
- * Copyright © 2020 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 <stddef.h>
27
-
28
-#include "media-roles.h"
29
-
30
-const struct str_map media_role_map[] = {
31
- { "Movie", "video", },
32
- { "Music", "music", },
33
- { "Game", "game", },
34
- { "Notification", "event", },
35
- { "Communication", "phone", },
36
- { "Movie", "animation", },
37
- { "Production", "production", },
38
- { "Accessibility", "a11y", },
39
- { "Test", "test", },
40
- { NULL, NULL },
41
-};
42
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/media-roles.h
Deleted
52
1
2
-/* PipeWire
3
- *
4
- * Copyright © 2020 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 PULSE_SERVER_MEDIA_ROLES_H
27
-#define PULSE_SERVER_MEDIA_ROLES_H
28
-
29
-#include <stddef.h>
30
-
31
-#include <spa/utils/string.h>
32
-
33
-struct str_map {
34
- const char *pw_str;
35
- const char *pa_str;
36
- const struct str_map *child;
37
-};
38
-
39
-extern const struct str_map media_role_map[];
40
-
41
-static inline const struct str_map *str_map_find(const struct str_map *map, const char *pw, const char *pa)
42
-{
43
- size_t i;
44
- for (i = 0; map[i].pw_str; i++)
45
- if ((pw && spa_streq(map[i].pw_str, pw)) ||
46
- (pa && spa_streq(map[i].pa_str, pa)))
47
- return &map[i];
48
- return NULL;
49
-}
50
-
51
-#endif /* PULSE_SERVER_MEDIA_ROLES_H */
52
pipewire-0.3.45.tar.gz/.gitlab-ci.yml -> pipewire-0.3.47.tar.gz/.gitlab-ci.yml
Changed
19
1
2
.fedora:
3
variables:
4
# Update this tag when you want to trigger a rebuild
5
- FDO_DISTRIBUTION_TAG: '2022-01-28.0'
6
+ FDO_DISTRIBUTION_TAG: '2022-02-16.0'
7
FDO_DISTRIBUTION_VERSION: '35'
8
FDO_DISTRIBUTION_PACKAGES: >-
9
alsa-lib-devel
10
11
FDO_DISTRIBUTION_EXEC: >-
12
mkdir -p /opt ;
13
cd /opt ;
14
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
15
+ curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/cxx/linux64
16
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN ;
17
tar xf /tmp/cov-analysis-linux64.tgz ;
18
mv cov-analysis-linux64-* coverity ;
19
pipewire-0.3.45.tar.gz/NEWS -> pipewire-0.3.47.tar.gz/NEWS
Changed
122
1
2
+# PipeWire 0.3.47 (2022-02-18)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+This is a quick emergency release to fix some severe
8
+problems with the previous release.
9
+
10
+## Highlights
11
+ - Fixes a bug in pulse-server that caused cached notifications
12
+ to play multiple times. (#2142)
13
+ - Removed check and warnings to catch leaked listeners on the
14
+ proxy. This might access invalid memory and cause infinite
15
+ loops in older wireplumber.
16
+
17
+Older versions:
18
+
19
+# PipeWire 0.3.46 (2022-02-17)
20
+
21
+This is a bugfix release that is API and ABI compatible with previous
22
+0.3.x releases.
23
+
24
+## Highlights
25
+ - Fix a critical bug in pipewire-pulse buffer size handling that made some
26
+ apps (MuseScore, ... ) stutter.
27
+ - Fix a critical bug where devices would not show when the kernel was
28
+ compiled without VERBOSE_PROCSFS.
29
+ - JACK clients will now use lock-quantum by default. This makes sure that
30
+ all dynamic quantum changes are disabled while a JACK app is running.
31
+ The only way to force a quantum chance is through a JACK app or with
32
+ the metadata.
33
+ - Almost all limits on number of ports, clients and nodes are removed.
34
+ - A Dummy fallback sink is now automatically created when there are no
35
+ other sinks. This avoids stalling browsers.
36
+ - Sound sharing with Zoom should work better. A new WirePlumber release
37
+ might be required.
38
+ - Many more fixes and improvements.
39
+
40
+
41
+## PipeWire
42
+ - Update docs with new config overrides.
43
+ - The rule matching logic was moved to config and code is now shared with
44
+ pulse-server and JACK.
45
+ - Add new Romanian translation.
46
+ - When a quantum is forced with metadata, any node that asked to lock-quantum
47
+ is ignored so that the quantum change can happen.
48
+ - Fix a bug where a mixer was removed twice, leading to potential memory
49
+ corruption.
50
+ - The port limits on nodes and filters are now removed. Some code was
51
+ simplified.
52
+ - Fix a potential leak because listeners where removed while they could be
53
+ emitted.
54
+ - Improve context.exec and avoid zombie processes.
55
+
56
+## Modules
57
+ - The RAOP module now has a default latency of 2 seconds, like PulseAudio.
58
+ - The echo-cancel module now uses the plugin loader to load the backends.
59
+ This makes it possible to add custom, out of tree, echo cancel plugins.
60
+
61
+## Tools
62
+ - Improve help of pw-link.
63
+ - Output to stdout and error to stderr. Use setlinebuf for stdout to improve
64
+ piping between apps. (#2110)
65
+
66
+## SPA
67
+ - Improve removing sources when dispatching. Also improve performance now
68
+ that a destroy loop can be removed. (#2114)
69
+ - Fix an fd leak in the logger when logging to a file.
70
+ - Improve loop enter/leave checks and support recursive loops.
71
+
72
+## pulse-server
73
+ - Clamp various buffer attributes to the max length. Fixes some issues
74
+ with various applications. (#2100)
75
+ - Module properties are now remapped correctly from their pulseaudio variant
76
+ to the PipeWire ones.
77
+ - Fix module index in introspect. Use the right index when loaded from our
78
+ internal modules. (#2101)
79
+ - Improve argument parsing and node.description. (#2086)
80
+ - The sink-index should now be filled in correctly when playing a sample.
81
+ (#2129)
82
+ - module-always-sink is now implemented and loaded by default. (#1838)
83
+ - Add support for loading some modules only once.
84
+ - Module load and unload now does extra sync to make it appear synchronous,
85
+ like in PulseAudio. This improves sounds sharing in Zoom.
86
+
87
+## ALSA
88
+ - Fix critial bug where alsa devices would not show when the kernel was
89
+ compiled without VERBOSE_PROCFS.
90
+ - Some corner cases were fixed in the ALSA timing code. When the capture node
91
+ is follower, it will now not try to read too much data and xrun but it will
92
+ instead produce a cycle of silence.
93
+ - Various fixes and improvements to make ALSA devices resync to the driver
94
+ more quickly and accurately.
95
+
96
+## JACK
97
+ - Add an option to name the defauld device as `system` to improve
98
+ compatibility with some applications,
99
+ - Use lock-quantum by default. This makes sure that all dynamic quantum
100
+ changes are disabled while a JACK app is running. The only way to force
101
+ a quantum chance is through a JACK app or with the metadata.
102
+ - It is now possible to do IPC calls from the data thread. Note that this
103
+ is a very bad idea but required for compatibility with JACK2.
104
+
105
+## GStreamer
106
+ - GStreamer sink will now set a default channelmap to make it possible to
107
+ remap to the channel layout of the device.
108
+
109
# PipeWire 0.3.45 (2022-02-03)
110
111
This is a bugfix release that is API and ABI compatible with previous
112
113
switch quantum and ensure it can't change for the lifetime of the JACK
114
app. (#2079)
115
116
-Older versions:
117
-
118
-
119
# PipeWire 0.3.44 (2022-01-27)
120
121
This is a bugfix release that is API and ABI compatible with previous
122
pipewire-0.3.45.tar.gz/doc/pipewire-daemon.dox -> pipewire-0.3.47.tar.gz/doc/pipewire-daemon.dox
Changed
22
1
2
- `$sysconfdir/pipewire/pipewire.conf` (usually `/etc/pipewire/pipewire.conf`)
3
- `$datadir/pipewire/pipewire.conf` (usually `/usr/share/pipewire/pipewire.conf`)
4
5
-The first configuration file found is loaded, the PipeWire daemon does not
6
-currently combine configuration files.
7
+The first configuration file found is loaded as the base configuration.
8
+
9
+Next, configuration sections are collected in the directories in this
10
+order:
11
+
12
+- `$datadir/pipewire/pipewire.conf.d/` (usually `/usr/share/pipewire/pipewire.conf.d/`)
13
+- `$sysconfdir/pipewire/pipewire.conf.d/` (usually `/etc/pipewire/pipewire.conf.d/`)
14
+- `$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/` (usually `$HOME/.config/pipewire/pipewire.conf.d/`)
15
+
16
+They are applied to the global configuration file. Properties are overwritten
17
+and array elements are appended. This makes it possible to make small custom customizations
18
+or additions to the main configuration file.
19
20
The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX`
21
and `PIPEWIRE_CONFIG_NAME` can be used to specify an alternative config
22
pipewire-0.3.45.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.47.tar.gz/doc/pipewire-modules.dox
Changed
9
1
2
- \subpage page_module_echo_cancel
3
- \subpage page_module_example_sink
4
- \subpage page_module_example_source
5
+- \subpage page_module_fallback_sink
6
- \subpage page_module_filter_chain
7
- \subpage page_module_link_factory
8
- \subpage page_module_loopback
9
pipewire-0.3.45.tar.gz/man/meson.build -> pipewire-0.3.47.tar.gz/man/meson.build
Changed
10
1
2
'pw-profiler.1.rst.in',
3
]
4
5
-if not get_option('pipewire-jack').disabled()
6
+if get_option('pipewire-jack').allowed()
7
manpages += 'pw-jack.1.rst.in'
8
endif
9
10
pipewire-0.3.45.tar.gz/man/pipewire.conf.5.rst.in -> pipewire-0.3.47.tar.gz/man/pipewire.conf.5.rst.in
Changed
54
1
2
3
*@PIPEWIRE_CONFDATADIR@/pipewire.conf*
4
5
+*@PIPEWIRE_CONFDATADIR@/pipewire.conf.d/*
6
+
7
+*@PIPEWIRE_CONFIG_DIR@/pipewire.conf.d/*
8
+
9
+*$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/*
10
+
11
DESCRIPTION
12
===========
13
14
PipeWire is a service that facilitates sharing of multimedia content
15
between devices and applications.
16
17
-On startup, the daemon reads a configuration file to configure
18
+On startup, the daemon reads a main configuration file to configure
19
itself. It executes a series of commands listed in the config
20
file.
21
22
23
and ``PIPEWIRE_CONFIG_NAME`` can be used to specify an alternative config
24
directory, subdirectory and file respectively.
25
26
+Next to the configuration file can be a directory with the same name as
27
+the file with a ``.d/`` suffix. All directories in the SYNOPSIS_ directory
28
+search paths are traversed in the listed order and the contents of the
29
+``*.conf`` files inside them are appended to the main configuration file
30
+as overrides. Object sections are merged and array sections are appended.
31
+
32
+
33
CONFIGURATION FILE FORMAT
34
=========================
35
36
37
38
name = [ { k = v1 } { k = v2 } ] # an array of dictionaries
39
40
+
41
+The configuration files can be expressed in full JSON syntax but for ease
42
+of use, a relaxed format may be used where:
43
+
44
+ * ``:`` to delimit keys and values can be substuted by ``=`` or a space.
45
+ * ``"`` around keys and string can be omited as long as no special characters
46
+ are used in the strings.
47
+ * ``,`` to separate objects can be replaced with a whitespace character.
48
+ * ``#`` can be used to start a comment until the line end
49
+
50
+
51
CONFIGURATION FILE SECTIONS
52
===========================
53
54
pipewire-0.3.45.tar.gz/meson.build -> pipewire-0.3.47.tar.gz/meson.build
Changed
201
1
2
project('pipewire', ['c' ],
3
- version : '0.3.45',
4
+ version : '0.3.47',
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_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir)
10
cdata.set_quoted('PLUGINDIR', spa_plugindir)
11
cdata.set_quoted('SPADATADIR', spa_datadir)
12
-# FIXME: --with-memory-alignment],[8,N,malloc,pagesize (default is 32)]) option
13
-cdata.set('MEMORY_ALIGNMENT_MALLOC', 1)
14
cdata.set_quoted('PA_ALSA_PATHS_DIR', alsadatadir / 'paths')
15
cdata.set_quoted('PA_ALSA_PROFILE_SETS_DIR', alsadatadir / 'profile-sets')
16
17
18
cdata.set('WORDS_BIGENDIAN', 1)
19
endif
20
21
-check_headers = [['dlfcn.h','HAVE_DLFCN_H'],
22
- ['inttypes.h', 'HAVE_INTTYPES_H'],
23
- ['memory.h', 'HAVE_MEMORY_H'],
24
- ['poll.h', 'HAVE_POLL_H'],
25
- ['stddef.h', 'HAVE_STDDEF_H'],
26
- ['stdint.h', 'HAVE_STDINT_H'],
27
- ['stdio_ext.h', 'HAVE_STDIO_EXT_H'],
28
- ['strings.h', 'HAVE_STRINGS_H'],
29
- ['string.h', 'HAVE_STRING_H'],
30
+check_headers = [
31
['sys/mount.h', 'HAVE_SYS_MOUNT_H'],
32
['sys/param.h', 'HAVE_SYS_PARAM_H'],
33
- ['sys/poll.h', 'HAVE_SYS_POLL_H'],
34
- ['sys/prctl.h', 'HAVE_SYS_PRCTL_H'],
35
['sys/random.h', 'HAVE_SYS_RANDOM_H'],
36
- ['sys/socket.h', 'HAVE_SYS_SOCKET_H'],
37
- ['sys/stat.h', 'HAVE_SYS_STAT_H'],
38
- ['sys/times.h', 'HAVE_SYS_TIMES_H'],
39
- ['sys/time.h', 'HAVE_SYS_TIME_H'],
40
- ['sys/types.h', 'HAVE_SYS_TYPES_H'],
41
- ['sys/utsname.h', 'HAVE_SYS_UTSNAME_H'],
42
['sys/vfs.h', 'HAVE_SYS_VFS_H'],
43
- ['sys/wait.h', 'HAVE_SYS_WAIT_H'],
44
['pwd.h', 'HAVE_PWD_H'],
45
- ['ucontext.h', 'HAVE_UCONTEXT_H'],
46
- ['unistd.h', 'HAVE_UNISTD_H'],
47
]
48
49
foreach h : check_headers
50
- if cc.has_header(h.get(0))
51
- cdata.set(h.get(1), 1)
52
- endif
53
+ cdata.set(h.get(1), cc.has_header(h.get(0)))
54
endforeach
55
56
-if cc.has_function('poll', prefix : '#include<poll.h>')
57
- cdata.set('HAVE_POLL', 1)
58
-endif
59
-if cc.has_function('pselect', prefix : '#include<sys/select.h>')
60
- cdata.set('HAVE_PSELECT', 1)
61
-endif
62
-cdata.set('HAVE_MMAP', 1)
63
-
64
-if cc.has_function('posix_memalign', prefix : '#include<stdlib.h>')
65
- cdata.set('HAVE_POSIX_MEMALIGN', 1)
66
-endif
67
-if cc.has_function('getpagesize', prefix : '#include<unistd.h>')
68
- cdata.set('HAVE_GETPAGESIZE', 1)
69
-endif
70
-if cc.has_function('gettid', prefix : '#include<unistd.h>', args: [ '-D_GNU_SOURCE' ])
71
- cdata.set('HAVE_GETTID', 1)
72
-endif
73
-if cc.has_function('clock_gettime', prefix : '#include <time.h>')
74
- cdata.set('HAVE_CLOCK_GETTIME', 1)
75
-endif
76
-
77
-if cc.has_type('ptrdiff_t', prefix : '#include <stddef.h>')
78
- cdata.set('HAVE_PTRDIFF_T', 1)
79
-endif
80
-
81
-if cc.has_header_symbol('string.h', 'strndupa', args : [ '-D_GNU_SOURCE' ])
82
- cdata.set('HAVE_STRNDUPA', 1)
83
-endif
84
-
85
-if cc.has_function('mkstemp', prefix : '#include <stdlib.h>')
86
- cdata.set('HAVE_MKSTEMP', 1)
87
-endif
88
-
89
-if cc.has_function('memfd_create', prefix : '#include <sys/mman.h>', args : [ '-D_GNU_SOURCE' ])
90
- cdata.set('HAVE_MEMFD_CREATE', 1)
91
-endif
92
-
93
-if cc.has_function('getrandom', prefix : '#include <stddef.h>\n#include <sys/random.h>', args : [ '-D_GNU_SOURCE' ])
94
- cdata.set('HAVE_GETRANDOM', 1)
95
-endif
96
+check_functions = [
97
+ ['gettid', '#include <unistd.h>', ['-D_GNU_SOURCE']],
98
+ ['memfd_create', '#include <sys/mman.h>', ['-D_GNU_SOURCE']],
99
+ ['getrandom', '#include <stddef.h>\n#include <sys/random.h>', ['-D_GNU_SOURCE']],
100
+ ['sigabbrev_np', '#include <string.h>', ['-D_GNU_SOURCE']],
101
+]
102
103
-if cc.has_function('sigabbrev_np', prefix : '#include <string.h>', args : [ '-D_GNU_SOURCE' ])
104
- cdata.set('HAVE_SIGABBREV_NP', 1)
105
-endif
106
+foreach f : check_functions
107
+ cdata.set('HAVE_' + f.get(0).to_upper(),
108
+ cc.has_function(f.get(0), prefix: f.get(1), args: f.get(2)))
109
+endforeach
110
111
-if cc.get_define('SYS_pidfd_open', prefix : '#include <sys/syscall.h>') != ''
112
- cdata.set('HAVE_PIDFD_OPEN', 1)
113
-endif
114
+cdata.set('HAVE_PIDFD_OPEN',
115
+ cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '')
116
117
systemd = dependency('systemd', required: get_option('systemd'))
118
systemd_dep = dependency('libsystemd',required: get_option('systemd'))
119
summary({'systemd conf data': systemd.found()}, bool_yn: true)
120
summary({'libsystemd': systemd_dep.found()}, bool_yn: true)
121
-if systemd.found() and systemd_dep.found()
122
- cdata.set('HAVE_SYSTEMD', 1)
123
-endif
124
+cdata.set('HAVE_SYSTEMD', systemd.found() and systemd_dep.found())
125
126
configinc = include_directories('.')
127
includes_inc = include_directories('include')
128
129
pthread_lib = dependency('threads')
130
dbus_dep = dependency('dbus-1', required : get_option('dbus'))
131
summary({'dbus (Bluetooth, rt, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies')
132
-if dbus_dep.found()
133
- cdata.set('HAVE_DBUS', 1)
134
-endif
135
+cdata.set('HAVE_DBUS', dbus_dep.found())
136
sdl_dep = dependency('sdl2', required : get_option('sdl2'))
137
summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
138
drm_dep = dependency('libdrm', required : false)
139
140
ncurses_dep = dependency('ncursesw', required : false)
141
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile'))
142
summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')
143
-if sndfile_dep.found()
144
- cdata.set('HAVE_SNDFILE', 1)
145
-endif
146
+cdata.set('HAVE_SNDFILE', sndfile_dep.found())
147
pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
148
summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
149
avahi_dep = dependency('avahi-client', required : get_option('avahi'))
150
151
152
libusb_dep = dependency('libusb-1.0', required : get_option('libusb'))
153
summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend')
154
-if libusb_dep.found()
155
- cdata.set('HAVE_LIBUSB', 1)
156
-endif
157
+cdata.set('HAVE_LIBUSB', libusb_dep.found())
158
159
cap_lib = dependency('libcap', required : false)
160
-if cap_lib.found()
161
- cdata.set('HAVE_LIBCAP', 1)
162
-endif
163
+cdata.set('HAVE_LIBCAP', cap_lib.found())
164
165
gst_option = get_option('gstreamer')
166
gst_deps_def = {
167
168
gst_dp_found = gst_dep.length() > 0
169
summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Backend')
170
171
-if not get_option('gstreamer-device-provider').disabled()
172
- cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', 1)
173
-endif
174
+cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provider').allowed())
175
176
webrtc_dep = dependency('webrtc-audio-processing',
177
version : ['>= 0.2', '< 1.0'],
178
required : get_option('echo-cancel-webrtc'))
179
summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
180
-
181
-if webrtc_dep.found()
182
- cdata.set('HAVE_WEBRTC', 1)
183
-endif
184
+cdata.set('HAVE_WEBRTC', webrtc_dep.found())
185
186
# On FreeBSD, epoll-shim library is required for eventfd() and timerfd()
187
epoll_shim_dep = (build_machine.system() == 'freebsd'
188
189
190
lilv_lib = dependency('lilv-0', required: get_option('lv2'))
191
summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true)
192
-if lilv_lib.found()
193
- cdata.set('HAVE_LILV', 1)
194
-endif
195
+cdata.set('HAVE_LILV', lilv_lib.found())
196
197
installed_tests_metadir = pipewire_datadir / 'installed-tests' / pipewire_name
198
installed_tests_execdir = pipewire_libexecdir / 'installed-tests' / pipewire_name
199
-installed_tests_enabled = not get_option('installed_tests').disabled()
200
+installed_tests_enabled = get_option('installed_tests').allowed()
201
pipewire-0.3.45.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.47.tar.gz/pipewire-jack/src/meson.build
Changed
9
1
2
pipewire_jack_sources = [
3
'export.c',
4
'pipewire-jack.c',
5
- 'match-rules.c',
6
'ringbuffer.c',
7
'uuid.c',
8
]
9
pipewire-0.3.45.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.47.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
201
1
2
3
#define JACK_CLIENT_NAME_SIZE 128
4
#define JACK_PORT_NAME_SIZE 256
5
-#define JACK_PORT_MAX 4096
6
#define JACK_PORT_TYPE_SIZE 32
7
-#define CONNECTION_NUM_FOR_PORT 1024
8
#define MONITOR_EXT " Monitor"
9
10
+#define MAX_MIDI_MIX 1024
11
#define MAX_BUFFER_FRAMES 8192
12
13
#define MAX_ALIGN 16
14
-#define MAX_PORTS 1024
15
#define MAX_BUFFERS 2
16
#define MAX_BUFFER_DATAS 1u
17
18
19
} rt;
20
21
pthread_mutex_t rt_lock;
22
+ unsigned int rt_locked:1;
23
24
unsigned int started:1;
25
unsigned int active:1;
26
27
unsigned int filter_name:1;
28
unsigned int freewheeling:1;
29
unsigned int locked_process:1;
30
+ unsigned int default_as_system:1;
31
int self_connect_mode;
32
int rt_max;
33
34
35
int res = 0; \
36
if (c->callback) { \
37
if (pthread_mutex_trylock(&c->rt_lock) == 0) { \
38
+ c->rt_locked = true; \
39
res = c->callback(__VA_ARGS__); \
40
+ c->rt_locked = false; \
41
pthread_mutex_unlock(&c->rt_lock); \
42
} \
43
} \
44
45
46
static int do_sync(struct client *client)
47
{
48
+ bool in_data_thread = pw_data_loop_in_thread(client->loop);
49
+
50
if (pw_thread_loop_in_thread(client->context.loop)) {
51
pw_log_warn("sync requested from callback");
52
return 0;
53
54
client->pending_sync = pw_proxy_sync((struct pw_proxy*)client->core, client->pending_sync);
55
56
while (true) {
57
+ if (in_data_thread && client->rt_locked)
58
+ pthread_mutex_unlock(&client->rt_lock);
59
+
60
pw_thread_loop_wait(client->context.loop);
61
62
+ if (in_data_thread && client->rt_locked)
63
+ pthread_mutex_lock(&client->rt_lock);
64
+
65
if (client->error)
66
return client->last_res;
67
68
69
struct client *client = data;
70
client->node = NULL;
71
spa_hook_remove(&client->proxy_listener);
72
+ spa_hook_remove(&client->node_listener);
73
}
74
75
static void on_node_bound(void *data, uint32_t global_id)
76
77
}
78
79
80
-static int execute_match(void *data, const char *action, const char *val, int len)
81
+static int execute_match(void *data, const char *location, const char *action,
82
+ const char *val, size_t len)
83
{
84
struct client *client = data;
85
if (spa_streq(action, "update-props"))
86
87
return 1;
88
}
89
90
-static int apply_jack_rules(void *data, const char *location, const char *section,
91
- const char *str, size_t len)
92
-{
93
- struct client *client = data;
94
- const struct pw_properties *p =
95
- pw_context_get_properties(client->context.context);
96
-
97
- if (p != NULL)
98
- pw_jack_match_rules(str, len, &p->dict, execute_match, client);
99
-
100
- return 0;
101
-}
102
-
103
SPA_EXPORT
104
jack_client_t * jack_client_open (const char *client_name,
105
jack_options_t options,
106
107
if ((str = getenv("PIPEWIRE_PROPS")) != NULL)
108
pw_properties_update_string(client->props, str, strlen(str));
109
110
-
111
- pw_context_conf_section_for_each(client->context.context, "jack.rules",
112
- apply_jack_rules, client);
113
+ pw_context_conf_section_match_rules(client->context.context, "jack.rules",
114
+ &client->props->dict, execute_match, client);
115
116
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
117
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false);
118
client->short_name = pw_properties_get_bool(client->props, "jack.short-name", false);
119
client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false);
120
client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true);
121
+ client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false);
122
123
client->self_connect_mode = SELF_CONNECT_ALLOW;
124
if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) {
125
126
spa_list_init(&client->mix);
127
spa_list_init(&client->free_mix);
128
129
- pw_map_init(&client->ports[SPA_DIRECTION_INPUT], MAX_PORTS, 32);
130
- pw_map_init(&client->ports[SPA_DIRECTION_OUTPUT], MAX_PORTS, 32);
131
+ pw_map_init(&client->ports[SPA_DIRECTION_INPUT], 32, 32);
132
+ pw_map_init(&client->ports[SPA_DIRECTION_OUTPUT], 32, 32);
133
spa_list_init(&client->free_ports);
134
135
pw_thread_loop_start(client->context.loop);
136
137
pw_properties_set(client->props, PW_KEY_MEDIA_ROLE, "DSP");
138
if (pw_properties_get(client->props, PW_KEY_NODE_ALWAYS_PROCESS) == NULL)
139
pw_properties_set(client->props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
140
+ if (pw_properties_get(client->props, PW_KEY_NODE_LOCK_QUANTUM) == NULL)
141
+ pw_properties_set(client->props, PW_KEY_NODE_LOCK_QUANTUM, "true");
142
pw_properties_set(client->props, PW_KEY_NODE_TRANSPORT_SYNC, "true");
143
144
client->node = pw_core_create_object(client->core,
145
146
&client->proxy_listener, &node_proxy_events, client);
147
148
client->info = SPA_NODE_INFO_INIT();
149
- client->info.max_input_ports = MAX_PORTS;
150
- client->info.max_output_ports = MAX_PORTS;
151
+ client->info.max_input_ports = UINT32_MAX;
152
+ client->info.max_output_ports = UINT32_MAX;
153
client->info.change_mask = SPA_NODE_CHANGE_MASK_FLAGS |
154
SPA_NODE_CHANGE_MASK_PROPS;
155
client->info.flags = SPA_NODE_FLAG_RT;
156
157
158
pw_thread_loop_stop(c->context.loop);
159
160
- if (c->registry)
161
+ if (c->registry) {
162
+ spa_hook_remove(&c->registry_listener);
163
pw_proxy_destroy((struct pw_proxy*)c->registry);
164
+ }
165
if (c->metadata && c->metadata->proxy) {
166
pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy);
167
}
168
+ spa_hook_remove(&c->core_listener);
169
pw_core_disconnect(c->core);
170
pw_context_destroy(c->context.context);
171
172
173
int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes)
174
{
175
struct client *c = (struct client *) client;
176
- char latency[128];
177
178
spa_return_val_if_fail(c != NULL, -EINVAL);
179
180
- snprintf(latency, sizeof(latency), "%d/%d", nframes, jack_get_sample_rate(client));
181
- pw_log_info("%p: buffer-size %s", client, latency);
182
+ pw_log_info("%p: buffer-size %u", client, nframes);
183
184
pw_thread_loop_lock(c->context.loop);
185
- pw_properties_set(c->props, PW_KEY_NODE_LATENCY, latency);
186
pw_properties_setf(c->props, PW_KEY_NODE_FORCE_QUANTUM, "%u", nframes);
187
188
c->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS;
189
190
{
191
struct mix *mix;
192
void *ptr = p->emptyptr;
193
- struct spa_pod_sequence *seq[CONNECTION_NUM_FOR_PORT];
194
+ struct spa_pod_sequence *seq[MAX_MIDI_MIX];
195
uint32_t n_seq = 0;
196
197
jack_midi_clear_buffer(ptr);
198
199
continue;
200
201
pipewire-0.3.45.tar.gz/po/LINGUAS -> pipewire-0.3.47.tar.gz/po/LINGUAS
Changed
9
1
2
pl
3
pt_BR
4
pt
5
+ro
6
ru
7
sk
8
sr@latin
9
pipewire-0.3.45.tar.gz/po/POTFILES.in -> pipewire-0.3.47.tar.gz/po/POTFILES.in
Changed
9
1
2
src/daemon/pipewire.desktop.in
3
src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
4
src/modules/module-protocol-pulse/modules/module-tunnel-source.c
5
+src/modules/module-fallback-sink.c
6
src/modules/module-pulse-tunnel.c
7
src/modules/module-zeroconf-discover.c
8
src/tools/pw-cat.c
9
pipewire-0.3.47.tar.gz/po/ro.po
Added
201
1
2
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+# This file is distributed under the same license as the pipewire package.
4
+#
5
+# Sergiu Bivol <sergiu@cip.md>, 2022.
6
+msgid ""
7
+msgstr ""
8
+"Project-Id-Version: pipewire\n"
9
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/issues/"
10
+"new\n"
11
+"POT-Creation-Date: 2021-11-17 15:06+0100\n"
12
+"PO-Revision-Date: 2022-02-05 12:06+0000\n"
13
+"Last-Translator: Sergiu Bivol <sergiu@cip.md>\n"
14
+"Language-Team: Romanian\n"
15
+"Language: ro\n"
16
+"MIME-Version: 1.0\n"
17
+"Content-Type: text/plain; charset=UTF-8\n"
18
+"Content-Transfer-Encoding: 8bit\n"
19
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 <"
20
+" 20)) ? 1 : 2;\n"
21
+"X-Generator: Lokalize 21.12.2\n"
22
+
23
+#: src/daemon/pipewire.c:45
24
+#, c-format
25
+msgid ""
26
+"%s [options]\n"
27
+" -h, --help Show this help\n"
28
+" --version Show version\n"
29
+" -c, --config Load config (Default %s)\n"
30
+msgstr ""
31
+"%s [opțiuni]\n"
32
+" -h, --help Arată acest ajutor\n"
33
+" --version Arată versiunea\n"
34
+" -c, --config Încarcă configurare (implicit %s)\n"
35
+
36
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:185
37
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:185
38
+#, c-format
39
+msgid "Tunnel to %s/%s"
40
+msgstr "Tunelează spre %s/%s"
41
+
42
+#: src/modules/module-pulse-tunnel.c:536
43
+#, c-format
44
+msgid "Tunnel for %s@%s"
45
+msgstr "Tunelează pentru %s@%s"
46
+
47
+#: src/modules/module-zeroconf-discover.c:332
48
+msgid "Unknown device"
49
+msgstr "Dispozitiv necunoscut"
50
+
51
+#: src/modules/module-zeroconf-discover.c:344
52
+#, c-format
53
+msgid "%s on %s@%s"
54
+msgstr "%s pe %s@%s"
55
+
56
+#: src/modules/module-zeroconf-discover.c:348
57
+#, c-format
58
+msgid "%s on %s"
59
+msgstr "%s pe %s"
60
+
61
+#: src/tools/pw-cat.c:1058
62
+#, c-format
63
+msgid ""
64
+"%s [options] <file>\n"
65
+" -h, --help Show this help\n"
66
+" --version Show version\n"
67
+" -v, --verbose Enable verbose operations\n"
68
+"\n"
69
+msgstr ""
70
+"%s [opțiuni] <fișier>\n"
71
+" -h, --help Arată acest ajutor\n"
72
+" --version Arată versiunea\n"
73
+" -v, --verbose Activează operații verboase\n"
74
+"\n"
75
+
76
+#: src/tools/pw-cat.c:1065
77
+#, c-format
78
+msgid ""
79
+" -R, --remote Remote daemon name\n"
80
+" --media-type Set media type (default %s)\n"
81
+" --media-category Set media category (default %s)\n"
82
+" --media-role Set media role (default %s)\n"
83
+" --target Set node target (default %s)\n"
84
+" 0 means don't link\n"
85
+" --latency Set node latency (default %s)\n"
86
+" Xunit (unit = s, ms, us, ns)\n"
87
+" or direct samples (256)\n"
88
+" the rate is the one of the source "
89
+"file\n"
90
+" --list-targets List available targets for --target\n"
91
+"\n"
92
+msgstr ""
93
+" -R, --remote Denumirea demonului distant\n"
94
+" --media-type Stabilește tipul mediului (implicit "
95
+"%s)\n"
96
+" --media-category Stabilește categoria mediului"
97
+" (implicit %s)\n"
98
+" --media-role Stabilește rolul mediului (implicit "
99
+"%s)\n"
100
+" --target Stabilește ținta nodului (implicit "
101
+"%s)\n"
102
+" 0 înseamnă „nu lega”\n"
103
+" --latency Stabilește latența nodului (implicit "
104
+"%s)\n"
105
+" Xunit (unitate = s, ms, us, ns)\n"
106
+" sau mostre directe (256)\n"
107
+" rata este cea a fișierului sursă\n"
108
+" --list-targets Enumeră țintele disponibile pentru"
109
+" --target\n"
110
+"\n"
111
+
112
+#: src/tools/pw-cat.c:1083
113
+#, c-format
114
+msgid ""
115
+" --rate Sample rate (req. for rec) (default "
116
+"%u)\n"
117
+" --channels Number of channels (req. for rec) "
118
+"(default %u)\n"
119
+" --channel-map Channel map\n"
120
+" one of: \"stereo\", "
121
+"\"surround-51\",... or\n"
122
+" comma separated list of channel "
123
+"names: eg. \"FL,FR\"\n"
124
+" --format Sample format %s (req. for rec) "
125
+"(default %s)\n"
126
+" --volume Stream volume 0-1.0 (default %.3f)\n"
127
+" -q --quality Resampler quality (0 - 15) (default "
128
+"%d)\n"
129
+"\n"
130
+msgstr ""
131
+" --rate Rată de eșantionare (nec. pt."
132
+" înregistrare) (implicit %u)\n"
133
+" --channels Număr de canale (nec. pt."
134
+" înregistrare) (implicit %u)\n"
135
+" --channel-map Hartă canale\n"
136
+" una dintre: \"stereo\","
137
+" \"surround-51\",... sau listă\n"
138
+" separată prin virgulă cu denumiri"
139
+" de canale: de ex. \"FL,FR\"\n"
140
+" --format Format de eșantionare %s (nec. pt."
141
+" înregistrare) (implicit %s)\n"
142
+" --volume Volum flux 0-1.0 (implicit %.3f)\n"
143
+" -q --quality Calitate de re-eșantionare (0 - 15)"
144
+" (implicit %d)\n"
145
+"\n"
146
+
147
+#: src/tools/pw-cat.c:1100
148
+msgid ""
149
+" -p, --playback Playback mode\n"
150
+" -r, --record Recording mode\n"
151
+" -m, --midi Midi mode\n"
152
+" -d, --dsd DSD mode\n"
153
+"\n"
154
+msgstr ""
155
+" -p, --playback Regim de redare\n"
156
+" -r, --record Regim de înregistrare\n"
157
+" -m, --midi Regim MIDI\n"
158
+" -d, --dsd regim DSD\n"
159
+"\n"
160
+
161
+#: src/tools/pw-cli.c:3018
162
+#, c-format
163
+msgid ""
164
+"%s [options] [command]\n"
165
+" -h, --help Show this help\n"
166
+" --version Show version\n"
167
+" -d, --daemon Start as daemon (Default false)\n"
168
+" -r, --remote Remote daemon name\n"
169
+"\n"
170
+msgstr ""
171
+"%s [opțiuni] [comandă]\n"
172
+" -h, --help Arată acest ajutor\n"
173
+" --version Arată versiunea\n"
174
+" -d, --daemon Pornește ca demon (implicit fals)\n"
175
+" -r, --remote Denumire demon distant\n"
176
+"\n"
177
+
178
+#: spa/plugins/alsa/acp/acp.c:321
179
+msgid "Pro Audio"
180
+msgstr "Pro Audio"
181
+
182
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
183
+#: spa/plugins/bluez5/bluez5-device.c:1145
184
+msgid "Off"
185
+msgstr "Oprit"
186
+
187
+#: spa/plugins/alsa/acp/alsa-mixer.c:2652
188
+msgid "Input"
189
+msgstr "Intrare"
190
+
191
+#: spa/plugins/alsa/acp/alsa-mixer.c:2653
192
+msgid "Docking Station Input"
193
+msgstr "Intrare stație de andocare"
194
+
195
+#: spa/plugins/alsa/acp/alsa-mixer.c:2654
196
+msgid "Docking Station Microphone"
197
+msgstr "Microfon stație de andocare"
198
+
199
+#: spa/plugins/alsa/acp/alsa-mixer.c:2655
200
+msgid "Docking Station Line In"
201
pipewire-0.3.45.tar.gz/po/sv.po -> pipewire-0.3.47.tar.gz/po/sv.po
Changed
201
1
2
# Swedish translation for pipewire.
3
-# Copyright © 2008-2021 Free Software Foundation, Inc.
4
+# Copyright © 2008-2022 Free Software Foundation, Inc.
5
# This file is distributed under the same license as the pipewire package.
6
# Daniel Nylander <po@danielnylander.se>, 2008, 2012.
7
# Josef Andersson <josef.andersson@fripost.org>, 2014, 2017.
8
-# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021.
9
+# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022.
10
#
11
# Termer:
12
# input/output: ingång/utgång (det handlar om ljud)
13
14
"Project-Id-Version: pipewire\n"
15
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
16
"issues\n"
17
-"POT-Creation-Date: 2021-09-21 15:31+0000\n"
18
-"PO-Revision-Date: 2021-09-21 21:51+0200\n"
19
+"POT-Creation-Date: 2022-02-13 15:33+0000\n"
20
+"PO-Revision-Date: 2022-02-14 22:57+0100\n"
21
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
22
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
23
"Language: sv\n"
24
25
"Content-Type: text/plain; charset=UTF-8\n"
26
"Content-Transfer-Encoding: 8bit\n"
27
"Plural-Forms: nplurals=2; plural=n != 1;\n"
28
-"X-Generator: Poedit 3.0\n"
29
+"X-Generator: Poedit 3.0.1\n"
30
31
#: src/daemon/pipewire.c:45
32
#, c-format
33
34
msgid "Start the PipeWire Media System"
35
msgstr "Starta mediasystemet PipeWire"
36
37
-#: src/examples/media-session/alsa-monitor.c:656
38
-#: spa/plugins/alsa/acp/compat.c:189
39
-msgid "Built-in Audio"
40
-msgstr "Inbyggt ljud"
41
-
42
-#: src/examples/media-session/alsa-monitor.c:660
43
-#: spa/plugins/alsa/acp/compat.c:194
44
-msgid "Modem"
45
-msgstr "Modem"
46
-
47
-#: src/examples/media-session/alsa-monitor.c:669
48
-#: src/modules/module-zeroconf-discover.c:296
49
-msgid "Unknown device"
50
-msgstr "Okänd enhet"
51
-
52
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:173
53
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:173
54
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:188
55
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:188
56
#, c-format
57
msgid "Tunnel to %s/%s"
58
msgstr "Tunnel till %s/%s"
59
60
-#: src/modules/module-pulse-tunnel.c:534
61
+#: src/modules/module-fallback-sink.c:51
62
+msgid "Dummy Output"
63
+msgstr "Attrapputgång"
64
+
65
+#: src/modules/module-pulse-tunnel.c:536
66
#, c-format
67
msgid "Tunnel for %s@%s"
68
msgstr "Tunnel för %s@%s"
69
70
-#: src/modules/module-zeroconf-discover.c:308
71
+#: src/modules/module-zeroconf-discover.c:332
72
+msgid "Unknown device"
73
+msgstr "Okänd enhet"
74
+
75
+#: src/modules/module-zeroconf-discover.c:344
76
#, c-format
77
msgid "%s on %s@%s"
78
msgstr "%s på %s@%s"
79
80
-#: src/modules/module-zeroconf-discover.c:312
81
+#: src/modules/module-zeroconf-discover.c:348
82
#, c-format
83
msgid "%s on %s"
84
msgstr "%s på %s"
85
86
-#: src/tools/pw-cat.c:1055
87
+#: src/tools/pw-cat.c:1075
88
#, c-format
89
msgid ""
90
"%s [options] <file>\n"
91
92
" -v, --verbose Aktivera utförliga operationer\n"
93
"\n"
94
95
-#: src/tools/pw-cat.c:1062
96
+#: src/tools/pw-cat.c:1082
97
#, c-format
98
msgid ""
99
" -R, --remote Remote daemon name\n"
100
101
" --list-targets Lista tillgängliga mål för --target\n"
102
"\n"
103
104
-#: src/tools/pw-cat.c:1080
105
+#: src/tools/pw-cat.c:1100
106
#, c-format
107
msgid ""
108
" --rate Sample rate (req. for rec) (default "
109
110
"%d)\n"
111
"\n"
112
113
-#: src/tools/pw-cat.c:1097
114
+#: src/tools/pw-cat.c:1117
115
msgid ""
116
" -p, --playback Playback mode\n"
117
" -r, --record Recording mode\n"
118
119
" -d, --dsd DSD-läge\n"
120
"\n"
121
122
-#: src/tools/pw-cli.c:2954
123
+#: src/tools/pw-cli.c:3050
124
#, c-format
125
msgid ""
126
"%s [options] [command]\n"
127
128
" -r, --remote Fjärrdemonnamn\n"
129
"\n"
130
131
-#: spa/plugins/alsa/acp/acp.c:310
132
+#: spa/plugins/alsa/acp/acp.c:321
133
msgid "Pro Audio"
134
msgstr "Professionellt ljud"
135
136
-#: spa/plugins/alsa/acp/acp.c:433 spa/plugins/alsa/acp/alsa-mixer.c:4648
137
-#: spa/plugins/bluez5/bluez5-device.c:1135
138
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
139
+#: spa/plugins/bluez5/bluez5-device.c:1159
140
msgid "Off"
141
msgstr "Av"
142
143
144
145
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
146
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
147
-#: spa/plugins/bluez5/bluez5-device.c:1292
148
+#: spa/plugins/bluez5/bluez5-device.c:1328
149
msgid "Microphone"
150
msgstr "Mikrofon"
151
152
153
msgstr "Ingen basökning"
154
155
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
156
-#: spa/plugins/bluez5/bluez5-device.c:1297
157
+#: spa/plugins/bluez5/bluez5-device.c:1333
158
msgid "Speaker"
159
msgstr "Högtalare"
160
161
162
163
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
164
#: spa/plugins/alsa/acp/alsa-mixer.c:4642
165
-#: spa/plugins/bluez5/bluez5-device.c:1282
166
+#: spa/plugins/bluez5/bluez5-device.c:1318
167
msgid "Headset"
168
msgstr "Headset"
169
170
171
#: spa/plugins/alsa/acp/alsa-util.c:1239
172
#, c-format
173
msgid ""
174
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
175
-"%lu ms).\n"
176
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
177
+"(%s%lu ms).\n"
178
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
179
"to the ALSA developers."
180
msgid_plural ""
181
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
182
-"%lu ms).\n"
183
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
184
+"(%s%lu ms).\n"
185
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
186
"to the ALSA developers."
187
msgstr[0] ""
188
189
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
190
"problemet till ALSA-utvecklarna."
191
192
-#: spa/plugins/alsa/acp/channelmap.h:466
193
+#: spa/plugins/alsa/acp/channelmap.h:464
194
msgid "(invalid)"
195
msgstr "(ogiltig)"
196
197
-#: spa/plugins/bluez5/bluez5-device.c:1145
198
+#: spa/plugins/alsa/acp/compat.c:189
199
+msgid "Built-in Audio"
200
+msgstr "Inbyggt ljud"
201
pipewire-0.3.45.tar.gz/spa/include/meson.build -> pipewire-0.3.47.tar.gz/spa/include/meson.build
Changed
9
1
2
'control',
3
'debug',
4
'graph',
5
+ 'interfaces',
6
'monitor',
7
'node',
8
'param',
9
pipewire-0.3.45.tar.gz/spa/include/spa/debug/buffer.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/buffer.h
Changed
17
1
2
* \{
3
*/
4
5
+#include <spa/debug/log.h>
6
#include <spa/debug/mem.h>
7
#include <spa/debug/types.h>
8
#include <spa/buffer/type-info.h>
9
10
-#ifndef spa_debug
11
-#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); })
12
-#endif
13
-
14
static inline int spa_debug_buffer(int indent, const struct spa_buffer *buffer)
15
{
16
uint32_t i;
17
pipewire-0.3.45.tar.gz/spa/include/spa/debug/dict.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/dict.h
Changed
15
1
2
* \{
3
*/
4
5
+#include <spa/debug/log.h>
6
#include <spa/utils/dict.h>
7
8
-#ifndef spa_debug
9
-#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); })
10
-#endif
11
-
12
static inline int spa_debug_dict(int indent, const struct spa_dict *dict)
13
{
14
const struct spa_dict_item *item;
15
pipewire-0.3.45.tar.gz/spa/include/spa/debug/format.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/format.h
Changed
132
1
2
*/
3
4
#include <spa/pod/parser.h>
5
+#include <spa/debug/log.h>
6
#include <spa/debug/types.h>
7
#include <spa/param/type-info.h>
8
#include <spa/param/format-utils.h>
9
10
{
11
switch (type) {
12
case SPA_TYPE_Bool:
13
- fprintf(stderr, "%s", *(int32_t *) body ? "true" : "false");
14
+ spa_debugn("%s", *(int32_t *) body ? "true" : "false");
15
break;
16
case SPA_TYPE_Id:
17
{
18
19
snprintf(tmp, sizeof(tmp), "%d", *(int32_t*)body);
20
str = tmp;
21
}
22
- fprintf(stderr, "%s", str);
23
+ spa_debugn("%s", str);
24
break;
25
}
26
case SPA_TYPE_Int:
27
- fprintf(stderr, "%d", *(int32_t *) body);
28
+ spa_debugn("%d", *(int32_t *) body);
29
break;
30
case SPA_TYPE_Long:
31
- fprintf(stderr, "%" PRIi64, *(int64_t *) body);
32
+ spa_debugn("%" PRIi64, *(int64_t *) body);
33
break;
34
case SPA_TYPE_Float:
35
- fprintf(stderr, "%f", *(float *) body);
36
+ spa_debugn("%f", *(float *) body);
37
break;
38
case SPA_TYPE_Double:
39
- fprintf(stderr, "%g", *(double *) body);
40
+ spa_debugn("%g", *(double *) body);
41
break;
42
case SPA_TYPE_String:
43
- fprintf(stderr, "%s", (char *) body);
44
+ spa_debugn("%s", (char *) body);
45
break;
46
case SPA_TYPE_Rectangle:
47
{
48
struct spa_rectangle *r = (struct spa_rectangle *)body;
49
- fprintf(stderr, "%" PRIu32 "x%" PRIu32, r->width, r->height);
50
+ spa_debugn("%" PRIu32 "x%" PRIu32, r->width, r->height);
51
break;
52
}
53
case SPA_TYPE_Fraction:
54
{
55
struct spa_fraction *f = (struct spa_fraction *)body;
56
- fprintf(stderr, "%" PRIu32 "/%" PRIu32, f->num, f->denom);
57
+ spa_debugn("%" PRIu32 "/%" PRIu32, f->num, f->denom);
58
break;
59
}
60
case SPA_TYPE_Bitmap:
61
- fprintf(stderr, "Bitmap");
62
+ spa_debugn("Bitmap");
63
break;
64
case SPA_TYPE_Bytes:
65
- fprintf(stderr, "Bytes");
66
+ spa_debugn("Bytes");
67
break;
68
case SPA_TYPE_Array:
69
{
70
71
struct spa_pod_array_body *b = (struct spa_pod_array_body *)body;
72
int i = 0;
73
info = info && info->values ? info->values : info;
74
- fprintf(stderr, "< ");
75
+ spa_debugn("< ");
76
SPA_POD_ARRAY_BODY_FOREACH(b, size, p) {
77
if (i++ > 0)
78
- fprintf(stderr, ", ");
79
+ spa_debugn(", ");
80
spa_debug_format_value(info, b->child.type, p, b->child.size);
81
}
82
- fprintf(stderr, " >");
83
+ spa_debugn(" >");
84
break;
85
}
86
default:
87
- fprintf(stderr, "INVALID type %d", type);
88
+ spa_debugn("INVALID type %d", type);
89
break;
90
}
91
return 0;
92
93
media_type = spa_debug_type_find_name(spa_type_media_type, mtype);
94
media_subtype = spa_debug_type_find_name(spa_type_media_subtype, mstype);
95
96
- fprintf(stderr, "%*s %s/%s\n", indent, "",
97
+ spa_debug("%*s %s/%s", indent, "",
98
media_type ? spa_debug_type_short_name(media_type) : "unknown",
99
media_subtype ? spa_debug_type_short_name(media_subtype) : "unknown");
100
101
102
ti = spa_debug_type_find(info, prop->key);
103
key = ti ? ti->name : NULL;
104
105
- fprintf(stderr, "%*s %16s : (%s) ", indent, "",
106
+ spa_debugn("%*s %16s : (%s) ", indent, "",
107
key ? spa_debug_type_short_name(key) : "unknown",
108
spa_debug_type_short_name(spa_types[type].name));
109
110
111
break;
112
}
113
114
- fprintf(stderr, "%s", ssep);
115
+ spa_debugn("%s", ssep);
116
117
for (i = 1; i < n_vals; i++) {
118
vals = SPA_PTROFF(vals, size, void);
119
if (i > 1)
120
- fprintf(stderr, "%s", sep);
121
+ spa_debugn("%s", sep);
122
spa_debug_format_value(ti ? ti->values : NULL, type, vals, size);
123
}
124
- fprintf(stderr, "%s", esep);
125
+ spa_debugn("%s", esep);
126
}
127
- fprintf(stderr, "\n");
128
+ spa_debugn("\n");
129
}
130
return 0;
131
}
132
pipewire-0.3.47.tar.gz/spa/include/spa/debug/log.h
Added
55
1
2
+/* Simple Plugin API
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef SPA_DEBUG_LOG_H
27
+#define SPA_DEBUG_LOG_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+#include <stdio.h>
34
+/**
35
+ * \addtogroup spa_debug
36
+ * \{
37
+ */
38
+
39
+#ifndef spa_debug
40
+#define spa_debug(fmt,...) ({ printf(fmt"\n", ## __VA_ARGS__); })
41
+#endif
42
+#ifndef spa_debugn
43
+#define spa_debugn(fmt,...) ({ printf(fmt, ## __VA_ARGS__); })
44
+#endif
45
+
46
+/**
47
+ * \}
48
+ */
49
+
50
+#ifdef __cplusplus
51
+} /* extern "C" */
52
+#endif
53
+
54
+#endif /* SPA_DEBUG_LOGH */
55
pipewire-0.3.45.tar.gz/spa/include/spa/debug/mem.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/mem.h
Changed
21
1
2
extern "C" {
3
#endif
4
5
+#include <inttypes.h>
6
+
7
/**
8
* \addtogroup spa_debug
9
* \{
10
*/
11
12
-#include <spa/utils/dict.h>
13
-
14
-#ifndef spa_debug
15
-#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); })
16
-#endif
17
+#include <spa/debug/log.h>
18
19
static inline int spa_debug_mem(int indent, const void *data, size_t size)
20
{
21
pipewire-0.3.45.tar.gz/spa/include/spa/debug/node.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/node.h
Changed
15
1
2
*/
3
4
#include <spa/node/node.h>
5
+#include <spa/debug/log.h>
6
#include <spa/debug/dict.h>
7
8
-#ifndef spa_debug
9
-#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); })
10
-#endif
11
-
12
static inline int spa_debug_port_info(int indent, const struct spa_port_info *info)
13
{
14
spa_debug("%*s" "struct spa_port_info %p:", indent, "", info);
15
pipewire-0.3.45.tar.gz/spa/include/spa/debug/pod.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/pod.h
Changed
18
1
2
* \{
3
*/
4
5
+#include <spa/debug/log.h>
6
#include <spa/debug/mem.h>
7
#include <spa/debug/types.h>
8
#include <spa/pod/pod.h>
9
#include <spa/pod/iter.h>
10
11
-#ifndef spa_debug
12
-#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); })
13
-#endif
14
-
15
static inline int
16
spa_debug_pod_value(int indent, const struct spa_type_info *info,
17
uint32_t type, void *body, uint32_t size)
18
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces
Added
2
1
+(directory)
2
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces/audio
Added
2
1
+(directory)
2
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces/audio/aec.h
Added
97
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+
27
+#include <spa/utils/dict.h>
28
+#include <spa/utils/hook.h>
29
+#include <spa/param/audio/raw.h>
30
+
31
+#ifndef SPA_AUDIO_AEC_H
32
+#define SPA_AUDIO_AEC_H
33
+
34
+#ifdef __cplusplus
35
+extern "C" {
36
+#endif
37
+
38
+#define SPA_TYPE_INTERFACE_AUDIO_AEC SPA_TYPE_INFO_INTERFACE_BASE "Audio:AEC"
39
+
40
+#define SPA_VERSION_AUDIO_AEC 0
41
+struct spa_audio_aec {
42
+ struct spa_interface iface;
43
+ const char *name;
44
+ const struct spa_dict *info;
45
+ const char *latency;
46
+};
47
+
48
+struct spa_audio_aec_info {
49
+#define SPA_AUDIO_AEC_CHANGE_MASK_PROPS (1u<<0)
50
+ uint64_t change_mask;
51
+
52
+ const struct spa_dict *props;
53
+};
54
+
55
+struct spa_audio_aec_events {
56
+#define SPA_VERSION_AUDIO_AEC_EVENTS 0
57
+ uint32_t version; /**< version of this structure */
58
+
59
+ /** Emitted when info changes */
60
+ void (*info) (void *data, const struct spa_audio_aec_info *info);
61
+};
62
+
63
+struct spa_audio_aec_methods {
64
+#define SPA_VERSION_AUDIO_AEC_METHODS 0
65
+ uint32_t version;
66
+
67
+ int (*add_listener) (void *object,
68
+ struct spa_hook *listener,
69
+ const struct spa_audio_aec_events *events,
70
+ void *data);
71
+
72
+ int (*init) (void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info);
73
+ int (*run) (void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples);
74
+ int (*set_props) (void *data, const struct spa_dict *args);
75
+};
76
+
77
+#define spa_audio_aec_method(o,method,version,...) \
78
+({ \
79
+ int _res = -ENOTSUP; \
80
+ struct spa_audio_aec *_o = o; \
81
+ spa_interface_call_res(&_o->iface, \
82
+ struct spa_audio_aec_methods, _res, \
83
+ method, version, ##__VA_ARGS__); \
84
+ _res; \
85
+})
86
+
87
+#define spa_audio_aec_add_listener(o,...) spa_audio_aec_method(o, add_listener, 0, __VA_ARGS__)
88
+#define spa_audio_aec_init(o,...) spa_audio_aec_method(o, init, 0, __VA_ARGS__)
89
+#define spa_audio_aec_run(o,...) spa_audio_aec_method(o, run, 0, __VA_ARGS__)
90
+#define spa_audio_aec_set_props(o,...) spa_audio_aec_method(o, set_props, 0, __VA_ARGS__)
91
+
92
+#ifdef __cplusplus
93
+} /* extern "C" */
94
+#endif
95
+
96
+#endif /* SPA_AUDIO_AEC_H */
97
pipewire-0.3.45.tar.gz/spa/include/spa/support/loop.h -> pipewire-0.3.47.tar.gz/spa/include/spa/support/loop.h
Changed
10
1
2
int fd;
3
uint32_t mask;
4
uint32_t rmask;
5
+ /* private data for the loop implementer */
6
+ void *priv;
7
};
8
9
typedef int (*spa_invoke_func_t) (struct spa_loop *loop,
10
pipewire-0.3.45.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.47.tar.gz/spa/include/spa/utils/defs.h
Changed
11
1
2
#define SPA_RESTRICT
3
#endif
4
5
+#define SPA_ROUND_DOWN(num,value) ((num) - ((num) % (value)))
6
+#define SPA_ROUND_UP(num,value) ((((num) + (value) - 1) / (value)) * (value))
7
+
8
#define SPA_ROUND_DOWN_N(num,align) ((num) & ~((align) - 1))
9
#define SPA_ROUND_UP_N(num,align) SPA_ROUND_DOWN_N((num) + ((align) - 1),align)
10
11
pipewire-0.3.45.tar.gz/spa/include/spa/utils/names.h -> pipewire-0.3.47.tar.gz/spa/include/spa/utils/names.h
Changed
10
1
2
#define SPA_NAME_AUDIO_ADAPT "audio.adapt" /**< combination of a node and an
3
* audio.convert. Does clock slaving */
4
5
+#define SPA_NAME_AEC "audio.aec" /**< Echo canceling */
6
+
7
/** video processing */
8
#define SPA_NAME_VIDEO_PROCESS_FORMAT "video.process.format" /**< processes raw video from one format
9
* to another */
10
pipewire-0.3.45.tar.gz/spa/meson.build -> pipewire-0.3.47.tar.gz/spa/meson.build
Changed
18
1
2
3
subdir('include')
4
5
-if not get_option('spa-plugins').disabled()
6
+if get_option('spa-plugins').allowed()
7
udevrulesdir = get_option('udevrulesdir')
8
if udevrulesdir == ''
9
# absolute path, otherwise meson prepends the prefix
10
11
12
subdir('tools')
13
subdir('tests')
14
-if not get_option('examples').disabled()
15
+if get_option('examples').allowed()
16
subdir('examples')
17
endif
18
pipewire-0.3.47.tar.gz/spa/plugins/aec
Added
2
1
+(directory)
2
pipewire-0.3.47.tar.gz/spa/plugins/aec/aec-null.c
Added
181
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/interfaces/audio/aec.h>
27
+#include <spa/support/log.h>
28
+#include <spa/utils/string.h>
29
+#include <spa/utils/names.h>
30
+#include <spa/support/plugin.h>
31
+
32
+struct impl {
33
+ struct spa_handle handle;
34
+ struct spa_audio_aec aec;
35
+ struct spa_log *log;
36
+
37
+ struct spa_hook_list hooks_list;
38
+
39
+ uint32_t channels;
40
+};
41
+
42
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.aec.null");
43
+#undef SPA_LOG_TOPIC_DEFAULT
44
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
45
+
46
+static int null_init(void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info)
47
+{
48
+ struct impl *impl = data;
49
+ impl->channels = info->channels;
50
+ return 0;
51
+}
52
+
53
+static int null_run(void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples)
54
+{
55
+ struct impl *impl = data;
56
+ uint32_t i;
57
+ for (i = 0; i < impl->channels; i++)
58
+ memcpy(out[i], rec[i], n_samples * sizeof(float));
59
+ return 0;
60
+}
61
+
62
+static struct spa_audio_aec_methods impl_aec = {
63
+ .init = null_init,
64
+ .run = null_run,
65
+};
66
+
67
+static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface)
68
+{
69
+ struct impl *impl;
70
+
71
+ spa_return_val_if_fail(handle != NULL, -EINVAL);
72
+ spa_return_val_if_fail(interface != NULL, -EINVAL);
73
+
74
+ impl = (struct impl *) handle;
75
+
76
+ if (spa_streq(type, SPA_TYPE_INTERFACE_AUDIO_AEC))
77
+ *interface = &impl->aec;
78
+ else
79
+ return -ENOENT;
80
+
81
+ return 0;
82
+}
83
+
84
+static int impl_clear(struct spa_handle *handle)
85
+{
86
+ spa_return_val_if_fail(handle != NULL, -EINVAL);
87
+
88
+ return 0;
89
+}
90
+
91
+static size_t
92
+impl_get_size(const struct spa_handle_factory *factory,
93
+ const struct spa_dict *params)
94
+{
95
+ return sizeof(struct impl);
96
+}
97
+
98
+static int
99
+impl_init(const struct spa_handle_factory *factory,
100
+ struct spa_handle *handle,
101
+ const struct spa_dict *info,
102
+ const struct spa_support *support,
103
+ uint32_t n_support)
104
+{
105
+ struct impl *impl;
106
+
107
+ spa_return_val_if_fail(factory != NULL, -EINVAL);
108
+ spa_return_val_if_fail(handle != NULL, -EINVAL);
109
+
110
+ handle->get_interface = impl_get_interface;
111
+ handle->clear = impl_clear;
112
+
113
+ impl = (struct impl *) handle;
114
+
115
+ impl->aec.iface = SPA_INTERFACE_INIT(
116
+ SPA_TYPE_INTERFACE_AUDIO_AEC,
117
+ SPA_VERSION_AUDIO_AEC,
118
+ &impl_aec, impl);
119
+ impl->aec.name = "null";
120
+ impl->aec.info = NULL;
121
+ impl->aec.latency = NULL;
122
+
123
+ impl->log = (struct spa_log*)spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
124
+ spa_log_topic_init(impl->log, &log_topic);
125
+
126
+ spa_hook_list_init(&impl->hooks_list);
127
+
128
+ return 0;
129
+}
130
+
131
+static const struct spa_interface_info impl_interfaces[] = {
132
+ {SPA_TYPE_INTERFACE_AUDIO_AEC,},
133
+};
134
+
135
+static int
136
+impl_enum_interface_info(const struct spa_handle_factory *factory,
137
+ const struct spa_interface_info **info,
138
+ uint32_t *index)
139
+{
140
+ spa_return_val_if_fail(factory != NULL, -EINVAL);
141
+ spa_return_val_if_fail(info != NULL, -EINVAL);
142
+ spa_return_val_if_fail(index != NULL, -EINVAL);
143
+
144
+ switch (*index) {
145
+ case 0:
146
+ *info = &impl_interfaces[*index];
147
+ break;
148
+ default:
149
+ return 0;
150
+ }
151
+ (*index)++;
152
+ return 1;
153
+}
154
+
155
+const struct spa_handle_factory spa_aec_exaudio_factory = {
156
+ SPA_VERSION_HANDLE_FACTORY,
157
+ SPA_NAME_AEC,
158
+ NULL,
159
+ impl_get_size,
160
+ impl_init,
161
+ impl_enum_interface_info,
162
+};
163
+
164
+
165
+SPA_EXPORT
166
+int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
167
+{
168
+ spa_return_val_if_fail(factory != NULL, -EINVAL);
169
+ spa_return_val_if_fail(index != NULL, -EINVAL);
170
+
171
+ switch (*index) {
172
+ case 0:
173
+ *factory = &spa_aec_exaudio_factory;
174
+ break;
175
+ default:
176
+ return 0;
177
+ }
178
+ (*index)++;
179
+ return 1;
180
+}
181
pipewire-0.3.47.tar.gz/spa/plugins/aec/aec-webrtc.cpp
Added
201
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com>
5
+ * © 2021 Arun Raghavan <arun@asymptotic.io>
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice (including the next
15
+ * paragraph) shall be included in all copies or substantial portions of the
16
+ * Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ */
26
+
27
+#include <memory>
28
+#include <utility>
29
+
30
+#include <spa/interfaces/audio/aec.h>
31
+#include <spa/support/log.h>
32
+#include <spa/utils/string.h>
33
+#include <spa/utils/names.h>
34
+#include <spa/support/plugin.h>
35
+
36
+#include <webrtc/modules/audio_processing/include/audio_processing.h>
37
+#include <webrtc/modules/interface/module_common_types.h>
38
+#include <webrtc/system_wrappers/include/trace.h>
39
+
40
+struct impl_data {
41
+ struct spa_handle handle;
42
+ struct spa_audio_aec aec;
43
+
44
+ struct spa_log *log;
45
+ std::unique_ptr<webrtc::AudioProcessing> apm;
46
+ spa_audio_info_raw info;
47
+ std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer;
48
+};
49
+
50
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.eac.webrtc");
51
+#undef SPA_LOG_TOPIC_DEFAULT
52
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
53
+
54
+static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bool default_value) {
55
+ const char *str_val;
56
+ bool value = default_value;
57
+ str_val = spa_dict_lookup(args, key);
58
+ if (str_val != NULL)
59
+ value =spa_atob(str_val);
60
+
61
+ return value;
62
+}
63
+
64
+static int webrtc_init(void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info)
65
+{
66
+ auto impl = reinterpret_cast<struct impl_data*>(data);
67
+
68
+ bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true);
69
+ bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true);
70
+ bool high_pass_filter = webrtc_get_spa_bool(args, "webrtc.high_pass_filter", true);
71
+ bool noise_suppression = webrtc_get_spa_bool(args, "webrtc.noise_suppression", true);
72
+ bool voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true);
73
+
74
+ // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech,
75
+ // result in very poor performance, disable by default
76
+ bool gain_control = webrtc_get_spa_bool(args, "webrtc.gain_control", false);
77
+
78
+ // Disable experimental flags by default
79
+ bool experimental_agc = webrtc_get_spa_bool(args, "webrtc.experimental_agc", false);
80
+ bool experimental_ns = webrtc_get_spa_bool(args, "webrtc.experimental_ns", false);
81
+
82
+ // FIXME: Intelligibility enhancer is not currently supported
83
+ // This filter will modify playback buffer (when calling ProcessReverseStream), but now
84
+ // playback buffer modifications are discarded.
85
+
86
+ webrtc::Config config;
87
+ config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(extended_filter));
88
+ config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(delay_agnostic));
89
+ config.Set<webrtc::ExperimentalAgc>(new webrtc::ExperimentalAgc(experimental_agc));
90
+ config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(experimental_ns));
91
+
92
+ webrtc::ProcessingConfig pconfig = {{
93
+ webrtc::StreamConfig(info->rate, info->channels, false), /* input stream */
94
+ webrtc::StreamConfig(info->rate, info->channels, false), /* output stream */
95
+ webrtc::StreamConfig(info->rate, info->channels, false), /* reverse input stream */
96
+ webrtc::StreamConfig(info->rate, info->channels, false), /* reverse output stream */
97
+ }};
98
+
99
+ auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
100
+ if (apm->Initialize(pconfig) != webrtc::AudioProcessing::kNoError) {
101
+ spa_log_error(impl->log, "Error initialising webrtc audio processing module");
102
+ return -1;
103
+ }
104
+
105
+ apm->high_pass_filter()->Enable(high_pass_filter);
106
+ // Always disable drift compensation since it requires drift sampling
107
+ apm->echo_cancellation()->enable_drift_compensation(false);
108
+ apm->echo_cancellation()->Enable(true);
109
+ // TODO: wire up supression levels to args
110
+ apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression);
111
+ apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh);
112
+ apm->noise_suppression()->Enable(noise_suppression);
113
+ apm->voice_detection()->Enable(voice_detection);
114
+ // TODO: wire up AGC parameters to args
115
+ apm->gain_control()->set_analog_level_limits(0, 255);
116
+ apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
117
+ apm->gain_control()->Enable(gain_control);
118
+ impl->apm = std::move(apm);
119
+ impl->info = *info;
120
+ impl->play_buffer = std::make_unique<float *[]>(info->channels);
121
+ impl->rec_buffer = std::make_unique<float *[]>(info->channels);
122
+ impl->out_buffer = std::make_unique<float *[]>(info->channels);
123
+ return 0;
124
+}
125
+
126
+static int webrtc_run(void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples)
127
+{
128
+ auto impl = reinterpret_cast<struct impl_data*>(data);
129
+ webrtc::StreamConfig config =
130
+ webrtc::StreamConfig(impl->info.rate, impl->info.channels, false);
131
+ unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10;
132
+
133
+ if (n_samples * 1000 / impl->info.rate % 10 != 0) {
134
+ spa_log_error(impl->log, "Buffers must be multiples of 10ms in length (currently %u samples)", n_samples);
135
+ return -1;
136
+ }
137
+
138
+ for (size_t i = 0; i < num_blocks; i ++) {
139
+ for (size_t j = 0; j < impl->info.channels; j++) {
140
+ impl->play_buffer[j] = const_cast<float *>(play[j]) + config.num_frames() * i;
141
+ impl->rec_buffer[j] = const_cast<float *>(rec[j]) + config.num_frames() * i;
142
+ impl->out_buffer[j] = out[j] + config.num_frames() * i;
143
+ }
144
+ /* FIXME: ProcessReverseStream may change the playback buffer, in which
145
+ * case we should use that, if we ever expose the intelligibility
146
+ * enhancer */
147
+ if (impl->apm->ProcessReverseStream(impl->play_buffer.get(), config, config, impl->play_buffer.get()) !=
148
+ webrtc::AudioProcessing::kNoError) {
149
+ spa_log_error(impl->log, "Processing reverse stream failed");
150
+ }
151
+
152
+ // Extra delay introduced by multiple frames
153
+ impl->apm->set_stream_delay_ms((num_blocks - 1) * 10);
154
+
155
+ if (impl->apm->ProcessStream(impl->rec_buffer.get(), config, config, impl->out_buffer.get()) !=
156
+ webrtc::AudioProcessing::kNoError) {
157
+ spa_log_error(impl->log, "Processing stream failed");
158
+ }
159
+ }
160
+
161
+ return 0;
162
+}
163
+
164
+static struct spa_audio_aec_methods impl_aec = {
165
+ SPA_VERSION_AUDIO_AEC_METHODS,
166
+ .add_listener = NULL,
167
+ .init = webrtc_init,
168
+ .run = webrtc_run,
169
+};
170
+
171
+static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface)
172
+{
173
+ auto impl = reinterpret_cast<struct impl_data*>(handle);
174
+
175
+ spa_return_val_if_fail(handle != NULL, -EINVAL);
176
+ spa_return_val_if_fail(interface != NULL, -EINVAL);
177
+
178
+ if (spa_streq(type, SPA_TYPE_INTERFACE_AUDIO_AEC))
179
+ *interface = &impl->aec;
180
+ else
181
+ return -ENOENT;
182
+
183
+ return 0;
184
+}
185
+
186
+static int impl_clear(struct spa_handle *handle)
187
+{
188
+ spa_return_val_if_fail(handle != NULL, -EINVAL);
189
+ auto impl = reinterpret_cast<struct impl_data*>(handle);
190
+ impl->~impl_data();
191
+ return 0;
192
+}
193
+
194
+static size_t
195
+impl_get_size(const struct spa_handle_factory *factory,
196
+ const struct spa_dict *params)
197
+{
198
+ return sizeof(struct impl_data);
199
+}
200
+
201
pipewire-0.3.47.tar.gz/spa/plugins/aec/meson.build
Added
18
1
2
+aec_null = shared_library('spa-aec-null',
3
+ [ 'aec-null.c' ],
4
+ include_directories : [ configinc ],
5
+ dependencies : [ spa_dep ],
6
+ install : true,
7
+ install_dir : spa_plugindir / 'aec')
8
+
9
+if webrtc_dep.found()
10
+ aec_webrtc = shared_library('spa-aec-webrtc',
11
+ [ 'aec-webrtc.cpp' ],
12
+ include_directories : [ configinc ],
13
+ dependencies : [ spa_dep, webrtc_dep ],
14
+ install : true,
15
+ install_dir : spa_plugindir / 'aec')
16
+endif
17
+
18
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
201
1
2
/* get the current params */
3
CHECK(snd_pcm_sw_params_current(hndl, params), "sw_params_current");
4
5
- CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE), "sw_params_set_tstamp_mode");
6
-
7
+ CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE),
8
+ "sw_params_set_tstamp_mode");
9
+ CHECK(snd_pcm_sw_params_set_tstamp_type(hndl, params, SND_PCM_TSTAMP_TYPE_MONOTONIC),
10
+ "sw_params_set_tstamp_type");
11
#if 0
12
snd_pcm_uframes_t boundary;
13
CHECK(snd_pcm_sw_params_get_boundary(params, &boundary), "get_boundary");
14
15
case SND_PCM_STATE_SUSPENDED:
16
spa_log_info(state->log, "%s: recover from state %s",
17
state->props.device, snd_pcm_state_name(st));
18
+ res = snd_pcm_resume(state->hndl);
19
+ if (res >= 0)
20
+ return res;
21
err = -ESTRPIPE;
22
break;
23
default:
24
25
return do_start(state);
26
}
27
28
-static int get_status(struct state *state, snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target)
29
+static int get_avail(struct state *state, uint64_t current_time)
30
{
31
- snd_pcm_sframes_t avail;
32
int res;
33
+ snd_pcm_sframes_t avail;
34
35
if (SPA_UNLIKELY((avail = snd_pcm_avail(state->hndl)) < 0)) {
36
if ((res = alsa_recover(state, avail)) < 0)
37
38
} else {
39
state->alsa_recovering = false;
40
}
41
+ return avail;
42
+}
43
+
44
+#if 0
45
+static int get_avail_htimestamp(struct state *state, uint64_t current_time)
46
+{
47
+ int res;
48
+ snd_pcm_uframes_t avail;
49
+ snd_htimestamp_t tstamp;
50
+ uint64_t then;
51
+
52
+ if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) {
53
+ if ((res = alsa_recover(state, avail)) < 0)
54
+ return res;
55
+ if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) {
56
+ spa_log_warn(state->log, "%s: snd_pcm_htimestamp error: %s",
57
+ state->props.device, snd_strerror(res));
58
+ avail = state->threshold * 2;
59
+ }
60
+ } else {
61
+ state->alsa_recovering = false;
62
+ }
63
+
64
+ if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) {
65
+ if (then < current_time)
66
+ avail += (current_time - then) * state->rate / SPA_NSEC_PER_SEC;
67
+ else
68
+ avail -= (then - current_time) * state->rate / SPA_NSEC_PER_SEC;
69
+ }
70
+ return SPA_MIN(avail, state->buffer_frames);
71
+}
72
+#endif
73
+
74
+static int get_status(struct state *state, uint64_t current_time,
75
+ snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target)
76
+{
77
+ int avail;
78
+
79
+ if ((avail = get_avail(state, current_time)) < 0)
80
+ return avail;
81
+
82
+ avail = SPA_MIN(avail, (int)state->buffer_frames);
83
84
*target = state->threshold + state->headroom;
85
86
87
return 0;
88
}
89
90
-static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t delay,
91
+static int update_time(struct state *state, uint64_t current_time, snd_pcm_sframes_t delay,
92
snd_pcm_sframes_t target, bool follower)
93
{
94
double err, corr;
95
96
97
if (SPA_UNLIKELY(state->dll.bw == 0.0)) {
98
spa_dll_set_bw(&state->dll, SPA_DLL_BW_MAX, state->threshold, state->rate);
99
- state->next_time = nsec;
100
- state->base_time = nsec;
101
+ state->next_time = current_time;
102
+ state->base_time = current_time;
103
}
104
diff = (int32_t) (state->last_threshold - state->threshold);
105
106
107
spa_log_trace(state->log, "%p: follower:%d quantum change %d -> %d (%d) %f",
108
state, follower, state->last_threshold, state->threshold, diff, err);
109
state->last_threshold = state->threshold;
110
+ state->alsa_sync = true;
111
}
112
- err = SPA_CLAMP(err, -state->max_error, state->max_error);
113
- corr = spa_dll_update(&state->dll, err);
114
+ if (err > state->max_error) {
115
+ err = state->max_error;
116
+ state->alsa_sync = true;
117
+ } else if (err < -state->max_error) {
118
+ err = -state->max_error;
119
+ state->alsa_sync = true;
120
+ }
121
+
122
+ if (!follower || state->matching)
123
+ corr = spa_dll_update(&state->dll, err);
124
+ else
125
+ corr = 1.0;
126
127
if (diff < 0)
128
state->next_time += diff / corr * 1e9 / state->rate;
129
130
if (SPA_UNLIKELY((state->next_time - state->base_time) > BW_PERIOD)) {
131
state->base_time = state->next_time;
132
133
- spa_log_debug(state->log, "%p: follower:%d match:%d rate:%f "
134
- "bw:%f thr:%u del:%ld target:%ld err:%f",
135
- state, follower, state->matching, corr, state->dll.bw,
136
- state->threshold, delay, target,
137
- err);
138
+ spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f "
139
+ "bw:%f thr:%u del:%ld target:%ld err:%f max:%f",
140
+ state->props.device, follower, state->matching,
141
+ corr, state->dll.bw, state->threshold, delay, target,
142
+ err, state->max_error);
143
}
144
145
if (state->rate_match) {
146
147
state->next_time += state->threshold / corr * 1e9 / state->rate;
148
149
if (SPA_LIKELY(!follower && state->clock)) {
150
- state->clock->nsec = nsec;
151
+ state->clock->nsec = current_time;
152
state->clock->position += state->duration;
153
state->clock->duration = state->duration;
154
state->clock->delay = delay + state->delay;
155
156
}
157
158
spa_log_trace_fp(state->log, "%p: follower:%d %"PRIu64" %f %ld %f %f %u",
159
- state, follower, nsec, corr, delay, err, state->threshold * corr,
160
+ state, follower, current_time, corr, delay, err, state->threshold * corr,
161
state->threshold);
162
163
return 0;
164
165
state->rate_denom = state->position->clock.rate.denom;
166
state->threshold = (state->duration * state->rate + state->rate_denom-1) / state->rate_denom;
167
state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching;
168
+ state->alsa_sync = true;
169
}
170
}
171
172
173
{
174
snd_pcm_t *hndl = state->hndl;
175
const snd_pcm_channel_area_t *my_areas;
176
- snd_pcm_uframes_t written, frames, offset, off, to_write, total_written;
177
+ snd_pcm_uframes_t written, frames, offset, off, to_write, total_written, max_write;
178
snd_pcm_sframes_t commitres;
179
int res = 0;
180
181
check_position_config(state);
182
183
+ max_write = state->buffer_frames;
184
+
185
if (state->following && state->alsa_started) {
186
- uint64_t nsec;
187
+ uint64_t current_time;
188
snd_pcm_uframes_t delay, target;
189
190
- if (SPA_UNLIKELY((res = get_status(state, &delay, &target)) < 0))
191
+ current_time = state->position->clock.nsec;
192
+
193
+ if (SPA_UNLIKELY((res = get_status(state, current_time, &delay, &target)) < 0))
194
return res;
195
196
- if (SPA_UNLIKELY(!state->alsa_recovering && delay > target + state->threshold)) {
197
+ if (SPA_UNLIKELY(state->alsa_sync)) {
198
spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
199
state->props.device, delay, target, state->threshold);
200
- spa_dll_init(&state->dll);
201
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
18
1
2
uint32_t start_delay;
3
4
uint32_t duration;
5
- uint32_t last_duration;
6
- uint64_t last_position;
7
unsigned int alsa_started:1;
8
unsigned int alsa_sync:1;
9
unsigned int alsa_recovering:1;
10
11
int64_t sample_count;
12
13
int64_t sample_time;
14
- uint64_t current_time;
15
uint64_t next_time;
16
uint64_t base_time;
17
18
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-udev.c
Changed
159
1
2
*d = 0;
3
}
4
5
+static int check_device_pcm_class(const char *devname)
6
+{
7
+ FILE *f;
8
+ char path[PATH_MAX];
9
+ char buf[16];
10
+ size_t sz;
11
+
12
+ /* Check device class */
13
+ spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class",
14
+ devname);
15
+ f = fopen(path, "r");
16
+ if (f == NULL)
17
+ return -errno;
18
+ sz = fread(buf, 1, sizeof(buf) - 1, f);
19
+ buf[sz] = '\0';
20
+ fclose(f);
21
+ return spa_strstartswith(buf, "modem") ? -ENXIO : 0;
22
+}
23
+
24
+static int get_num_pcm_devices(unsigned int card_id)
25
+{
26
+ char prefix[32];
27
+ DIR *snd = NULL;
28
+ struct dirent *entry;
29
+ int num_dev = 0;
30
+ int res;
31
+
32
+ /* Check if card has PCM devices, without opening them */
33
+
34
+ spa_scnprintf(prefix, sizeof(prefix), "pcmC%uD", card_id);
35
+
36
+ if ((snd = opendir("/dev/snd")) == NULL)
37
+ return -errno;
38
+
39
+ while ((errno = 0, entry = readdir(snd)) != NULL) {
40
+ if (!(entry->d_type == DT_CHR &&
41
+ spa_strstartswith(entry->d_name, prefix)))
42
+ continue;
43
+
44
+ res = check_device_pcm_class(entry->d_name);
45
+ if (res != -ENXIO) {
46
+ /* count device also if sysfs status file not accessible */
47
+ ++num_dev;
48
+ }
49
+ }
50
+ if (errno != 0)
51
+ res = -errno;
52
+ else
53
+ res = num_dev;
54
+
55
+ closedir(snd);
56
+ return res;
57
+}
58
+
59
static int check_device_available(struct impl *this, struct device *device, int *num_pcm)
60
{
61
char path[PATH_MAX];
62
63
struct dirent *entry, *entry_pcm;
64
int res;
65
66
+ res = get_num_pcm_devices(device->id);
67
+ if (res < 0) {
68
+ spa_log_error(this->log, "Error finding PCM devices for ALSA card %u: %s",
69
+ (unsigned int)device->id, spa_strerror(res));
70
+ return res;
71
+ }
72
+ *num_pcm = res;
73
+
74
+ spa_log_debug(this->log, "card %u has %d pcm device(s)", (unsigned int)device->id, *num_pcm);
75
+
76
/*
77
* Check if some pcm devices of the card are busy. Check it via /proc, as we
78
* don't want to actually open any devices using alsa-lib (generates uncontrolled
79
* number of inotify events), or replicate its subdevice logic.
80
+ *
81
+ * The /proc/asound directory might not exist if kernel is compiled with
82
+ * CONFIG_SND_PROCFS=n, and the pcmXX directories may be missing if compiled
83
+ * with CONFIG_SND_VERBOSE_PROCFS=n. In those cases, the busy check always succeeds.
84
*/
85
86
- *num_pcm = 0;
87
+ res = 0;
88
89
spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id);
90
91
92
spa_strstartswith(entry->d_name, "pcm")))
93
continue;
94
95
- /* Check device class */
96
- spa_scnprintf(path, sizeof(path), "/sys/class/sound/pcmC%uD%s/pcm_class",
97
+ spa_scnprintf(path, sizeof(path), "pcmC%uD%s",
98
(unsigned int)device->id, entry->d_name+3);
99
- f = fopen(path, "r");
100
- if (f == NULL)
101
- goto done;
102
- sz = fread(buf, 1, sizeof(buf) - 1, f);
103
- buf[sz] = '\0';
104
- fclose(f);
105
- if (spa_strstartswith(buf, "modem"))
106
+ if (check_device_pcm_class(path) < 0)
107
continue;
108
109
/* Check busy status */
110
111
if (!spa_strstartswith(buf, "closed")) {
112
spa_log_debug(this->log, "card %u pcm device %s busy",
113
(unsigned int)device->id, entry->d_name);
114
- errno = EBUSY;
115
+ res = -EBUSY;
116
goto done;
117
}
118
spa_log_debug(this->log, "card %u pcm device %s free",
119
120
if (errno != 0)
121
goto done;
122
123
- ++*num_pcm;
124
-
125
closedir(pcm);
126
pcm = NULL;
127
}
128
129
goto done;
130
131
done:
132
- res = -errno;
133
+ if (errno != 0) {
134
+ spa_log_info(this->log, "card %u: failed to find busy status (%s)",
135
+ (unsigned int)device->id, spa_strerror(-errno));
136
+ }
137
if (card)
138
closedir(card);
139
if (pcm)
140
141
* device->emitted to true. alsalib functions can be used after that.
142
*/
143
144
+ snprintf(path, sizeof(path), "hw:%u", id);
145
+
146
if ((res = check_device_available(this, device, &pcm)) < 0)
147
return res;
148
if (pcm == 0) {
149
spa_log_debug(this->log, "no pcm devices for %s", path);
150
device->ignored = true;
151
- return 0;
152
+ return -ENODEV;
153
}
154
155
- snprintf(path, sizeof(path), "hw:%u", id);
156
spa_log_debug(this->log, "emitting card %s", path);
157
device->emitted = true;
158
159
pipewire-0.3.45.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf
Changed
18
1
2
; Texas Instruments PCM2902
3
;
4
; This is a generic chip used in multiple products, including at least
5
-; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and
6
-; some unbranded "usb mini microphone".
7
+; Behringer U-Phoria UMC22, Behringer U-Phoria UM2, Behringer Xenyx 302USB,
8
+; Intopic Jazz-UB700 and some unbranded "usb mini microphone".
9
;
10
; Behringer UMC22 has stereo input (representing two physical mono inputs),
11
; others have mono input.
12
;
13
+; (Behringer UMC22 and UM2 are "the same device" with different controls)
14
+;
15
; Some devices have a mic input path, but at least Behringer Xenyx 302USB
16
; doesn't have any input mixer controls.
17
;
18
pipewire-0.3.45.tar.gz/spa/plugins/alsa/test-timer.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/test-timer.c
Changed
102
1
2
unsigned int rate;
3
unsigned int channels;
4
snd_pcm_uframes_t period;
5
+ snd_pcm_uframes_t buffer_frames;
6
7
snd_pcm_t *hndl;
8
int timerfd;
9
10
+ double max_error;
11
float accumulator;
12
13
uint64_t next_time;
14
15
16
static int on_timer_wakeup(struct state *state)
17
{
18
- snd_pcm_sframes_t avail, delay;
19
+ snd_pcm_sframes_t delay;
20
double error, corr;
21
-
22
- /* check the delay in the device */
23
- CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
24
+#if 1
25
+ snd_pcm_sframes_t avail;
26
+ CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
27
+#else
28
+ snd_pcm_uframes_t avail;
29
+ snd_htimestamp_t tstamp;
30
+ uint64_t then;
31
+
32
+ CHECK(snd_pcm_htimestamp(state->hndl, &avail, &tstamp), "htimestamp");
33
+ delay = state->buffer_frames - avail;
34
+
35
+ then = TIMESPEC_TO_NSEC(&tstamp);
36
+ if (then != 0) {
37
+ if (then < state->next_time) {
38
+ delay -= (state->next_time - then) * state->rate / NSEC_PER_SEC;
39
+ } else {
40
+ delay += (then - state->next_time) * state->rate / NSEC_PER_SEC;
41
+ }
42
+ }
43
+#endif
44
45
/* calculate the error, we want to have exactly 1 period of
46
* samples remaining in the device when we wakeup. */
47
error = (double)delay - (double)state->period;
48
+ if (error > state->max_error)
49
+ error = state->max_error;
50
+ else if (error < -state->max_error)
51
+ error = -state->max_error;
52
53
/* update the dll with the error, this gives a rate correction */
54
corr = spa_dll_update(&state->dll, error);
55
56
57
if (state->next_time - state->prev_time > BW_PERIOD) {
58
state->prev_time = state->next_time;
59
-
60
- /* reduce bandwidth and show some stats */
61
- if (state->dll.bw > SPA_DLL_BW_MIN)
62
- spa_dll_set_bw(&state->dll, state->dll.bw / 2.0,
63
- state->period, state->rate);
64
-
65
fprintf(stdout, "corr:%f error:%f bw:%f\n",
66
corr, error, state->dll.bw);
67
}
68
69
struct state state = { 0, };
70
const char *device = DEFAULT_DEVICE;
71
snd_pcm_hw_params_t *hparams;
72
+ snd_pcm_sw_params_t *sparams;
73
struct timespec now;
74
75
CHECK(snd_pcm_open(&state.hndl, device, SND_PCM_STREAM_PLAYBACK, 0), "open %s failed", device);
76
77
&state.rate, 0), "set rate");
78
CHECK(snd_pcm_hw_params(state.hndl, hparams), "hw_params");
79
80
+ CHECK(snd_pcm_hw_params_get_buffer_size(hparams, &state.buffer_frames), "get_buffer_size_max");
81
+
82
fprintf(stdout, "opened format:%s rate:%u channels:%u\n",
83
snd_pcm_format_name(SND_PCM_FORMAT_S32_LE),
84
state.rate, state.channels);
85
86
+ snd_pcm_sw_params_alloca(&sparams);
87
+#if 0
88
+ CHECK(snd_pcm_sw_params_current(state.hndl, sparams), "sw_params_current");
89
+ CHECK(snd_pcm_sw_params_set_tstamp_mode(state.hndl, sparams, SND_PCM_TSTAMP_ENABLE),
90
+ "sw_params_set_tstamp_type");
91
+ CHECK(snd_pcm_sw_params_set_tstamp_type(state.hndl, sparams, SND_PCM_TSTAMP_TYPE_MONOTONIC),
92
+ "sw_params_set_tstamp_type");
93
+ CHECK(snd_pcm_sw_params(state.hndl, sparams), "sw_params");
94
+#endif
95
+
96
spa_dll_init(&state.dll);
97
spa_dll_set_bw(&state.dll, SPA_DLL_BW_MAX, state.period, state.rate);
98
+ state.max_error = 256.0;
99
100
if ((state.timerfd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0)
101
perror("timerfd");
102
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
10
1
2
3
/* Check if USB ALT6 is really available on the device */
4
if (device->adapter->bus_type == BUS_TYPE_USB && !msbc_alt1_ok && msbc_ok) {
5
-#if HAVE_LIBUSB
6
+#ifdef HAVE_LIBUSB
7
if (device->adapter->source_id == SOURCE_ID_USB) {
8
msbc_ok = check_usb_altsetting_6(backend, device->adapter->vendor_id,
9
device->adapter->product_id);
10
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
14
1
2
}
3
}
4
5
-static inline void add_dict(struct spa_pod_builder *builder, const char *key, const char *val)
6
-{
7
- spa_pod_builder_string(builder, key);
8
- spa_pod_builder_string(builder, val);
9
-}
10
-
11
static int a2dp_codec_to_endpoint(const struct a2dp_codec *codec,
12
const char * endpoint,
13
char** object_path)
14
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/meson.build
Changed
56
1
2
endif
3
endforeach
4
5
-if not get_option('bluez5-backend-hsp-native').disabled()
6
- cdata.set('HAVE_BLUEZ_5_BACKEND_HSP_NATIVE', 1)
7
- cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', 1)
8
-endif
9
-if not get_option('bluez5-backend-hfp-native').disabled()
10
- cdata.set('HAVE_BLUEZ_5_BACKEND_HFP_NATIVE', 1)
11
- cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', 1)
12
-endif
13
-if not get_option('bluez5-backend-ofono').disabled()
14
- cdata.set('HAVE_BLUEZ_5_BACKEND_OFONO', 1)
15
-endif
16
-if not get_option('bluez5-backend-hsphfpd').disabled()
17
- cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', 1)
18
-endif
19
-
20
-if dependency('bluez', version: '< 6', required: false).found()
21
- cdata.set('HAVE_BLUEZ_5_HCI', 1)
22
-endif
23
+cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE',
24
+ get_option('bluez5-backend-hsp-native').allowed() or
25
+ get_option('bluez5-backend-hfp-native').allowed())
26
+cdata.set('HAVE_BLUEZ_5_BACKEND_HSP_NATIVE', get_option('bluez5-backend-hsp-native').allowed())
27
+cdata.set('HAVE_BLUEZ_5_BACKEND_HFP_NATIVE', get_option('bluez5-backend-hfp-native').allowed())
28
+cdata.set('HAVE_BLUEZ_5_BACKEND_OFONO', get_option('bluez5-backend-ofono').allowed())
29
+cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', get_option('bluez5-backend-hsphfpd').allowed())
30
+cdata.set('HAVE_BLUEZ_5_HCI', dependency('bluez', version: '< 6', required: false).found())
31
32
bluez5_sources = [
33
'plugin.c',
34
35
36
install_data(bluez5_data, install_dir : spa_datadir / 'bluez5')
37
38
-if not get_option('bluez5-backend-hsp-native').disabled() or not get_option('bluez5-backend-hfp-native').disabled()
39
+if get_option('bluez5-backend-hsp-native').allowed() or get_option('bluez5-backend-hfp-native').allowed()
40
if libusb_dep.found()
41
bluez5_deps += libusb_dep
42
endif
43
bluez5_sources += ['backend-native.c']
44
endif
45
46
-if not get_option('bluez5-backend-ofono').disabled()
47
+if get_option('bluez5-backend-ofono').allowed()
48
bluez5_sources += ['backend-ofono.c']
49
endif
50
51
-if not get_option('bluez5-backend-hsphfpd').disabled()
52
+if get_option('bluez5-backend-hsphfpd').allowed()
53
bluez5_sources += ['backend-hsphfpd.c']
54
endif
55
56
pipewire-0.3.45.tar.gz/spa/plugins/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/meson.build
Changed
54
1
2
if alsa_dep.found()
3
subdir('alsa')
4
endif
5
-if not get_option('audioconvert').disabled()
6
+if get_option('audioconvert').allowed()
7
subdir('audioconvert')
8
endif
9
-if not get_option('audiomixer').disabled()
10
+if get_option('audiomixer').allowed()
11
subdir('audiomixer')
12
endif
13
-if not get_option('control').disabled()
14
+if get_option('control').allowed()
15
subdir('control')
16
endif
17
-if not get_option('audiotestsrc').disabled()
18
+if get_option('audiotestsrc').allowed()
19
subdir('audiotestsrc')
20
endif
21
if bluez_dep.found()
22
23
if jack_dep.found()
24
subdir('jack')
25
endif
26
-if not get_option('support').disabled()
27
+if get_option('support').allowed()
28
subdir('support')
29
endif
30
-if not get_option('test').disabled()
31
+if get_option('test').allowed()
32
subdir('test')
33
endif
34
-if not get_option('videoconvert').disabled()
35
+if get_option('videoconvert').allowed()
36
subdir('videoconvert')
37
endif
38
-if not get_option('videotestsrc').disabled()
39
+if get_option('videotestsrc').allowed()
40
subdir('videotestsrc')
41
endif
42
-if not get_option('volume').disabled()
43
+if get_option('volume').allowed()
44
subdir('volume')
45
endif
46
if vulkan_headers
47
48
if libcamera_dep.found()
49
subdir('libcamera')
50
endif
51
+
52
+subdir('aec')
53
\ No newline at end of file
54
pipewire-0.3.45.tar.gz/spa/plugins/support/logger.c -> pipewire-0.3.47.tar.gz/spa/plugins/support/logger.c
Changed
28
1
2
struct spa_log log;
3
4
FILE *file;
5
+ bool close_file;
6
7
struct spa_system *system;
8
struct spa_source source;
9
10
11
support_log_free_patterns(&this->patterns);
12
13
+ if (this->close_file && this->file != NULL)
14
+ fclose(this->file);
15
+
16
if (this->have_source) {
17
spa_loop_remove_source(this->source.loop, &this->source);
18
spa_system_close(this->system, this->source.fd);
19
20
this->file = fopen(str, "w");
21
if (this->file == NULL)
22
fprintf(stderr, "Warning: failed to open file %s: (%m)", str);
23
+ else
24
+ this->close_file = true;
25
}
26
if ((str = spa_dict_lookup(info, SPA_KEY_LOG_PATTERNS)) != NULL)
27
support_log_parse_patterns(&this->patterns, str);
28
pipewire-0.3.45.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.47.tar.gz/spa/plugins/support/loop.c
Changed
156
1
2
#define MAX_ALIGN 8
3
#define ITEM_ALIGN 8
4
#define DATAS_SIZE (4096*8)
5
+#define MAX_EP 32
6
7
/** \cond */
8
9
10
struct spa_system *system;
11
12
struct spa_list source_list;
13
- struct spa_list destroy_list;
14
struct spa_hook_list hooks_list;
15
16
int poll_fd;
17
pthread_t thread;
18
+ int enter_count;
19
20
struct spa_source *wakeup;
21
int ack_fd;
22
23
{
24
struct impl *impl = object;
25
source->loop = &impl->loop;
26
+ source->priv = NULL;
27
return spa_system_pollfd_add(impl->system, impl->poll_fd, source->fd, source->mask, source);
28
}
29
30
31
static int loop_remove_source(void *object, struct spa_source *source)
32
{
33
struct impl *impl = object;
34
+ struct spa_poll_event *e;
35
+ if ((e = source->priv)) {
36
+ /* active in an iteration of the loop, remove it from there */
37
+ e->data = NULL;
38
+ source->priv = NULL;
39
+ }
40
source->loop = NULL;
41
return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd);
42
}
43
44
static void loop_enter(void *object)
45
{
46
struct impl *impl = object;
47
- impl->thread = pthread_self();
48
+ pthread_t thread_id = pthread_self();
49
+
50
+ if (impl->enter_count == 0) {
51
+ spa_return_if_fail(impl->thread == 0);
52
+ impl->thread = thread_id;
53
+ impl->enter_count = 1;
54
+ } else {
55
+ spa_return_if_fail(impl->enter_count > 0);
56
+ spa_return_if_fail(impl->thread == thread_id);
57
+ impl->enter_count++;
58
+ }
59
spa_log_trace(impl->log, "%p: enter %lu", impl, impl->thread);
60
}
61
62
static void loop_leave(void *object)
63
{
64
struct impl *impl = object;
65
+ pthread_t thread_id = pthread_self();
66
+
67
+ spa_return_if_fail(impl->enter_count > 0);
68
+ spa_return_if_fail(impl->thread == thread_id);
69
+
70
spa_log_trace(impl->log, "%p: leave %lu", impl, impl->thread);
71
- impl->thread = 0;
72
-}
73
74
-static inline void process_destroy(struct impl *impl)
75
-{
76
- struct source_impl *source, *tmp;
77
- spa_list_for_each_safe(source, tmp, &impl->destroy_list, link)
78
- free(source);
79
- spa_list_init(&impl->destroy_list);
80
+ if (--impl->enter_count == 0)
81
+ impl->thread = 0;
82
}
83
84
static int loop_iterate(void *object, int timeout)
85
{
86
struct impl *impl = object;
87
- struct spa_loop *loop = &impl->loop;
88
- struct spa_poll_event ep[32];
89
+ struct spa_poll_event ep[MAX_EP], *e;
90
int i, nfds;
91
92
spa_loop_control_hook_before(&impl->hooks_list);
93
94
- nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
95
+ nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, MAX_EP, timeout);
96
97
spa_loop_control_hook_after(&impl->hooks_list);
98
99
100
for (i = 0; i < nfds; i++) {
101
struct spa_source *s = ep[i].data;
102
s->rmask = ep[i].events;
103
+ /* already active in another iteration of the loop,
104
+ * remove it from that iteration */
105
+ if (SPA_UNLIKELY(e = s->priv))
106
+ e->data = NULL;
107
+ s->priv = &ep[i];
108
}
109
for (i = 0; i < nfds; i++) {
110
struct spa_source *s = ep[i].data;
111
- if (SPA_LIKELY(s->rmask && s->fd != -1 && s->loop == loop))
112
+ if (SPA_LIKELY(s && s->rmask)) {
113
+ s->priv = NULL;
114
s->func(s);
115
+ }
116
}
117
- if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
118
- process_destroy(impl);
119
-
120
return nfds;
121
}
122
123
124
spa_system_close(impl->impl->system, source->fd);
125
source->fd = -1;
126
}
127
- spa_list_insert(&impl->impl->destroy_list, &impl->link);
128
+ free(source);
129
}
130
131
static const struct spa_loop_methods impl_loop = {
132
133
134
impl = (struct impl *) handle;
135
136
+ if (impl->enter_count != 0)
137
+ spa_log_warn(impl->log, "%p: loop is entered %d times",
138
+ impl, impl->enter_count);
139
+
140
spa_list_consume(source, &impl->source_list, link)
141
loop_destroy_source(impl, &source->source);
142
143
- process_destroy(impl);
144
-
145
spa_system_close(impl->system, impl->ack_fd);
146
spa_system_close(impl->system, impl->poll_fd);
147
148
149
impl->poll_fd = res;
150
151
spa_list_init(&impl->source_list);
152
- spa_list_init(&impl->destroy_list);
153
spa_hook_list_init(&impl->hooks_list);
154
155
impl->buffer_data = SPA_PTR_ALIGN(impl->buffer_mem, MAX_ALIGN, uint8_t);
156
pipewire-0.3.45.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/support/meson.build
Changed
10
1
2
install_dir : spa_plugindir / 'support')
3
spa_support_dep = declare_dependency(link_with: spa_support_lib)
4
5
-if not get_option('evl').disabled()
6
+if get_option('evl').allowed()
7
evl_inc = include_directories('/usr/evl/include')
8
evl_lib = cc.find_library('evl',
9
dirs: ['/usr/evl/lib/'],
10
pipewire-0.3.45.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/client-rt.conf.in
Changed
13
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
+#
6
+# It is also possible to place a file with an updated section in
7
+# @PIPEWIRE_CONFIG_DIR@/client-rt.conf.d/ for system-wide changes or in
8
+# ~/.config/pipewire/client-rt.conf.d/ for local changes.
9
+#
10
11
context.properties = {
12
## Configure properties in the system.
13
pipewire-0.3.45.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/client.conf.in
Changed
14
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
-
6
+#
7
+# It is also possible to place a file with an updated section in
8
+# @PIPEWIRE_CONFIG_DIR@/client.conf.d/ for system-wide changes or in
9
+# ~/.config/pipewire/client.conf.d/ for local changes.
10
+#
11
context.properties = {
12
## Configure properties in the system.
13
#mem.warn-mlock = false
14
pipewire-0.3.45.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/jack.conf.in
Changed
33
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
+#
6
+# It is also possible to place a file with an updated section in
7
+# @PIPEWIRE_CONFIG_DIR@/jack.conf.d/ for system-wide changes or in
8
+# ~/.config/pipewire/jack.conf.d/ for local changes.
9
+#
10
11
context.properties = {
12
## Configure properties in the system.
13
14
# global properties for all jack clients
15
jack.properties = {
16
#node.latency = 1024/48000
17
- #node.lock-quantum = false
18
+ #node.rate = 1/48000
19
+ #node.quantum = 1024/48000
20
+ #node.lock-quantum = true
21
+ #node.force-quantum = 0
22
#jack.show-monitor = true
23
#jack.merge-monitor = false
24
#jack.short-name = false
25
26
# ignore-all: Ignore all self connect requests
27
#jack.self-connect-mode = allow
28
#jack.locked-process = true
29
+ #jack.default-as-system = false
30
}
31
32
# client specific properties
33
pipewire-0.3.45.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/minimal.conf.in
Changed
13
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
+#
6
+# It is also possible to place a file with an updated section in
7
+# @PIPEWIRE_CONFIG_DIR@/minimal.conf.d/ for system-wide changes or in
8
+# ~/.config/pipewire/minimal.conf.d/ for local changes.
9
+#
10
11
context.properties = {
12
## Configure properties in the system.
13
pipewire-0.3.45.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
21
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
+#
6
+# It is also possible to place a file with an updated section in
7
+# @PIPEWIRE_CONFIG_DIR@/pipewire-pulse.conf.d/ for system-wide changes or in
8
+# ~/.config/pipewire/pipewire-pulse.conf.d/ for local changes.
9
+#
10
11
context.properties = {
12
## Configure properties in the system.
13
14
15
# Extra modules can be loaded here. Setup in default.pa can be moved here
16
context.exec = [
17
+ { path = "pactl" args = "load-module module-always-sink" }
18
#{ path = "pactl" args = "load-module module-switch-on-connect" }
19
#{ path = "/usr/bin/sh" args = "~/.config/pipewire/default.pw" }
20
]
21
pipewire-0.3.45.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/pipewire.conf.in
Changed
22
1
2
#
3
# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes
4
# or in ~/.config/pipewire for local changes.
5
+#
6
+# It is also possible to place a file with an updated section in
7
+# @PIPEWIRE_CONFIG_DIR@/pipewire.conf.d/ for system-wide changes or in
8
+# ~/.config/pipewire/pipewire.conf.d/ for local changes.
9
+#
10
11
context.properties = {
12
## Configure properties in the system.
13
14
#default.clock.rate = 48000
15
#default.clock.allowed-rates = [ 48000 ]
16
#default.clock.quantum = 1024
17
- #default.clock.min-quantum = 32
18
+ default.clock.min-quantum = 16
19
#default.clock.max-quantum = 2048
20
#default.clock.quantum-limit = 8192
21
#default.video.width = 640
22
pipewire-0.3.45.tar.gz/src/daemon/systemd/meson.build -> pipewire-0.3.47.tar.gz/src/daemon/systemd/meson.build
Changed
10
1
2
-if not get_option('systemd-system-service').disabled()
3
+if get_option('systemd-system-service').allowed()
4
subdir('system')
5
endif
6
-if not get_option('systemd-user-service').disabled()
7
+if get_option('systemd-user-service').allowed()
8
subdir('user')
9
endif
10
pipewire-0.3.45.tar.gz/src/gst/gstpipewire.c -> pipewire-0.3.47.tar.gz/src/gst/gstpipewire.c
Changed
10
1
2
gst_element_register (plugin, "pipewiresink", GST_RANK_NONE,
3
GST_TYPE_PIPEWIRE_SINK);
4
5
-#if HAVE_GSTREAMER_DEVICE_PROVIDER
6
+#ifdef HAVE_GSTREAMER_DEVICE_PROVIDER
7
if (!gst_device_provider_register (plugin, "pipewiredeviceprovider",
8
GST_RANK_PRIMARY + 1, GST_TYPE_PIPEWIRE_DEVICE_PROVIDER))
9
return FALSE;
10
pipewire-0.3.45.tar.gz/src/gst/gstpipewireformat.c -> pipewire-0.3.47.tar.gz/src/gst/gstpipewireformat.c
Changed
58
1
2
return TRUE;
3
}
4
5
+static void
6
+set_default_channels (struct spa_pod_builder *b, uint32_t channels)
7
+{
8
+ uint32_t position[SPA_AUDIO_MAX_CHANNELS] = {0};
9
+ gboolean ok = TRUE;
10
+
11
+ switch (channels) {
12
+ case 8:
13
+ position[6] = SPA_AUDIO_CHANNEL_SL;
14
+ position[7] = SPA_AUDIO_CHANNEL_SR;
15
+ SPA_FALLTHROUGH
16
+ case 6:
17
+ position[5] = SPA_AUDIO_CHANNEL_LFE;
18
+ SPA_FALLTHROUGH
19
+ case 5:
20
+ position[4] = SPA_AUDIO_CHANNEL_FC;
21
+ SPA_FALLTHROUGH
22
+ case 4:
23
+ position[2] = SPA_AUDIO_CHANNEL_RL;
24
+ position[3] = SPA_AUDIO_CHANNEL_RR;
25
+ SPA_FALLTHROUGH
26
+ case 2:
27
+ position[0] = SPA_AUDIO_CHANNEL_FL;
28
+ position[1] = SPA_AUDIO_CHANNEL_FR;
29
+ break;
30
+ case 1:
31
+ position[0] = SPA_AUDIO_CHANNEL_MONO;
32
+ break;
33
+ default:
34
+ ok = FALSE;
35
+ break;
36
+ }
37
+
38
+ if (ok)
39
+ spa_pod_builder_add (b, SPA_FORMAT_AUDIO_position,
40
+ SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position), 0);
41
+}
42
+
43
static gboolean
44
handle_audio_fields (ConvertData *d)
45
{
46
47
}
48
if (i > 0) {
49
choice = spa_pod_builder_pop(&d->b, &f);
50
- if (i == 1)
51
+ if (i == 1) {
52
choice->body.type = SPA_CHOICE_None;
53
+ set_default_channels (&d->b, v);
54
+ }
55
}
56
}
57
return TRUE;
58
pipewire-0.3.45.tar.gz/src/gst/meson.build -> pipewire-0.3.47.tar.gz/src/gst/meson.build
Changed
10
1
2
'gstpipewiresrc.c',
3
]
4
5
-if not get_option('gstreamer-device-provider').disabled()
6
+if get_option('gstreamer-device-provider').allowed()
7
pipewire_gst_sources += [ 'gstpipewiredeviceprovider.c' ]
8
endif
9
10
pipewire-0.3.45.tar.gz/src/meson.build -> pipewire-0.3.47.tar.gz/src/meson.build
Changed
14
1
2
subdir('daemon')
3
subdir('tools')
4
subdir('modules')
5
-if not get_option('examples').disabled()
6
+if get_option('examples').allowed()
7
subdir('examples')
8
endif
9
-if not get_option('tests').disabled()
10
+if get_option('tests').allowed()
11
subdir('tests')
12
endif
13
14
pipewire-0.3.45.tar.gz/src/modules/meson.build -> pipewire-0.3.47.tar.gz/src/modules/meson.build
Changed
87
1
2
'module-echo-cancel.c',
3
'module-example-sink.c',
4
'module-example-source.c',
5
+ 'module-fallback-sink.c',
6
'module-filter-chain.c',
7
'module-link-factory.c',
8
'module-loopback.c',
9
10
11
pipewire_module_echo_cancel_sources = [
12
'module-echo-cancel.c',
13
- 'module-echo-cancel/aec-null.c',
14
]
15
16
-if webrtc_dep.found()
17
- pipewire_module_echo_cancel_sources += [
18
- 'module-echo-cancel/aec-webrtc.cpp'
19
- ]
20
-endif
21
-
22
pipewire_module_echo_cancel = shared_library('pipewire-module-echo-cancel',
23
pipewire_module_echo_cancel_sources,
24
include_directories : [configinc],
25
install : true,
26
install_dir : modules_install_dir,
27
install_rpath: modules_install_dir,
28
- dependencies : [mathlib, dl_lib, pipewire_dep, webrtc_dep],
29
+ dependencies : [mathlib, dl_lib, pipewire_dep],
30
)
31
32
pipewire_module_profiler = shared_library('pipewire-module-profiler',
33
34
'module-protocol-pulse/extensions/ext-stream-restore.c',
35
'module-protocol-pulse/format.c',
36
'module-protocol-pulse/manager.c',
37
- 'module-protocol-pulse/media-roles.c',
38
'module-protocol-pulse/message.c',
39
'module-protocol-pulse/message-handler.c',
40
'module-protocol-pulse/module.c',
41
42
'module-protocol-pulse/pending-sample.c',
43
'module-protocol-pulse/pulse-server.c',
44
'module-protocol-pulse/quirks.c',
45
+ 'module-protocol-pulse/remap.c',
46
'module-protocol-pulse/reply.c',
47
'module-protocol-pulse/sample.c',
48
'module-protocol-pulse/sample-play.c',
49
50
'module-protocol-pulse/stream.c',
51
'module-protocol-pulse/utils.c',
52
'module-protocol-pulse/volume.c',
53
+ 'module-protocol-pulse/modules/module-always-sink.c',
54
'module-protocol-pulse/modules/module-combine-sink.c',
55
'module-protocol-pulse/modules/module-echo-cancel.c',
56
'module-protocol-pulse/modules/module-ladspa-sink.c',
57
58
'module-protocol-pulse/dbus-name.c',
59
]
60
pipewire_module_protocol_pulse_deps += dbus_dep
61
- cdata.set('HAVE_DBUS', 1)
62
endif
63
64
if avahi_dep.found()
65
66
'module-zeroconf-discover/avahi-poll.c',
67
]
68
pipewire_module_protocol_pulse_deps += avahi_dep
69
- cdata.set('HAVE_AVAHI', 1)
70
+ cdata.set('HAVE_AVAHI', true)
71
endif
72
73
pipewire_module_protocol_pulse = shared_library('pipewire-module-protocol-pulse',
74
75
)
76
endif
77
summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules')
78
+
79
+pipewire_module_fallback_sink = shared_library('pipewire-module-fallback-sink',
80
+ [ 'module-fallback-sink.c' ],
81
+ include_directories : [configinc],
82
+ install : true,
83
+ install_dir : modules_install_dir,
84
+ install_rpath: modules_install_dir,
85
+ dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep],
86
+)
87
pipewire-0.3.45.tar.gz/src/modules/module-access.c -> pipewire-0.3.47.tar.gz/src/modules/module-access.c
Changed
14
1
2
3
#include "config.h"
4
5
-#if HAVE_SYS_VFS_H
6
+#ifdef HAVE_SYS_VFS_H
7
#include <sys/vfs.h>
8
#endif
9
-#if HAVE_SYS_MOUNT_H
10
+#ifdef HAVE_SYS_MOUNT_H
11
#include <sys/mount.h>
12
#endif
13
14
pipewire-0.3.45.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.47.tar.gz/src/modules/module-client-node/client-node.c
Changed
201
1
2
3
/** \cond */
4
5
-#define MAX_INPUTS 1024
6
-#define MAX_OUTPUTS 1024
7
-
8
#define MAX_BUFFERS 64
9
#define MAX_METAS 16u
10
#define MAX_DATAS 64u
11
#define MAX_AREAS 2048
12
-#define MAX_MIX 128
13
-
14
-#define CHECK_IN_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_INPUTS)
15
-#define CHECK_OUT_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_OUTPUTS)
16
-#define CHECK_PORT_ID(this,d,p) (CHECK_IN_PORT_ID(this,d,p) || CHECK_OUT_PORT_ID(this,d,p))
17
-#define CHECK_FREE_IN_PORT(this,d,p) (CHECK_IN_PORT_ID(this,d,p) && (this)->in_ports[p] == NULL)
18
-#define CHECK_FREE_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p] == NULL)
19
-#define CHECK_FREE_PORT(this,d,p) (CHECK_FREE_IN_PORT (this,d,p) || CHECK_FREE_OUT_PORT (this,d,p))
20
-#define CHECK_IN_PORT(this,d,p) (CHECK_IN_PORT_ID(this,d,p) && (this)->in_ports[p])
21
-#define CHECK_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p])
22
-#define CHECK_PORT(this,d,p) (CHECK_IN_PORT (this,d,p) || CHECK_OUT_PORT (this,d,p))
23
-
24
-#define GET_IN_PORT(this,p) (this->in_ports[p])
25
-#define GET_OUT_PORT(this,p) (this->out_ports[p])
26
-#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
27
+
28
+#define CHECK_FREE_PORT(this,d,p) (p <= pw_map_get_size(&this->ports[d]) && !CHECK_PORT(this,d,p))
29
+#define CHECK_PORT(this,d,p) (pw_map_lookup(&this->ports[d], p) != NULL)
30
+#define GET_PORT(this,d,p) (pw_map_lookup(&this->ports[d], p))
31
32
#define CHECK_PORT_BUFFER(this,b,p) (b < p->n_buffers)
33
34
35
struct spa_source data_source;
36
int writefd;
37
38
- uint32_t n_inputs;
39
- uint32_t n_outputs;
40
- struct port *in_ports[MAX_INPUTS];
41
- struct port *out_ports[MAX_OUTPUTS];
42
+ struct pw_map ports[2];
43
44
struct port dummy;
45
46
47
mix_id = 0;
48
else
49
mix_id++;
50
- if (mix_id >= MAX_MIX)
51
- return NULL;
52
+
53
len = pw_array_get_len(&p->mix, struct mix);
54
if (mix_id >= len) {
55
size_t need = sizeof(struct mix) * (mix_id + 1 - len);
56
57
{
58
struct node *this = object;
59
struct spa_hook_list save;
60
- uint32_t i;
61
+ union pw_map_item *item;
62
63
spa_return_val_if_fail(this != NULL, -EINVAL);
64
65
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
66
67
- for (i = 0; i < MAX_INPUTS; i++) {
68
- if (this->in_ports[i])
69
- emit_port_info(this, this->in_ports[i]);
70
+ pw_array_for_each(item, &this->ports[SPA_DIRECTION_INPUT].items) {
71
+ if (item->data)
72
+ emit_port_info(this, item->data);
73
}
74
- for (i = 0; i < MAX_OUTPUTS; i++) {
75
- if (this->out_ports[i])
76
- emit_port_info(this, this->out_ports[i]);
77
+ pw_array_for_each(item, &this->ports[SPA_DIRECTION_OUTPUT].items) {
78
+ if (item->data)
79
+ emit_port_info(this, item->data);
80
}
81
spa_hook_list_join(&this->hooks, &save);
82
83
84
pw_array_clear(&port->mix);
85
pw_array_init(&port->mix, sizeof(struct mix) * 2);
86
87
- if (port->direction == SPA_DIRECTION_INPUT) {
88
- if (this->in_ports[port->id] == port) {
89
- this->in_ports[port->id] = NULL;
90
- this->n_inputs--;
91
- }
92
- }
93
- else {
94
- if (this->out_ports[port->id] == port) {
95
- this->out_ports[port->id] = NULL;
96
- this->n_outputs--;
97
- }
98
- }
99
+ pw_map_insert_at(&this->ports[port->direction], port->id, NULL);
100
+
101
if (!port->removed)
102
spa_node_emit_port_info(&this->hooks, port->direction, port->id, NULL);
103
}
104
105
106
spa_return_val_if_fail(this != NULL, -EINVAL);
107
spa_return_val_if_fail(num != 0, -EINVAL);
108
- spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
109
110
port = GET_PORT(this, direction, port_id);
111
+ spa_return_val_if_fail(port != NULL, -EINVAL);
112
113
pw_log_debug("%p: seq:%d port %d.%d id:%u start:%u num:%u n_params:%d",
114
this, seq, direction, port_id, id, start, num, port->n_params);
115
116
struct mix *mix;
117
118
spa_return_val_if_fail(this != NULL, -EINVAL);
119
- if(!CHECK_PORT(this, direction, port_id))
120
+
121
+ port = GET_PORT(this, direction, port_id);
122
+ if(port == NULL)
123
return param == NULL ? 0 : -EINVAL;
124
125
pw_log_debug("%p: port %d.%d set param %s %d", this,
126
direction, port_id,
127
spa_debug_type_find_name(spa_type_param, id), id);
128
129
- port = GET_PORT(this, direction, port_id);
130
-
131
if (id == SPA_PARAM_Format) {
132
pw_array_for_each(mix, &port->mix)
133
clear_buffers(this, mix);
134
135
direction == SPA_DIRECTION_INPUT ? "input" : "output",
136
port_id, mix_id, data, size);
137
138
- if (!CHECK_PORT(this, direction, port_id))
139
- return data == NULL ? 0 : -EINVAL;
140
-
141
port = GET_PORT(this, direction, port_id);
142
+ if (port == NULL)
143
+ return data == NULL ? 0 : -EINVAL;
144
145
if ((mix = find_mix(port, mix_id)) == NULL || !mix->valid)
146
return -EINVAL;
147
148
uint32_t i, j, peer_id;
149
struct pw_client_node_buffer *mb;
150
151
- if (!CHECK_PORT(this, direction, port_id))
152
+ p = GET_PORT(this, direction, port_id);
153
+ if (p == NULL)
154
return n_buffers == 0 ? 0 : -EINVAL;
155
156
if (n_buffers > MAX_BUFFERS)
157
return -ENOSPC;
158
159
- p = GET_PORT(this, direction, port_id);
160
161
spa_log_debug(this->log, "%p: %s port %d.%d use buffers %p %u flags:%08x", this,
162
direction == SPA_DIRECTION_INPUT ? "input" : "output",
163
164
struct node *this = object;
165
166
spa_return_val_if_fail(this != NULL, -EINVAL);
167
- spa_return_val_if_fail(CHECK_OUT_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL);
168
+ spa_return_val_if_fail(CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL);
169
170
spa_log_trace_fp(this->log, "reuse buffer %d", buffer_id);
171
172
173
174
spa_log_debug(this->log, "%p: got port update change:%08x params:%d",
175
this, change_mask, n_params);
176
- if (!CHECK_PORT_ID(this, direction, port_id))
177
- return -EINVAL;
178
179
remove = (change_mask == 0);
180
181
182
struct port *target;
183
184
if (port == NULL) {
185
+ if (!CHECK_FREE_PORT(this, direction, port_id))
186
+ return -EINVAL;
187
+
188
target = &this->dummy;
189
spa_zero(this->dummy);
190
target->direction = direction;
191
192
direction == SPA_DIRECTION_INPUT ? "input" : "output",
193
port_id, mix_id, buffers, n_buffers);
194
195
- spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
196
-
197
p = GET_PORT(this, direction, port_id);
198
+ spa_return_val_if_fail(p != NULL, -EINVAL);
199
200
if (direction == SPA_DIRECTION_OUTPUT)
201
pipewire-0.3.45.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.47.tar.gz/src/modules/module-client-node/remote-node.c
Changed
94
1
2
#include "pipewire/extensions/client-node.h"
3
4
#define MAX_BUFFERS 64
5
-#define MAX_MIX 4096
6
7
PW_LOG_TOPIC_EXTERN(mod_topic);
8
#define PW_LOG_TOPIC_DEFAULT mod_topic
9
10
int rtwritefd;
11
struct pw_memmap *activation;
12
13
- struct mix mix_pool[MAX_MIX];
14
struct spa_list mix[2];
15
struct spa_list free_mix;
16
17
18
if ((mix = find_mix(data, direction, port_id, mix_id)))
19
return mix;
20
21
- if (spa_list_is_empty(&data->free_mix))
22
- return NULL;
23
-
24
port = pw_impl_node_find_port(data->node, direction, port_id);
25
if (port == NULL)
26
return NULL;
27
28
- mix = spa_list_first(&data->free_mix, struct mix, link);
29
- spa_list_remove(&mix->link);
30
+ if (spa_list_is_empty(&data->free_mix)) {
31
+ if ((mix = calloc(1, sizeof(*mix))) == NULL)
32
+ return NULL;
33
+ } else {
34
+ mix = spa_list_first(&data->free_mix, struct mix, link);
35
+ spa_list_remove(&mix->link);
36
+ }
37
38
mix_init(mix, port, mix_id);
39
spa_list_append(&data->mix[direction], &mix->link);
40
41
clear_buffers(data, mix);
42
pw_array_clear(&mix->buffers);
43
44
- spa_list_remove(&mix->mix.link);
45
spa_list_append(&data->free_mix, &mix->link);
46
pw_impl_port_release_mix(mix->port, &mix->mix);
47
}
48
49
static void clean_node(struct node_data *d)
50
{
51
- struct mix *mix, *tmp;
52
+ struct mix *mix;
53
54
if (d->have_transport) {
55
- spa_list_for_each_safe(mix, tmp, &d->mix[SPA_DIRECTION_INPUT], link)
56
+ spa_list_consume(mix, &d->mix[SPA_DIRECTION_INPUT], link)
57
clear_mix(d, mix);
58
- spa_list_for_each_safe(mix, tmp, &d->mix[SPA_DIRECTION_OUTPUT], link)
59
+ spa_list_consume(mix, &d->mix[SPA_DIRECTION_OUTPUT], link)
60
clear_mix(d, mix);
61
}
62
+ spa_list_consume(mix, &d->free_mix, link) {
63
+ spa_list_remove(&mix->link);
64
+ free(mix);
65
+ }
66
clean_transport(d);
67
}
68
69
70
pw_log_debug("%p: removed", data);
71
72
spa_hook_remove(&data->proxy_client_node_listener);
73
+ spa_hook_remove(&data->client_node_listener);
74
75
if (data->node) {
76
spa_hook_remove(&data->node_listener);
77
78
struct pw_impl_node *node = object;
79
struct pw_proxy *client_node;
80
struct node_data *data;
81
- int i;
82
83
user_data_size = SPA_ROUND_UP_N(user_data_size, __alignof__(struct node_data));
84
85
86
spa_list_init(&data->free_mix);
87
spa_list_init(&data->mix[0]);
88
spa_list_init(&data->mix[1]);
89
- for (i = 0; i < MAX_MIX; i++)
90
- spa_list_append(&data->free_mix, &data->mix_pool[i].link);
91
92
spa_list_init(&data->links);
93
94
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.47.tar.gz/src/modules/module-echo-cancel.c
Changed
201
1
2
#include <spa/param/audio/raw.h>
3
#include <spa/param/profiler.h>
4
#include <spa/pod/builder.h>
5
+#include <spa/support/plugin.h>
6
#include <spa/utils/json.h>
7
+#include <spa/utils/names.h>
8
#include <spa/utils/result.h>
9
#include <spa/utils/ringbuffer.h>
10
#include <spa/utils/string.h>
11
+#include <spa/support/plugin-loader.h>
12
+#include <spa/interfaces/audio/aec.h>
13
14
#include <pipewire/private.h>
15
#include <pipewire/impl.h>
16
17
18
#include <pipewire/extensions/profiler.h>
19
20
-#include "module-echo-cancel/echo-cancel.h"
21
-
22
/** \page page_module_echo_cancel PipeWire Module: Echo Cancel
23
*
24
* The `echo-cancel` module performs echo cancellation. The module creates
25
26
*
27
* - `source.props = {}`: properties to be passed to the source stream
28
* - `sink.props = {}`: properties to be passed to the sink stream
29
- * - `aec.method = <str>`: the echo cancellation method. Currently supported:
30
- * `webrtc`. Leave unset to use the default method (`webrtc`).
31
+ * - `library.name = <str>`: the echo cancellation library Currently supported:
32
+ * `aec/libspa-aec-exaudio`. Leave unset to use the default method (`aec/libspa-aec-exaudio`).
33
* - `aec.args = <str>`: arguments to pass to the echo cancellation method
34
*
35
* ## General options
36
37
* context.modules = [
38
* { name = libpipewire-module-echo-cancel
39
* args = {
40
- * # aec.method = webrtc
41
+ * # library.name = aec/libspa-aec-exaudio
42
* # node.latency = 1024/48000
43
* source.props = {
44
* node.name = "Echo Cancellation Source"
45
46
"[ audio.position=<channel map> ] "
47
"[ buffer.max_size=<max buffer size in ms> ] "
48
"[ buffer.play_delay=<play delay in ms> ] "
49
- "[ aec.method=<aec method> ] "
50
+ "[ library.name =<library name> ] "
51
"[ aec.args=<aec arguments> ] "
52
"[ source.props=<properties> ] "
53
"[ sink.props=<properties> ] " },
54
55
uint32_t out_ringsize;
56
struct spa_ringbuffer out_ring;
57
58
- const struct echo_cancel_info *aec_info;
59
- void *aec;
60
+ struct spa_audio_aec *aec;
61
uint32_t aec_blocksize;
62
63
unsigned int capture_ready:1;
64
65
66
uint32_t max_buffer_size;
67
uint32_t buffer_delay;
68
+
69
+ struct spa_handle *spa_handle;
70
+ struct spa_plugin_loader *loader;
71
};
72
73
static void do_unload_module(void *obj, void *data, int res, uint32_t id)
74
75
pw_stream_queue_buffer(impl->playback, pout);
76
77
/* Now run the canceller */
78
- echo_cancel_run(impl->aec_info, impl->aec, rec, play_delayed, out, size / sizeof(float));
79
+ spa_audio_aec_run(impl->aec, rec, play_delayed, out, size / sizeof(float));
80
81
/* Next, copy over the output to the output ringbuffer */
82
avail = spa_ringbuffer_get_write_index(&impl->out_ring, &oindex);
83
84
pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
85
if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LATENCY)) != NULL)
86
pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
87
- else if (impl->aec_info->latency)
88
- pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
89
+ else if (impl->aec->latency)
90
+ pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec->latency);
91
92
impl->capture = pw_stream_new(impl->core,
93
"Echo-Cancel Capture", props);
94
95
pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str);
96
if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LATENCY)) != NULL)
97
pw_properties_set(props, PW_KEY_NODE_LATENCY, str);
98
- else if (impl->aec_info->latency)
99
- pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency);
100
+ else if (impl->aec->latency)
101
+ pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec->latency);
102
103
impl->playback = pw_stream_new(impl->core,
104
"Echo-Cancel Playback", props);
105
106
pw_stream_destroy(impl->sink);
107
if (impl->core && impl->do_disconnect)
108
pw_core_disconnect(impl->core);
109
- if (impl->aec)
110
- echo_cancel_destroy(impl->aec_info, impl->aec);
111
+ if (impl->spa_handle)
112
+ spa_plugin_loader_unload(impl->loader, impl->spa_handle);
113
pw_properties_free(impl->source_props);
114
pw_properties_free(impl->sink_props);
115
116
117
struct impl *impl;
118
uint32_t id = pw_global_get_id(pw_impl_module_get_global(module));
119
const char *str;
120
- int res;
121
+ const char *path;
122
+ int res = 0;
123
+ struct spa_handle *handle = NULL;
124
+ void *iface;
125
126
PW_LOG_TOPIC_INIT(mod_topic);
127
128
129
if (pw_properties_get(impl->sink_props, PW_KEY_MEDIA_CLASS) == NULL)
130
pw_properties_set(impl->sink_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
131
132
- if ((str = pw_properties_get(props, "aec.method")) == NULL)
133
- str = "webrtc";
134
+ if ((str = pw_properties_get(props, "aec.method")) != NULL)
135
+ pw_log_warn("aec.method is not supported anymore use library.name");
136
137
-#ifdef HAVE_WEBRTC
138
- if (spa_streq(str, "webrtc"))
139
- impl->aec_info = echo_cancel_webrtc;
140
- else
141
-#endif
142
- impl->aec_info = echo_cancel_null;
143
+ /* Use webrtc as default */
144
+ if ((path = pw_properties_get(props, "library.name")) == NULL)
145
+ path = "aec/libspa-aec-webrtc";
146
+
147
+ struct spa_dict_item info_items[] = {
148
+ { SPA_KEY_LIBRARY_NAME, path },
149
+ };
150
+ struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items);
151
+
152
+ impl->loader = spa_support_find(context->support, context->n_support, SPA_TYPE_INTERFACE_PluginLoader);
153
+ if (impl->loader == NULL) {
154
+ pw_log_error("a plugin loader is needed");
155
+ return -EINVAL;
156
+ }
157
+
158
+ handle = spa_plugin_loader_load(impl->loader, SPA_NAME_AEC, &info);
159
+ if (handle == NULL) {
160
+ pw_log_error("AEC codec plugin %s not available library.name %s", SPA_NAME_AEC, path);
161
+ return -ENOENT;
162
+ }
163
+
164
+ if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_AUDIO_AEC, &iface)) < 0) {
165
+ pw_log_error("can't get %s interface %d", SPA_TYPE_INTERFACE_AUDIO_AEC, res);
166
+ return res;
167
+ }
168
+ impl->aec = iface;
169
+ impl->spa_handle = handle;
170
+ if (impl->aec->iface.version != SPA_VERSION_AUDIO_AEC) {
171
+ pw_log_error("codec plugin %s has incompatible ABI version (%d != %d)",
172
+ SPA_NAME_AEC, impl->aec->iface.version, SPA_VERSION_AUDIO_AEC);
173
+ res = -ENOENT;
174
+ goto error;
175
+ }
176
+
177
+ (void)SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_AUDIO_AEC, (struct spa_audio_aec *)impl->aec);
178
+
179
+ pw_log_info("Using plugin AEC %s", impl->aec->name);
180
181
if ((str = pw_properties_get(props, "aec.args")) != NULL)
182
aec_props = pw_properties_new_string(str);
183
else
184
aec_props = pw_properties_new(NULL, NULL);
185
186
- impl->aec = echo_cancel_create(impl->aec_info, aec_props, &impl->info);
187
+ if (spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info)) {
188
+ pw_log_error("codec plugin %s create failed", impl->aec->name);
189
+ res = -ENOENT;
190
+ goto error;
191
+ }
192
193
pw_properties_free(aec_props);
194
195
- if (impl->aec_info->latency) {
196
+ if (impl->aec->latency) {
197
unsigned int num, denom, req_num, req_denom;
198
unsigned int factor = 0;
199
unsigned int new_num = 0;
200
201
pipewire-0.3.47.tar.gz/src/modules/module-fallback-sink.c
Added
201
1
2
+/* PipeWire
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
+#include <string.h>
27
+#include <stdio.h>
28
+#include <errno.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <fcntl.h>
32
+#include <unistd.h>
33
+
34
+#include "config.h"
35
+
36
+#include <spa/utils/result.h>
37
+#include <spa/utils/string.h>
38
+#include <spa/param/audio/raw.h>
39
+
40
+#include <pipewire/impl.h>
41
+#include <pipewire/i18n.h>
42
+
43
+/** \page page_module_fallback_sink PipeWire Module: Fallback Sink
44
+ *
45
+ * Fallback sink, which appear dynamically when no other sinks are
46
+ * present. This is only useful for Pulseaudio compatibility.
47
+ */
48
+
49
+#define NAME "fallback-sink"
50
+
51
+#define DEFAULT_SINK_NAME "auto_null"
52
+#define DEFAULT_SINK_DESCRIPTION _("Dummy Output")
53
+
54
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
55
+#define PW_LOG_TOPIC_DEFAULT mod_topic
56
+
57
+#define MODULE_USAGE ("[ sink.name=<str> ] " \
58
+ "[ sink.description=<str> ] ")
59
+
60
+static const struct spa_dict_item module_props[] = {
61
+ { PW_KEY_MODULE_AUTHOR, "Pauli Virtanen <pav@iki.fi>" },
62
+ { PW_KEY_MODULE_DESCRIPTION, "Dynamically appearing fallback sink" },
63
+ { PW_KEY_MODULE_USAGE, MODULE_USAGE },
64
+ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
65
+};
66
+
67
+struct bitmap {
68
+ uint8_t *data;
69
+ size_t size;
70
+ size_t items;
71
+};
72
+
73
+struct impl {
74
+ struct pw_context *context;
75
+
76
+ struct pw_impl_module *module;
77
+ struct spa_hook module_listener;
78
+
79
+ struct pw_core *core;
80
+ struct pw_registry *registry;
81
+ struct pw_proxy *sink;
82
+
83
+ struct spa_hook core_listener;
84
+ struct spa_hook core_proxy_listener;
85
+ struct spa_hook registry_listener;
86
+ struct spa_hook sink_listener;
87
+
88
+ struct pw_properties *properties;
89
+
90
+ struct bitmap sink_ids;
91
+ struct bitmap fallback_sink_ids;
92
+
93
+ int check_seq;
94
+
95
+ unsigned int do_disconnect:1;
96
+ unsigned int scheduled:1;
97
+};
98
+
99
+static int bitmap_add(struct bitmap *map, uint32_t i)
100
+{
101
+ const uint32_t pos = (i >> 3);
102
+ const uint8_t mask = 1 << (i & 0x7);
103
+
104
+ if (pos >= map->size) {
105
+ size_t new_size = map->size + pos + 16;
106
+ void *p;
107
+
108
+ p = realloc(map->data, new_size);
109
+ if (!p)
110
+ return -errno;
111
+
112
+ memset((uint8_t*)p + map->size, 0, new_size - map->size);
113
+ map->data = p;
114
+ map->size = new_size;
115
+ }
116
+
117
+ if (map->data[pos] & mask)
118
+ return 1;
119
+
120
+ map->data[pos] |= mask;
121
+ ++map->items;
122
+
123
+ return 0;
124
+}
125
+
126
+static bool bitmap_remove(struct bitmap *map, uint32_t i)
127
+{
128
+ const uint32_t pos = (i >> 3);
129
+ const uint8_t mask = 1 << (i & 0x7);
130
+
131
+ if (pos >= map->size)
132
+ return false;
133
+
134
+ if (!(map->data[pos] & mask))
135
+ return false;
136
+
137
+ map->data[pos] &= ~mask;
138
+ --map->items;
139
+
140
+ return true;
141
+}
142
+
143
+static void bitmap_free(struct bitmap *map)
144
+{
145
+ free(map->data);
146
+ spa_zero(*map);
147
+}
148
+
149
+static int add_id(struct bitmap *map, uint32_t id)
150
+{
151
+ int res;
152
+
153
+ if (id == SPA_ID_INVALID)
154
+ return -EINVAL;
155
+
156
+ if ((res = bitmap_add(map, id)) < 0)
157
+ pw_log_error("%s", spa_strerror(res));
158
+
159
+ return res;
160
+}
161
+
162
+static void reschedule_check(struct impl *impl)
163
+{
164
+ if (!impl->scheduled)
165
+ return;
166
+
167
+ impl->check_seq = pw_core_sync(impl->core, 0, impl->check_seq);
168
+}
169
+
170
+static void schedule_check(struct impl *impl)
171
+{
172
+ if (impl->scheduled)
173
+ return;
174
+
175
+ impl->scheduled = true;
176
+ impl->check_seq = pw_core_sync(impl->core, 0, impl->check_seq);
177
+}
178
+
179
+static void sink_proxy_removed(void *data)
180
+{
181
+ struct impl *impl = data;
182
+
183
+ pw_proxy_destroy(impl->sink);
184
+}
185
+
186
+static void sink_proxy_bound(void *data, uint32_t id)
187
+{
188
+ struct impl *impl = data;
189
+
190
+ add_id(&impl->sink_ids, id);
191
+ add_id(&impl->fallback_sink_ids, id);
192
+
193
+ reschedule_check(impl);
194
+ schedule_check(impl);
195
+}
196
+
197
+static void sink_proxy_destroy(void *data)
198
+{
199
+ struct impl *impl = data;
200
+
201
pipewire-0.3.45.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.47.tar.gz/src/modules/module-profiler.c
Changed
28
1
2
spa_list_for_each(t, &node->rt.target_list, link) {
3
struct pw_impl_node *n = t->node;
4
struct pw_node_activation *na;
5
+ struct spa_fraction latency;
6
7
if (n == NULL || n == node)
8
continue;
9
10
+ latency = n->latency;
11
+ if (n->force_quantum != 0)
12
+ latency.num = n->force_quantum;
13
+ if (n->force_rate != 0)
14
+ latency.denom = n->force_rate;
15
+
16
na = n->rt.activation;
17
spa_pod_builder_prop(&b, SPA_PROFILER_followerBlock, 0);
18
spa_pod_builder_add_struct(&b,
19
20
SPA_POD_Long(na->awake_time),
21
SPA_POD_Long(na->finish_time),
22
SPA_POD_Int(na->status),
23
- SPA_POD_Fraction(&n->latency));
24
+ SPA_POD_Fraction(&latency));
25
}
26
spa_pod_builder_pop(&b, &f[0]);
27
28
pipewire-0.3.45.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-native.c
Changed
10
1
2
#include <fcntl.h>
3
#include <sys/file.h>
4
#include <ctype.h>
5
-#if HAVE_PWD_H
6
+#ifdef HAVE_PWD_H
7
#include <pwd.h>
8
#endif
9
#if defined(__FreeBSD__)
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-native/local-socket.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/local-socket.c
Changed
10
1
2
#include <sys/stat.h>
3
#include <fcntl.h>
4
#include <sys/file.h>
5
-#if HAVE_PWD_H
6
+#ifdef HAVE_PWD_H
7
#include <pwd.h>
8
#endif
9
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
19
1
2
}
3
4
/* returns true if an event with the (mask, event, index) triplet should be dropped because it is redundant */
5
-static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t index)
6
+static bool client_prune_subscribe_events(struct client *client, uint32_t event, uint32_t index)
7
{
8
struct message *m, *t;
9
10
11
12
pw_log_debug("client %p: SUBSCRIBE event:%08x index:%u", client, event, index);
13
14
- if (client_prune_subscribe_events(client, mask, event, index))
15
+ if (client_prune_subscribe_events(client, event, index))
16
return 0;
17
18
struct message *reply = message_alloc(client->impl, -1, 0);
19
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c
Changed
9
1
2
#include "../extension.h"
3
#include "../format.h"
4
#include "../manager.h"
5
-#include "../media-roles.h"
6
#include "../message.h"
7
#include "../reply.h"
8
#include "../volume.h"
9
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c
Changed
11
1
2
#include "../extension.h"
3
#include "../format.h"
4
#include "../manager.h"
5
-#include "../media-roles.h"
6
#include "../message.h"
7
+#include "../remap.h"
8
#include "../reply.h"
9
#include "../volume.h"
10
#include "registry.h"
11
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/message.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/message.c
Changed
57
1
2
#include <spa/debug/buffer.h>
3
#include <spa/utils/defs.h>
4
#include <spa/utils/string.h>
5
-#include <pipewire/keys.h>
6
#include <pipewire/log.h>
7
8
#include "defs.h"
9
#include "format.h"
10
#include "internal.h"
11
#include "log.h"
12
-#include "media-roles.h"
13
#include "message.h"
14
+#include "remap.h"
15
#include "volume.h"
16
17
#define MAX_SIZE (256*1024)
18
19
return v * v * v;
20
}
21
22
-static const struct str_map key_table[] = {
23
- { PW_KEY_DEVICE_BUS_PATH, "device.bus_path" },
24
- { PW_KEY_DEVICE_FORM_FACTOR, "device.form_factor" },
25
- { PW_KEY_DEVICE_ICON_NAME, "device.icon_name" },
26
- { PW_KEY_DEVICE_INTENDED_ROLES, "device.intended_roles" },
27
- { PW_KEY_NODE_DESCRIPTION, "device.description" },
28
- { PW_KEY_MEDIA_ICON_NAME, "media.icon_name" },
29
- { PW_KEY_APP_ICON_NAME, "application.icon_name" },
30
- { PW_KEY_APP_PROCESS_MACHINE_ID, "application.process.machine_id" },
31
- { PW_KEY_APP_PROCESS_SESSION_ID, "application.process.session_id" },
32
- { PW_KEY_MEDIA_ROLE, "media.role", media_role_map },
33
- { NULL, NULL },
34
-};
35
-
36
static int read_u8(struct message *m, uint8_t *val)
37
{
38
if (m->offset + 1 > m->length)
39
40
TAG_INVALID)) < 0)
41
return res;
42
43
- if (remap && (map = str_map_find(key_table, NULL, key)) != NULL) {
44
+ if (remap && (map = str_map_find(props_key_map, NULL, key)) != NULL) {
45
key = map->pw_str;
46
if (map->child != NULL &&
47
(map = str_map_find(map->child, NULL, data)) != NULL)
48
49
int l;
50
const struct str_map *map;
51
52
- if (remap && (map = str_map_find(key_table, key, NULL)) != NULL) {
53
+ if (remap && (map = str_map_find(props_key_map, key, NULL)) != NULL) {
54
key = map->pa_str;
55
if (map->child != NULL &&
56
(map = str_map_find(map->child, val, NULL)) != NULL)
57
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
127
1
2
3
#include <stdlib.h>
4
#include <string.h>
5
+#include <ctype.h>
6
7
#include <spa/utils/defs.h>
8
#include <spa/utils/list.h>
9
10
#include "internal.h"
11
#include "log.h"
12
#include "module.h"
13
+#include "remap.h"
14
15
static void on_module_unload(void *obj, void *data, int res, uint32_t index)
16
{
17
18
{
19
char *s = strdup(str), *p = s, *e, f;
20
const char *k, *v;
21
+ const struct str_map *map;
22
23
while (*p) {
24
+ while (*p && isspace(*p))
25
+ p++;
26
e = strchr(p, '=');
27
if (e == NULL)
28
break;
29
30
if (*e != '\0')
31
p++;
32
*e = '\0';
33
+
34
+ if ((map = str_map_find(props_key_map, NULL, k)) != NULL) {
35
+ k = map->pw_str;
36
+ if (map->child != NULL &&
37
+ (map = str_map_find(map->child, NULL, v)) != NULL)
38
+ v = map->pw_str;
39
+ }
40
pw_properties_set(props, k, v);
41
}
42
free(s);
43
44
#include "modules/registry.h"
45
46
static const struct module_info module_list[] = {
47
- { "module-combine-sink", create_module_combine_sink, },
48
- { "module-echo-cancel", create_module_echo_cancel, },
49
- { "module-ladspa-sink", create_module_ladspa_sink, },
50
- { "module-ladspa-source", create_module_ladspa_source, },
51
- { "module-loopback", create_module_loopback, },
52
- { "module-null-sink", create_module_null_sink, },
53
- { "module-native-protocol-tcp", create_module_native_protocol_tcp, },
54
- { "module-pipe-source", create_module_pipe_source, },
55
- { "module-pipe-sink", create_module_pipe_sink, },
56
- { "module-raop-discover", create_module_raop_discover, },
57
- { "module-remap-sink", create_module_remap_sink, },
58
- { "module-remap-source", create_module_remap_source, },
59
- { "module-simple-protocol-tcp", create_module_simple_protocol_tcp, },
60
- { "module-switch-on-connect", create_module_switch_on_connect, },
61
- { "module-tunnel-sink", create_module_tunnel_sink, },
62
- { "module-tunnel-source", create_module_tunnel_source, },
63
- { "module-zeroconf-discover", create_module_zeroconf_discover, },
64
+ { "module-always-sink", 1, create_module_always_sink, },
65
+ { "module-combine-sink", 0, create_module_combine_sink, },
66
+ { "module-echo-cancel", 0, create_module_echo_cancel, },
67
+ { "module-ladspa-sink", 0, create_module_ladspa_sink, },
68
+ { "module-ladspa-source", 0, create_module_ladspa_source, },
69
+ { "module-loopback", 0, create_module_loopback, },
70
+ { "module-null-sink", 0, create_module_null_sink, },
71
+ { "module-native-protocol-tcp", 0, create_module_native_protocol_tcp, },
72
+ { "module-pipe-source", 0, create_module_pipe_source, },
73
+ { "module-pipe-sink", 0, create_module_pipe_sink, },
74
+ { "module-raop-discover", 1, create_module_raop_discover, },
75
+ { "module-remap-sink", 0, create_module_remap_sink, },
76
+ { "module-remap-source", 0, create_module_remap_source, },
77
+ { "module-simple-protocol-tcp", 0, create_module_simple_protocol_tcp, },
78
+ { "module-switch-on-connect", 1, create_module_switch_on_connect, },
79
+ { "module-tunnel-sink", 0, create_module_tunnel_sink, },
80
+ { "module-tunnel-source", 0, create_module_tunnel_source, },
81
+ { "module-zeroconf-discover", 1, create_module_zeroconf_discover, },
82
#ifdef HAVE_AVAHI
83
- { "module-zeroconf-publish", create_module_zeroconf_publish, },
84
+ { "module-zeroconf-publish", 0, create_module_zeroconf_publish, },
85
#endif
86
- { "module-roc-sink", create_module_roc_sink, },
87
- { "module-roc-source", create_module_roc_source, },
88
- { "module-x11-bell", create_module_x11_bell, },
89
+ { "module-roc-sink", 0, create_module_roc_sink, },
90
+ { "module-roc-source", 0, create_module_roc_source, },
91
+ { "module-x11-bell", 0, create_module_x11_bell, },
92
};
93
94
static const struct module_info *find_module_info(const char *name)
95
96
return NULL;
97
}
98
99
+static int find_module_by_name(void *item_data, void *data)
100
+{
101
+ const char *name = data;
102
+ const struct module *module = item_data;
103
+ return spa_streq(module->name, name) ? 1 : 0;
104
+}
105
+
106
struct module *module_create(struct client *client, const char *name, const char *args)
107
{
108
struct impl *impl = client->impl;
109
110
errno = ENOENT;
111
return NULL;
112
}
113
+
114
+ if (info->load_once) {
115
+ int exists;
116
+ exists = pw_map_for_each(&impl->modules, find_module_by_name,
117
+ (void *)name);
118
+ if (exists) {
119
+ errno = EEXIST;
120
+ return NULL;
121
+ }
122
+ }
123
+
124
module = info->create(impl, args);
125
if (module == NULL)
126
return NULL;
127
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/module.h
Changed
9
1
2
3
struct module_info {
4
const char *name;
5
+ unsigned int load_once:1;
6
struct module *(*create) (struct impl *impl, const char *args);
7
};
8
9
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c
Added
138
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <pipewire/pipewire.h>
27
+
28
+#include "../module.h"
29
+
30
+#define NAME "always-sink"
31
+
32
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
33
+#define PW_LOG_TOPIC_DEFAULT mod_topic
34
+
35
+struct module_always_sink_data {
36
+ struct module *module;
37
+
38
+ struct pw_impl_module *mod;
39
+ struct spa_hook mod_listener;
40
+};
41
+
42
+static void module_destroy(void *data)
43
+{
44
+ struct module_always_sink_data *d = data;
45
+ spa_hook_remove(&d->mod_listener);
46
+ d->mod = NULL;
47
+ module_schedule_unload(d->module);
48
+}
49
+
50
+static const struct pw_impl_module_events module_events = {
51
+ PW_VERSION_IMPL_MODULE_EVENTS,
52
+ .destroy = module_destroy
53
+};
54
+
55
+static int module_always_sink_load(struct client *client, struct module *module)
56
+{
57
+ struct module_always_sink_data *data = module->user_data;
58
+ FILE *f;
59
+ char *args;
60
+ const char *str;
61
+ size_t size;
62
+
63
+ f = open_memstream(&args, &size);
64
+ fprintf(f, "{");
65
+ if ((str = pw_properties_get(module->props, "sink_name")) != NULL)
66
+ fprintf(f, " sink.name = \"%s\"", str);
67
+ fprintf(f, " }");
68
+ fclose(f);
69
+
70
+ data->mod = pw_context_load_module(module->impl->context,
71
+ "libpipewire-module-fallback-sink",
72
+ args, NULL);
73
+ free(args);
74
+
75
+ if (data->mod == NULL)
76
+ return -errno;
77
+
78
+ pw_impl_module_add_listener(data->mod,
79
+ &data->mod_listener,
80
+ &module_events, data);
81
+ return 0;
82
+}
83
+
84
+static int module_always_sink_unload(struct module *module)
85
+{
86
+ struct module_always_sink_data *d = module->user_data;
87
+
88
+ if (d->mod) {
89
+ spa_hook_remove(&d->mod_listener);
90
+ pw_impl_module_destroy(d->mod);
91
+ d->mod = NULL;
92
+ }
93
+ return 0;
94
+}
95
+
96
+static const struct module_methods module_always_sink_methods = {
97
+ VERSION_MODULE_METHODS,
98
+ .load = module_always_sink_load,
99
+ .unload = module_always_sink_unload,
100
+};
101
+
102
+static const struct spa_dict_item module_always_sink_info[] = {
103
+ { PW_KEY_MODULE_AUTHOR, "Pauli Virtanen <pav@iki.fi>" },
104
+ { PW_KEY_MODULE_DESCRIPTION, "Always keeps at least one sink loaded even if it's a null one" },
105
+ { PW_KEY_MODULE_USAGE, "sink_name=<name of sink>" },
106
+ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
107
+};
108
+
109
+struct module *create_module_always_sink(struct impl *impl, const char *argument)
110
+{
111
+ struct module *module;
112
+ struct pw_properties *props = NULL;
113
+ int res;
114
+
115
+ PW_LOG_TOPIC_INIT(mod_topic);
116
+
117
+ props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_always_sink_info));
118
+ if (props == NULL) {
119
+ res = -EINVAL;
120
+ goto out;
121
+ }
122
+ if (argument)
123
+ module_args_add_props(props, argument);
124
+
125
+ module = module_new(impl, &module_always_sink_methods, sizeof(struct module_always_sink_data));
126
+ if (module == NULL) {
127
+ res = -errno;
128
+ goto out;
129
+ }
130
+ module->props = props;
131
+
132
+ return module;
133
+out:
134
+ pw_properties_free(props);
135
+ errno = -res;
136
+ return NULL;
137
+}
138
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
201
1
2
3
#define MAX_SINKS 64 /* ... good enough for anyone */
4
5
+#define TIMEOUT_SINKS_MSEC 2000
6
+
7
static const struct spa_dict_item module_combine_sink_info[] = {
8
{ PW_KEY_MODULE_AUTHOR, "Arun Raghavan <arun@asymptotic.io>" },
9
{ PW_KEY_MODULE_DESCRIPTION, "Combine multiple sinks into a single sink" },
10
11
struct spa_hook stream_listener;
12
struct module_combine_sink_data *data;
13
bool cleanup;
14
+ bool started;
15
};
16
17
struct module_combine_sink_data {
18
19
struct combine_stream streams[MAX_SINKS];
20
21
struct spa_source *cleanup;
22
+ struct spa_source *sinks_timeout;
23
24
struct spa_audio_info_raw info;
25
+
26
+ unsigned int sinks_pending;
27
+ unsigned int source_started:1;
28
+ unsigned int load_emitted:1;
29
+ unsigned int start_error:1;
30
};
31
32
/* Core connection: mainly to unload the module if the connection errors out */
33
34
pw_stream_queue_buffer(data->sink, in);
35
}
36
37
+static void check_initialized(struct module_combine_sink_data *data)
38
+{
39
+ struct module *module = data->module;
40
+
41
+ if (data->load_emitted)
42
+ return;
43
+
44
+ if (data->start_error) {
45
+ pw_log_debug("module load error");
46
+ data->load_emitted = true;
47
+ module_emit_loaded(module, -EIO);
48
+ } else if (data->sinks_pending == 0 && data->source_started) {
49
+ pw_log_debug("module loaded");
50
+ data->load_emitted = true;
51
+ module_emit_loaded(module, 0);
52
+ }
53
+}
54
+
55
static void on_in_stream_state_changed(void *d, enum pw_stream_state old,
56
enum pw_stream_state state, const char *error)
57
{
58
59
struct module *module = data->module;
60
uint32_t i;
61
62
+ if (!data->source_started && state != PW_STREAM_STATE_CONNECTING) {
63
+ /* Input stream appears on server */
64
+ data->source_started = true;
65
+ if (state < PW_STREAM_STATE_PAUSED)
66
+ data->start_error = true;
67
+ check_initialized(data);
68
+ }
69
+
70
switch (state) {
71
case PW_STREAM_STATE_PAUSED:
72
pw_stream_flush(data->sink, false);
73
74
{
75
struct combine_stream *s = data;
76
77
+ if (!s->started && state != PW_STREAM_STATE_CONNECTING) {
78
+ /* Output stream appears on server */
79
+ s->started = true;
80
+ if (s->data->sinks_pending > 0)
81
+ --s->data->sinks_pending;
82
+ if (state < PW_STREAM_STATE_PAUSED)
83
+ s->data->start_error = true;
84
+ check_initialized(s->data);
85
+ }
86
+
87
if (state == PW_STREAM_STATE_UNCONNECTED) {
88
s->cleanup = true;
89
pw_loop_signal_event(s->data->module->impl->loop, s->data->cleanup);
90
91
pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true");
92
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
93
pw_properties_set(props, PW_KEY_NODE_PASSIVE, "true");
94
+ pw_properties_setf(props, "pulse.module.id", "%u", data->module->index);
95
96
cstream->data = data;
97
cstream->stream = pw_stream_new(data->core, NULL, props);
98
if (cstream->stream == NULL) {
99
pw_log_error("Could not create stream");
100
- return;
101
+ goto error;
102
}
103
104
pw_stream_add_listener(cstream->stream,
105
106
PW_STREAM_FLAG_RT_PROCESS,
107
params, n_params)) < 0) {
108
pw_log_error("Could not connect to sink '%s'", sink_name);
109
- return;
110
+ goto error;
111
}
112
+
113
+ return;
114
+
115
+error:
116
+ data->start_error = true;
117
+ check_initialized(data);
118
}
119
120
static const struct pw_manager_events manager_events = {
121
122
}
123
}
124
125
+static void on_sinks_timeout(void *d, uint64_t count)
126
+{
127
+ struct module_combine_sink_data *data = d;
128
+
129
+ if (data->load_emitted)
130
+ return;
131
+
132
+ data->start_error = true;
133
+ check_initialized(data);
134
+}
135
+
136
static int module_combine_sink_load(struct client *client, struct module *module)
137
{
138
struct module_combine_sink_data *data = module->user_data;
139
140
pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index);
141
pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index);
142
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
143
+ pw_properties_setf(props, "pulse.module.id", "%u", module->index);
144
145
if ((str = pw_properties_get(module->props, "sink_properties")) != NULL)
146
module_args_add_props(props, str);
147
148
return res;
149
150
data->manager = pw_manager_new(data->core);
151
- if (client->manager == NULL)
152
+ if (data->manager == NULL)
153
return -errno;
154
155
pw_manager_add_listener(data->manager, &data->manager_listener,
156
157
158
data->cleanup = pw_loop_add_event(module->impl->loop, on_cleanup, data);
159
160
- return 0;
161
+ data->sinks_timeout = pw_loop_add_timer(module->impl->loop, on_sinks_timeout, data);
162
+ if (data->sinks_timeout) {
163
+ struct timespec timeout = {0}, interval = {0};
164
+ timeout.tv_sec = TIMEOUT_SINKS_MSEC / 1000;
165
+ timeout.tv_nsec = (TIMEOUT_SINKS_MSEC % 1000) * SPA_NSEC_PER_MSEC;
166
+ pw_loop_update_timer(module->impl->loop, data->sinks_timeout, &timeout, &interval, false);
167
+ }
168
+
169
+ return data->load_emitted ? 0 : SPA_RESULT_RETURN_ASYNC(0);
170
}
171
172
static int module_combine_sink_unload(struct module *module)
173
174
if (d->cleanup != NULL)
175
pw_loop_destroy_source(module->impl->loop, d->cleanup);
176
177
+ if (d->sinks_timeout != NULL)
178
+ pw_loop_destroy_source(module->impl->loop, d->sinks_timeout);
179
+
180
/* Note that we explicitly disconnect the hooks to avoid having the
181
* cleanup triggered again in those callbacks */
182
if (d->sink != NULL) {
183
184
const char *str;
185
char *sink_name = NULL, **sink_names = NULL;
186
struct spa_audio_info_raw info = { 0 };
187
- int i, n, res;
188
+ int i, res;
189
+ int num_sinks = 0;
190
191
PW_LOG_TOPIC_INIT(mod_topic);
192
193
194
}
195
196
if ((str = pw_properties_get(props, "slaves")) != NULL) {
197
- sink_names = pw_split_strv(str, ",", MAX_SINKS, &n);
198
+ sink_names = pw_split_strv(str, ",", MAX_SINKS, &num_sinks);
199
pw_properties_set(props, "slaves", NULL);
200
}
201
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
25
1
2
3
pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index);
4
pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index);
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
7
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
11
if (pw_properties_get(capture_props, PW_KEY_DEVICE_CLASS) == NULL)
12
pw_properties_set(capture_props, PW_KEY_DEVICE_CLASS, "filter");
13
14
+ if ((str = pw_properties_get(capture_props, PW_KEY_NODE_DESCRIPTION)) == NULL) {
15
+ str = pw_properties_get(capture_props, PW_KEY_NODE_NAME);
16
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
17
+ "%s Sink", str);
18
+ } else {
19
+ pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
20
+ }
21
+
22
if ((str = pw_properties_get(props, "master")) != NULL ||
23
(str = pw_properties_get(props, "sink_master")) != NULL) {
24
pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str);
25
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
53
1
2
3
pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index);
4
pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index);
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
7
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
11
module_args_add_props(props, argument);
12
13
if ((str = pw_properties_get(props, "source_name")) != NULL) {
14
- pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
15
+ pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
16
pw_properties_set(props, "source_name", NULL);
17
}
18
if ((str = pw_properties_get(props, "source_properties")) != NULL) {
19
- module_args_add_props(capture_props, str);
20
+ module_args_add_props(playback_props, str);
21
pw_properties_set(props, "source_properties", NULL);
22
}
23
if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL)
24
25
if (pw_properties_get(playback_props, PW_KEY_DEVICE_CLASS) == NULL)
26
pw_properties_set(playback_props, PW_KEY_DEVICE_CLASS, "filter");
27
28
+ if ((str = pw_properties_get(playback_props, PW_KEY_NODE_DESCRIPTION)) == NULL) {
29
+ str = pw_properties_get(playback_props, PW_KEY_NODE_NAME);
30
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
31
+ "%s Source", str);
32
+ } else {
33
+ pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
34
+ }
35
+
36
if ((str = pw_properties_get(props, "master")) != NULL ||
37
(str = pw_properties_get(props, "source_master")) != NULL) {
38
- pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str);
39
+ pw_properties_set(capture_props, PW_KEY_NODE_TARGET, str);
40
pw_properties_set(props, "master", NULL);
41
}
42
43
- if (module_args_to_audioinfo(impl, props, &capture_info) < 0) {
44
+ if (module_args_to_audioinfo(impl, props, &playback_info) < 0) {
45
res = -EINVAL;
46
goto out;
47
}
48
- playback_info = capture_info;
49
+ capture_info = playback_info;
50
51
position_to_props(&capture_info, capture_props);
52
position_to_props(&playback_info, playback_props);
53
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
10
1
2
3
pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
4
pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
7
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
10
1
2
3
pw_core_add_listener(d->core, &d->core_listener, &core_events, module);
4
5
+ pw_properties_setf(module->props, "pulse.module.id", "%u", module->index);
6
+
7
d->proxy = pw_core_create_object(d->core,
8
"adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE,
9
module->props ? &module->props->dict : NULL, 0);
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c
Changed
10
1
2
&data->core_listener,
3
&core_events, data);
4
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+
7
data->capture = pw_stream_new(data->core,
8
"pipesink capture", data->capture_props);
9
data->capture_props = NULL;
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c
Changed
11
1
2
&data->core_listener,
3
&core_events, data);
4
5
+ pw_properties_setf(data->playback_props, "pulse.module.id",
6
+ "%u", module->index);
7
+
8
data->playback = pw_stream_new(data->core,
9
"pipesource playback", data->playback_props);
10
data->playback_props = NULL;
11
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
10
1
2
3
pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index);
4
pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index);
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
7
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
10
1
2
3
pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index);
4
pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index);
5
+ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
6
+ pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index);
7
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
28
1
2
{
3
struct module_roc_sink_data *data = module->user_data;
4
FILE *f;
5
- const char *str;
6
char *args;
7
size_t size;
8
9
+ pw_properties_setf(data->sink_props, "pulse.module.id",
10
+ "%u", module->index);
11
+
12
f = open_memstream(&args, &size);
13
fprintf(f, "{");
14
- /* Can't just serialise this dict because the "null" method gets
15
- * interpreted as a JSON null */
16
- if ((str = pw_properties_get(data->roc_props, "local.ip")))
17
- fprintf(f, " local.ip = \"%s\"", str);
18
- if ((str = pw_properties_get(data->roc_props, "remote.ip")))
19
- fprintf(f, " remote.ip = \"%s\"", str);
20
- if ((str = pw_properties_get(data->roc_props, "remote.source.port")))
21
- fprintf(f, " remote.source.port = \"%s\"", str);
22
- if ((str = pw_properties_get(data->roc_props, "remote.repair.port")))
23
- fprintf(f, " remote.repair.port = \"%s\"", str);
24
+ pw_properties_serialize_dict(f, &data->roc_props->dict, 0);
25
fprintf(f, " } sink.props = {");
26
pw_properties_serialize_dict(f, &data->sink_props->dict, 0);
27
fprintf(f, " } }");
28
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
30
1
2
{
3
struct module_roc_source_data *data = module->user_data;
4
FILE *f;
5
- const char *str;
6
char *args;
7
size_t size;
8
9
+ pw_properties_setf(data->source_props, "pulse.module.id",
10
+ "%u", module->index);
11
+
12
f = open_memstream(&args, &size);
13
fprintf(f, "{");
14
- /* Can't just serialise this dict because the "null" method gets
15
- * interpreted as a JSON null */
16
- if ((str = pw_properties_get(data->roc_props, "local.ip")))
17
- fprintf(f, " local.ip = \"%s\"", str);
18
- if ((str = pw_properties_get(data->roc_props, "local.source.port")))
19
- fprintf(f, " local.source.port = \"%s\"", str);
20
- if ((str = pw_properties_get(data->roc_props, "local.repair.port")))
21
- fprintf(f, " local.repair.port = \"%s\"", str);
22
- if ((str = pw_properties_get(data->roc_props, "sess.latency.msec")))
23
- fprintf(f, " sess.latency.msec = \"%s\"", str);
24
- if ((str = pw_properties_get(data->roc_props, "resampler.profile")))
25
- fprintf(f, " resampler.profile = \"%s\"", str);
26
+ pw_properties_serialize_dict(f, &data->roc_props->dict, 0);
27
fprintf(f, " } source.props = {");
28
pw_properties_serialize_dict(f, &data->source_props->dict, 0);
29
fprintf(f, " } }");
30
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
11
1
2
3
server = pw_properties_get(module->props, "server");
4
5
+ pw_properties_setf(data->stream_props, "pulse.module.id",
6
+ "%u", module->index);
7
+
8
f = open_memstream(&args, &size);
9
fprintf(f, "{");
10
pw_properties_serialize_dict(f, &module->props->dict, 0);
11
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
11
1
2
size_t size;
3
const char *server;
4
5
+ pw_properties_setf(data->stream_props, "pulse.module.id",
6
+ "%u", module->index);
7
+
8
server = pw_properties_get(module->props, "server");
9
10
f = open_memstream(&args, &size);
11
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c
Changed
10
1
2
}
3
4
data->manager = pw_manager_new(data->core);
5
- if (client->manager == NULL) {
6
+ if (data->manager == NULL) {
7
pw_log_error("failed to create pipewire manager: %m");
8
return -errno;
9
}
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/registry.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/registry.h
Changed
9
1
2
3
struct impl;
4
5
+struct module *create_module_always_sink(struct impl *impl, const char *argument);
6
struct module *create_module_combine_sink(struct impl *impl, const char *argument);
7
struct module *create_module_echo_cancel(struct impl *impl, const char *argument);
8
struct module *create_module_ladspa_sink(struct impl *impl, const char *argument);
9
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/operation.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.c
Changed
44
1
2
#include "operation.h"
3
#include "reply.h"
4
5
-int operation_new(struct client *client, uint32_t tag)
6
+int operation_new_cb(struct client *client, uint32_t tag,
7
+ void (*callback)(void *data, struct client *client, uint32_t tag),
8
+ void *data)
9
{
10
struct operation *o;
11
12
13
14
o->client = client;
15
o->tag = tag;
16
+ o->callback = callback;
17
+ o->data = data;
18
19
spa_list_append(&client->operations, &o->link);
20
pw_manager_sync(client->manager);
21
22
return 0;
23
}
24
25
+int operation_new(struct client *client, uint32_t tag)
26
+{
27
+ return operation_new_cb(client, tag, NULL, NULL);
28
+}
29
+
30
void operation_free(struct operation *o)
31
{
32
spa_list_remove(&o->link);
33
34
35
pw_log_info("[%s]: tag:%u complete", client->name, o->tag);
36
37
- reply_simple_ack(client, o->tag);
38
+ if (o->callback)
39
+ o->callback(o->data, client, o->tag);
40
+ else
41
+ reply_simple_ack(client, o->tag);
42
operation_free(o);
43
}
44
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/operation.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.h
Changed
16
1
2
struct spa_list link;
3
struct client *client;
4
uint32_t tag;
5
+ void (*callback) (void *data, struct client *client, uint32_t tag);
6
+ void *data;
7
};
8
9
int operation_new(struct client *client, uint32_t tag);
10
+int operation_new_cb(struct client *client, uint32_t tag,
11
+ void (*callback) (void *data, struct client *client, uint32_t tag),
12
+ void *data);
13
void operation_free(struct operation *o);
14
void operation_complete(struct operation *o);
15
16
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
201
1
2
}
3
4
static int send_object_event(struct client *client, struct pw_manager_object *o,
5
- uint32_t facility)
6
+ uint32_t type)
7
{
8
uint32_t event = 0, mask = 0, res_index = o->index;
9
10
if (pw_manager_object_is_sink(o)) {
11
client_queue_subscribe_event(client,
12
SUBSCRIPTION_MASK_SINK,
13
- SUBSCRIPTION_EVENT_SINK | facility,
14
+ SUBSCRIPTION_EVENT_SINK | type,
15
res_index);
16
}
17
if (pw_manager_object_is_source_or_monitor(o)) {
18
19
if (event != SPA_ID_INVALID)
20
client_queue_subscribe_event(client,
21
mask,
22
- event | facility,
23
+ event | type,
24
res_index);
25
return 0;
26
}
27
28
29
if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH)
30
attr->maxlength = MAXLENGTH;
31
- attr->maxlength -= attr->maxlength % frame_size;
32
- attr->maxlength = SPA_MAX(attr->maxlength, frame_size);
33
+ attr->maxlength = SPA_ROUND_UP(attr->maxlength, frame_size);
34
+
35
+ minreq = SPA_MIN(minreq, attr->maxlength);
36
37
if (attr->tlength == (uint32_t) -1)
38
attr->tlength = frac_to_bytes_round_up(s->default_tlength, &s->ss);
39
- if (attr->tlength > attr->maxlength)
40
- attr->tlength = attr->maxlength;
41
- attr->tlength -= attr->tlength % frame_size;
42
- attr->tlength = SPA_MAX(attr->tlength, frame_size);
43
+ attr->tlength = SPA_MIN(attr->tlength, attr->maxlength);
44
+ attr->tlength = SPA_ROUND_UP(attr->tlength, frame_size);
45
attr->tlength = SPA_MAX(attr->tlength, minreq);
46
47
if (attr->minreq == (uint32_t) -1) {
48
49
/* With low-latency, tlength/4 gives a decent default in all of traditional,
50
* adjust latency and early request modes. */
51
uint32_t m = attr->tlength / 4;
52
- m -= m % frame_size;
53
+ m = SPA_ROUND_DOWN(m, frame_size);
54
attr->minreq = SPA_MIN(process, m);
55
}
56
attr->minreq = SPA_MAX(attr->minreq, minreq);
57
58
if (attr->tlength < attr->minreq+frame_size)
59
- attr->tlength = attr->minreq + frame_size;
60
+ attr->tlength = SPA_MIN(attr->minreq + frame_size, attr->maxlength);
61
62
if (s->early_requests) {
63
latency = attr->minreq;
64
65
else
66
latency = attr->minreq;
67
68
- latency -= latency % frame_size;
69
+ latency = SPA_ROUND_DOWN(latency, frame_size);
70
71
if (attr->tlength >= latency)
72
attr->tlength -= latency;
73
74
}
75
76
if (attr->tlength < latency + 2 * attr->minreq)
77
- attr->tlength = latency + 2 * attr->minreq;
78
+ attr->tlength = SPA_MIN(latency + 2 * attr->minreq, attr->maxlength);
79
80
- attr->minreq -= attr->minreq % frame_size;
81
+ attr->minreq = SPA_ROUND_DOWN(attr->minreq, frame_size);
82
if (attr->minreq <= 0) {
83
attr->minreq = frame_size;
84
attr->tlength += frame_size*2;
85
}
86
if (attr->tlength <= attr->minreq)
87
- attr->tlength = attr->minreq*2 + frame_size;
88
+ attr->tlength = SPA_MIN(attr->minreq*2 + frame_size, attr->maxlength);
89
90
max_prebuf = attr->tlength + frame_size - attr->minreq;
91
if (attr->prebuf == (uint32_t) -1 || attr->prebuf > max_prebuf)
92
attr->prebuf = max_prebuf;
93
- attr->prebuf -= attr->prebuf % frame_size;
94
+ attr->prebuf = SPA_ROUND_DOWN(attr->prebuf, frame_size);
95
96
attr->fragsize = 0;
97
98
99
pw_log_info("[%s] SUBSCRIBE tag:%u mask:%08x",
100
client->name, tag, mask);
101
102
+ if (mask & ~SUBSCRIPTION_MASK_ALL)
103
+ return -EINVAL;
104
+
105
client->subscribed = mask;
106
107
return reply_simple_ack(client, tag);
108
109
return o;
110
}
111
112
-static void sample_play_ready(void *data, uint32_t index)
113
+static void sample_play_ready_reply(void *data, struct client *client, uint32_t tag)
114
{
115
struct pending_sample *ps = data;
116
- struct client *client = ps->client;
117
struct message *reply;
118
+ uint32_t index = id_to_index(client->manager, ps->play->id);
119
120
pw_log_info("[%s] PLAY_SAMPLE tag:%u index:%u",
121
client->name, ps->tag, index);
122
123
client_queue_message(client, reply);
124
}
125
126
+static void sample_play_ready(void *data, uint32_t id)
127
+{
128
+ struct pending_sample *ps = data;
129
+ struct client *client = ps->client;
130
+ operation_new_cb(client, ps->tag, sample_play_ready_reply, ps);
131
+}
132
+
133
static void on_sample_done(void *obj, void *data, int res, uint32_t id)
134
{
135
struct pending_sample *ps = obj;
136
137
snprintf(monitor_name, size, "%s.monitor", name);
138
139
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
140
+ module_id = id_to_index(manager, (uint32_t)atoi(str));
141
+ if (module_id == SPA_ID_INVALID &&
142
+ (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
143
module_id = (uint32_t)atoi(str);
144
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
145
card_id = (uint32_t)atoi(str);
146
147
TAG_STRING, desc,
148
TAG_SAMPLE_SPEC, &dev_info.ss,
149
TAG_CHANNEL_MAP, &dev_info.map,
150
- TAG_U32, id_to_index(manager, module_id), /* module index */
151
+ TAG_U32, module_id, /* module index */
152
TAG_CVOLUME, &dev_info.volume_info.volume,
153
TAG_BOOLEAN, dev_info.volume_info.mute,
154
TAG_U32, o->index, /* monitor source index */
155
156
snprintf(monitor_desc, size, "Monitor of %s", desc);
157
158
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
159
+ module_id = id_to_index(manager, (uint32_t)atoi(str));
160
+ if (module_id == SPA_ID_INVALID &&
161
+ (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
162
module_id = (uint32_t)atoi(str);
163
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
164
card_id = (uint32_t)atoi(str);
165
166
TAG_STRING, is_monitor ? monitor_desc : desc,
167
TAG_SAMPLE_SPEC, &dev_info.ss,
168
TAG_CHANNEL_MAP, &dev_info.map,
169
- TAG_U32, id_to_index(manager, module_id), /* module index */
170
+ TAG_U32, module_id, /* module index */
171
TAG_CVOLUME, &dev_info.volume_info.volume,
172
TAG_BOOLEAN, dev_info.volume_info.mute,
173
TAG_U32, is_monitor ? o->index : SPA_ID_INVALID,/* monitor of sink */
174
175
return -ENOENT;
176
177
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
178
+ module_id = id_to_index(manager, (uint32_t)atoi(str));
179
+ if (module_id == SPA_ID_INVALID &&
180
+ (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
181
module_id = (uint32_t)atoi(str);
182
+
183
if (!pw_manager_object_is_virtual(o) &&
184
(str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL)
185
client_id = (uint32_t)atoi(str);
186
187
message_put(m,
188
TAG_U32, o->index, /* sink_input index */
189
TAG_STRING, get_media_name(info),
190
- TAG_U32, id_to_index(manager, module_id), /* module index */
191
+ TAG_U32, module_id, /* module index */
192
TAG_U32, id_to_index(manager, client_id), /* client index */
193
TAG_U32, peer_index, /* sink index */
194
TAG_SAMPLE_SPEC, &dev_info.ss,
195
196
return -ENOENT;
197
198
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
199
+ module_id = id_to_index(manager, (uint32_t)atoi(str));
200
+ if (module_id == SPA_ID_INVALID &&
201
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/quirks.c
Changed
137
1
2
return 0;
3
}
4
5
-static bool find_match(struct spa_json *arr, const struct spa_dict *props)
6
-{
7
- struct spa_json it[1];
8
-
9
- while (spa_json_enter_object(arr, &it[0]) > 0) {
10
- char key[256], val[1024];
11
- const char *str, *value;
12
- int match = 0, fail = 0;
13
- int len;
14
-
15
- while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
16
- bool success = false;
17
-
18
- if ((len = spa_json_next(&it[0], &value)) <= 0)
19
- break;
20
-
21
- str = spa_dict_lookup(props, key);
22
-
23
- if (spa_json_is_null(value, len)) {
24
- success = str == NULL;
25
- } else {
26
- if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0)
27
- continue;
28
- value = val;
29
- len = strlen(val);
30
- }
31
- if (str != NULL) {
32
- if (value[0] == '~') {
33
- regex_t preg;
34
- if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
35
- if (regexec(&preg, str, 0, NULL, 0) == 0)
36
- success = true;
37
- regfree(&preg);
38
- }
39
- } else if (strncmp(str, value, len) == 0 &&
40
- strlen(str) == (size_t)len) {
41
- success = true;
42
- }
43
- }
44
- if (success) {
45
- match++;
46
- pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
47
- }
48
- else
49
- fail++;
50
- }
51
- if (match > 0 && fail == 0)
52
- return true;
53
- }
54
- return false;
55
-}
56
-
57
-static int pw_conf_match_rules(const char *rules, size_t size, const struct spa_dict *props,
58
- int (*matched) (void *data, const char *action, const char *val, int len),
59
- void *data)
60
-{
61
- const char *val;
62
- struct spa_json it[4], actions;
63
- int count = 0;
64
-
65
- spa_json_init(&it[0], rules, size);
66
- if (spa_json_enter_array(&it[0], &it[1]) < 0)
67
- return 0;
68
-
69
- while (spa_json_enter_object(&it[1], &it[2]) > 0) {
70
- char key[64];
71
- bool have_match = false, have_actions = false;
72
-
73
- while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
74
- if (spa_streq(key, "matches")) {
75
- if (spa_json_enter_array(&it[2], &it[3]) < 0)
76
- break;
77
-
78
- have_match = find_match(&it[3], props);
79
- }
80
- else if (spa_streq(key, "actions")) {
81
- if (spa_json_enter_object(&it[2], &actions) > 0)
82
- have_actions = true;
83
- }
84
- else if (spa_json_next(&it[2], &val) <= 0)
85
- break;
86
- }
87
- if (!have_match || !have_actions)
88
- continue;
89
-
90
- while (spa_json_get_string(&actions, key, sizeof(key)) > 0) {
91
- int res, len;
92
- pw_log_debug("action %s", key);
93
-
94
- if ((len = spa_json_next(&actions, &val)) <= 0)
95
- break;
96
-
97
- if (spa_json_is_container(val, len))
98
- len = spa_json_container_len(&actions, val, len);
99
-
100
- if ((res = matched(data, key, val, len)) < 0)
101
- return res;
102
-
103
- count += res;
104
- }
105
- }
106
- return count;
107
-}
108
-
109
-static int client_rule_matched(void *data, const char *action, const char *val, int len)
110
+static int apply_match(void *data, const char *location, const char *action,
111
+ const char *val, size_t len)
112
{
113
struct client *client = data;
114
115
116
return 0;
117
}
118
119
-static int apply_pulse_rules(void *data, const char *location, const char *section,
120
- const char *str, size_t len)
121
-{
122
- struct client *client = data;
123
- pw_conf_match_rules(str, len, &client->props->dict,
124
- client_rule_matched, client);
125
- return 0;
126
-}
127
-
128
int client_update_quirks(struct client *client)
129
{
130
struct impl *impl = client->impl;
131
struct pw_context *context = impl->context;
132
- return pw_context_conf_section_for_each(context, "pulse.rules",
133
- apply_pulse_rules, client);
134
+ return pw_context_conf_section_match_rules(context, "pulse.rules",
135
+ &client->props->dict, apply_match, client);
136
}
137
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/remap.c
Added
58
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2020 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 <stddef.h>
27
+
28
+#include <pipewire/keys.h>
29
+
30
+#include "remap.h"
31
+
32
+const struct str_map media_role_map[] = {
33
+ { "Movie", "video", },
34
+ { "Music", "music", },
35
+ { "Game", "game", },
36
+ { "Notification", "event", },
37
+ { "Communication", "phone", },
38
+ { "Movie", "animation", },
39
+ { "Production", "production", },
40
+ { "Accessibility", "a11y", },
41
+ { "Test", "test", },
42
+ { NULL, NULL },
43
+};
44
+
45
+const struct str_map props_key_map[] = {
46
+ { PW_KEY_DEVICE_BUS_PATH, "device.bus_path" },
47
+ { PW_KEY_DEVICE_FORM_FACTOR, "device.form_factor" },
48
+ { PW_KEY_DEVICE_ICON_NAME, "device.icon_name" },
49
+ { PW_KEY_DEVICE_INTENDED_ROLES, "device.intended_roles" },
50
+ { PW_KEY_NODE_DESCRIPTION, "device.description" },
51
+ { PW_KEY_MEDIA_ICON_NAME, "media.icon_name" },
52
+ { PW_KEY_APP_ICON_NAME, "application.icon_name" },
53
+ { PW_KEY_APP_PROCESS_MACHINE_ID, "application.process.machine_id" },
54
+ { PW_KEY_APP_PROCESS_SESSION_ID, "application.process.session_id" },
55
+ { PW_KEY_MEDIA_ROLE, "media.role", media_role_map },
56
+ { NULL, NULL },
57
+};
58
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/remap.h
Added
54
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2020 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 PULSE_SERVER_REMAP_H
27
+#define PULSE_SERVER_REMAP_H
28
+
29
+#include <stddef.h>
30
+
31
+#include <spa/utils/string.h>
32
+
33
+struct str_map {
34
+ const char *pw_str;
35
+ const char *pa_str;
36
+ const struct str_map *child;
37
+};
38
+
39
+extern const struct str_map media_role_map[];
40
+
41
+extern const struct str_map props_key_map[];
42
+
43
+static inline const struct str_map *str_map_find(const struct str_map *map, const char *pw, const char *pa)
44
+{
45
+ size_t i;
46
+ for (i = 0; map[i].pw_str; i++)
47
+ if ((pw && spa_streq(map[i].pw_str, pw)) ||
48
+ (pa && spa_streq(map[i].pa_str, pa)))
49
+ return &map[i];
50
+ return NULL;
51
+}
52
+
53
+#endif /* PULSE_SERVER_REMAP_H */
54
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/sample-play.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/sample-play.c
Changed
12
1
2
sample_play_emit_done(p, -EIO);
3
break;
4
case PW_STREAM_STATE_PAUSED:
5
- p->index = pw_stream_get_node_id(p->stream);
6
- sample_play_emit_ready(p, p->index);
7
+ p->id = pw_stream_get_node_id(p->stream);
8
+ sample_play_emit_ready(p, p->id);
9
break;
10
default:
11
break;
12
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/sample-play.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/sample-play.h
Changed
10
1
2
struct sample *sample;
3
struct pw_stream *stream;
4
struct spa_io_rate_match *rate_match;
5
- uint32_t index;
6
+ uint32_t id;
7
struct spa_hook listener;
8
struct pw_context *context;
9
struct pw_loop *main_loop;
10
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
19
1
2
if (errno == EINTR)
3
continue;
4
res = -errno;
5
- if (res != -EAGAIN && res != -EWOULDBLOCK)
6
+ if (res != -EAGAIN && res != -EWOULDBLOCK &&
7
+ res != -EPIPE && res != -ECONNRESET)
8
pw_log_warn("recv client:%p res %zd: %m", client, r);
9
goto exit;
10
}
11
12
error:
13
switch (res) {
14
case -EPIPE:
15
+ case -ECONNRESET:
16
pw_log_info("server %p: client %p [%s] disconnected",
17
client->server, client, client->name);
18
SPA_FALLTHROUGH;
19
pipewire-0.3.45.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-raop-sink.c
Changed
21
1
2
#define DEFAULT_CHANNELS "2"
3
#define DEFAULT_POSITION "[ FL FR ]"
4
5
+#define DEFAULT_LATENCY (DEFAULT_RATE*2)
6
+
7
#define MODULE_USAGE "[ node.latency=<latency as fraction> ] " \
8
"[ node.name=<name of the nodes> ] " \
9
"[ node.description=<description of the nodes> ] " \
10
11
12
if ((str = spa_dict_lookup(headers, "Audio-Latency")) != NULL) {
13
if (!spa_atou32(str, &impl->latency, 0))
14
- impl->latency = 0;
15
+ impl->latency = DEFAULT_LATENCY;
16
+ } else {
17
+ impl->latency = DEFAULT_LATENCY;
18
}
19
20
spa_zero(latency);
21
pipewire-0.3.45.tar.gz/src/pipewire/conf.c -> pipewire-0.3.47.tar.gz/src/pipewire/conf.c
Changed
201
1
2
#include <unistd.h>
3
#include <sys/wait.h>
4
#include <dirent.h>
5
-#if HAVE_PWD_H
6
+#include <regex.h>
7
+#ifdef HAVE_PWD_H
8
#include <pwd.h>
9
#endif
10
#ifdef __FreeBSD__
11
12
if (pid == 0) {
13
char *cmd, **argv;
14
15
+ /* Double fork to avoid zombies; we don't want to set SIGCHLD handler */
16
+ pid = fork();
17
+
18
+ if (pid < 0) {
19
+ pw_log_error("fork error: %m");
20
+ exit(1);
21
+ } else if (pid != 0) {
22
+ exit(0);
23
+ }
24
+
25
cmd = spa_aprintf("%s %s", key, args ? args : "");
26
argv = pw_split_strv(cmd, " \t", INT_MAX, &n_args);
27
free(cmd);
28
29
if (res == -1) {
30
res = -errno;
31
pw_log_error("execvp error '%s': %m", key);
32
- return res;
33
}
34
- }
35
- else {
36
+
37
+ exit(1);
38
+ } else if (pid < 0) {
39
+ pw_log_error("fork error: %m");
40
+ } else {
41
int status = 0;
42
- res = waitpid(pid, &status, WNOHANG);
43
- pw_log_info("exec got pid %d res:%d status:%d", pid, res, status);
44
+ do {
45
+ errno = 0;
46
+ res = waitpid(pid, &status, 0);
47
+ } while (res < 0 && errno == EINTR);
48
+ pw_log_debug("exec got pid %d res:%d status:%d", (int)pid, res, status);
49
}
50
return 0;
51
}
52
53
return res;
54
}
55
56
+
57
SPA_EXPORT
58
int pw_context_conf_section_for_each(struct pw_context *context, const char *section,
59
int (*callback) (void *data, const char *location, const char *section,
60
61
struct pw_properties *conf = context->conf;
62
const char *path = NULL;
63
const struct spa_dict_item *it;
64
- int res;
65
+ int res = 0;
66
67
spa_dict_for_each(it, &conf->dict) {
68
if (spa_strendswith(it->key, "config.path")) {
69
70
update_props, &data);
71
return data.count;
72
}
73
+
74
+struct match {
75
+ const struct spa_dict *props;
76
+ int (*matched) (void *data, const char *location, const char *action,
77
+ const char *val, size_t len);
78
+ void *data;
79
+};
80
+
81
+/*
82
+ * {
83
+ * # all keys must match the value. ~ in value starts regex.
84
+ * <key> = <value>
85
+ * ...
86
+ * }
87
+ */
88
+static bool find_match(struct spa_json *arr, const struct spa_dict *props)
89
+{
90
+ struct spa_json it[1];
91
+
92
+ while (spa_json_enter_object(arr, &it[0]) > 0) {
93
+ char key[256], val[1024];
94
+ const char *str, *value;
95
+ int match = 0, fail = 0;
96
+ int len;
97
+
98
+ while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
99
+ bool success = false;
100
+
101
+ if ((len = spa_json_next(&it[0], &value)) <= 0)
102
+ break;
103
+
104
+ str = spa_dict_lookup(props, key);
105
+
106
+ if (spa_json_is_null(value, len)) {
107
+ success = str == NULL;
108
+ } else {
109
+ if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0)
110
+ continue;
111
+ value = val;
112
+ len = strlen(val);
113
+ }
114
+ if (str != NULL) {
115
+ if (value[0] == '~') {
116
+ regex_t preg;
117
+ if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
118
+ if (regexec(&preg, str, 0, NULL, 0) == 0)
119
+ success = true;
120
+ regfree(&preg);
121
+ }
122
+ } else if (strncmp(str, value, len) == 0 &&
123
+ strlen(str) == (size_t)len) {
124
+ success = true;
125
+ }
126
+ }
127
+ if (success) {
128
+ match++;
129
+ pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
130
+ }
131
+ else
132
+ fail++;
133
+ }
134
+ if (match > 0 && fail == 0)
135
+ return true;
136
+ }
137
+ return false;
138
+}
139
+
140
+/**
141
+ * rules = [
142
+ * {
143
+ * matches = [
144
+ * # any of the items in matches needs to match, it one does,
145
+ * # actions are emited.
146
+ * {
147
+ * # all keys must match the value. ~ in value starts regex.
148
+ * <key> = <value>
149
+ * ...
150
+ * }
151
+ * ...
152
+ * ]
153
+ * actions = {
154
+ * <action> = <value>
155
+ * ...
156
+ * }
157
+ * }
158
+ * ]
159
+ */
160
+static int match_rules(void *data, const char *location, const char *section,
161
+ const char *str, size_t len)
162
+{
163
+ struct match *match = data;
164
+ const struct spa_dict *props = match->props;
165
+ const char *val;
166
+ struct spa_json it[4], actions;
167
+
168
+ spa_json_init(&it[0], str, len);
169
+ if (spa_json_enter_array(&it[0], &it[1]) < 0)
170
+ return 0;
171
+
172
+ while (spa_json_enter_object(&it[1], &it[2]) > 0) {
173
+ char key[64];
174
+ bool have_match = false, have_actions = false;
175
+
176
+ while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
177
+ if (spa_streq(key, "matches")) {
178
+ if (spa_json_enter_array(&it[2], &it[3]) < 0)
179
+ break;
180
+
181
+ have_match = find_match(&it[3], props);
182
+ }
183
+ else if (spa_streq(key, "actions")) {
184
+ if (spa_json_enter_object(&it[2], &actions) > 0)
185
+ have_actions = true;
186
+ }
187
+ else if (spa_json_next(&it[2], &val) <= 0)
188
+ break;
189
+ }
190
+ if (!have_match || !have_actions)
191
+ continue;
192
+
193
+ while (spa_json_get_string(&actions, key, sizeof(key)) > 0) {
194
+ int res, len;
195
+ pw_log_debug("action %s", key);
196
+
197
+ if ((len = spa_json_next(&actions, &val)) <= 0)
198
+ break;
199
+
200
+ if (spa_json_is_container(val, len))
201
pipewire-0.3.45.tar.gz/src/pipewire/context.c -> pipewire-0.3.47.tar.gz/src/pipewire/context.c
Changed
36
1
2
struct pw_impl_node *n, *s, *target, *fallback;
3
uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum;
4
uint32_t *rates, n_rates, def_rate;
5
- bool freewheel = false, global_force_rate, force_rate, global_force_quantum;
6
+ bool freewheel = false, global_force_rate, force_rate, force_quantum, global_force_quantum;
7
8
pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason);
9
10
11
get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum);
12
rates = get_rates(context, &def_rate, &n_rates, &global_force_rate);
13
14
- global_force_quantum = rate_quantum == 0;
15
+ force_quantum = global_force_quantum = rate_quantum == 0;
16
force_rate = global_force_rate;
17
18
/* start from all drivers and group all nodes that are linked
19
20
def_quantum = min_quantum = max_quantum = s->force_quantum;
21
rate_quantum = 0;
22
quantum_stamp = s->stamp;
23
+ force_quantum = true;
24
}
25
if (!global_force_rate && s->force_rate > 0 &&
26
s->stamp > rate_stamp) {
27
28
running = !n->passive;
29
}
30
31
+ if (force_quantum)
32
+ lock_quantum = false;
33
if (force_rate)
34
lock_rate = false;
35
36
pipewire-0.3.45.tar.gz/src/pipewire/context.h -> pipewire-0.3.47.tar.gz/src/pipewire/context.h
Changed
14
1
2
int (*callback) (void *data, const char *location, const char *section,
3
const char *str, size_t len),
4
void *data);
5
+/** emit callback for all matched properties. Since 0.3.46 */
6
+int pw_context_conf_section_match_rules(struct pw_context *context, const char *section,
7
+ struct spa_dict *props,
8
+ int (*callback) (void *data, const char *location, const char *action,
9
+ const char *str, size_t len),
10
+ void *data);
11
12
/** Get the context support objects */
13
const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support);
14
pipewire-0.3.45.tar.gz/src/pipewire/filter.c -> pipewire-0.3.47.tar.gz/src/pipewire/filter.c
Changed
99
1
2
#define MAX_BUFFERS 64
3
4
#define MASK_BUFFERS (MAX_BUFFERS-1)
5
-#define MAX_PORTS 1024
6
7
static bool mlock_warned = false;
8
9
10
} rt;
11
12
struct spa_list port_list;
13
- struct port *ports[2][MAX_PORTS];
14
+ struct pw_map ports[2];
15
16
uint32_t change_mask_all;
17
struct spa_node_info info;
18
19
enum spa_direction direction, uint32_t user_data_size)
20
{
21
struct port *p;
22
- int i;
23
-
24
- for (i = 0; i < MAX_PORTS; i++) {
25
- if ((filter->ports[direction][i]) == NULL)
26
- break;
27
- }
28
- if (i == MAX_PORTS)
29
- return NULL;
30
31
p = calloc(1, sizeof(struct port) + user_data_size);
32
p->filter = filter;
33
p->direction = direction;
34
- p->id = i;
35
p->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
36
p->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
37
38
spa_list_init(&p->param_list);
39
spa_ringbuffer_init(&p->dequeued.ring);
40
spa_ringbuffer_init(&p->queued.ring);
41
-
42
- filter->ports[direction][i] = p;
43
+ p->id = pw_map_insert_new(&filter->ports[direction], p);
44
spa_list_append(&filter->port_list, &p->link);
45
46
return p;
47
48
49
static inline struct port *get_port(struct filter *filter, enum spa_direction direction, uint32_t port_id)
50
{
51
- if ((direction != SPA_DIRECTION_INPUT && direction != SPA_DIRECTION_OUTPUT) ||
52
- port_id >= MAX_PORTS)
53
+ if ((direction != SPA_DIRECTION_INPUT && direction != SPA_DIRECTION_OUTPUT))
54
return NULL;
55
- return filter->ports[direction][port_id];
56
+ return pw_map_lookup(&filter->ports[direction], port_id);
57
}
58
59
static inline int push_queue(struct port *port, struct queue *queue, struct buffer *buffer)
60
61
62
spa_list_init(&impl->param_list);
63
spa_list_init(&impl->port_list);
64
+ pw_map_init(&impl->ports[SPA_DIRECTION_INPUT], 32, 32);
65
+ pw_map_init(&impl->ports[SPA_DIRECTION_OUTPUT], 32, 32);
66
67
spa_hook_list_init(&this->listener_list);
68
spa_list_init(&this->controls);
69
70
spa_hook_list_clean(&impl->hooks);
71
spa_hook_list_clean(&filter->listener_list);
72
73
+ pw_map_clear(&impl->ports[SPA_DIRECTION_INPUT]);
74
+ pw_map_clear(&impl->ports[SPA_DIRECTION_OUTPUT]);
75
+
76
free(filter->name);
77
78
if (impl->data.context)
79
80
SPA_NODE_CHANGE_MASK_PARAMS;
81
82
impl->info = SPA_NODE_INFO_INIT();
83
- impl->info.max_input_ports = MAX_PORTS;
84
- impl->info.max_output_ports = MAX_PORTS;
85
+ impl->info.max_input_ports = UINT32_MAX;
86
+ impl->info.max_output_ports = UINT32_MAX;
87
impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0;
88
impl->info.props = &filter->properties->dict;
89
impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
90
91
spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL);
92
93
spa_list_remove(&port->link);
94
- impl->ports[port->direction][port->id] = NULL;
95
+ pw_map_remove(&impl->ports[port->direction], port->id);
96
97
clear_buffers(port);
98
clear_params(impl, port, SPA_ID_INVALID);
99
pipewire-0.3.45.tar.gz/src/pipewire/map.h -> pipewire-0.3.47.tar.gz/src/pipewire/map.h
Changed
10
1
2
*/
3
static inline void pw_map_init(struct pw_map *map, size_t size, size_t extend)
4
{
5
- pw_array_init(&map->items, extend);
6
+ pw_array_init(&map->items, extend * sizeof(union pw_map_item));
7
pw_array_ensure_size(&map->items, size * sizeof(union pw_map_item));
8
map->free_list = SPA_ID_INVALID;
9
}
10
pipewire-0.3.45.tar.gz/src/pipewire/proxy.c -> pipewire-0.3.47.tar.gz/src/pipewire/proxy.c
Changed
34
1
2
pw_proxy_emit_destroy(proxy);
3
}
4
5
- spa_hook_list_clean(&proxy->listener_list);
6
- spa_hook_list_clean(&proxy->object_listener_list);
7
-
8
pw_proxy_unref(proxy);
9
}
10
11
12
pw_log_debug("%p: free %u", proxy, proxy->id);
13
/** client must explicitly destroy all proxies */
14
assert(proxy->destroyed);
15
+
16
+#if DEBUG_LISTENERS
17
+ {
18
+ struct spa_hook *h;
19
+ spa_list_for_each(h, &proxy->object_listener_list.list, link) {
20
+ pw_log_warn("%p: proxy %u: leaked object listener %p",
21
+ proxy, proxy->id, h);
22
+ break;
23
+ }
24
+ spa_list_for_each(h, &proxy->listener_list.list, link) {
25
+ pw_log_warn("%p: proxy %u: leaked listener %p",
26
+ proxy, proxy->id, h);
27
+ break;
28
+ }
29
+ }
30
+#endif
31
free(proxy);
32
}
33
34
pipewire-0.3.45.tar.gz/src/pipewire/stream.c -> pipewire-0.3.47.tar.gz/src/pipewire/stream.c
Changed
9
1
2
#define MAX_BUFFERS 64
3
4
#define MASK_BUFFERS (MAX_BUFFERS-1)
5
-#define MAX_PORTS 1
6
7
static bool mlock_warned = false;
8
9
pipewire-0.3.45.tar.gz/src/pipewire/utils.c -> pipewire-0.3.47.tar.gz/src/pipewire/utils.c
Changed
10
1
2
#include <fcntl.h>
3
#include <unistd.h>
4
#include <errno.h>
5
-#if HAVE_SYS_RANDOM_H
6
+#ifdef HAVE_SYS_RANDOM_H
7
#include <sys/random.h>
8
#endif
9
#include <string.h>
10
pipewire-0.3.45.tar.gz/src/tools/meson.build -> pipewire-0.3.47.tar.gz/src/tools/meson.build
Changed
10
1
2
endif
3
4
build_pw_cat = false
5
-if not get_option('pw-cat').disabled() and sndfile_dep.found()
6
+if get_option('pw-cat').allowed() and sndfile_dep.found()
7
build_pw_cat = true
8
9
pwcat_sources = [
10
pipewire-0.3.45.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.47.tar.gz/src/tools/pw-cat.c
Changed
53
1
2
struct data *data = userdata;
3
4
if (data->verbose)
5
- fprintf(stdout, "remote %"PRIu32" is named \"%s\"\n",
6
+ printf("remote %"PRIu32" is named \"%s\"\n",
7
info->id, info->name);
8
}
9
10
11
id, type, name, media_class, desc ? : "", prio);
12
13
spa_dict_for_each(item, props) {
14
- fprintf(stdout, "\t\t%s = \"%s\"\n", item->key, item->value);
15
+ printf("\t\t%s = \"%s\"\n", item->key, item->value);
16
}
17
}
18
19
20
return EXIT_SUCCESS;
21
22
case OPT_VERSION:
23
- fprintf(stdout, "%s\n"
24
+ printf("%s\n"
25
"Compiled with libpipewire %s\n"
26
"Linked with libpipewire %s\n",
27
prog,
28
29
}
30
31
error_connect_fail:
32
- if (data.stream)
33
+ if (data.stream) {
34
+ spa_hook_remove(&data.stream_listener);
35
pw_stream_destroy(data.stream);
36
+ }
37
error_no_stream:
38
- if (data.metadata)
39
+ if (data.metadata) {
40
+ spa_hook_remove(&data.metadata_listener);
41
pw_proxy_destroy((struct pw_proxy*)data.metadata);
42
- if (data.registry)
43
+ }
44
+ if (data.registry) {
45
+ spa_hook_remove(&data.registry_listener);
46
pw_proxy_destroy((struct pw_proxy*)data.registry);
47
+ }
48
error_no_registry:
49
+ spa_hook_remove(&data.core_listener);
50
pw_core_disconnect(data.core);
51
error_ctx_connect_failed:
52
pw_context_destroy(data.context);
53
pipewire-0.3.45.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.47.tar.gz/src/tools/pw-cli.c
Changed
201
1
2
#define FNM_EXTMATCH 0
3
#endif
4
5
-#define spa_debug(...) fprintf(stdout,__VA_ARGS__);fputc('\n', stdout)
6
+#define spa_debug(fmt,...) printf(fmt, ## __VA_ARGS__)
7
8
#include <spa/utils/result.h>
9
#include <spa/utils/string.h>
10
11
const struct spa_dict_item *item;
12
13
if (header)
14
- fprintf(stdout, "%c\tproperties:\n", mark);
15
+ printf("%c\tproperties:\n", mark);
16
if (props == NULL || props->n_items == 0) {
17
if (header)
18
- fprintf(stdout, "\t\tnone\n");
19
+ printf("\t\tnone\n");
20
return;
21
}
22
23
spa_dict_for_each(item, props) {
24
- fprintf(stdout, "%c\t\t%s = \"%s\"\n", mark, item->key, item->value);
25
+ printf("%c\t\t%s = \"%s\"\n", mark, item->key, item->value);
26
}
27
}
28
29
30
uint32_t i;
31
32
if (header)
33
- fprintf(stdout, "%c\tparams: (%u)\n", mark, n_params);
34
+ printf("%c\tparams: (%u)\n", mark, n_params);
35
if (params == NULL || n_params == 0) {
36
if (header)
37
- fprintf(stdout, "\t\tnone\n");
38
+ printf("\t\tnone\n");
39
return;
40
}
41
for (i = 0; i < n_params; i++) {
42
const struct spa_type_info *type_info = spa_type_param;
43
44
- fprintf(stdout, "%c\t %d (%s) %c%c\n",
45
+ printf("%c\t %d (%s) %c%c\n",
46
params[i].user > 0 ? mark : ' ', params[i].id,
47
spa_debug_type_find_name(type_info, params[i].id),
48
params[i].flags & SPA_PARAM_INFO_READ ? 'r' : '-',
49
50
{
51
size_t i;
52
53
- fprintf(stdout, "Available commands:\n");
54
+ printf("Available commands:\n");
55
for (i = 0; i < SPA_N_ELEMENTS(command_list); i++) {
56
- fprintf(stdout, "\t%-20.20s\t%s\n", command_list[i].name, command_list[i].description);
57
+ printf("\t%-20.20s\t%s\n", command_list[i].name, command_list[i].description);
58
}
59
return true;
60
}
61
62
}
63
64
id = pw_map_insert_new(&data->vars, module);
65
- fprintf(stdout, "%d = @module:%d\n", id, pw_global_get_id(pw_impl_module_get_global(module)));
66
+ printf("%d = @module:%d\n", id, pw_global_get_id(pw_impl_module_get_global(module)));
67
68
return true;
69
}
70
71
free(rd->name);
72
rd->name = info->name ? strdup(info->name) : NULL;
73
if (rd->data->interactive)
74
- fprintf(stdout, "remote %d is named '%s'\n", rd->id, rd->name);
75
+ printf("remote %d is named '%s'\n", rd->id, rd->name);
76
}
77
78
static void set_prompt(struct remote_data *rd)
79
80
if (filter && !global_matches(global, filter))
81
return 0;
82
83
- fprintf(stdout, "\tid %d, type %s/%d\n", global->id,
84
+ printf("\tid %d, type %s/%d\n", global->id,
85
global->type, global->version);
86
if (global->properties)
87
print_properties(&global->properties->dict, ' ', false);
88
89
global->properties = props ? pw_properties_new_dict(props) : NULL;
90
91
if (rd->data->monitoring) {
92
- fprintf(stdout, "remote %d added global: ", rd->id);
93
+ printf("remote %d added global: ", rd->id);
94
print_global(global, NULL);
95
}
96
97
98
ret = bind_global(rd, global, &error);
99
if (!ret) {
100
if (rd->data->interactive)
101
- fprintf(stdout, "Error: \"%s\"\n", error);
102
+ fprintf(stderr, "Error: \"%s\"\n", error);
103
free(error);
104
}
105
}
106
107
108
global = pw_map_lookup(&rd->globals, id);
109
if (global == NULL) {
110
- fprintf(stdout, "remote %d removed unknown global %d\n", rd->id, id);
111
+ fprintf(stderr, "remote %d removed unknown global %d\n", rd->id, id);
112
return;
113
}
114
115
if (rd->data->monitoring) {
116
- fprintf(stdout, "remote %d removed global: ", rd->id);
117
+ printf("remote %d removed global: ", rd->id);
118
print_global(global, NULL);
119
}
120
121
122
spa_list_append(&data->remotes, &rd->link);
123
124
if (rd->data->interactive)
125
- fprintf(stdout, "%d = @remote:%p\n", rd->id, rd->core);
126
+ printf("%d = @remote:%p\n", rd->id, rd->core);
127
128
data->current = rd;
129
130
131
struct remote_data *rd;
132
133
spa_list_for_each(rd, &data->remotes, link)
134
- fprintf(stdout, "\t%d = @remote:%p '%s'\n", rd->id, rd->core, rd->name);
135
+ printf("\t%d = @remote:%p '%s'\n", rd->id, rd->core, rd->name);
136
137
return true;
138
}
139
140
if (global == NULL)
141
return;
142
143
- fprintf(stdout, "\tid: %d\n", global->id);
144
- fprintf(stdout, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
145
+ printf("\tid: %d\n", global->id);
146
+ printf("\tpermissions: "PW_PERMISSION_FORMAT"\n",
147
PW_PERMISSION_ARGS(global->permissions));
148
- fprintf(stdout, "\ttype: %s/%d\n", global->type, global->version);
149
+ printf("\ttype: %s/%d\n", global->type, global->version);
150
}
151
152
static void info_core(struct proxy_data *pd)
153
154
struct pw_core_info *info = pd->info;
155
156
info_global(pd);
157
- fprintf(stdout, "\tcookie: %u\n", info->cookie);
158
- fprintf(stdout, "\tuser-name: \"%s\"\n", info->user_name);
159
- fprintf(stdout, "\thost-name: \"%s\"\n", info->host_name);
160
- fprintf(stdout, "\tversion: \"%s\"\n", info->version);
161
- fprintf(stdout, "\tname: \"%s\"\n", info->name);
162
+ printf("\tcookie: %u\n", info->cookie);
163
+ printf("\tuser-name: \"%s\"\n", info->user_name);
164
+ printf("\thost-name: \"%s\"\n", info->host_name);
165
+ printf("\tversion: \"%s\"\n", info->version);
166
+ printf("\tname: \"%s\"\n", info->name);
167
print_properties(info->props, MARK_CHANGE(PW_CORE_CHANGE_MASK_PROPS), true);
168
info->change_mask = 0;
169
}
170
171
struct pw_module_info *info = pd->info;
172
173
info_global(pd);
174
- fprintf(stdout, "\tname: \"%s\"\n", info->name);
175
- fprintf(stdout, "\tfilename: \"%s\"\n", info->filename);
176
- fprintf(stdout, "\targs: \"%s\"\n", info->args);
177
+ printf("\tname: \"%s\"\n", info->name);
178
+ printf("\tfilename: \"%s\"\n", info->filename);
179
+ printf("\targs: \"%s\"\n", info->args);
180
print_properties(info->props, MARK_CHANGE(PW_MODULE_CHANGE_MASK_PROPS), true);
181
info->change_mask = 0;
182
}
183
184
struct pw_node_info *info = pd->info;
185
186
info_global(pd);
187
- fprintf(stdout, "%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS),
188
+ printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS),
189
info->n_input_ports, info->max_input_ports);
190
- fprintf(stdout, "%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS),
191
+ printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS),
192
info->n_output_ports, info->max_output_ports);
193
- fprintf(stdout, "%c\tstate: \"%s\"", MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE),
194
+ printf("%c\tstate: \"%s\"", MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE),
195
pw_node_state_as_string(info->state));
196
if (info->state == PW_NODE_STATE_ERROR && info->error)
197
- fprintf(stdout, " \"%s\"\n", info->error);
198
+ printf(" \"%s\"\n", info->error);
199
else
200
- fprintf(stdout, "\n");
201
pipewire-0.3.45.tar.gz/src/tools/pw-dot.c -> pipewire-0.3.47.tar.gz/src/tools/pw-dot.c
Changed
54
1
2
static void destroy_proxy(void *user_data)
3
{
4
struct global *g = user_data;
5
+ spa_hook_remove(&g->object_listener);
6
+ spa_hook_remove(&g->proxy_listener);
7
pw_properties_free(g->props);
8
if (g->info)
9
g->info_destroy(g->info);
10
11
pw_main_loop_quit(d->loop);
12
}
13
14
-static void show_help(const char *name)
15
+static void show_help(const char *name, bool error)
16
{
17
- fprintf(stdout, "%s [options]\n"
18
+ fprintf(error ? stderr : stdout, "%s [options]\n"
19
" -h, --help Show this help\n"
20
" --version Show version\n"
21
" -a, --all Show all object types\n"
22
23
while ((c = getopt_long(argc, argv, "hVasdr:o:L9", long_options, NULL)) != -1) {
24
switch (c) {
25
case 'h' :
26
- show_help(argv[0]);
27
+ show_help(argv[0], false);
28
return 0;
29
case 'V' :
30
- fprintf(stdout, "%s\n"
31
+ printf("%s\n"
32
"Compiled with libpipewire %s\n"
33
"Linked with libpipewire %s\n",
34
argv[0],
35
36
fprintf(stderr, "orthogonal edges enabled\n");
37
break;
38
default:
39
- show_help(argv[0]);
40
+ show_help(argv[0], true);
41
return -1;
42
}
43
}
44
45
draw_graph(&data, dot_path);
46
47
dot_str_clear(&data.dot_str);
48
+ spa_hook_remove(&data.registry_listener);
49
pw_proxy_destroy((struct pw_proxy*)data.registry);
50
+ spa_hook_remove(&data.core_listener);
51
pw_context_destroy(data.context);
52
pw_main_loop_destroy(data.loop);
53
pw_deinit();
54
pipewire-0.3.45.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.47.tar.gz/src/tools/pw-dump.c
Changed
57
1
2
pw_main_loop_quit(d->loop);
3
}
4
5
-static void show_help(struct data *data, const char *name)
6
+static void show_help(struct data *data, const char *name, bool error)
7
{
8
- fprintf(stdout, "%s [options] [<id>]\n"
9
+ fprintf(error ? stderr : stdout, "%s [options] [<id>]\n"
10
" -h, --help Show this help\n"
11
" --version Show version\n"
12
" -r, --remote Remote daemon name\n"
13
14
data.out = stdout;
15
if (isatty(fileno(data.out)) && getenv("NO_COLOR") == NULL)
16
colors = true;
17
+ setlinebuf(data.out);
18
19
while ((c = getopt_long(argc, argv, "hVr:mNC", long_options, NULL)) != -1) {
20
switch (c) {
21
case 'h' :
22
- show_help(&data, argv[0]);
23
+ show_help(&data, argv[0], false);
24
return 0;
25
case 'V' :
26
- fprintf(stdout, "%s\n"
27
+ printf("%s\n"
28
"Compiled with libpipewire %s\n"
29
"Linked with libpipewire %s\n",
30
argv[0],
31
32
else if (!strcmp(optarg, "always"))
33
colors = true;
34
else {
35
- show_help(&data, argv[0]);
36
+ fprintf(stderr, "Unknown color: %s\n", optarg);
37
+ show_help(&data, argv[0], true);
38
return -1;
39
}
40
break;
41
default:
42
- show_help(&data, argv[0]);
43
+ show_help(&data, argv[0], true);
44
return -1;
45
}
46
}
47
48
if (data.info)
49
pw_core_info_free(data.info);
50
51
+ spa_hook_remove(&data.registry_listener);
52
pw_proxy_destroy((struct pw_proxy*)data.registry);
53
+ spa_hook_remove(&data.core_listener);
54
pw_context_destroy(data.context);
55
pw_main_loop_destroy(data.loop);
56
pw_deinit();
57
pipewire-0.3.45.tar.gz/src/tools/pw-link.c -> pipewire-0.3.47.tar.gz/src/tools/pw-link.c
Changed
125
1
2
prefix2 = " ";
3
}
4
5
- fprintf(stdout, "%s%s%s%s\n", data->prefix, prefix,
6
+ printf("%s%s%s%s\n", data->prefix, prefix,
7
id, port_name(buffer, sizeof(buffer), n, p));
8
if (verbose) {
9
port_path(buffer, sizeof(buffer), n, p);
10
if (buffer[0] != '\0')
11
- fprintf(stdout, "%s %s%s%s\n", data->prefix, prefix2, prefix, buffer);
12
+ printf("%s %s%s%s\n", data->prefix, prefix2, prefix, buffer);
13
port_alias(buffer, sizeof(buffer), n, p);
14
if (buffer[0] != '\0')
15
- fprintf(stdout, "%s %s%s%s\n", data->prefix, prefix2, prefix, buffer);
16
+ printf("%s %s%s%s\n", data->prefix, prefix2, prefix, buffer);
17
}
18
}
19
20
21
if (data->opt_id)
22
snprintf(id, sizeof(id), "%4d ", link->id);
23
24
- fprintf(stdout, "%s%s%s -> %s\n", data->prefix, id,
25
+ printf("%s%s%s -> %s\n", data->prefix, id,
26
port_name(buffer1, sizeof(buffer1), n1, p1),
27
port_name(buffer2, sizeof(buffer2), n2, p2));
28
return 0;
29
30
pw_main_loop_quit(data->loop);
31
}
32
33
-static void show_help(struct data *data, const char *name)
34
+static void show_help(struct data *data, const char *name, bool error)
35
{
36
- fprintf(stdout, "%1$s : PipeWire port and link manager.\n"
37
+ fprintf(error ? stderr : stdout, "%1$s : PipeWire port and link manager.\n"
38
"Generic: %1$s [options]\n"
39
" -h, --help Show this help\n"
40
" --version Show version\n"
41
42
" -o, --output List output ports\n"
43
" -i, --input List input ports\n"
44
" -l, --links List links\n"
45
- " -m, --monitor Monitor links\n"
46
+ " -m, --monitor Monitor links and ports\n"
47
" -I, --id List IDs\n"
48
" -v, --verbose Verbose port properties\n"
49
"Connect: %1$s [options] output input\n"
50
- " -L, --linger Linger (for use with -m)\n"
51
+ " -L, --linger Linger (default, unless -m is used)\n"
52
" -P, --passive Passive link\n"
53
" -p, --props=PROPS Properties as JSON object\n"
54
"Disconnect: %1$s -d [options] output input\n"
55
56
pw_init(&argc, &argv);
57
spa_list_init(&data.objects);
58
59
+ setlinebuf(stdout);
60
+
61
data.props = pw_properties_new(NULL, NULL);
62
if (data.props == NULL) {
63
fprintf(stderr, "can't create properties: %m\n");
64
65
while ((c = getopt_long(argc, argv, "hVr:oilmIvLPp:d", long_options, NULL)) != -1) {
66
switch (c) {
67
case 'h':
68
- show_help(&data, argv[0]);
69
+ show_help(&data, argv[0], NULL);
70
return 0;
71
case 'V':
72
- fprintf(stdout, "%s\n"
73
+ printf("%s\n"
74
"Compiled with libpipewire %s\n"
75
"Linked with libpipewire %s\n",
76
argv[0],
77
78
data.opt_mode |= MODE_DISCONNECT;
79
break;
80
default:
81
- show_help(&data, argv[0]);
82
+ show_help(&data, argv[0], true);
83
return -1;
84
}
85
}
86
if (argc == 1)
87
- show_help(&data, argv[0]);
88
+ show_help(&data, argv[0], true);
89
+
90
+ if (data.opt_id && (data.opt_mode & MODE_LIST) == 0) {
91
+ fprintf(stderr, "-I option needs one or more of -l, -i or -o\n");
92
+ return -1;
93
+ }
94
95
if ((data.opt_mode & MODE_MONITOR) == 0)
96
pw_properties_set(data.props, PW_KEY_OBJECT_LINGER, "true");
97
98
do_list(&data);
99
} else if (data.opt_mode & MODE_DISCONNECT) {
100
if (data.opt_output == NULL) {
101
- fprintf(stderr, "missing link-id or output and input port names\n");
102
+ fprintf(stderr, "missing link-id or output and input port names to disconnect\n");
103
return -1;
104
}
105
if ((res = do_unlink_ports(&data)) < 0) {
106
107
} else {
108
if (data.opt_output == NULL ||
109
data.opt_input == NULL) {
110
- fprintf(stderr, "missing output and input port names\n");
111
+ fprintf(stderr, "missing output and input port names to connect\n");
112
return -1;
113
}
114
if ((res = do_link_ports(&data)) < 0) {
115
116
regfree(data.out_regex);
117
if (data.in_regex)
118
regfree(data.in_regex);
119
+ spa_hook_remove(&data.registry_listener);
120
pw_proxy_destroy((struct pw_proxy*)data.registry);
121
+ spa_hook_remove(&data.core_listener);
122
pw_core_disconnect(data.core);
123
pw_context_destroy(data.context);
124
pw_main_loop_destroy(data.loop);
125
pipewire-0.3.45.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.47.tar.gz/src/tools/pw-loopback.c
Changed
35
1
2
};
3
4
5
-static void show_help(struct data *data, const char *name)
6
+static void show_help(struct data *data, const char *name, bool error)
7
{
8
- fprintf(stdout, "%s [options]\n"
9
+ fprintf(error ? stderr : stdout, "%s [options]\n"
10
" -h, --help Show this help\n"
11
" --version Show version\n"
12
" -r, --remote Remote daemon name\n"
13
14
while ((c = getopt_long(argc, argv, "hVr:g:c:m:l:C:P:i:o:", long_options, NULL)) != -1) {
15
switch (c) {
16
case 'h':
17
- show_help(&data, argv[0]);
18
+ show_help(&data, argv[0], false);
19
return 0;
20
case 'V':
21
- fprintf(stdout, "%s\n"
22
+ printf("%s\n"
23
"Compiled with libpipewire %s\n"
24
"Linked with libpipewire %s\n",
25
argv[0],
26
27
pw_properties_update_string(data.playback_props, optarg, strlen(optarg));
28
break;
29
default:
30
- show_help(&data, argv[0]);
31
+ show_help(&data, argv[0], true);
32
return -1;
33
}
34
}
35
pipewire-0.3.45.tar.gz/src/tools/pw-metadata.c -> pipewire-0.3.47.tar.gz/src/tools/pw-metadata.c
Changed
98
1
2
if ((d->opt_id == SPA_ID_INVALID || d->opt_id == id) &&
3
(d->opt_key == NULL || spa_streq(d->opt_key, key))) {
4
if (key == NULL) {
5
- fprintf(stdout, "remove: id:%u all keys\n", id);
6
+ printf("remove: id:%u all keys\n", id);
7
} else if (value == NULL) {
8
- fprintf(stdout, "remove: id:%u key:'%s'\n", id, key);
9
+ printf("remove: id:%u key:'%s'\n", id, key);
10
} else {
11
- fprintf(stdout, "update: id:%u key:'%s' value:'%s' type:'%s'\n", id, key, value, type);
12
+ printf("update: id:%u key:'%s' value:'%s' type:'%s'\n", id, key, value, type);
13
}
14
}
15
16
17
return;
18
}
19
20
- fprintf(stdout, "Found \"%s\" metadata %d\n", d->opt_name, id);
21
+ printf("Found \"%s\" metadata %d\n", d->opt_name, id);
22
d->metadata = pw_registry_bind(d->registry,
23
id, type, PW_VERSION_METADATA, 0);
24
25
if (d->opt_delete) {
26
if (d->opt_id != SPA_ID_INVALID) {
27
if (d->opt_key != NULL)
28
- fprintf(stdout, "delete property: id:%u key:%s\n", d->opt_id, d->opt_key);
29
+ printf("delete property: id:%u key:%s\n", d->opt_id, d->opt_key);
30
else
31
- fprintf(stdout, "delete properties: id:%u\n", d->opt_id);
32
+ printf("delete properties: id:%u\n", d->opt_id);
33
pw_metadata_set_property(d->metadata, d->opt_id, d->opt_key, NULL, NULL);
34
} else {
35
- fprintf(stdout, "delete all properties\n");
36
+ printf("delete all properties\n");
37
pw_metadata_clear(d->metadata);
38
}
39
} else if (d->opt_id != SPA_ID_INVALID && d->opt_key != NULL && d->opt_value != NULL) {
40
- fprintf(stdout, "set property: id:%u key:%s value:%s type:%s\n",
41
+ printf("set property: id:%u key:%s value:%s type:%s\n",
42
d->opt_id, d->opt_key, d->opt_value, d->opt_type);
43
pw_metadata_set_property(d->metadata, d->opt_id, d->opt_key, d->opt_type, d->opt_value);
44
} else {
45
46
pw_main_loop_quit(data->loop);
47
}
48
49
-static void show_help(struct data *data, const char *name)
50
+static void show_help(struct data *data, const char *name, bool error)
51
{
52
- fprintf(stdout, "%s [options] [ id [ key [ value [ type ] ] ] ]\n"
53
+ fprintf(error ? stderr : stdout, "%s [options] [ id [ key [ value [ type ] ] ] ]\n"
54
" -h, --help Show this help\n"
55
" --version Show version\n"
56
" -r, --remote Remote daemon name\n"
57
58
{ NULL, 0, NULL, 0}
59
};
60
61
+ setlinebuf(stdout);
62
+
63
pw_init(&argc, &argv);
64
65
data.opt_name = "default";
66
67
while ((c = getopt_long(argc, argv, "hVr:mdn:", long_options, NULL)) != -1) {
68
switch (c) {
69
case 'h':
70
- show_help(&data, argv[0]);
71
+ show_help(&data, argv[0], false);
72
return 0;
73
case 'V':
74
- fprintf(stdout, "%s\n"
75
+ printf("%s\n"
76
"Compiled with libpipewire %s\n"
77
"Linked with libpipewire %s\n",
78
argv[0],
79
80
data.opt_name = optarg;
81
break;
82
default:
83
- show_help(&data, argv[0]);
84
+ show_help(&data, argv[0], true);
85
return -1;
86
}
87
}
88
89
90
if (data.metadata)
91
pw_proxy_destroy((struct pw_proxy*)data.metadata);
92
+ spa_hook_remove(&data.registry_listener);
93
pw_proxy_destroy((struct pw_proxy*)data.registry);
94
+ spa_hook_remove(&data.core_listener);
95
pw_core_disconnect(data.core);
96
pw_context_destroy(data.context);
97
pw_main_loop_destroy(data.loop);
98
pipewire-0.3.45.tar.gz/src/tools/pw-mididump.c -> pipewire-0.3.47.tar.gz/src/tools/pw-mididump.c
Changed
49
1
2
ev.data = SPA_POD_BODY(&c->value),
3
ev.size = SPA_POD_BODY_SIZE(&c->value);
4
5
- fprintf(stdout, "%4d: ", c->offset);
6
+ printf("%4d: ", c->offset);
7
midi_file_dump_event(stdout, &ev);
8
}
9
10
11
return 0;
12
}
13
14
-static void show_help(const char *name)
15
+static void show_help(const char *name, bool error)
16
{
17
- fprintf(stdout, "%s [options] [FILE]\n"
18
+ fprintf(error ? stderr : stdout, "%s [options] [FILE]\n"
19
" -h, --help Show this help\n"
20
" --version Show version\n"
21
" -r, --remote Remote daemon name\n",
22
23
24
pw_init(&argc, &argv);
25
26
+ setlinebuf(stdout);
27
+
28
while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) {
29
switch (c) {
30
case 'h':
31
- show_help(argv[0]);
32
+ show_help(argv[0], false);
33
return 0;
34
case 'V':
35
- fprintf(stdout, "%s\n"
36
+ printf("%s\n"
37
"Compiled with libpipewire %s\n"
38
"Linked with libpipewire %s\n",
39
argv[0],
40
41
data.opt_remote = optarg;
42
break;
43
default:
44
- show_help(argv[0]);
45
+ show_help(argv[0], true);
46
return -1;
47
}
48
}
49
pipewire-0.3.45.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.47.tar.gz/src/tools/pw-mon.c
Changed
201
1
2
{ .prefix = "*", .suffix = "" },
3
};
4
5
-#define with_prefix(use_prefix_, stream_) \
6
- for (bool once_ = !!fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).prefix); \
7
+#define with_prefix(use_prefix_) \
8
+ for (bool once_ = !!printf("%s", (pprefix[!!(use_prefix_)]).prefix); \
9
once_; \
10
- once_ = false, fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).suffix))
11
+ once_ = false, printf("%s", (pprefix[!!(use_prefix_)]).suffix))
12
13
14
struct param {
15
16
{
17
struct param *p;
18
19
- with_prefix(use_prefix, stderr) {
20
- fprintf(stderr, "\tparams:\n");
21
+ with_prefix(use_prefix) {
22
+ printf("\tparams:\n");
23
}
24
25
spa_list_for_each(p, &data->param_list, link) {
26
- with_prefix(p->changed, stderr) {
27
- fprintf(stderr, "\t id:%u (%s)\n",
28
+ with_prefix(p->changed) {
29
+ printf("\t id:%u (%s)\n",
30
p->id,
31
spa_debug_type_find_name(spa_type_param, p->id));
32
if (spa_pod_is_object_type(p->param, SPA_TYPE_OBJECT_Format))
33
34
{
35
const struct spa_dict_item *item;
36
37
- with_prefix(use_prefix, stderr) {
38
- fprintf(stderr, "\tproperties:\n");
39
+ with_prefix(use_prefix) {
40
+ printf("\tproperties:\n");
41
if (props == NULL || props->n_items == 0) {
42
- fprintf(stderr, "\t\tnone\n");
43
+ printf("\t\tnone\n");
44
return;
45
}
46
}
47
48
spa_dict_for_each(item, props) {
49
- with_prefix(use_prefix, stderr) {
50
+ with_prefix(use_prefix) {
51
if (item->value)
52
- fprintf(stderr, "\t\t%s = \"%s\"\n", item->key, item->value);
53
+ printf("\t\t%s = \"%s\"\n", item->key, item->value);
54
else
55
- fprintf(stderr, "\t\t%s = (null)\n", item->key);
56
+ printf("\t\t%s = (null)\n", item->key);
57
}
58
}
59
}
60
61
{
62
bool print_all = true, print_mark = true;
63
64
- fprintf(stderr, "\ttype: %s\n", PW_TYPE_INTERFACE_Core);
65
- fprintf(stderr, "\tcookie: %u\n", info->cookie);
66
- fprintf(stderr, "\tuser-name: \"%s\"\n", info->user_name);
67
- fprintf(stderr, "\thost-name: \"%s\"\n", info->host_name);
68
- fprintf(stderr, "\tversion: \"%s\"\n", info->version);
69
- fprintf(stderr, "\tname: \"%s\"\n", info->name);
70
+ printf("\ttype: %s\n", PW_TYPE_INTERFACE_Core);
71
+ printf("\tcookie: %u\n", info->cookie);
72
+ printf("\tuser-name: \"%s\"\n", info->user_name);
73
+ printf("\thost-name: \"%s\"\n", info->host_name);
74
+ printf("\tversion: \"%s\"\n", info->version);
75
+ printf("\tname: \"%s\"\n", info->name);
76
if (print_all) {
77
print_properties(info->props, MARK_CHANGE(PW_CORE_CHANGE_MASK_PROPS));
78
}
79
80
81
print_all = true;
82
if (data->info == NULL) {
83
- fprintf(stderr, "added:\n");
84
+ printf("added:\n");
85
print_mark = false;
86
}
87
else {
88
- fprintf(stderr, "changed:\n");
89
+ printf("changed:\n");
90
print_mark = true;
91
}
92
93
info = data->info = pw_module_info_update(data->info, info);
94
95
- fprintf(stderr, "\tid: %d\n", data->id);
96
- fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
97
+ printf("\tid: %d\n", data->id);
98
+ printf("\tpermissions: "PW_PERMISSION_FORMAT"\n",
99
PW_PERMISSION_ARGS(data->permissions));
100
- fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version);
101
- fprintf(stderr, "\tname: \"%s\"\n", info->name);
102
- fprintf(stderr, "\tfilename: \"%s\"\n", info->filename);
103
- fprintf(stderr, "\targs: \"%s\"\n", info->args);
104
+ printf("\ttype: %s (version %d)\n", data->type, data->version);
105
+ printf("\tname: \"%s\"\n", info->name);
106
+ printf("\tfilename: \"%s\"\n", info->filename);
107
+ printf("\targs: \"%s\"\n", info->args);
108
if (print_all) {
109
print_properties(info->props, MARK_CHANGE(PW_MODULE_CHANGE_MASK_PROPS));
110
}
111
112
113
print_all = true;
114
if (data->first) {
115
- fprintf(stderr, "added:\n");
116
+ printf("added:\n");
117
print_mark = false;
118
data->first = false;
119
}
120
else {
121
- fprintf(stderr, "changed:\n");
122
+ printf("changed:\n");
123
print_mark = true;
124
}
125
126
- fprintf(stderr, "\tid: %d\n", data->id);
127
- fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
128
+ printf("\tid: %d\n", data->id);
129
+ printf("\tpermissions: "PW_PERMISSION_FORMAT"\n",
130
PW_PERMISSION_ARGS(data->permissions));
131
- fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version);
132
+ printf("\ttype: %s (version %d)\n", data->type, data->version);
133
if (print_all) {
134
print_params(data, MARK_CHANGE(PW_NODE_CHANGE_MASK_PARAMS));
135
- with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), stderr) {
136
- fprintf(stderr, "\tinput ports: %u/%u\n",
137
+ with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS)) {
138
+ printf("\tinput ports: %u/%u\n",
139
info->n_input_ports, info->max_input_ports);
140
}
141
- with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), stderr) {
142
- fprintf(stderr, "\toutput ports: %u/%u\n",
143
+ with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS)) {
144
+ printf("\toutput ports: %u/%u\n",
145
info->n_output_ports, info->max_output_ports);
146
}
147
- with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE), stderr) {
148
- fprintf(stderr, "\tstate: \"%s\"",
149
+ with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE)) {
150
+ printf("\tstate: \"%s\"",
151
pw_node_state_as_string(info->state));
152
}
153
if (info->state == PW_NODE_STATE_ERROR && info->error)
154
- fprintf(stderr, " \"%s\"\n", info->error);
155
+ printf(" \"%s\"\n", info->error);
156
else
157
- fprintf(stderr, "\n");
158
+ printf("\n");
159
print_properties(info->props, MARK_CHANGE(PW_NODE_CHANGE_MASK_PROPS));
160
}
161
}
162
163
164
print_all = true;
165
if (data->first) {
166
- fprintf(stderr, "added:\n");
167
+ printf("added:\n");
168
print_mark = false;
169
data->first = false;
170
}
171
else {
172
- fprintf(stderr, "changed:\n");
173
+ printf("changed:\n");
174
print_mark = true;
175
}
176
177
- fprintf(stderr, "\tid: %d\n", data->id);
178
- fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n",
179
+ printf("\tid: %d\n", data->id);
180
+ printf("\tpermissions: "PW_PERMISSION_FORMAT"\n",
181
PW_PERMISSION_ARGS(data->permissions));
182
- fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version);
183
+ printf("\ttype: %s (version %d)\n", data->type, data->version);
184
185
- fprintf(stderr, "\tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
186
+ printf("\tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
187
if (print_all) {
188
print_params(data, MARK_CHANGE(PW_PORT_CHANGE_MASK_PARAMS));
189
print_properties(info->props, MARK_CHANGE(PW_PORT_CHANGE_MASK_PROPS));
190
191
192
print_all = true;
193
if (data->info == NULL) {
194
- fprintf(stderr, "added:\n");
195
+ printf("added:\n");
196
print_mark = false;
197
}
198
else {
199
- fprintf(stderr, "changed:\n");
200
+ printf("changed:\n");
201
pipewire-0.3.45.tar.gz/src/tools/pw-profiler.c -> pipewire-0.3.47.tar.gz/src/tools/pw-profiler.c
Changed
113
1
2
3
if (d->driver_id == 0) {
4
d->driver_id = driver_id;
5
- fprintf(stderr, "logging driver %u\n", driver_id);
6
+ printf("logging driver %u\n", driver_id);
7
}
8
else if (d->driver_id != driver_id)
9
return -1;
10
11
strncpy(d->followers[idx].name, name, MAX_NAME);
12
d->followers[idx].name[MAX_NAME-1] = '\0';
13
d->followers[idx].id = id;
14
- fprintf(stderr, "logging follower %u (\"%s\")\n", id, name);
15
+ printf("logging follower %u (\"%s\")\n", id, name);
16
17
return idx;
18
}
19
20
d->last_status = point->clock.nsec;
21
}
22
else if (point->clock.nsec - d->last_status > SPA_NSEC_PER_SEC) {
23
- fprintf(stderr, "logging %"PRIi64" samples %"PRIi64" seconds [CPU %f %f %f]\r",
24
+ printf("logging %"PRIi64" samples %"PRIi64" seconds [CPU %f %f %f]\r",
25
d->count, (int64_t) ((d->last_status - d->start_status) / SPA_NSEC_PER_SEC),
26
point->cpu_load[0], point->cpu_load[1], point->cpu_load[2]);
27
d->last_status = point->clock.nsec;
28
29
if (d->driver_id == 0)
30
return;
31
32
- fprintf(stderr, "\ndumping scripts for %d followers\n", d->n_followers);
33
+ printf("\ndumping scripts for %d followers\n", d->n_followers);
34
35
out = fopen("Timing1.plot", "w");
36
if (out == NULL) {
37
38
"gnuplot Timing5.plot\n");
39
fclose(out);
40
}
41
- fprintf(stderr, "run 'sh generate_timings.sh' and load Timings.html in a browser\n");
42
+ printf("run 'sh generate_timings.sh' and load Timings.html in a browser\n");
43
}
44
45
static void profiler_profile(void *data, const struct spa_pod *pod)
46
47
if (proxy == NULL)
48
goto error_proxy;
49
50
- fprintf(stderr, "Attaching to Profiler id:%d\n", id);
51
+ printf("Attaching to Profiler id:%d\n", id);
52
d->profiler = proxy;
53
pw_proxy_add_object_listener(proxy, &d->profiler_listener, &profiler_events, d);
54
55
56
pw_main_loop_quit(d->loop);
57
}
58
59
-static void show_help(const char *name)
60
+static void show_help(const char *name, bool error)
61
{
62
- fprintf(stdout, "%s [options]\n"
63
+ fprintf(error ? stderr : stdout, "%s [options]\n"
64
" -h, --help Show this help\n"
65
" --version Show version\n"
66
" -r, --remote Remote daemon name\n"
67
68
while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) {
69
switch (c) {
70
case 'h':
71
- show_help(argv[0]);
72
+ show_help(argv[0], false);
73
return 0;
74
case 'V':
75
- fprintf(stdout, "%s\n"
76
+ printf("%s\n"
77
"Compiled with libpipewire %s\n"
78
"Linked with libpipewire %s\n",
79
argv[0],
80
81
opt_remote = optarg;
82
break;
83
default:
84
- show_help(argv[0]);
85
+ show_help(argv[0], true);
86
return -1;
87
}
88
}
89
90
return -1;
91
}
92
93
- fprintf(stderr, "Logging to %s\n", data.filename);
94
+ printf("Logging to %s\n", data.filename);
95
96
pw_core_add_listener(data.core,
97
&data.core_listener,
98
99
100
pw_main_loop_run(data.loop);
101
102
- pw_proxy_destroy((struct pw_proxy*)data.profiler);
103
+ if (data.profiler) {
104
+ spa_hook_remove(&data.profiler_listener);
105
+ pw_proxy_destroy((struct pw_proxy*)data.profiler);
106
+ }
107
+ spa_hook_remove(&data.registry_listener);
108
pw_proxy_destroy((struct pw_proxy*)data.registry);
109
+ spa_hook_remove(&data.core_listener);
110
pw_context_destroy(data.context);
111
pw_main_loop_destroy(data.loop);
112
113
pipewire-0.3.45.tar.gz/src/tools/pw-reserve.c -> pipewire-0.3.47.tar.gz/src/tools/pw-reserve.c
Changed
71
1
2
3
static void reserve_acquired(void *data, struct rd_device *d)
4
{
5
- fprintf(stdout, "reserve acquired\n");
6
+ printf("reserve acquired\n");
7
}
8
9
static void reserve_release(void *data, struct rd_device *d, int forced)
10
{
11
struct impl *impl = data;
12
- fprintf(stdout, "reserve release\n");
13
+ printf("reserve release\n");
14
rd_device_complete_release(impl->device, true);
15
}
16
17
static void reserve_busy(void *data, struct rd_device *d, const char *name, int32_t prio)
18
{
19
- fprintf(stdout, "reserve busy %s, prio %d\n", name, prio);
20
+ printf("reserve busy %s, prio %d\n", name, prio);
21
}
22
23
static void reserve_available(void *data, struct rd_device *d, const char *name)
24
{
25
- fprintf(stdout, "reserve available %s\n", name);
26
+ printf("reserve available %s\n", name);
27
}
28
29
static const struct rd_device_callbacks reserve_callbacks = {
30
31
#define DEFAULT_APPNAME "pw-reserve"
32
#define DEFAULT_PRIORITY 0
33
34
-static void show_help(const char *name)
35
+static void show_help(const char *name, bool error)
36
{
37
- fprintf(stdout, "%s [options]\n"
38
+ fprintf(error ? stderr : stdout, "%s [options]\n"
39
" -h, --help Show this help\n"
40
" --version Show version\n"
41
" -n, --name Name to reserve (Audio0, Midi0, Video0, ..)\n"
42
43
{ NULL, 0, NULL, 0}
44
};
45
46
+ setlinebuf(stdout);
47
+
48
pw_init(&argc, &argv);
49
50
while ((c = getopt_long(argc, argv, "hVn:a:p:m", long_options, NULL)) != -1) {
51
switch (c) {
52
case 'h':
53
- show_help(argv[0]);
54
+ show_help(argv[0], false);
55
return 0;
56
case 'V':
57
- fprintf(stdout, "%s\n"
58
+ printf("%s\n"
59
"Compiled with libpipewire %s\n"
60
"Linked with libpipewire %s\n",
61
argv[0],
62
63
opt_monitor = true;
64
break;
65
default:
66
- fprintf(stderr, "invalid option '%c'\n", c);
67
+ show_help(argv[0], true);
68
return -1;
69
}
70
}
71
pipewire-0.3.45.tar.gz/src/tools/pw-top.c -> pipewire-0.3.47.tar.gz/src/tools/pw-top.c
Changed
59
1
2
}
3
} else if (spa_streq(type, PW_TYPE_INTERFACE_Profiler)) {
4
if (d->profiler != NULL) {
5
- fprintf(stderr, "Ignoring profiler %d: already attached\n", id);
6
+ printf("Ignoring profiler %d: already attached\n", id);
7
return;
8
}
9
10
11
pw_main_loop_quit(d->loop);
12
}
13
14
-static void show_help(const char *name)
15
+static void show_help(const char *name, bool error)
16
{
17
- fprintf(stdout, "%s [options]\n"
18
+ fprintf(error ? stderr : stdout, "%s [options]\n"
19
" -h, --help Show this help\n"
20
" --version Show version\n"
21
" -r, --remote Remote daemon name\n",
22
23
while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) {
24
switch (c) {
25
case 'h':
26
- show_help(argv[0]);
27
+ show_help(argv[0], false);
28
return 0;
29
case 'V':
30
- fprintf(stdout, "%s\n"
31
+ printf("%s\n"
32
"Compiled with libpipewire %s\n"
33
"Linked with libpipewire %s\n",
34
argv[0],
35
36
opt_remote = optarg;
37
break;
38
default:
39
- show_help(argv[0]);
40
+ show_help(argv[0], true);
41
return -1;
42
}
43
}
44
45
spa_list_consume(n, &data.node_list, link)
46
remove_node(&data, n);
47
48
- pw_proxy_destroy((struct pw_proxy*)data.profiler);
49
+ if (data.profiler) {
50
+ spa_hook_remove(&data.profiler_listener);
51
+ pw_proxy_destroy((struct pw_proxy*)data.profiler);
52
+ }
53
+ spa_hook_remove(&data.registry_listener);
54
pw_proxy_destroy((struct pw_proxy*)data.registry);
55
+ spa_hook_remove(&data.core_listener);
56
pw_context_destroy(data.context);
57
pw_main_loop_destroy(data.loop);
58
59
pipewire-0.3.45.tar.gz/test/meson.build -> pipewire-0.3.47.tar.gz/test/meson.build
Changed
16
1
2
link_with: pwtest_lib)
3
)
4
5
+test('test-loop',
6
+ executable('test-loop',
7
+ 'test-loop.c',
8
+ include_directories: pwtest_inc,
9
+ dependencies: [ spa_dep ],
10
+ link_with: pwtest_lib)
11
+)
12
+
13
test('test-context',
14
executable('test-context',
15
'test-context.c',
16
pipewire-0.3.45.tar.gz/test/pwtest-compat.c -> pipewire-0.3.47.tar.gz/test/pwtest-compat.c
Changed
10
1
2
3
#include "config.h"
4
5
-#if !HAVE_SIGABBREV_NP
6
+#ifndef HAVE_SIGABBREV_NP
7
#include <stddef.h>
8
#include <signal.h>
9
10
pipewire-0.3.45.tar.gz/test/pwtest.c -> pipewire-0.3.47.tar.gz/test/pwtest.c
Changed
74
1
2
#include <stdio.h>
3
#include <unistd.h>
4
#include <signal.h>
5
-#if HAVE_PIDFD_OPEN
6
+#ifdef HAVE_PIDFD_OPEN
7
#include <sys/syscall.h>
8
#endif
9
-#if HAVE_LIBCAP
10
+#ifdef HAVE_LIBCAP
11
#include <sys/capability.h>
12
#endif
13
#include <sys/epoll.h>
14
15
16
static void pwtest_backtrace(pid_t p)
17
{
18
-#if HAVE_GSTACK
19
+#ifdef HAVE_GSTACK
20
char pid[11];
21
pid_t parent, child;
22
int status;
23
24
struct spa_handle **hnd;
25
26
SPA_FOR_EACH_ELEMENT(plugin->handles, hnd) {
27
- if (*hnd)
28
+ if (*hnd) {
29
+ spa_handle_clear(*hnd);
30
free(*hnd);
31
+ }
32
}
33
SPA_FOR_EACH_ELEMENT(plugin->dlls, dll) {
34
if (*dll)
35
- dlclose(dll);
36
+ dlclose(*dll);
37
}
38
free(plugin);
39
}
40
41
r = spa_handle_factory_init(factory, handle, info, plugin->support, plugin->nsupport);
42
pwtest_neg_errno_ok(r);
43
if ((r = spa_handle_get_interface(handle, interface_name, &iface)) != 0) {
44
- dlclose(hnd);
45
+ spa_handle_clear(handle);
46
free(handle);
47
+ dlclose(hnd);
48
return -ENOSYS;
49
}
50
51
- plugin->handles[plugin->ndlls++] = hnd;
52
+ plugin->dlls[plugin->ndlls++] = hnd;
53
plugin->handles[plugin->nhandles++] = handle;
54
plugin->support[plugin->nsupport++] = SPA_SUPPORT_INIT(interface_name, iface);
55
56
57
size_t nevents = 0;
58
int r;
59
60
-#if HAVE_PIDFD_OPEN
61
+#ifdef HAVE_PIDFD_OPEN
62
pidfd = syscall(SYS_pidfd_open, pid, 0);
63
#else
64
errno = ENOSYS;
65
66
static bool is_debugger_attached(void)
67
{
68
bool rc = false;
69
-#if HAVE_LIBCAP
70
+#ifdef HAVE_LIBCAP
71
int status;
72
int pid = fork();
73
74
pipewire-0.3.45.tar.gz/test/test-context.c -> pipewire-0.3.47.tar.gz/test/test-context.c
Changed
10
1
2
SPA_TYPE_INTERFACE_Loop,
3
SPA_TYPE_INTERFACE_LoopUtils,
4
SPA_TYPE_INTERFACE_Log,
5
-#if HAVE_DBUS
6
+#ifdef HAVE_DBUS
7
SPA_TYPE_INTERFACE_DBus,
8
#endif
9
SPA_TYPE_INTERFACE_CPU
10
pipewire-0.3.45.tar.gz/test/test-lib.c -> pipewire-0.3.47.tar.gz/test/test-lib.c
Changed
10
1
2
pwtest_str_eq(headerversion, version_expected);
3
pwtest_str_eq(libversion, version_expected);
4
5
+ pw_deinit();
6
+
7
return PWTEST_PASS;
8
}
9
10
pipewire-0.3.47.tar.gz/test/test-loop.c
Added
201
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <stdio.h>
27
+#include <stdint.h>
28
+#include <stdlib.h>
29
+#include <unistd.h>
30
+#include <sys/eventfd.h>
31
+
32
+#include "pwtest.h"
33
+
34
+#include <pipewire/pipewire.h>
35
+
36
+struct obj {
37
+ int x;
38
+ struct spa_source source;
39
+};
40
+
41
+struct data {
42
+ struct pw_main_loop *ml;
43
+ struct pw_loop *l;
44
+ struct obj *a, *b;
45
+ int count;
46
+};
47
+
48
+static void on_event(struct spa_source *source)
49
+{
50
+ struct data *d = source->data;
51
+
52
+ pw_loop_remove_source(d->l, &d->a->source);
53
+ pw_loop_remove_source(d->l, &d->b->source);
54
+ close(d->a->source.fd);
55
+ close(d->b->source.fd);
56
+ free(d->a);
57
+ free(d->b);
58
+
59
+ pw_main_loop_quit(d->ml);
60
+}
61
+
62
+PWTEST(pwtest_loop_destroy2)
63
+{
64
+ struct data data;
65
+
66
+ pw_init(0, NULL);
67
+
68
+ spa_zero(data);
69
+ data.ml = pw_main_loop_new(NULL);
70
+ pwtest_ptr_notnull(data.ml);
71
+
72
+ data.l = pw_main_loop_get_loop(data.ml);
73
+ pwtest_ptr_notnull(data.l);
74
+
75
+ data.a = calloc(1, sizeof(*data.a));
76
+ data.b = calloc(1, sizeof(*data.b));
77
+
78
+ data.a->source.func = on_event;
79
+ data.a->source.fd = eventfd(0, 0);
80
+ data.a->source.mask = SPA_IO_IN;
81
+ data.a->source.data = &data;
82
+ data.b->source.func = on_event;
83
+ data.b->source.fd = eventfd(0, 0);
84
+ data.b->source.mask = SPA_IO_IN;
85
+ data.b->source.data = &data;
86
+
87
+ pw_loop_add_source(data.l, &data.a->source);
88
+ pw_loop_add_source(data.l, &data.b->source);
89
+
90
+ write(data.a->source.fd, &(uint64_t){1}, sizeof(uint64_t));
91
+ write(data.b->source.fd, &(uint64_t){1}, sizeof(uint64_t));
92
+
93
+ pw_main_loop_run(data.ml);
94
+ pw_main_loop_destroy(data.ml);
95
+
96
+ pw_deinit();
97
+
98
+ return PWTEST_PASS;
99
+}
100
+
101
+static void
102
+on_event_recurse1(struct spa_source *source)
103
+{
104
+ static bool first = true;
105
+ struct data *d = source->data;
106
+ uint64_t val;
107
+
108
+ ++d->count;
109
+ pwtest_int_lt(d->count, 3);
110
+
111
+ read(source->fd, &val, sizeof(val));
112
+
113
+ if (first) {
114
+ first = false;
115
+ pw_loop_enter(d->l);
116
+ pw_loop_iterate(d->l, -1);
117
+ pw_loop_leave(d->l);
118
+ }
119
+ pw_main_loop_quit(d->ml);
120
+}
121
+
122
+PWTEST(pwtest_loop_recurse1)
123
+{
124
+ struct data data;
125
+
126
+ pw_init(0, NULL);
127
+
128
+ spa_zero(data);
129
+ data.ml = pw_main_loop_new(NULL);
130
+ pwtest_ptr_notnull(data.ml);
131
+
132
+ data.l = pw_main_loop_get_loop(data.ml);
133
+ pwtest_ptr_notnull(data.l);
134
+
135
+ data.a = calloc(1, sizeof(*data.a));
136
+ data.b = calloc(1, sizeof(*data.b));
137
+
138
+ data.a->source.func = on_event_recurse1;
139
+ data.a->source.fd = eventfd(0, 0);
140
+ data.a->source.mask = SPA_IO_IN;
141
+ data.a->source.data = &data;
142
+ data.b->source.func = on_event_recurse1;
143
+ data.b->source.fd = eventfd(0, 0);
144
+ data.b->source.mask = SPA_IO_IN;
145
+ data.b->source.data = &data;
146
+
147
+ pw_loop_add_source(data.l, &data.a->source);
148
+ pw_loop_add_source(data.l, &data.b->source);
149
+
150
+ write(data.a->source.fd, &(uint64_t){1}, sizeof(uint64_t));
151
+ write(data.b->source.fd, &(uint64_t){1}, sizeof(uint64_t));
152
+
153
+ pw_main_loop_run(data.ml);
154
+ pw_main_loop_destroy(data.ml);
155
+
156
+ pw_deinit();
157
+
158
+ free(data.a);
159
+ free(data.b);
160
+
161
+ return PWTEST_PASS;
162
+}
163
+
164
+static void
165
+on_event_recurse2(struct spa_source *source)
166
+{
167
+ static bool first = true;
168
+ struct data *d = source->data;
169
+ uint64_t val;
170
+
171
+ ++d->count;
172
+ pwtest_int_lt(d->count, 3);
173
+
174
+ read(source->fd, &val, sizeof(val));
175
+
176
+ if (first) {
177
+ first = false;
178
+ pw_loop_enter(d->l);
179
+ pw_loop_iterate(d->l, -1);
180
+ pw_loop_leave(d->l);
181
+ } else {
182
+ pw_loop_remove_source(d->l, &d->a->source);
183
+ pw_loop_remove_source(d->l, &d->b->source);
184
+ close(d->a->source.fd);
185
+ close(d->b->source.fd);
186
+ free(d->a);
187
+ free(d->b);
188
+ }
189
+ pw_main_loop_quit(d->ml);
190
+}
191
+
192
+PWTEST(pwtest_loop_recurse2)
193
+{
194
+ struct data data;
195
+
196
+ pw_init(0, NULL);
197
+
198
+ spa_zero(data);
199
+ data.ml = pw_main_loop_new(NULL);
200
+ pwtest_ptr_notnull(data.ml);
201
pipewire-0.3.45.tar.gz/test/test-pwtest.c -> pipewire-0.3.47.tar.gz/test/test-pwtest.c
Changed
10
1
2
3
PWTEST(compat_sigabbrev_np)
4
{
5
-#if !HAVE_SIGABBREV_NP
6
+#ifndef HAVE_SIGABBREV_NP
7
pwtest_str_eq(sigabbrev_np(SIGABRT), "ABRT");
8
pwtest_str_eq(sigabbrev_np(SIGSEGV), "SEGV");
9
pwtest_str_eq(sigabbrev_np(SIGSTOP), "STOP");
10