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 50
_service
Changed
x
1
2
<service name="download_url">
3
<param name="host">gitlab.freedesktop.org</param>
4
<param name="protocol">https</param>
5
- <param name="path">/pipewire/pipewire/-/archive/1.4.0/pipewire-1.4.0.tar.bz2</param>
6
+ <param name="path">/pipewire/pipewire/-/archive/1.4.1/pipewire-1.4.1.tar.bz2</param>
7
</service>
8
</services>
9
\ No newline at end of file
10
_service:download_url:pipewire-1.4.0.tar.bz2/NEWS -> _service:download_url:pipewire-1.4.1.tar.bz2/NEWS
Changed
55
1
2
+# PipeWire 1.4.1 (2025-03-14)
3
+
4
+This is a quick bugfix release that is API and ABI compatible with
5
+previous 1.x releases.
6
+
7
+## Highlights
8
+ - Handle SplitPCM wrong channels specifications. This fixes some
9
+ problems with disappearing devices.
10
+ - Add backwards compatibility support for when the kernel does not
11
+ support UMP. Also fix UMP output. This restores MIDI support for
12
+ older kernels/ALSA.
13
+ - Fix a crash in audioconvert because the resampler was not using the
14
+ right number of channels.
15
+ - Some compilation fixes and small improvements.
16
+
17
+
18
+## PipeWire
19
+ - Don't emit events when disconnecting a stream. (#3314)
20
+ - Fix some compilation problems. (#4603)
21
+
22
+## Modules
23
+ - Bump the ROC requirement to version 0.4.0
24
+
25
+## SPA
26
+ - Handle SplitPCM too few or too many channels. Add an error string
27
+ to the device names when the UCM config has an error.
28
+ - Add backwards compatibility support for when the kernel does not
29
+ support UMP.
30
+ - Configure the channels in the resampler correctly in all
31
+ cases. (#4595)
32
+ - Fix UMP output.
33
+ - Use the right samplerate of the filter-graph in audioconvert in
34
+ all cases.
35
+
36
+## Bluetooth
37
+ - Fix a crash with an incomming call.
38
+
39
+
40
+Older versions:
41
+
42
# PipeWire 1.4.0 (2025-03-06)
43
44
This is the 1.4 release that is API and ABI compatible with previous
45
46
## JACK
47
- Add an option to disable the MIDI2 port flags. (#4584)
48
49
-
50
-Older versions:
51
-
52
# PipeWire 1.3.83 (2025-02-20)
53
54
This is the third and hopefully last 1.4 release candidate that
55
_service:download_url:pipewire-1.4.0.tar.bz2/meson.build -> _service:download_url:pipewire-1.4.1.tar.bz2/meson.build
Changed
63
1
2
project('pipewire', 'c' ,
3
- version : '1.4.0',
4
+ version : '1.4.1',
5
license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
meson_version : '>= 0.61.1',
7
default_options : 'warning_level=3',
8
9
add_project_arguments(cxx.get_supported_arguments(cxx_flags), language: 'cpp')
10
endif
11
12
-sse_args = '-msse'
13
-sse2_args = '-msse2'
14
-ssse3_args = '-mssse3'
15
-sse41_args = '-msse4.1'
16
-fma_args = '-mfma'
17
-avx_args = '-mavx'
18
-avx2_args = '-mavx2'
19
-
20
-have_sse = cc.has_argument(sse_args)
21
-have_sse2 = cc.has_argument(sse2_args)
22
-have_ssse3 = cc.has_argument(ssse3_args)
23
-have_sse41 = cc.has_argument(sse41_args)
24
-have_fma = cc.has_argument(fma_args)
25
-have_avx = cc.has_argument(avx_args)
26
-have_avx2 = cc.has_argument(avx2_args)
27
+have_sse = false
28
+have_sse2 = false
29
+have_ssse3 = false
30
+have_sse41 = false
31
+have_fma = false
32
+have_avx = false
33
+have_avx2 = false
34
+if host_machine.cpu_family() in 'x86', 'x86_64'
35
+ sse_args = '-msse'
36
+ sse2_args = '-msse2'
37
+ ssse3_args = '-mssse3'
38
+ sse41_args = '-msse4.1'
39
+ fma_args = '-mfma'
40
+ avx_args = '-mavx'
41
+ avx2_args = '-mavx2'
42
+
43
+ have_sse = cc.has_argument(sse_args)
44
+ have_sse2 = cc.has_argument(sse2_args)
45
+ have_ssse3 = cc.has_argument(ssse3_args)
46
+ have_sse41 = cc.has_argument(sse41_args)
47
+ have_fma = cc.has_argument(fma_args)
48
+ have_avx = cc.has_argument(avx_args)
49
+ have_avx2 = cc.has_argument(avx2_args)
50
+endif
51
52
have_neon = false
53
if host_machine.cpu_family() == 'aarch64'
54
55
summary({'intl support': libintl_dep.found()}, bool_yn: true)
56
57
need_alsa = get_option('pipewire-alsa').enabled() or 'media-session' in get_option('session-managers')
58
-alsa_dep = dependency('alsa', version : '>=1.2.10', required: need_alsa)
59
+alsa_dep = dependency('alsa', version : '>=1.2.6', required: need_alsa)
60
summary({'pipewire-alsa': alsa_dep.found()}, bool_yn: true)
61
62
if host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
63
_service:download_url:pipewire-1.4.0.tar.bz2/spa/meson.build -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/meson.build
Changed
16
1
2
endif
3
4
# plugin-specific dependencies
5
- alsa_dep = dependency('alsa', version : '>=1.2.10', required: get_option('alsa'))
6
+ alsa_dep = dependency('alsa', version : '>=1.2.6', required: get_option('alsa'))
7
summary({'ALSA': alsa_dep.found()}, bool_yn: true, section: 'Backend')
8
9
+ if alsa_dep.version().version_compare('>=1.2.10')
10
+ cdata.set('HAVE_ALSA_UMP', true)
11
+ endif
12
+
13
bluez_dep = dependency('bluez', version : '>= 4.101', required: get_option('bluez5'))
14
bluez_gio_dep = dependency('gio-2.0', required : get_option('bluez5'))
15
bluez_gio_unix_dep = dependency('gio-unix-2.0', required : get_option('bluez5'))
16
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/acp-tool.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/acp-tool.c
Changed
20
1
2
int level, const char *file, int line, const char *func,
3
const char *fmt, va_list arg)
4
{
5
+ static const char * const levels = { "E", "W", "N", "I", "D", "T" };
6
+ const char *level_str = levelsSPA_CLAMP(level, 0, (int)SPA_N_ELEMENTS(levels) - 1);
7
+
8
+ if (file) {
9
+ const char *p = strrchr(file, '/');
10
+ if (p)
11
+ file = p + 1;
12
+ }
13
+
14
+ fprintf(stderr, "%s %16s:%-5d ", level_str, file ? file : "", line);
15
+ while (level-- > 1)
16
+ fprintf(stderr, " ");
17
vfprintf(stderr, fmt, arg);
18
fprintf(stderr, "\n");
19
}
20
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/acp/acp.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/acp/acp.c
Changed
52
1
2
int n_profiles, n_ports, n_devices;
3
uint32_t idx;
4
const char *arr;
5
+ bool broken_ucm = false;
6
7
n_devices = 0;
8
pa_dynarray_init(&impl->out.devices, device_free);
9
10
dev->ports, NULL);
11
12
pa_dynarray_append(&ap->out.devices, dev);
13
+
14
+ if (m->split && m->split->broken)
15
+ broken_ucm = true;
16
}
17
}
18
19
20
dev->ports, NULL);
21
22
pa_dynarray_append(&ap->out.devices, dev);
23
+
24
+ if (m->split && m->split->broken)
25
+ broken_ucm = true;
26
}
27
}
28
cp->n_devices = pa_dynarray_size(&ap->out.devices);
29
30
pa_hashmap_put(impl->profiles, ap->name, cp);
31
}
32
33
+
34
+ /* Add a conspicuous notice if there are errors in the UCM profile */
35
+ if (broken_ucm) {
36
+ const char *desc;
37
+ char *new_desc = NULL;
38
+
39
+ desc = pa_proplist_gets(impl->proplist, PA_PROP_DEVICE_DESCRIPTION);
40
+ if (!desc)
41
+ desc = "";
42
+ new_desc = spa_aprintf(_("%s ALSA UCM error"), desc);
43
+ pa_log_notice("Errors in ALSA UCM profile for card %s", desc);
44
+ if (new_desc)
45
+ pa_proplist_sets(impl->proplist, PA_PROP_DEVICE_DESCRIPTION, new_desc);
46
+ free(new_desc);
47
+ }
48
+
49
pa_dynarray_init(&impl->out.ports, NULL);
50
n_ports = 0;
51
PA_HASHMAP_FOREACH(dp, impl->ports, state) {
52
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/acp/alsa-ucm.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/acp/alsa-ucm.c
Changed
201
1
2
const char *device_name;
3
int i;
4
uint32_t hw_channels;
5
+ const char *pcm_name;
6
+ const char *rule_name;
7
+
8
+ if (spa_streq(prefix, "Playback"))
9
+ pcm_name = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SINK);
10
+ else
11
+ pcm_name = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_SOURCE);
12
+ if (!pcm_name)
13
+ pcm_name = "";
14
15
device_name = pa_proplist_gets(device->proplist, PA_ALSA_PROP_UCM_NAME);
16
if (!device_name)
17
18
if (pa_atou(value, &idx) < 0)
19
break;
20
21
- if (idx >= hw_channels)
22
- goto fail;
23
+ if (idx >= hw_channels) {
24
+ pa_log_notice("Error in ALSA UCM profile for %s (%s): %sChannel%d=%d >= %sChannels=%d",
25
+ pcm_name, device_name, prefix, i, idx, prefix, hw_channels);
26
+ split->broken = true;
27
+ }
28
29
value = ucm_get_string(uc_mgr, "%sChannelPos%d/%s", prefix, i, device_name);
30
- if (!value)
31
+ if (!value) {
32
+ rule_name = "ChannelPos";
33
goto fail;
34
+ }
35
36
map = snd_pcm_chmap_parse_string(value);
37
- if (!map)
38
+ if (!map) {
39
+ rule_name = "ChannelPos value";
40
goto fail;
41
+ }
42
43
if (map->channels == 1) {
44
pa_log_debug("Split %s channel %d -> device %s channel %d: %s (%d)",
45
46
free(map);
47
} else {
48
free(map);
49
+ rule_name = "channel map parsing";
50
goto fail;
51
}
52
}
53
54
return split;
55
56
fail:
57
- pa_log_warn("Invalid SplitPCM ALSA UCM rule for device %s", device_name);
58
+ pa_log_warn("Invalid SplitPCM ALSA UCM %s for device %s (%s)", rule_name, pcm_name, device_name);
59
pa_xfree(split);
60
return NULL;
61
}
62
63
dev->eld_device = pcm_device;
64
}
65
66
-static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m, int mode) {
67
+static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m, int mode, bool max_channels) {
68
snd_pcm_t* pcm;
69
pa_sample_spec try_ss = ucm->default_sample_spec;
70
pa_channel_map try_map;
71
72
bool exact_channels = m->channel_map.channels > 0;
73
74
if (!m->split) {
75
+ if (max_channels) {
76
+ errno = EINVAL;
77
+ return NULL;
78
+ }
79
+
80
if (exact_channels) {
81
try_map = m->channel_map;
82
try_ss.channels = try_map.channels;
83
84
return NULL;
85
}
86
87
- exact_channels = true;
88
- try_ss.channels = m->split->hw_channels;
89
+ exact_channels = false;
90
+ try_ss.channels = max_channels ? PA_CHANNELS_MAX : m->split->hw_channels;
91
pa_channel_map_init_extend(&try_map, try_ss.channels, PA_CHANNEL_MAP_AUX);
92
}
93
94
95
&try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, NULL, NULL, exact_channels);
96
97
if (pcm) {
98
- if (!exact_channels)
99
+ if (m->split) {
100
+ const char *mode_name = mode == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture";
101
+
102
+ if (try_map.channels < m->split->hw_channels) {
103
+ pa_logl((max_channels ? PA_LOG_NOTICE : PA_LOG_DEBUG),
104
+ "Error in ALSA UCM profile for %s (%s): %sChannels=%d > avail %d",
105
+ m->device_strings0, m->name, mode_name, m->split->hw_channels, try_map.channels);
106
+
107
+ /* Retry with max channel count, in case ALSA rounded down */
108
+ if (!max_channels) {
109
+ pa_alsa_close(&pcm);
110
+ return mapping_open_pcm(ucm, m, mode, true);
111
+ }
112
+
113
+ /* Just accept whatever we got... Some of the routings won't get connected
114
+ * anywhere */
115
+ m->split->hw_channels = try_map.channels;
116
+ m->split->broken = true;
117
+ } else if (try_map.channels > m->split->hw_channels) {
118
+ pa_log_notice("Error in ALSA UCM profile for %s (%s): %sChannels=%d < avail %d",
119
+ m->device_strings0, m->name, mode_name, m->split->hw_channels, try_map.channels);
120
+ m->split->hw_channels = try_map.channels;
121
+ m->split->broken = true;
122
+ }
123
+ } else if (!exact_channels) {
124
m->channel_map = try_map;
125
+ }
126
mapping_init_eld(m, pcm);
127
}
128
129
return pcm;
130
}
131
132
-static void pa_alsa_init_proplist_split_pcm(pa_idxset *mappings, pa_alsa_mapping *leader, pa_direction_t direction)
133
+static void pa_alsa_init_split_pcm(pa_idxset *mappings, pa_alsa_mapping *leader, pa_direction_t direction)
134
{
135
pa_proplist *props = pa_proplist_new();
136
uint32_t idx;
137
138
pa_proplist_update(m->output_proplist, PA_UPDATE_REPLACE, props);
139
else
140
pa_proplist_update(m->input_proplist, PA_UPDATE_REPLACE, props);
141
+
142
+ /* Update HW channel count to match probed one */
143
+ m->split->hw_channels = leader->split->hw_channels;
144
}
145
146
pa_proplist_free(props);
147
148
if (!m->split)
149
pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
150
else
151
- pa_alsa_init_proplist_split_pcm(p->output_mappings, m, PA_DIRECTION_OUTPUT);
152
+ pa_alsa_init_split_pcm(p->output_mappings, m, PA_DIRECTION_OUTPUT);
153
154
pa_alsa_close(&m->output_pcm);
155
}
156
157
if (!m->split)
158
pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
159
else
160
- pa_alsa_init_proplist_split_pcm(p->input_mappings, m, PA_DIRECTION_INPUT);
161
+ pa_alsa_init_split_pcm(p->input_mappings, m, PA_DIRECTION_INPUT);
162
163
pa_alsa_close(&m->input_pcm);
164
}
165
166
pa_log_info("Set ucm verb to %s", verb_name);
167
168
if ((snd_use_case_set(ucm->ucm_mgr, "_verb", verb_name)) < 0) {
169
- pa_log("Failed to set verb %s", verb_name);
170
+ pa_log("Profile '%s': failed to set verb %s", p->name, verb_name);
171
p->supported = false;
172
continue;
173
}
174
175
if (m->split && !m->split->leader)
176
continue;
177
178
- m->output_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_PLAYBACK);
179
+ m->output_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_PLAYBACK, false);
180
if (!m->output_pcm) {
181
+ pa_log_info("Profile '%s' mapping '%s': output PCM open failed",
182
+ p->name, m->name);
183
p->supported = false;
184
break;
185
}
186
187
if (m->split && !m->split->leader)
188
continue;
189
190
- m->input_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_CAPTURE);
191
+ m->input_pcm = mapping_open_pcm(ucm, m, SND_PCM_STREAM_CAPTURE, false);
192
if (!m->input_pcm) {
193
+ pa_log_info("Profile '%s' mapping '%s': input PCM open failed",
194
+ p->name, m->name);
195
p->supported = false;
196
break;
197
}
198
199
200
if (!p->supported) {
201
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/acp/alsa-ucm.h -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/acp/alsa-ucm.h
Changed
9
1
2
int channels;
3
int idxPA_CHANNELS_MAX;
4
enum snd_pcm_chmap_position posPA_CHANNELS_MAX;
5
+ bool broken;
6
};
7
8
struct pa_alsa_ucm_device {
9
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/alsa-seq-bridge.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/alsa-seq-bridge.c
Changed
26
1
2
this->quantum_limit = 8192;
3
this->min_pool_size = 500;
4
this->max_pool_size = 2000;
5
+ this->ump = true;
6
7
for (i = 0; info && i < info->n_items; i++) {
8
const char *k = info->itemsi.key;
9
10
spa_atou32(s, &this->min_pool_size, 0);
11
} else if (spa_streq(k, "api.alsa.seq.max-pool")) {
12
spa_atou32(s, &this->max_pool_size, 0);
13
+ } else if (spa_streq(k, "api.alsa.seq.ump")) {
14
+ this->ump = spa_atob(s);
15
}
16
}
17
18
19
""SPA_KEY_API_ALSA_DISABLE_LONGNAME"=<bool, default false> "
20
" api.alsa.seq.min-pool=<min-pool, default 500> "
21
" api.alsa.seq.max-pool=<max-pool, default 2000>"
22
+ " api.alsa.seq.ump = <boolean> "
23
},
24
};
25
26
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/alsa-seq.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/alsa-seq.c
Changed
201
1
2
3
#define CHECK(s,msg,...) if ((res = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(res)); return res; }
4
5
-static int seq_open(struct seq_state *state, struct seq_conn *conn, bool with_queue)
6
+static int seq_open(struct seq_state *state, struct seq_conn *conn, bool with_queue, bool probe_ump)
7
{
8
struct props *props = &state->props;
9
int res;
10
11
0)) < 0)
12
return res;
13
14
- if ((res = snd_seq_set_client_midi_version(conn->hndl, SND_SEQ_CLIENT_UMP_MIDI_2_0)) < 0) {
15
- snd_seq_close(conn->hndl);
16
- spa_log_info(state->log, "%p: ALSA failed to enable UMP MIDI: %s",
17
- state, snd_strerror(res));
18
- return res;
19
+ if (!state->ump) {
20
+ spa_log_info(state->log, "%p: ALSA UMP MIDI disabled", state);
21
+ return 0;
22
+ }
23
+
24
+#ifdef HAVE_ALSA_UMP
25
+ res = snd_seq_set_client_midi_version(conn->hndl, SND_SEQ_CLIENT_UMP_MIDI_2_0);
26
+#else
27
+ res = -EOPNOTSUPP;
28
+#endif
29
+ if (res < 0) {
30
+ spa_log_lev(state->log, (probe_ump ? SPA_LOG_LEVEL_INFO : SPA_LOG_LEVEL_ERROR),
31
+ "%p: ALSA failed to enable UMP MIDI: %s", state, snd_strerror(res));
32
+ if (!probe_ump) {
33
+ snd_seq_close(conn->hndl);
34
+ return res; /* either all are UMP or none are UMP */
35
+ }
36
+
37
+ state->ump = false;
38
+ } else {
39
+ spa_log_debug(state->log, "%p: ALSA UMP MIDI enabled", state);
40
+ state->ump = true;
41
}
42
43
return 0;
44
45
}
46
}
47
48
-static void debug_event(struct seq_state *state, snd_seq_ump_event_t *ev)
49
+static void debug_event(struct seq_state *state, snd_seq_event_t *ev)
50
+{
51
+ if (SPA_LIKELY(!spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_TRACE)))
52
+ return;
53
+
54
+ spa_log_trace(state->log, "event type:%d flags:0x%x", ev->type, ev->flags);
55
+ switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) {
56
+ case SND_SEQ_TIME_STAMP_TICK:
57
+ spa_log_trace(state->log, " time: %d ticks", ev->time.tick);
58
+ break;
59
+ case SND_SEQ_TIME_STAMP_REAL:
60
+ spa_log_trace(state->log, " time = %d.%09d",
61
+ (int)ev->time.time.tv_sec,
62
+ (int)ev->time.time.tv_nsec);
63
+ break;
64
+ }
65
+ spa_log_trace(state->log, " source:%d.%d dest:%d.%d queue:%d",
66
+ ev->source.client,
67
+ ev->source.port,
68
+ ev->dest.client,
69
+ ev->dest.port,
70
+ ev->queue);
71
+}
72
+
73
+#ifdef HAVE_ALSA_UMP
74
+static void debug_ump_event(struct seq_state *state, snd_seq_ump_event_t *ev)
75
{
76
if (SPA_LIKELY(!spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_TRACE)))
77
return;
78
79
ev->dest.port,
80
ev->queue);
81
}
82
+#endif
83
84
static void alsa_seq_on_sys(struct spa_source *source)
85
{
86
struct seq_state *state = source->data;
87
- snd_seq_ump_event_t *ev;
88
+ const bool ump = state->ump;
89
int res;
90
91
- while (snd_seq_ump_event_input(state->sys.hndl, &ev) > 0) {
92
- const snd_seq_addr_t *addr = &ev->data.addr;
93
+ while (1) {
94
+ const snd_seq_addr_t *addr;
95
+ snd_seq_event_type_t type;
96
+
97
+ if (ump) {
98
+#ifdef HAVE_ALSA_UMP
99
+ snd_seq_ump_event_t *ev;
100
+
101
+ res = snd_seq_ump_event_input(state->sys.hndl, &ev);
102
+ if (res <= 0)
103
+ break;
104
+
105
+ debug_ump_event(state, ev);
106
+
107
+ addr = &ev->data.addr;
108
+ type = ev->type;
109
+#else
110
+ spa_assert_not_reached();
111
+#endif
112
+ } else {
113
+ snd_seq_event_t *ev;
114
+
115
+ res = snd_seq_event_input(state->sys.hndl, &ev);
116
+ if (res <= 0)
117
+ break;
118
+
119
+ debug_event(state, ev);
120
+
121
+ addr = &ev->data.addr;
122
+ type = ev->type;
123
+ }
124
125
if (addr->client == state->event.addr.client)
126
continue;
127
128
- debug_event(state, ev);
129
-
130
- switch (ev->type) {
131
+ switch (type) {
132
case SND_SEQ_EVENT_CLIENT_START:
133
case SND_SEQ_EVENT_CLIENT_CHANGE:
134
spa_log_info(state->log, "client add/change %d", addr->client);
135
136
break;
137
default:
138
spa_log_info(state->log, "unhandled event %d: %d:%d",
139
- ev->type, addr->client, addr->port);
140
+ type, addr->client, addr->port);
141
break;
142
143
}
144
145
146
spa_zero(reserve);
147
for (i = 0; i < 16; i++) {
148
- spa_log_debug(state->log, "close %d", i);
149
- if ((res = seq_open(state, &reservei, false)) < 0)
150
+ spa_log_debug(state->log, "open %d", i);
151
+ if ((res = seq_open(state, &reservei, false, (i == 0))) < 0)
152
break;
153
}
154
if (i >= 2) {
155
156
157
static int process_read(struct seq_state *state)
158
{
159
- snd_seq_ump_event_t *ev;
160
struct seq_stream *stream = &state->streamsSPA_DIRECTION_OUTPUT;
161
+ const bool ump = state->ump;
162
uint32_t i;
163
uint32_t *data;
164
+ uint8_t midi1_dataMAX_EVENT_SIZE;
165
+ uint32_t ump_dataMAX_EVENT_SIZE;
166
long size;
167
- int res;
168
+ int res = -1;
169
170
/* copy all new midi events into their port buffers */
171
- while ((res = snd_seq_ump_event_input(state->event.hndl, &ev)) > 0) {
172
- const snd_seq_addr_t *addr = &ev->source;
173
+ while (1) {
174
+ const snd_seq_addr_t *addr;
175
struct seq_port *port;
176
uint64_t ev_time, diff;
177
uint32_t offset;
178
+ void *event;
179
+ uint8_t *midi1_ptr;
180
+ size_t midi1_size = 0;
181
+ uint64_t ump_state = 0;
182
+ snd_seq_event_type_t SPA_UNUSED type;
183
+
184
+ if (ump) {
185
+#ifdef HAVE_ALSA_UMP
186
+ snd_seq_ump_event_t *ev;
187
+
188
+ res = snd_seq_ump_event_input(state->event.hndl, &ev);
189
+ if (res <= 0)
190
+ break;
191
+
192
+ debug_ump_event(state, ev);
193
+
194
+ event = ev;
195
+ addr = &ev->source;
196
+ ev_time = SPA_TIMESPEC_TO_NSEC(&ev->time.time);
197
+ type = ev->type;
198
+#else
199
+ spa_assert_not_reached();
200
+#endif
201
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/alsa/alsa-seq.h -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/alsa/alsa-seq.h
Changed
22
1
2
#include <stddef.h>
3
#include <math.h>
4
5
+#include "config.h"
6
+
7
#include <alsa/asoundlib.h>
8
+#ifdef HAVE_ALSA_UMP
9
#include <alsa/ump_msg.h>
10
+#endif
11
12
#include <spa/support/plugin.h>
13
#include <spa/support/loop.h>
14
15
unsigned int opened:1;
16
unsigned int started:1;
17
unsigned int following:1;
18
+ unsigned int ump:1;
19
20
struct seq_stream streams2;
21
22
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/audioconvert/audioconvert.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/audioconvert/audioconvert.c
Changed
167
1
2
uint32_t src_idx;
3
uint32_t dst_idx;
4
uint32_t final_idx;
5
- uint32_t n_datas;
6
struct port *ctrlport;
7
};
8
9
10
bool passthrough;
11
uint32_t in_idx;
12
uint32_t out_idx;
13
- uint32_t n_in;
14
- uint32_t n_out;
15
void *data;
16
void (*run) (struct stage *stage, struct stage_context *c);
17
};
18
19
{
20
int res;
21
char rate_str64;
22
- struct dir *in;
23
+ struct dir *dir;
24
25
if (graph == NULL)
26
return 0;
27
28
- in = &this->dirSPA_DIRECTION_INPUT;
29
- snprintf(rate_str, sizeof(rate_str), "%d", in->format.info.raw.rate);
30
+ dir = &this->dirSPA_DIRECTION_REVERSE(this->direction);
31
+ snprintf(rate_str, sizeof(rate_str), "%d", dir->format.info.raw.rate);
32
33
spa_filter_graph_deactivate(graph);
34
res = spa_filter_graph_activate(graph,
35
36
struct dir *in = &this->dirSPA_DIRECTION_INPUT;
37
struct dir *out = &this->dirSPA_DIRECTION_OUTPUT;
38
int res;
39
+ uint32_t channels;
40
+
41
+ if (this->direction == SPA_DIRECTION_INPUT)
42
+ channels = in->format.info.raw.channels;
43
+ else
44
+ channels = out->format.info.raw.channels;
45
46
spa_log_info(this->log, "%p: %s/%d@%d->%s/%d@%d", this,
47
spa_debug_type_find_name(spa_type_audio_format, SPA_AUDIO_FORMAT_DSP_F32),
48
- out->format.info.raw.channels,
49
+ channels,
50
in->format.info.raw.rate,
51
spa_debug_type_find_name(spa_type_audio_format, SPA_AUDIO_FORMAT_DSP_F32),
52
- out->format.info.raw.channels,
53
+ channels,
54
out->format.info.raw.rate);
55
56
if (this->props.resample_disabled && !this->resample_peaks &&
57
58
if (this->resample.free)
59
resample_free(&this->resample);
60
61
- this->resample.channels = out->format.info.raw.channels;
62
+ this->resample.channels = channels;
63
this->resample.i_rate = in->format.info.raw.rate;
64
this->resample.o_rate = out->format.info.raw.rate;
65
this->resample.log = this->log;
66
67
s->passthrough = false;
68
s->in_idx = ctx->src_idx;
69
s->out_idx = ctx->src_idx;
70
- s->n_in = ctx->n_datas;
71
- s->n_out = ctx->n_datas;
72
s->data = NULL;
73
s->run = run_wav_stage;
74
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
75
76
struct impl *impl = s->impl;
77
struct dir *dir = &impl->dirSPA_DIRECTION_OUTPUT;
78
uint32_t i;
79
- for (i = 0; i < s->n_in; i++) {
80
+ for (i = 0; i < dir->conv.n_channels; i++) {
81
c->datass->out_idxi = c->datass->in_idxdir->remapi;
82
spa_log_trace_fp(impl->log, "%p: output remap %d -> %d", impl, i, dir->remapi);
83
}
84
85
s->passthrough = false;
86
s->in_idx = ctx->dst_idx;
87
s->out_idx = CTX_DATA_REMAP_DST;
88
- s->n_in = ctx->n_datas;
89
- s->n_out = ctx->n_datas;
90
s->data = NULL;
91
s->run = run_dst_remap_stage;
92
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
93
94
s->passthrough = false;
95
s->in_idx = ctx->src_idx;
96
s->out_idx = CTX_DATA_REMAP_SRC;
97
- s->n_in = ctx->n_datas;
98
- s->n_out = ctx->n_datas;
99
s->data = NULL;
100
s->run = run_src_remap_stage;
101
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
102
103
s->passthrough = false;
104
s->in_idx = ctx->src_idx;
105
s->out_idx = ctx->dst_idx;
106
- s->n_in = ctx->n_datas;
107
- s->n_out = ctx->n_datas;
108
s->data = NULL;
109
s->run = run_src_convert_stage;
110
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
111
112
s->passthrough = false;
113
s->in_idx = ctx->src_idx;
114
s->out_idx = ctx->dst_idx;
115
- s->n_in = ctx->n_datas;
116
- s->n_out = ctx->n_datas;
117
s->data = NULL;
118
s->run = run_resample_stage;
119
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
120
121
s->passthrough = false;
122
s->in_idx = ctx->src_idx;
123
s->out_idx = ctx->dst_idx;
124
- s->n_in = ctx->n_datas;
125
- s->n_out = ctx->n_datas;
126
s->data = fg;
127
s->run = run_filter_stage;
128
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
129
130
s->passthrough = false;
131
s->in_idx = ctx->src_idx;
132
s->out_idx = ctx->dst_idx;
133
- s->n_in = ctx->n_datas;
134
- s->n_out = ctx->n_datas;
135
s->data = NULL;
136
s->run = run_channelmix_stage;
137
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
138
139
s->passthrough = false;
140
s->in_idx = ctx->src_idx;
141
s->out_idx = ctx->final_idx;
142
- s->n_in = ctx->n_datas;
143
- s->n_out = ctx->n_datas;
144
s->data = NULL;
145
s->run = run_dst_convert_stage;
146
spa_log_trace(impl->log, "%p: stage %d", impl, impl->n_stages);
147
148
ctx.in_samples = n_samples;
149
ctx.n_samples = n_samples;
150
ctx.n_out = n_out;
151
- ctx.src_idx = CTX_DATA_SRC;
152
- ctx.dst_idx = CTX_DATA_DST;
153
- ctx.final_idx = CTX_DATA_DST;
154
- ctx.n_datas = dir->conv.n_channels;
155
ctx.ctrlport = ctrlport;
156
157
- if (this->recalc)
158
+ if (SPA_UNLIKELY(this->recalc)) {
159
+ ctx.src_idx = CTX_DATA_SRC;
160
+ ctx.dst_idx = CTX_DATA_DST;
161
+ ctx.final_idx = CTX_DATA_DST;
162
recalc_stages(this, &ctx);
163
+ }
164
165
for (i = 0; i < this->n_stages; i++) {
166
struct stage *s = &this->stagesi;
167
_service:download_url:pipewire-1.4.0.tar.bz2/spa/plugins/bluez5/backend-native.c -> _service:download_url:pipewire-1.4.1.tar.bz2/spa/plugins/bluez5/backend-native.c
Changed
133
1
2
struct rfcomm_call_data *call_data = data;
3
struct rfcomm *rfcomm = call_data->rfcomm;
4
struct impl *backend = rfcomm->backend;
5
+ struct spa_bt_telephony_call *call, *tcall;
6
+ bool found_held = false;
7
+ bool hfp_hf_in_progress = false;
8
char reply20;
9
bool res;
10
11
+ spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
12
+ if (call->state == CALL_STATE_HELD)
13
+ found_held = true;
14
+ }
15
+
16
switch (call_data->call->state) {
17
case CALL_STATE_ACTIVE:
18
case CALL_STATE_DIALING:
19
case CALL_STATE_ALERTING:
20
case CALL_STATE_INCOMING:
21
- rfcomm_send_cmd(rfcomm, "AT+CHUP");
22
+ if (found_held) {
23
+ if (!rfcomm->chld_supported) {
24
+ *err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
25
+ return;
26
+ } else if (rfcomm->hfp_hf_in_progress) {
27
+ *err = BT_TELEPHONY_ERROR_IN_PROGRESS;
28
+ return;
29
+ }
30
+
31
+ rfcomm_send_cmd(rfcomm, "AT+CHLD=1");
32
+ hfp_hf_in_progress = true;
33
+ } else {
34
+ rfcomm_send_cmd(rfcomm, "AT+CHUP");
35
+ }
36
break;
37
case CALL_STATE_WAITING:
38
+ if (rfcomm->hfp_hf_in_progress) {
39
+ *err = BT_TELEPHONY_ERROR_IN_PROGRESS;
40
+ return;
41
+ }
42
rfcomm_send_cmd(rfcomm, "AT+CHLD=0");
43
+ hfp_hf_in_progress = true;
44
break;
45
default:
46
spa_log_info(backend->log, "Call not incoming, waiting or active: skip hangup");
47
48
return;
49
}
50
51
+ if (hfp_hf_in_progress) {
52
+ if (call_data->call->state != CALL_STATE_WAITING) {
53
+ spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
54
+ if (call->state == CALL_STATE_ACTIVE) {
55
+ call->state = CALL_STATE_DISCONNECTED;
56
+ telephony_call_notify_updated_props(call);
57
+ telephony_call_destroy(call);
58
+ }
59
+ }
60
+ spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
61
+ if (call->state == CALL_STATE_HELD) {
62
+ call->state = CALL_STATE_ACTIVE;
63
+ telephony_call_notify_updated_props(call);
64
+ }
65
+ }
66
+ }
67
+ rfcomm->hfp_hf_in_progress = true;
68
+ }
69
*err = BT_TELEPHONY_ERROR_NONE;
70
}
71
72
73
}
74
SPA_FALLTHROUGH;
75
case hfp_hf_chld:
76
+ rfcomm->slc_configured = true;
77
+
78
+ if (!rfcomm->codec_negotiation_supported) {
79
+ if (rfcomm_new_transport(rfcomm, HFP_AUDIO_CODEC_CVSD) < 0) {
80
+ // TODO: We should manage the missing transport
81
+ } else {
82
+ spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
83
+ }
84
+ }
85
+
86
+ rfcomm->telephony_ag = telephony_ag_new(backend->telephony, 0);
87
+ rfcomm->telephony_ag->address = strdup(rfcomm->device->address);
88
+ telephony_ag_set_callbacks(rfcomm->telephony_ag,
89
+ &telephony_ag_callbacks, rfcomm);
90
+ if (rfcomm->transport) {
91
+ rfcomm->telephony_ag->transport.codec = rfcomm->transport->codec;
92
+ rfcomm->telephony_ag->transport.state = rfcomm->transport->state;
93
+ }
94
+ telephony_ag_register(rfcomm->telephony_ag);
95
+
96
rfcomm_send_cmd(rfcomm, "AT+CLIP=1");
97
rfcomm->hf_state = hfp_hf_clip;
98
break;
99
100
SPA_FALLTHROUGH;
101
case hfp_hf_nrec:
102
rfcomm->hf_state = hfp_hf_slc1;
103
- rfcomm->slc_configured = true;
104
-
105
- if (!rfcomm->codec_negotiation_supported) {
106
- if (rfcomm_new_transport(rfcomm, HFP_AUDIO_CODEC_CVSD) < 0) {
107
- // TODO: We should manage the missing transport
108
- } else {
109
- spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
110
- }
111
- }
112
-
113
- rfcomm->telephony_ag = telephony_ag_new(backend->telephony, 0);
114
- rfcomm->telephony_ag->address = strdup(rfcomm->device->address);
115
- telephony_ag_set_callbacks(rfcomm->telephony_ag,
116
- &telephony_ag_callbacks, rfcomm);
117
- if (rfcomm->transport) {
118
- rfcomm->telephony_ag->transport.codec = rfcomm->transport->codec;
119
- rfcomm->telephony_ag->transport.state = rfcomm->transport->state;
120
- }
121
- telephony_ag_register(rfcomm->telephony_ag);
122
123
if (rfcomm->hfp_hf_clcc) {
124
rfcomm_send_cmd(rfcomm, "AT+CLCC");
125
126
} else if (profile == SPA_BT_PROFILE_HFP_AG) {
127
/* Start SLC connection */
128
unsigned int hf_features = SPA_BT_HFP_HF_FEATURE_CLIP | SPA_BT_HFP_HF_FEATURE_3WAY |
129
+ SPA_BT_HFP_HF_FEATURE_ECNR |
130
SPA_BT_HFP_HF_FEATURE_ENHANCED_CALL_STATUS |
131
SPA_BT_HFP_HF_FEATURE_ESCO_S4;
132
bool has_msbc = device_supports_codec(backend, rfcomm->device, HFP_AUDIO_CODEC_MSBC);
133
_service:download_url:pipewire-1.4.0.tar.bz2/src/daemon/systemd/user/pipewire.service.in -> _service:download_url:pipewire-1.4.1.tar.bz2/src/daemon/systemd/user/pipewire.service.in
Changed
9
1
2
# After=pipewire.socket is not needed, as it is already implicit in the
3
# socket-service relationship, see systemd.socket(5).
4
Requires=pipewire.socket
5
+ConditionUser=!root
6
7
Service
8
LockPersonality=yes
9
_service:download_url:pipewire-1.4.0.tar.bz2/src/daemon/systemd/user/pipewire.socket -> _service:download_url:pipewire-1.4.1.tar.bz2/src/daemon/systemd/user/pipewire.socket
Changed
8
1
2
Unit
3
Description=PipeWire Multimedia System Sockets
4
+ConditionUser=!root
5
6
Socket
7
Priority=6
8
_service:download_url:pipewire-1.4.0.tar.bz2/src/modules/meson.build -> _service:download_url:pipewire-1.4.1.tar.bz2/src/modules/meson.build
Changed
10
1
2
endif
3
summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules')
4
5
-roc_dep = dependency('roc', version: '>= 0.3.0', required: get_option('roc'))
6
+roc_dep = dependency('roc', version: '>= 0.4.0', required: get_option('roc'))
7
summary({'ROC': roc_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
8
9
pipewire_module_rtp_source = shared_library('pipewire-module-rtp-source',
10
_service:download_url:pipewire-1.4.0.tar.bz2/src/pipewire/loop.h -> _service:download_url:pipewire-1.4.1.tar.bz2/src/pipewire/loop.h
Changed
10
1
2
PW_API_LOOP_IMPL void pw_loop_destroy_source(struct pw_loop *object,
3
struct spa_source *source)
4
{
5
- return spa_loop_utils_destroy_source(object->utils, source);
6
+ spa_loop_utils_destroy_source(object->utils, source);
7
}
8
9
/**
10
_service:download_url:pipewire-1.4.0.tar.bz2/src/pipewire/stream.c -> _service:download_url:pipewire-1.4.1.tar.bz2/src/pipewire/stream.c
Changed
10
1
2
if (impl->n_buffers == 0 ||
3
(impl->direction == SPA_DIRECTION_OUTPUT && update_requested(impl) <= 0))
4
return;
5
- if (impl->rt_callbacks.funcs)
6
+ if (impl->rt_callbacks.funcs && !impl->disconnecting)
7
spa_callbacks_call_fast(&impl->rt_callbacks, struct pw_stream_events, process, 0);
8
}
9
10