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 20
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Tue Dec 20 18:46:39 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.63
6
+
7
+-------------------------------------------------------------------
8
Fri Dec 16 18:14:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
10
- Update to version 0.3.62
11
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.62
6
+Version: 0.3.63
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.62.tar.gz/Makefile.in -> pipewire-0.3.63.tar.gz/Makefile.in
Changed
10
1
2
$(MAKE) run DBG=gdb
3
4
valgrind:
5
- $(MAKE) run DBG="DISABLE_RTKIT=1 valgrind --trace-children=yes"
6
+ $(MAKE) run DBG="DISABLE_RTKIT=1 PIPEWIRE_DLCLOSE=false valgrind --trace-children=yes"
7
8
test: all
9
ninja -C $(BUILD_ROOT) test
10
pipewire-0.3.62.tar.gz/NEWS -> pipewire-0.3.63.tar.gz/NEWS
Changed
59
1
2
+# PipeWire 0.3.63 (2022-12-15)
3
+
4
+This is a quick bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+ - Fix a critical bug that causes audio distortion in some cases when using
9
+ AVX2.
10
+ - Fix a crash in mpv caused by deinit of PipeWire.
11
+ - Resample the convolver IR to match the graph samplerate for better
12
+ results.
13
+ - Many more small bugfixes and improvements.
14
+
15
+
16
+## PipeWire
17
+ - Fix a segfault in the PipeWire deinit code triggered by mpv in some
18
+ cases. (#2881)
19
+ - Fix docs about SPA_PLUGIN_DIR.
20
+ - Always dlclose by default (even under valgrind). Add an option with
21
+ PIPEWIRE_DLCLOSE to select alternative behaviour.
22
+ - Improve PIPEWIRE_DEBUG category handling.
23
+
24
+## modules
25
+ - Resample the IR for the convolver when the IR samplerate and graph rate
26
+ don't match.
27
+
28
+## SPA
29
+ - Handle spurious reads from timerfd gracefully.
30
+ - Fix potential stack-use-after-scope when starting Audacity.
31
+ - Fix distorted audio when using AVX2. (#2885)
32
+ - Remove fallback to default channel map in channelmix.
33
+ - Improve sorting of MIDI events, use the same order as Ardour. (#1816)
34
+ - Enable LFE downmixing by default. (#2425)
35
+ - Make IEC958/AC3 and IEC958/DTS work better by enforcing a fixed minimal
36
+ buffering for the encoder to avoid stuttering. (#2650)
37
+
38
+## Pulse-Server
39
+ - Add a new pulse.cmd config section to execute pulse commands, currently
40
+ only for loading modules. This removes the dependency on pactl.
41
+ - Improve debug of messages.
42
+
43
+
44
+Older versions:
45
+
46
# PipeWire 0.3.62 (2022-12-09)
47
48
This is a bugfix release that is API and ABI compatible with previous
49
50
- Support was added for offloading bluetooth handling. Some hardware can
51
receive, decode and play the bluetooth audio directly in hardware.
52
53
-
54
-Older versions:
55
-
56
# PipeWire 0.3.61 (2022-11-24)
57
58
This is a bugfix release that is API and ABI compatible with previous
59
pipewire-0.3.62.tar.gz/doc/spa-plugins.dox -> pipewire-0.3.63.tar.gz/doc/spa-plugins.dox
Changed
36
1
2
In pseudo-code, loading a logger interface looks like this:
3
4
\code{.py}
5
-handle = dlopen("$SPA_PLUGIN_PATH/support/libspa-support.so")
6
+handle = dlopen("$SPA_PLUGIN_DIR/support/libspa-support.so")
7
factory_enumeration_func = dlsym(handle, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)
8
spa_log *logger = NULL
9
10
11
The `spa-inspect` tool provides a CLI interface to inspect SPA plugins:
12
13
\verbatim
14
-$ export SPA_PLUGIN_PATH=$(pkg-config --variable plugindir libspa-0.2)
15
-$ spa-inspect ${SPA_PLUGIN_PATH}/support/libspa-support.so
16
+$ export SPA_PLUGIN_DIR=$(pkg-config --variable plugindir libspa-0.2)
17
+$ spa-inspect ${SPA_PLUGIN_DIR}/support/libspa-support.so
18
...
19
factory version: 1
20
factory name: 'support.cpu'
21
22
To `dlopen` a plugin we then need to prefix the plugin path like this:
23
24
\code{.c}
25
-#define SPA_PLUGIN_PATH /usr/lib64/spa-0.2/"
26
-void *hnd = dlopen(SPA_PLUGIN_PATH"/support/libspa-support.so", RTLD_NOW);
27
+#define SPA_PLUGIN_DIR /usr/lib64/spa-0.2/"
28
+void *hnd = dlopen(SPA_PLUGIN_DIR"/support/libspa-support.so", RTLD_NOW);
29
\endcode
30
31
-The environment variable `SPA_PLUGIN_PATH` and `pkg-config` variable
32
+The environment variable `SPA_PLUGIN_DIR` and `pkg-config` variable
33
`plugindir` are usually used to find the location of the plugins. You will
34
have to do some more work to construct the shared object path.
35
36
pipewire-0.3.62.tar.gz/meson.build -> pipewire-0.3.63.tar.gz/meson.build
Changed
8
1
2
project('pipewire', 'c' ,
3
- version : '0.3.62',
4
+ version : '0.3.63',
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
pipewire-0.3.62.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.63.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
81
1
2
}
3
}
4
5
+static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
6
+{
7
+ if (a->offset < b->offset)
8
+ return -1;
9
+ if (a->offset > b->offset)
10
+ return 1;
11
+ if (a->type != b->type)
12
+ return 0;
13
+ switch(a->type) {
14
+ case SPA_CONTROL_Midi:
15
+ {
16
+ /* 11 (controller) > 12 (program change) >
17
+ * 8 (note off) > 9 (note on) > 10 (aftertouch) >
18
+ * 13 (channel pressure) > 14 (pitch bend) */
19
+ static int priotab = { 5,4,3,7,6,2,1,0 };
20
+ uint8_t *da, *db;
21
+
22
+ if (SPA_POD_BODY_SIZE(&a->value) < 1 ||
23
+ SPA_POD_BODY_SIZE(&b->value) < 1)
24
+ return 0;
25
+
26
+ da = SPA_POD_BODY(&a->value);
27
+ db = SPA_POD_BODY(&b->value);
28
+ if ((da0 & 0xf) != (db0 & 0xf))
29
+ return 0;
30
+ return priotab(db0>>4) & 7 - priotab(da0>>4) & 7;
31
+ }
32
+ default:
33
+ return 0;
34
+ }
35
+}
36
+
37
static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix)
38
{
39
struct spa_pod_control *cn_seq;
40
41
while (true) {
42
struct spa_pod_control *next = NULL;
43
uint32_t next_index = 0;
44
- uint8_t *data;
45
- size_t size;
46
47
for (i = 0; i < n_seq; i++) {
48
if (!spa_pod_control_is_inside(&seqi->body,
49
SPA_POD_BODY_SIZE(seqi), ci))
50
continue;
51
52
- if (next == NULL || ci->offset < next->offset) {
53
+ if (next == NULL || event_sort(ci, next) <= 0) {
54
next = ci;
55
next_index = i;
56
}
57
58
if (SPA_UNLIKELY(next == NULL))
59
break;
60
61
- data = SPA_POD_BODY(&next->value);
62
- size = SPA_POD_BODY_SIZE(&next->value);
63
-
64
switch(next->type) {
65
case SPA_CONTROL_Midi:
66
+ {
67
+ uint8_t *data = SPA_POD_BODY(&next->value);
68
+ size_t size = SPA_POD_BODY_SIZE(&next->value);
69
+
70
if (fix)
71
fix_midi_event(data, size);
72
73
74
spa_strerror(res));
75
break;
76
}
77
+ }
78
cnext_index = spa_pod_control_next(cnext_index);
79
}
80
}
81
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
63
1
2
if (is_batch)
3
state->headroom += period_size;
4
5
+ if (spa_strstartswith(state->props.device, "a52") ||
6
+ spa_strstartswith(state->props.device, "dca"))
7
+ state->min_delay = SPA_MIN(2048u, state->buffer_frames);
8
+ else
9
+ state->min_delay = 0;
10
+
11
state->headroom = SPA_MIN(state->headroom, state->buffer_frames);
12
state->start_delay = state->default_start_delay;
13
14
- state->latencystate->port_direction.min_rate = state->headroom;
15
- state->latencystate->port_direction.max_rate = state->headroom;
16
+ state->latencystate->port_direction.min_rate =
17
+ state->latencystate->port_direction.max_rate =
18
+ SPA_MAX(state->min_delay, state->headroom);
19
20
spa_log_info(state->log, "%s (%s): format:%s access:%s-%s rate:%d channels:%d "
21
"buffer frames %lu, period frames %lu, periods %u, frame_size %zd "
22
23
*delay = avail;
24
*target = SPA_MAX(*target, state->read_size);
25
}
26
- *target = SPA_MIN(*target, state->buffer_frames);
27
+ *target = SPA_CLAMP(*target, state->min_delay, state->buffer_frames);
28
return 0;
29
}
30
31
32
struct state *state = source->data;
33
snd_pcm_uframes_t delay, target;
34
uint64_t expire, current_time;
35
+ int res;
36
37
- if (SPA_UNLIKELY(state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0))
38
- spa_log_warn(state->log, "%p: error reading timerfd: %m", state);
39
+ if (SPA_LIKELY(state->started)) {
40
+ if (SPA_UNLIKELY((res = spa_system_timerfd_read(state->data_system,
41
+ state->timerfd, &expire)) < 0)) {
42
+ /* we can get here when the timer is changed since the last
43
+ * timerfd wakeup, for example by do_reassign_follower() executed
44
+ * in the same epoll wakeup cycle */
45
+ if (res != -EAGAIN)
46
+ spa_log_warn(state->log, "%p: error reading timerfd: %s",
47
+ state, spa_strerror(res));
48
+ return;
49
+ }
50
+ }
51
52
check_position_config(state);
53
54
55
else
56
snd_pcm_pause(state->hndl, 0);
57
}
58
+
59
+ state->alsa_sync_warning = false;
60
return 0;
61
}
62
63
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
9
1
2
uint32_t last_threshold;
3
uint32_t headroom;
4
uint32_t start_delay;
5
+ uint32_t min_delay;
6
7
uint32_t duration;
8
unsigned int alsa_started:1;
9
pipewire-0.3.62.tar.gz/spa/plugins/alsa/alsa-seq.c -> pipewire-0.3.63.tar.gz/spa/plugins/alsa/alsa-seq.c
Changed
18
1
2
uint64_t expire;
3
int res;
4
5
- if (state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0)
6
- spa_log_warn(state->log, "error reading timerfd: %m");
7
+ if (state->started) {
8
+ if ((res = spa_system_timerfd_read(state->data_system, state->timerfd, &expire)) < 0) {
9
+ if (res != -EAGAIN)
10
+ spa_log_warn(state->log, "%p: error reading timerfd: %s",
11
+ state, spa_strerror(res));
12
+ return;
13
+ }
14
+ }
15
16
state->current_time = state->next_time;
17
18
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
26
1
2
3
static int configure_format(struct impl *this, uint32_t flags, const struct spa_pod *format)
4
{
5
+ uint8_t buffer4096;
6
int res;
7
8
if (format == NULL && !this->have_format)
9
10
SPA_PARAM_Format, flags,
11
format)) < 0)
12
return res;
13
+
14
if (res > 0) {
15
- uint8_t buffer4096;
16
- struct spa_pod_builder b = { 0 };
17
+ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
18
uint32_t state = 0;
19
struct spa_pod *fmt;
20
21
/* format was changed to nearest compatible format */
22
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
23
24
if ((res = spa_node_port_enum_params_sync(this->follower,
25
this->direction, 0,
26
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
68
1
2
return 0;
3
}
4
5
-#define _MASK(ch) (1ULL << SPA_AUDIO_CHANNEL_ ## ch)
6
-#define STEREO (_MASK(FL)|_MASK(FR))
7
-
8
-static uint64_t default_mask(uint32_t channels)
9
-{
10
- uint64_t mask = 0;
11
- switch (channels) {
12
- case 7:
13
- case 8:
14
- mask |= _MASK(RL);
15
- mask |= _MASK(RR);
16
- SPA_FALLTHROUGH
17
- case 5:
18
- case 6:
19
- mask |= _MASK(SL);
20
- mask |= _MASK(SR);
21
- if ((channels & 1) == 0)
22
- mask |= _MASK(LFE);
23
- SPA_FALLTHROUGH
24
- case 3:
25
- mask |= _MASK(FC);
26
- SPA_FALLTHROUGH
27
- case 2:
28
- mask |= _MASK(FL);
29
- mask |= _MASK(FR);
30
- break;
31
- case 1:
32
- mask |= _MASK(MONO);
33
- break;
34
- case 4:
35
- mask |= _MASK(FL);
36
- mask |= _MASK(FR);
37
- mask |= _MASK(RL);
38
- mask |= _MASK(RR);
39
- break;
40
- }
41
- return mask;
42
-}
43
-
44
static void fix_volumes(struct impl *this, struct volumes *vols, uint32_t channels)
45
{
46
float s;
47
48
spa_log_info(this->log, "out %s (%016"PRIx64")", format_position(str, sizeof(str),
49
dst_chan, out->format.info.raw.position), dst_mask);
50
51
- if (src_mask & 1)
52
- src_mask = default_mask(src_chan);
53
- if (dst_mask & 1)
54
- dst_mask = default_mask(dst_chan);
55
-
56
spa_log_info(this->log, "%p: %s/%d@%d->%s/%d@%d %08"PRIx64":%08"PRIx64, this,
57
spa_debug_type_find_name(spa_type_audio_format, SPA_AUDIO_FORMAT_DSP_F32),
58
src_chan,
59
60
61
props_reset(&this->props);
62
63
- this->mix.options = CHANNELMIX_OPTION_UPMIX;
64
+ this->mix.options = CHANNELMIX_OPTION_UPMIX | CHANNELMIX_OPTION_MIX_LFE;
65
this->mix.upmix = CHANNELMIX_UPMIX_PSD;
66
this->mix.log = this->log;
67
this->mix.lfe_cutoff = 150.0f;
68
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
17
1
2
3
if (i == 0)
4
idx2 += snprintf(str2 + idx2, sizeof(str2) - idx2, "%-4.4s ",
5
+ src_mask == ~0LU ? "MONO" :
6
spa_debug_type_find_short_name(spa_type_audio_channel, j + 3));
7
8
mix->matrix_origicjc++ = matrixij;
9
10
if (i == 0)
11
spa_log_info(mix->log, " %s", str2);
12
spa_log_info(mix->log, "%-4.4s %s %f",
13
+ dst_mask == ~0LU ? "MONO" :
14
spa_debug_type_find_short_name(spa_type_audio_channel, i + 3),
15
str, sum);
16
}
17
pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.63.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c
Changed
28
1
2
__m256i in4;
3
__m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
4
__m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
5
- 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
6
+ 4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
7
8
if (SPA_IS_ALIGNED(d0, 32) &&
9
SPA_IS_ALIGNED(d1, 32) &&
10
11
__m256i in4;
12
__m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE);
13
__m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
14
- 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
15
+ 4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
16
17
if (SPA_IS_ALIGNED(d0, 32) &&
18
SPA_IS_ALIGNED(d1, 32))
19
20
__m256i in2;
21
__m256 out2, factor = _mm256_set1_ps(1.0f / S24_SCALE);
22
__m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels,
23
- 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
24
+ 4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels);
25
26
if (SPA_IS_ALIGNED(d0, 32))
27
unrolled = n_samples & ~15;
28
pipewire-0.3.62.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c
Changed
43
1
2
#include <spa/support/loop.h>
3
#include <spa/utils/list.h>
4
#include <spa/utils/keys.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
}
11
}
12
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
{
16
uint64_t expirations;
17
+ int res = 0;
18
19
if (this->async || this->props.live) {
20
- if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
- perror("read timerfd");
22
+ if ((res = spa_system_timerfd_read(this->data_system,
23
+ this->timer_source.fd, &expirations)) < 0) {
24
+ if (res != -EAGAIN)
25
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+ this, spa_strerror(res));
27
+ }
28
}
29
+ return 0;
30
}
31
32
static int make_buffer(struct impl *this)
33
34
uint32_t filled, avail;
35
uint32_t index, offset, l0, l1;
36
37
- read_timer(this);
38
+ if (read_timer(this) < 0)
39
+ return 0;
40
41
if (spa_list_is_empty(&port->empty)) {
42
set_timer(this, false);
43
pipewire-0.3.62.tar.gz/spa/plugins/avb/avb-pcm.c -> pipewire-0.3.63.tar.gz/spa/plugins/avb/avb-pcm.c
Changed
30
1
2
#include <arpa/inet.h>
3
4
#include <spa/pod/filter.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/support/system.h>
8
#include <spa/utils/keys.h>
9
10
struct state *state = source->data;
11
uint64_t expirations, current_time, duration;
12
uint32_t rate;
13
+ int res;
14
15
spa_log_trace(state->log, "timeout");
16
17
- if (spa_system_timerfd_read(state->data_system,
18
- state->timer_source.fd, &expirations) < 0) {
19
- if (errno == EAGAIN)
20
- return;
21
- spa_log_error(state->log, "read timerfd: %m");
22
+ if ((res = spa_system_timerfd_read(state->data_system,
23
+ state->timer_source.fd, &expirations)) < 0) {
24
+ if (res != -EAGAIN)
25
+ spa_log_error(state->log, "read timerfd: %s", spa_strerror(res));
26
+ return;
27
}
28
29
current_time = state->next_time;
30
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/media-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/media-sink.c
Changed
41
1
2
{
3
struct impl *this = source->data;
4
uint64_t exp;
5
+ int res;
6
7
spa_log_trace(this->log, "%p: flush on timeout", this);
8
9
- if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
10
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
11
+ if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
12
+ if (res != -EAGAIN)
13
+ spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
14
+ return;
15
+ }
16
17
if (this->transport == NULL) {
18
enable_flush_timer(this, false);
19
20
uint32_t rate;
21
struct spa_io_buffers *io = port->io;
22
uint64_t prev_time, now_time;
23
+ int res;
24
25
if (this->transport == NULL)
26
return;
27
28
- if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
29
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
30
+ if (this->started) {
31
+ if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
32
+ if (res != -EAGAIN)
33
+ spa_log_warn(this->log, "error reading timerfd: %s",
34
+ spa_strerror(res));
35
+ return;
36
+ }
37
+ }
38
39
prev_time = this->current_time;
40
now_time = this->current_time = this->next_time;
41
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/media-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/media-source.c
Changed
38
1
2
{
3
struct impl *this = source->data;
4
uint64_t exp;
5
+ int res;
6
7
- if (spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp) < 0)
8
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
9
+ if ((res = spa_system_timerfd_read(this->data_system, this->duplex_timerfd, &exp)) < 0) {
10
+ if (res != -EAGAIN)
11
+ spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
12
+ return;
13
+ }
14
15
set_duplex_timeout(this, this->duplex_timeout);
16
17
18
uint64_t exp, duration;
19
uint32_t rate;
20
uint64_t prev_time, now_time;
21
+ int res;
22
23
if (this->transport == NULL)
24
return;
25
26
- if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
27
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
28
+ if (this->started) {
29
+ if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
30
+ if (res != -EAGAIN)
31
+ spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
32
+ return;
33
+ }
34
+ }
35
36
prev_time = this->current_time;
37
now_time = this->current_time = this->next_time;
38
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/sco-sink.c
Changed
45
1
2
enable_flush_timer(this, false);
3
}
4
5
-
6
static void sco_on_flush_timeout(struct spa_source *source)
7
{
8
struct impl *this = source->data;
9
uint64_t exp;
10
+ int res;
11
12
spa_log_trace(this->log, "%p: flush on timeout", this);
13
14
- if (spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp) < 0)
15
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
16
+ if ((res = spa_system_timerfd_read(this->data_system, this->flush_timerfd, &exp)) < 0) {
17
+ if (res != -EAGAIN)
18
+ spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
19
+ return;
20
+ }
21
22
if (this->transport == NULL) {
23
enable_flush_timer(this, false);
24
25
uint32_t rate;
26
struct spa_io_buffers *io = port->io;
27
uint64_t prev_time, now_time;
28
+ int res;
29
30
if (this->transport == NULL)
31
return;
32
33
- if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
34
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
35
+ if (this->started) {
36
+ if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
37
+ if (res != -EAGAIN)
38
+ spa_log_warn(this->log, "error reading timerfd: %s", spa_strerror(res));
39
+ return;
40
+ }
41
+ }
42
43
prev_time = this->current_time;
44
now_time = this->current_time = this->next_time;
45
pipewire-0.3.62.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/bluez5/sco-source.c
Changed
31
1
2
#include <spa/support/loop.h>
3
#include <spa/support/log.h>
4
#include <spa/support/system.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/list.h>
7
#include <spa/utils/keys.h>
8
#include <spa/utils/names.h>
9
10
uint64_t exp, duration;
11
uint32_t rate;
12
uint64_t prev_time, now_time;
13
+ int res;
14
15
if (this->transport == NULL)
16
return;
17
18
- if (this->started && spa_system_timerfd_read(this->data_system, this->timerfd, &exp) < 0)
19
- spa_log_warn(this->log, "error reading timerfd: %s", strerror(errno));
20
+ if (this->started) {
21
+ if ((res = spa_system_timerfd_read(this->data_system, this->timerfd, &exp)) < 0) {
22
+ if (res != -EAGAIN)
23
+ spa_log_warn(this->log, "error reading timerfd: %s",
24
+ spa_strerror(res));
25
+ return;
26
+ }
27
+ }
28
29
prev_time = this->current_time;
30
now_time = this->current_time = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/control/mixer.c -> pipewire-0.3.63.tar.gz/spa/plugins/control/mixer.c
Changed
57
1
2
#include <spa/node/io.h>
3
#include <spa/param/audio/format-utils.h>
4
#include <spa/param/param.h>
5
+#include <spa/control/control.h>
6
#include <spa/pod/filter.h>
7
8
#define NAME "control-mixer"
9
10
return queue_buffer(this, port, &port->buffersbuffer_id);
11
}
12
13
+static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
14
+{
15
+ if (a->offset < b->offset)
16
+ return -1;
17
+ if (a->offset > b->offset)
18
+ return 1;
19
+ if (a->type != b->type)
20
+ return 0;
21
+ switch(a->type) {
22
+ case SPA_CONTROL_Midi:
23
+ {
24
+ /* 11 (controller) > 12 (program change) >
25
+ * 8 (note off) > 9 (note on) > 10 (aftertouch) >
26
+ * 13 (channel pressure) > 14 (pitch bend) */
27
+ static int priotab = { 5,4,3,7,6,2,1,0 };
28
+ uint8_t *da, *db;
29
+
30
+ if (SPA_POD_BODY_SIZE(&a->value) < 1 ||
31
+ SPA_POD_BODY_SIZE(&b->value) < 1)
32
+ return 0;
33
+
34
+ da = SPA_POD_BODY(&a->value);
35
+ db = SPA_POD_BODY(&b->value);
36
+ if ((da0 & 0xf) != (db0 & 0xf))
37
+ return 0;
38
+ return priotab(db0>>4) & 7 - priotab(da0>>4) & 7;
39
+ }
40
+ default:
41
+ return 0;
42
+ }
43
+}
44
+
45
static int impl_node_process(void *object)
46
{
47
struct impl *this = object;
48
49
SPA_POD_BODY_SIZE(seqi), ctrli))
50
continue;
51
52
- if (next == NULL || ctrli->offset < next->offset) {
53
+ if (next == NULL || event_sort(ctrli, next) <= 0) {
54
next = ctrli;
55
next_index = i;
56
}
57
pipewire-0.3.62.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.63.tar.gz/spa/plugins/support/node-driver.c
Changed
31
1
2
#include <spa/support/log.h>
3
#include <spa/support/loop.h>
4
#include <spa/utils/names.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/keys.h>
9
10
struct impl *this = source->data;
11
uint64_t expirations, nsec, duration;
12
uint32_t rate;
13
+ int res;
14
15
spa_log_trace(this->log, "timeout");
16
17
- if (spa_system_timerfd_read(this->data_system,
18
- this->timer_source.fd, &expirations) < 0) {
19
- if (errno == EAGAIN)
20
- return;
21
- perror("read timerfd");
22
+ if ((res = spa_system_timerfd_read(this->data_system,
23
+ this->timer_source.fd, &expirations)) < 0) {
24
+ if (res != EAGAIN)
25
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+ this, spa_strerror(res));
27
+ return;
28
}
29
30
nsec = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.63.tar.gz/spa/plugins/support/null-audio-sink.c
Changed
31
1
2
#include <spa/utils/list.h>
3
#include <spa/utils/keys.h>
4
#include <spa/utils/json.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
struct impl *this = source->data;
11
uint64_t expirations, nsec, duration = 10;
12
uint32_t rate;
13
+ int res;
14
15
spa_log_trace(this->log, "timeout");
16
17
- if (spa_system_timerfd_read(this->data_system,
18
- this->timer_source.fd, &expirations) < 0) {
19
- if (errno == EAGAIN)
20
- return;
21
- perror("read timerfd");
22
+ if ((res = spa_system_timerfd_read(this->data_system,
23
+ this->timer_source.fd, &expirations)) < 0) {
24
+ if (res != EAGAIN)
25
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+ this, spa_strerror(res));
27
+ return;
28
}
29
30
nsec = this->next_time;
31
pipewire-0.3.62.tar.gz/spa/plugins/test/fakesink.c -> pipewire-0.3.63.tar.gz/spa/plugins/test/fakesink.c
Changed
44
1
2
#include <spa/support/log.h>
3
#include <spa/support/loop.h>
4
#include <spa/utils/list.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
}
11
}
12
13
-static inline void read_timer(struct impl *this)
14
+static inline int read_timer(struct impl *this)
15
{
16
uint64_t expirations;
17
+ int res = 0;
18
19
if (this->callbacks.funcs || this->props.live) {
20
- if (spa_system_timerfd_read(this->data_system,
21
- this->timer_source.fd, &expirations) < 0)
22
- perror("read timerfd");
23
+ if ((res = spa_system_timerfd_read(this->data_system,
24
+ this->timer_source.fd, &expirations)) < 0) {
25
+ if (res != -EAGAIN)
26
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
27
+ this, spa_strerror(res));
28
+ }
29
}
30
+ return res;
31
}
32
33
static void render_buffer(struct impl *this, struct buffer *b)
34
35
struct spa_io_buffers *io = port->io;
36
int n_bytes;
37
38
- read_timer(this);
39
+ if (read_timer(this) < 0)
40
+ return 0;
41
42
if (spa_list_is_empty(&port->ready)) {
43
io->status = SPA_STATUS_NEED_DATA;
44
pipewire-0.3.62.tar.gz/spa/plugins/test/fakesrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/test/fakesrc.c
Changed
44
1
2
#include <spa/support/log.h>
3
#include <spa/support/loop.h>
4
#include <spa/utils/list.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
}
11
}
12
13
-static inline void read_timer(struct impl *this)
14
+static inline int read_timer(struct impl *this)
15
{
16
uint64_t expirations;
17
+ int res = 0;
18
19
if (this->callbacks.funcs || this->props.live) {
20
- if (spa_system_timerfd_read(this->data_system,
21
- this->timer_source.fd, &expirations) < 0)
22
- perror("read timerfd");
23
+ if ((res = spa_system_timerfd_read(this->data_system,
24
+ this->timer_source.fd, &expirations)) < 0) {
25
+ if (res != -EAGAIN)
26
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
27
+ this, spa_strerror(res));
28
+ }
29
}
30
+ return res;
31
}
32
33
static int make_buffer(struct impl *this)
34
35
struct spa_io_buffers *io = port->io;
36
int n_bytes;
37
38
- read_timer(this);
39
+ if (read_timer(this) < 0)
40
+ return 0;
41
42
if (spa_list_is_empty(&port->empty)) {
43
set_timer(this, false);
44
pipewire-0.3.62.tar.gz/spa/plugins/videotestsrc/videotestsrc.c -> pipewire-0.3.63.tar.gz/spa/plugins/videotestsrc/videotestsrc.c
Changed
43
1
2
#include <spa/support/loop.h>
3
#include <spa/utils/list.h>
4
#include <spa/utils/keys.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
}
11
}
12
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
{
16
uint64_t expirations;
17
+ int res = 0;
18
19
if (this->async || this->props.live) {
20
- if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
- perror("read timerfd");
22
+ if ((res = spa_system_timerfd_read(this->data_system,
23
+ this->timer_source.fd, &expirations)) < 0) {
24
+ if (res != -EAGAIN)
25
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+ this, spa_strerror(res));
27
+ }
28
}
29
+ return res;
30
}
31
32
static int make_buffer(struct impl *this)
33
34
struct spa_io_buffers *io = port->io;
35
uint32_t n_bytes;
36
37
- read_timer(this);
38
+ if (read_timer(this) < 0)
39
+ return 0;
40
41
if (spa_list_is_empty(&port->empty)) {
42
set_timer(this, false);
43
pipewire-0.3.62.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c -> pipewire-0.3.63.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c
Changed
43
1
2
#include <spa/utils/list.h>
3
#include <spa/utils/keys.h>
4
#include <spa/utils/names.h>
5
+#include <spa/utils/result.h>
6
#include <spa/utils/string.h>
7
#include <spa/node/node.h>
8
#include <spa/node/utils.h>
9
10
}
11
}
12
13
-static void read_timer(struct impl *this)
14
+static int read_timer(struct impl *this)
15
{
16
uint64_t expirations;
17
+ int res = 0;
18
19
if (this->async || this->props.live) {
20
- if (spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations) < 0)
21
- perror("read timerfd");
22
+ if ((res = spa_system_timerfd_read(this->data_system,
23
+ this->timer_source.fd, &expirations)) < 0) {
24
+ if (res != -EAGAIN)
25
+ spa_log_error(this->log, NAME " %p: timerfd error: %s",
26
+ this, spa_strerror(res));
27
+ }
28
}
29
+ return res;
30
}
31
32
static int make_buffer(struct impl *this)
33
34
uint32_t n_bytes;
35
int res;
36
37
- read_timer(this);
38
+ if (read_timer(this) < 0)
39
+ return 0;
40
41
if ((res = spa_vulkan_ready(&this->state)) < 0) {
42
res = SPA_STATUS_OK;
43
pipewire-0.3.62.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/client-rt.conf.in
Changed
10
1
2
#node.autoconnect = true
3
#resample.quality = 4
4
#channelmix.normalize = false
5
- #channelmix.mix-lfe = false
6
+ #channelmix.mix-lfe = true
7
#channelmix.upmix = true
8
#channelmix.upmix-method = psd # none, simple
9
#channelmix.lfe-cutoff = 150
10
pipewire-0.3.62.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/client.conf.in
Changed
10
1
2
#node.autoconnect = true
3
#resample.quality = 4
4
#channelmix.normalize = false
5
- #channelmix.mix-lfe = false
6
+ #channelmix.mix-lfe = true
7
#channelmix.upmix = true
8
#channelmix.upmix-method = psd # none, simple
9
#channelmix.lfe-cutoff = 150
10
pipewire-0.3.62.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/minimal.conf.in
Changed
19
1
2
resample.disable = true
3
#monitor.channel-volumes = false
4
#channelmix.normalize = false
5
- #channelmix.mix-lfe = false
6
+ #channelmix.mix-lfe = true
7
#channelmix.upmix = true
8
#channelmix.upmix-method = psd # none, simple
9
#channelmix.lfe-cutoff = 150
10
11
#resample.quality = 4
12
resample.disable = true
13
#channelmix.normalize = false
14
- #channelmix.mix-lfe = false
15
+ #channelmix.mix-lfe = true
16
#channelmix.upmix = true
17
#channelmix.upmix-method = psd # none, simple
18
#channelmix.lfe-cutoff = 150
19
pipewire-0.3.62.tar.gz/src/daemon/pipewire-avb.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/pipewire-avb.conf.in
Changed
10
1
2
#node.autoconnect = true
3
#resample.quality = 4
4
#channelmix.normalize = false
5
- #channelmix.mix-lfe = false
6
+ #channelmix.mix-lfe = true
7
#channelmix.upmix = true
8
#channelmix.lfe-cutoff = 120
9
#channelmix.fc-cutoff = 6000
10
pipewire-0.3.62.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.63.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
36
1
2
}
3
4
5
-# Extra modules can be loaded here. Setup in default.pa can be moved here
6
+# Extra scripts can be started here. Setup in default.pa can be moved in
7
+# a script or in pulse.cmd below
8
context.exec =
9
- { path = "pactl" args = "load-module module-always-sink" }
10
- #{ path = "pactl" args = "load-module module-switch-on-connect" }
11
+ #{ path = "pactl" args = "load-module module-always-sink" }
12
+ #{ path = "pactl" args = "upload-sample my-sample.wav my-sample" }
13
#{ path = "/usr/bin/sh" args = "~/.config/pipewire/default.pw" }
14
15
16
+# Extra commands can be executed here.
17
+# load-module : loads a module with args and flags
18
+# args = "<module-name> <module-args>"
19
+# flags = "no-fail"
20
+pulse.cmd =
21
+ { cmd = "load-module" args = "module-always-sink" flags = }
22
+ #{ cmd = "load-module" args = "module-switch-on-connect" }
23
+ #{ cmd = "load-module" args = "module-gsettings" flags = "nofail" }
24
+
25
+
26
stream.properties = {
27
#node.latency = 1024/48000
28
#node.autoconnect = true
29
#resample.quality = 4
30
#channelmix.normalize = false
31
- #channelmix.mix-lfe = false
32
+ #channelmix.mix-lfe = true
33
#channelmix.upmix = true
34
#channelmix.upmix-method = psd # none, simple
35
#channelmix.lfe-cutoff = 150
36
pipewire-0.3.62.tar.gz/src/modules/meson.build -> pipewire-0.3.63.tar.gz/src/modules/meson.build
Changed
18
1
2
'module-filter-chain/convolver.c'
3
4
filter_chain_dependencies =
5
- mathlib, dl_lib, pipewire_dep, sndfile_dep
6
+ mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep
7
8
9
if lilv_lib.found()
10
11
'module-protocol-pulse.c',
12
'module-protocol-pulse/client.c',
13
'module-protocol-pulse/collect.c',
14
+ 'module-protocol-pulse/cmd.c',
15
'module-protocol-pulse/extension.c',
16
'module-protocol-pulse/extensions/ext-device-manager.c',
17
'module-protocol-pulse/extensions/ext-device-restore.c',
18
pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.63.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
118
1
2
#endif
3
4
#include <spa/utils/json.h>
5
+#include <spa/utils/result.h>
6
#include <spa/support/cpu.h>
7
+#include <spa/plugins/audioconvert/resample.h>
8
9
#include <pipewire/log.h>
10
11
12
return samples;
13
}
14
15
+static float *resample_buffer(float *samples, int *n_samples,
16
+ unsigned long in_rate, unsigned long out_rate, uint32_t quality)
17
+{
18
+ uint32_t in_len, out_len, total_out = 0;
19
+ int out_n_samples;
20
+ float *out_samples, *out_buf, *in_buf;
21
+ struct resample r;
22
+ int res;
23
+
24
+ spa_zero(r);
25
+ r.channels = 1;
26
+ r.i_rate = in_rate;
27
+ r.o_rate = out_rate;
28
+ r.cpu_flags = dsp_ops.cpu_flags;
29
+ r.quality = quality;
30
+ if ((res = resample_native_init(&r)) < 0) {
31
+ pw_log_error("resampling failed: %s", spa_strerror(res));
32
+ errno = -res;
33
+ return NULL;
34
+ }
35
+
36
+ out_n_samples = SPA_ROUND_UP(*n_samples * out_rate, in_rate) / in_rate;
37
+ out_samples = calloc(out_n_samples, sizeof(float));
38
+ if (out_samples == NULL)
39
+ goto error;
40
+
41
+ in_len = *n_samples;
42
+ in_buf = samples;
43
+ out_len = out_n_samples;
44
+ out_buf = out_samples;
45
+
46
+ pw_log_info("Resampling filter: rate: %lu => %lu, n_samples: %u => %u, q:%u",
47
+ in_rate, out_rate, in_len, out_len, quality);
48
+
49
+ resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len);
50
+ pw_log_debug("resampled: %u -> %u samples", in_len, out_len);
51
+ total_out += out_len;
52
+
53
+ in_len = resample_delay(&r);
54
+ in_buf = calloc(in_len, sizeof(float));
55
+ if (in_buf == NULL)
56
+ goto error;
57
+
58
+ out_buf = out_samples + total_out;
59
+ out_len = out_n_samples - total_out;
60
+
61
+ pw_log_debug("flushing resampler: %u in %u out", in_len, out_len);
62
+ resample_process(&r, (void*)&in_buf, &in_len, (void*)&out_buf, &out_len);
63
+ pw_log_debug("flushed: %u -> %u samples", in_len, out_len);
64
+ total_out += out_len;
65
+
66
+ free(in_buf);
67
+ free(samples);
68
+ resample_free(&r);
69
+
70
+ *n_samples = total_out;
71
+ return out_samples;
72
+
73
+error:
74
+ resample_free(&r);
75
+ free(samples);
76
+ free(out_samples);
77
+ return NULL;
78
+}
79
+
80
static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
81
unsigned long SampleRate, int index, const char *config)
82
{
83
84
char filenamePATH_MAX = "";
85
int blocksize = 0, tailsize = 0;
86
int delay = 0;
87
+ int resample_quality = RESAMPLE_DEFAULT_QUALITY;
88
float gain = 1.0f;
89
unsigned long rate;
90
91
92
return NULL;
93
}
94
}
95
+ else if (spa_streq(key, "resample_quality")) {
96
+ if (spa_json_get_int(&it1, &resample_quality) <= 0) {
97
+ pw_log_error("convolver:resample_quality requires a number");
98
+ return NULL;
99
+ }
100
+ }
101
else if (spa_json_next(&it1, &val) < 0)
102
break;
103
}
104
105
rate = SampleRate;
106
samples = read_samples(filename, gain, delay, offset,
107
length, channel, &rate, &n_samples);
108
- if (rate != SampleRate) {
109
- pw_log_warn("Convolver samplerate %lu doesn't match filter rate %lu. "
110
- "Consider forcing a filter rate.", rate, SampleRate);
111
- }
112
+ if (rate != SampleRate)
113
+ samples = resample_buffer(samples, &n_samples,
114
+ rate, SampleRate, resample_quality);
115
}
116
if (samples == NULL) {
117
errno = ENOENT;
118
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse.c
Changed
17
1
2
3
PW_LOG_TOPIC(mod_topic, "mod." NAME);
4
#define PW_LOG_TOPIC_DEFAULT mod_topic
5
+PW_LOG_TOPIC(pulse_conn, "conn." NAME);
6
PW_LOG_TOPIC(pulse_ext_dev_restore, "mod." NAME ".device-restore");
7
PW_LOG_TOPIC(pulse_ext_stream_restore, "mod." NAME ".stream-restore");
8
9
10
int res;
11
12
PW_LOG_TOPIC_INIT(mod_topic);
13
+ PW_LOG_TOPIC_INIT(pulse_conn);
14
/* it's easier to init these here than adding an init() call to the
15
* extensions */
16
PW_LOG_TOPIC_INIT(pulse_ext_dev_restore);
17
pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/cmd.c
Added
138
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/utils/json.h>
27
+
28
+#include <pipewire/utils.h>
29
+
30
+#include "module.h"
31
+#include "cmd.h"
32
+
33
+static const char WHITESPACE = " \t\n\r";
34
+
35
+static int do_load_module(struct impl *impl, char *args, const char *flags)
36
+{
37
+ int res, n;
38
+ struct module *module;
39
+ char *a2 = { NULL };
40
+
41
+ n = pw_split_ip(args, WHITESPACE, 2, a);
42
+ if (n < 1) {
43
+ pw_log_info("load-module expects module name");
44
+ return -EINVAL;
45
+ }
46
+
47
+ module = module_create(impl, a0, a1);
48
+ if (module == NULL)
49
+ return -errno;
50
+ if ((res = module_load(module)) < 0)
51
+ return res;
52
+
53
+ return res;
54
+}
55
+
56
+static int do_cmd(struct impl *impl, const char *cmd, char *args, const char *flags)
57
+{
58
+ int res = 0;
59
+ if (spa_streq(cmd, "load-module")) {
60
+ res = do_load_module(impl, args, flags);
61
+ } else {
62
+ pw_log_warn("ignoring unknown command `%s` with args `%s`",
63
+ cmd, args);
64
+ }
65
+ if (res < 0) {
66
+ if (flags && strstr(flags, "nofail")) {
67
+ pw_log_info("nofail command %s %s: %s",
68
+ cmd, args, spa_strerror(res));
69
+ res = 0;
70
+ } else {
71
+ pw_log_error("can't run command %s %s: %s",
72
+ cmd, args, spa_strerror(res));
73
+ }
74
+ }
75
+ return res;
76
+}
77
+
78
+/*
79
+ * pulse.cmd =
80
+ * { cmd = <command> args = "<arguments>" }
81
+ * ...
82
+ *
83
+ */
84
+static int parse_cmd(void *user_data, const char *location,
85
+ const char *section, const char *str, size_t len)
86
+{
87
+ struct impl *impl = user_data;
88
+ struct spa_json it3;
89
+ char key512, *s;
90
+ int res = 0;
91
+
92
+ s = strndup(str, len);
93
+ spa_json_init(&it0, s, len);
94
+ if (spa_json_enter_array(&it0, &it1) < 0) {
95
+ pw_log_error("config file error: pulse.cmd is not an array");
96
+ res = -EINVAL;
97
+ goto exit;
98
+ }
99
+
100
+ while (spa_json_enter_object(&it1, &it2) > 0) {
101
+ char *cmd = NULL, *args = NULL, *flags = NULL;
102
+
103
+ while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
104
+ const char *val;
105
+ int len;
106
+
107
+ if ((len = spa_json_next(&it2, &val)) <= 0)
108
+ break;
109
+
110
+ if (spa_streq(key, "cmd")) {
111
+ cmd = (char*)val;
112
+ spa_json_parse_stringn(val, len, cmd, len+1);
113
+ } else if (spa_streq(key, "args")) {
114
+ args = (char*)val;
115
+ spa_json_parse_stringn(val, len, args, len+1);
116
+ } else if (spa_streq(key, "flags")) {
117
+ if (spa_json_is_container(val, len))
118
+ len = spa_json_container_len(&it2, val, len);
119
+ flags = (char*)val;
120
+ spa_json_parse_stringn(val, len, flags, len+1);
121
+ }
122
+ }
123
+ if (cmd != NULL)
124
+ res = do_cmd(impl, cmd, args, flags);
125
+ if (res < 0)
126
+ break;
127
+ }
128
+exit:
129
+ free(s);
130
+ return res;
131
+}
132
+
133
+int cmd_run(struct impl *impl)
134
+{
135
+ return pw_context_conf_section_for_each(impl->context, "pulse.cmd",
136
+ parse_cmd, impl);
137
+}
138
pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/cmd.h
Added
34
1
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef PULSER_SERVER_CMD_H
27
+#define PULSER_SERVER_CMD_H
28
+
29
+#include "internal.h"
30
+
31
+int cmd_run(struct impl *impl);
32
+
33
+#endif /* PULSER_SERVER_CMD_H */
34
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/message.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/message.c
Changed
19
1
2
#include "defs.h"
3
#include "format.h"
4
#include "internal.h"
5
-#include "log.h"
6
#include "message.h"
7
#include "remap.h"
8
#include "volume.h"
9
10
11
#define PA_CHANNELS_MAX (32u)
12
13
+PW_LOG_TOPIC_EXTERN(pulse_conn);
14
+#define PW_LOG_TOPIC_DEFAULT pulse_conn
15
+
16
static inline uint32_t volume_from_linear(float vol)
17
{
18
uint32_t v;
19
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.63.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
35
1
2
#include "client.h"
3
#include "collect.h"
4
#include "commands.h"
5
+#include "cmd.h"
6
#include "dbus-name.h"
7
#include "defs.h"
8
#include "extension.h"
9
10
11
#define TEMPORARY_MOVE_TIMEOUT (SPA_NSEC_PER_SEC)
12
13
+PW_LOG_TOPIC_EXTERN(pulse_conn);
14
+
15
bool debug_messages = false;
16
17
struct latency_offset_data {
18
19
20
load_defaults(&impl->defs, props);
21
22
- debug_messages = pw_debug_is_category_enabled("connection");
23
+ debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn);
24
25
impl->context = context;
26
impl->loop = pw_context_get_main_loop(context);
27
28
#ifdef HAVE_DBUS
29
impl->dbus_name = dbus_request_name(context, "org.pulseaudio.Server");
30
#endif
31
+ cmd_run(impl);
32
33
return (struct pw_protocol_pulse *) impl;
34
35
pipewire-0.3.62.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.63.tar.gz/src/pipewire/pipewire.c
Changed
201
1
2
char *filename;
3
void *hnd;
4
spa_handle_factory_enum_func_t enum_func;
5
- struct spa_list handles;
6
int ref;
7
};
8
9
10
11
struct registry {
12
struct spa_list plugins;
13
+ struct spa_list handles; /* all handles across all plugins by age (youngest first) */
14
};
15
16
struct support {
17
- char **categories;
18
const char *plugin_dir;
19
const char *support_lib;
20
struct registry registry;
21
22
unsigned int in_valgrind:1;
23
unsigned int no_color:1;
24
unsigned int no_config:1;
25
+ unsigned int do_dlclose:1;
26
};
27
28
static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
29
30
plugin->filename = strdup(filename);
31
plugin->hnd = hnd;
32
plugin->enum_func = enum_func;
33
- spa_list_init(&plugin->handles);
34
35
spa_list_append(®istry->plugins, &plugin->link);
36
37
38
if (--plugin->ref == 0) {
39
spa_list_remove(&plugin->link);
40
pw_log_debug("unloaded plugin:'%s'", plugin->filename);
41
- if (!global_support.in_valgrind)
42
+ if (global_support.do_dlclose)
43
dlclose(plugin->hnd);
44
free(plugin->filename);
45
free(plugin);
46
47
handle->ref = 1;
48
handle->plugin = plugin;
49
handle->factory_name = strdup(factory_name);
50
- spa_list_append(&plugin->handles, &handle->link);
51
+ spa_list_prepend(&sup->registry.handles, &handle->link);
52
53
return &handle->handle;
54
55
56
static struct handle *find_handle(struct spa_handle *handle)
57
{
58
struct registry *registry = &global_support.registry;
59
- struct plugin *p;
60
struct handle *h;
61
62
- spa_list_for_each(p, ®istry->plugins, link) {
63
- spa_list_for_each(h, &p->handles, link) {
64
- if (&h->handle == handle)
65
- return h;
66
- }
67
+ spa_list_for_each(h, ®istry->handles, link) {
68
+ if (&h->handle == handle)
69
+ return h;
70
}
71
+
72
return NULL;
73
}
74
75
76
}
77
#endif
78
79
-static enum spa_log_level
80
-parse_log_level(const char *str)
81
-{
82
- enum spa_log_level l = SPA_LOG_LEVEL_NONE;
83
- switch(str0) {
84
- case 'X': l = SPA_LOG_LEVEL_NONE; break;
85
- case 'E': l = SPA_LOG_LEVEL_ERROR; break;
86
- case 'W': l = SPA_LOG_LEVEL_WARN; break;
87
- case 'I': l = SPA_LOG_LEVEL_INFO; break;
88
- case 'D': l = SPA_LOG_LEVEL_DEBUG; break;
89
- case 'T': l = SPA_LOG_LEVEL_TRACE; break;
90
+static bool
91
+parse_log_level(const char *str, enum spa_log_level *l)
92
+{
93
+ uint32_t lvl;
94
+ if (strlen(str) == 1) {
95
+ switch(str0) {
96
+ case 'X': lvl = SPA_LOG_LEVEL_NONE; break;
97
+ case 'E': lvl = SPA_LOG_LEVEL_ERROR; break;
98
+ case 'W': lvl = SPA_LOG_LEVEL_WARN; break;
99
+ case 'I': lvl = SPA_LOG_LEVEL_INFO; break;
100
+ case 'D': lvl = SPA_LOG_LEVEL_DEBUG; break;
101
+ case 'T': lvl = SPA_LOG_LEVEL_TRACE; break;
102
default:
103
- l = atoi(str);
104
- break;
105
+ goto check_int;
106
+ }
107
+ } else {
108
+check_int:
109
+ if (!spa_atou32(str, &lvl, 0))
110
+ return false;
111
+ if (lvl > SPA_LOG_LEVEL_TRACE)
112
+ return false;
113
}
114
- return l;
115
+ *l = lvl;
116
+ return true;
117
}
118
119
static char *
120
121
char json1024 = {0};
122
char *pos = json;
123
char *end = pos + sizeof(json) - 1;
124
+ enum spa_log_level lvl;
125
126
str = getenv("PIPEWIRE_DEBUG");
127
128
129
*/
130
pos += spa_scnprintf(pos, end - pos, " { conn.* = %d },", SPA_LOG_LEVEL_NONE);
131
132
- /* We only have single-digit log levels, so any single-character
133
- * string is of the form PIPEWIRE_DEBUG=<N> */
134
- if (slen == 1) {
135
- pw_log_set_level(parse_log_level(str));
136
- goto out;
137
- }
138
-
139
tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens);
140
if (n_tokens > 0) {
141
int i;
142
143
int n_tok;
144
char **tok;
145
char *pattern;
146
- enum spa_log_level lvl;
147
148
tok = pw_split_strv(tokensi, ":", 2, &n_tok);
149
- if (n_tok == 2) {
150
+ if (n_tok == 2 && parse_log_level(tok1, &lvl)) {
151
pattern = tok0;
152
- lvl = parse_log_level(tok1);
153
-
154
pos += spa_scnprintf(pos, end - pos, "{ %s = %d },",
155
pattern, lvl);
156
+ } else if (n_tok == 1 && parse_log_level(tok0, &lvl)) {
157
+ pw_log_set_level(lvl);
158
} else {
159
- pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'\n", tokensi);
160
+ pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'",
161
+ tokensi);
162
}
163
164
pw_free_strv(tok);
165
}
166
}
167
pw_free_strv(tokens);
168
-out:
169
pos += spa_scnprintf(pos, end - pos, "");
170
return strdup(json);
171
}
172
173
pthread_mutex_lock(&support_lock);
174
support->in_valgrind = RUNNING_ON_VALGRIND;
175
176
+ support->do_dlclose = true;
177
+ if ((str = getenv("PIPEWIRE_DLCLOSE")) != NULL)
178
+ support->do_dlclose = pw_properties_parse_bool(str);
179
+
180
if (getenv("NO_COLOR") != NULL)
181
support->no_color = true;
182
183
184
support->support_lib = str;
185
186
spa_list_init(&support->registry.plugins);
187
+ spa_list_init(&support->registry.handles);
188
189
if (pw_log_is_default()) {
190
char *patterns = NULL;
191
192
{
193
struct support *support = &global_support;
194
struct registry *registry = &support->registry;
195
- struct plugin *p;
196
+ struct handle *h;
197
198
pthread_mutex_lock(&init_lock);
199
if (support->init_count == 0)
200
201
pipewire-0.3.62.tar.gz/src/pipewire/utils.c -> pipewire-0.3.63.tar.gz/src/pipewire/utils.c
Changed
39
1
2
return arr.data;
3
}
4
5
+/** Split a string in-place based on delimiters
6
+ * \param str a string to split
7
+ * \param delimiter delimiter characters to split on
8
+ * \param max_tokens the max number of tokens to split
9
+ * \paramout tokens an array to hold up to \a max_tokens of strings
10
+ * \return the number of tokens in \a tokens
11
+ *
12
+ * \a str will be modified in-place so that \a tokens will contain zero terminated
13
+ * strings split at \a delimiter characters.
14
+ */
15
+SPA_EXPORT
16
+int pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens)
17
+{
18
+ const char *state = NULL;
19
+ char *s, *t;
20
+ size_t len, l2;
21
+ int n = 0;
22
+
23
+ s = (char *)pw_split_walk(str, delimiter, &len, &state);
24
+ while (s && n + 1 < max_tokens) {
25
+ t = (char*)pw_split_walk(str, delimiter, &l2, &state);
26
+ slen = '\0';
27
+ tokensn++ = s;
28
+ s = t;
29
+ len = l2;
30
+ }
31
+ if (s)
32
+ tokensn++ = s;
33
+ return n;
34
+}
35
+
36
/** Free a NULL terminated array of strings
37
* \param str a NULL terminated array of string
38
*
39
pipewire-0.3.62.tar.gz/src/pipewire/utils.h -> pipewire-0.3.63.tar.gz/src/pipewire/utils.h
Changed
11
1
2
char **
3
pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens);
4
5
+int
6
+pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens);
7
+
8
void
9
pw_free_strv(char **str);
10
11
pipewire-0.3.62.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.63.tar.gz/src/tools/pw-cli.c
Changed
28
1
2
static int children_of(struct remote_data *rd, uint32_t parent_id,
3
const char *child_type, uint32_t **children);
4
5
-static int pw_split_ip(char *str, const char *delimiter, int max_tokens, char *tokens)
6
-{
7
- const char *state = NULL;
8
- char *s, *t;
9
- size_t len, l2;
10
- int n = 0;
11
-
12
- s = (char *)pw_split_walk(str, delimiter, &len, &state);
13
- while (s && n + 1 < max_tokens) {
14
- t = (char*)pw_split_walk(str, delimiter, &l2, &state);
15
- slen = '\0';
16
- tokensn++ = s;
17
- s = t;
18
- len = l2;
19
- }
20
- if (s)
21
- tokensn++ = s;
22
- return n;
23
-}
24
-
25
static void print_properties(struct spa_dict *props, char mark, bool header)
26
{
27
const struct spa_dict_item *item;
28
pipewire-0.3.62.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.63.tar.gz/src/tools/pw-mon.c
Changed
10
1
2
if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL)
3
colors = true;
4
5
- while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) {
6
+ while ((c = getopt_long(argc, argv, "hVr:NC", long_options, NULL)) != -1) {
7
switch (c) {
8
case 'h':
9
show_help(argv0, false);
10
pipewire-0.3.62.tar.gz/test/test-logger.c -> pipewire-0.3.63.tar.gz/test/test-logger.c
Changed
23
1
2
"invalid value",
3
"*:5,some invalid value",
4
"*:W,foo.bar:3,invalid:",
5
- "*:W,1,foo.bar:D",
6
- "*:W,D,foo.bar:3",
7
+ "*:W,2,foo.bar:Q",
8
+ "*:W,7,foo.bar:D",
9
+ "*:W,Q,foo.bar:5",
10
+ "*:W,D,foo.bar:8",
11
};
12
13
pwtest_int_lt(which, SPA_N_ELEMENTS(envvars));
14
15
PWTEST_ARG_RANGE, SPA_LOG_LEVEL_NONE, SPA_LOG_LEVEL_TRACE + 1,
16
PWTEST_NOARG);
17
pwtest_add(logger_debug_env_invalid,
18
- PWTEST_ARG_RANGE, 0, 5, /* see the test */
19
+ PWTEST_ARG_RANGE, 0, 7, /* see the test */
20
PWTEST_NOARG);
21
pwtest_add(logger_topics, PWTEST_NOARG);
22
pwtest_add(logger_journal, PWTEST_NOARG);
23
pipewire-0.3.62.tar.gz/test/test-utils.c -> pipewire-0.3.63.tar.gz/test/test-utils.c
Changed
24
1
2
{
3
const char *test1 = "a \n test string \n \r ";
4
const char *del = "\n\r ";
5
+ const char *test2 = "a:";
6
+ const char *del2 = ":";
7
int n_tokens;
8
char **res;
9
10
11
pwtest_str_eq(res1, "test string \n \r ");
12
pwtest_ptr_null(res2);
13
pw_free_strv(res);
14
+
15
+ res = pw_split_strv(test2, del2, 2, &n_tokens);
16
+ pwtest_ptr_notnull(res);
17
+ pwtest_int_eq(n_tokens, 1);
18
+ pwtest_str_eq(res0, "a");
19
+ pwtest_ptr_null(res1);
20
+ pw_free_strv(res);
21
}
22
23
PWTEST(utils_split)
24